Esempio n. 1
0
        public override void Connect(EndPoint remoteEndPoint)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint))
            {
                throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint");
            }

            try
            {
#if SILVERLIGHT && !WINDOWS_PHONE
                ProxyEndPoint.ConnectAsync(ClientAccessPolicyProtocol, ProcessConnect, remoteEndPoint);
#elif WINDOWS_PHONE
                ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint);
#else
                ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint);
#endif
            }
            catch (Exception e)
            {
                OnException(new Exception("Failed to connect proxy server", e));
            }
        }
 /// <summary>
 ///     Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
 /// </summary>
 private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                              CancellationTokenSource cancellationTokenSource)
 {
     bufferSize    = server.BufferSize;
     bufferPool    = server.BufferPool;
     exceptionFunc = server.ExceptionFunc;
 }
        public override void Connect(EndPoint remoteEndPoint)
        {
            DnsEndPoint targetEndPoint = remoteEndPoint as DnsEndPoint;

            if (targetEndPoint == null)
            {
                OnCompleted(new ProxyEventArgs(new Exception("The argument 'remoteEndPoint' must be a DnsEndPoint")));
                return;
            }

            try
            {
#if SILVERLIGHT && !WINDOWS_PHONE
                ProxyEndPoint.ConnectAsync(ClientAccessPolicyProtocol, ProcessConnect, targetEndPoint);
#elif WINDOWS_PHONE
                ProxyEndPoint.ConnectAsync(ProcessConnect, remoteEndPoint);
#else
                ProxyEndPoint.ConnectAsync(null, ProcessConnect, targetEndPoint);
#endif
            }
            catch (Exception e)
            {
                OnException(new Exception("Failed to connect proxy server", e));
            }
        }
        public TestProxyServer(bool isReverseProxy, ProxyServer upStreamProxy = null)
        {
            ProxyServer = new ProxyServer();
            ProxyEndPoint explicitEndPoint = isReverseProxy ?
                                             (ProxyEndPoint) new TransparentProxyEndPoint(IPAddress.Any, 0, true) :
                                             new ExplicitProxyEndPoint(IPAddress.Any, 0, true);

            ProxyServer.AddEndPoint(explicitEndPoint);

            if (upStreamProxy != null)
            {
                ProxyServer.UpStreamHttpProxy = new ExternalProxy()
                {
                    HostName = "localhost",
                    Port     = upStreamProxy.ProxyEndPoints[0].Port
                };

                ProxyServer.UpStreamHttpsProxy = new ExternalProxy()
                {
                    HostName = "localhost",
                    Port     = upStreamProxy.ProxyEndPoints[0].Port
                };
            }

            ProxyServer.Start();
        }
        protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                                       CancellationTokenSource cancellationTokenSource,
                                       Request request) : this(server, endPoint, cancellationTokenSource)
        {
            CancellationTokenSource = cancellationTokenSource;

            ProxyClient   = new ProxyClient();
            WebSession    = new HttpWebClient(request);
            LocalEndPoint = endPoint;

            WebSession.ProcessId = new Lazy <int>(() =>
            {
                if (RunTime.IsWindows)
                {
                    var remoteEndPoint = ClientEndPoint;

                    // If client is localhost get the process id
                    if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
                    {
                        var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4;
                        return(TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port));
                    }

                    // can't access process Id of remote request from remote machine
                    return(-1);
                }

                throw new PlatformNotSupportedException();
            });
        }
Esempio n. 6
0
        public int GetProcessId(ProxyEndPoint endPoint)
        {
            if (processId.HasValue)
            {
                return(processId.Value);
            }

            if (RunTime.IsWindows)
            {
                var remoteEndPoint = (IPEndPoint)RemoteEndPoint;

                // If client is localhost get the process id
                if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
                {
                    processId = TcpHelper.GetProcessIdByLocalPort(endPoint.IpAddress.AddressFamily, remoteEndPoint.Port);
                }
                else
                {
                    // can't access process Id of remote request from remote machine
                    processId = -1;
                }

                return(processId.Value);
            }

            throw new PlatformNotSupportedException();
        }
            protected override async Task handleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
            {
                tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
                tcpClient.SendTimeout    = ConnectionTimeOutSeconds * 1000;

                tcpClient.LingerState = new LingerOption(true, TcpTimeWaitSeconds);


                using (var requestState = new TRequestState())
                {
                    await InvokeClientConnectionCreateEvent(tcpClient);

                    var clientConnection = new TcpClientConnection(this, tcpClient);
                    requestState.server           = this;
                    requestState.clientConnection = clientConnection;

                    if (endPoint is TransparentProxyEndPoint tep)
                    {
                        await handleClient(tep, requestState);
                    }
                    else
                    {
                        await handleClient((ExplicitProxyEndPoint)endPoint, requestState);
                    }
                }
            }
