Ejemplo n.º 1
0
        void CloseClient(ProxyData Data)
        {
#if ENABLEDEBUG
            lock (Data.debug)
                Data.debug.Add("CloseClient");
#endif

            try
            {
                Data.ClientSocket.Shutdown(SocketShutdown.Both);
                Data.ClientSocket.Disconnect(false);
                Data.ClientSocket.Close();
                Data.ClientSocket.Dispose();
            }
            catch { }

            try
            {
                Data.Event.Set();
            }
            catch { }
        }
Ejemplo n.º 2
0
        private void SwapSocket(string OldHost, string Host, ProxyData data, bool Https)
        {
            try
            {
#if ENABLEDEBUG
                lock (data.debug)
                    data.debug.Add("SwapSocket " + OldHost + "->" + Host);
#endif
                string[] parts = Host.Split(':');

                string port = Https ? "443" : "80";
                string host = Host;

                if (parts.Length == 2)
                {
                    host = parts[0];
                    port = parts[1];
                }

                Socket socket = CreateSocket(host, int.Parse(port));

                data.CurrentServer = new SocketData {
                    ServerSocket = socket, Data = data
                };

                if (data.SSL)
                {
                    BeginRelayServer(data.CurrentServer);
                }
                else
                {
                    BeginReadServerHeader(data.CurrentServer);
                }
            }
            catch { }
        }
Ejemplo n.º 3
0
        //Si estamos recibiendo un Header del servidor, por mucho que sea KeepAlive se cierra para que se
        //entere el servidor a no ser que se cierre por un swapeo
        //
        //->//MAL!!
        //->//Desde el relay se vuelve a lanzar el ReadServer, puede que haga falta encapsular el socket y la query en
        //->//otro objeto para poder cambiar referencias
        void EndReadServerHeader(IAsyncResult Result)
        {
            SocketData sckData = (SocketData)Result.AsyncState;

            if (sckData != sckData.Data.CurrentServer)
            {
                try
                {
                    sckData.ServerSocket.EndReceive(Result);
                }
                catch { }
                try
                {
                    CloseServer(sckData);
                }
                catch { }

                return;
            }

            ProxyData Data = sckData.Data;

#if ENABLEDEBUG
            lock (Data.debug)
                Data.debug.Add("EndReadServerHeader");
#endif
            try
            {
                int leidos = sckData.ServerSocket.EndReceive(Result);

                if (leidos == 0)
                {
                    CloseServer(sckData);

                    if (!Data.ClosedBySwap && Data.RequestLeft != 0)
                    {
                        CloseClient(Data);
                    }
                    else
                    {
                        Data.ClosedBySwap = false;
                    }

                    return;
                }


                byte[] endBuffer = new Byte[4096];

                bool gotHeader = false;
                int  pos       = 0;

                while (leidos > 0 && !gotHeader)
                {
#if ENABLEDEBUG
                    Data.serverReceived.AddRange(sckData.ServerBuffer.Take(leidos));
#endif
                    Buffer.BlockCopy(sckData.ServerBuffer, 0, endBuffer, pos, leidos);
                    pos += leidos;

                    if (pos > 4)
                    {
                        //HasTrail
                        gotHeader = endBuffer[pos - 4] == trail[0] &&
                                    endBuffer[pos - 3] == trail[1] &&
                                    endBuffer[pos - 2] == trail[2] &&
                                    endBuffer[pos - 1] == trail[3];

                        if (!gotHeader)
                        {
                            leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 0, 1, SocketFlags.None);
                        }
                        else
                        {
                            ProcessServerHeader(sckData, endBuffer, pos);
                        }
                    }
                    else
                    {
                        leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 0, 1, SocketFlags.None);
                    }
                }
            }
            catch
            {
                CloseServer(sckData);

                if (!Data.ClosedBySwap && Data.RequestLeft != 0)
                {
                    CloseClient(Data);
                }
                else
                {
                    Data.ClosedBySwap = false;
                }
            }
        }
