/// <summary> /// Return a message or null if timout passes without a complete message ending with Eof can be found /// </summary> /// <param name="cancelationToken"></param> /// <returns></returns> public async Task <IncomingMessage> ReadAsync(CancellationToken cancelationToken) { // at start, some left overs might still be at the begining of the buffer, // currentIndex can therefore be greater than 0 byte[] eof = { 0x0D, 0x0A }; var eofMatchCharCount = 0; while (eofMatchCharCount < eof.Length) { var byteCount = await _byteStream.ReadAsync(_buffer, _currentBufferIndex, BufferSize - _currentBufferIndex, cancelationToken); if (byteCount <= 0) { return(null); } _currentBufferIndex += byteCount; while (eofMatchCharCount < eof.Length && byteCount > 0) { if (_buffer[_currentBufferIndex - byteCount] == eof[eofMatchCharCount]) { eofMatchCharCount++; } else { eofMatchCharCount = 0; } byteCount--; } if (eofMatchCharCount != eof.Length) { continue; } var msgBytes = new byte[_currentBufferIndex - byteCount]; for (var i = 0; i < _currentBufferIndex - byteCount; i++) { msgBytes[i] = _buffer[i]; } var parser = _parserFactory.Create(msgBytes); var msg = parser.Parse(msgBytes); for (var i = 0; i < byteCount; i++) { _buffer[i] = _buffer[_currentBufferIndex - byteCount + i]; } _currentBufferIndex = byteCount; return(msg); } return(null); }