Esempio n. 8
0
        /// <summary>
        /// Constructor to initialize the proxy
        /// </summary>
        internal SessionEventArgs(int bufferSize,
                                  ProxyEndPoint endPoint,
                                  Func <SessionEventArgs, Task> httpResponseHandler)
        {
            this.bufferSize          = bufferSize;
            this.httpResponseHandler = httpResponseHandler;

            ProxyClient   = new ProxyClient();
            WebSession    = new HttpWebClient(bufferSize);
            LocalEndPoint = endPoint;

            WebSession.ProcessId = new Lazy <int>(() =>
            {
                if (RunTime.IsWindows)
                {
                    var remoteEndPoint = (IPEndPoint)ProxyClient.TcpClient.Client.RemoteEndPoint;

                    //If client is localhost get the process id
                    if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
                    {
                        return(NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled));
                    }

                    //can't access process Id of remote request from remote machine
                    return(-1);
                }

                throw new PlatformNotSupportedException();
            });
        }
 /// <summary>
 ///     Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
 /// </summary>
 private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                              CancellationTokenSource cancellationTokenSource)
 {
     BufferSize    = server.BufferSize;
     BufferPool    = server.BufferPool;
     ExceptionFunc = server.ExceptionFunc;
     TimeLine["Session Created"] = DateTime.Now;
 }
 /// <summary>
 ///   Asynchronously close this connection
 /// </summary>
 /// <returns> A task representating the closing process </returns>
 public async Task CloseAsync()
 {
     await KickUserAsync("Proxy connection shutdown");
     if (_serverEndPoint != null)
     {
         _serverEndPoint.Close ();
         _serverEndPoint = null;
     }
 }
Esempio n. 11
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
 /// </summary>
 private SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                              CancellationTokenSource cancellationTokenSource)
 {
     BufferSize    = server.BufferSize;
     BufferPool    = server.BufferPool;
     ExceptionFunc = server.ExceptionFunc;
     TimeLine["Session Created"] = DateTime.Now;
     Challenge = Guid.NewGuid().ToString("N");
 }
Esempio n. 12
0
        /// <summary>
        /// Listen on the given end point on local machine
        /// </summary>
        /// <param name="endPoint"></param>
        private void Listen(ProxyEndPoint endPoint)
        {
            endPoint.listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
            endPoint.listener.Start();

            endPoint.Port = ((IPEndPoint)endPoint.listener.LocalEndpoint).Port;
            // accept clients asynchronously
            endPoint.listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
        }
Esempio n. 13
0
        public static void AddEndPoint(ProxyEndPoint endPoint)
        {
            ProxyEndPoints.Add(endPoint);

            if (proxyRunning)
            {
                Listen(endPoint);
            }
        }
        protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                                       CancellationTokenSource cancellationTokenSource,
                                       Request request) : this(server)
        {
            CancellationTokenSource = cancellationTokenSource;

            ProxyClient   = new ProxyClient();
            HttpClient    = new HttpWebClient(request);
            LocalEndPoint = endPoint;

            HttpClient.ProcessId = new Lazy <int>(() => ProxyClient.Connection.GetProcessId(endPoint));
        }
Esempio n. 15
0
        protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                                       CancellationTokenSource cancellationTokenSource,
                                       Request?request) : this(server)
        {
            CancellationTokenSource = cancellationTokenSource;

            ProxyClient   = new ProxyClient();
            HttpClient    = new HttpWebClient(request);
            LocalEndPoint = endPoint;
            EnableWinAuth = server.EnableWinAuth && isWindowsAuthenticationSupported;

            HttpClient.ProcessId = new Lazy <int>(() => ProxyClient.Connection.GetProcessId(endPoint));
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
        /// </summary>
        private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                                               HttpClientStream clientStream, ConnectRequest?connectRequest, Request request, CancellationTokenSource cancellationTokenSource) : base(clientStream.Connection)
        {
            BufferPool    = server.BufferPool;
            ExceptionFunc = server.ExceptionFunc;
            TimeLine["Session Created"] = DateTime.Now;

            CancellationTokenSource = cancellationTokenSource;

            ClientStream  = clientStream;
            HttpClient    = new HttpWebClient(connectRequest, request, new Lazy <int>(() => clientStream.Connection.GetProcessId(endPoint)));
            LocalEndPoint = endPoint;
        }
