/// <summary>
        ///     Perform WebSocket server upgrade
        /// </summary>
        /// <param name="request">WebSocket upgrade HTTP request</param>
        /// <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 Boolean PerformServerUpgrade(HttpNetworkRequest request, HttpNetworkResponse response)
        {
            if (request.Method != "GET")
            {
                return(false);
            }

            Boolean error      = false;
            Boolean connection = false;
            Boolean upgrade    = false;
            Boolean wsKey      = false;
            Boolean wsVersion  = false;

            String accept = "";

            // Validate WebSocket handshake headers
            for (Int32 i = 0; i < request.Headers; ++i)
            {
                Tuple <String, String> header = request.Header(i);
                String key   = header.Item1;
                String value = header.Item2;

                if (key == "Connection")
                {
                    if (value != "Upgrade" && value != "keep-alive, Upgrade")
                    {
                        error = true;
                        response.MakeErrorResponse("Invalid WebSocket handshaked request: 'Connection' header value must be 'Upgrade' or 'keep-alive, Upgrade'", 400);
                        break;
                    }

                    connection = true;
                }
                else if (key == "Upgrade")
                {
                    if (value != "websocket")
                    {
                        error = true;
                        response.MakeErrorResponse("Invalid WebSocket handshaked request: 'Upgrade' header value must be 'websocket'", 400);
                        break;
                    }

                    upgrade = true;
                }
                else if (key == "Sec-WebSocket-Key")
                {
                    if (String.IsNullOrEmpty(value))
                    {
                        error = true;
                        response.MakeErrorResponse("Invalid WebSocket handshaked request: 'Sec-WebSocket-Key' header value must be non empty", 400);
                        break;
                    }

                    // Calculate the original WebSocket hash
                    String wskey = value + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                    Byte[] wshash;
                    using (SHA1Managed sha1 = new SHA1Managed())
                    {
                        wshash = sha1.ComputeHash(Encoding.UTF8.GetBytes(wskey));
                    }

                    accept = Convert.ToBase64String(wshash);

                    wsKey = true;
                }
                else if (key == "Sec-WebSocket-Version")
                {
                    if (value != "13")
                    {
                        error = true;
                        response.MakeErrorResponse("Invalid WebSocket handshaked request: 'Sec-WebSocket-Version' header value must be '13'", 400);
                        break;
                    }

                    wsVersion = true;
                }
            }

            // Filter out non WebSocket handshake requests
            if (!connection && !upgrade && !wsKey && !wsVersion)
            {
                return(false);
            }

            // Failed to perform WebSocket handshake
            if (!connection || !upgrade || !wsKey || !wsVersion)
            {
                if (!error)
                {
                    response.MakeErrorResponse("Invalid WebSocket response", 400);
                }

                _wsHandler.SendResponse(response);
                return(false);
            }

            // Prepare WebSocket upgrade success response
            response.Clear();
            response.SetBegin(101);
            response.SetHeader("Connection", "Upgrade");
            response.SetHeader("Upgrade", "websocket");
            response.SetHeader("Sec-WebSocket-Accept", accept);
            response.SetBody();

            // Validate WebSocket upgrade request and response
            if (!_wsHandler.OnWsConnecting(request, response))
            {
                return(false);
            }

            // Send WebSocket upgrade response
            _wsHandler.SendResponse(response);

            // WebSocket successfully handshaked!
            WsHandshaked = true;
            Array.Fill(WsSendMask, (Byte)0);
            _wsHandler.OnWsConnected(request);

            return(true);
        }