public void Serialize(Stream stream, object packet)
{
var p = (Packet)packet;
// Jump 8 Bytes for writing Length | Checksum
var packetLengthMarker = new StreamLengthMarker(stream, false);
stream.Seek(8, SeekOrigin.Current);
// Write Packet Header
var header = (byte)((byte)(p.Type) |
(byte)(p.Message != null ? 0x80 : 0) |
(byte)(p.Exception != null ? 0x40 : 0));
stream.WriteByte(header);
stream.Write7BitEncodedInt(p.ActorId);
stream.Write7BitEncodedInt(p.RequestId);
// Write Message
if (p.Message != null)
{
if (p.Type == PacketType.System)
{
// System message: Always string.
stream.WriteString((string)p.Message);
}
else
{
// User message: Length, Signature, and Data
var messageTypeAlias = _data.TypeTable.GetAlias(p.Message.GetType());
stream.Write7BitEncodedInt(messageTypeAlias);
var messageLengthMarker = new StreamLengthMarker(stream, true);
_data.MessageSerializer.Serialize(stream, p.Message);
messageLengthMarker.WriteLength(true);
}
}
// Write Exception
if (p.Exception != null)
{
_exceptionSerializer.Serialize(stream, p.Exception);
}
// Write Length
packetLengthMarker.WriteLength(false);
// Encrypt and Calc Checksum
ArraySegment<byte> s0, s1;
GetBuffers(stream, (int)packetLengthMarker.StartPosition + 8, packetLengthMarker.Length - 4,
out s0, out s1);
var ctx = new EncryptContext { Key = _serializeWrapKey };
Encrypt(s0.Array, s0.Offset, s0.Array, s0.Offset, s0.Count, ref ctx);
Encrypt(s1.Array, s1.Offset, s1.Array, s1.Offset, s1.Count, ref ctx);
if (_serializeWrapKey != 0)
{
_serializeWrapKey += 1;
if (_serializeWrapKey == 0)
_serializeWrapKey = 1;
}
// Write Checksum
var hashBytes = BitConverter.GetBytes(ctx.Hash);
stream.Write(hashBytes, 0, hashBytes.Length);
// End of stream, again.
stream.Seek(packetLengthMarker.EndPosition, SeekOrigin.Begin);
// Pending WrapKey
if (_serializeWrapPendingKey != 0)
{
_serializeWrapKey = _serializeWrapPendingKey;
_serializeWrapPendingKey = 0;
}
}