Esempio n. 1
0
        // ProxyHTTP: proxy a HTTP request
        private void ProxyHTTP(Socket client)
        {
            NetworkStream netStream = new NetworkStream(client);
            HandyNetReader reader = new HandyNetReader(netStream);

            string line = null;
            int reqNo;
            int contentLength = 0;
            string contentType = "";
            Match match;
            string uri;
            string meth;
            Dictionary<string, string> headers = new Dictionary<string, string>();

            lock (this)
            {
                capsReqCount++; reqNo = capsReqCount;
            }

            byte[] byteLine = reader.ReadLine();
            if(byteLine==null)
            {
                //This dirty hack is part of the LIBOMV-457 workaround
                //The connecting libomv client being proxied can manage to trigger a null from the ReadLine()
                //The happens just after the seed request and is not seen again. TODO find this bug in the library.
                netStream.Close(); client.Close();
                return;
            }

            if (byteLine != null) line = Encoding.UTF8.GetString(byteLine).Replace("\r", "");

            if (line == null)
                throw new Exception("EOF in client HTTP header");

            match = new Regex(@"^(\S+)\s+(\S+)\s+(HTTP/\d\.\d)$").Match(line);

            if (!match.Success)
            {
                OpenMetaverse.Logger.Log("[" + reqNo + "] Bad request!", Helpers.LogLevel.Warning);
                byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
                netStream.Write(wr, 0, wr.Length);
                netStream.Close(); client.Close();
                return;
            }

            meth = match.Groups[1].Captures[0].ToString();
            uri = match.Groups[2].Captures[0].ToString();

            OpenMetaverse.Logger.Log(String.Format("[{0}] {1}:{2}", reqNo, meth, uri), Helpers.LogLevel.Debug);
            
            // read HTTP header
            do
            {
                // read one line of the header
                line = Encoding.UTF8.GetString(reader.ReadLine()).Replace("\r", "");

                // check for premature EOF
                if (line == null)
                    throw new Exception("EOF in client HTTP header");

                if (line == "") break;

                match = new Regex(@"^([^:]+):\s*(.*)$").Match(line);

                if (!match.Success)
                {
                    OpenMetaverse.Logger.Log(String.Format("[{0}] Bad Header: '{1}'", reqNo, line), Helpers.LogLevel.Warning);
                    byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
                    netStream.Write(wr, 0, wr.Length);
                    netStream.Close(); client.Close();
                    return;
                }

                string key = match.Groups[1].Captures[0].ToString();
                string val = match.Groups[2].Captures[0].ToString();
                headers[key.ToLower()] = val;
            } while (line != "");

            if (headers.ContainsKey("content-length"))
            {
                contentLength = Convert.ToInt32(headers["content-length"]);
            }

            if (headers.ContainsKey("content-type")) {
                contentType = headers["content-type"];
            }

            // read the HTTP body into a buffer
            byte[] content = new byte[contentLength];
            reader.Read(content, 0, contentLength);

            if (contentLength < 8192) 
                OpenMetaverse.Logger.Log(String.Format("[{0}] request length={1}:\n{2}", reqNo, contentLength, Utils.BytesToString(content)), Helpers.LogLevel.Debug);

            if (uri == "/")
            {
                if (contentType == "application/xml+llsd" || contentType == "application/xml") {
                    ProxyLoginSD(netStream, content);
                } else {
                    ProxyLogin(netStream, content);
                }
            }
            else if (new Regex(@"^/https?://.*$").Match(uri).Success)
            {
                ProxyCaps(netStream, meth, uri.Substring(1), headers, content, reqNo);
            }
            else if (new Regex(@"^/https?:/.*$").Match(uri).Success)
            {
                //This is a libomv client and the proxy CAPS URI has been munged by the C# URI class
                //Part of the LIBOMV-457 work around, TODO make this much nicer.
                uri=uri.Replace(":/","://");
                ProxyCaps(netStream, meth, uri.Substring(1), headers, content, reqNo);
            }
            else
            {
                OpenMetaverse.Logger.Log("404 not found: " + uri, Helpers.LogLevel.Error);
                byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\n\r\n");
                netStream.Write(wr, 0, wr.Length);
                netStream.Close(); client.Close();
                return;
            }

            netStream.Close();
            client.Close();

        }
