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 { } }
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 { } }
//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; } } }
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); } }
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); } }
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 { } }
public void WriteDebug(string FileName, ProxyData Data) { File.WriteAllBytes(FileName, Data.clientSent.ToArray()); }
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); }
public void ClientSent(byte[] data, ProxyData Data) { Data.clientSent.AddRange(data); }
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); } } }