Ejemplo n.º 1
0
        /// <summary>
        /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
        /// Sends back an XMLRPC unknown request response if no handler is registered for the requested method.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        private bool HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
        {
            Stream requestStream = request.InputStream;

            Encoding encoding = Encoding.UTF8;
            StreamReader reader = new StreamReader(requestStream, encoding);

            string requestBody = reader.ReadToEnd();
            reader.Close();
            requestStream.Close();
            //MainConsole.Instance.Debug(requestBody);
            requestBody = requestBody.Replace("<base64></base64>", "");
            XmlRpcRequest xmlRprcRequest = null;

            try
            {
                if(requestBody.StartsWith("<?xml"))
                    xmlRprcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
            }
            catch (XmlException)
            {
            }

            if (xmlRprcRequest != null)
            {
                string methodName = xmlRprcRequest.MethodName;
                if (methodName != null)
                {
                    xmlRprcRequest.Params.Add(request.RemoteIPEndPoint); // Param[1]
                    XmlRpcResponse xmlRpcResponse;

                    XmlRpcMethod method;
                    bool methodWasFound;
                    lock (m_rpcHandlers)
                    {
                        methodWasFound = m_rpcHandlers.TryGetValue(methodName, out method);
                    }

                    if (methodWasFound)
                    {
                        xmlRprcRequest.Params.Add(request.Url); // Param[2]
                        xmlRprcRequest.Params.Add(request.Headers.Get("X-Forwarded-For")); // Param[3]

                        try
                        {
                            xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
                        }
                        catch (Exception e)
                        {
                            string errorMessage
                                = String.Format(
                                    "Requested method [{0}] from {1} threw exception: {2} {3}",
                                    methodName, request.RemoteIPEndPoint.Address, e, e.StackTrace);

                            MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: {0}", errorMessage);

                            // if the registered XmlRpc method threw an exception, we pass a fault-code along
                            xmlRpcResponse = new XmlRpcResponse();

                            // Code probably set in accordance with http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
                            xmlRpcResponse.SetFault(-32603, errorMessage);
                        }

                        // if the method wasn't found, we can't determine KeepAlive state anyway, so lets do it only here
                        response.KeepAlive = m_rpcHandlersKeepAlive[methodName];
                    }
                    else
                    {
                        xmlRpcResponse = new XmlRpcResponse();

                        // Code set in accordance with http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
                        xmlRpcResponse.SetFault(
                            XmlRpcErrorCodes.SERVER_ERROR_METHOD,
                            String.Format("Requested method [{0}] not found", methodName));
                    }

                    string responseString = XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse);

                    response.ContentType = "text/xml";

                    byte[] buffer = Encoding.UTF8.GetBytes(responseString);

                    response.SendChunked = false;
                    response.ContentLength64 = buffer.Length;
                    response.ContentEncoding = Encoding.UTF8;
                    try
                    {
                        response.OutputStream.Write(buffer, 0, buffer.Length);
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
                    }
                    finally
                    {
                        try
                        {
                            response.Send();
                            //response.FreeContext();
                        }
                        catch (SocketException e)
                        {
                            // This has to be here to prevent a Linux/Mono crash
                            MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                        }
                        catch (IOException e)
                        {
                            MainConsole.Instance.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                        }
                    }
                    return true;
                }
                //HandleLLSDRequests(request, response);
                response.ContentType = "text/plain";
                response.StatusCode = 404;
                response.StatusDescription = "Not Found";
                response.ProtocolVersion = "HTTP/1.0";
                byte[] buf = Encoding.UTF8.GetBytes("Not found");
                response.KeepAlive = false;

                MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: Handler not found for http request {0}, port {1}", request.RawUrl, Port);

                response.SendChunked = false;
                response.ContentLength64 = buf.Length;
                response.ContentEncoding = Encoding.UTF8;

                try
                {
                    response.OutputStream.Write(buf, 0, buf.Length);
                }
                catch (Exception ex)
                {
                    MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
                }
                finally
                {
                    try
                    {
                        response.Send();
                        //response.FreeContext();
                    }
                    catch (SocketException e)
                    {
                        // This has to be here to prevent a Linux/Mono crash
                        MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                    }
                    catch (IOException e)
                    {
                        MainConsole.Instance.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                    }
                }
                return true;
                //responseString = "Error";
            }

            return false;
        }
