public static WebSocketClient Connect(string url, string[] protocols = null, IHttpAuthorization authorization = null) { string selectedProtocol; Stream s = ConnectStream(url, protocols, out selectedProtocol, authorization); return(new WebSocketClient(s) { SelectedProtocol = selectedProtocol }); }
private static Stream ConnectStream(string url, string[] protocols, out string selectedProtocol, IHttpAuthorization authorization) { Stream stream; var uri = new Uri(url, UriKind.Absolute); string host = uri.Host; int port = uri.Port; redoafter401: switch (uri.Scheme) { case "ws": case "http": stream = OpenPlainStream(host, port); break; case "wss": case "https": stream = OpenSslStream(host, port); break; default: throw new ArgumentException("Unsupported scheme"); } Guid m_Guid = Guid.NewGuid(); string webSocketKey = Convert.ToBase64String(m_Guid.ToByteArray()); var webSocketRequest = new StringBuilder(string.Format("GET {0} HTTP/1.1\r\n" + "Host: {1}\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: {2}\r\n" + "Sec-WebSocket-Version: 13\r\n", uri.PathAndQuery, host, webSocketKey)); if (protocols != null) { webSocketRequest.Append("Sec-WebSocket-Protocol: " + string.Join(",", protocols) + "\r\n"); } if (authorization != null) { var txheaders = new Dictionary <string, string>(); authorization.GetRequestHeaders(txheaders, "GET", uri.PathAndQuery); foreach (KeyValuePair <string, string> kvp in txheaders) { webSocketRequest.Append($"{kvp.Key}: {kvp.Value}\r\n"); } } webSocketRequest.Append("\r\n"); string websocketkeyuuid = webSocketKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] websocketacceptdata = Encoding.ASCII.GetBytes(websocketkeyuuid); string websocketaccept; using (var sha1 = SHA1.Create()) { websocketaccept = Convert.ToBase64String(sha1.ComputeHash(websocketacceptdata)); } byte[] reqdata = Encoding.ASCII.GetBytes(webSocketRequest.ToString()); stream.Write(reqdata, 0, reqdata.Length); string resline = ReadHeaderLine(stream); string[] splits = resline.Split(new char[] { ' ' }, 3); if (splits.Length < 3) { stream.Close(); throw new HttpClient.BadHttpResponseException(); } if (!splits[0].StartsWith("HTTP/")) { stream.Close(); throw new HttpClient.BadHttpResponseException(); } var headers = new Dictionary <string, string>(); if (splits[1] != "101") { int statusCode; if (!int.TryParse(splits[1], out statusCode)) { statusCode = 500; } ReadHeaderLines(stream, headers); if (statusCode == 401 && authorization != null && authorization.CanHandleUnauthorized(headers)) { goto redoafter401; } if (statusCode == 401) { string data; if (headers.TryGetValue("www-authenticate", out data)) { string authtype; Dictionary <string, string> authpara = HttpClient.ParseWWWAuthenticate(data, out authtype); if (authpara == null) { throw new HttpClient.BadHttpResponseException("Invalid WWW-Authenticate"); } else { string realm; if (!authpara.TryGetValue("realm", out realm)) { realm = string.Empty; } throw new HttpClient.HttpUnauthorizedException(authtype, realm, authpara); } } } if (statusCode == 404) { throw new HttpException(statusCode, splits[2] + " (" + url + ")"); } else if (splits[1] == "200") { stream.Close(); throw new NotAWebSocketConnectionException(); } else { stream.Close(); throw new HttpException(statusCode, splits[2]); } } /* parse Headers */ ReadHeaderLines(stream, headers); string headerLine; if (!headers.TryGetValue("connection", out headerLine) || headerLine.Trim() != "upgrade") { stream.Close(); throw new NotAWebSocketConnectionException(); } if (!headers.TryGetValue("upgrade", out headerLine) || headerLine.Trim() != "websocket") { stream.Close(); throw new NotAWebSocketConnectionException(); } if (!headers.TryGetValue("sec-websocket-accept", out headerLine) || headerLine.Trim() != websocketaccept) { stream.Close(); throw new NotAWebSocketConnectionException(); } selectedProtocol = headers.TryGetValue("sec-websocket-protocol", out headerLine) ? headerLine : string.Empty; return(stream); }
public HttpProvider(string url, IHttpAuthorization autoAuthorization, bool autoAddSlash = true) { _baseUri = url ?? throw new ArgumentNullException(nameof(url)); _autoAuthorization = autoAuthorization; _autoSlash = autoAddSlash; }