private void Close() { KeepAlive = null; LastProcessedUri = null; if (Client != null) { try { Client.Close(); } catch { } finally { Stream = null; Client = null; } } }
private void Connect() { Uri uri = #if !BESTHTTP_DISABLE_PROXY CurrentRequest.HasProxy ? CurrentRequest.Proxy.Address : #endif CurrentRequest.CurrentUri; #region TCP Connection if (Client == null) { Client = new TcpClient(); } if (!Client.Connected) { Client.ConnectTimeout = CurrentRequest.ConnectTimeout; #if NETFX_CORE || (UNITY_WP8 && !UNITY_EDITOR) Client.UseHTTPSProtocol = #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) !CurrentRequest.UseAlternateSSL && #endif HTTPProtocolFactory.IsSecureProtocol(uri); #endif Client.Connect(uri.Host, uri.Port); if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("HTTPConnection", "Connected to " + uri.Host + ":" + uri.Port.ToString()); } } else if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("HTTPConnection", "Already connected to " + uri.Host + ":" + uri.Port.ToString()); } #endregion lock (HTTPManager.Locker) StartTime = DateTime.UtcNow; if (Stream == null) { bool isSecure = HTTPProtocolFactory.IsSecureProtocol(CurrentRequest.CurrentUri); #if !BESTHTTP_DISABLE_PROXY #region Proxy Handling if (HasProxy && (!Proxy.IsTransparent || (isSecure && Proxy.NonTransparentForHTTPS))) { Stream = Client.GetStream(); var outStream = new BinaryWriter(Stream); bool retry; do { // If we have to becouse of a authentication request, we will switch it to true retry = false; outStream.SendAsASCII(string.Format("CONNECT {0}:{1} HTTP/1.1", CurrentRequest.CurrentUri.Host, CurrentRequest.CurrentUri.Port)); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII("Proxy-Connection: Keep-Alive"); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII("Connection: Keep-Alive"); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII(string.Format("Host: {0}:{1}", CurrentRequest.CurrentUri.Host, CurrentRequest.CurrentUri.Port)); outStream.Write(HTTPRequest.EOL); // Proxy Authentication if (HasProxy && Proxy.Credentials != null) { switch (Proxy.Credentials.Type) { case AuthenticationTypes.Basic: // With Basic authentication we don't want to wait for a challange, we will send the hash with the first request outStream.Write(string.Format("Proxy-Authorization: {0}", string.Concat("Basic ", Convert.ToBase64String(Encoding.UTF8.GetBytes(Proxy.Credentials.UserName + ":" + Proxy.Credentials.Password)))).GetASCIIBytes()); outStream.Write(HTTPRequest.EOL); break; case AuthenticationTypes.Unknown: case AuthenticationTypes.Digest: var digest = DigestStore.Get(Proxy.Address); if (digest != null) { string authentication = digest.GenerateResponseHeader(CurrentRequest, Proxy.Credentials); if (!string.IsNullOrEmpty(authentication)) { outStream.Write(string.Format("Proxy-Authorization: {0}", authentication).GetASCIIBytes()); outStream.Write(HTTPRequest.EOL); } } break; } } outStream.Write(HTTPRequest.EOL); // Make sure to send all the wrote data to the wire outStream.Flush(); CurrentRequest.ProxyResponse = new HTTPResponse(CurrentRequest, Stream, false, false); // Read back the response of the proxy if (!CurrentRequest.ProxyResponse.Receive(-1, true)) { throw new Exception("Connection to the Proxy Server failed!"); } if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("HTTPConnection", "Proxy returned - status code: " + CurrentRequest.ProxyResponse.StatusCode + " message: " + CurrentRequest.ProxyResponse.Message); } switch (CurrentRequest.ProxyResponse.StatusCode) { // Proxy authentication required // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.8 case 407: { string authHeader = DigestStore.FindBest(CurrentRequest.ProxyResponse.GetHeaderValues("proxy-authenticate")); if (!string.IsNullOrEmpty(authHeader)) { var digest = DigestStore.GetOrCreate(Proxy.Address); digest.ParseChallange(authHeader); if (Proxy.Credentials != null && digest.IsUriProtected(Proxy.Address) && (!CurrentRequest.HasHeader("Proxy-Authorization") || digest.Stale)) { retry = true; } } break; } default: if (!CurrentRequest.ProxyResponse.IsSuccess) { throw new Exception(string.Format("Proxy returned Status Code: \"{0}\", Message: \"{1}\" and Response: {2}", CurrentRequest.ProxyResponse.StatusCode, CurrentRequest.ProxyResponse.Message, CurrentRequest.ProxyResponse.DataAsText)); } break; } } while (retry); } #endregion #endif // #if !BESTHTTP_DISABLE_PROXY // We have to use CurrentRequest.CurrentUri here, becouse uri can be a proxy uri with a different protocol if (isSecure) { #region SSL Upgrade #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) if (CurrentRequest.UseAlternateSSL) { var handler = new TlsClientProtocol(Client.GetStream(), new Org.BouncyCastle.Security.SecureRandom()); // http://tools.ietf.org/html/rfc3546#section-3.1 // It is RECOMMENDED that clients include an extension of type "server_name" in the client hello whenever they locate a server by a supported name type. List <string> hostNames = new List <string>(1); hostNames.Add(CurrentRequest.CurrentUri.Host); handler.Connect(new LegacyTlsClient(CurrentRequest.CurrentUri, CurrentRequest.CustomCertificateVerifyer == null ? new AlwaysValidVerifyer() : CurrentRequest.CustomCertificateVerifyer, CurrentRequest.CustomClientCredentialsProvider, hostNames)); Stream = handler.Stream; } else #endif { #if !NETFX_CORE && !UNITY_WP8 SslStream sslStream = new SslStream(Client.GetStream(), false, (sender, cert, chain, errors) => { return(CurrentRequest.CallCustomCertificationValidator(cert, chain)); }); if (!sslStream.IsAuthenticated) { sslStream.AuthenticateAsClient(CurrentRequest.CurrentUri.Host); } Stream = sslStream; #else Stream = Client.GetStream(); #endif } #endregion } else { Stream = Client.GetStream(); } } }
private void Connect() { Uri uri = #if !BESTHTTP_DISABLE_PROXY CurrentRequest.HasProxy ? CurrentRequest.Proxy.Address : #endif CurrentRequest.CurrentUri; #region TCP Connection if (Client == null) { Client = new TcpClient(); } if (!Client.Connected) { Client.ConnectTimeout = CurrentRequest.ConnectTimeout; if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("'{0}' - Connecting to {1}:{2}", this.CurrentRequest.CurrentUri.ToString(), uri.Host, uri.Port.ToString())); } #if !NETFX_CORE && (!UNITY_WEBGL || UNITY_EDITOR) Client.SendBufferSize = HTTPManager.SendBufferSize; Client.ReceiveBufferSize = HTTPManager.ReceiveBufferSize; if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("'{0}' - Buffer sizes - Send: {1} Receive: {2} Blocking: {3}", this.CurrentRequest.CurrentUri.ToString(), Client.SendBufferSize.ToString(), Client.ReceiveBufferSize.ToString(), Client.Client.Blocking.ToString())); } #endif Client.Connect(uri.Host, uri.Port); if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("HTTPConnection", "Connected to " + uri.Host + ":" + uri.Port.ToString()); } } else if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("HTTPConnection", "Already connected to " + uri.Host + ":" + uri.Port.ToString()); } #endregion StartTime = DateTime.UtcNow; if (Stream == null) { bool isSecure = HTTPProtocolFactory.IsSecureProtocol(CurrentRequest.CurrentUri); Stream = Client.GetStream(); /*if (Stream.CanTimeout) * Stream.ReadTimeout = Stream.WriteTimeout = (int)CurrentRequest.Timeout.TotalMilliseconds;*/ #if !BESTHTTP_DISABLE_PROXY if (CurrentRequest.Proxy != null) { CurrentRequest.Proxy.Connect(this.Stream, this.CurrentRequest); } #endif // We have to use CurrentRequest.CurrentUri here, because uri can be a proxy uri with a different protocol if (isSecure) { // Under the new experimental runtime there's a bug in the Socket.Send implementation that can cause a // connection when the TLS protocol is used. #if !NETFX_CORE && (!UNITY_WEBGL || UNITY_EDITOR) && NET_4_6 //Client.SendBufferSize = 0; #endif #region SSL Upgrade #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) if (CurrentRequest.UseAlternateSSL) { var handler = new TlsClientProtocol(Client.GetStream(), new BestHTTP.SecureProtocol.Org.BouncyCastle.Security.SecureRandom()); // http://tools.ietf.org/html/rfc3546#section-3.1 // -It is RECOMMENDED that clients include an extension of type "server_name" in the client hello whenever they locate a server by a supported name type. // -Literal IPv4 and IPv6 addresses are not permitted in "HostName". // User-defined list has a higher priority List <string> hostNames = CurrentRequest.CustomTLSServerNameList; // If there's no user defined one and the host isn't an IP address, add the default one if ((hostNames == null || hostNames.Count == 0) && !CurrentRequest.CurrentUri.IsHostIsAnIPAddress()) { hostNames = new List <string>(1); hostNames.Add(CurrentRequest.CurrentUri.Host); } handler.Connect(new LegacyTlsClient(CurrentRequest.CurrentUri, CurrentRequest.CustomCertificateVerifyer == null ? new AlwaysValidVerifyer() : CurrentRequest.CustomCertificateVerifyer, CurrentRequest.CustomClientCredentialsProvider, hostNames)); Stream = handler.Stream; } else #endif { #if !NETFX_CORE SslStream sslStream = new SslStream(Client.GetStream(), false, (sender, cert, chain, errors) => { return(CurrentRequest.CallCustomCertificationValidator(cert, chain)); }); if (!sslStream.IsAuthenticated) { sslStream.AuthenticateAsClient(CurrentRequest.CurrentUri.Host); } Stream = sslStream; #else Stream = Client.GetStream(); #endif } #endregion } } }
public void Connect(HTTPRequest request) { string negotiatedProtocol = HTTPProtocolFactory.W3C_HTTP1; Uri uri = #if !BESTHTTP_DISABLE_PROXY request.HasProxy ? request.Proxy.Address : #endif request.CurrentUri; #region TCP Connection if (Client == null) { Client = new TcpClient(); } if (!Client.Connected) { Client.ConnectTimeout = request.ConnectTimeout; #if NETFX_CORE Client.UseHTTPSProtocol = #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) !Request.UseAlternateSSL && #endif HTTPProtocolFactory.IsSecureProtocol(uri); #endif if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("TCPConnector", string.Format("'{0}' - Connecting to {1}:{2}", request.CurrentUri.ToString(), uri.Host, uri.Port.ToString()), request.Context); } #if !NETFX_CORE && (!UNITY_WEBGL || UNITY_EDITOR) Client.SendBufferSize = HTTPManager.SendBufferSize; Client.ReceiveBufferSize = HTTPManager.ReceiveBufferSize; if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("TCPConnector", string.Format("'{0}' - Buffer sizes - Send: {1} Receive: {2} Blocking: {3}", request.CurrentUri.ToString(), Client.SendBufferSize.ToString(), Client.ReceiveBufferSize.ToString(), Client.Client.Blocking.ToString()), request.Context); } #endif #if NETFX_CORE && !UNITY_EDITOR && !ENABLE_IL2CPP try { Client.Connect(uri.Host, uri.Port); } finally { request.Timing.Add(TimingEventNames.TCP_Connection); } #else System.Net.IPAddress[] addresses = null; try { if (Client.ConnectTimeout > TimeSpan.Zero) { // https://forum.unity3d.com/threads/best-http-released.200006/page-37#post-3150972 using (System.Threading.ManualResetEvent mre = new System.Threading.ManualResetEvent(false)) { IAsyncResult result = System.Net.Dns.BeginGetHostAddresses(uri.Host, (res) => { try { mre.Set(); } catch { } }, null); bool success = mre.WaitOne(Client.ConnectTimeout); if (success) { addresses = System.Net.Dns.EndGetHostAddresses(result); } else { throw new TimeoutException("DNS resolve timed out!"); } } } else { addresses = System.Net.Dns.GetHostAddresses(uri.Host); } } finally { request.Timing.Add(TimingEventNames.DNS_Lookup); } if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("TCPConnector", string.Format("'{0}' - DNS Query returned with addresses: {1}", request.CurrentUri.ToString(), addresses != null ? addresses.Length : -1), request.Context); } if (request.IsCancellationRequested) { throw new Exception("IsCancellationRequested"); } try { Client.Connect(addresses, uri.Port, request); } finally { request.Timing.Add(TimingEventNames.TCP_Connection); } if (request.IsCancellationRequested) { throw new Exception("IsCancellationRequested"); } #endif if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("TCPConnector", "Connected to " + uri.Host + ":" + uri.Port.ToString(), request.Context); } } else if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("TCPConnector", "Already connected to " + uri.Host + ":" + uri.Port.ToString(), request.Context); } #endregion if (Stream == null) { bool isSecure = HTTPProtocolFactory.IsSecureProtocol(request.CurrentUri); // set the stream to Client.GetStream() so the proxy, if there's any can use it directly. this.Stream = this.TopmostStream = Client.GetStream(); /*if (Stream.CanTimeout) * Stream.ReadTimeout = Stream.WriteTimeout = (int)Request.Timeout.TotalMilliseconds;*/ #if !BESTHTTP_DISABLE_PROXY if (request.HasProxy) { try { request.Proxy.Connect(this.Stream, request); } finally { request.Timing.Add(TimingEventNames.Proxy_Negotiation); } } if (request.IsCancellationRequested) { throw new Exception("IsCancellationRequested"); } #endif // proxy connect is done, we can set the stream to a buffered one. HTTPProxy requires the raw NetworkStream for HTTPResponse's ReadUnknownSize! this.Stream = this.TopmostStream = new BufferedReadNetworkStream(Client.GetStream(), Math.Max(8 * 1024, HTTPManager.ReceiveBufferSize)); // We have to use Request.CurrentUri here, because uri can be a proxy uri with a different protocol if (isSecure) { DateTime tlsNegotiationStartedAt = DateTime.Now; #region SSL Upgrade #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) if (request.UseAlternateSSL) { var handler = new TlsClientProtocol(this.Stream, new BestHTTP.SecureProtocol.Org.BouncyCastle.Security.SecureRandom()); List <string> protocols = new List <string>(); #if !BESTHTTP_DISABLE_HTTP2 SupportedProtocols protocol = request.ProtocolHandler == SupportedProtocols.Unknown ? HTTPProtocolFactory.GetProtocolFromUri(request.CurrentUri) : request.ProtocolHandler; if (protocol == SupportedProtocols.HTTP) { // http/2 over tls (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids) protocols.Add(HTTPProtocolFactory.W3C_HTTP2); } #endif protocols.Add(HTTPProtocolFactory.W3C_HTTP1); AbstractTlsClient tlsClient = null; if (HTTPManager.TlsClientFactory == null) { tlsClient = HTTPManager.DefaultTlsClientFactory(request, protocols); } else { try { tlsClient = HTTPManager.TlsClientFactory(request, protocols); } catch { } if (tlsClient == null) { tlsClient = HTTPManager.DefaultTlsClientFactory(request, protocols); } } tlsClient.LoggingContext = request.Context; handler.Connect(tlsClient); if (!string.IsNullOrEmpty(tlsClient.ServerSupportedProtocol)) { negotiatedProtocol = tlsClient.ServerSupportedProtocol; } Stream = handler.Stream; } else #endif { #if !NETFX_CORE SslStream sslStream = new SslStream(Client.GetStream(), false, (sender, cert, chain, errors) => { return(request.CallCustomCertificationValidator(cert, chain)); }); if (!sslStream.IsAuthenticated) { sslStream.AuthenticateAsClient(request.CurrentUri.Host); } Stream = sslStream; #else Stream = Client.GetStream(); #endif } #endregion request.Timing.Add(TimingEventNames.TLS_Negotiation, DateTime.Now - tlsNegotiationStartedAt); } } this.NegotiatedProtocol = negotiatedProtocol; }
public void Connect(HTTPRequest request) { string negotiatedProtocol = HTTPProtocolFactory.W3C_HTTP1; Uri uri = #if !BESTHTTP_DISABLE_PROXY request.HasProxy ? request.Proxy.Address : #endif request.CurrentUri; #region TCP Connection if (Client == null) { Client = new TcpClient(); } if (!Client.Connected) { Client.ConnectTimeout = request.ConnectTimeout; #if NETFX_CORE Client.UseHTTPSProtocol = #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) !Request.UseAlternateSSL && #endif HTTPProtocolFactory.IsSecureProtocol(uri); #endif if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("TCPConnector", string.Format("'{0}' - Connecting to {1}:{2}", request.CurrentUri.ToString(), uri.Host, uri.Port.ToString())); } #if !NETFX_CORE && (!UNITY_WEBGL || UNITY_EDITOR) Client.SendBufferSize = HTTPManager.SendBufferSize; Client.ReceiveBufferSize = HTTPManager.ReceiveBufferSize; if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("TCPConnector", string.Format("'{0}' - Buffer sizes - Send: {1} Receive: {2} Blocking: {3}", request.CurrentUri.ToString(), Client.SendBufferSize.ToString(), Client.ReceiveBufferSize.ToString(), Client.Client.Blocking.ToString())); } #endif Client.Connect(uri.Host, uri.Port); if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("TCPConnector", "Connected to " + uri.Host + ":" + uri.Port.ToString()); } } else if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) { HTTPManager.Logger.Information("TCPConnector", "Already connected to " + uri.Host + ":" + uri.Port.ToString()); } #endregion if (Stream == null) { bool isSecure = HTTPProtocolFactory.IsSecureProtocol(request.CurrentUri); this.Stream = this.TopmostStream = Client.GetStream(); /*if (Stream.CanTimeout) * Stream.ReadTimeout = Stream.WriteTimeout = (int)Request.Timeout.TotalMilliseconds;*/ #if !BESTHTTP_DISABLE_PROXY if (request.Proxy != null) { request.Proxy.Connect(this.Stream, request); } #endif // We have to use Request.CurrentUri here, because uri can be a proxy uri with a different protocol if (isSecure) { #region SSL Upgrade #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) if (request.UseAlternateSSL) { var handler = new TlsClientProtocol(Client.GetStream(), new BestHTTP.SecureProtocol.Org.BouncyCastle.Security.SecureRandom()); // http://tools.ietf.org/html/rfc3546#section-3.1 // -It is RECOMMENDED that clients include an extension of type "server_name" in the client hello whenever they locate a server by a supported name type. // -Literal IPv4 and IPv6 addresses are not permitted in "HostName". // User-defined list has a higher priority List <string> hostNames = request.CustomTLSServerNameList; // If there's no user defined one and the host isn't an IP address, add the default one if ((hostNames == null || hostNames.Count == 0) && !request.CurrentUri.IsHostIsAnIPAddress()) { hostNames = new List <string>(1); hostNames.Add(request.CurrentUri.Host); } List <string> protocols = new List <string>(); #if !BESTHTTP_DISABLE_HTTP2 SupportedProtocols protocol = request.ProtocolHandler == SupportedProtocols.Unknown ? HTTPProtocolFactory.GetProtocolFromUri(request.CurrentUri) : request.ProtocolHandler; if (protocol == SupportedProtocols.HTTP) { // http/2 over tls (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids) protocols.Add(HTTPProtocolFactory.W3C_HTTP2); } #endif protocols.Add(HTTPProtocolFactory.W3C_HTTP1); var tlsClient = new LegacyTlsClient(request.CurrentUri, request.CustomCertificateVerifyer == null ? new AlwaysValidVerifyer() : request.CustomCertificateVerifyer, request.CustomClientCredentialsProvider, hostNames, protocols); handler.Connect(tlsClient); if (!string.IsNullOrEmpty(tlsClient.ServerSupportedProtocol)) { negotiatedProtocol = tlsClient.ServerSupportedProtocol; } Stream = handler.Stream; } else #endif { #if !NETFX_CORE SslStream sslStream = new SslStream(Client.GetStream(), false, (sender, cert, chain, errors) => { return(request.CallCustomCertificationValidator(cert, chain)); }); if (!sslStream.IsAuthenticated) { sslStream.AuthenticateAsClient(request.CurrentUri.Host); } Stream = sslStream; #else Stream = Client.GetStream(); #endif } #endregion } } this.NegotiatedProtocol = negotiatedProtocol; }
private void Close() { LastProcessedUri = null; if (Client != null) { try { Client.Close(); } catch { } finally { Stream = null; Client = null; } } }
private void Connect() { Uri uri = #if !BESTHTTP_DISABLE_PROXY CurrentRequest.HasProxy ? CurrentRequest.Proxy.Address : #endif CurrentRequest.CurrentUri; #region TCP Connection if (Client == null) Client = new TcpClient(); if (!Client.Connected) { Client.ConnectTimeout = CurrentRequest.ConnectTimeout; #if NETFX_CORE || (UNITY_WP8 && !UNITY_EDITOR) Client.UseHTTPSProtocol = #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) !CurrentRequest.UseAlternateSSL && #endif HTTPProtocolFactory.IsSecureProtocol(uri); #endif Client.Connect(uri.Host, uri.Port); if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) HTTPManager.Logger.Information("HTTPConnection", "Connected to " + uri.Host + ":" + uri.Port.ToString()); } else if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) HTTPManager.Logger.Information("HTTPConnection", "Already connected to " + uri.Host + ":" + uri.Port.ToString()); #endregion lock (HTTPManager.Locker) StartTime = DateTime.UtcNow; if (Stream == null) { bool isSecure = HTTPProtocolFactory.IsSecureProtocol(CurrentRequest.CurrentUri); #if !BESTHTTP_DISABLE_PROXY #region Proxy Handling if (HasProxy && (!Proxy.IsTransparent || (isSecure && Proxy.NonTransparentForHTTPS))) { Stream = Client.GetStream(); var outStream = new BinaryWriter(Stream); bool retry; do { // If we have to becouse of a authentication request, we will switch it to true retry = false; outStream.SendAsASCII(string.Format("CONNECT {0}:{1} HTTP/1.1", CurrentRequest.CurrentUri.Host, CurrentRequest.CurrentUri.Port)); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII("Proxy-Connection: Keep-Alive"); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII("Connection: Keep-Alive"); outStream.Write(HTTPRequest.EOL); outStream.SendAsASCII(string.Format("Host: {0}:{1}", CurrentRequest.CurrentUri.Host, CurrentRequest.CurrentUri.Port)); outStream.Write(HTTPRequest.EOL); // Proxy Authentication if (HasProxy && Proxy.Credentials != null) { switch (Proxy.Credentials.Type) { case AuthenticationTypes.Basic: // With Basic authentication we don't want to wait for a challange, we will send the hash with the first request outStream.Write(string.Format("Proxy-Authorization: {0}", string.Concat("Basic ", Convert.ToBase64String(Encoding.UTF8.GetBytes(Proxy.Credentials.UserName + ":" + Proxy.Credentials.Password)))).GetASCIIBytes()); outStream.Write(HTTPRequest.EOL); break; case AuthenticationTypes.Unknown: case AuthenticationTypes.Digest: var digest = DigestStore.Get(Proxy.Address); if (digest != null) { string authentication = digest.GenerateResponseHeader(CurrentRequest, Proxy.Credentials); if (!string.IsNullOrEmpty(authentication)) { outStream.Write(string.Format("Proxy-Authorization: {0}", authentication).GetASCIIBytes()); outStream.Write(HTTPRequest.EOL); } } break; } } outStream.Write(HTTPRequest.EOL); // Make sure to send all the wrote data to the wire outStream.Flush(); CurrentRequest.ProxyResponse = new HTTPResponse(CurrentRequest, Stream, false, false); // Read back the response of the proxy if (!CurrentRequest.ProxyResponse.Receive(-1, true)) throw new Exception("Connection to the Proxy Server failed!"); if (HTTPManager.Logger.Level <= Logger.Loglevels.Information) HTTPManager.Logger.Information("HTTPConnection", "Proxy returned - status code: " + CurrentRequest.ProxyResponse.StatusCode + " message: " + CurrentRequest.ProxyResponse.Message); switch(CurrentRequest.ProxyResponse.StatusCode) { // Proxy authentication required // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.8 case 407: { string authHeader = DigestStore.FindBest(CurrentRequest.ProxyResponse.GetHeaderValues("proxy-authenticate")); if (!string.IsNullOrEmpty(authHeader)) { var digest = DigestStore.GetOrCreate(Proxy.Address); digest.ParseChallange(authHeader); if (Proxy.Credentials != null && digest.IsUriProtected(Proxy.Address) && (!CurrentRequest.HasHeader("Proxy-Authorization") || digest.Stale)) retry = true; } break; } default: if (!CurrentRequest.ProxyResponse.IsSuccess) throw new Exception(string.Format("Proxy returned Status Code: \"{0}\", Message: \"{1}\" and Response: {2}", CurrentRequest.ProxyResponse.StatusCode, CurrentRequest.ProxyResponse.Message, CurrentRequest.ProxyResponse.DataAsText)); break; } } while (retry); } #endregion #endif // #if !BESTHTTP_DISABLE_PROXY // We have to use CurrentRequest.CurrentUri here, becouse uri can be a proxy uri with a different protocol if (isSecure) { #region SSL Upgrade #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) if (CurrentRequest.UseAlternateSSL) { var handler = new TlsClientProtocol(Client.GetStream(), new Org.BouncyCastle.Security.SecureRandom()); // http://tools.ietf.org/html/rfc3546#section-3.1 // It is RECOMMENDED that clients include an extension of type "server_name" in the client hello whenever they locate a server by a supported name type. List<string> hostNames = new List<string>(1); hostNames.Add(CurrentRequest.CurrentUri.Host); handler.Connect(new LegacyTlsClient(CurrentRequest.CurrentUri, CurrentRequest.CustomCertificateVerifyer == null ? new AlwaysValidVerifyer() : CurrentRequest.CustomCertificateVerifyer, CurrentRequest.CustomClientCredentialsProvider, hostNames)); Stream = handler.Stream; } else #endif { #if !NETFX_CORE && !UNITY_WP8 SslStream sslStream = new SslStream(Client.GetStream(), false, (sender, cert, chain, errors) => { return CurrentRequest.CallCustomCertificationValidator(cert, chain); }); if (!sslStream.IsAuthenticated) sslStream.AuthenticateAsClient(CurrentRequest.CurrentUri.Host); Stream = sslStream; #else Stream = Client.GetStream(); #endif } #endregion } else Stream = Client.GetStream(); } }