/// <summary> /// Read the next <see cref="T:PacketBuffer"/> from the stream. /// </summary> /// <returns>The next packet extracted from the stream.</returns> /// <param name="processedBytes">Incremented by the number of bytes read from the stream. See remarks.</param> /// <remarks> /// The next packet is returned first from the current <see cref="T:CollatedPacketDecoder"/> if possible. /// Otherwise packet data are read from the stream and decoded as required. The <paramref name="processedBytes"/> /// value is only adjusted when data are read from the stream, not when a packet is extracted from the /// collation buffer. /// </remarks> public PacketBuffer NextPacket(ref long processedBytes) { PacketBuffer packet = null; // If decoding, just pull from the decoder. if (DecodingCollated) { packet = _decoder.Next(); if (packet != null) { return(packet); } } // Check for transition from raw stream to GZip stream. if (!_isGZipStream && GZipUtil.IsGZipStream(_activeStream)) { _isGZipStream = true; _activeStream = new GZipStream(_activeStream, CompressionMode.Decompress); } // Read next packet. int bytesRead = 0; _headerStream.Position = 0; _headerStream.SetLength(PacketHeader.Size); if (!_searchForHeader) { bytesRead = _activeStream.Read(_headerStream.GetBuffer(), 0, PacketHeader.Size); } else { _searchForHeader = false; // Look for the marker bytes. UInt32 marker = 0; int markerSize = 4; while (!EndOfStream && marker != PacketHeader.PacketMarker) { bytesRead = _activeStream.Read(_headerStream.GetBuffer(), 0, markerSize); marker = Endian.FromNetwork(BitConverter.ToUInt32(_headerStream.GetBuffer(), 0)); } if (marker != PacketHeader.PacketMarker) { // Failed. EndOfStream = true; return(null); } bytesRead += _activeStream.Read(_headerStream.GetBuffer(), markerSize, PacketHeader.Size - markerSize); } if (bytesRead < PacketHeader.Size) { EndOfStream = true; return(null); } _headerStream.SetLength(bytesRead); // Decode header. if (!_header.Read(new NetworkReader(_headerStream))) { // TODO: Throw exception _searchForHeader = true; return(null); } // Extract packet. int crcSize = ((_header.Flags & (byte)PacketFlag.NoCrc) == 0) ? Crc16.CrcSize : 0; packet = new PacketBuffer(_header.PacketSize + crcSize); packet.Emplace(_headerStream.GetBuffer(), bytesRead); processedBytes += packet.Emplace(_activeStream, _header.PacketSize + crcSize - bytesRead); if (packet.Status != PacketBufferStatus.Complete) { // TODO: throw exception _searchForHeader = true; return(packet); } // Decoder packet. _decoder.SetPacket(packet); packet = _decoder.Next(); return(packet); }