Exemple #1
0
        private async Task <bool> Handshake(ConnectionStream stream, Uri uri, int port)
        {
            state = WebsockState.Connecting;
            string handshakeData = HttpHandshakeData
                                   .Replace("{Path}", uri.PathAndQuery)
                                   .Replace("{Host}", uri.Host)
                                   .Replace("{Scheme}", uri.Scheme)
                                   .Replace("{Port}", port.ToString())
                                   .Replace("{Key}", GenerateKey());
            await stream.WriteAsync(handshakeData);

            string response = Encoding.UTF8.GetString(await stream.ReadAsync());

            return(response.Split('\n')[0].Split(' ')[1] == "101");
        }
Exemple #2
0
        // Perform websocket handshake with client
        private async Task <bool> HandshakeClient(ConnectionStream stream)
        {
            // read and parse http request data
            byte[] httpData = await stream.ReadAsync();

            HttpPacket packet = new HttpPacket(httpData);

            // client requests checks
            if (!packet.Method.ToLower().StartsWith("get"))
            {
                return(await RejectClient(stream, "Only allows GET Requests"));
            }
            if (!packet.Headers.ContainsKey("Sec-WebSocket-Key"))
            {
                return(await RejectClient(stream, "No WebSocket-Key found"));
            }
            if (!packet.Headers.ContainsKey("Upgrade"))
            {
                return(await RejectClient(stream, "Upgrade header not set"));
            }
            else if (!packet.Headers["Upgrade"].ToLower().StartsWith("websocket"))
            {
                return(await RejectClient(stream, "Upgrade header not websocket"));
            }
            if (!packet.Headers.ContainsKey("Connection"))
            {
                return(await RejectClient(stream, "Connection header not set"));
            }
            else if (!packet.Headers["Connection"].ToLower().StartsWith("upgrade"))
            {
                return(await RejectClient(stream, "Connection header not upgrade"));
            }

            // generate websocket key, send response to client and complete handshake
            httpData = Encoding.UTF8.GetBytes(HttpHandshakeSucces.Replace(
                                                  "{WebsockKey}", GenerateKey(packet.Headers["Sec-WebSocket-Key"])));
            await stream.WriteAsync(httpData, httpData.Length);

            return(true);
        }
Exemple #3
0
        public async Task <byte[]> GetMessage()
        {
            int size = 0;

            byte[]       buffer = new byte[2];
            WebsockFrame frame  = new WebsockFrame();

            // read first byte of data
            buffer = await stream.ReadAsync(buffer.Length);

            frame.Fin    = (buffer[0] & 0x80) != 0;           // first bit
            frame.Rsv1   = (buffer[0] & 0x40) != 0;           // second bit
            frame.Rsv2   = (buffer[0] & 0x20) != 0;           // thrid bit
            frame.Rsv3   = (buffer[0] & 0x10) != 0;           // fourth bit
            frame.Opcode = (WebsockOpCode)(buffer[0] & 0x0f); // fifth to eigth bits

            // read second byte of data
            frame.Masked = (buffer[1] & 0x80) != 0;    // set second byte first bit
            size         = (int)(buffer[1] & (~0x80)); // get deciding size

            // payload size is 64 bits long
            if (size == 127)
            {
                size   = 0;
                buffer = new byte[8];
                buffer = await stream.ReadAsync(buffer.Length);

                size |= (buffer[0] & 0xff) << 56;
                size |= (buffer[1] & 0xff) << 48;
                size |= (buffer[2] & 0xff) << 40;
                size |= (buffer[3] & 0xff) << 32;
                size |= (buffer[4] & 0xff) << 24;
                size |= (buffer[5] & 0xff) << 16;
                size |= (buffer[6] & 0xff) << 8;
                size |= (buffer[7] & 0xff) << 0;

                // payload size is 16 bits long
            }
            else if (size == 126)
            {
                size   = 0;
                buffer = new byte[2];
                buffer = await stream.ReadAsync(buffer.Length);

                size |= (buffer[0] & 0xff) << 8;
                size |= (buffer[1] & 0xff) << 0;
            }

            // read mask data
            if (frame.Masked)
            {
                frame.MaskingKey = new byte[4];
                frame.MaskingKey = await stream.ReadAsync(frame.MaskingKey.Length);
            }

            // read payload data
            frame.Data = new byte[size];
            frame.Data = await stream.ReadAsync(size);

            if (frame.Masked)
            {
                for (int i = 0; i < size; i++)
                {
                    frame.Data[i] ^= frame.MaskingKey[i % 4];
                }
            }

            // combine with continued data
            if (dataBuilder.Length > 0)
            {
                byte[] continued = dataBuilder.ToArray();
                dataBuilder.SetLength(0);
                byte[] combined = new byte[continued.Length + frame.Data.Length];
                Buffer.BlockCopy(continued, 0, combined, 0, continued.Length);
                Buffer.BlockCopy(frame.Data, 0, continued, continued.Length, frame.Data.Length);
                frame.Data = combined;
            }

            // build up fragmented frame & try again
            if (frame.Opcode == WebsockOpCode.Continue)
            {
                dataBuilder.Write(frame.Data, 0, frame.Data.Length);
                return(await GetMessage());

                // echo back close data and close connection
            }
            else if (frame.Opcode == WebsockOpCode.Close)
            {
                await SendAsync(frame.Data, WebsockOpCode.Close);

                throw new WebsockCloseException(frame.Data);

                // perform ping callback that was queued up & try again
            }
            else if (frame.Opcode == WebsockOpCode.Pong)
            {
                await callbacks.Dequeue()(frame.Data);

                return(await GetMessage());

                // frame is either Text or Binary, return data
            }
            else
            {
                return(frame.Data);
            }
        }