Ejemplo n.º 1
0
        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
            });
        }
Ejemplo n.º 2
0
        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;
 }