Enable compressed (gzip) fatpack transfers.

bulletsim
Melanie 2011-05-08 20:20:00 +01:00
parent 1bdac6ed19
commit 9688db2f68
7 changed files with 244 additions and 149 deletions

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Reflection;
@ -142,20 +143,25 @@ namespace OpenSim.Framework
/// </summary>
public static OSDMap PutToService(string url, OSDMap data, int timeout)
{
return ServiceOSDRequest(url,data, "PUT", timeout);
return ServiceOSDRequest(url,data, "PUT", timeout, false);
}
public static OSDMap PostToService(string url, OSDMap data, int timeout)
{
return ServiceOSDRequest(url, data, "POST", timeout);
return ServiceOSDRequest(url, data, "POST", timeout, false);
}
public static OSDMap PostToServiceCompressed(string url, OSDMap data, int timeout)
{
return ServiceOSDRequest(url, data, "POST", timeout, true);
}
public static OSDMap GetFromService(string url, int timeout)
{
return ServiceOSDRequest(url, null, "GET", timeout);
return ServiceOSDRequest(url, null, "GET", timeout, false);
}
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout)
public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed)
{
int reqnum = m_requestNumber++;
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
@ -180,10 +186,31 @@ namespace OpenSim.Framework
string strBuffer = OSDParser.SerializeJsonString(data);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
request.ContentType = "application/json";
request.ContentLength = buffer.Length; //Count bytes to send
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(buffer, 0, buffer.Length); //Send it
if (compressed)
{
request.ContentType = "application/x-gzip";
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream comp = new GZipStream(ms, CompressionMode.Compress))
{
comp.Write(buffer, 0, buffer.Length);
comp.Flush();
ms.Seek(0, SeekOrigin.Begin);
request.ContentLength = ms.Length; //Count bytes to send
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(ms.ToArray(), 0, (int)ms.Length);
}
}
}
else
{
request.ContentType = "application/json";
request.ContentLength = buffer.Length; //Count bytes to send
using (Stream requestStream = request.GetRequestStream())
requestStream.Write(buffer, 0, buffer.Length); //Send it
}
}
// capture how much time was spent writing, this may seem silly

View File

@ -328,6 +328,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// Let's create an agent there if one doesn't exist yet.
bool logout = false;
sp.ControllingClient.SendTeleportProgress(teleportFlags | (uint)TeleportFlags.DisableCancel, "Creating agent...");
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
{
sp.ControllingClient.SendTeleportFailed(String.Format("Destination refused: {0}",

View File

@ -49,13 +49,13 @@ using log4net;
namespace OpenSim.Server.Handlers.Hypergrid
{
public class GatekeeperAgentHandler : OpenSim.Server.Handlers.Simulation.AgentHandler
public class GatekeeperAgentHandler : OpenSim.Server.Handlers.Simulation.AgentPostHandler
{
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IGatekeeperService m_GatekeeperService;
public GatekeeperAgentHandler(IGatekeeperService gatekeeper, bool proxy)
public GatekeeperAgentHandler(IGatekeeperService gatekeeper, bool proxy) : base("/foreignagent")
{
m_GatekeeperService = gatekeeper;
m_Proxy = proxy;
@ -65,7 +65,5 @@ namespace OpenSim.Server.Handlers.Hypergrid
{
return m_GatekeeperService.LoginAgent(aCircuit, destination, out reason);
}
}
}

View File

@ -73,7 +73,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
server.AddXmlRPCHandler("link_region", hghandlers.LinkRegionRequest, false);
server.AddXmlRPCHandler("get_region", hghandlers.GetRegion, false);
server.AddHTTPHandler("/foreignagent/", new GatekeeperAgentHandler(m_GatekeeperService, m_Proxy).Handler);
server.AddStreamHandler(new GatekeeperAgentHandler(m_GatekeeperService, m_Proxy));
}
public GatekeeperServiceInConnector(IConfigSource config, IHttpServer server)

View File

@ -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);
}
}
}

View File

@ -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<ISimulationService>();
m_LocalSimulationService = m_LocalSimulationService.GetInnerService();
//ServerUtils.LoadPlugin<ISimulationService>(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));
}
}
}

View File

@ -102,12 +102,21 @@ namespace OpenSim.Services.Connectors.Simulation
args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
args["teleport_flags"] = OSD.FromString(flags.ToString());
OSDMap result = WebUtil.PostToService(uri, args, 20000);
OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
if (result["Success"].AsBoolean())
return true;
result = WebUtil.PostToService(uri, args, 30000);
if (result["Success"].AsBoolean())
{
m_log.WarnFormat(
"[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
return true;
}
m_log.WarnFormat(
"[REMOTE SIMULATION CONNECTOR]: Failed to create agent {0} {1} at remote simulator {1}",
"[REMOTE SIMULATION CONNECTOR]: Failed to create agent {0} {1} at remote simulator {2}",
aCircuit.firstname, aCircuit.lastname, destination.RegionName);
reason = result["Message"] != null ? result["Message"].AsString() : "error";
return false;
@ -274,7 +283,7 @@ namespace OpenSim.Services.Connectors.Simulation
try
{
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000);
OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000, false);
bool success = result["success"].AsBoolean();
if (result.ContainsKey("_Result"))
{
@ -326,7 +335,7 @@ namespace OpenSim.Services.Connectors.Simulation
try
{
WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000);
WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false);
}
catch (Exception e)
{
@ -346,7 +355,7 @@ namespace OpenSim.Services.Connectors.Simulation
try
{
WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000);
WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false);
}
catch (Exception e)
{