コード例 #1
0
        /// <summary>
        /// Perform WebSocket client upgrade
        /// </summary>
        /// <param name="response">WebSocket upgrade HTTP response</param>
        /// <returns>'true' if the WebSocket was successfully upgrade, 'false' if the WebSocket was not upgrade</returns>
        public bool PerformClientUpgrade(HttpResponse response)
        {
            if (response.Status != 101)
            {
                return(false);
            }

            bool error      = false;
            bool accept     = false;
            bool connection = false;
            bool upgrade    = false;

            // Validate WebSocket handshake headers
            for (int i = 0; i < response.Headers; i++)
            {
                var header = response.Header(i);
                var key    = header.Item1;
                var value  = header.Item2;

                if (string.Compare(key, "Connection", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (string.Compare(value, "Upgrade", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        error = true;
                        _wsHandler.OnWsError("Invalid WebSocket handshaked response: 'Connection' header value must be 'Upgrade'");
                        break;
                    }

                    connection = true;
                }
                else if (string.Compare(key, "Upgrade", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (string.Compare(value, "websocket", StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        error = true;
                        _wsHandler.OnWsError("Invalid WebSocket handshaked response: 'Upgrade' header value must be 'websocket'");
                        break;
                    }

                    upgrade = true;
                }
                else if (string.Compare(key, "Sec-WebSocket-Accept", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    // Calculate the original WebSocket hash
                    string wskey = Convert.ToBase64String(WsNonce) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                    string wshash;
                    using (SHA1Managed sha1 = new SHA1Managed())
                    {
                        wshash = Encoding.UTF8.GetString(sha1.ComputeHash(Encoding.UTF8.GetBytes(wskey)));
                    }

                    // Get the received WebSocket hash
                    wskey = Encoding.UTF8.GetString(Convert.FromBase64String(value));

                    // Compare original and received hashes
                    if (string.Compare(wskey, wshash, StringComparison.InvariantCulture) != 0)
                    {
                        error = true;
                        _wsHandler.OnWsError("Invalid WebSocket handshaked response: 'Sec-WebSocket-Accept' value validation failed");
                        break;
                    }

                    accept = true;
                }
            }

            // Failed to perform WebSocket handshake
            if (!accept || !connection || !upgrade)
            {
                if (!error)
                {
                    _wsHandler.OnWsError("Invalid WebSocket response");
                }
                return(false);
            }

            // WebSocket successfully handshaked!
            WsHandshaked = true;
            WsRandom.NextBytes(WsSendMask);
            _wsHandler.OnWsConnected(response);

            return(true);
        }