예제 #1
0
        public IEnumerable <PacketMessage> Parse(CircularBlob stream)
        {
            while (stream.CanRead())
            {
                // peek everything untill we 100% have the packet.
                var opcodePeek     = stream.Peek();
                var lenType        = _db.GetIncoming(opcodePeek);
                var lenPayloadPeek = 0;
                var payloadOffset  = 0;

                switch (lenType)
                {
                case PacketLength.NextByte:
                    if (!stream.CanRead(1))
                    {
                        break;
                    }

                    lenPayloadPeek = stream.Peek(1);
                    payloadOffset  = 1;
                    break;

                case PacketLength.NextShort:
                    if (!stream.CanRead(2))
                    {
                        break;
                    }

                    lenPayloadPeek = stream.Peek(1) << 8 + stream.Peek(2);
                    payloadOffset  = 2;
                    break;

                case PacketLength.Undefined:
                    yield return(PacketMessage.Undefined(opcodePeek));

                    yield break;

                default:
                    lenPayloadPeek = (byte)lenType;
                    break;
                }

                if (!stream.CanRead(payloadOffset + lenPayloadPeek))
                {
                    break;
                }


                // we can read the whole packet, do so.
                // do some assertions on the way
                var opcode = stream.ReadByte();
                Debug.Assert(opcode == opcodePeek);
                var lenPayload = 0;

                switch (lenType)
                {
                case PacketLength.NextByte:
                    lenPayload = stream.ReadByte();
                    break;

                case PacketLength.NextShort:
                    lenPayload = stream.ReadInt16();
                    break;

                case PacketLength.Undefined:
                    yield return(PacketMessage.Undefined(opcodePeek));

                    yield break;

                default:
                    lenPayload = (byte)lenType;
                    break;
                }

                Debug.Assert(lenPayload == lenPayloadPeek);

                // don't bother creating a new Blob if we're storing nothing.
                if (lenPayload == 0)
                {
                    yield return(PacketMessage.Success(opcode, Blob.Empty));
                }
                else
                {
                    var payload = new byte[lenPayload];
                    stream.ReadBlock(payload, 0, lenPayload);

                    yield return(PacketMessage.Success(opcode, new Blob(payload)));
                }
            }
        }