/// <summary> /// Read and return the next IPacket from the stream /// </summary> public IPacket Read() { #if ADD_GUARD_BYTES byte[] preamble = new byte[4]; m_Stream.Read(preamble, 0, 4); //now compare it against the preamble. CompareArrays(preamble, PacketWriter.s_PreambleGuardPattern); #endif int packetSize = (int)m_Reader.ReadUInt64(); //if the packet size is less than one, that's obviously wrong if (packetSize < 1) { throw new GibraltarSerializationException("The size of the next packet is smaller than 1 byte or negative, which can't be correct. The packet stream is corrupted.", true); } // TODO: There's got to be a more efficient way to get this done byte[] buffer = new byte[packetSize]; m_Stream.Read(buffer, 0, packetSize); IFieldReader bufferReader = new FieldReader(new MemoryStream(buffer), m_Reader.Strings, m_MajorVersion, m_MinorVersion); PacketDefinition definition; int typeIndex = (int)bufferReader.ReadUInt32(); if (typeIndex >= m_cachedTypes.Count) { definition = PacketDefinition.ReadPacketDefinition(bufferReader); if (string.IsNullOrEmpty(definition.TypeName)) { //we're hosed... we won't be able to parse this packet. throw new GibraltarSerializationException("The type name of the definition is null, which can't be correct. The packet stream is corrupted.", true); } m_cachedTypes.Add(definition); m_cachedTypes.Commit(); } else { definition = m_cachedTypes[typeIndex]; } IPacketFactory factory = m_PacketFactory.GetPacketFactory(definition.TypeName); IPacket packet = factory.CreatePacket(definition, bufferReader); //we used to populate a packet cache here, but a cached packet should be read just once - it shouldn't be in the stream //(and I changed PacketWriter to enforce that) #if ADD_GUARD_BYTES byte[] postamble = new byte[4]; m_Stream.Read(postamble, 0, 4); //now compare it against the preamble. CompareArrays(postamble, PacketWriter.s_PostambleGuardPattern); #endif return(packet); }
/// <summary> /// Initialize a PacketReader to read the specified stream using /// the provided encoding for strings. /// </summary> /// <param name="stream">Data to be read</param> /// <param name="inputIsReadOnly">Indicates if the input can be assumed fixed in length</param> /// <param name="majorVersion">Major version of the serialization protocol</param> /// <param name="minorVersion">Minor version of the serialization protocol</param> public PacketReader(Stream stream, bool inputIsReadOnly, int majorVersion, int minorVersion) { m_Stream = stream; m_InputIsReadOnly = inputIsReadOnly; m_MajorVersion = majorVersion; m_MinorVersion = minorVersion; // m_ReleaseStream = false; // m_Stream was passed in to us, don't release it upon Dispose()! // (false by default) If we were invoked from another constructor, they will overwrite m_ReleaseStream correctly m_Reader = new FieldReader(stream, new UniqueStringList(), majorVersion, minorVersion); m_cachedTypes = new PacketDefinitionList(); m_PacketFactory = new PacketFactory(); if ((inputIsReadOnly) && (m_Stream != null)) { m_StreamLength = m_Stream.Length; } }