internal Proxy GetProxy(Uri uri) { // WebSocket is not a request-response based protocol, so we need a 'tunnel' through the proxy HTTPProxy proxy = HTTPManager.Proxy as HTTPProxy; if (proxy != null && proxy.UseProxyForAddress(uri)) { proxy = new HTTPProxy(proxy.Address, proxy.Credentials, false, /*turn on 'tunneling'*/ false, /*sendWholeUri*/ proxy.NonTransparentForHTTPS); } return(proxy); }
/// <summary> /// Creates a WebSocket instance from the given uri, protocol and origin. /// </summary> /// <param name="uri">The uri of the WebSocket server</param> /// <param name="origin">Servers that are not intended to process input from any web page but only for certain sites SHOULD verify the |Origin| field is an origin they expect. /// If the origin indicated is unacceptable to the server, then it SHOULD respond to the WebSocket handshake with a reply containing HTTP 403 Forbidden status code.</param> /// <param name="protocol">The application-level protocol that the client want to use(eg. "chat", "leaderboard", etc.). Can be null or empty string if not used.</param> /// <param name="extensions">Optional IExtensions implementations</param> public WebSocket(Uri uri, string origin, string protocol #if !UNITY_WEBGL || UNITY_EDITOR , params IExtension[] extensions #endif ) { this.Context = new LoggingContext(this); string scheme = HTTPProtocolFactory.IsSecureProtocol(uri) ? "wss" : "ws"; int port = uri.Port != -1 ? uri.Port : (scheme.Equals("wss", StringComparison.OrdinalIgnoreCase) ? 443 : 80); // Somehow if i use the UriBuilder it's not the same as if the uri is constructed from a string... //uri = new UriBuilder(uri.Scheme, uri.Host, uri.Scheme.Equals("wss", StringComparison.OrdinalIgnoreCase) ? 443 : 80, uri.PathAndQuery).Uri; uri = new Uri(scheme + "://" + uri.Host + ":" + port + uri.GetRequestPathAndQueryURL()); #if !UNITY_WEBGL || UNITY_EDITOR // Set up some default values. this.PingFrequency = 1000; this.CloseAfterNoMessage = TimeSpan.FromSeconds(2); InternalRequest = new HTTPRequest(uri, OnInternalRequestCallback); InternalRequest.Context.Add("WebSocket", this.Context); // Called when the regular GET request is successfully upgraded to WebSocket InternalRequest.OnUpgraded = OnInternalRequestUpgraded; //http://tools.ietf.org/html/rfc6455#section-4 // The request MUST contain an |Upgrade| header field whose value MUST include the "websocket" keyword. InternalRequest.SetHeader("Upgrade", "websocket"); // The request MUST contain a |Connection| header field whose value MUST include the "Upgrade" token. InternalRequest.SetHeader("Connection", "Upgrade"); // The request MUST include a header field with the name |Sec-WebSocket-Key|. The value of this header field MUST be a nonce consisting of a // randomly selected 16-byte value that has been base64-encoded (see Section 4 of [RFC4648]). The nonce MUST be selected randomly for each connection. InternalRequest.SetHeader("Sec-WebSocket-Key", GetSecKey(new object[] { this, InternalRequest, uri, new object() })); // The request MUST include a header field with the name |Origin| [RFC6454] if the request is coming from a browser client. // If the connection is from a non-browser client, the request MAY include this header field if the semantics of that client match the use-case described here for browser clients. // More on Origin Considerations: http://tools.ietf.org/html/rfc6455#section-10.2 if (!string.IsNullOrEmpty(origin)) { InternalRequest.SetHeader("Origin", origin); } // The request MUST include a header field with the name |Sec-WebSocket-Version|. The value of this header field MUST be 13. InternalRequest.SetHeader("Sec-WebSocket-Version", "13"); if (!string.IsNullOrEmpty(protocol)) { InternalRequest.SetHeader("Sec-WebSocket-Protocol", protocol); } // Disable caching InternalRequest.SetHeader("Cache-Control", "no-cache"); InternalRequest.SetHeader("Pragma", "no-cache"); this.Extensions = extensions; #if !BESTHTTP_DISABLE_CACHING InternalRequest.DisableCache = true; #endif #if !BESTHTTP_DISABLE_PROXY // WebSocket is not a request-response based protocol, so we need a 'tunnel' through the proxy HTTPProxy httpProxy = HTTPManager.Proxy as HTTPProxy; if (httpProxy != null && httpProxy.UseProxyForAddress(uri)) { InternalRequest.Proxy = new HTTPProxy(httpProxy.Address, httpProxy.Credentials, false, /*turn on 'tunneling'*/ false, /*sendWholeUri*/ httpProxy.NonTransparentForHTTPS); } #endif #else this.Uri = uri; this.Protocol = protocol; #endif // Under WebGL when only the WebSocket protocol is used Setup() isn't called, so we have to call it here. HTTPManager.Setup(); }