public ContentStream(HttpStream stream) : base() { this.inner = stream; this.positionStart = stream.CanSeek ? stream.Position : 0; this.position = 0; if (stream.contentLength != -1) { this.length = stream.contentLength; } else if (stream.CanSeek) { SeekLength(); } else { this.length = -1; } }
private void DoClient() { int count = 0; BpsLimiter.BpsShare bpsShare; if (bpsLimiter != null) { bpsShare = bpsLimiter.GetShare(); } else { bpsShare = null; } try { var buffer = new byte[BUFFER_LENGTH]; int read; Stream stream; HttpStream httpIn = new HttpStream(stream = clientIn.GetStream()); HttpStream httpOut = null; bool doSwap = false; Task <IPAddress> taskSwap = null; HttpStream.HttpHeader header; while (clientIn.Connected) { Cache.CacheStream cache = null; bool writeCache = false; if ((read = httpIn.ReadHeader(buffer, 0, out header)) == 0) { return; } var request = (HttpStream.HttpRequestHeader)header; if (RequestHeaderReceived != null) { RequestHeaderReceived(this, request); } try { #region Cached responses if (Cache.Enabled) { cache = Cache.GetCache(request.Location); if (cache != null) { if (cache.HasData) { do { read = httpIn.Read(buffer, 0, BUFFER_LENGTH); }while (read > 0); if (ResponseHeaderReceived != null) { ResponseHeaderReceived(this, HttpStream.HttpResponseHeader.Cached()); } while ((read = cache.Read(buffer, 0, BUFFER_LENGTH)) > 0) { httpIn.Write(buffer, 0, read); } continue; } writeCache = cache.CanWrite; } } #endregion #region Remote connection if (doSwap) { if (taskSwap.IsCompleted) { if (taskSwap.Result != null) { ipPool.AddSample(taskSwap.Result, double.MaxValue); } else if (clientSwap != null && clientSwap.Connected) { if (clientOut != null) { clientOut.Close(); } clientOut = clientSwap; clientSwap = null; remoteEP = (IPEndPoint)clientOut.Client.RemoteEndPoint; if (remoteEP.Port == 443) { httpOut.SetBaseStream(clientOut.GetStream(), true, ASSET_HOST, false); } else { httpOut.SetBaseStream(clientOut.GetStream(), true); } } doSwap = false; count = 0; taskSwap.Dispose(); } } if (clientOut == null || !clientOut.Connected) { clientOut = new TcpClient() { ReceiveTimeout = CONNECTION_TIMEOUT_SECONDS * 1000, SendTimeout = CONNECTION_TIMEOUT_SECONDS * 1000, ReceiveBufferSize = BUFFER_LENGTH * 2, }; try { if (!clientOut.ConnectAsync(remoteEP.Address, remoteEP.Port).Wait(CONNECTION_TIMEOUT_SECONDS * 1000)) { throw new TimeoutException("Unable to connect to " + remoteEP.ToString()); } } catch { if (doIPPool) { ipPool.AddSample(remoteEP.Address, double.MaxValue); } throw; } if (remoteEP.Port == 443) { httpOut = new HttpStream(clientOut.GetStream(), ASSET_HOST, false); } else { httpOut = new HttpStream(clientOut.GetStream()); } } #endregion if (read > 0 && RequestDataReceived != null) { RequestDataReceived(this, new ArraySegment <byte>(buffer, 0, read)); } clientOut.ReceiveTimeout = clientOut.SendTimeout = CONNECTION_TIMEOUT_SECONDS * 1000; do { httpOut.Write(buffer, 0, read); read = httpIn.Read(buffer, 0, BUFFER_LENGTH); if (read > 0 && RequestDataReceived != null) { RequestDataReceived(this, new ArraySegment <byte>(buffer, 0, read)); } }while (read > 0); if ((read = httpOut.ReadHeader(buffer, 0, out header)) == 0) { return; } if (ResponseHeaderReceived != null) { ResponseHeaderReceived(this, (HttpStream.HttpResponseHeader)header); } if (read > 0 && ResponseDataReceived != null) { ResponseDataReceived(this, new ArraySegment <byte>(buffer, 0, read)); } clientOut.ReceiveTimeout = clientOut.SendTimeout = CONNECTION_TRANSFER_TIMEOUT_SECONDS * 1000; DateTime startTime = DateTime.UtcNow; long bytes = 0; try { do { if (writeCache) { cache.Write(buffer, 0, read); } httpIn.Write(buffer, 0, read); if (bpsShare != null) { read = httpOut.Read(buffer, 0, bpsShare.GetLimit(BUFFER_LENGTH)); bpsShare.Used(read); } else { read = httpOut.Read(buffer, 0, BUFFER_LENGTH); } bytes += read; if (read > 0 && ResponseDataReceived != null) { ResponseDataReceived(this, new ArraySegment <byte>(buffer, 0, read)); } }while (read > 0); } catch { if (doIPPool) { ipPool.AddSample(remoteEP.Address, double.MaxValue); } throw; } var response = (HttpStream.HttpResponseHeader)header; if (writeCache && response.StatusCode == HttpStatusCode.OK) { cache.Commit(); } if (doIPPool) { double ms = DateTime.UtcNow.Subtract(startTime).TotalMilliseconds; if (ms > 0) { if (response.StatusCode == HttpStatusCode.OK) { ipPool.AddSample(remoteEP.Address, bytes / ms); } else { ipPool.AddSample(remoteEP.Address, bytes / ms * 2); } } if (++count == 10) { var ip = ipPool.GetIP(); if (ip == remoteEP.Address) { count = 0; } else { doSwap = true; taskSwap = new Task <IPAddress>( delegate { var clientSwap = this.clientSwap = new TcpClient() { ReceiveTimeout = CONNECTION_TIMEOUT_SECONDS * 1000, SendTimeout = CONNECTION_TIMEOUT_SECONDS * 1000, ReceiveBufferSize = BUFFER_LENGTH * 2, }; try { if (!clientSwap.ConnectAsync(ip, Settings.PatchingUseHttps.Value ? 443 : 80).Wait(CONNECTION_TIMEOUT_SECONDS * 1000)) { throw new TimeoutException(); } return(null); } catch (Exception e) { Util.Logging.Log(e); clientSwap.Close(); return(ip); } }); taskSwap.Start(); } } } } finally { if (cache != null) { cache.Dispose(); } } var keepAlive = ((HttpStream.HttpResponseHeader)header).KeepAlive; if (keepAlive.keepAlive) { if (keepAlive.timeout > 0) { clientIn.Client.ReceiveTimeout = keepAlive.timeout * 1000; clientOut.Client.ReceiveTimeout = keepAlive.timeout * 1000; } } else { return; } } } catch (Exception e) { Util.Logging.Log(e); if (Error != null) { Error(this, e); } } finally { if (bpsShare != null) { bpsShare.Dispose(); } if (clientIn != null) { clientIn.Close(); } if (clientOut != null) { clientOut.Close(); } if (clientSwap != null) { clientSwap.Close(); } if (Closed != null) { Closed(this, EventArgs.Empty); } } }