Exemple #1
0
        void ThreadFunc(object param)
        {
            bool alreadyReconnected = false;
            bool redirected         = false;

            RetryCauses cause = RetryCauses.None;

#if LOCK_ON_FILE
            object uriLock = null;
#endif

#if UNITY_WEBPLAYER
            // Right now, no caching supported in the webplayer
            if (!CurrentRequest.DisableCache)
            {
                CurrentRequest.DisableCache = true;
            }
#endif

            try
            {
                if (!HasProxy && CurrentRequest.HasProxy)
                {
                    Proxy = CurrentRequest.Proxy;
                }

                // Lock only if we will use the cached entity.
#if LOCK_ON_FILE
                if (!CurrentRequest.DisableCache)
                {
                    Monitor.Enter(uriLock = HTTPCacheFileLock.Acquire(CurrentRequest.CurrentUri));
                }
#endif

                // Try load the full response from an already saved cache entity. If the response
                if (TryLoadAllFromCache())
                {
                    return;
                }

                if (Client != null && !Client.IsConnected())
                {
                    Close();
                }

                do // of while (reconnect)
                {
                    if (cause == RetryCauses.Reconnect)
                    {
                        Close();
#if NETFX_CORE
                        await Task.Delay(100);
#else
                        Thread.Sleep(100);
#endif
                    }

                    LastProcessedUri = CurrentRequest.CurrentUri;

                    cause = RetryCauses.None;

                    // Connect to the server
                    Connect();

                    if (State == HTTPConnectionStates.AbortRequested)
                    {
                        throw new Exception("AbortRequested");
                    }

                    // Setup cache control headers before we send out the request
                    if (!CurrentRequest.DisableCache)
                    {
                        HTTPCacheService.SetHeaders(CurrentRequest);
                    }

                    // Write the request to the stream
                    // sentRequest will be true if the request sent out successfully(no SocketException), so we can try read the response
                    bool sentRequest = CurrentRequest.SendOutTo(Stream);

                    // sentRequest only true if there are no exceptions during CurrentRequest.SendOutTo.
                    if (!sentRequest)
                    {
                        Close();

                        if (State == HTTPConnectionStates.TimedOut)
                        {
                            throw new Exception("AbortRequested");
                        }

                        // We will try again only once
                        if (!alreadyReconnected)
                        {
                            alreadyReconnected = true;
                            cause = RetryCauses.Reconnect;
                        }
                    }

                    // If sending out the request succeded, we will try read the response.
                    if (sentRequest)
                    {
                        bool received = Receive();

                        if (State == HTTPConnectionStates.TimedOut)
                        {
                            throw new Exception("AbortRequested");
                        }

                        if (!received && !alreadyReconnected)
                        {
                            alreadyReconnected = true;
                            cause = RetryCauses.Reconnect;
                        }

                        if (CurrentRequest.Response != null)
                        {
                            switch (CurrentRequest.Response.StatusCode)
                            {
                            // Not authorized
                            // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
                            case 401:
                            {
                                string authHeader = CurrentRequest.Response.GetFirstHeaderValue("www-authenticate");
                                if (!string.IsNullOrEmpty(authHeader))
                                {
                                    var digest = DigestStore.GetOrCreate(CurrentRequest.CurrentUri);
                                    digest.ParseChallange(authHeader);

                                    if (CurrentRequest.Credentials != null && digest.IsUriProtected(CurrentRequest.CurrentUri) && (!CurrentRequest.HasHeader("Authorization") || digest.Stale))
                                    {
                                        cause = RetryCauses.Authenticate;
                                    }
                                }

                                goto default;
                            }

                            // Proxy authentication required
                            // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.8
                            case 407:
                            {
                                if (CurrentRequest.HasProxy)
                                {
                                    string authHeader = CurrentRequest.Response.GetFirstHeaderValue("proxy-authenticate");
                                    if (!string.IsNullOrEmpty(authHeader))
                                    {
                                        var digest = DigestStore.GetOrCreate(CurrentRequest.Proxy.Address);
                                        digest.ParseChallange(authHeader);

                                        if (CurrentRequest.Proxy.Credentials != null && digest.IsUriProtected(CurrentRequest.Proxy.Address) && (!CurrentRequest.HasHeader("Proxy-Authorization") || digest.Stale))
                                        {
                                            cause = RetryCauses.ProxyAuthenticate;
                                        }
                                    }
                                }

                                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 (CurrentRequest.RedirectCount >= CurrentRequest.MaxRedirects)
                                {
                                    goto default;
                                }
                                CurrentRequest.RedirectCount++;

                                string location = CurrentRequest.Response.GetFirstHeaderValue("location");
                                if (!string.IsNullOrEmpty(location))
                                {
                                    Uri redirectUri = GetRedirectUri(location);

                                    // Let the user to take some control over the redirection
                                    if (!CurrentRequest.CallOnBeforeRedirection(redirectUri))
                                    {
                                        HTTPManager.Logger.Information("HTTPConnection", "OnBeforeRedirection returned False");
                                        goto default;
                                    }

                                    // Remove the previously set Host header.
                                    CurrentRequest.RemoveHeader("Host");

                                    // Set the Referer header to the last Uri.
                                    CurrentRequest.SetHeader("Referer", CurrentRequest.CurrentUri.ToString());

                                    // Set the new Uri, the CurrentUri will return this while the IsRedirected property is true
                                    CurrentRequest.RedirectUri = redirectUri;

                                    // Discard the redirect response, we don't need it any more
                                    CurrentRequest.Response = null;

                                    redirected = CurrentRequest.IsRedirected = true;
                                }
                                else
                                            #if !NETFX_CORE
                                { throw new MissingFieldException(string.Format("Got redirect status({0}) without 'location' header!", CurrentRequest.Response.StatusCode.ToString())); }
                                            #else
                                { throw new Exception(string.Format("Got redirect status({0}) without 'location' header!", CurrentRequest.Response.StatusCode.ToString())); }
                                            #endif

                                goto default;
                            }

                            default:
                                if (CurrentRequest.IsCookiesEnabled)
                                {
                                    CookieJar.Set(CurrentRequest.Response);
                                }

                                TryStoreInCache();
                                break;
                            }

                            // If we have a response and the server telling us that it closed the connection after the message sent to us, then
                            //  we will colse the connection too.
                            if (CurrentRequest.Response == null ||
                                CurrentRequest.Response.HasHeaderWithValue("connection", "close") ||
                                CurrentRequest.UseAlternateSSL)
                            {
                                Close();
                            }
                        }
                    }
                } while (cause != RetryCauses.None);
            }
            catch (TimeoutException e)
            {
                CurrentRequest.Response  = null;
                CurrentRequest.Exception = e;
                CurrentRequest.State     = HTTPRequestStates.ConnectionTimedOut;

                Close();
            }
            catch (Exception e)
            {
                if (CurrentRequest.UseStreaming)
                {
                    HTTPCacheService.DeleteEntity(CurrentRequest.CurrentUri);
                }

                // Something gone bad, Response must be null!
                CurrentRequest.Response = null;

                switch (State)
                {
                case HTTPConnectionStates.AbortRequested:
                    CurrentRequest.State = HTTPRequestStates.Aborted;
                    break;

                case HTTPConnectionStates.TimedOut:
                    CurrentRequest.State = HTTPRequestStates.TimedOut;
                    break;

                default:
                    CurrentRequest.Exception = e;
                    CurrentRequest.State     = HTTPRequestStates.Error;
                    break;
                }

                Close();
            }
            finally
            {
#if LOCK_ON_FILE
                if (!CurrentRequest.DisableCache && uriLock != null)
                {
                    Monitor.Exit(uriLock);
                }
#endif

                // Avoid state changes. While we are in this block changing the connection's State, on Unity's main thread
                //  the HTTPManager's OnUpdate will check the connections's State and call functions that can change the inner state of
                //  the object. (Like setting the CurrentRequest to null in function Recycle() causing a NullRef exception)
                lock (HTTPManager.Locker)
                {
                    if (CurrentRequest != null && CurrentRequest.Response != null && CurrentRequest.Response.IsUpgraded)
                    {
                        State = HTTPConnectionStates.Upgraded;
                    }
                    else
                    {
                        State = redirected ? HTTPConnectionStates.Redirected : (Client == null ? HTTPConnectionStates.Closed : HTTPConnectionStates.WaitForRecycle);
                    }

                    // Change the request's state only when the whole processing finished
                    if (CurrentRequest.State == HTTPRequestStates.Processing && (State == HTTPConnectionStates.Closed || State == HTTPConnectionStates.WaitForRecycle))
                    {
                        CurrentRequest.State = HTTPRequestStates.Finished;
                    }

                    if (CurrentRequest.State == HTTPRequestStates.ConnectionTimedOut)
                    {
                        State = HTTPConnectionStates.Closed;
                    }

                    LastProcessTime = DateTime.UtcNow;
                }

                HTTPCacheService.SaveLibrary();
                CookieJar.Persist();
            }
        }
