private void CloseServer(SocketData Data) { #if ENABLEDEBUG lock (Data.Data.debug) Data.Data.debug.Add("CloseServer SocketData"); #endif try { if (Data.Data.CurrentServer == Data) { Data.Data.Host = ""; } Data.ServerSocket.Shutdown(SocketShutdown.Both); Data.ServerSocket.Disconnect(false); Data.ServerSocket.Close(); Data.ServerSocket.Dispose(); } catch { } }
private void ProcessServerHeader(SocketData Data, byte[] Header, int Len) { Data.Chunked = false; Data.KeepAlive = Data.Data.KeepAlive; #if ENABLEDEBUG lock (Data.Data.debug) Data.Data.debug.Add("ProcessServerHeader"); #endif string header = Encoding.ASCII.GetString(Header, 0, Len); #if ENABLEDEBUG Data.Data.responseheaders.Add(header); #endif string[] lines = header.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); int contentLength = -1; 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)) { continue; } } else if (llinea.StartsWith("connection:")) { string[] partes = linea.Split(':'); if (partes.Length != 2) { continue; } if (partes[1].Trim().ToLower() == "keep-alive") { Data.KeepAlive = Data.Data.KeepAlive; } else { Data.KeepAlive = false; } } else if (llinea.StartsWith("transfer-encoding:")) { string[] partes = linea.Split(':'); if (partes.Length != 2) { continue; } if (partes[1].Trim().ToLower() == "chunked") { contentLength = 0; Data.Chunked = true; } } } ///Si se cierra una conexión de servidor, es una conexión SSL y es KeepAlive ///se debería comenzar otro request?? Data.ResponseLeft = contentLength; byte[] data; foreach (string s in lines) { if (s.StartsWith("proxy")) { continue; } data = Encoding.ASCII.GetBytes(s + "\r\n"); Data.Data.ClientSocket.Send(data); #if ENABLEDEBUG ClientSent(data, Data.Data); #endif } data = Encoding.ASCII.GetBytes("\r\n"); Data.Data.ClientSocket.Send(data); #if ENABLEDEBUG ClientSent(data, Data.Data); #endif if (Data.Chunked) { string tam = ""; int leidos = 0; while (!tam.EndsWith("\r\n")) { leidos = Data.ServerSocket.Receive(Data.ServerBuffer, 1, SocketFlags.None); if (leidos == 0) { throw new Exception(); } tam += Encoding.ASCII.GetString(Data.ServerBuffer, 0, 1); } int tamChunk = int.Parse(tam.Substring(0, tam.Length - 2), System.Globalization.NumberStyles.HexNumber); Data.Data.ClientSocket.Send(Encoding.ASCII.GetBytes(tam)); #if ENABLEDEBUG ClientSent(Encoding.ASCII.GetBytes(tam), Data.Data); #endif Data.ResponseLeft = contentLength = tamChunk; if (tamChunk == 0) { leidos = Data.ServerSocket.Receive(Data.ServerBuffer, 1, SocketFlags.None); if (leidos == 0) { throw new Exception(); } leidos = Data.ServerSocket.Receive(Data.ServerBuffer, 1, 1, SocketFlags.None); if (leidos == 0) { throw new Exception(); } Data.Data.ClientSocket.Send(Data.ServerBuffer, 2, SocketFlags.None); #if ENABLEDEBUG ClientSent(Data.ServerBuffer, 2, Data.Data); #endif } } string[] response = lines[0].Split(' '); int responseCode = int.Parse(response[1]); if ((responseCode > 99 && responseCode < 200) || responseCode == 204 || responseCode == 304) { contentLength = 0; } else if (contentLength == -1 && Data.Data.KeepAlive) { Data.Data.KeepAlive = Data.KeepAlive = false; } if (contentLength != 0) { BeginRelayServer(Data); } else { BeginReadServerHeader(Data); } }
//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; } } }
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 { } }
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); } } }