Ejemplo n.º 4
0
        private void EndRelayClient(IAsyncResult Result)
        {
            ProxyData Data = (ProxyData)Result.AsyncState;

#if ENABLEDEBUG
            lock (Data.debug)
                Data.debug.Add("EndRelayClient");
#endif
            try
            {
                int leidos = Data.ClientSocket.EndReceive(Result);

                if (leidos == 0)
                {
                    while (Data.ClientSocket.Connected)
                    {
                        Thread.Sleep(1);
                    }

                    CloseClient(Data);
                    CloseServer(Data);
                    return;
                }
#if ENABLEDEBUG
                Data.clientReceived.AddRange(Data.ClientBuffer.Take(leidos));
#endif
                if (Data.RequestLeft == -1)
                {
                    Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 0, leidos, SocketFlags.None);
                }
                else
                {
                    Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 0, Math.Min(leidos, Data.RequestLeft), SocketFlags.None);
                }

                int inicio    = Data.RequestLeft;
                int restantes = leidos - Data.RequestLeft;

                if (Data.RequestLeft > 0)
                {
                    Data.RequestLeft -= Math.Min(leidos, Data.RequestLeft);
                }

                if (Data.RequestLeft < 1 && Data.SourceRequest.Method.ToLower() != "connect")
                {
                    if (!Data.Chunked)
                    {
                        BeginReadClientHeader(Data);
                    }
                    else
                    {
                        string tam = "";
                        int    pos = inicio;

                        int tamChunk = -1;

newChunk:

                        //aqui se atrapa el \r\n anterior
                        while (restantes > 0 && (!tam.EndsWith("\r\n") || tam.Length < 3))
                        {
                            restantes--;
                            tam += Encoding.ASCII.GetString(Data.ClientBuffer, pos, 1);
                            pos++;
                        }

                        while (!tam.EndsWith("\r\n") || tam.Length < 3)
                        {
                            leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            tam += Encoding.ASCII.GetString(Data.ClientBuffer, 0, 1);
                        }

                        tamChunk = int.Parse(tam.Substring(2, tam.Length - 4), System.Globalization.NumberStyles.HexNumber);

                        bool lastChunk = tamChunk == 0;

                        Data.CurrentServer.ServerSocket.Send(Encoding.ASCII.GetBytes(tam));

                        //TODO: Añadir soporte para el trail
                        if (restantes > 0)
                        {
                            if (restantes >= tamChunk)
                            {
                                Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, pos, tamChunk, SocketFlags.None);
                                restantes -= tamChunk;
                                pos       += tamChunk;
                                tam        = "";

                                if (lastChunk)
                                {
                                    if (restantes >= 2)
                                    {
                                        Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, pos, 2, SocketFlags.None);
                                    }
                                    else if (restantes > 0)
                                    {
                                        Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, pos, 1, SocketFlags.None);

                                        leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 0, 1, SocketFlags.None);
                                    }
                                    else
                                    {
                                        leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 0, 1, SocketFlags.None);

                                        leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 0, 1, SocketFlags.None);
                                    }

                                    if (restantes > 2)
                                    {
                                        throw new Exception();
                                    }

                                    lastChunk = false;

                                    BeginReadClientHeader(Data);

                                    return;
                                }
                                else
                                {
                                    goto newChunk;
                                }
                            }

                            tamChunk -= Math.Min(restantes, tamChunk);

                            Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, pos, restantes, SocketFlags.None);
                        }

                        Data.RequestLeft = tamChunk;

                        if (lastChunk)
                        {
                            leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 2, SocketFlags.None);

                            BeginReadClientHeader(Data);
                        }
                        else
                        {
                            BeginRelayClient(Data);
                        }
                    }
                }
                else
                {
                    BeginRelayClient(Data);
                }
            }
            catch
            {
                CloseClient(Data);
                CloseServer(Data);
            }
        }