Esempio n. 17
0
        /// <summary>
        /// Add a proxy end point
        /// </summary>
        /// <param name="endPoint"></param>
        public void AddEndPoint(ProxyEndPoint endPoint)
        {
            if (ProxyEndPoints.Any(x => x.IpAddress.Equals(endPoint.IpAddress) && endPoint.Port != 0 && x.Port == endPoint.Port))
            {
                throw new Exception("Cannot add another endpoint to same port & ip address");
            }

            ProxyEndPoints.Add(endPoint);

            if (proxyRunning)
            {
                Listen(endPoint);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Remove a proxy end point
        /// Will throw error if the end point does'nt exist
        /// </summary>
        /// <param name="endPoint"></param>
        public void RemoveEndPoint(ProxyEndPoint endPoint)
        {
            if (ProxyEndPoints.Contains(endPoint) == false)
            {
                throw new Exception("Cannot remove endPoints not added to proxy");
            }

            ProxyEndPoints.Remove(endPoint);

            if (proxyRunning)
            {
                QuitListen(endPoint);
            }
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="SessionEventArgsBase" /> class.
        /// </summary>
        private protected SessionEventArgsBase(ProxyServer server, ProxyEndPoint endPoint,
                                               TcpClientConnection clientConnection, HttpClientStream clientStream, ConnectRequest?connectRequest, Request request, CancellationTokenSource cancellationTokenSource)
        {
            BufferPool    = server.BufferPool;
            ExceptionFunc = server.ExceptionFunc;
            TimeLine["Session Created"] = DateTime.Now;

            CancellationTokenSource = cancellationTokenSource;

            ClientConnection = clientConnection;
            ClientStream     = clientStream;
            HttpClient       = new HttpWebClient(connectRequest, request, new Lazy <int>(() => clientConnection.GetProcessId(endPoint)));
            LocalEndPoint    = endPoint;
            EnableWinAuth    = server.EnableWinAuth && isWindowsAuthenticationSupported;
        }
Esempio n. 20
0
        /// <summary>
        /// 构造函数
        /// </summary>
        private Proxy()
        {
            _proxyServer = new ProxyServer(false, false, false)
            {
                TcpTimeWaitSeconds       = 10,
                ConnectionTimeOutSeconds = 15,
                ReuseSocket              = false,
                EnableConnectionPool     = false,
                ForwardToUpstreamGateway = false
            };
            // 阻止生成pfx文件
            _proxyServer.CertificateManager.SaveFakeCertificates = false;
            _proxyServer.CertificateManager.RootCertificate      = new X509Certificate2();
            _proxyServer.BeforeResponse += BeforeResponse;
            _proxyServer.BeforeRequest  += BeforeRequest;
            _endPoint = new ExplicitProxyEndPoint(IPAddress.Any, 18888, false);
            _proxyServer.AddEndPoint(_endPoint);
            _signTimer = new Timer(Defines.SignExpireTime)
            {
                AutoReset = true, Enabled = true, Interval = Defines.SignExpireTime
            };
            _signTimer.Elapsed += _signTimerElapsed;
            _ruleJObject        =
                (JObject)JsonConvert.DeserializeObject(System.Text.Encoding.UTF8.GetString(Resource.DataProcess));
            _urlList = new List <string>();
            if (_ruleJObject != null)
            {
                foreach (var it in _ruleJObject)
                {
                    _urlList.Add(it.Key);
                }
            }

            _specialUrlDict = new Dictionary <string, ProcessDelegate>
            {
                { "Index/index", GetIndex },
                { "Fairy/teamFairy", TeamFairy },
                { "Mission/teamMove", TeamMove },
                { "Mission/startMission", StartMission }
            };

            using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
            {
                socket.Connect(Defines.NetTestIP, 65530);
                LocalIPAddress = socket.LocalEndPoint is IPEndPoint endPoint?endPoint.Address.ToString() : "";
            }
        }
Esempio n. 21
0
        private async void Listen(ProxyEndPoint endPoint)
        {
            endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
            endPoint.Listener.Start();

            endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;

            while (true)
            {
                TcpClient tcpClient = await endPoint.Listener.AcceptTcpClientAsync();

                if (tcpClient != null)
                {
                    Task.Run(async() => HandleClient(tcpClient, endPoint));
                }
            }
        }
Esempio n. 22
0
        public override void Connect(EndPoint remoteEndPoint)
        {
            IPEndPoint targetEndPoint = remoteEndPoint as IPEndPoint;

            if (targetEndPoint == null)
            {
                OnCompleted(new ProxyEventArgs(new Exception("The argument 'remoteEndPoint' must be a IPEndPoint")));
                return;
            }

            try
            {
                ProxyEndPoint.ConnectAsync(null, ProcessConnect, targetEndPoint);
            }
            catch (Exception e)
            {
                OnException(new Exception("Failed to connect proxy server", e));
            }
        }
Esempio n. 23
0
        /// <summary>
        /// Listen on the given end point on local machine
        /// </summary>
        /// <param name="endPoint"></param>
        private void Listen(ProxyEndPoint endPoint)
        {
            endPoint.Listener = new TcpListener(endPoint.IpAddress, endPoint.Port);
            try
            {
                endPoint.Listener.Start();

                endPoint.Port = ((IPEndPoint)endPoint.Listener.LocalEndpoint).Port;

                // accept clients asynchronously
                endPoint.Listener.BeginAcceptTcpClient(OnAcceptConnection, endPoint);
            }
            catch (SocketException ex)
            {
                var pex = new Exception($"Endpoint {endPoint} failed to start. Check inner exception and exception data for details.", ex);
                pex.Data.Add("ipAddress", endPoint.IpAddress);
                pex.Data.Add("port", endPoint.Port);
                throw pex;
            }
        }
Esempio n. 24
0
        public override void Connect(EndPoint remoteEndPoint)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint))
            {
                throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint");
            }

            try
            {
                ProxyEndPoint.ConnectAsync(this.ProcessConnect, remoteEndPoint);
            }
            catch (Exception e)
            {
                this.OnException(new Exception("Failed to connect proxy server", e));
            }
        }