Ejemplo n.º 2
0
        private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
        {
            //MainConsole.Instance.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request");
            Stream requestStream = request.InputStream;

            Encoding encoding = Encoding.UTF8;
            StreamReader reader = new StreamReader(requestStream, encoding);

            string requestBody = reader.ReadToEnd();
            reader.Close();
            requestStream.Close();

            //MainConsole.Instance.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody);
            response.KeepAlive = true;

            OSD llsdRequest = null;
            OSD llsdResponse = null;

            bool LegacyLLSDLoginLibOMV = (requestBody.Contains("passwd") && requestBody.Contains("mac") && requestBody.Contains("viewer_digest"));

            if (requestBody.Length == 0)
            // Get Request
            {
                requestBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><llsd><map><key>request</key><string>get</string></map></llsd>";
            }
            try
            {
                llsdRequest = OSDParser.Deserialize(requestBody);
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
            }

            if (llsdRequest != null)// && m_defaultLlsdHandler != null)
            {

                LLSDMethod llsdhandler = null;

                if (TryGetLLSDHandler(request.RawUrl, out llsdhandler) && !LegacyLLSDLoginLibOMV)
                {
                    // we found a registered llsd handler to service this request
                    llsdResponse = llsdhandler(request.RawUrl, llsdRequest, request.RemoteIPEndPoint);
                }
                else
                {
                    // we didn't find a registered llsd handler to service this request
                    // .. give em the failed message
                    llsdResponse = GenerateNoLLSDHandlerResponse();
                }

            }
            else
            {
                llsdResponse = GenerateNoLLSDHandlerResponse();
            }
            byte[] buffer = new byte[0];
            if (llsdResponse.ToString() == "shutdown404!")
            {
                response.ContentType = "text/plain";
                response.StatusCode = 404;
                response.StatusDescription = "Not Found";
                response.ProtocolVersion = "HTTP/1.0";
                buffer = Encoding.UTF8.GetBytes("Not found");
            }
            else
            {
                // Select an appropriate response format
                buffer = BuildLLSDResponse(request, response, llsdResponse);
            }

            response.SendChunked = false;
            response.ContentLength64 = buffer.Length;
            response.ContentEncoding = Encoding.UTF8;
            response.KeepAlive = true;

            try
            {
                response.OutputStream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
            }
            finally
            {
                //response.OutputStream.Close();
                try
                {
                    response.Send();
                    response.OutputStream.Flush();
                    //response.FreeContext();
                    //response.OutputStream.Close();
                }
                catch (IOException e)
                {
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
                }
                catch (SocketException e)
                {
                    // This has to be here to prevent a Linux/Mono crash
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux.", e);
                }
            }
        }
Ejemplo n.º 3
0
        public void SendHTML500(OSHttpResponse response)
        {
            // I know this statuscode is dumb, but the client doesn't respond to 404s and 500s
            response.StatusCode = (int)OSHttpStatusCode.SuccessOk;
            response.AddHeader("Content-type", "text/html");

            string responseString = GetHTTP500();
            byte[] buffer = Encoding.UTF8.GetBytes(responseString);

            response.SendChunked = false;
            response.ContentLength64 = buffer.Length;
            response.ContentEncoding = Encoding.UTF8;
            try
            {
                response.OutputStream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
            }
            finally
            {
                //response.OutputStream.Close();
                try
                {
                    response.Send();
                    //response.FreeContext();
                }
                catch (SocketException e)
                {
                    // This has to be here to prevent a Linux/Mono crash
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                }
            }
        }