Ejemplo n.º 5
0
        private void ProcessClientHeader(ProxyData Data, byte[] Header, int Len)
        {
#if ENABLEDEBUG
            lock (Data.debug)
                Data.debug.Add("ProcessClientHeader");
#endif

            Data.Chunked = false;

            string header = Encoding.ASCII.GetString(Header, 0, Len);

            string[] lines = header.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            string[] tokens = lines[0].Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            if (tokens.Length != 3)
            {
                throw new Exception("invalid http request line");
            }

            Data.SourceRequest.Method = tokens[0].ToLower();

            Regex urlParser = new Regex("^[a-zA-Z]+:/+([^\\n/]*)(/.*)?", RegexOptions.Singleline);

            Match m = urlParser.Match(tokens[1]);

            if (m == null || !m.Success)
            {
                CloseClient(Data);
                CloseServer(Data);
                return;
            }

            string newhost = m.Groups[1].Value.Trim();
            string oldhost = Data.Host;

            bool switchSocket = oldhost.ToLower() != newhost.ToLower();

            Data.Host = newhost;
            Data.SourceRequest.Method          = tokens[0];
            Data.SourceRequest.SourceUrl       = tokens[1];
            Data.SourceRequest.ProtocolVersion = tokens[2];

            Data.SSL = Data.SourceRequest.Method.ToLower() == "connect";

            if (Data.SSL)
            {
                Data.KeepAlive = false;
            }

            int contentLength = Data.SSL ? -1 : 0;

            foreach (string linea in lines)
            {
                string llinea = linea.ToLower();

                if (llinea.StartsWith("content-length:"))
                {
                    string[] partes = linea.Split(':');

                    if (partes.Length != 2 || !int.TryParse(partes[1], out contentLength))
                    {
                        CloseClient(Data);
                        CloseServer(Data);
                        return;
                    }
                }
                else if (llinea.StartsWith("proxy-connection:") || llinea.StartsWith("connection"))
                {
                    string[] partes = linea.Split(':');

                    if (partes.Length != 2)
                    {
                        CloseClient(Data);
                        CloseServer(Data);
                        return;
                    }

                    if (partes[1].Trim() != "keep-alive")
                    {
                        Data.KeepAlive = false;
                    }
                }
                else if (llinea.StartsWith("transfer-encoding:"))
                {
                    string[] partes = linea.Split(':');

                    if (partes.Length != 2)
                    {
                        CloseClient(Data);
                        CloseServer(Data);
                        return;
                    }

                    if (partes[1].ToLower().Trim() == "chunked")
                    {
                        Data.Chunked  = true;
                        contentLength = 0;
                    }
                }
            }

            Data.RequestLeft = contentLength;

            if (switchSocket)
            {
                try
                {
                    Data.ClosedBySwap = true;
                    SwapSocket(oldhost, Data.Host, Data, Data.SSL);
                }
                catch
                {
                    CloseClient(Data);
                    CloseServer(Data);
                    return;
                }
            }

            if (Data.SourceRequest.Method.ToLower() != "connect")
            {
                string reconstructed = Data.SourceRequest.Method + " " + (m.Groups[2].Value.Trim() == "" ? "/" : m.Groups[2].Value.Trim()) + " " + Data.SourceRequest.ProtocolVersion + "\r\n";

                foreach (string s in lines.Skip(1))
                {
                    if (s.StartsWith("proxy"))
                    {
                        continue;
                    }

                    reconstructed += s + "\r\n";
                }

                reconstructed += "\r\n";
                Data.CurrentServer.ServerSocket.Send(Encoding.ASCII.GetBytes(reconstructed));

#if ENABLEDEBUG
                Data.requestheaders.Add("Original\r\n" + header + "Enviada\r\n" + reconstructed);
#endif
            }
            else
            {
                byte[] okdata = Encoding.ASCII.GetBytes("HTTP/1.1 200 Connection established\r\nProxy-Agent: GusNet.GusBridge Server\r\n\r\n");
                Data.ClientSocket.Send(okdata, 0, okdata.Length, SocketFlags.None);
            }

            if (Data.Chunked)
            {
                string tam    = "";
                int    leidos = 0;

                while (!tam.EndsWith("\r\n"))
                {
                    leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                    if (leidos == 0)
                    {
                        throw new Exception();
                    }

                    tam += Encoding.ASCII.GetString(Data.ClientBuffer, 0, 1);
                }

                int tamChunk = int.Parse(tam.Substring(0, tam.Length - 2), System.Globalization.NumberStyles.HexNumber);

                Data.CurrentServer.ServerSocket.Send(Encoding.ASCII.GetBytes(tam));

                Data.RequestLeft = contentLength = tamChunk;

                if (tamChunk == 0)
                {
                    leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, SocketFlags.None);

                    if (leidos == 0)
                    {
                        throw new Exception();
                    }

                    leidos = Data.ClientSocket.Receive(Data.ClientBuffer, 1, 1, SocketFlags.None);

                    if (leidos == 0)
                    {
                        throw new Exception();
                    }

                    Data.CurrentServer.ServerSocket.Send(Data.ClientBuffer, 2, SocketFlags.None);
                }
            }

            if (contentLength != 0)
            {
                BeginRelayClient(Data);
            }
            else
            {
                BeginReadClientHeader(Data);
            }
        }