Esempio n. 25
0
        private async Task HandleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
        {
            UpdateClientConnectionCount(true);

            tcpClient.ReceiveTimeout = ConnectionTimeOutSeconds * 1000;
            tcpClient.SendTimeout    = ConnectionTimeOutSeconds * 1000;

            try
            {
                if (endPoint.GetType() == typeof(TransparentProxyEndPoint))
                {
                    await HandleClient(endPoint as TransparentProxyEndPoint, tcpClient);
                }
                else
                {
                    await HandleClient(endPoint as ExplicitProxyEndPoint, tcpClient);
                }
            }
            finally
            {
                UpdateClientConnectionCount(false);

                try
                {
                    if (tcpClient != null)
                    {
                        //This line is important!
                        //contributors please don't remove it without discussion
                        //It helps to avoid eventual deterioration of performance due to TCP port exhaustion
                        //due to default TCP CLOSE_WAIT timeout for 4 minutes
                        tcpClient.LingerState = new LingerOption(true, 0);
                        tcpClient.Dispose();
                    }
                }
                catch
                {
                }
            }
        }
Esempio n. 26
0
        /// <summary>
        ///     Handle the client.
        /// </summary>
        /// <param name="tcpClient">The client.</param>
        /// <param name="endPoint">The proxy endpoint.</param>
        /// <returns>The task.</returns>
        private async Task handleClient(TcpClient tcpClient, ProxyEndPoint endPoint)
        {
            tcpClient.ReceiveTimeout    = ConnectionTimeOutSeconds * 1000;
            tcpClient.SendTimeout       = ConnectionTimeOutSeconds * 1000;
            tcpClient.SendBufferSize    = BufferSize;
            tcpClient.ReceiveBufferSize = BufferSize;

            await InvokeConnectionCreateEvent(tcpClient, true);

            using (var clientConnection = new TcpClientConnection(this, tcpClient))
            {
                if (endPoint is TransparentProxyEndPoint)
                {
                    TransparentProxyEndPoint tep = endPoint as TransparentProxyEndPoint;
                    await handleClient(tep, clientConnection);
                }
                else
                {
                    await handleClient((ExplicitProxyEndPoint)endPoint, clientConnection);
                }
            }
        }
        public override void Connect(EndPoint remoteEndPoint)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint))
            {
                throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint");
            }

            //check if our hostname matches an ip address or not
            Match isProxyIpAddress = Regex.Match(ProxyHostName, @"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}");

            Debug.WriteLine("[PROXY] Connecting to proxy: " + ProxyHostName);

            if (isProxyIpAddress.Success)
            {
                Debug.WriteLine("[PROXY] endpoint is IP endpoint");
            }
            else
            {
                Debug.WriteLine("[PROXY] endpoint is a hostname/DNS endpoint");
                isProxyHostname = true;
            }

            try
            {
                //save reference to remote endpoint if we need to do back-and-forth connecting
                lastEndpoint = remoteEndPoint;
                ProxyEndPoint.ConnectAsync(null, ProcessConnect, remoteEndPoint);
            }
            catch (Exception e)
            {
                OnException(new Exception("[PROXY] Failed to connect proxy server", e));
            }
        }
        public override void Connect(EndPoint remoteEndPoint)
        {
            if (remoteEndPoint == null)
            {
                throw new ArgumentNullException("remoteEndPoint");
            }

            if (!(remoteEndPoint is IPEndPoint || remoteEndPoint is DnsEndPoint))
            {
                throw new ArgumentException("remoteEndPoint must be IPEndPoint or DnsEndPoint", "remoteEndPoint");
            }

            try
            {
                //save reference to remote endpoint if we need to do back-and-forth connecting
                lastEndpoint = remoteEndPoint;
                ProxyEndPoint.ConnectAsync(null, ProcessConnect, remoteEndPoint);
            }
            catch (Exception e)
            {
                OnException(new Exception("Failed to connect proxy server", e));
            }
        }
