Пример #1
0
            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;
                }
            }
Пример #2
0
        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);
                }
            }
        }