public static byte[] CreateALPNExtension(System.Collections.Generic.List <string> protocols) { if (protocols == null) { throw new TlsFatalAlert(AlertDescription.internal_error); } // https://tools.ietf.org/html/rfc7301 using (var buf = new BestHTTP.Extensions.BufferPoolMemoryStream()) { using (var protoBuf = new BestHTTP.Extensions.BufferPoolMemoryStream()) { foreach (string protocol in protocols) { // Empty strings MUST NOT be included and byte strings MUST NOT be truncated. if (string.IsNullOrEmpty(protocol)) { continue; } byte[] asciiEncoding = Strings.ToAsciiByteArray(protocol); if (asciiEncoding.Length < 1) { throw new TlsFatalAlert(AlertDescription.internal_error); } TlsUtilities.WriteOpaque8(asciiEncoding, protoBuf); BestHTTP.PlatformSupport.Memory.BufferPool.Release(asciiEncoding); } TlsUtilities.CheckUint16(protoBuf.Length); TlsUtilities.WriteUint16((int)protoBuf.Length, buf); protoBuf.WriteTo(buf); } return(buf.ToArray()); } }
/// <summary> /// This function must return the encoded representation of the given message. /// </summary> public BufferSegment EncodeMessage(Message message) { var memBuffer = BufferPool.Get(256, true); var stream = new BestHTTP.Extensions.BufferPoolMemoryStream(memBuffer, 0, memBuffer.Length, true, true, false, true); // Write 5 bytes for placeholder for length prefix stream.WriteByte(0); stream.WriteByte(0); stream.WriteByte(0); stream.WriteByte(0); stream.WriteByte(0); var buffer = BufferPool.Get(MsgPackWriter.DEFAULT_BUFFER_SIZE, true); var context = new SerializationContext { Options = SerializationOptions.SuppressTypeInformation, EnumSerializerFactory = this.Options.EnumSerializerFactory, ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance }; var writer = new MsgPackWriter(stream, context, buffer); switch (message.type) { case MessageTypes.StreamItem: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streamitem-message-encoding-1 // [2, Headers, InvocationId, Item] writer.WriteArrayBegin(4); writer.WriteNumber(2); WriteHeaders(writer); writer.WriteString(message.invocationId); WriteValue(writer, message.item); writer.WriteArrayEnd(); break; case MessageTypes.Completion: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#completion-message-encoding-1 // [3, Headers, InvocationId, ResultKind, Result?] byte resultKind = (byte)(!string.IsNullOrEmpty(message.error) ? /*error*/ 1 : message.result != null ? /*non-void*/ 3 : /*void*/ 2); writer.WriteArrayBegin(resultKind == 2 ? 4 : 5); writer.WriteNumber(3); WriteHeaders(writer); writer.WriteString(message.invocationId); writer.WriteNumber(resultKind); if (resultKind == 1) // error { writer.WriteString(message.error); } else if (resultKind == 3) // non-void { WriteValue(writer, message.result); } writer.WriteArrayEnd(); break; case MessageTypes.Invocation: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#invocation-message-encoding-1 // [1, Headers, InvocationId, NonBlocking, Target, [Arguments], [StreamIds]] case MessageTypes.StreamInvocation: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#streaminvocation-message-encoding-1 // [4, Headers, InvocationId, Target, [Arguments], [StreamIds]] writer.WriteArrayBegin(message.streamIds != null ? 6 : 5); writer.WriteNumber((int)message.type); WriteHeaders(writer); writer.WriteString(message.invocationId); writer.WriteString(message.target); writer.WriteArrayBegin(message.arguments != null ? message.arguments.Length : 0); if (message.arguments != null) { for (int i = 0; i < message.arguments.Length; ++i) { WriteValue(writer, message.arguments[i]); } } writer.WriteArrayEnd(); if (message.streamIds != null) { writer.WriteArrayBegin(message.streamIds.Length); for (int i = 0; i < message.streamIds.Length; ++i) { WriteValue(writer, message.streamIds[i]); } writer.WriteArrayEnd(); } writer.WriteArrayEnd(); break; case MessageTypes.CancelInvocation: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#cancelinvocation-message-encoding-1 // [5, Headers, InvocationId] writer.WriteArrayBegin(3); writer.WriteNumber(5); WriteHeaders(writer); writer.WriteString(message.invocationId); writer.WriteArrayEnd(); break; case MessageTypes.Ping: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#ping-message-encoding-1 // [6] writer.WriteArrayBegin(1); writer.WriteNumber(6); writer.WriteArrayEnd(); break; case MessageTypes.Close: // https://github.com/aspnet/AspNetCore/blob/master/src/SignalR/docs/specs/HubProtocol.md#close-message-encoding-1 // [7, Error, AllowReconnect?] writer.WriteArrayBegin(string.IsNullOrEmpty(message.error) ? 1 : 2); writer.WriteNumber(7); if (!string.IsNullOrEmpty(message.error)) { writer.WriteString(message.error); } writer.WriteArrayEnd(); break; } writer.Flush(); // release back the buffer we used for the MsgPackWriter BufferPool.Release(buffer); // get how much bytes got written to the buffer. This includes the 5 placeholder bytes too. int length = (int)stream.Position; // this is the length without the 5 placeholder bytes int contentLength = length - 5; // get the stream's internal buffer. We set the releaseBuffer flag to false, so we can use it safely. buffer = stream.GetBuffer(); // add varint length prefix byte prefixBytes = GetRequiredBytesForLengthPrefix(contentLength); WriteLengthAsVarInt(buffer, 5 - prefixBytes, contentLength); // return with the final segment return(new BufferSegment(buffer, 5 - prefixBytes, contentLength + prefixBytes)); }
public OutgoingPacket CreateOutgoing(Socket socket, SocketIOEventTypes socketIOEvent, int id, string name, object[] args) { var memBuffer = BufferPool.Get(256, true); var stream = new BestHTTP.Extensions.BufferPoolMemoryStream(memBuffer, 0, memBuffer.Length, true, true, false, true); var buffer = BufferPool.Get(MsgPackWriter.DEFAULT_BUFFER_SIZE, true); var context = new SerializationContext { Options = SerializationOptions.SuppressTypeInformation, EnumSerializerFactory = (enumType) => new EnumNumberSerializer(enumType)/*, * ExtensionTypeHandler = CustomMessagePackExtensionTypeHandler.Instance*/ }; var writer = new MsgPackWriter(stream, context, buffer); switch (socketIOEvent) { case SocketIOEventTypes.Connect: // No Data | Object if (args != null && args.Length > 0 && args[0] != null) { writer.WriteObjectBegin(id >= 0 ? 4 : 3); } else { writer.WriteObjectBegin(id >= 0 ? 3 : 2); } break; case SocketIOEventTypes.Disconnect: writer.WriteObjectBegin(id > 0 ? 3 : 2); break; case SocketIOEventTypes.Error: writer.WriteObjectBegin(id > 0 ? 4 : 3); break; default: writer.WriteObjectBegin(id >= 0 ? 4 : 3); break; } writer.WriteMember("type"); writer.Write((int)socketIOEvent); writer.WriteMember("nsp"); writer.Write(socket.Namespace); if (id >= 0) { writer.WriteMember("id"); writer.Write(id); } switch (socketIOEvent) { case SocketIOEventTypes.Connect: // No Data | Object if (args != null && args.Length > 0 && args[0] != null) { writer.WriteMember("data"); writer.WriteValue(args[0], args[0].GetType()); } break; case SocketIOEventTypes.Disconnect: // No Data break; case SocketIOEventTypes.Error: writer.WriteMember("data"); // String | Object if (args != null && args.Length > 0) { writer.WriteValue(args[0], args[0].GetType()); } else { writer.WriteObjectBegin(0); writer.WriteObjectEnd(); } break; default: writer.WriteMember("data"); // Array int argCount = (args != null ? args.Length : 0); writer.WriteArrayBegin(!string.IsNullOrEmpty(name) ? 1 + argCount : argCount); if (!string.IsNullOrEmpty(name)) { writer.Write(name); } foreach (var arg in args) { writer.WriteValue(arg, arg.GetType()); } writer.WriteArrayEnd(); break; } writer.WriteObjectEnd(); writer.Flush(); BufferPool.Release(buffer); // get how much bytes got written to the buffer int length = (int)stream.Position; buffer = stream.GetBuffer(); return(new OutgoingPacket { PayloadData = new BufferSegment(buffer, 0, length) }); }