/// <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); } }
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); } } }