Beispiel #1
0
        private static void HandleHttpSessionRequest(TcpClient client, string httpCmd, Stream clientStream, string tunnelHostName, List<string> requestLines, CustomBinaryReader clientStreamReader, StreamWriter clientStreamWriter, string securehost)
        {
            if (httpCmd == null)
            {
                if (clientStreamReader != null)
                    clientStreamReader.Dispose();

                if (clientStreamWriter != null)
                    clientStreamWriter.Dispose();

                if (clientStream != null)
                    clientStream.Dispose();

                if (client != null)
                    client.Close();

                return;
            }

            var args = new SessionEventArgs(BUFFER_SIZE);
            args.Client = client;
            args.tunnelHostName = tunnelHostName;
            args.securehost = securehost;

            try
            {
                //break up the line into three components (method, remote URL & Http Version)
                var splitBuffer = httpCmd.Split(spaceSplit, 3);

                if (splitBuffer.Length != 3)
                {
                    TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);

                    if (args != null)
                        args.Dispose();

                    if (clientStreamReader != null)
                        clientStreamReader.Dispose();

                    if (clientStreamWriter != null)
                        clientStreamWriter.Dispose();

                    if (clientStream != null)
                        clientStream.Dispose();

                    if (client != null)
                        client.Close();

                    return;
                }
                var method = splitBuffer[0];
                var remoteUri = splitBuffer[1];
                Version version;
                if (splitBuffer[2] == "HTTP/1.1")
                {
                    version = new Version(1, 1);
                }
                else
                {
                    version = new Version(1, 0);
                }

                if (securehost != null)
                {
                    remoteUri = securehost + remoteUri;
                    args.IsSSLRequest = true;
                }

                //construct the web request that we are going to issue on behalf of the client.
                args.ProxyRequest = (HttpWebRequest)HttpWebRequest.Create(remoteUri.Trim());
                args.ProxyRequest.Proxy = null;
                args.ProxyRequest.UseDefaultCredentials = true;
                args.ProxyRequest.Method = method;
                args.ProxyRequest.ProtocolVersion = version;
                args.ClientStream = clientStream;
                args.ClientStreamReader = clientStreamReader;
                args.ClientStreamWriter = clientStreamWriter;

                for (int i = 1; i < requestLines.Count; i++)
                {
                    var rawHeader = requestLines[i];
                    String[] header = rawHeader.ToLower().Trim().Split(colonSpaceSplit, 2, StringSplitOptions.None);

                    //if request was upgrade to web-socket protocol then relay the request without proxying
                    if ((header[0] == "upgrade") && (header[1] == "websocket"))
                    {

                        TcpHelper.SendRaw(httpCmd, tunnelHostName, requestLines, args.IsSSLRequest, clientStreamReader.BaseStream);

                        if (args != null)
                            args.Dispose();

                        if (clientStreamReader != null)
                            clientStreamReader.Dispose();

                        if (clientStreamWriter != null)
                            clientStreamWriter.Dispose();

                        if (clientStream != null)
                            clientStream.Dispose();

                        if (client != null)
                            client.Close();

                        return;
                    }
                }

                SetClientRequestHeaders(requestLines, args.ProxyRequest);

                int contentLen = (int)args.ProxyRequest.ContentLength;

                args.ProxyRequest.AllowAutoRedirect = false;
                args.ProxyRequest.AutomaticDecompression = DecompressionMethods.None;

                //If requested interception
                if (BeforeRequest != null)
                {
                    args.RequestHostname = args.ProxyRequest.RequestUri.Host;
                    args.RequestURL = args.ProxyRequest.RequestUri.OriginalString;

                    args.RequestLength = contentLen;

                    args.RequestHttpVersion = version;
                    args.ClientPort = ((IPEndPoint)client.Client.RemoteEndPoint).Port;
                    args.ClientIpAddress = ((IPEndPoint)client.Client.RemoteEndPoint).Address;
                    args.RequestIsAlive = args.ProxyRequest.KeepAlive;

                    BeforeRequest(null, args);
                }

                string tmpLine;
                if (args.CancelRequest)
                {
                    if (args != null)
                        args.Dispose();

                    if (clientStreamReader != null)
                        clientStreamReader.Dispose();

                    if (clientStreamWriter != null)
                        clientStreamWriter.Dispose();

                    if (clientStream != null)
                        clientStream.Dispose();

                    if (client != null)
                        client.Close();

                    return;
                }

                args.ProxyRequest.ConnectionGroupName = args.RequestHostname;
                args.ProxyRequest.AllowWriteStreamBuffering = true;

                //If request was modified by user
                if (args.RequestWasModified)
                {
                    ASCIIEncoding encoding = new ASCIIEncoding();
                    byte[] requestBytes = encoding.GetBytes(args.RequestHtmlBody);
                    args.ProxyRequest.ContentLength = requestBytes.Length;
                    Stream newStream = args.ProxyRequest.GetRequestStream();
                    newStream.Write(requestBytes, 0, requestBytes.Length);
                    args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args);

                }
                else
                {
                    //If its a post/put request, then read the client html body and send it to server
                    if (method.ToUpper() == "POST" || method.ToUpper() == "PUT")
                    {
                        SendClientRequestBody(args);

                        //Http request body sent, now wait asynchronously for response
                        args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args);

                    }
                    else
                    {
                        //otherwise wait for response asynchronously
                        args.ProxyRequest.BeginGetResponse(new AsyncCallback(HandleHttpSessionResponse), args);
                    }

                }

                //Now read the next request (if keep-Alive is enabled, otherwise exit this thread)
                //If client is pipeling the request, this will be immediately hit before response for previous request was made

                tmpLine = null;
                requestLines.Clear();
                while (!String.IsNullOrEmpty(tmpLine = args.ClientStreamReader.ReadLine()))
                {
                    requestLines.Add(tmpLine);
                }
                httpCmd = requestLines.Count() > 0 ? requestLines[0] : null;
                TcpClient Client = args.Client;

                //Http request body sent, now wait for next request
                Task.Factory.StartNew(() => HandleHttpSessionRequest(Client, httpCmd, args.ClientStream, args.tunnelHostName, requestLines, args.ClientStreamReader, args.ClientStreamWriter, args.securehost));

            }
            catch
            {
                if (args != null)
                    args.Dispose();

                if (clientStreamReader != null)
                    clientStreamReader.Dispose();

                if (clientStreamWriter != null)
                    clientStreamWriter.Dispose();

                if (clientStream != null)
                    clientStream.Dispose();

                if (client != null)
                    client.Close();

            }
        }