Ejemplo n.º 6
0
        public override void ProcessRequest(GusServer.GusServerRequest Request)
        {
            string currentHost = Request.Method.ToLower() == "connect" ? Request.Path : Request.RequestHeaders["Host"];

            string[] address = currentHost.Split(':');

            Socket socket;

            ManualResetEvent evt;
            ProxyData        bdata = null;

            try
            {
                string sport = "80";

                if (address.Length == 1)
                {
                    if (Request.Method.ToLower() == "connect")
                    {
                        sport = "443";
                    }
                }
                else
                {
                    sport = address[1];
                }

                socket = CreateSocket(address[0], int.Parse(sport));

                evt = new ManualResetEvent(false);

                bdata = new ProxyData {
                    ClientSocket = Request.Processor.Socket, Event = evt, Host = currentHost, SourceRequest = Request, KeepAlive = Request.Method.ToLower() != "connect"
                };

                SocketData sckData = new SocketData {
                    Data = bdata, ServerSocket = socket
                };
                bdata.CurrentServer = sckData;

                if (Request.RequestHeaders.ContainsKey("Proxy-Connection") && Request.RequestHeaders["Proxy-Connection"].ToLower() != "keep-alive")
                {
                    bdata.KeepAlive = false;
                }

                if (Request.RequestHeaders.ContainsKey("Connection") && Request.RequestHeaders["Connection"].ToLower() != "keep-alive")
                {
                    bdata.KeepAlive = false;
                }


#if ENABLEDEBUG
                bdata.ProxyKeepAlive = bdata.KeepAlive;
#endif

                if (Request.Method.ToLower() == "connect")
                {
                    bdata.SSL            = true;
                    bdata.RequestLeft    = -1;
                    sckData.ResponseLeft = -1;
                    bdata.KeepAlive      = false;
                }

                if (bdata.SSL)
                {
                    byte[] okdata = Encoding.ASCII.GetBytes(Request.ProtocolVersion + " 200 Connection established\r\nProxy-Agent: GusNet.GusBridge Server\r\n\r\n");
                    bdata.ClientSocket.Send(okdata, 0, okdata.Length, SocketFlags.None);
                }
                else
                {
                    byte[] header = ReconstructRequest(Request, bdata);
#if ENABLEDEBUG
                    bdata.requestheaders.Add("Original\r\n" + Encoding.ASCII.GetString(Request.Processor.OriginalRequest) + "Enviada\r\n" + Encoding.ASCII.GetString(header));
#endif
                    socket.Send(header, SocketFlags.None);

                    if (!string.IsNullOrEmpty(Request.Processor.PostDataFile))
                    {
                        Stream str    = File.OpenRead(Request.Processor.PostDataFile);
                        int    leidos = str.Read(bdata.ClientBuffer, 0, bdata.ClientBuffer.Length);

                        while (leidos > 0)
                        {
                            socket.Send(bdata.ClientBuffer, leidos, SocketFlags.None);
                            leidos = str.Read(bdata.ClientBuffer, 0, bdata.ClientBuffer.Length);
                        }

                        str.Close();
                    }
                }

                if (bdata.SSL)
                {
                    BeginRelayClient(bdata);
                }
                else
                {
                    BeginReadClientHeader(bdata);
                }

                if (bdata.SSL)
                {
                    BeginRelayServer(sckData);
                }
                else
                {
                    BeginReadServerHeader(sckData);
                }

#if ENABLEDEBUG
                //Para poder poner Breakpoints en peticiones que se están ejecutando
                while (!evt.WaitOne(10))
                {
                }
                DebugData(bdata);
#else
                evt.WaitOne();
#endif
            }
            catch
            { }
        }
