From 9688db2f687b04623fa61580307da35f90df9d4c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 8 May 2011 20:20:00 +0100 Subject: Enable compressed (gzip) fatpack transfers. --- .../Server/Handlers/Simulation/AgentHandlers.cs | 299 +++++++++++++-------- .../Simulation/SimulationServiceInConnector.cs | 23 +- 2 files changed, 191 insertions(+), 131 deletions(-) (limited to 'OpenSim/Server/Handlers/Simulation') diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 8b6fb4f..d52750b 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.IO; +using System.IO.Compression; using System.Reflection; using System.Net; using System.Text; @@ -53,8 +54,6 @@ namespace OpenSim.Server.Handlers.Simulation private ISimulationService m_SimulationService; - protected bool m_Proxy = false; - public AgentHandler() { } public AgentHandler(ISimulationService sim) @@ -91,16 +90,12 @@ namespace OpenSim.Server.Handlers.Simulation // Next, let's parse the verb string method = (string)request["http-method"]; + m_log.DebugFormat("[SIMULATION]: Got verb {0} in HTTP handler", method); if (method.Equals("PUT")) { DoAgentPut(request, responsedata); return responsedata; } - else if (method.Equals("POST")) - { - DoAgentPost(request, responsedata, agentID); - return responsedata; - } else if (method.Equals("GET")) { DoAgentGet(request, responsedata, agentID, regionID); @@ -127,111 +122,6 @@ namespace OpenSim.Server.Handlers.Simulation } - protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) - { - OSDMap args = Utils.GetOSDMap((string)request["body"]); - if (args == null) - { - responsedata["int_response_code"] = HttpStatusCode.BadRequest; - responsedata["str_response_string"] = "Bad request"; - return; - } - - // retrieve the input arguments - int x = 0, y = 0; - UUID uuid = UUID.Zero; - string regionname = string.Empty; - uint teleportFlags = 0; - if (args.ContainsKey("destination_x") && args["destination_x"] != null) - Int32.TryParse(args["destination_x"].AsString(), out x); - else - m_log.WarnFormat(" -- request didn't have destination_x"); - if (args.ContainsKey("destination_y") && args["destination_y"] != null) - Int32.TryParse(args["destination_y"].AsString(), out y); - else - m_log.WarnFormat(" -- request didn't have destination_y"); - if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) - UUID.TryParse(args["destination_uuid"].AsString(), out uuid); - if (args.ContainsKey("destination_name") && args["destination_name"] != null) - regionname = args["destination_name"].ToString(); - if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) - teleportFlags = args["teleport_flags"].AsUInteger(); - - GridRegion destination = new GridRegion(); - destination.RegionID = uuid; - destination.RegionLocX = x; - destination.RegionLocY = y; - destination.RegionName = regionname; - - AgentCircuitData aCircuit = new AgentCircuitData(); - try - { - aCircuit.UnpackAgentCircuitData(args); - } - catch (Exception ex) - { - m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message); - responsedata["int_response_code"] = HttpStatusCode.BadRequest; - responsedata["str_response_string"] = "Bad request"; - return; - } - - OSDMap resp = new OSDMap(2); - string reason = String.Empty; - - // This is the meaning of POST agent - //m_regionClient.AdjustUserInformation(aCircuit); - //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); - bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); - - resp["reason"] = OSD.FromString(reason); - resp["success"] = OSD.FromBoolean(result); - // Let's also send out the IP address of the caller back to the caller (HG 1.5) - resp["your_ip"] = OSD.FromString(GetCallerIP(request)); - - // TODO: add reason if not String.Empty? - responsedata["int_response_code"] = HttpStatusCode.OK; - responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); - } - - private string GetCallerIP(Hashtable request) - { - if (!m_Proxy) - return Util.GetCallerIP(request); - - // We're behind a proxy - Hashtable headers = (Hashtable)request["headers"]; - - //// DEBUG - //foreach (object o in headers.Keys) - // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); - - string xff = "X-Forwarded-For"; - if (headers.ContainsKey(xff.ToLower())) - xff = xff.ToLower(); - - if (!headers.ContainsKey(xff) || headers[xff] == null) - { - m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); - return Util.GetCallerIP(request); - } - - m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); - - IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); - if (ep != null) - return ep.Address.ToString(); - - // Oops - return Util.GetCallerIP(request); - } - - // subclasses can override this - protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) - { - return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); - } - protected void DoAgentPut(Hashtable request, Hashtable responsedata) { OSDMap args = Utils.GetOSDMap((string)request["body"]); @@ -434,4 +324,189 @@ namespace OpenSim.Server.Handlers.Simulation } + public class AgentPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private ISimulationService m_SimulationService; + protected bool m_Proxy = false; + + public AgentPostHandler(ISimulationService service) : + base("POST", "/agent") + { + m_SimulationService = service; + } + + public AgentPostHandler(string path) : + base("POST", path) + { + m_SimulationService = null; + } + + public override byte[] Handle(string path, Stream request, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + m_log.DebugFormat("[SIMULATION]: Stream handler called"); + + Hashtable keysvals = new Hashtable(); + Hashtable headervals = new Hashtable(); + + string[] querystringkeys = httpRequest.QueryString.AllKeys; + string[] rHeaders = httpRequest.Headers.AllKeys; + + keysvals.Add("uri", httpRequest.RawUrl); + keysvals.Add("content-type", httpRequest.ContentType); + keysvals.Add("http-method", httpRequest.HttpMethod); + + foreach (string queryname in querystringkeys) + keysvals.Add(queryname, httpRequest.QueryString[queryname]); + + foreach (string headername in rHeaders) + headervals[headername] = httpRequest.Headers[headername]; + + keysvals.Add("headers", headervals); + keysvals.Add("querystringkeys", querystringkeys); + + Stream inputStream; + if (httpRequest.ContentType == "application/x-gzip") + inputStream = new GZipStream(request, CompressionMode.Decompress); + else + inputStream = request; + + Encoding encoding = Encoding.UTF8; + StreamReader reader = new StreamReader(inputStream, encoding); + + string requestBody = reader.ReadToEnd(); + keysvals.Add("body", requestBody); + + httpResponse.StatusCode = 200; + httpResponse.ContentType = "text/html"; + httpResponse.KeepAlive = false; + + Hashtable responsedata = new Hashtable(); + + UUID agentID; + UUID regionID; + string action; + + if (!Utils.GetParams((string)keysvals["uri"], out agentID, out regionID, out action)) + { + m_log.InfoFormat("[AGENT HANDLER]: Invalid parameters for agent message {0}", keysvals["uri"]); + + httpResponse.StatusCode = 404; + + return encoding.GetBytes("false"); + } + + DoAgentPost(keysvals, responsedata, agentID); + + httpResponse.StatusCode = (int)responsedata["int_response_code"]; + return encoding.GetBytes((string)responsedata["str_response_string"]); + } + + protected void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) + { + OSDMap args = Utils.GetOSDMap((string)request["body"]); + if (args == null) + { + responsedata["int_response_code"] = HttpStatusCode.BadRequest; + responsedata["str_response_string"] = "Bad request"; + return; + } + + // retrieve the input arguments + int x = 0, y = 0; + UUID uuid = UUID.Zero; + string regionname = string.Empty; + uint teleportFlags = 0; + if (args.ContainsKey("destination_x") && args["destination_x"] != null) + Int32.TryParse(args["destination_x"].AsString(), out x); + else + m_log.WarnFormat(" -- request didn't have destination_x"); + if (args.ContainsKey("destination_y") && args["destination_y"] != null) + Int32.TryParse(args["destination_y"].AsString(), out y); + else + m_log.WarnFormat(" -- request didn't have destination_y"); + if (args.ContainsKey("destination_uuid") && args["destination_uuid"] != null) + UUID.TryParse(args["destination_uuid"].AsString(), out uuid); + if (args.ContainsKey("destination_name") && args["destination_name"] != null) + regionname = args["destination_name"].ToString(); + if (args.ContainsKey("teleport_flags") && args["teleport_flags"] != null) + teleportFlags = args["teleport_flags"].AsUInteger(); + + GridRegion destination = new GridRegion(); + destination.RegionID = uuid; + destination.RegionLocX = x; + destination.RegionLocY = y; + destination.RegionName = regionname; + + AgentCircuitData aCircuit = new AgentCircuitData(); + try + { + aCircuit.UnpackAgentCircuitData(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[AGENT HANDLER]: exception on unpacking ChildCreate message {0}", ex.Message); + responsedata["int_response_code"] = HttpStatusCode.BadRequest; + responsedata["str_response_string"] = "Bad request"; + return; + } + + OSDMap resp = new OSDMap(2); + string reason = String.Empty; + + // This is the meaning of POST agent + //m_regionClient.AdjustUserInformation(aCircuit); + //bool result = m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); + bool result = CreateAgent(destination, aCircuit, teleportFlags, out reason); + + resp["reason"] = OSD.FromString(reason); + resp["success"] = OSD.FromBoolean(result); + // Let's also send out the IP address of the caller back to the caller (HG 1.5) + resp["your_ip"] = OSD.FromString(GetCallerIP(request)); + + // TODO: add reason if not String.Empty? + responsedata["int_response_code"] = HttpStatusCode.OK; + responsedata["str_response_string"] = OSDParser.SerializeJsonString(resp); + } + + private string GetCallerIP(Hashtable request) + { + if (!m_Proxy) + return Util.GetCallerIP(request); + + // We're behind a proxy + Hashtable headers = (Hashtable)request["headers"]; + + //// DEBUG + //foreach (object o in headers.Keys) + // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); + + string xff = "X-Forwarded-For"; + if (headers.ContainsKey(xff.ToLower())) + xff = xff.ToLower(); + + if (!headers.ContainsKey(xff) || headers[xff] == null) + { + m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); + return Util.GetCallerIP(request); + } + + m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); + + IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); + if (ep != null) + return ep.Address.ToString(); + + // Oops + return Util.GetCallerIP(request); + } + + // subclasses can override this + protected virtual bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint teleportFlags, out string reason) + { + return m_SimulationService.CreateAgent(destination, aCircuit, teleportFlags, out reason); + } + } } diff --git a/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs index f33eda7..42d8eca 100644 --- a/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs +++ b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs @@ -43,30 +43,15 @@ namespace OpenSim.Server.Handlers.Simulation public SimulationServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) : base(config, server, String.Empty) { - //IConfig serverConfig = config.Configs["SimulationService"]; - //if (serverConfig == null) - // throw new Exception("No section 'SimulationService' in config file"); - - //string simService = serverConfig.GetString("LocalServiceModule", - // String.Empty); - - //if (simService == String.Empty) - // throw new Exception("No SimulationService in config file"); - - //Object[] args = new Object[] { config }; m_LocalSimulationService = scene.RequestModuleInterface(); m_LocalSimulationService = m_LocalSimulationService.GetInnerService(); - //ServerUtils.LoadPlugin(simService, args); - //System.Console.WriteLine("XXXXXXXXXXXXXXXXXXX m_AssetSetvice == null? " + ((m_AssetService == null) ? "yes" : "no")); - //server.AddStreamHandler(new AgentGetHandler(m_SimulationService, m_AuthenticationService)); - //server.AddStreamHandler(new AgentPostHandler(m_SimulationService, m_AuthenticationService)); - //server.AddStreamHandler(new AgentPutHandler(m_SimulationService, m_AuthenticationService)); - //server.AddStreamHandler(new AgentDeleteHandler(m_SimulationService, m_AuthenticationService)); + // This one MUST be a stream handler because compressed fatpacks + // are pure binary and shoehorning that into a string with UTF-8 + // encoding breaks it + server.AddStreamHandler(new AgentPostHandler(m_LocalSimulationService)); server.AddHTTPHandler("/agent/", new AgentHandler(m_LocalSimulationService).Handler); server.AddHTTPHandler("/object/", new ObjectHandler(m_LocalSimulationService).Handler); - - //server.AddStreamHandler(new ObjectPostHandler(m_SimulationService, authentication)); } } } -- cgit v1.1