/// <summary>
        /// This function must parse binary representation of the messages into the list of Messages.
        /// </summary>
        public void ParseMessages(BufferSegment segment, ref List <Message> messages)
        {
            messages.Clear();

            int offset = segment.Offset;

            while (offset < segment.Count)
            {
                int length = (int)ReadVarInt(segment.Data, ref offset);

                using (var stream = new System.IO.MemoryStream(segment.Data, offset, length))
                {
                    var buff = BufferPool.Get(MsgPackReader.DEFAULT_BUFFER_SIZE, true);
                    try
                    {
                        var context = new SerializationContext {
                            Options = SerializationOptions.SuppressTypeInformation,
                            ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance
                        };
                        var reader = new MsgPackReader(stream, context, Endianness.BigEndian, buff);

                        reader.NextToken();
                        reader.NextToken();

                        int messageType = reader.ReadByte();
                        switch ((MessageTypes)messageType)
                        {
                        case MessageTypes.Invocation: messages.Add(ReadInvocation(reader)); break;

                        case MessageTypes.StreamItem: messages.Add(ReadStreamItem(reader)); break;

                        case MessageTypes.Completion: messages.Add(ReadCompletion(reader)); break;

                        case MessageTypes.StreamInvocation: messages.Add(ReadStreamInvocation(reader)); break;

                        case MessageTypes.CancelInvocation: messages.Add(ReadCancelInvocation(reader)); break;

                        case MessageTypes.Ping:

                            // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1
                            messages.Add(new Message {
                                type = MessageTypes.Ping
                            });
                            break;

                        case MessageTypes.Close: messages.Add(ReadClose(reader)); break;
                        }

                        reader.NextToken();
                    }
                    finally
                    {
                        BufferPool.Release(buff);
                    }
                }

                offset += length;
            }
        }
        private Message ReadCompletion(MsgPackReader reader)
        {
            // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1

            ReadHeaders(reader);
            string invocationId = reader.ReadString();
            byte   resultKind   = reader.ReadByte();

            switch (resultKind)
            {
            // 1 - Error result - Result contains a String with the error message
            case 1:
                string error = reader.ReadString();
                return(new Message
                {
                    type = MessageTypes.Completion,
                    invocationId = invocationId,
                    error = error
                });

            // 2 - Void result - Result is absent
            case 2:
                return(new Message
                {
                    type = MessageTypes.Completion,
                    invocationId = invocationId
                });

            // 3 - Non-Void result - Result contains the value returned by the server
            case 3:
                object item = ReadItem(reader, invocationId);
                return(new Message
                {
                    type = MessageTypes.Completion,
                    invocationId = invocationId,
                    item = item,
                    result = item
                });

            default:
                throw new NotImplementedException("Unknown resultKind: " + resultKind);
            }
        }
Example #3
0
        public IncomingPacket Parse(SocketManager manager, BufferSegment data, TransportEventTypes transportEvent = TransportEventTypes.Unknown)
        {
            using (var stream = new System.IO.MemoryStream(data.Data, data.Offset, data.Count))
            {
                var buff = BufferPool.Get(MsgPackReader.DEFAULT_BUFFER_SIZE, true);
                try
                {
                    var context = new SerializationContext
                    {
                        Options = SerializationOptions.SuppressTypeInformation/*,
                                                                               * ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance*/
                    };
                    IJsonReader reader = new MsgPackReader(stream, context, Endianness.BigEndian, buff);

                    reader.ReadObjectBegin();

                    int    type = -1, id = -1;
                    string nsp = null;

                    bool hasData = false, readData = false;

                    IncomingPacket packet = IncomingPacket.Empty;

READ:

                    while (reader.Token != JsonToken.EndOfObject)
                    {
                        string key = reader.ReadMember();

                        switch (key)
                        {
                        case "type":
                            type = reader.ReadByte();
                            break;

                        case "nsp":
                            nsp = reader.ReadString();
                            break;

                        case "id":
                            id = reader.ReadInt32();
                            break;

                        case "data":
                            if (!hasData)
                            {
                                hasData = true;
                                SkipData(reader, (SocketIOEventTypes)type);
                            }
                            else
                            {
                                readData = true;

                                packet = new IncomingPacket(transportEvent != TransportEventTypes.Unknown ? transportEvent : TransportEventTypes.Message, (SocketIOEventTypes)type, nsp, id);
                                (string eventName, object[] args) = ReadData(manager, packet, reader);

                                packet.EventName = eventName;
                                if (args != null)
                                {
                                    if (args.Length == 1)
                                    {
                                        packet.DecodedArg = args[0];
                                    }
                                    else
                                    {
                                        packet.DecodedArgs = args;
                                    }
                                }
                            }
                            break;
                        }
                    }

                    // type, nsp, id and data can come in any order. To read data strongly typed we need to know all the additional fields before processing the data field.
                    // In order to do it, when we first encounter the data field we skip it than we do a reset and an additional turn but reading the data too now.
                    if (hasData && !readData)
                    {
                        reader.Reset();
                        stream.Position = 0;
                        reader.ReadObjectBegin();

                        goto READ;
                    }

                    reader.ReadObjectEnd();

                    return(packet.Equals(IncomingPacket.Empty) ? new IncomingPacket(transportEvent != TransportEventTypes.Unknown ? transportEvent : TransportEventTypes.Message, (SocketIOEventTypes)type, nsp, id) : packet);
                }
                finally
                {
                    BufferPool.Release(buff);
                }
            }
        }