예제 #1
0
        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));
        }
예제 #3
0
        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)
            });
        }