/// <summary> /// Initialize WebSocket random nonce /// </summary> public void InitWsNonce() { WsRandom.NextBytes(WsNonce); }
/// <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); }