Esempio n. 29
0
 /// <summary>
 /// Constructor to initialize the proxy
 /// </summary>
 internal SessionEventArgs(RequestStateBase state, ProxyEndPoint endPoint, HttpClientStream clientStream, ConnectRequest?connectRequest, CancellationTokenSource cancellationTokenSource)
     : base(state, endPoint, clientStream, connectRequest, new Request(), cancellationTokenSource)
 {
 }
Esempio n. 30
0
 /// <summary>
 /// Quit listening on the given end point
 /// </summary>
 /// <param name="endPoint"></param>
 private void QuitListen(ProxyEndPoint endPoint)
 {
     endPoint.listener.Stop();
     endPoint.listener.Server.Close();
     endPoint.listener.Server.Dispose();
 }
Esempio n. 31
0
 public ProxyHttpServer(Int32 httpPort)
 {
     _httpStack = new HttpStack(httpPort);
     _httpStack.RequestHandler = HandleRequest;
     _proxyEndPoint = new ProxyEndPoint(this);
 }
Esempio n. 32
0
        /// <summary>
        /// This is the core request handler method for a particular connection from client
        /// </summary>
        /// <param name="client"></param>
        /// <param name="httpCmd"></param>
        /// <param name="clientStream"></param>
        /// <param name="clientStreamReader"></param>
        /// <param name="clientStreamWriter"></param>
        /// <param name="httpsHostName"></param>
        /// <returns></returns>
        private async Task HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream,
                                                    CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string httpsHostName, ProxyEndPoint endPoint, List <HttpHeader> connectHeaders, ExternalProxy customUpStreamHttpProxy = null, ExternalProxy customUpStreamHttpsProxy = null)
        {
            TcpConnection connection = null;

            //Loop through each subsequest request on this particular client connection
            //(assuming HTTP connection is kept alive by client)
            while (true)
            {
                if (string.IsNullOrEmpty(httpCmd))
                {
                    Dispose(clientStream, clientStreamReader, clientStreamWriter, null);
                    break;
                }

                var args = new SessionEventArgs(BUFFER_SIZE, HandleHttpSessionResponse);
                args.ProxyClient.TcpClient     = client;
                args.WebSession.ConnectHeaders = connectHeaders;

                args.WebSession.ProcessId = new Lazy <int>(() =>
                {
                    var remoteEndPoint = (IPEndPoint)args.ProxyClient.TcpClient.Client.RemoteEndPoint;

                    //If client is localhost get the process id
                    if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
                    {
                        return(NetworkHelper.GetProcessIdFromPort(remoteEndPoint.Port, endPoint.IpV6Enabled));
                    }

                    //can't access process Id of remote request from remote machine
                    return(-1);
                });
                try
                {
                    //break up the line into three components (method, remote URL & Http Version)
                    var httpCmdSplit = httpCmd.Split(ProxyConstants.SpaceSplit, 3);

                    var httpMethod = httpCmdSplit[0];

                    //find the request HTTP version
                    Version httpVersion = new Version(1, 1);
                    if (httpCmdSplit.Length == 3)
                    {
                        var httpVersionString = httpCmdSplit[2].ToLower().Trim();

                        if (httpVersionString == "http/1.0")
                        {
                            httpVersion = new Version(1, 0);
                        }
                    }


                    //Read the request headers in to unique and non-unique header collections
                    string tmpLine;
                    while (!string.IsNullOrEmpty(tmpLine = await clientStreamReader.ReadLineAsync()))
                    {
                        var header = tmpLine.Split(ProxyConstants.ColonSplit, 2);

                        var newHeader = new HttpHeader(header[0], header[1]);

                        //if header exist in non-unique header collection add it there
                        if (args.WebSession.Request.NonUniqueRequestHeaders.ContainsKey(newHeader.Name))
                        {
                            args.WebSession.Request.NonUniqueRequestHeaders[newHeader.Name].Add(newHeader);
                        }
                        //if header is alread in unique header collection then move both to non-unique collection
                        else if (args.WebSession.Request.RequestHeaders.ContainsKey(newHeader.Name))
                        {
                            var existing = args.WebSession.Request.RequestHeaders[newHeader.Name];

                            var nonUniqueHeaders = new List <HttpHeader>();

                            nonUniqueHeaders.Add(existing);
                            nonUniqueHeaders.Add(newHeader);

                            args.WebSession.Request.NonUniqueRequestHeaders.Add(newHeader.Name, nonUniqueHeaders);
                            args.WebSession.Request.RequestHeaders.Remove(newHeader.Name);
                        }
                        //add to unique header collection
                        else
                        {
                            args.WebSession.Request.RequestHeaders.Add(newHeader.Name, newHeader);
                        }
                    }

                    var httpRemoteUri = new Uri(httpsHostName == null ? httpCmdSplit[1]
                        : (string.Concat("https://", args.WebSession.Request.Host == null ?
                                         httpsHostName : args.WebSession.Request.Host, httpCmdSplit[1])));

                    args.WebSession.Request.RequestUri = httpRemoteUri;

                    args.WebSession.Request.Method      = httpMethod.Trim().ToUpper();
                    args.WebSession.Request.HttpVersion = httpVersion;
                    args.ProxyClient.ClientStream       = clientStream;
                    args.ProxyClient.ClientStreamReader = clientStreamReader;
                    args.ProxyClient.ClientStreamWriter = clientStreamWriter;

                    if (httpsHostName == null && (await CheckAuthorization(clientStreamWriter, args.WebSession.Request.RequestHeaders.Values) == false))
                    {
                        Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
                        break;
                    }

                    PrepareRequestHeaders(args.WebSession.Request.RequestHeaders, args.WebSession);
                    args.WebSession.Request.Host = args.WebSession.Request.RequestUri.Authority;

                    //If user requested interception do it
                    if (BeforeRequest != null)
                    {
                        Delegate[] invocationList = BeforeRequest.GetInvocationList();
                        Task[]     handlerTasks   = new Task[invocationList.Length];

                        for (int i = 0; i < invocationList.Length; i++)
                        {
                            handlerTasks[i] = ((Func <object, SessionEventArgs, Task>)invocationList[i])(null, args);
                        }

                        await Task.WhenAll(handlerTasks);
                    }

                    //if upgrading to websocket then relay the requet without reading the contents
                    if (args.WebSession.Request.UpgradeToWebSocket)
                    {
                        await TcpHelper.SendRaw(BUFFER_SIZE, ConnectionTimeOutSeconds, httpRemoteUri.Host, httpRemoteUri.Port,
                                                httpCmd, httpVersion, args.WebSession.Request.RequestHeaders, args.IsHttps,
                                                SupportedSslProtocols, new RemoteCertificateValidationCallback(ValidateServerCertificate),
                                                new LocalCertificateSelectionCallback(SelectClientCertificate),
                                                clientStream, tcpConnectionFactory, UpStreamEndPoint);

                        Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
                        break;
                    }

                    //construct the web request that we are going to issue on behalf of the client.
                    await HandleHttpSessionRequestInternal(connection, args, customUpStreamHttpProxy, customUpStreamHttpsProxy, false).ConfigureAwait(false);


                    if (args.WebSession.Request.CancelRequest)
                    {
                        break;
                    }

                    //if connection is closing exit
                    if (args.WebSession.Response.ResponseKeepAlive == false)
                    {
                        break;
                    }

                    // read the next request
                    httpCmd = await clientStreamReader.ReadLineAsync();
                }
                catch (Exception e)
                {
                    ExceptionFunc(new ProxyHttpException("Error occured whilst handling session request", e, args));
                    Dispose(clientStream, clientStreamReader, clientStreamWriter, args);
                    break;
                }
            }

            if (connection != null)
            {
                //dispose
                connection.Dispose();
            }
        }
        internal virtual async void HandleClient()
        {
            string kickMessage = "Failed to login";
            bool success = true;
            try
            {
                ClientRemoteInterface clientRemoteInterface =
                    ClientRemoteInterface.Create(new NetworkStream(_networkSocket), 60);
                _clientEndPoint = new ProxyEndPoint(clientRemoteInterface, clientRemoteInterface.EndPoint.Version);
                _clientEndPoint.RemoteEndPoint = (IPEndPoint) _networkSocket.RemoteEndPoint;

                Packet packet = await clientRemoteInterface.ReadPacketAsync ();

                var listPing = packet as PlayerListPing;
                var handshakeRequest = packet as HandshakeRequest;


                if (listPing != null) // send motd
                {
                    _isMotDRequest = true;

                    if (listPing.MagicByte == 1)
                    {
                        //Plugin Message begins @ 1.6

                        AdditionalServerListInformation additionalInformation = null;

                        try
                        {
                            clientRemoteInterface.EndPoint.Stream.ReadTimeout = 1;
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        try
                        {
                            additionalInformation =
                                await clientRemoteInterface.ReadAdditionalServerListInformationAsync();
                        }
                        catch (TimeoutException timeOut)
                        {
                        }

                        additionalInformation = additionalInformation ?? new AdditionalServerListInformation
                        {
                            Host = _server.LocalEndPoint.Address.ToString(),
                            Port = _server.LocalEndPoint.Port,
                            ProtocolVersion = (byte) _server.PublicMinecraftVersion
                        };
                        additionalInformation.ProtocolVersion = ProtocolInformation.MaxSupportedClientVersion <
                                                                additionalInformation.ProtocolVersion
                            ? (byte) ProtocolInformation.MaxSupportedClientVersion
                            : additionalInformation.ProtocolVersion;
                        additionalInformation.ProtocolVersion = ProtocolInformation.MinSupportedClientVersion >
                                                                additionalInformation.ProtocolVersion
                            ? (byte) ProtocolInformation.MinSupportedClientVersion
                            : additionalInformation.ProtocolVersion;

                        string response = ProtocolHelper.BuildMotDString(additionalInformation.ProtocolVersion,
                            _server.ServerVersionName, _server.MotD,
                            _server.ConnectedUsers, _server.MaxUsers);
                        await KickUserAsync(response);
                    }
                    else
                    {
                        string response = ProtocolHelper.BuildMotDString(_server.MotD, _server.ConnectedUsers,
                            _server.MaxUsers);
                        await KickUserAsync(response);
                    }
                    return;
                }

                if (handshakeRequest != null)
                {
                    Username = handshakeRequest.UserName;
                    Host = handshakeRequest.Host;
                    ClientEndPoint.ProtocolVersion = handshakeRequest.ProtocolVersion;

                    if (handshakeRequest.ProtocolVersion < ProtocolInformation.MinSupportedClientVersion)
                    {
                        await KickUserAsync("Outdated Client");
                        return;
                    }
                    else if (handshakeRequest.ProtocolVersion > ProtocolInformation.MaxSupportedClientVersion)
                    {
                        await KickUserAsync("Outdated Server");
                        return;
                    }

                    var args = new UserEventArgs(this);

                    _server.PluginManager.TriggerPlugin.OnPlayerConnected(args);

                    if (args.Canceled)
                    {
                        await ClientEndPoint.SendPacketAsync(new DisconnectPacket {Reason = args.CancelMessage});
                        _networkSocket.Close ();
                        _server.RemoveConnection(this);
                        return;
                    }

                    bool onlineMode = _server.OnlineModeEnabled(this);
                    string serverId = onlineMode ? Session.GetSessionHash () : "-";

                    var randomBuffer = new byte[4];
                    _random.NextBytes(randomBuffer);
                    await ClientEndPoint.SendPacketAsync(new EncryptionKeyRequest
                                                             {
                                                                 ServerId = serverId,
                                                                 PublicKey =
                                                                     AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair).
                                                                     GetBytes (),
                                                                 VerifyToken = randomBuffer
                                                             });
                    do
                    {
                        packet = await ClientEndPoint.ReceivePacketAsync ();
                    } while (packet is KeepAlive);

                    var encryptionKeyResponse = (EncryptionKeyResponse) packet;
                    byte[] verification = ProtocolSecurity.RsaDecrypt(
                        encryptionKeyResponse.VerifyToken.ToArray (), _server.RSACryptoServiceProvider, true);
                    byte[] sharedKey = ProtocolSecurity.RsaDecrypt(
                        encryptionKeyResponse.SharedKey.ToArray (), _server.RSACryptoServiceProvider, true);
                    if (verification.Length != randomBuffer.Length
                        || !verification.Zip(randomBuffer, (a, b) => a == b).All(a => a))
                    {
                        await KickUserAsync("Verify token failure");
                        _logger.Error("Failed to login a Client, Verify token failure");
                        return;
                    }

                    await ClientEndPoint.SendPacketAsync(new EncryptionKeyResponse {SharedKey = new byte[0]});

                    ClientEndPoint.ConnectionKey = sharedKey;
                    ClientEndPoint.EnableAes (); //now everything is encrypted

                    Packet p = await ClientEndPoint.ReceivePacketAsync ();

                    if (!(p is RespawnRequestPacket))
                    {
                        await KickUserAsync("Protocol failure");
                        _logger.Error("Failed to login a Client, Protocol failure");
                        return;
                    }

                    string hash = ProtocolSecurity.ComputeHash(
                        Encoding.ASCII.GetBytes(serverId),
                        ClientEndPoint.ConnectionKey,
                        AsnKeyBuilder.PublicKeyToX509(_server.RSAKeyPair).GetBytes ());

                    if (onlineMode)
                    {
                        bool result;
                        try
                        {
                            result = await _server.CheckUserAccountAsync(this, hash);
                        }
                        catch (OperationCanceledException ex)
                        {
                            Task t = KickUserAsync(ex.Message);
                            return;
                        }

                        if (!result)
                        {
                            await KickUserAsync("User not premium");
                            return;
                        }
                    }

                    _logger.InfoFormat("{0}[{1}] is connected", Username, _networkSocket.RemoteEndPoint);

                    _server.PromoteConnection(this);

                    Packet response = await InitializeServerAsync ();

                    var logonResponse = response as LogOnResponse;
                    if (logonResponse != null)
                    {
                        EntityID = logonResponse.EntityId;
                    }

                    await ClientEndPoint.SendPacketAsync(response);

                    StartClientListening ();
                    StartServerListening ();

                    args = new UserEventArgs(this);

                    _server.PluginManager.TriggerPlugin.OnUserConnectedCompleted(args);

                    args.EnsureSuccess ();
                }
            }
            catch (TaskCanceledException)
            {
                return;
            }
            catch (OperationCanceledException ex)
            {
                kickMessage = ex.Message;
                success = false;
                _quitMessagePosted = true;
                _logger.Error(string.Format("Client login aborted ({0})", Username), ex);
            }
            catch (Exception ex)
            {
                success = false;
                _quitMessagePosted = true;
                if (!string.IsNullOrEmpty(Username))
                    _logger.Error(string.Format("Failed to login a client ({0})", Username), ex);
            }
            if (!success)
                await KickUserAsync(kickMessage);
        }
 private void UnregisterServer()
 {
     if (ServerEndPoint != null)
     {
         ServerEndPoint.PacketReceived -= ServerPacketReceived;
         ServerEndPoint.ConnectionLost -= ServerConnectionLost;
         ServerEndPoint.Close ();
         _serverEndPoint = null;
     }
 }
        /// <summary>
        ///   Asynchronously initialize the server side of this connection
        /// </summary>
        /// <param name="serverEndPoint"> Information of the new server this connection should connect to. </param>
        /// <returns> A task which returns the LogOnPacket or DisconnectPacket of the established connection. </returns>
        public async Task<Packet> InitializeServerAsync(RemoteServerInfo serverEndPoint)
        {
            ProxyEndPoint server = null;
            try
            {
                UnregisterServer ();
                _serverEndPoint = null;

                if (!string.IsNullOrEmpty(serverEndPoint.KickMessage))
                {
                    await KickUserAsync(serverEndPoint.KickMessage);
                    throw new OperationCanceledException("User got kicked.");
                }

                if (serverEndPoint.MinecraftVersion == 0)
                    _server.GetServerVersion(this, serverEndPoint);
                if (serverEndPoint.MinecraftVersion == null)
                {
                    var information =await  MinecraftPinger.GetServerInformationAsync(serverEndPoint.EndPoint);
                    if((serverEndPoint.MinecraftVersion = information.ProtocolVersion) == null)
                        throw new InvalidOperationException("Could not auto detect server version");
                    
                }

                var socket = new Socket(serverEndPoint.EndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
                                 {
                                     ReceiveBufferSize = 1024*1024
                                 };

                await socket.ConnectTaskAsync(serverEndPoint.EndPoint);
                server =
                    new ProxyEndPoint(
                        ServerRemoteInterface.Create(new NetworkStream(socket), (int)serverEndPoint.MinecraftVersion),
                        (int)serverEndPoint.MinecraftVersion);
                server.RemoteEndPoint = (IPEndPoint) socket.RemoteEndPoint;
                var handshakeRequest = new HandshakeRequest
                                           {
                                               UserName = Username,
                                               Host = Host,
                                               ProtocolVersion = (byte) serverEndPoint.MinecraftVersion
                                           };
                await server.SendPacketAsync(handshakeRequest);

                Packet tp = await server.ReceivePacketAsync ();

                if (tp is DisconnectPacket)
                {
                    throw new OperationCanceledException((tp as DisconnectPacket).Reason);
                }

                var encryptionKeyRequest = tp as EncryptionKeyRequest;

                server.ConnectionKey = ProtocolSecurity.GenerateAes128Key ();
                byte[] key = ProtocolSecurity.RsaEncrypt(server.ConnectionKey, encryptionKeyRequest.PublicKey.ToArray (),
                                                         false);
                byte[] verifyToken = ProtocolSecurity.RsaEncrypt(encryptionKeyRequest.VerifyToken.ToArray (),
                                                                 encryptionKeyRequest.PublicKey.ToArray (), false);

                var encryptionKeyResponse = new EncryptionKeyResponse
                                                {
                                                    SharedKey = key,
                                                    VerifyToken = verifyToken
                                                };
                await server.SendPacketAsync(encryptionKeyResponse);

                Packet p = await server.ReceivePacketAsync ();

                server.EnableAes ();

                await server.SendPacketAsync(new RespawnRequestPacket ());

                return await server.ReceivePacketAsync ();
            }
            catch (Exception ex)
            {
                _quitMessagePosted = true;
                _logger.Error("Could not connect to remote server", ex);
                throw;
            }
            finally
            {
                _serverEndPoint = server;
            }
        }