Ejemplo n.º 4
0
        // public void ConvertIHttpClientContextToOSHttp(object stateinfo)
        // {
        //     HttpServerContextObj objstate = (HttpServerContextObj)stateinfo;

        //     OSHttpRequest request = objstate.oreq;
        //     OSHttpResponse resp = objstate.oresp;

        //     HandleRequest(request,resp);
        // }

        /// <summary>
        /// This methods is the start of incoming HTTP request handling.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        public virtual void HandleRequest(OSHttpRequest request, OSHttpResponse response)
        {
            if (request.HttpMethod == String.Empty) // Can't handle empty requests, not wasting a thread
            {
                try
                {
                    SendHTML500(response);
                }
                catch
                {
                }

                return;
            }

            string reqnum = "unknown";
            int tickstart = Environment.TickCount;
            string RawUrl = request.RawUrl;
            string HTTPMethod = request.HttpMethod;

            try
            {
                if (request.Headers["opensim-request-id"] != null)
                    reqnum = String.Format("{0}:{1}", request.RemoteIPEndPoint, request.Headers["opensim-request-id"]);
                // MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);

                //Fix the current Culture
                Culture.SetCurrentCulture();

                //response.KeepAlive = true;
                response.SendChunked = false;

                IRequestHandler requestHandler;

                string path = request.RawUrl;
                string handlerKey = GetHandlerKey(request.HttpMethod, path);

                //                MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);

                if (TryGetStreamHandler(handlerKey, out requestHandler))
                {
                    //MainConsole.Instance.Debug("[BASE HTTP SERVER]: Found Stream Handler");
                    // Okay, so this is bad, but should be considered temporary until everything is IStreamHandler.
                    byte[] buffer;

                    response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.


                    if (requestHandler is IStreamedRequestHandler)
                    {
                        IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;

                        buffer = streamedRequestHandler.Handle(path, request.InputStream, request, response);
                    }
                    else if (requestHandler is IGenericHTTPHandler)
                    {
                        //MainConsole.Instance.Debug("[BASE HTTP SERVER]: Found Caps based HTTP Handler");
                        IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler;
                        Stream requestStream = request.InputStream;

                        Encoding encoding = Encoding.UTF8;
                        StreamReader reader = new StreamReader(requestStream, encoding);

                        string requestBody = reader.ReadToEnd();

                        reader.Close();
                        //requestStream.Close();

                        Hashtable keysvals = new Hashtable();
                        Hashtable headervals = new Hashtable();
                        //string host = String.Empty;

                        string[] querystringkeys = request.QueryString.AllKeys;
                        string[] rHeaders = request.Headers.AllKeys;


                        foreach (string queryname in querystringkeys)
                        {
                            keysvals.Add(queryname, request.QueryString[queryname]);
                        }

                        foreach (string headername in rHeaders)
                        {
                            //MainConsole.Instance.Warn("[HEADER]: " + headername + "=" + request.Headers[headername]);
                            headervals[headername] = request.Headers[headername];
                        }

                        //                        if (headervals.Contains("Host"))
                        //                        {
                        //                            host = (string)headervals["Host"];
                        //                        }

                        keysvals.Add("requestbody", requestBody);
                        keysvals.Add("headers", headervals);
                        if (keysvals.Contains("method"))
                        {
                            //MainConsole.Instance.Warn("[HTTP]: Contains Method");
                            //string method = (string)keysvals["method"];
                            //MainConsole.Instance.Warn("[HTTP]: " + requestBody);

                        }
                        DoHTTPGruntWork(HTTPRequestHandler.Handle(path, keysvals), response, request);
                        return;
                    }
                    else
                    {
                        IStreamHandler streamHandler = (IStreamHandler)requestHandler;

                        using (MemoryStream memoryStream = new MemoryStream())
                        {
                            streamHandler.Handle(path, request.InputStream, memoryStream, request, response);
                            memoryStream.Flush();
                            buffer = memoryStream.ToArray();
                        }
                    }

                    request.InputStream.Close();

                    // HTTP IN support. The script engine takes it from here
                    // Nothing to worry about for us.
                    //
                    if (buffer == null)
                        return;

                    if (!response.SendChunked)
                        response.ContentLength64 = buffer.LongLength;

                    try
                    {
                        response.OutputStream.Write(buffer, 0, buffer.Length);
                    }
                    catch (HttpListenerException)
                    {
                        MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
                    }
                    //
                    try
                    {
                        response.Send();
                    }
                    catch (SocketException e)
                    {
                        // This has to be here to prevent a Linux/Mono crash
                        MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                    }
                    catch (IOException e)
                    {
                        MainConsole.Instance.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                    }
                    response = null;
                    //This makes timeouts VERY bad if enabled
                    /*try
                    {
                        //Clean up after ourselves
                        response.OutputStream.Close();
                        response.FreeContext();
                    }
                    catch(Exception ex)
                    {
                        MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: ISSUE WITH CLEANUP {0}", ex.ToString());
                    }*/
                    return;
                }

                if (request.AcceptTypes != null && request.AcceptTypes.Length > 0)
                {
#if (!ISWIN)
                    foreach (string strAccept in request.AcceptTypes)
                    {
                        if (strAccept.Contains("application/llsd+xml") || strAccept.Contains("application/llsd+json"))
                        {
                            HandleLLSDRequests(request, response);
                            return;
                        }
                    }
#else
                    if (request.AcceptTypes.Any(strAccept => strAccept.Contains("application/llsd+xml") ||
                                                             strAccept.Contains("application/llsd+json")))
                    {
                        HandleLLSDRequests(request, response);
                        return;
                    }
#endif
                }

                switch (request.ContentType)
                {
                    case null:
                    case "text/html":
                    case "application/x-www-form-urlencoded":
                        //                        MainConsole.Instance.DebugFormat(
                        //                            "[BASE HTTP SERVER]: Found a text/html content type for request {0}", request.RawUrl);
                        HandleHTTPRequest(request, response);
                        return;

                    case "application/llsd+xml":
                    case "application/xml+llsd":
                    case "application/llsd+json":
                        //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: found a application/llsd+xml content type");
                        HandleLLSDRequests(request, response);
                        return;

                    case "text/xml":
                    case "application/xml":
                    case "application/json":
                    default:
                        //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: in default handler");
                        // Point of note..  the DoWeHaveA methods check for an EXACT path
                        //                        if (request.RawUrl.Contains("/CAPS/EQG"))
                        //                        {
                        //                            int i = 1;
                        //                        }
                        //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
                        if (DoWeHaveALLSDHandler(request.RawUrl))
                        {
                            //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: Found LLSD Handler");
                            HandleLLSDRequests(request, response);
                            return;
                        }

                        //                        MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
                        if (DoWeHaveAHTTPHandler(request.RawUrl))
                        {
                            //                            MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: Found HTTP Handler for request {0}", request.RawUrl);
                            HandleHTTPRequest(request, response);
                            return;
                        }

                        //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: Generic XMLRPC");
                        // generic login request.
                        if (!HandleXmlRpcRequests(request, response))
                        {
                            SendHTML404(response, "");
                        }

                        return;
                }
            }
            catch (SocketException e)
            {
                // At least on linux, it appears that if the client makes a request without requiring the response,
                // an unconnected socket exception is thrown when we close the response output stream.  There's no
                // obvious way to tell if the client didn't require the response, so instead we'll catch and ignore
                // the exception instead.
                //
                // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
                // with the minimum first
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux", e);
            }
            catch (IOException)
            {
                MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw ");
            }
            catch (Exception e)
            {
                MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: HandleRequest() threw {0}", e);
                SendHTML500(response);
            }
            finally
            {
                int tickdiff = Environment.TickCount - tickstart;
                if (MainConsole.Instance.IsEnabled(log4net.Core.Level.Trace))
                    MainConsole.Instance.TraceFormat("[BASE HTTP SERVER]: request for {0} on port {3}, {2} took {1} ms", RawUrl, tickdiff, HTTPMethod, Port);
                // Every month or so this will wrap and give bad numbers, not really a problem
                // since its just for reporting, 500ms limit can be adjusted
                if (tickdiff > 500)
                    MainConsole.Instance.InfoFormat("[BASE HTTP SERVER]: slow request <{0}> for {1},{3} took {2} ms", reqnum, RawUrl, tickdiff, HTTPMethod);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        ///   Get the user's display name, currently not used?
        /// </summary>
        /// <param name = "mDhttpMethod"></param>
        /// <param name = "agentID"></param>
        /// <returns></returns>
        private byte[] ProcessGetDisplayName(string path, Stream request, OSHttpRequest httpRequest,
                                             OSHttpResponse httpResponse)
        {
            //I've never seen this come in, so for now... do nothing
            NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
            string[] ids = query.GetValues("ids");
            string username = query.GetOne("username");

            OSDMap map = new OSDMap();
            OSDArray agents = new OSDArray();
            OSDArray bad_ids = new OSDArray();
            OSDArray bad_usernames = new OSDArray();

            if (ids != null)
            {
                foreach (string id in ids)
                {
                    UserAccount account = m_userService.GetUserAccount(UUID.Zero, UUID.Parse(id));
                    if (account != null)
                    {
                        IUserProfileInfo info =
                            DataManager.RequestPlugin<IProfileConnector>().GetUserProfile(account.PrincipalID);
                        if (info != null)
                            PackUserInfo(info, account, ref agents);
                        else
                            PackUserInfo(info, account, ref agents);
                        //else //Technically is right, but needs to be packed no matter what for OS based grids
                        //    bad_ids.Add (id);
                    }
                }
            }
            else if (username != null)
            {
                UserAccount account = m_userService.GetUserAccount(UUID.Zero, username.Replace('.', ' '));
                if (account != null)
                {
                    IUserProfileInfo info =
                        DataManager.RequestPlugin<IProfileConnector>().GetUserProfile(account.PrincipalID);
                    if (info != null)
                        PackUserInfo(info, account, ref agents);
                    else
                        bad_usernames.Add(username);
                }
            }

            map["agents"] = agents;
            map["bad_ids"] = bad_ids;
            map["bad_usernames"] = bad_usernames;

            byte[] m = OSDParser.SerializeLLSDXmlBytes(map);
            httpResponse.Body.Write(m, 0, m.Length);
            httpResponse.StatusCode = (int) HttpStatusCode.OK;
            httpResponse.Send();
            return null;
        }
Ejemplo n.º 6
0
        internal void DoHTTPGruntWork(Hashtable responsedata, OSHttpResponse response, OSHttpRequest request)
        {
            //MainConsole.Instance.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
            byte[] buffer;
            if (responsedata.Count == 0)
            {
                response.StatusCode = 404;
                buffer = Encoding.UTF8.GetBytes("404");
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.OutputStream.Close();
                return;
            }
            int responsecode = (int)responsedata["int_response_code"];
            string responseString = (string)responsedata["str_response_string"];
            string contentType = (string)responsedata["content_type"];


            if (responsedata.ContainsKey("error_status_text"))
            {
                response.StatusDescription = (string)responsedata["error_status_text"];
            }
            if (responsedata.ContainsKey("http_protocol_version"))
            {
                response.ProtocolVersion = (string)responsedata["http_protocol_version"];
            }

            if (responsedata.ContainsKey("keepalive"))
            {
                bool keepalive = (bool)responsedata["keepalive"];
                response.KeepAlive = keepalive;

            }

            if (responsedata.ContainsKey("reusecontext"))
                response.ReuseContext = (bool)responsedata["reusecontext"];

            //Even though only one other part of the entire code uses HTTPHandlers, we shouldn't expect this
            //and should check for NullReferenceExceptions

            if (string.IsNullOrEmpty(contentType))
            {
                contentType = "text/html";
            }

            // The client ignores anything but 200 here for web login, so ensure that this is 200 for that

            response.StatusCode = responsecode;

            if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently)
            {
                response.RedirectLocation = (string)responsedata["str_redirect_location"];
                response.StatusCode = responsecode;
            }

            response.AddHeader("Content-Type", contentType);


            if (!(contentType.Contains("image")
                || contentType.Contains("x-shockwave-flash")
                || contentType.Contains("application/x-oar")
                || contentType.Contains("application/vnd.ll.mesh")))
            {
                // Text
                buffer = Encoding.UTF8.GetBytes(responseString);
            }
            else
            {
                // Binary!
                buffer = Convert.FromBase64String(responseString);
            }

            bool sendBuffer = true;

            string ETag = Util.SHA1Hash(buffer.ToString());
            response.AddHeader("ETag", ETag);
            List<string> rHeaders = request.Headers.AllKeys.ToList<string>();
            if (rHeaders.Contains("if-none-match") && request.Headers["if-none-match"].IndexOf(ETag) >= 0)
            {
                response.StatusCode = 304;
                response.StatusDescription = "Not Modified";
                sendBuffer = false;
            }


            try
            {
                if (sendBuffer)
                {
                    response.SendChunked = false;
                    response.ContentLength64 = buffer.Length;
                    response.ContentEncoding = Encoding.UTF8;
                    response.OutputStream.Write(buffer, 0, buffer.Length);
                }
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[HTTPD]: Error - " + ex);
            }
            finally
            {
                //response.OutputStream.Close();
                try
                {
                    response.OutputStream.Flush();
                    response.Send();

                    //if (!response.KeepAlive && response.ReuseContext)
                    //    response.FreeContext();
                }
                catch (SocketException e)
                {
                    // This has to be here to prevent a Linux/Mono crash
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                }
                catch (IOException e)
                {
                    MainConsole.Instance.Warn("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                }
                catch (Exception e)
                {
                    MainConsole.Instance.Warn("[BASE HTTP SERVER]: New Error in HTTP Server sending: " + e);
                }
            }
        }
Ejemplo n.º 7
0
        private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
        {
            //MainConsole.Instance.DebugFormat("[GETTEXTURE]: called in {0}", m_scene.RegionInfo.RegionName);

            // Try to parse the texture ID from the request URL
            NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
            string textureStr = query.GetOne("texture_id");
            string format = query.GetOne("format");

            if (m_assetService == null)
            {
                httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
                return null;
            }

            UUID textureID;
            if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
            {
                string[] formats;
                if (!string.IsNullOrEmpty(format))
                {
                    formats = new[] { format.ToLower() };
                }
                else
                {
                    formats = WebUtils.GetPreferredImageTypes(httpRequest.Headers.Get("Accept"));
                    if (formats.Length == 0)
                        formats = new[] { DefaultFormat }; // default
                }
                // OK, we have an array with preferred formats, possibly with only one entry
                httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound;
                foreach (string f in formats)
                {
                    if (FetchTexture(httpRequest, httpResponse, textureID, f))
                        break;
                }
            }
            else
            {
                MainConsole.Instance.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url);
            }

            httpResponse.Send();
            httpRequest.InputStream.Close();
            httpRequest = null;
            return null;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// This methods is the start of incoming HTTP request handling.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        public virtual void HandleRequest(OSHttpRequest request, OSHttpResponse response)
        {
            if (request.HttpMethod == String.Empty) // Can't handle empty requests, not wasting a thread
            {
                try
                {
                    SendHTML500(response);
                }
                catch
                {
                }

                return;
            }

            string requestMethod = request.HttpMethod;
            string uriString = request.RawUrl;

            int requestStartTick = Environment.TickCount;

            // Will be adjusted later on.
            int requestEndTick = requestStartTick;

            IStreamedRequestHandler requestHandler = null;

            try
            {
                // OpenSim.Framework.WebUtil.OSHeaderRequestID
                //                if (request.Headers["opensim-request-id"] != null)
                //                    reqnum = String.Format("{0}:{1}",request.RemoteIPEndPoint,request.Headers["opensim-request-id"]);
                //MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: <{0}> handle request for {1}",reqnum,request.RawUrl);

                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US", true);

                //                //  This is the REST agent interface. We require an agent to properly identify
                //                //  itself. If the REST handler recognizes the prefix it will attempt to
                //                //  satisfy the request. If it is not recognizable, and no damage has occurred
                //                //  the request can be passed through to the other handlers. This is a low
                //                //  probability event; if a request is matched it is normally expected to be
                //                //  handled
                //                IHttpAgentHandler agentHandler;
                //
                //                if (TryGetAgentHandler(request, response, out agentHandler))
                //                {
                //                    if (HandleAgentRequest(agentHandler, request, response))
                //                    {
                //                        requestEndTick = Environment.TickCount;
                //                        return;
                //                    }
                //                }

                //response.KeepAlive = true;
                response.SendChunked = false;

                string path = request.RawUrl;
                string handlerKey = GetHandlerKey(request.HttpMethod, path);
                byte[] buffer = null;

                if (TryGetStreamHandler(handlerKey, out requestHandler))
                {
                    if (DebugLevel >= 3)
                        LogIncomingToStreamHandler(request, requestHandler);

                    response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.

                    buffer = requestHandler.Handle(path, request.InputStream, request, response);
                }
                else
                {
                    switch (request.ContentType)
                    {
                        case null:
                        case "text/html":
                            if (DebugLevel >= 3)
                                LogIncomingToContentTypeHandler(request);

                            buffer = HandleHTTPRequest(request, response);
                            break;

                        case "application/llsd+xml":
                        case "application/xml+llsd":
                        case "application/llsd+json":
                            if (DebugLevel >= 3)
                                LogIncomingToContentTypeHandler(request);

                            buffer = HandleLLSDRequests(request, response);
                            break;

                        case "text/xml":
                        case "application/xml":
                        case "application/json":
                        default:
                            //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: in default handler");
                            // Point of note..  the DoWeHaveA methods check for an EXACT path
                            //                        if (request.RawUrl.Contains("/CAPS/EQG"))
                            //                        {
                            //                            int i = 1;
                            //                        }
                            //MainConsole.Instance.Info("[Debug BASE HTTP SERVER]: Checking for LLSD Handler");
                            if (DoWeHaveALLSDHandler(request.RawUrl))
                            {
                                if (DebugLevel >= 3)
                                    LogIncomingToContentTypeHandler(request);

                                buffer = HandleLLSDRequests(request, response);
                            }
                            else if (GetXmlRPCHandler(request.RawUrl) != null)
                            {
                                if (DebugLevel >= 3)
                                    LogIncomingToXmlRpcHandler(request);

                                // generic login request.
                                buffer = HandleXmlRpcRequests(request, response);
                            }
                            //                        MainConsole.Instance.DebugFormat("[BASE HTTP SERVER]: Checking for HTTP Handler for request {0}", request.RawUrl);
                            else if (DoWeHaveAHTTPHandler(request.RawUrl))
                            {
                                if (DebugLevel >= 3)
                                    LogIncomingToContentTypeHandler(request);

                                buffer = HandleHTTPRequest(request, response);
                            }
                            else
                            {
                                if (DebugLevel >= 3)
                                    LogIncomingToXmlRpcHandler(request);

                                // generic login request.
                                buffer = HandleXmlRpcRequests(request, response);
                            }

                            break;
                    }
                }

                request.InputStream.Close();

                if (buffer != null)
                {
                    if (!response.SendChunked)
                        response.ContentLength64 = buffer.LongLength;

                    response.OutputStream.Write(buffer, 0, buffer.Length);
                }

                // Do not include the time taken to actually send the response to the caller in the measurement
                // time.  This is to avoid logging when it's the client that is slow to process rather than the
                // server
                requestEndTick = Environment.TickCount;

                response.Send();

                //response.OutputStream.Close();

                //response.FreeContext();
            }
            catch (SocketException e)
            {
                // At least on linux, it appears that if the client makes a request without requiring the response,
                // an unconnected socket exception is thrown when we close the response output stream.  There's no
                // obvious way to tell if the client didn't require the response, so instead we'll catch and ignore
                // the exception instead.
                //
                // An alternative may be to turn off all response write exceptions on the HttpListener, but let's go
                // with the minimum first
                MainConsole.Instance.Warn(String.Format("[BASE HTTP SERVER]: HandleRequest threw {0}.\nNOTE: this may be spurious on Linux ", e.Message), e);
            }
            catch (IOException e)
            {
                MainConsole.Instance.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
            }
            catch (Exception e)
            {
                MainConsole.Instance.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
                SendHTML500(response);
            }
            finally
            {
                // Every month or so this will wrap and give bad numbers, not really a problem
                // since its just for reporting
                int tickdiff = requestEndTick - requestStartTick;
                if (tickdiff > 3000 && requestHandler != null)
                {
                    MainConsole.Instance.InfoFormat(
                        "[BASE HTTP SERVER]: Slow handling of {0} {1} from {2} took {3}ms",
                        requestMethod,
                        uriString,
                        request.RemoteIPEndPoint,
                        tickdiff);
                }
                else if (DebugLevel >= 4)
                {
                    MainConsole.Instance.DebugFormat(
                        "[BASE HTTP SERVER]: HTTP IN :{0} took {1}ms",
                        Port,
                        tickdiff);
                }
            }
        }
Ejemplo n.º 9
0
        internal void SendGenericHTTPResponse(Hashtable responsedata, OSHttpResponse response, OSHttpRequest request)
        {
            //MainConsole.Instance.Info("[BASE HTTP SERVER]: Doing HTTP Grunt work with response");
            byte[] buffer;
            if (responsedata.Count == 0)
            {
                response.StatusCode = (int)HttpStatusCode.NotFound;
                buffer = Encoding.UTF8.GetBytes("404");
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Send();
                return;
            }

            int responsecode = (int)responsedata["int_response_code"];
            string responseString = (string)responsedata["str_response_string"];
            string contentType = (string)responsedata["content_type"];

            if (responsedata.ContainsKey("error_status_text"))
                response.StatusDescription = (string)responsedata["error_status_text"];

            if (responsedata.ContainsKey("keepalive"))
                response.KeepAlive = (bool)responsedata["keepalive"];

            response.ContentType = string.IsNullOrEmpty(contentType) ? "text/html" : contentType;

            response.StatusCode = responsecode;

            if (responsecode == (int)OSHttpStatusCode.RedirectMovedPermanently)
            {
                response.RedirectLocation = (string)responsedata["str_redirect_location"];
                response.StatusCode = responsecode;
            }

            if (contentType != null && !(contentType.Contains("image")
                                         || contentType.Contains("x-shockwave-flash")
                                         || contentType.Contains("application/x-oar")
                                         || contentType.Contains("application/vnd.ll.mesh")))
            {
                // Text
                buffer = Encoding.UTF8.GetBytes(responseString);
            }
            else
            {
                // Binary!
                buffer = Convert.FromBase64String(responseString);
            }

            bool sendBuffer = true;

            string ETag = Util.SHA1Hash(buffer.ToString());
            response.AddHeader("ETag", ETag);
            List<string> rHeaders = request.Headers.AllKeys.ToList();
            if (rHeaders.Contains("if-none-match") && request.Headers["if-none-match"].IndexOf(ETag) >= 0)
            {
                response.StatusCode = 304;
                response.StatusDescription = "Not Modified";
                sendBuffer = false;
            }


            try
            {
                if (sendBuffer)
                {
                    response.ContentEncoding = Encoding.UTF8;
                    response.OutputStream.Write(buffer, 0, buffer.Length);
                }
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[HTTPD]: Error - " + ex);
            }
            finally
            {
                try
                {
                    response.Send();
                }
                catch (SocketException e)
                {
                    // This has to be here to prevent a Linux/Mono crash
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                }
                catch (IOException e)
                {
                    MainConsole.Instance.Debug("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                }
            }
        }
Ejemplo n.º 10
0
        private void HandleLLSDRequests(OSHttpRequest request, OSHttpResponse response)
        {
            string requestBody;
            using(StreamReader reader = new StreamReader(request.InputStream, Encoding.UTF8))
                requestBody = reader.ReadToEnd();

            response.KeepAlive = true;
            response.ContentEncoding = Encoding.UTF8;

            OSD llsdRequest = null, llsdResponse = null;

            bool LegacyLLSDLoginLibOMV = (requestBody.Contains("passwd") && requestBody.Contains("mac") && requestBody.Contains("viewer_digest"));

            if (requestBody.Length == 0)
                requestBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><llsd><map><key>request</key><string>get</string></map></llsd>";

            try
            {
                llsdRequest = OSDParser.Deserialize(requestBody);
            }
            catch (Exception ex)
            {
                MainConsole.Instance.Warn("[BASE HTTP SERVER]: Error - " + ex);
            }

            if (llsdRequest != null)
            {
                LLSDMethod llsdhandler = null;
                if (_server.TryGetLLSDHandler(request.RawUrl, out llsdhandler) && !LegacyLLSDLoginLibOMV)
                {
                    // we found a registered llsd handler to service this request
                    llsdResponse = llsdhandler(request.RawUrl, llsdRequest, request.RemoteIPEndPoint);
                }
                else
                {
                    // we didn't find a registered llsd handler to service this request
                    // .. give em the failed message
                    llsdResponse = GenerateNoLLSDHandlerResponse();
                }
            }
            else
                llsdResponse = GenerateNoLLSDHandlerResponse();

            byte[] buffer = new byte[0];
            if (llsdResponse.ToString() == "shutdown404!")
            {
                response.ContentType = "text/plain";
                response.StatusCode = (int)HttpStatusCode.NotFound;
                response.StatusDescription = "Not Found";
                buffer = Encoding.UTF8.GetBytes("Not found");
            }
            else
            {
                // Select an appropriate response format
                buffer = BuildLLSDResponse(request, response, llsdResponse);
            }

            try
            {
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Send();
            }
            catch (IOException e)
            {
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: LLSD IOException {0}.", e);
            }
            catch (SocketException e)
            {
                // This has to be here to prevent a Linux/Mono crash
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: LLSD issue {0}.\nNOTE: this may be spurious on Linux.", e);
            }
        }
Ejemplo n.º 11
0
        private static void HandleStreamHandler(OSHttpRequest request, OSHttpResponse response, string path, ref int respcontentLength, IStreamedRequestHandler requestHandler)
        {
            byte[] buffer = null;
            response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
            
            try
            {
                IStreamedRequestHandler streamedRequestHandler = requestHandler as IStreamedRequestHandler;
                buffer = streamedRequestHandler.Handle(path, request.InputStream, request, response);
            }
            catch (Exception ex)
            {
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: HTTP handler threw an exception " + ex + ".");
            }

            if (request.InputStream != null)
                request.InputStream.Dispose();

            if (buffer == null)
            {
                if (response.OutputStream.CanWrite)
                {
                    response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    buffer = Encoding.UTF8.GetBytes("Internal Server Error");
                }
                else
                    return;//The handler took care of sending it for us
            }
            else if (buffer == MainServer.BadRequest)
            {
                response.StatusCode = (int)HttpStatusCode.BadRequest;
                buffer = Encoding.UTF8.GetBytes("Bad Request");
            }

            respcontentLength = buffer.Length;
            try
            {
                if (buffer != MainServer.NoResponse)
                    response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Send();
            }
            catch (SocketException e)
            {
                // This has to be here to prevent a Linux/Mono crash
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
            }
            catch (HttpListenerException)
            {
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: HTTP request abnormally terminated.");
            }
            catch (IOException e)
            {
                MainConsole.Instance.Debug("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
            }
            finally
            {
                buffer = null;
            }
        }
Ejemplo n.º 12
0
        private void SendHTML500(OSHttpResponse response)
        {
            // I know this statuscode is dumb, but the client/MSIE doesn't respond to 404s and 500s
            response.StatusCode = (int)HttpStatusCode.OK;
            response.AddHeader("Content-type", "text/html");

            byte[] buffer = Encoding.UTF8.GetBytes(GetHTTP500());

            response.ContentEncoding = Encoding.UTF8;
            try
            {
                response.OutputStream.Write(buffer, 0, buffer.Length);
                response.Send();
            }
            catch (SocketException e)
            {
                // This has to be here to prevent a Linux/Mono crash
                MainConsole.Instance.WarnFormat("[BASE HTTP SERVER] XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
        /// Sends back an XMLRPC unknown request response if no handler is registered for the requested method.
        /// </summary>
        /// <param name="request"></param>
        /// <param name="response"></param>
        private bool HandleXmlRpcRequests(OSHttpRequest request, OSHttpResponse response)
        {
            XmlRpcRequest xmlRprcRequest = null;
            string requestBody;

            using (StreamReader reader = new StreamReader(request.InputStream, Encoding.UTF8))
                requestBody = reader.ReadToEnd();

            requestBody = requestBody.Replace("<base64></base64>", "");

            try
            {
                if (requestBody.StartsWith("<?xml"))
                    xmlRprcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
            }
            catch (XmlException)
            {
            }

            if (xmlRprcRequest != null)
            {
                string methodName = xmlRprcRequest.MethodName;
                byte[] buf;
                if (methodName != null)
                {
                    xmlRprcRequest.Params.Add(request.RemoteIPEndPoint);
                    XmlRpcResponse xmlRpcResponse;
                    XmlRpcMethod method;

                    if (_server.TryGetXMLHandler(methodName, out method))
                    {
                        xmlRprcRequest.Params.Add(request.Url); // Param[2]
                        xmlRprcRequest.Params.Add(request.Headers.Get("X-Forwarded-For")); // Param[3]

                        try
                        {
                            xmlRpcResponse = method(xmlRprcRequest, request.RemoteIPEndPoint);
                        }
                        catch (Exception e)
                        {
                            MainConsole.Instance.ErrorFormat("[BASE HTTP SERVER]: Requested method [{0}] from {1} threw exception: {2} {3}",
                                    methodName, request.RemoteIPEndPoint.Address, e, e.StackTrace);

                            // if the registered XmlRpc method threw an exception, we pass a fault-code along
                            xmlRpcResponse = new XmlRpcResponse();

                            // Code probably set in accordance with http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
                            xmlRpcResponse.SetFault(-32603, string.Format("Requested method [{0}] from {1} threw exception: {2} {3}",
                                    methodName, request.RemoteIPEndPoint.Address, e, e.StackTrace));
                        }

                        // if the method wasn't found, we can't determine KeepAlive state anyway, so lets do it only here
                        response.KeepAlive = _server.GetXMLHandlerIsKeepAlive(methodName);
                    }
                    else
                    {
                        xmlRpcResponse = new XmlRpcResponse();

                        // Code set in accordance with http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
                        xmlRpcResponse.SetFault(
                            XmlRpcErrorCodes.SERVER_ERROR_METHOD,
                            String.Format("Requested method [{0}] not found", methodName));
                    }

                    buf = Encoding.UTF8.GetBytes(XmlRpcResponseSerializer.Singleton.Serialize(xmlRpcResponse));
                    response.ContentType = "text/xml";
                }
                else
                {
                    response.ContentType = "text/plain";
                    response.StatusCode = (int)HttpStatusCode.NotFound;
                    response.StatusDescription = "Not Found";
                    buf = Encoding.UTF8.GetBytes("Not found");
                    response.ContentEncoding = Encoding.UTF8;
                }

                try
                {
                    response.OutputStream.Write(buf, 0, buf.Length);
                    response.Send();
                }
                catch (SocketException e)
                {
                    // This has to be here to prevent a Linux/Mono crash
                    MainConsole.Instance.WarnFormat("[BASE HTTP SERVER]: XmlRpcRequest issue {0}.\nNOTE: this may be spurious on Linux.", e);
                }
                catch (IOException e)
                {
                    MainConsole.Instance.Debug("[BASE HTTP SERVER]: XmlRpcRequest issue: " + e);
                }
                return true;
            }

            return false;
        }
Ejemplo n.º 14
0
        /// <summary>
        /// FIXME: This should be part of BaseHttpServer
        /// </summary>
        internal static void DoHTTPGruntWork(BaseHttpServer server, PollServiceHttpRequest req, Hashtable responsedata)
        {
            OSHttpResponse response
                = new OSHttpResponse(new HttpResponse(req.HttpContext, req.Request), req.HttpContext);

            byte[] buffer = server.DoHTTPGruntWork(responsedata, response);

            response.SendChunked = false;
            response.ContentLength64 = buffer.Length;
            response.ContentEncoding = Encoding.UTF8;

            try
            {
                response.OutputStream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                m_log.Warn(string.Format("[POLL SERVICE WORKER THREAD]: Error ", ex));
            }
            finally
            {
                //response.OutputStream.Close();
                try
                {
                    response.OutputStream.Flush();
                    response.Send();

                    //if (!response.KeepAlive && response.ReuseContext)
                    //    response.FreeContext();
                }
                catch (Exception e)
                {
                    m_log.Warn(String.Format("[POLL SERVICE WORKER THREAD]: Error ", e));
                }
            }
        }
Ejemplo n.º 15
0
        private byte[] ProcessAvatarPickerSearch(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
        {
            NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
            string amt = query.GetOne("page-size");
            string name = query.GetOne("names");
            List<UserAccount> accounts = m_service.Registry.RequestModuleInterface<IUserAccountService>().GetUserAccounts(UUID.Zero, name) ??
                                         new List<UserAccount>(0);

            OSDMap body = new OSDMap();
            OSDArray array = new OSDArray();
            foreach (UserAccount account in accounts)
            {
                OSDMap map = new OSDMap();
                map["agent_id"] = account.PrincipalID;
                IUserProfileInfo profileInfo = DataManager.RequestPlugin<IProfileConnector>().GetUserProfile(account.PrincipalID);
                map["display_name"] = (profileInfo == null || profileInfo.DisplayName == "") ? account.Name : profileInfo.DisplayName;
                map["username"] = account.Name;
                array.Add(map);
            }

            body["agents"] = array;
            byte[] m = OSDParser.SerializeLLSDXmlBytes(body);
            httpResponse.Body.Write(m, 0, m.Length);
            httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK;
            httpResponse.Send();
            return null;
        }