예제 #1
0
 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;
        }
예제 #4
0
 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;
        }
예제 #6
0
        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);
        }
예제 #8
0
        internal override void Abort(HTTPConnectionStates newState)
        {
            State = newState;

            switch (State)
            {
            case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
            }

            XHR_Abort(this.NativeId);
        }
예제 #9
0
        public ConnectionEventInfo(ConnectionBase sourceConn, HTTPRequest request)
        {
            this.Source = sourceConn;

            this.Event = ConnectionEvents.StateChange;

            this.State = HTTPConnectionStates.ClosedResendRequest;

            this.ProtocolSupport = HostProtocolSupport.Unknown;

            this.Request = request;
        }
예제 #10
0
 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();
     }
 }
예제 #11
0
        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;
        }
예제 #12
0
        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();
            }
        }
예제 #13
0
        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);
        }
예제 #14
0
        internal void Abort(HTTPConnectionStates newState)
        {
            State = newState;

            switch (State)
            {
            case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
            }

            if (Stream != null)
            {
                Stream.Dispose();
            }
        }
예제 #15
0
        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);
        }
예제 #16
0
        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));
                }
            }
        }
예제 #17
0
        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));
                    }
                }
            }
        }
예제 #18
0
        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;
                    }
                }
            }
        }
예제 #19
0
        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));
                }
            }
        }
예제 #21
0
 internal abstract void Abort(HTTPConnectionStates hTTPConnectionStates);
예제 #22
0
 internal abstract void Abort(HTTPConnectionStates hTTPConnectionStates);
예제 #23
0
        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);
                        }
                    }
                }
            }
        }
예제 #24
0
 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();
        }
        internal override void Abort(HTTPConnectionStates newState)
        {
            State = newState;

            switch (State)
            {
                case HTTPConnectionStates.TimedOut: TimedOutStart = DateTime.UtcNow; break;
            }

            throw new NotImplementedException();
        }
        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));
                }
            }
        }