Exemple #2
0
        void ThreadFunc(object param)
        {
            bool alreadyReconnected = false;
            bool redirected         = false;

            RetryCauses cause = RetryCauses.None;

            try
            {
#if !BESTHTTP_DISABLE_PROXY
                if (!HasProxy && CurrentRequest.HasProxy)
                {
                    Proxy = CurrentRequest.Proxy;
                }
#endif

#if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
                // Try load the full response from an already saved cache entity. If the response
                if (TryLoadAllFromCache())
                {
                    return;
                }
#endif

                if (Client != null && !Client.IsConnected())
                {
                    Close();
                }

                do // of while (reconnect)
                {
                    if (cause == RetryCauses.Reconnect)
                    {
                        Close();
#if NETFX_CORE
                        await Task.Delay(100);
#else
                        Thread.Sleep(100);
#endif
                    }

                    LastProcessedUri = CurrentRequest.CurrentUri;

                    cause = RetryCauses.None;

                    // Connect to the server
                    Connect();

                    if (State == HTTPConnectionStates.AbortRequested)
                    {
                        throw new Exception("AbortRequested");
                    }

                    #if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
                    // Setup cache control headers before we send out the request
                    if (!CurrentRequest.DisableCache)
                    {
                        HTTPCacheService.SetHeaders(CurrentRequest);
                    }
                    #endif

                    // Write the request to the stream
                    // sentRequest will be true if the request sent out successfully(no SocketException), so we can try read the response
                    bool sentRequest = false;
                    try
                    {
#if !NETFX_CORE
                        Client.NoDelay = CurrentRequest.TryToMinimizeTCPLatency;
#endif
                        CurrentRequest.SendOutTo(Stream);

                        sentRequest = true;
                    }
                    catch (Exception ex)
                    {
                        Close();

                        if (State == HTTPConnectionStates.TimedOut ||
                            State == HTTPConnectionStates.AbortRequested)
                        {
                            throw new Exception("AbortRequested");
                        }

                        // We will try again only once
                        if (!alreadyReconnected && !CurrentRequest.DisableRetry)
                        {
                            alreadyReconnected = true;
                            cause = RetryCauses.Reconnect;
                        }
                        else // rethrow exception
                        {
                            throw ex;
                        }
                    }

                    // If sending out the request succeeded, we will try read the response.
                    if (sentRequest)
                    {
                        bool received = Receive();

                        if (State == HTTPConnectionStates.TimedOut ||
                            State == HTTPConnectionStates.AbortRequested)
                        {
                            throw new Exception("AbortRequested");
                        }

                        if (!received && !alreadyReconnected && !CurrentRequest.DisableRetry)
                        {
                            alreadyReconnected = true;
                            cause = RetryCauses.Reconnect;
                        }

                        if (CurrentRequest.Response != null)
                        {
#if !BESTHTTP_DISABLE_COOKIES && (!UNITY_WEBGL || UNITY_EDITOR)
                            // Try to store cookies before we do anything else, as we may remove the response deleting the cookies as well.
                            if (CurrentRequest.IsCookiesEnabled)
                            {
                                CookieJar.Set(CurrentRequest.Response);
                            }
#endif

                            switch (CurrentRequest.Response.StatusCode)
                            {
                            // Not authorized
                            // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
                            case 401:
                            {
                                string authHeader = DigestStore.FindBest(CurrentRequest.Response.GetHeaderValues("www-authenticate"));
                                if (!string.IsNullOrEmpty(authHeader))
                                {
                                    var digest = DigestStore.GetOrCreate(CurrentRequest.CurrentUri);
                                    digest.ParseChallange(authHeader);

                                    if (CurrentRequest.Credentials != null && digest.IsUriProtected(CurrentRequest.CurrentUri) && (!CurrentRequest.HasHeader("Authorization") || digest.Stale))
                                    {
                                        cause = RetryCauses.Authenticate;
                                    }
                                }

                                goto default;
                            }

#if !BESTHTTP_DISABLE_PROXY
                            // Proxy authentication required
                            // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.8
                            case 407:
                            {
                                if (CurrentRequest.HasProxy)
                                {
                                    string authHeader = DigestStore.FindBest(CurrentRequest.Response.GetHeaderValues("proxy-authenticate"));
                                    if (!string.IsNullOrEmpty(authHeader))
                                    {
                                        var digest = DigestStore.GetOrCreate(CurrentRequest.Proxy.Address);
                                        digest.ParseChallange(authHeader);

                                        if (CurrentRequest.Proxy.Credentials != null && digest.IsUriProtected(CurrentRequest.Proxy.Address) && (!CurrentRequest.HasHeader("Proxy-Authorization") || digest.Stale))
                                        {
                                            cause = RetryCauses.ProxyAuthenticate;
                                        }
                                    }
                                }

                                goto default;
                            }
#endif

                            // 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 (CurrentRequest.RedirectCount >= CurrentRequest.MaxRedirects)
                                {
                                    goto default;
                                }
                                CurrentRequest.RedirectCount++;

                                string location = CurrentRequest.Response.GetFirstHeaderValue("location");
                                if (!string.IsNullOrEmpty(location))
                                {
                                    Uri redirectUri = GetRedirectUri(location);

                                    if (HTTPManager.Logger.Level == Logger.Loglevels.All)
                                    {
                                        HTTPManager.Logger.Verbose("HTTPConnection", string.Format("{0} - Redirected to Location: '{1}' redirectUri: '{1}'", this.CurrentRequest.CurrentUri.ToString(), location, redirectUri));
                                    }

                                    // Let the user to take some control over the redirection
                                    if (!CurrentRequest.CallOnBeforeRedirection(redirectUri))
                                    {
                                        HTTPManager.Logger.Information("HTTPConnection", "OnBeforeRedirection returned False");
                                        goto default;
                                    }

                                    // Remove the previously set Host header.
                                    CurrentRequest.RemoveHeader("Host");

                                    // Set the Referer header to the last Uri.
                                    CurrentRequest.SetHeader("Referer", CurrentRequest.CurrentUri.ToString());

                                    // Set the new Uri, the CurrentUri will return this while the IsRedirected property is true
                                    CurrentRequest.RedirectUri = redirectUri;

                                    // Discard the redirect response, we don't need it any more
                                    CurrentRequest.Response = null;

                                    redirected = CurrentRequest.IsRedirected = true;
                                }
                                else
#if !NETFX_CORE
                                { throw new MissingFieldException(string.Format("Got redirect status({0}) without 'location' header!", CurrentRequest.Response.StatusCode.ToString())); }
#else
                                { throw new Exception(string.Format("Got redirect status({0}) without 'location' header!", CurrentRequest.Response.StatusCode.ToString())); }
#endif

                                goto default;
                            }


                            default:
#if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
                                TryStoreInCache();
#endif
                                break;
                            }

                            // 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 = CurrentRequest.Response == null || CurrentRequest.Response.HasHeaderWithValue("connection", "close");
                            bool closeByClient = !CurrentRequest.Response.IsClosedManually && !CurrentRequest.IsKeepAlive;
                            if (closeByServer || closeByClient)
                            {
                                Close();
                            }
                            else if (CurrentRequest.Response != null)
                            {
                                var keepAliveheaderValues = CurrentRequest.Response.GetHeaderValues("keep-alive");
                                if (keepAliveheaderValues != null && keepAliveheaderValues.Count > 0)
                                {
                                    if (KeepAlive == null)
                                    {
                                        KeepAlive = new KeepAliveHeader();
                                    }
                                    KeepAlive.Parse(keepAliveheaderValues);
                                }
                            }
                        }
                    }
                } while (cause != RetryCauses.None);
            }
            catch (TimeoutException e)
            {
                CurrentRequest.Response  = null;
                CurrentRequest.Exception = e;
                CurrentRequest.State     = HTTPRequestStates.ConnectionTimedOut;

                Close();
            }
            catch (Exception e)
            {
                if (CurrentRequest != null)
                {
#if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
                    if (CurrentRequest.UseStreaming)
                    {
                        HTTPCacheService.DeleteEntity(CurrentRequest.CurrentUri);
                    }
#endif

                    // Something gone bad, Response must be null!
                    CurrentRequest.Response = null;

                    switch (State)
                    {
                    case HTTPConnectionStates.Closed:
                    case HTTPConnectionStates.AbortRequested:
                        CurrentRequest.State = HTTPRequestStates.Aborted;
                        break;

                    case HTTPConnectionStates.TimedOut:
                        CurrentRequest.State = HTTPRequestStates.TimedOut;
                        break;

                    default:
                        CurrentRequest.Exception = e;
                        CurrentRequest.State     = HTTPRequestStates.Error;
                        break;
                    }
                }

                Close();
            }
            finally
            {
                if (CurrentRequest != null)
                {
                    // Avoid state changes. While we are in this block changing the connection's State, on Unity's main thread
                    //  the HTTPManager's OnUpdate will check the connections's State and call functions that can change the inner state of
                    //  the object. (Like setting the CurrentRequest to null in function Recycle() causing a NullRef exception)
                    lock (HTTPManager.Locker)
                    {
                        if (CurrentRequest != null && CurrentRequest.Response != null && CurrentRequest.Response.IsUpgraded)
                        {
                            State = HTTPConnectionStates.Upgraded;
                        }
                        else
                        {
                            State = redirected ? HTTPConnectionStates.Redirected : (Client == null ? HTTPConnectionStates.Closed : HTTPConnectionStates.WaitForRecycle);
                        }

                        // Change the request's state only when the whole processing finished
                        if (CurrentRequest.State == HTTPRequestStates.Processing && (State == HTTPConnectionStates.Closed || State == HTTPConnectionStates.WaitForRecycle))
                        {
                            if (CurrentRequest.Response != null)
                            {
                                CurrentRequest.State = HTTPRequestStates.Finished;
                            }
                            else
                            {
                                CurrentRequest.Exception = new Exception(string.Format("Remote server closed the connection before sending response header! Previous request state: {0}. Connection state: {1}",
                                                                                       CurrentRequest.State.ToString(),
                                                                                       State.ToString()));
                                CurrentRequest.State = HTTPRequestStates.Error;
                            }
                        }

                        if (CurrentRequest.State == HTTPRequestStates.ConnectionTimedOut)
                        {
                            State = HTTPConnectionStates.Closed;
                        }

                        LastProcessTime = DateTime.UtcNow;

                        if (OnConnectionRecycled != null)
                        {
                            RecycleNow();
                        }
                    }

#if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR)
                    HTTPCacheService.SaveLibrary();
#endif

#if !BESTHTTP_DISABLE_COOKIES && (!UNITY_WEBGL || UNITY_EDITOR)
                    CookieJar.Persist();
#endif
                }
            }
        }
        protected override void ThreadFunc(object param)
        {
            bool        flag  = false;
            bool        flag2 = false;
            RetryCauses none  = RetryCauses.None;

            try
            {
                if (!base.HasProxy && base.CurrentRequest.HasProxy)
                {
                    base.Proxy = base.CurrentRequest.Proxy;
                }
                if (!this.TryLoadAllFromCache())
                {
                    if ((this.Client != null) && !this.Client.IsConnected())
                    {
                        this.Close();
                    }
                    do
                    {
                        if (none == RetryCauses.Reconnect)
                        {
                            this.Close();
                            Thread.Sleep(100);
                        }
                        base.LastProcessedUri = base.CurrentRequest.CurrentUri;
                        none = RetryCauses.None;
                        this.Connect();
                        if (base.State == HTTPConnectionStates.AbortRequested)
                        {
                            throw new Exception("AbortRequested");
                        }
                        if (!base.CurrentRequest.DisableCache)
                        {
                            HTTPCacheService.SetHeaders(base.CurrentRequest);
                        }
                        bool flag3 = false;
                        try
                        {
                            this.Client.NoDelay = base.CurrentRequest.TryToMinimizeTCPLatency;
                            base.CurrentRequest.SendOutTo(this.Stream);
                            flag3 = true;
                        }
                        catch (Exception exception)
                        {
                            this.Close();
                            if ((base.State == HTTPConnectionStates.TimedOut) || (base.State == HTTPConnectionStates.AbortRequested))
                            {
                                throw new Exception("AbortRequested");
                            }
                            if (flag || base.CurrentRequest.DisableRetry)
                            {
                                throw exception;
                            }
                            flag = true;
                            none = RetryCauses.Reconnect;
                        }
                        if (flag3)
                        {
                            bool flag4 = this.Receive();
                            if ((base.State == HTTPConnectionStates.TimedOut) || (base.State == HTTPConnectionStates.AbortRequested))
                            {
                                throw new Exception("AbortRequested");
                            }
                            if ((!flag4 && !flag) && !base.CurrentRequest.DisableRetry)
                            {
                                flag = true;
                                none = RetryCauses.Reconnect;
                            }
                            if (base.CurrentRequest.Response != null)
                            {
                                if (base.CurrentRequest.IsCookiesEnabled)
                                {
                                    CookieJar.Set(base.CurrentRequest.Response);
                                }
                                switch (base.CurrentRequest.Response.StatusCode)
                                {
                                case 0x12d:
                                case 0x12e:
                                case 0x133:
                                case 0x134:
                                    if (base.CurrentRequest.RedirectCount < base.CurrentRequest.MaxRedirects)
                                    {
                                        HTTPRequest currentRequest = base.CurrentRequest;
                                        currentRequest.RedirectCount++;
                                        string firstHeaderValue = base.CurrentRequest.Response.GetFirstHeaderValue("location");
                                        if (string.IsNullOrEmpty(firstHeaderValue))
                                        {
                                            throw new MissingFieldException($"Got redirect status({base.CurrentRequest.Response.StatusCode.ToString()}) without 'location' header!");
                                        }
                                        Uri redirectUri = this.GetRedirectUri(firstHeaderValue);
                                        if (HTTPManager.Logger.Level == Loglevels.All)
                                        {
                                            HTTPManager.Logger.Verbose("HTTPConnection", string.Format("{0} - Redirected to Location: '{1}' redirectUri: '{1}'", base.CurrentRequest.CurrentUri.ToString(), firstHeaderValue, redirectUri));
                                        }
                                        if (!base.CurrentRequest.CallOnBeforeRedirection(redirectUri))
                                        {
                                            HTTPManager.Logger.Information("HTTPConnection", "OnBeforeRedirection returned False");
                                        }
                                        else
                                        {
                                            base.CurrentRequest.RemoveHeader("Host");
                                            base.CurrentRequest.SetHeader("Referer", base.CurrentRequest.CurrentUri.ToString());
                                            base.CurrentRequest.RedirectUri = redirectUri;
                                            base.CurrentRequest.Response    = null;
                                            bool flag5 = true;
                                            base.CurrentRequest.IsRedirected = flag5;
                                            flag2 = flag5;
                                        }
                                    }
                                    break;

                                case 0x191:
                                {
                                    string str = DigestStore.FindBest(base.CurrentRequest.Response.GetHeaderValues("www-authenticate"));
                                    if (!string.IsNullOrEmpty(str))
                                    {
                                        Digest orCreate = DigestStore.GetOrCreate(base.CurrentRequest.CurrentUri);
                                        orCreate.ParseChallange(str);
                                        if (((base.CurrentRequest.Credentials != null) && orCreate.IsUriProtected(base.CurrentRequest.CurrentUri)) && (!base.CurrentRequest.HasHeader("Authorization") || orCreate.Stale))
                                        {
                                            none = RetryCauses.Authenticate;
                                        }
                                    }
                                    break;
                                }

                                case 0x197:
                                    if (base.CurrentRequest.HasProxy)
                                    {
                                        string str2 = DigestStore.FindBest(base.CurrentRequest.Response.GetHeaderValues("proxy-authenticate"));
                                        if (!string.IsNullOrEmpty(str2))
                                        {
                                            Digest orCreate = DigestStore.GetOrCreate(base.CurrentRequest.Proxy.Address);
                                            orCreate.ParseChallange(str2);
                                            if (((base.CurrentRequest.Proxy.Credentials != null) && orCreate.IsUriProtected(base.CurrentRequest.Proxy.Address)) && (!base.CurrentRequest.HasHeader("Proxy-Authorization") || orCreate.Stale))
                                            {
                                                none = RetryCauses.ProxyAuthenticate;
                                            }
                                        }
                                    }
                                    break;
                                }
                                this.TryStoreInCache();
                                if ((base.CurrentRequest.Response == null) || !base.CurrentRequest.Response.IsClosedManually)
                                {
                                    bool flag6 = (base.CurrentRequest.Response == null) || base.CurrentRequest.Response.HasHeaderWithValue("connection", "close");
                                    bool flag7 = !base.CurrentRequest.IsKeepAlive;
                                    if (flag6 || flag7)
                                    {
                                        this.Close();
                                    }
                                    else if (base.CurrentRequest.Response != null)
                                    {
                                        List <string> headerValues = base.CurrentRequest.Response.GetHeaderValues("keep-alive");
                                        if ((headerValues != null) && (headerValues.Count > 0))
                                        {
                                            if (this.KeepAlive == null)
                                            {
                                                this.KeepAlive = new KeepAliveHeader();
                                            }
                                            this.KeepAlive.Parse(headerValues);
                                        }
                                    }
                                }
                            }
                        }
                    }while (none != RetryCauses.None);
                }
            }
            catch (TimeoutException exception2)
            {
                base.CurrentRequest.Response  = null;
                base.CurrentRequest.Exception = exception2;
                base.CurrentRequest.State     = HTTPRequestStates.ConnectionTimedOut;
                this.Close();
            }
            catch (Exception exception3)
            {
                if (base.CurrentRequest != null)
                {
                    if (base.CurrentRequest.UseStreaming)
                    {
                        HTTPCacheService.DeleteEntity(base.CurrentRequest.CurrentUri, true);
                    }
                    base.CurrentRequest.Response = null;
                    switch (base.State)
                    {
                    case HTTPConnectionStates.AbortRequested:
                    case HTTPConnectionStates.Closed:
                        base.CurrentRequest.State = HTTPRequestStates.Aborted;
                        goto Label_0685;

                    case HTTPConnectionStates.TimedOut:
                        base.CurrentRequest.State = HTTPRequestStates.TimedOut;
                        goto Label_0685;
                    }
                    base.CurrentRequest.Exception = exception3;
                    base.CurrentRequest.State     = HTTPRequestStates.Error;
                }
Label_0685:
                this.Close();
            }
            finally
            {
                if (base.CurrentRequest != null)
                {
                    object locker = HTTPManager.Locker;
                    lock (locker)
                    {
                        if (((base.CurrentRequest != null) && (base.CurrentRequest.Response != null)) && base.CurrentRequest.Response.IsUpgraded)
                        {
                            base.State = HTTPConnectionStates.Upgraded;
                        }
                        else
                        {
                            base.State = !flag2 ? ((this.Client != null) ? HTTPConnectionStates.WaitForRecycle : HTTPConnectionStates.Closed) : HTTPConnectionStates.Redirected;
                        }
                        if ((base.CurrentRequest.State == HTTPRequestStates.Processing) && ((base.State == HTTPConnectionStates.Closed) || (base.State == HTTPConnectionStates.WaitForRecycle)))
                        {
                            if (base.CurrentRequest.Response != null)
                            {
                                base.CurrentRequest.State = HTTPRequestStates.Finished;
                            }
                            else
                            {
                                base.CurrentRequest.Exception = new Exception($"Remote server closed the connection before sending response header! Previous request state: {base.CurrentRequest.State.ToString()}. Connection state: {base.State.ToString()}");
                                base.CurrentRequest.State     = HTTPRequestStates.Error;
                            }
                        }
                        if (base.CurrentRequest.State == HTTPRequestStates.ConnectionTimedOut)
                        {
                            base.State = HTTPConnectionStates.Closed;
                        }
                        base.LastProcessTime = DateTime.UtcNow;
                        if (base.OnConnectionRecycled != null)
                        {
                            base.RecycleNow();
                        }
                    }
                    HTTPCacheService.SaveLibrary();
                    CookieJar.Persist();
                }
            }
        }
        private void ThreadFunc(object param)
        {
            bool        flag        = false;
            bool        flag2       = false;
            RetryCauses retryCauses = RetryCauses.None;
            object      obj         = null;

            try
            {
                if (!CurrentRequest.DisableCache)
                {
                    Monitor.Enter(obj = HTTPCacheFileLock.Acquire(CurrentRequest.CurrentUri));
                }
                CurrentRequest.Processing = true;
                if (!TryLoadAllFromCache())
                {
                    if (Client != null && !Client.IsConnected())
                    {
                        Close();
                    }
                    do
                    {
                        if (retryCauses == RetryCauses.Reconnect)
                        {
                            Close();
                            Thread.Sleep(100);
                        }
                        retryCauses = RetryCauses.None;
                        Connect();
                        if (!CurrentRequest.DisableCache)
                        {
                            HTTPCacheService.SetHeaders(CurrentRequest);
                        }
                        bool flag3 = CurrentRequest.SendOutTo(Stream);
                        if (!flag3)
                        {
                            Close();
                            if (!flag)
                            {
                                flag        = true;
                                retryCauses = RetryCauses.Reconnect;
                            }
                        }
                        if (flag3)
                        {
                            if (!Receive() && !flag)
                            {
                                flag        = true;
                                retryCauses = RetryCauses.Reconnect;
                            }
                            if (CurrentRequest.Response != null)
                            {
                                switch (CurrentRequest.Response.StatusCode)
                                {
                                case 401:
                                {
                                    string firstHeaderValue2 = CurrentRequest.Response.GetFirstHeaderValue("www-authenticate");
                                    if (!string.IsNullOrEmpty(firstHeaderValue2))
                                    {
                                        Digest orCreate = DigestStore.GetOrCreate(CurrentRequest.CurrentUri);
                                        orCreate.ParseChallange(firstHeaderValue2);
                                        if (CurrentRequest.Credentials != null && orCreate.IsUriProtected(CurrentRequest.CurrentUri) && (!CurrentRequest.HasHeader("Authorization") || orCreate.Stale))
                                        {
                                            retryCauses = RetryCauses.Authenticate;
                                        }
                                    }
                                    break;
                                }

                                case 301:
                                case 302:
                                case 307:
                                    if (CurrentRequest.RedirectCount < CurrentRequest.MaxRedirects)
                                    {
                                        CurrentRequest.RedirectCount++;
                                        string firstHeaderValue = CurrentRequest.Response.GetFirstHeaderValue("location");
                                        if (string.IsNullOrEmpty(firstHeaderValue))
                                        {
                                            throw new MissingFieldException($"Got redirect status({CurrentRequest.Response.StatusCode.ToString()}) without 'location' header!");
                                        }
                                        CurrentRequest.RedirectUri = GetRedirectUri(firstHeaderValue);
                                        CurrentRequest.Response    = null;
                                        bool flag4 = true;
                                        CurrentRequest.IsRedirected = flag4;
                                        flag2 = flag4;
                                    }
                                    break;
                                }
                                TryStoreInCache();
                                if (CurrentRequest.Response.HasHeaderWithValue("connection", "close") || CurrentRequest.UseAlternateSSL)
                                {
                                    Close();
                                }
                            }
                        }
                    }while (retryCauses != 0);
                }
            }
            catch (Exception exception)
            {
                if (CurrentRequest.UseStreaming)
                {
                    HTTPCacheService.DeleteEntity(CurrentRequest.CurrentUri);
                }
                CurrentRequest.Response  = null;
                CurrentRequest.Exception = exception;
                Close();
            }
            finally
            {
                if (!CurrentRequest.DisableCache && obj != null)
                {
                    Monitor.Exit(obj);
                }
                HTTPCacheService.SaveLibrary();
                CurrentRequest.Processing = false;
                if (CurrentRequest != null && CurrentRequest.Response != null && CurrentRequest.Response.IsUpgraded)
                {
                    State = HTTPConnectionStates.Upgraded;
                }
                else
                {
                    State = (flag2 ? HTTPConnectionStates.Redirected : ((Client != null) ? HTTPConnectionStates.WaitForRecycle : HTTPConnectionStates.Closed));
                }
                LastProcessTime = DateTime.UtcNow;
            }
        }
