public GuildedSocketMessage(
        [JsonProperty(Required = Required.Always)]
        SocketOpcode op,

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        string?t = null,

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        JObject?d = null,

        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        string?s = null
        ) =>
    (Opcode, EventName, RawData, MessageId) = (op, t, d, s);
Exemple #2
0
        /// <summary>
        /// Send a WebSocket frame to the client.
        /// </summary>
        /// <param name="data">Data to send.</param>
        /// <param name="opcode">Frame opcode.</param>
        /// <param name="isFIN">Whether frame has FIN bit set.</param>
        protected void SendFrame(byte[] data,
                                 SocketOpcode opcode = SocketOpcode.TEXT, bool isFIN = true)
        {
            byte[] header = new byte[14];
            header[0] = (byte)((isFIN ? 0x80 : 0) | (byte)opcode);
            int idx = 2;

            if (data.Length < 126)
            {
                //not bothering with masking
                header[1] = (byte)data.Length;
            }
            else if (data.Length < 65535)
            {
                header[1] = 126;
                header[2] = (byte)(data.Length >> 8);
                header[3] = (byte)(data.Length & 0xFF);
                idx       = 4;
            }
            else
            {
                //data.Length is `int` and apparently C#'s idea of sanity
                //is for the shift amount to be mod 32, so trying to
                //include the higher bytes here actually gives you the lower
                //bytes again, giving an insane length.
                header[1] = 127;
                header[2] = 0;                 //(byte)((data.Length >> 56) & 0xFF);
                header[3] = 0;                 //(byte)((data.Length >> 48) & 0xFF);
                header[4] = 0;                 //(byte)((data.Length >> 40) & 0xFF);
                header[5] = 0;                 //(byte)((data.Length >> 32) & 0xFF);
                header[6] = (byte)((data.Length >> 24) & 0xFF);
                header[7] = (byte)((data.Length >> 16) & 0xFF);
                header[8] = (byte)((data.Length >> 8) & 0xFF);
                header[9] = (byte)(data.Length & 0xFF);
                idx       = 10;
            }

            stream.Write(header, 0, idx);
            stream.Write(data, 0, data.Length);
        }
Exemple #3
0
        /// <summary>
        /// Read the WebSocket frame header from the socket.
        /// </summary>
        /// <returns>The header.</returns>
        /// <param name="req">HttpRequest to read from.</param>
        /// <exception cref="OperationCanceledException">Socket closed while reading.</exception>
        /// <exception cref="ObjectDisposedException">Socket closed while reading.</exception>
        private SocketMessageHeader ReadHeader(HttpRequest req, byte[] buffer)
        {
            int idx = 0;

            //Read the header bytes.
            //XXX deal with messages < 14 bytes (header is variable length)
            //14 is the maximum possible length
            while (idx < 14)
            {
                int r = req.stream.Read(buffer, idx, 14 - idx);
                if (r <= 0)
                {
                    throw new OperationCanceledException();                        //closed
                }
                idx += r;
            }
            //WebServer.Log($"Socket got header {buffer[0]} {buffer[1]}, read {idx} bytes");
            int bufLen = idx;

            //Decode the header.
            SocketMessageRawHeader header = new SocketMessageRawHeader {
                flagsAndOpcode = buffer[0],
                maskAndLength  = buffer[1],
            };
            SocketOpcode opcode = (SocketOpcode)(header.flagsAndOpcode & 0x0F);
            bool         isFIN  = (header.flagsAndOpcode & 0x80) != 0;
            bool         isMask = (header.maskAndLength & 0x80) != 0;
            long         length = header.maskAndLength & 0x7F;

            byte[] maskKey = new byte[4];

            //Decode the length.
            if (length == 126)              //XXX verify byte order
            {
                length = (buffer[2] << 8) | buffer[3];
                idx    = 4;
            }
            else if (length == 127)              //XXX verify byte order
            {
                length =
                    (buffer[2] << 56) |
                    (buffer[3] << 48) |
                    (buffer[4] << 40) |
                    (buffer[5] << 32) |
                    (buffer[6] << 24) |
                    (buffer[7] << 16) |
                    (buffer[8] << 8) |
                    buffer[9];
                idx = 10;
            }
            else
            {
                idx = 2;
            }
            //Log($"Message length: {length}, opcode: {opcode}, mask: {isMask} @{idx}");

            //Read the mask key.
            if (isMask)
            {
                maskKey[0] = buffer[idx + 0];
                maskKey[1] = buffer[idx + 1];
                maskKey[2] = buffer[idx + 2];
                maskKey[3] = buffer[idx + 3];
                //Log($"Reading mask key from buffer pos {idx}: {maskKey[0]} {maskKey[1]} {maskKey[2]} {maskKey[3]}");
                idx += 4;
            }
            //else, we don't care what maskKey is, we won't use it.

            return(new SocketMessageHeader {
                opcode = opcode,
                isFIN = isFIN,
                isMask = isMask,
                length = length,
                maskKey = maskKey,
                headerLength = idx,
                readLength = bufLen,
            });
        }