Ejemplo n.º 7
0
 public void WriteDebug(string FileName, ProxyData Data)
 {
     File.WriteAllBytes(FileName, Data.clientSent.ToArray());
 }
Ejemplo n.º 8
0
 public void ClientSent(byte[] sdata, int offset, int len, ProxyData Data)
 {
     byte[] data = new byte[len];
     Buffer.BlockCopy(sdata, offset, data, 0, len);
     Data.clientSent.AddRange(data);
 }
Ejemplo n.º 9
0
 public void ClientSent(byte[] data, ProxyData Data)
 {
     Data.clientSent.AddRange(data);
 }
Ejemplo n.º 10
0
        private void EndRelayServer(IAsyncResult Result)
        {
            SocketData sckData = (SocketData)Result.AsyncState;

            if (sckData != sckData.Data.CurrentServer)
            {
                try
                {
                    sckData.ServerSocket.EndReceive(Result);
                }
                catch { }

                try
                {
                    sckData.ServerSocket.Shutdown(SocketShutdown.Both);
                    sckData.ServerSocket.Disconnect(false);
                    sckData.ServerSocket.Close();
                    sckData.ServerSocket.Dispose();
                }
                catch { }

                return;
            }

            ProxyData Data = sckData.Data;

#if ENABLEDEBUG
            lock (Data.debug)
                Data.debug.Add("EndRelayServer");
#endif
            try
            {
                int leidos = sckData.ServerSocket.EndReceive(Result);

                if (leidos == 0)
                {
                    CloseServer(Data);

                    if (!Data.KeepAlive || sckData.ResponseLeft != 0)
                    {
                        CloseClient(Data);
                    }

                    return;
                }
#if ENABLEDEBUG
                Data.serverReceived.AddRange(sckData.ServerBuffer.Take(leidos));
#endif

                int enviados = 0;
                //OJ
                if (sckData.ResponseLeft == -1)
                {
                    Data.ClientSocket.Send(sckData.ServerBuffer, 0, leidos, SocketFlags.None);
                }
                else
                {
                    enviados = Data.ClientSocket.Send(sckData.ServerBuffer, 0, Math.Min(leidos, sckData.ResponseLeft), SocketFlags.None);
#if ENABLEDEBUG
                    ClientSent(sckData.ServerBuffer, 0, Math.Min(leidos, sckData.ResponseLeft), Data);
#endif
                }

                int inicio    = sckData.ResponseLeft;
                int restantes = leidos - sckData.ResponseLeft;

                if (sckData.ResponseLeft > 0)
                {
                    sckData.ResponseLeft -= Math.Min(leidos, sckData.ResponseLeft);
                }



                if (sckData.ResponseLeft < 1 && Data.SourceRequest.Method.ToLower() != "connect" && (sckData.KeepAlive || Data.KeepAlive || sckData.Chunked))
                {
                    if (!sckData.Chunked)
                    {
                        BeginReadServerHeader(sckData);
                    }
                    else
                    {
                        string tam = "";
                        int    pos = inicio;

                        int tamChunk = -1;

newChunk:
                        //aqui se atrapa el \r\n anterior
                        while (restantes > 0 && (!tam.EndsWith("\r\n") || tam.Length < 3))
                        {
                            restantes--;
                            tam += Encoding.ASCII.GetString(sckData.ServerBuffer, pos, 1);
                            pos++;
                        }

                        while (!tam.EndsWith("\r\n") || tam.Length < 3)
                        {
                            leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            tam += Encoding.ASCII.GetString(sckData.ServerBuffer, 0, 1);
                        }

                        tamChunk = int.Parse(tam.Substring(2, tam.Length - 4), System.Globalization.NumberStyles.HexNumber);

                        bool lastChunk = tamChunk == 0;

                        Data.ClientSocket.Send(Encoding.ASCII.GetBytes(tam));
#if ENABLEDEBUG
                        ClientSent(Encoding.ASCII.GetBytes(tam), Data);
#endif
                        if (restantes > 0)
                        {
                            if (restantes >= tamChunk)
                            {
                                Data.ClientSocket.Send(sckData.ServerBuffer, pos, tamChunk, SocketFlags.None);
#if ENABLEDEBUG
                                ClientSent(sckData.ServerBuffer, pos, tamChunk, Data);
#endif
                                restantes -= tamChunk;
                                pos       += tamChunk;
                                tam        = "";

                                if (lastChunk)
                                {
                                    if (restantes >= 2)
                                    {
                                        Data.ClientSocket.Send(sckData.ServerBuffer, pos, 2, SocketFlags.None);
#if ENABLEDEBUG
                                        ClientSent(sckData.ServerBuffer, pos, 2, Data);
#endif
                                    }
                                    else if (restantes > 0)
                                    {
                                        Data.ClientSocket.Send(sckData.ServerBuffer, pos, 1, SocketFlags.None);
#if ENABLEDEBUG
                                        ClientSent(sckData.ServerBuffer, pos, 1, Data);
#endif

                                        leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.ClientSocket.Send(sckData.ServerBuffer, 0, 1, SocketFlags.None);
#if ENABLEDEBUG
                                        ClientSent(sckData.ServerBuffer, 0, 1, Data);
#endif
                                    }
                                    else
                                    {
                                        leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.ClientSocket.Send(sckData.ServerBuffer, 0, 1, SocketFlags.None);
#if ENABLEDEBUG
                                        ClientSent(sckData.ServerBuffer, 0, 1, Data);
#endif

                                        leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, SocketFlags.None);

                                        if (leidos == 0)
                                        {
                                            throw new Exception();
                                        }

                                        Data.ClientSocket.Send(sckData.ServerBuffer, 0, 1, SocketFlags.None);
#if ENABLEDEBUG
                                        ClientSent(sckData.ServerBuffer, 0, 1, Data);
#endif
                                    }

                                    if (restantes > 2)
                                    {
                                        throw new Exception();
                                    }

                                    lastChunk = false;

                                    BeginReadServerHeader(sckData);

                                    return;
                                }
                                else
                                {
                                    goto newChunk;
                                }
                            }

                            tamChunk -= Math.Min(restantes, tamChunk);

                            Data.ClientSocket.Send(sckData.ServerBuffer, pos, restantes, SocketFlags.None);
#if ENABLEDEBUG
                            ClientSent(sckData.ServerBuffer, pos, restantes, Data);
#endif
                        }

                        sckData.ResponseLeft = tamChunk;

                        if (lastChunk)
                        {
                            leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            leidos = sckData.ServerSocket.Receive(sckData.ServerBuffer, 1, 1, SocketFlags.None);

                            if (leidos == 0)
                            {
                                throw new Exception();
                            }

                            Data.ClientSocket.Send(sckData.ServerBuffer, 2, SocketFlags.None);
#if ENABLEDEBUG
                            ClientSent(sckData.ServerBuffer, 2, Data);
#endif
                            BeginReadServerHeader(sckData);
                        }
                        else
                        {
                            BeginRelayServer(sckData);
                        }
                    }
                }
                else
                {
                    BeginRelayServer(sckData);
                }
            }
            catch
            {
                CloseServer(sckData);

                if (!Data.KeepAlive || sckData.ResponseLeft != 0)
                {
                    CloseClient(Data);
                }
            }
        }