public override bool Handle(byte[] firstPacket, int length, Socket socket, object state) { if (socket.ProtocolType != ProtocolType.Tcp) { return(false); } try { string request = Encoding.UTF8.GetString(firstPacket, 0, length); string[] lines = request.Split('\r', '\n'); bool hostMatch = false, pathMatch = false, useSocks = false; bool secretMatch = PacSecret.IsNullOrEmpty(); foreach (string line in lines) { string[] kv = line.Split(new char[] { ':' }, 2); if (kv.Length == 2) { if (kv[0] == "Host") { if (kv[1].Trim() == ((IPEndPoint)socket.LocalEndPoint).ToString()) { hostMatch = true; } } //else if (kv[0] == "User-Agent") //{ // // we need to drop connections when changing servers // if (kv[1].IndexOf("Chrome") >= 0) // { // useSocks = true; // } //} } else if (kv.Length == 1) { if (line.IndexOf("pac", StringComparison.Ordinal) >= 0) { pathMatch = true; } if (!secretMatch) { if (line.IndexOf(PacSecret, StringComparison.Ordinal) >= 0) { secretMatch = true; } } } } if (hostMatch && pathMatch) { if (!secretMatch) { socket.Close(); // Close immediately } else { SendResponse(socket, useSocks); } return(true); } return(false); } catch (ArgumentException) { return(false); } }
public override bool Handle(byte[] firstPacket, int length, Socket socket, object state) { if (socket.ProtocolType != ProtocolType.Tcp) { return(false); } try { /* * RFC 7230 * * GET /hello.txt HTTP/1.1 * User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 * Host: www.example.com * Accept-Language: en, mi */ string request = Encoding.UTF8.GetString(firstPacket, 0, length); string[] lines = request.Split('\r', '\n'); bool hostMatch = false, pathMatch = false, useSocks = false; bool secretMatch = PacSecret.IsNullOrEmpty(); if (lines.Length < 2) // need at lease RequestLine + Host { return(false); } // parse request line string requestLine = lines[0]; // GET /pac?t=yyyyMMddHHmmssfff&secret=foobar HTTP/1.1 string[] requestItems = requestLine.Split(' '); if (requestItems.Length == 3 && requestItems[0] == "GET") { int index = requestItems[1].IndexOf('?'); if (index < 0) { index = requestItems[1].Length; } string resourceString = requestItems[1].Substring(0, index).Remove(0, 1); if (string.Equals(resourceString, RESOURCE_NAME, StringComparison.OrdinalIgnoreCase)) { pathMatch = true; if (!secretMatch) { string queryString = requestItems[1].Substring(index); if (queryString.Contains(PacSecret)) { secretMatch = true; } } } } // parse request header for (int i = 1; i < lines.Length; i++) { if (string.IsNullOrEmpty(lines[i])) { continue; } string[] kv = lines[i].Split(new char[] { ':' }, 2); if (kv.Length == 2) { if (kv[0] == "Host") { if (kv[1].Trim() == ((IPEndPoint)socket.LocalEndPoint).ToString()) { hostMatch = true; } } //else if (kv[0] == "User-Agent") //{ // // we need to drop connections when changing servers // if (kv[1].IndexOf("Chrome") >= 0) // { // useSocks = true; // } //} } } if (hostMatch && pathMatch) { if (!secretMatch) { socket.Close(); // Close immediately } else { SendResponse(socket, useSocks); } return(true); } return(false); } catch (ArgumentException) { return(false); } }