internal void Abort(HTTPConnectionStates newState) { State = newState; if (Stream != null) { Stream.Dispose(); } }
public ConnectionEventInfo(ConnectionBase sourceConn, HostProtocolSupport protocolSupport) { this.Source = sourceConn; this.Event = ConnectionEvents.ProtocolSupport; this.State = HTTPConnectionStates.Initial; this.ProtocolSupport = protocolSupport; }
public ConnectionEventInfo(ConnectionBase sourceConn, ConnectionEvents @event) { this.Source = sourceConn; this.Event = @event; this.State = HTTPConnectionStates.Initial; this.ProtocolSupport = HostProtocolSupport.Unknown; }
internal override void Abort(HTTPConnectionStates newState) { base.State = newState; if (base.State == HTTPConnectionStates.TimedOut) { base.TimedOutStart = DateTime.UtcNow; } throw new NotImplementedException(); }
public ConnectionEventInfo(ConnectionBase sourceConn, HTTPConnectionStates newState) { this.Source = sourceConn; this.Event = ConnectionEvents.StateChange; this.State = newState; this.ProtocolSupport = HostProtocolSupport.Unknown; }
internal override void Abort(HTTPConnectionStates newState) { State = newState; switch (State) { case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break; } throw new NotImplementedException(); }
internal override void Abort(HTTPConnectionStates newState) { State = newState; switch (State) { case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break; } XHR_Abort(this.NativeId); }
public ConnectionEventInfo(ConnectionBase sourceConn, HTTPRequest request) { this.Source = sourceConn; this.Event = ConnectionEvents.StateChange; this.State = HTTPConnectionStates.ClosedResendRequest; this.ProtocolSupport = HostProtocolSupport.Unknown; this.Request = request; }
internal override void Abort(HTTPConnectionStates newState) { base.State = newState; if (base.State == HTTPConnectionStates.TimedOut) { base.TimedOutStart = DateTime.UtcNow; } if (this.Stream != null) { this.Stream.Dispose(); } }
internal HostConnection RemoveConnection(ConnectionBase conn, HTTPConnectionStates setState) { conn.State = setState; conn.Dispose(); bool found = this.Connections.Remove(conn); if (!found) HTTPManager.Logger.Warning(typeof(HostConnection).Name, string.Format("RemoveConnection - Couldn't find connection! key: {0}", conn.ServerAddress), this.Context, conn.Context); return this; }
internal void Abort(HTTPConnectionStates newState) { this.State = newState; HTTPConnectionStates state = this.State; if (state == HTTPConnectionStates.TimedOut) { this.TimedOutStart = DateTime.UtcNow; } if (this.Stream != null) { this.Stream.Dispose(); } }
internal HostConnection RemoveConnection(ConnectionBase conn, HTTPConnectionStates setState) { conn.State = setState; conn.Dispose(); bool found = this.Connections.Remove(conn); if (!found) { HTTPManager.Logger.Warning(typeof(HostConnection).Name, string.Format("'{0}': RemoveConnection - Couldn't find connection! key: {1}", this.VariantId, conn.ServerAddress)); } return(this); }
internal void Abort(HTTPConnectionStates newState) { State = newState; switch (State) { case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break; } if (Stream != null) { Stream.Dispose(); } }
internal HostConnection RemoveConnection(ConnectionBase conn, HTTPConnectionStates setState) { conn.State = setState; conn.Dispose(); bool found = this.Connections.Remove(conn); if (!found) { HTTPManager.Logger.Warning(typeof(HostConnection).Name, "RemoveConnection - Couldn't find connection! key: " + conn.ServerAddress); } return(this); }
public void RunHandler() { HTTPManager.Logger.Information("HTTP1Handler", string.Format("[{0}] started processing request '{1}'", this, this.conn.CurrentRequest.CurrentUri.ToString())); HTTPConnectionStates proposedConnectionState = HTTPConnectionStates.Processing; bool resendRequest = false; try { if (this.conn.CurrentRequest.IsCancellationRequested) { return; } #if !BESTHTTP_DISABLE_CACHING // Try load the full response from an already saved cache entity. // If the response could be loaded completely, we can skip connecting (if not already) and a full round-trip time to the server. if (HTTPCacheService.IsCachedEntityExpiresInTheFuture(this.conn.CurrentRequest) && ConnectionHelper.TryLoadAllFromCache(this.ToString(), this.conn.CurrentRequest)) { HTTPManager.Logger.Information("HTTP1Handler", string.Format("[{0}] Request could be fully loaded from cache! '{1}'", this, this.conn.CurrentRequest.CurrentUri.ToString())); return; } #endif if (this.conn.CurrentRequest.IsCancellationRequested) { return; } #if !BESTHTTP_DISABLE_CACHING // Setup cache control headers before we send out the request if (!this.conn.CurrentRequest.DisableCache) { HTTPCacheService.SetHeaders(this.conn.CurrentRequest); } #endif // Write the request to the stream this.conn.CurrentRequest.SendOutTo(this.conn.connector.Stream); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } // Receive response from the server bool received = Receive(this.conn.CurrentRequest); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } if (!received && this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Retries++; resendRequest = true; return; } ConnectionHelper.HandleResponse(this.conn.ToString(), this.conn.CurrentRequest, out resendRequest, out proposedConnectionState, ref this._keepAlive); } catch (TimeoutException e) { this.conn.CurrentRequest.Response = null; // We will try again only once if (this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { this.conn.CurrentRequest.Retries++; resendRequest = true; } else { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.ConnectionTimedOut; } proposedConnectionState = HTTPConnectionStates.Closed; } catch (Exception e) { if (this.ShutdownType == ShutdownTypes.Immediate) { return; } #if !BESTHTTP_DISABLE_CACHING if (this.conn.CurrentRequest.UseStreaming) { HTTPCacheService.DeleteEntity(this.conn.CurrentRequest.CurrentUri); } #endif // Something gone bad, Response must be null! this.conn.CurrentRequest.Response = null; if (!this.conn.CurrentRequest.IsCancellationRequested) { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.Error; } proposedConnectionState = HTTPConnectionStates.Closed; } finally { // Exit ASAP if (this.ShutdownType != ShutdownTypes.Immediate) { if (this.conn.CurrentRequest.IsCancellationRequested) { // we don't know what stage the request is cancelled, we can't safely reuse the tcp channel. proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Response = null; this.conn.CurrentRequest.State = this.conn.CurrentRequest.IsTimedOut ? HTTPRequestStates.TimedOut : HTTPRequestStates.Aborted; } else if (resendRequest) { RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.conn.CurrentRequest, RequestEvents.Resend)); } else if (this.conn.CurrentRequest.Response != null && this.conn.CurrentRequest.Response.IsUpgraded) { proposedConnectionState = HTTPConnectionStates.WaitForProtocolShutdown; } else if (this.conn.CurrentRequest.State == HTTPRequestStates.Processing) { if (this.conn.CurrentRequest.Response != null) { this.conn.CurrentRequest.State = HTTPRequestStates.Finished; } else { this.conn.CurrentRequest.Exception = new Exception(string.Format("[{0}] Remote server closed the connection before sending response header! Previous request state: {1}. Connection state: {2}", this.ToString(), this.conn.CurrentRequest.State.ToString(), this.conn.State.ToString())); this.conn.CurrentRequest.State = HTTPRequestStates.Error; proposedConnectionState = HTTPConnectionStates.Closed; } } this.conn.CurrentRequest = null; if (proposedConnectionState == HTTPConnectionStates.Processing) { proposedConnectionState = HTTPConnectionStates.Recycle; } ConnectionEventHelper.EnqueueConnectionEvent(new ConnectionEventInfo(this.conn, proposedConnectionState)); } } }
public void RunHandler() { HTTPManager.Logger.Information("HTTP1Handler", string.Format("[{0}] started processing request '{1}'", this, this.conn.CurrentRequest.CurrentUri.ToString()), this.Context, this.conn.CurrentRequest.Context); System.Threading.Thread.CurrentThread.Name = "BestHTTP.HTTP1 R&W"; HTTPConnectionStates proposedConnectionState = HTTPConnectionStates.Processing; bool resendRequest = false; try { if (this.conn.CurrentRequest.IsCancellationRequested) { return; } #if !BESTHTTP_DISABLE_CACHING // Setup cache control headers before we send out the request if (!this.conn.CurrentRequest.DisableCache) { HTTPCacheService.SetHeaders(this.conn.CurrentRequest); } #endif // Write the request to the stream this.conn.CurrentRequest.QueuedAt = DateTime.MinValue; this.conn.CurrentRequest.ProcessingStarted = DateTime.UtcNow; this.conn.CurrentRequest.SendOutTo(this.conn.connector.Stream); this.conn.CurrentRequest.Timing.Add(TimingEventNames.Request_Sent); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } this.conn.CurrentRequest.OnCancellationRequested += OnCancellationRequested; // Receive response from the server bool received = Receive(this.conn.CurrentRequest); this.conn.CurrentRequest.Timing.Add(TimingEventNames.Response_Received); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } if (!received && this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Retries++; resendRequest = true; return; } ConnectionHelper.HandleResponse(this.conn.ToString(), this.conn.CurrentRequest, out resendRequest, out proposedConnectionState, ref this._keepAlive, this.conn.Context, this.conn.CurrentRequest.Context); } catch (TimeoutException e) { this.conn.CurrentRequest.Response = null; // Do nothing here if Abort() got called on the request, its State is already set. if (!this.conn.CurrentRequest.IsTimedOut) { // We will try again only once if (this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { this.conn.CurrentRequest.Retries++; resendRequest = true; } else { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.ConnectionTimedOut; } } proposedConnectionState = HTTPConnectionStates.Closed; } catch (Exception e) { if (this.ShutdownType == ShutdownTypes.Immediate) { return; } string exceptionMessage = string.Empty; if (e == null) { exceptionMessage = "null"; } else { System.Text.StringBuilder sb = new System.Text.StringBuilder(); Exception exception = e; int counter = 1; while (exception != null) { sb.AppendFormat("{0}: {1} {2}", counter++.ToString(), exception.Message, exception.StackTrace); exception = exception.InnerException; if (exception != null) { sb.AppendLine(); } } exceptionMessage = sb.ToString(); } HTTPManager.Logger.Verbose("HTTP1Handler", exceptionMessage, this.Context, this.conn.CurrentRequest.Context); #if !BESTHTTP_DISABLE_CACHING if (this.conn.CurrentRequest.UseStreaming) { HTTPCacheService.DeleteEntity(this.conn.CurrentRequest.CurrentUri); } #endif // Something gone bad, Response must be null! this.conn.CurrentRequest.Response = null; // Do nothing here if Abort() got called on the request, its State is already set. if (!this.conn.CurrentRequest.IsCancellationRequested) { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.Error; } proposedConnectionState = HTTPConnectionStates.Closed; } finally { this.conn.CurrentRequest.OnCancellationRequested -= OnCancellationRequested; // Exit ASAP if (this.ShutdownType != ShutdownTypes.Immediate) { if (this.conn.CurrentRequest.IsCancellationRequested) { // we don't know what stage the request is canceled, we can't safely reuse the tcp channel. proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Response = null; // The request's State already set, or going to be set soon in RequestEvents.cs. //this.conn.CurrentRequest.State = this.conn.CurrentRequest.IsTimedOut ? HTTPRequestStates.TimedOut : HTTPRequestStates.Aborted; } else if (resendRequest) { // Here introducing a ClosedResendRequest connection state, where we have to process the connection's state change to Closed // than we have to resend the request. // If we would send the Resend request here, than a few lines below the Closed connection state change, // request events are processed before connection events (just switching the EnqueueRequestEvent and EnqueueConnectionEvent wouldn't work // see order of ProcessQueues in HTTPManager.OnUpdate!) and it would pick this very same closing/closed connection! if (proposedConnectionState == HTTPConnectionStates.Closed) { ConnectionEventHelper.EnqueueConnectionEvent(new ConnectionEventInfo(this.conn, this.conn.CurrentRequest)); } else { RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.conn.CurrentRequest, RequestEvents.Resend)); } } else if (this.conn.CurrentRequest.Response != null && this.conn.CurrentRequest.Response.IsUpgraded) { proposedConnectionState = HTTPConnectionStates.WaitForProtocolShutdown; } else if (this.conn.CurrentRequest.State == HTTPRequestStates.Processing) { if (this.conn.CurrentRequest.Response != null) { this.conn.CurrentRequest.State = HTTPRequestStates.Finished; } else { this.conn.CurrentRequest.Exception = new Exception(string.Format("[{0}] Remote server closed the connection before sending response header! Previous request state: {1}. Connection state: {2}", this.ToString(), this.conn.CurrentRequest.State.ToString(), this.conn.State.ToString())); this.conn.CurrentRequest.State = HTTPRequestStates.Error; proposedConnectionState = HTTPConnectionStates.Closed; } } this.conn.CurrentRequest = null; if (proposedConnectionState == HTTPConnectionStates.Processing) { proposedConnectionState = HTTPConnectionStates.Recycle; } if (proposedConnectionState != HTTPConnectionStates.ClosedResendRequest) { ConnectionEventHelper.EnqueueConnectionEvent(new ConnectionEventInfo(this.conn, proposedConnectionState)); } } } }
protected override void ThreadFunc(object param) { try { using (FileStream stream = new FileStream(base.CurrentRequest.CurrentUri.LocalPath, FileMode.Open, FileAccess.Read)) { Stream[] streams = new Stream[] { new MemoryStream(), stream }; using (StreamList list = new StreamList(streams)) { list.Write("HTTP/1.1 200 Ok\r\n"); list.Write("Content-Type: application/octet-stream\r\n"); list.Write("Content-Length: " + stream.Length.ToString() + "\r\n"); list.Write("\r\n"); list.Seek(0L, SeekOrigin.Begin); base.CurrentRequest.Response = new HTTPResponse(base.CurrentRequest, list, base.CurrentRequest.UseStreaming, false); if (!base.CurrentRequest.Response.Receive(-1, true)) { base.CurrentRequest.Response = null; } } } } catch (Exception exception) { if (base.CurrentRequest != null) { base.CurrentRequest.Response = null; HTTPConnectionStates state = base.State; if (state != HTTPConnectionStates.AbortRequested) { if (state == HTTPConnectionStates.TimedOut) { goto Label_0139; } goto Label_014A; } base.CurrentRequest.State = HTTPRequestStates.Aborted; } return; Label_0139: base.CurrentRequest.State = HTTPRequestStates.TimedOut; return; Label_014A: base.CurrentRequest.Exception = exception; base.CurrentRequest.State = HTTPRequestStates.Error; } finally { base.State = HTTPConnectionStates.Closed; if (base.CurrentRequest.State == HTTPRequestStates.Processing) { if (base.CurrentRequest.Response != null) { base.CurrentRequest.State = HTTPRequestStates.Finished; } else { base.CurrentRequest.State = HTTPRequestStates.Error; } } } }
private void ThreadFunc(object param) { bool flag = false; bool flag2 = false; HTTPConnection.RetryCauses retryCauses = HTTPConnection.RetryCauses.None; try { if (!this.HasProxy && this.CurrentRequest.HasProxy) { this.Proxy = this.CurrentRequest.Proxy; } if (!this.TryLoadAllFromCache()) { if (this.Client != null && !this.Client.IsConnected()) { this.Close(); } while (true) { if (retryCauses == HTTPConnection.RetryCauses.Reconnect) { this.Close(); Thread.Sleep(100); } this.LastProcessedUri = this.CurrentRequest.CurrentUri; retryCauses = HTTPConnection.RetryCauses.None; this.Connect(); if (this.State == HTTPConnectionStates.AbortRequested) { break; } if (!this.CurrentRequest.DisableCache) { HTTPCacheService.SetHeaders(this.CurrentRequest); } bool flag3 = this.CurrentRequest.SendOutTo(this.Stream); if (!flag3) { this.Close(); if (this.State == HTTPConnectionStates.TimedOut) { goto Block_13; } if (!flag) { flag = true; retryCauses = HTTPConnection.RetryCauses.Reconnect; } } if (flag3) { bool flag4 = this.Receive(); if (this.State == HTTPConnectionStates.TimedOut) { goto Block_16; } if (!flag4 && !flag) { flag = true; retryCauses = HTTPConnection.RetryCauses.Reconnect; } if (this.CurrentRequest.Response != null) { int statusCode = this.CurrentRequest.Response.StatusCode; switch (statusCode) { case 301: case 302: case 307: case 308: { if (this.CurrentRequest.RedirectCount >= this.CurrentRequest.MaxRedirects) { goto IL_3F7; } this.CurrentRequest.RedirectCount++; string firstHeaderValue = this.CurrentRequest.Response.GetFirstHeaderValue("location"); if (string.IsNullOrEmpty(firstHeaderValue)) { goto IL_3C9; } Uri redirectUri = this.GetRedirectUri(firstHeaderValue); if (!this.CurrentRequest.CallOnBeforeRedirection(redirectUri)) { HTTPManager.Logger.Information("HTTPConnection", "OnBeforeRedirection returned False"); goto IL_3F7; } this.CurrentRequest.RemoveHeader("Host"); this.CurrentRequest.SetHeader("Referer", this.CurrentRequest.CurrentUri.ToString()); this.CurrentRequest.RedirectUri = redirectUri; this.CurrentRequest.Response = null; bool flag5 = true; this.CurrentRequest.IsRedirected = flag5; flag2 = flag5; goto IL_3F7; } case 303: case 304: case 305: case 306: IL_186: if (statusCode == 401) { string firstHeaderValue2 = this.CurrentRequest.Response.GetFirstHeaderValue("www-authenticate"); if (!string.IsNullOrEmpty(firstHeaderValue2)) { Digest orCreate = DigestStore.GetOrCreate(this.CurrentRequest.CurrentUri); orCreate.ParseChallange(firstHeaderValue2); if (this.CurrentRequest.Credentials != null && orCreate.IsUriProtected(this.CurrentRequest.CurrentUri) && (!this.CurrentRequest.HasHeader("Authorization") || orCreate.Stale)) { retryCauses = HTTPConnection.RetryCauses.Authenticate; } } goto IL_3F7; } if (statusCode != 407) { goto IL_3F7; } if (this.CurrentRequest.HasProxy) { string firstHeaderValue3 = this.CurrentRequest.Response.GetFirstHeaderValue("proxy-authenticate"); if (!string.IsNullOrEmpty(firstHeaderValue3)) { Digest orCreate2 = DigestStore.GetOrCreate(this.CurrentRequest.Proxy.Address); orCreate2.ParseChallange(firstHeaderValue3); if (this.CurrentRequest.Proxy.Credentials != null && orCreate2.IsUriProtected(this.CurrentRequest.Proxy.Address) && (!this.CurrentRequest.HasHeader("Proxy-Authorization") || orCreate2.Stale)) { retryCauses = HTTPConnection.RetryCauses.ProxyAuthenticate; } } } goto IL_3F7; } goto IL_186; IL_3F7: if (this.CurrentRequest.IsCookiesEnabled) { CookieJar.Set(this.CurrentRequest.Response); } this.TryStoreInCache(); if (this.CurrentRequest.Response == null || this.CurrentRequest.Response.HasHeaderWithValue("connection", "close") || this.CurrentRequest.UseAlternateSSL) { this.Close(); } } } if (retryCauses == HTTPConnection.RetryCauses.None) { goto Block_37; } } throw new Exception("AbortRequested"); Block_13: throw new Exception("AbortRequested"); Block_16: throw new Exception("AbortRequested"); IL_3C9: throw new MissingFieldException(string.Format("Got redirect status({0}) without 'location' header!", this.CurrentRequest.Response.StatusCode.ToString())); Block_37 :; } } catch (TimeoutException exception) { this.CurrentRequest.Response = null; this.CurrentRequest.Exception = exception; this.CurrentRequest.State = HTTPRequestStates.ConnectionTimedOut; this.Close(); } catch (Exception exception2) { if (this.CurrentRequest != null) { if (this.CurrentRequest.UseStreaming) { HTTPCacheService.DeleteEntity(this.CurrentRequest.CurrentUri, true); } this.CurrentRequest.Response = null; HTTPConnectionStates state = this.State; if (state != HTTPConnectionStates.AbortRequested) { if (state != HTTPConnectionStates.TimedOut) { this.CurrentRequest.Exception = exception2; this.CurrentRequest.State = HTTPRequestStates.Error; } else { this.CurrentRequest.State = HTTPRequestStates.TimedOut; } } else { this.CurrentRequest.State = HTTPRequestStates.Aborted; } } this.Close(); } finally { if (this.CurrentRequest != null) { object locker = HTTPManager.Locker; lock (locker) { if (this.CurrentRequest != null && this.CurrentRequest.Response != null && this.CurrentRequest.Response.IsUpgraded) { this.State = HTTPConnectionStates.Upgraded; } else { this.State = ((!flag2) ? ((this.Client != null) ? HTTPConnectionStates.WaitForRecycle : HTTPConnectionStates.Closed) : HTTPConnectionStates.Redirected); } if (this.CurrentRequest.State == HTTPRequestStates.Processing && (this.State == HTTPConnectionStates.Closed || this.State == HTTPConnectionStates.WaitForRecycle)) { this.CurrentRequest.State = HTTPRequestStates.Finished; } if (this.CurrentRequest.State == HTTPRequestStates.ConnectionTimedOut) { this.State = HTTPConnectionStates.Closed; } this.LastProcessTime = DateTime.UtcNow; } HTTPCacheService.SaveLibrary(); CookieJar.Persist(); } } }
public void RunHandler() { HTTPManager.Logger.Information("HTTP1Handler", string.Format("[{0}] started processing request '{1}'", this, this.conn.CurrentRequest.CurrentUri.ToString()), this.Context, this.conn.CurrentRequest.Context); HTTPConnectionStates proposedConnectionState = HTTPConnectionStates.Processing; bool resendRequest = false; try { if (this.conn.CurrentRequest.IsCancellationRequested) { return; } #if !BESTHTTP_DISABLE_CACHING // Setup cache control headers before we send out the request if (!this.conn.CurrentRequest.DisableCache) { HTTPCacheService.SetHeaders(this.conn.CurrentRequest); } #endif // Write the request to the stream this.conn.CurrentRequest.SendOutTo(this.conn.connector.Stream); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } this.conn.CurrentRequest.OnCancellationRequested += OnCancellationRequested; // Receive response from the server bool received = Receive(this.conn.CurrentRequest); if (this.conn.CurrentRequest.IsCancellationRequested) { return; } if (!received && this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Retries++; resendRequest = true; return; } ConnectionHelper.HandleResponse(this.conn.ToString(), this.conn.CurrentRequest, out resendRequest, out proposedConnectionState, ref this._keepAlive, this.conn.Context, this.conn.CurrentRequest.Context); } catch (TimeoutException e) { this.conn.CurrentRequest.Response = null; // We will try again only once if (this.conn.CurrentRequest.Retries < this.conn.CurrentRequest.MaxRetries) { this.conn.CurrentRequest.Retries++; resendRequest = true; } else { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.ConnectionTimedOut; } proposedConnectionState = HTTPConnectionStates.Closed; } catch (Exception e) { if (this.ShutdownType == ShutdownTypes.Immediate) { return; } string exceptionMessage = string.Empty; if (e == null) { exceptionMessage = "null"; } else { System.Text.StringBuilder sb = new System.Text.StringBuilder(); Exception exception = e; int counter = 1; while (exception != null) { sb.AppendFormat("{0}: {1} {2}", counter++.ToString(), exception.Message, exception.StackTrace); exception = exception.InnerException; if (exception != null) { sb.AppendLine(); } } exceptionMessage = sb.ToString(); } HTTPManager.Logger.Verbose("HTTP1Handler", exceptionMessage, this.Context, this.conn.CurrentRequest.Context); #if !BESTHTTP_DISABLE_CACHING if (this.conn.CurrentRequest.UseStreaming) { HTTPCacheService.DeleteEntity(this.conn.CurrentRequest.CurrentUri); } #endif // Something gone bad, Response must be null! this.conn.CurrentRequest.Response = null; if (!this.conn.CurrentRequest.IsCancellationRequested) { this.conn.CurrentRequest.Exception = e; this.conn.CurrentRequest.State = HTTPRequestStates.Error; } proposedConnectionState = HTTPConnectionStates.Closed; } finally { this.conn.CurrentRequest.OnCancellationRequested -= OnCancellationRequested; // Exit ASAP if (this.ShutdownType != ShutdownTypes.Immediate) { if (this.conn.CurrentRequest.IsCancellationRequested) { // we don't know what stage the request is canceled, we can't safely reuse the tcp channel. proposedConnectionState = HTTPConnectionStates.Closed; this.conn.CurrentRequest.Response = null; this.conn.CurrentRequest.State = this.conn.CurrentRequest.IsTimedOut ? HTTPRequestStates.TimedOut : HTTPRequestStates.Aborted; } else if (resendRequest) { RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.conn.CurrentRequest, RequestEvents.Resend)); } else if (this.conn.CurrentRequest.Response != null && this.conn.CurrentRequest.Response.IsUpgraded) { proposedConnectionState = HTTPConnectionStates.WaitForProtocolShutdown; } else if (this.conn.CurrentRequest.State == HTTPRequestStates.Processing) { if (this.conn.CurrentRequest.Response != null) { this.conn.CurrentRequest.State = HTTPRequestStates.Finished; } else { this.conn.CurrentRequest.Exception = new Exception(string.Format("[{0}] Remote server closed the connection before sending response header! Previous request state: {1}. Connection state: {2}", this.ToString(), this.conn.CurrentRequest.State.ToString(), this.conn.State.ToString())); this.conn.CurrentRequest.State = HTTPRequestStates.Error; proposedConnectionState = HTTPConnectionStates.Closed; } } this.conn.CurrentRequest = null; if (proposedConnectionState == HTTPConnectionStates.Processing) { proposedConnectionState = HTTPConnectionStates.Recycle; } ConnectionEventHelper.EnqueueConnectionEvent(new ConnectionEventInfo(this.conn, proposedConnectionState)); } } }
internal abstract void Abort(HTTPConnectionStates hTTPConnectionStates);
public static void HandleResponse(string context, HTTPRequest request, out bool resendRequest, out HTTPConnectionStates proposedConnectionState, ref KeepAliveHeader keepAlive) { resendRequest = false; proposedConnectionState = HTTPConnectionStates.Processing; if (request.Response != null) { #if !BESTHTTP_DISABLE_COOKIES // Try to store cookies before we do anything else, as we may remove the response deleting the cookies as well. if (request.IsCookiesEnabled && CookieJar.Set(request.Response)) { PluginEventHelper.EnqueuePluginEvent(new PluginEventInfo(PluginEvents.SaveCookieLibrary)); } #endif switch (request.Response.StatusCode) { // Not authorized // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 case 401: { string authHeader = DigestStore.FindBest(request.Response.GetHeaderValues("www-authenticate")); if (!string.IsNullOrEmpty(authHeader)) { var digest = DigestStore.GetOrCreate(request.CurrentUri); digest.ParseChallange(authHeader); if (request.Credentials != null && digest.IsUriProtected(request.CurrentUri) && (!request.HasHeader("Authorization") || digest.Stale)) { resendRequest = true; } } goto default; } // Redirected case 301: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.2 case 302: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.3 case 307: // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.8 case 308: // http://tools.ietf.org/html/rfc7238 { if (request.RedirectCount >= request.MaxRedirects) { goto default; } request.RedirectCount++; string location = request.Response.GetFirstHeaderValue("location"); if (!string.IsNullOrEmpty(location)) { Uri redirectUri = ConnectionHelper.GetRedirectUri(request, location); if (HTTPManager.Logger.Level == Logger.Loglevels.All) { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("[{0}] - Redirected to Location: '{1}' redirectUri: '{1}'", context, location, redirectUri)); } // Let the user to take some control over the redirection if (!request.CallOnBeforeRedirection(redirectUri)) { HTTPManager.Logger.Information("HTTPConnection", string.Format("[{0}] OnBeforeRedirection returned False", context)); goto default; } // Remove the previously set Host header. request.RemoveHeader("Host"); // Set the Referer header to the last Uri. request.SetHeader("Referer", request.CurrentUri.ToString()); // Set the new Uri, the CurrentUri will return this while the IsRedirected property is true request.RedirectUri = redirectUri; // Discard the redirect response, we don't need it any more request.Response = null; request.IsRedirected = true; resendRequest = true; } else { throw new Exception(string.Format("[{0}] Got redirect status({1}) without 'location' header!", context, request.Response.StatusCode.ToString())); } goto default; } #if !BESTHTTP_DISABLE_CACHING case 304: if (request.DisableCache) { break; } if (ConnectionHelper.LoadFromCache(context, request)) { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("[{0}] - HandleResponse - Loaded from cache successfully!", context)); } else { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("[{0}] - HandleResponse - Loaded from cache failed!", context)); resendRequest = true; } break; #endif default: #if !BESTHTTP_DISABLE_CACHING ConnectionHelper.TryStoreInCache(request); #endif break; } // Closing the stream is done manually? if (!request.Response.IsClosedManually) { // If we have a response and the server telling us that it closed the connection after the message sent to us, then // we will close the connection too. bool closeByServer = request.Response.HasHeaderWithValue("connection", "close"); bool closeByClient = !request.IsKeepAlive; if (closeByServer || closeByClient) { proposedConnectionState = HTTPConnectionStates.Closed; } else if (request.Response != null) { var keepAliveheaderValues = request.Response.GetHeaderValues("keep-alive"); if (keepAliveheaderValues != null && keepAliveheaderValues.Count > 0) { if (keepAlive == null) { keepAlive = new KeepAliveHeader(); } keepAlive.Parse(keepAliveheaderValues); } } } } }
internal void Abort(HTTPConnectionStates newState) { State = newState; if (Stream != null) Stream.Dispose(); }
internal void Abort(HTTPConnectionStates newState) { State = newState; switch(State) { case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break; } if (Stream != null) Stream.Dispose(); }
void OnResponse(int httpStatus, byte[] buffer, int bufferLength) { HTTPConnectionStates proposedConnectionState = HTTPConnectionStates.Processing; bool resendRequest = false; try { if (this.CurrentRequest.IsCancellationRequested) { return; } using (var ms = new BufferPoolMemoryStream()) { Stream = ms; XHR_GetStatusLine(NativeId, OnBufferCallback); XHR_GetResponseHeaders(NativeId, OnBufferCallback); if (buffer != null && bufferLength > 0) { ms.Write(buffer, 0, bufferLength); } ms.Seek(0L, SeekOrigin.Begin); var internalBuffer = ms.GetBuffer(); string tmp = System.Text.Encoding.UTF8.GetString(internalBuffer); HTTPManager.Logger.Information(this.NativeId + " OnResponse - full response ", tmp, this.Context); SupportedProtocols protocol = CurrentRequest.ProtocolHandler == SupportedProtocols.Unknown ? HTTPProtocolFactory.GetProtocolFromUri(CurrentRequest.CurrentUri) : CurrentRequest.ProtocolHandler; CurrentRequest.Response = HTTPProtocolFactory.Get(protocol, CurrentRequest, ms, CurrentRequest.UseStreaming, false); CurrentRequest.Response.Receive(buffer != null && bufferLength > 0 ? (int)bufferLength : -1, true); KeepAliveHeader keepAlive = null; ConnectionHelper.HandleResponse(this.ToString(), this.CurrentRequest, out resendRequest, out proposedConnectionState, ref keepAlive); } } catch (Exception e) { HTTPManager.Logger.Exception(this.NativeId + " WebGLConnection", "OnResponse", e, this.Context); if (this.ShutdownType == ShutdownTypes.Immediate) { return; } #if !BESTHTTP_DISABLE_CACHING if (this.CurrentRequest.UseStreaming) { HTTPCacheService.DeleteEntity(this.CurrentRequest.CurrentUri); } #endif // Something gone bad, Response must be null! this.CurrentRequest.Response = null; if (!this.CurrentRequest.IsCancellationRequested) { this.CurrentRequest.Exception = e; this.CurrentRequest.State = HTTPRequestStates.Error; } proposedConnectionState = HTTPConnectionStates.Closed; } finally { // Exit ASAP if (this.ShutdownType != ShutdownTypes.Immediate) { if (this.CurrentRequest.IsCancellationRequested) { // we don't know what stage the request is cancelled, we can't safely reuse the tcp channel. proposedConnectionState = HTTPConnectionStates.Closed; this.CurrentRequest.Response = null; this.CurrentRequest.State = this.CurrentRequest.IsTimedOut ? HTTPRequestStates.TimedOut : HTTPRequestStates.Aborted; } else if (resendRequest) { RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.CurrentRequest, RequestEvents.Resend)); } else if (this.CurrentRequest.Response != null && this.CurrentRequest.Response.IsUpgraded) { proposedConnectionState = HTTPConnectionStates.WaitForProtocolShutdown; } else if (this.CurrentRequest.State == HTTPRequestStates.Processing) { if (this.CurrentRequest.Response != null) { this.CurrentRequest.State = HTTPRequestStates.Finished; } else { this.CurrentRequest.Exception = new Exception(string.Format("[{0}] Remote server closed the connection before sending response header! Previous request state: {1}. Connection state: {2}", this.ToString(), this.CurrentRequest.State.ToString(), this.State.ToString())); this.CurrentRequest.State = HTTPRequestStates.Error; proposedConnectionState = HTTPConnectionStates.Closed; } } this.CurrentRequest = null; if (proposedConnectionState == HTTPConnectionStates.Processing) { proposedConnectionState = HTTPConnectionStates.Closed; } ConnectionEventHelper.EnqueueConnectionEvent(new ConnectionEventInfo(this, proposedConnectionState)); } } }