private bool LoadFromCache(Uri uri) { int length; using (Stream stream = HTTPCacheService.GetBody(uri, out length)) { if (stream == null) { return(false); } if (!base.CurrentRequest.Response.HasHeader("content-length")) { base.CurrentRequest.Response.Headers.Add("content-length", new List <string>(1) { length.ToString() }); } base.CurrentRequest.Response.IsFromCache = true; base.CurrentRequest.Response.ReadRaw(stream, length); } return(true); }
public static void OnQuit() { HTTPManager.Logger.Information("HTTPManager", "OnQuit called!"); IsQuitting = true; AbortAll(); #if !BESTHTTP_DISABLE_CACHING HTTPCacheService.SaveLibrary(); #endif #if !BESTHTTP_DISABLE_COOKIES CookieJar.Persist(); #endif OnUpdate(); HostManager.Clear(); Heartbeats.Clear(); }
private bool TryLoadAllFromCache() { if (CurrentRequest.DisableCache) { return(false); } try { if (HTTPCacheService.IsCachedEntityExpiresInTheFuture(CurrentRequest)) { CurrentRequest.Response = HTTPCacheService.GetFullResponse(CurrentRequest); if (CurrentRequest.Response != null) { return(true); } } } catch { HTTPCacheService.DeleteEntity(CurrentRequest.CurrentUri); } return(false); }
public static void Setup() { if (IsSetupCalled) { return; } IsSetupCalled = true; IsQuitting = false; HTTPManager.Logger.Information("HTTPManager", "Setup called! UserAgent: " + UserAgent); HTTPUpdateDelegator.CheckInstance(); #if !BESTHTTP_DISABLE_CACHING HTTPCacheService.CheckSetup(); #endif #if !BESTHTTP_DISABLE_COOKIES Cookies.CookieJar.SetupFolder(); Cookies.CookieJar.Load(); #endif HostManager.Load(); }
private bool Receive() { SupportedProtocols protocol = CurrentRequest.ProtocolHandler == SupportedProtocols.Unknown ? HTTPProtocolFactory.GetProtocolFromUri(CurrentRequest.CurrentUri) : CurrentRequest.ProtocolHandler; CurrentRequest.Response = HTTPProtocolFactory.Get(protocol, CurrentRequest, Stream, CurrentRequest.UseStreaming, false); if (!CurrentRequest.Response.Receive()) { CurrentRequest.Response = null; return(false); } // We didn't check HTTPManager.IsCachingDisabled's value on purpose. (sending out a request with conditional get then change IsCachingDisabled to true may produce undefined behavior) if (CurrentRequest.Response.StatusCode == 304) { #if !BESTHTTP_DISABLE_CACHING && (!UNITY_WEBGL || UNITY_EDITOR) int bodyLength; using (var cacheStream = HTTPCacheService.GetBody(CurrentRequest.CurrentUri, out bodyLength)) { if (!CurrentRequest.Response.HasHeader("content-length")) { CurrentRequest.Response.Headers.Add("content-length", new List <string>(1) { bodyLength.ToString() }); } CurrentRequest.Response.IsFromCache = true; CurrentRequest.Response.ReadRaw(cacheStream, bodyLength); } #else return(false); #endif } return(true); }
private bool LoadFromCache(Uri uri) { if (HTTPManager.Logger.Level == Loglevels.All) { HTTPManager.Logger.Verbose("HTTPConnection", $"{base.CurrentRequest.CurrentUri.ToString()} - LoadFromCache for Uri: {uri.ToString()}"); } HTTPCacheFileInfo entity = HTTPCacheService.GetEntity(uri); if (entity == null) { HTTPManager.Logger.Warning("HTTPConnection", $"{base.CurrentRequest.CurrentUri.ToString()} - LoadFromCache for Uri: {uri.ToString()} - Cached entity not found!"); return(false); } base.CurrentRequest.Response.CacheFileInfo = entity; using (System.IO.Stream stream = entity.GetBodyStream(out int num)) { if (stream == null) { return(false); } if (!base.CurrentRequest.Response.HasHeader("content-length")) { List <string> list = new List <string>(1) { num.ToString() }; base.CurrentRequest.Response.Headers.Add("content-length", list); } base.CurrentRequest.Response.IsFromCache = true; if (!base.CurrentRequest.CacheOnly) { base.CurrentRequest.Response.ReadRaw(stream, (long)num); } } return(true); }
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(); } } }
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 } } }
public static void DownloadImage(string imageUrl, int imageSize, OnImageDownloaded onImageDownload, string fallbackImageUrl = "", bool isRetry = false) { ImageDownloader imageDownloaderQueue = CreateInstanceIfNeeded(); if (!string.IsNullOrEmpty(imageUrl)) { if (downloadingImages == null) { downloadingImages = new Dictionary <string, List <OnImageDownloaded> >(); } if (downloadedImages == null) { downloadedImages = new Dictionary <string, Texture2D>(); } if (cachedImageQueue == null) { cachedImageQueue = new List <string>(); } string cacheRef = imageUrl + ":" + imageSize; if (downloadedImages.ContainsKey(cacheRef)) { onImageDownload(downloadedImages[cacheRef]); } else if (downloadingImages.ContainsKey(cacheRef)) { downloadingImages[cacheRef].Add(onImageDownload); } else { try { string url = imageUrl; bool flag = false; if (imageSize != 0 && imageUrl.StartsWith("https://api.vrchat.cloud/api/1/file/")) { string[] array = imageUrl.Remove(0, "https://api.vrchat.cloud/api/1/file/".Length).Split('/'); if (array.Length == 2 || (array.Length == 3 && array[2] == "file")) { string text = array[0]; string text2 = array[1]; url = "https://api.vrchat.cloud/api/1/image/" + text + "/" + text2 + "/" + imageSize.ToString(); flag = true; } } downloadingImages[cacheRef] = new List <OnImageDownloaded>(); HTTPManager.SendRequest(url, HTTPMethods.Get, HTTPManager.KeepAliveDefaultValue, disableCache : false, delegate(HTTPRequest request, HTTPResponse response) { Action loadImage2 = delegate { if (response != null) { Texture2D dataAsTexture2D = response.DataAsTexture2D; EncacheTexture(cacheRef, dataAsTexture2D); onImageDownload(dataAsTexture2D); foreach (OnImageDownloaded item in downloadingImages[cacheRef]) { item(response.DataAsTexture2D); } downloadingImages.Remove(cacheRef); } else { Debug.LogError((object)("No response received: " + ((request.Exception == null) ? "No Exception" : (request.Exception.Message + "\n" + request.Exception.StackTrace)))); DownloadFallbackOrUseErrorImage(fallbackImageUrl, onImageDownload); } }; if (response != null && response.Data == null) { downloadingImages.Remove(cacheRef); HTTPCacheService.DeleteEntity(request.CurrentUri); if (!isRetry) { DownloadImage(imageUrl, imageSize, onImageDownload, fallbackImageUrl, isRetry: true); } } else if (imageDownloaderQueue != null) { imageDownloaderQueue.QueueImageLoad(loadImage2); } }); } catch (Exception ex) { Exception e; Exception ex2 = e = ex; Action loadImage = delegate { Debug.Log((object)("Could not download image " + imageUrl + " - " + e.Message)); DownloadFallbackOrUseErrorImage(fallbackImageUrl, onImageDownload); }; imageDownloaderQueue.QueueImageLoad(loadImage); } } } }
private void ProcessState(List <HTTP2FrameHeaderAndPayload> outgoingFrames) { switch (this.State) { case HTTP2StreamStates.Idle: UInt32 initiatedInitialWindowSize = this.settings.InitiatedMySettings[HTTP2Settings.INITIAL_WINDOW_SIZE]; this.localWindow = initiatedInitialWindowSize; // window update with a zero increment would be an error (https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE) //if (HTTP2Connection.MaxValueFor31Bits > initiatedInitialWindowSize) // this.outgoing.Enqueue(HTTP2FrameHelper.CreateWindowUpdateFrame(this.Id, HTTP2Connection.MaxValueFor31Bits - initiatedInitialWindowSize)); //this.localWindow = HTTP2Connection.MaxValueFor31Bits; #if !BESTHTTP_DISABLE_CACHING // Setup cache control headers before we send out the request if (!this.AssignedRequest.DisableCache) { HTTPCacheService.SetHeaders(this.AssignedRequest); } #endif // hpack encode the request's header this.encoder.Encode(this, this.AssignedRequest, this.outgoing, this.Id); // HTTP/2 uses DATA frames to carry message payloads. // The chunked transfer encoding defined in Section 4.1 of [RFC7230] MUST NOT be used in HTTP/2. this.bodyToSend = this.AssignedRequest.GetEntityBody(); this.State = HTTP2StreamStates.Open; if (this.bodyToSend == null || this.bodyToSend.Length == 0) { this.State = HTTP2StreamStates.HalfClosedLocal; } else { this.State = HTTP2StreamStates.Open; } break; case HTTP2StreamStates.Open: // remote Window can be negative! See https://httpwg.org/specs/rfc7540.html#InitialWindowSize if (this.remoteWindow <= 0) { HTTPManager.Logger.Warning("HTTP2Stream", string.Format("[{0}] Skipping data sending as remote Window is {1}!", this.Id, this.remoteWindow)); return; } // This step will send one frame per OpenState call. Int64 maxFrameSize = Math.Min(this.remoteWindow, this.settings.RemoteSettings[HTTP2Settings.MAX_FRAME_SIZE]); HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload(); frame.Type = HTTP2FrameTypes.DATA; frame.StreamId = this.Id; frame.Payload = this.bodyToSend; frame.PayloadLength = (UInt32)Math.Min(maxFrameSize, this.bodyToSend.Length - this.bodyToSendOffset); frame.PayloadOffset = this.bodyToSendOffset; frame.DontUseMemPool = true; this.bodyToSendOffset += frame.PayloadLength; if (this.bodyToSendOffset >= this.bodyToSend.Length) { frame.Flags = (byte)(HTTP2DataFlags.END_STREAM); this.State = HTTP2StreamStates.HalfClosedLocal; } this.outgoing.Enqueue(frame); this.remoteWindow -= frame.PayloadLength; this.sentData += frame.PayloadLength; //HTTPManager.Logger.Information("HTTP2Stream", string.Format("[{0}] New DATA frame created! remoteWindow: {1:N0}", this.Id, this.remoteWindow)); break; case HTTP2StreamStates.HalfClosedLocal: break; case HTTP2StreamStates.HalfClosedRemote: break; case HTTP2StreamStates.Closed: break; } }
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; } }
private void ProcessState(List <HTTP2FrameHeaderAndPayload> outgoingFrames) { switch (this.State) { case HTTP2StreamStates.Idle: UInt32 initiatedInitialWindowSize = this.settings.InitiatedMySettings[HTTP2Settings.INITIAL_WINDOW_SIZE]; this.localWindow = initiatedInitialWindowSize; // window update with a zero increment would be an error (https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE) //if (HTTP2Connection.MaxValueFor31Bits > initiatedInitialWindowSize) // this.outgoing.Enqueue(HTTP2FrameHelper.CreateWindowUpdateFrame(this.Id, HTTP2Connection.MaxValueFor31Bits - initiatedInitialWindowSize)); //this.localWindow = HTTP2Connection.MaxValueFor31Bits; #if !BESTHTTP_DISABLE_CACHING // Setup cache control headers before we send out the request if (!this.AssignedRequest.DisableCache) { HTTPCacheService.SetHeaders(this.AssignedRequest); } #endif // hpack encode the request's headers this.encoder.Encode(this, this.AssignedRequest, this.outgoing, this.Id); // HTTP/2 uses DATA frames to carry message payloads. // The chunked transfer encoding defined in Section 4.1 of [RFC7230] MUST NOT be used in HTTP/2. this.uploadStreamInfo = this.AssignedRequest.GetUpStream(); //this.State = HTTP2StreamStates.Open; if (this.uploadStreamInfo.Stream == null) { this.State = HTTP2StreamStates.HalfClosedLocal; this.AssignedRequest.Timing.Add(TimingEventNames.Request_Sent); } else { this.State = HTTP2StreamStates.Open; this.lastReadCount = 1; } break; case HTTP2StreamStates.Open: // remote Window can be negative! See https://httpwg.org/specs/rfc7540.html#InitialWindowSize if (this.remoteWindow <= 0) { HTTPManager.Logger.Warning("HTTP2Stream", string.Format("[{0}] Skipping data sending as remote Window is {1}!", this.Id, this.remoteWindow), this.Context, this.AssignedRequest.Context, this.parent.Context); return; } // This step will send one frame per OpenState call. Int64 maxFrameSize = Math.Min(this.remoteWindow, this.settings.RemoteSettings[HTTP2Settings.MAX_FRAME_SIZE]); HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload(); frame.Type = HTTP2FrameTypes.DATA; frame.StreamId = this.Id; frame.Payload = BufferPool.Get(maxFrameSize, true); // Expect a readCount of zero if it's end of the stream. But, to enable non-blocking scenario to wait for data, going to treat a negative value as no data. this.lastReadCount = this.uploadStreamInfo.Stream.Read(frame.Payload, 0, (int)Math.Min(maxFrameSize, int.MaxValue)); if (this.lastReadCount <= 0) { BufferPool.Release(frame.Payload); frame.Payload = null; frame.PayloadLength = 0; if (this.lastReadCount < 0) { break; } } else { frame.PayloadLength = (UInt32)this.lastReadCount; } frame.PayloadOffset = 0; frame.DontUseMemPool = false; if (this.lastReadCount <= 0) { this.uploadStreamInfo.Stream.Dispose(); this.uploadStreamInfo = new HTTPRequest.UploadStreamInfo(); frame.Flags = (byte)(HTTP2DataFlags.END_STREAM); this.State = HTTP2StreamStates.HalfClosedLocal; this.AssignedRequest.Timing.Add(TimingEventNames.Request_Sent); } this.outgoing.Enqueue(frame); this.remoteWindow -= frame.PayloadLength; this.sentData += frame.PayloadLength; if (this.AssignedRequest.OnUploadProgress != null) { RequestEventHelper.EnqueueRequestEvent(new RequestEventInfo(this.AssignedRequest, RequestEvents.UploadProgress, this.sentData, this.uploadStreamInfo.Length)); } //HTTPManager.Logger.Information("HTTP2Stream", string.Format("[{0}] New DATA frame created! remoteWindow: {1:N0}", this.Id, this.remoteWindow), this.Context, this.AssignedRequest.Context, this.parent.Context); break; case HTTP2StreamStates.HalfClosedLocal: break; case HTTP2StreamStates.HalfClosedRemote: break; case HTTP2StreamStates.Closed: break; } }
private void Awake() { HTTPCacheService.SetupCacheFolder(); CookieJar.SetupFolder(); CookieJar.Load(); }
public static void HandleResponse(string context, HTTPRequest request, out bool resendRequest, out HTTPConnectionStates proposedConnectionState, ref KeepAliveHeader keepAlive, LoggingContext loggingContext1 = null, LoggingContext loggingContext2 = null, LoggingContext loggingContext3 = null) { 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); } #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), loggingContext1, loggingContext2, loggingContext3); } // 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), loggingContext1, loggingContext2, loggingContext3); 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; 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, loggingContext1, loggingContext2, loggingContext3)) { request.Timing.Add(TimingEventNames.Loading_From_Cache); HTTPManager.Logger.Verbose("HTTPConnection", string.Format("[{0}] - HandleResponse - Loaded from cache successfully!", context), loggingContext1, loggingContext2, loggingContext3); // Update any caching value HTTPCacheService.SetUpCachingValues(request.CurrentUri, request.Response); } else { HTTPManager.Logger.Verbose("HTTPConnection", string.Format("[{0}] - HandleResponse - Loaded from cache failed!", context), loggingContext1, loggingContext2, loggingContext3); resendRequest = true; } break; #endif default: #if !BESTHTTP_DISABLE_CACHING ConnectionHelper.TryStoreInCache(request); #endif break; } // Closing the stream is done manually? if (request.Response != null && !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); } } } // Null out the response here instead of the redirected cases (301, 302, 307, 308) // because response might have a Connection: Close header that we would miss to process. // If Connection: Close is present, the server is closing the connection and we would // reuse that closed connection. if (resendRequest) { // Discard the redirect response, we don't need it any more request.Response = null; if (proposedConnectionState == HTTPConnectionStates.Closed) { proposedConnectionState = HTTPConnectionStates.ClosedResendRequest; } } } }
private void TryStoreInCache() { if (((!base.CurrentRequest.UseStreaming && !base.CurrentRequest.DisableCache) && ((base.CurrentRequest.Response != null) && HTTPCacheService.IsSupported)) && HTTPCacheService.IsCacheble(base.CurrentRequest.CurrentUri, base.CurrentRequest.MethodType, base.CurrentRequest.Response)) { if (base.CurrentRequest.IsRedirected) { HTTPCacheService.Store(base.CurrentRequest.Uri, base.CurrentRequest.MethodType, base.CurrentRequest.Response); } else { HTTPCacheService.Store(base.CurrentRequest.CurrentUri, base.CurrentRequest.MethodType, base.CurrentRequest.Response); } } }
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 TryStoreInCache() { if (!CurrentRequest.UseStreaming && !CurrentRequest.DisableCache && CurrentRequest.Response != null && HTTPCacheService.IsCacheble(CurrentRequest.CurrentUri, CurrentRequest.MethodType, CurrentRequest.Response)) { HTTPCacheService.Store(CurrentRequest.CurrentUri, CurrentRequest.MethodType, CurrentRequest.Response); } }
// Token: 0x060025A8 RID: 9640 RVA: 0x000B99E4 File Offset: 0x000B7DE4 private void OnGUI() { GeneralStatistics stats = HTTPManager.GetGeneralStatistics(StatisticsQueryFlags.All); GUIHelper.DrawArea(new Rect(0f, 0f, (float)(Screen.width / 3), 160f), false, delegate { GUIHelper.DrawCenteredText("Connections"); GUILayout.Space(5f); GUIHelper.DrawRow("Sum:", stats.Connections.ToString()); GUIHelper.DrawRow("Active:", stats.ActiveConnections.ToString()); GUIHelper.DrawRow("Free:", stats.FreeConnections.ToString()); GUIHelper.DrawRow("Recycled:", stats.RecycledConnections.ToString()); GUIHelper.DrawRow("Requests in queue:", stats.RequestsInQueue.ToString()); }); GUIHelper.DrawArea(new Rect((float)(Screen.width / 3), 0f, (float)(Screen.width / 3), 160f), false, delegate { GUIHelper.DrawCenteredText("Cache"); if (!HTTPCacheService.IsSupported) { GUI.color = Color.yellow; GUIHelper.DrawCenteredText("Disabled in WebPlayer, WebGL & Samsung Smart TV Builds!"); GUI.color = Color.white; } else { GUILayout.Space(5f); GUIHelper.DrawRow("Cached entities:", stats.CacheEntityCount.ToString()); GUIHelper.DrawRow("Sum Size (bytes): ", stats.CacheSize.ToString("N0")); GUILayout.BeginVertical(new GUILayoutOption[0]); GUILayout.FlexibleSpace(); if (GUILayout.Button("Clear Cache", new GUILayoutOption[0])) { HTTPCacheService.BeginClear(); } GUILayout.EndVertical(); } }); GUIHelper.DrawArea(new Rect((float)(Screen.width / 3 * 2), 0f, (float)(Screen.width / 3), 160f), false, delegate { GUIHelper.DrawCenteredText("Cookies"); if (!CookieJar.IsSavingSupported) { GUI.color = Color.yellow; GUIHelper.DrawCenteredText("Saving and loading from disk is disabled in WebPlayer, WebGL & Samsung Smart TV Builds!"); GUI.color = Color.white; } else { GUILayout.Space(5f); GUIHelper.DrawRow("Cookies:", stats.CookieCount.ToString()); GUIHelper.DrawRow("Estimated size (bytes):", stats.CookieJarSize.ToString("N0")); GUILayout.BeginVertical(new GUILayoutOption[0]); GUILayout.FlexibleSpace(); if (GUILayout.Button("Clear Cookies", new GUILayoutOption[0])) { HTTPManager.OnQuit(); } GUILayout.EndVertical(); } }); if (SampleSelector.SelectedSample == null || (SampleSelector.SelectedSample != null && !SampleSelector.SelectedSample.IsRunning)) { GUIHelper.DrawArea(new Rect(0f, 165f, (float)((SampleSelector.SelectedSample != null) ? (Screen.width / 3) : Screen.width), (float)(Screen.height - 160 - 5)), false, delegate { this.scrollPos = GUILayout.BeginScrollView(this.scrollPos, new GUILayoutOption[0]); for (int i = 0; i < this.Samples.Count; i++) { this.DrawSample(this.Samples[i]); } GUILayout.EndScrollView(); }); if (SampleSelector.SelectedSample != null) { this.DrawSampleDetails(SampleSelector.SelectedSample); } } else if (SampleSelector.SelectedSample != null && SampleSelector.SelectedSample.IsRunning) { GUILayout.BeginArea(new Rect(0f, (float)(Screen.height - 50), (float)Screen.width, 50f), string.Empty); GUILayout.FlexibleSpace(); GUILayout.BeginHorizontal(new GUILayoutOption[0]); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(new GUILayoutOption[0]); GUILayout.FlexibleSpace(); if (GUILayout.Button("Back", new GUILayoutOption[] { GUILayout.MinWidth(100f) })) { SampleSelector.SelectedSample.DestroyUnityObject(); } GUILayout.FlexibleSpace(); GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.EndArea(); } }
private void Awake() { HTTPCacheService.SetupCacheFolder(); }
private void OnGUI() { GUIHelper.DrawArea(GUIHelper.ClientArea, true, delegate { GUILayout.BeginHorizontal(new GUILayoutOption[0]); GUILayout.Label("Delete cached entities older then", new GUILayoutOption[0]); GUILayout.Label(this.value.ToString(), new GUILayoutOption[] { GUILayout.MinWidth(50f) }); this.value = (int)GUILayout.HorizontalSlider((float)this.value, 1f, 60f, new GUILayoutOption[] { GUILayout.MinWidth(100f) }); GUILayout.Space(10f); this.deleteOlderType = (CacheMaintenanceSample.DeleteOlderTypes)GUILayout.SelectionGrid((int)this.deleteOlderType, new string[] { "Days", "Hours", "Mins", "Secs" }, 4, new GUILayoutOption[0]); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.Space(10f); GUILayout.BeginHorizontal(new GUILayoutOption[0]); GUILayout.Label("Max Cache Size (bytes): ", new GUILayoutOption[] { GUILayout.Width(150f) }); GUILayout.Label(this.maxCacheSize.ToString("N0"), new GUILayoutOption[] { GUILayout.Width(70f) }); this.maxCacheSize = (int)GUILayout.HorizontalSlider((float)this.maxCacheSize, 1024f, 1.048576E+07f, new GUILayoutOption[0]); GUILayout.EndHorizontal(); GUILayout.Space(10f); if (GUILayout.Button("Maintenance", new GUILayoutOption[0])) { TimeSpan deleteOlder = TimeSpan.FromDays(14.0); switch (this.deleteOlderType) { case CacheMaintenanceSample.DeleteOlderTypes.Days: deleteOlder = TimeSpan.FromDays((double)this.value); break; case CacheMaintenanceSample.DeleteOlderTypes.Hours: deleteOlder = TimeSpan.FromHours((double)this.value); break; case CacheMaintenanceSample.DeleteOlderTypes.Mins: deleteOlder = TimeSpan.FromMinutes((double)this.value); break; case CacheMaintenanceSample.DeleteOlderTypes.Secs: deleteOlder = TimeSpan.FromSeconds((double)this.value); break; } HTTPCacheService.BeginMaintainence(new HTTPCacheMaintananceParams(deleteOlder, (ulong)((long)this.maxCacheSize))); } }); }
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)); } } }
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(); } } }
// Token: 0x0600512E RID: 20782 RVA: 0x001BB51C File Offset: 0x001B991C private IEnumerator DownloadAndLoadRemotePluginCoroutine(AssetBundleDownload download) { if (Player.Instance != null && Player.Instance.isInternal) { Debug.Log(string.Concat(new object[] { "[", download.downloadId, "] Requires plugin. About to download ", download.pluginUrl })); } if (!PluginManager.IsAllowedUrl(download.pluginUrl)) { yield break; } HTTPRequest pluginReq = null; try { pluginReq = new HTTPRequest(new Uri(download.pluginUrl), null); } catch (Exception ex) { download.OnDownloadError("Bad plugin url: " + ex.Message, LoadErrorReason.InvalidURL); yield break; } if (download.forceRefreshCache) { HTTPCacheService.DeleteEntity(pluginReq.CurrentUri, true); } pluginReq.OnProgress = new OnDownloadProgressDelegate(download.OnDownloadProgress); pluginReq.Send(); yield return(base.StartCoroutine(pluginReq)); VRC.Network.ValidateCompletedHTTPRequest(pluginReq, delegate(HTTPResponse response) { if (!this.CheckForCancellation(download)) { VRC.Core.Logger.Log("[" + download.downloadId + "] Downloaded and loading plugin...", DebugLevel.AssetBundleDownloadManager); try { PluginManager.Instance.Load(download.pluginUrl, pluginReq.Response.Data); } catch (Exception ex2) { download.OnPluginLoadError(ex2.Message); } } }, delegate(string errorStr) { string text = "Failed to download plugin from " + download.pluginUrl + " - " + errorStr; VRC.Core.Logger.LogError(string.Concat(new object[] { "[", download.downloadId, "] ", text }), DebugLevel.AssetBundleDownloadManager); download.OnDownloadError(text, LoadErrorReason.ConnectionError); }); yield break; }
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)); } } }
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)); } } } }
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)); } } }
void OnGUI() { GUI.Label(new Rect(5, 5, Screen.width - 10, 30), string.Format("Cache size: {0,10:N0} Entity Count: {1}", HTTPCacheService.GetCacheSize(), HTTPCacheService.GetCacheEntityCount())); float height = (Screen.height - 300) / TestScenes.Length; if (GUI.Button(new Rect(5, 40, Screen.width, height), "Clear Cache")) { BestHTTP.Caching.HTTPCacheService.BeginClear(); } for (int i = 0; i < TestScenes.Length; ++i) { if (GUI.Button(new Rect(3, 300 + (i * height), Screen.width - 6, height), TestScenes[i])) { Application.LoadLevel(TestScenes[i]); } } }
public static void Setup() { HTTPUpdateDelegator.CheckInstance(); HTTPCacheService.CheckSetup(); Cookies.CookieJar.SetupFolder(); }
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(); } }
protected void BeginReceiveStreamFragments() { if (!baseRequest.DisableCache && baseRequest.UseStreaming && !IsFromCache && HTTPCacheService.IsCacheble(baseRequest.CurrentUri, baseRequest.MethodType, this)) { cacheStream = HTTPCacheService.PrepareStreamed(baseRequest.CurrentUri, this); } allFragmentSize = 0; }