Esempio n. 2
0
        // ProxyHTTP: proxy a HTTP request
        private void ProxyHTTP(Socket client)
        {
            NetworkStream netStream = new NetworkStream(client);
            HandyNetReader reader = new HandyNetReader(netStream);

            string line = null;
            int reqNo;
            int contentLength = 0;
            string contentType = "";
            Match match;
            string uri;
            string meth;
            Dictionary<string, string> headers = new Dictionary<string, string>();

            lock (this)
            {
                capsReqCount++; reqNo = capsReqCount;
            }

            byte[] byteLine = reader.ReadLine();
            if (byteLine != null) line = Encoding.UTF8.GetString(byteLine).Replace("\r", "");

            if (line == null)
                throw new Exception("EOF in client HTTP header");

            match = new Regex(@"^(\S+)\s+(\S+)\s+(HTTP/\d\.\d)$").Match(line);

            if (!match.Success)
            {
                Console.WriteLine("[" + reqNo + "] Bad request!");
                byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
                netStream.Write(wr, 0, wr.Length);
                netStream.Close(); client.Close();
                return;
            }


            meth = match.Groups[1].Captures[0].ToString();
            uri = match.Groups[2].Captures[0].ToString();
#if DEBUG_CAPS
            Console.WriteLine("[" + reqNo + "] " + meth + ": " + uri); // FIXME - for debugging only
#endif

            // read HTTP header
            do
            {
                // read one line of the header
                line = Encoding.UTF8.GetString(reader.ReadLine()).Replace("\r", "");

                // check for premature EOF
                if (line == null)
                    throw new Exception("EOF in client HTTP header");

                if (line == "") break;

                match = new Regex(@"^([^:]+):\s*(.*)$").Match(line);

                if (!match.Success)
                {
                    Console.WriteLine("[" + reqNo + "] Bad header: '" + line + "'");
                    byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
                    netStream.Write(wr, 0, wr.Length);
                    netStream.Close(); client.Close();
                    return;
                }

                string key = match.Groups[1].Captures[0].ToString();
                string val = match.Groups[2].Captures[0].ToString();
                headers[key.ToLower()] = val;
            } while (line != "");

            if (headers.ContainsKey("content-length"))
            {
                contentLength = Convert.ToInt32(headers["content-length"]);
            }

            if (headers.ContainsKey("content-type")) {
                contentType = headers["content-type"];
            }

            // read the HTTP body into a buffer
            byte[] content = new byte[contentLength];
            reader.Read(content, 0, contentLength);

#if DEBUG_CAPS
            if (contentLength < 8192) Console.WriteLine("[" + reqNo + "] request length = " + contentLength + ":\n" + Utils.BytesToString(content) + "\n-------------");
#endif

            if (uri == "/")
            {
                if (contentType == "application/xml+llsd" || contentType == "application/xml") {
                    ProxyLoginSD(netStream, content);
                } else {
                    ProxyLogin(netStream, content);
                }
            }
            else if (new Regex(@"^/https?://.*$").Match(uri).Success)
            {
                ProxyCaps(netStream, meth, uri.Substring(1), headers, content, reqNo);
            }
            else
            {
                Console.WriteLine("404 not found: " + uri);
                byte[] wr = Encoding.ASCII.GetBytes("HTTP/1.0 404 Not Found\r\nContent-Length: 0\r\n\r\n");
                netStream.Write(wr, 0, wr.Length);
                netStream.Close(); client.Close();
                return;
            }

            netStream.Close();
            client.Close();

        }