Exemple #5
0
        protected override void ThreadFunc(object param)
        {
            bool        flag        = false;
            bool        flag2       = false;
            RetryCauses retryCauses = RetryCauses.None;

            try
            {
                if (!base.HasProxy && base.CurrentRequest.HasProxy)
                {
                    base.Proxy = base.CurrentRequest.Proxy;
                }
                if (!TryLoadAllFromCache())
                {
                    if (Client != null && !Client.IsConnected())
                    {
                        Close();
                    }
                    while (true)
                    {
                        if (retryCauses == RetryCauses.Reconnect)
                        {
                            Close();
                            Thread.Sleep(100);
                        }
                        base.LastProcessedUri = base.CurrentRequest.CurrentUri;
                        retryCauses           = RetryCauses.None;
                        Connect();
                        if (base.State == HTTPConnectionStates.AbortRequested)
                        {
                            throw new Exception("AbortRequested");
                        }
                        if (!base.CurrentRequest.DisableCache)
                        {
                            HTTPCacheService.SetHeaders(base.CurrentRequest);
                        }
                        bool flag3 = false;
                        try
                        {
                            base.CurrentRequest.SendOutTo(Stream);
                            flag3 = true;
                        }
                        catch (Exception ex)
                        {
                            Close();
                            if (base.State == HTTPConnectionStates.TimedOut)
                            {
                                throw new Exception("AbortRequested");
                            }
                            if (flag || base.CurrentRequest.DisableRetry)
                            {
                                throw ex;
                            }
                            flag        = true;
                            retryCauses = RetryCauses.Reconnect;
                        }
                        if (flag3)
                        {
                            bool flag4 = Receive();
                            if (base.State == HTTPConnectionStates.TimedOut)
                            {
                                break;
                            }
                            if (!flag4 && !flag && !base.CurrentRequest.DisableRetry)
                            {
                                flag        = true;
                                retryCauses = RetryCauses.Reconnect;
                            }
                            if (base.CurrentRequest.Response != null)
                            {
                                if (base.CurrentRequest.IsCookiesEnabled)
                                {
                                    CookieJar.Set(base.CurrentRequest.Response);
                                }
                                switch (base.CurrentRequest.Response.StatusCode)
                                {
                                case 401:
                                {
                                    string text2 = DigestStore.FindBest(base.CurrentRequest.Response.GetHeaderValues("www-authenticate"));
                                    if (!string.IsNullOrEmpty(text2))
                                    {
                                        Digest orCreate2 = DigestStore.GetOrCreate(base.CurrentRequest.CurrentUri);
                                        orCreate2.ParseChallange(text2);
                                        if (base.CurrentRequest.Credentials != null && orCreate2.IsUriProtected(base.CurrentRequest.CurrentUri) && (!base.CurrentRequest.HasHeader("Authorization") || orCreate2.Stale))
                                        {
                                            retryCauses = RetryCauses.Authenticate;
                                        }
                                    }
                                    break;
                                }

                                case 407:
                                    if (base.CurrentRequest.HasProxy)
                                    {
                                        string text = DigestStore.FindBest(base.CurrentRequest.Response.GetHeaderValues("proxy-authenticate"));
                                        if (!string.IsNullOrEmpty(text))
                                        {
                                            Digest orCreate = DigestStore.GetOrCreate(base.CurrentRequest.Proxy.Address);
                                            orCreate.ParseChallange(text);
                                            if (base.CurrentRequest.Proxy.Credentials != null && orCreate.IsUriProtected(base.CurrentRequest.Proxy.Address) && (!base.CurrentRequest.HasHeader("Proxy-Authorization") || orCreate.Stale))
                                            {
                                                retryCauses = RetryCauses.ProxyAuthenticate;
                                            }
                                        }
                                    }
                                    break;

                                case 301:
                                case 302:
                                case 307:
                                case 308:
                                    if (base.CurrentRequest.RedirectCount < base.CurrentRequest.MaxRedirects)
                                    {
                                        base.CurrentRequest.RedirectCount++;
                                        string firstHeaderValue = base.CurrentRequest.Response.GetFirstHeaderValue("location");
                                        if (string.IsNullOrEmpty(firstHeaderValue))
                                        {
                                            throw new MissingFieldException($"Got redirect status({base.CurrentRequest.Response.StatusCode.ToString()}) without 'location' header!");
                                        }
                                        Uri redirectUri = GetRedirectUri(firstHeaderValue);
                                        if (!base.CurrentRequest.CallOnBeforeRedirection(redirectUri))
                                        {
                                            HTTPManager.Logger.Information("HTTPConnection", "OnBeforeRedirection returned False");
                                        }
                                        else
                                        {
                                            base.CurrentRequest.RemoveHeader("Host");
                                            base.CurrentRequest.SetHeader("Referer", base.CurrentRequest.CurrentUri.ToString());
                                            base.CurrentRequest.RedirectUri = redirectUri;
                                            base.CurrentRequest.Response    = null;
                                            bool flag5 = true;
                                            base.CurrentRequest.IsRedirected = flag5;
                                            flag2 = flag5;
                                        }
                                    }
                                    break;
                                }
                                TryStoreInCache();
                                if (base.CurrentRequest.Response == null || (!base.CurrentRequest.Response.IsClosedManually && base.CurrentRequest.Response.HasHeaderWithValue("connection", "close")))
                                {
                                    Close();
                                }
                            }
                        }
                        if (retryCauses == RetryCauses.None)
                        {
                            return;
                        }
                    }
                    throw new Exception("AbortRequested");
                }
            }
            catch (TimeoutException exception)
            {
                base.CurrentRequest.Response  = null;
                base.CurrentRequest.Exception = exception;
                base.CurrentRequest.State     = HTTPRequestStates.ConnectionTimedOut;
                Close();
            }
            catch (Exception exception2)
            {
                if (base.CurrentRequest != null)
                {
                    if (base.CurrentRequest.UseStreaming)
                    {
                        HTTPCacheService.DeleteEntity(base.CurrentRequest.CurrentUri);
                    }
                    base.CurrentRequest.Response = null;
                    switch (base.State)
                    {
                    case HTTPConnectionStates.AbortRequested:
                    case HTTPConnectionStates.Closed:
                        base.CurrentRequest.State = HTTPRequestStates.Aborted;
                        break;

                    case HTTPConnectionStates.TimedOut:
                        base.CurrentRequest.State = HTTPRequestStates.TimedOut;
                        break;

                    default:
                        base.CurrentRequest.Exception = exception2;
                        base.CurrentRequest.State     = HTTPRequestStates.Error;
                        break;
                    }
                }
                Close();
            }
            finally
            {
                if (base.CurrentRequest != null)
                {
                    lock (HTTPManager.Locker)
                    {
                        if (base.CurrentRequest != null && base.CurrentRequest.Response != null && base.CurrentRequest.Response.IsUpgraded)
                        {
                            base.State = HTTPConnectionStates.Upgraded;
                        }
                        else
                        {
                            base.State = (flag2 ? HTTPConnectionStates.Redirected : ((Client != null) ? HTTPConnectionStates.WaitForRecycle : HTTPConnectionStates.Closed));
                        }
                        if (base.CurrentRequest.State == HTTPRequestStates.Processing && (base.State == HTTPConnectionStates.Closed || base.State == HTTPConnectionStates.WaitForRecycle))
                        {
                            if (base.CurrentRequest.Response != null)
                            {
                                base.CurrentRequest.State = HTTPRequestStates.Finished;
                            }
                            else
                            {
                                base.CurrentRequest.State = HTTPRequestStates.Error;
                            }
                        }
                        if (base.CurrentRequest.State == HTTPRequestStates.ConnectionTimedOut)
                        {
                            base.State = HTTPConnectionStates.Closed;
                        }
                        LastProcessTime = DateTime.UtcNow;
                        if (OnConnectionRecycled != null)
                        {
                            RecycleNow();
                        }
                    }
                    HTTPCacheService.SaveLibrary();
                    CookieJar.Persist();
                }
            }
        }