diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs new file mode 100644 index 0000000000..1d455c6b8d --- /dev/null +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -0,0 +1,182 @@ +using System; +using System.IO; +using System.Reflection; +using System.Net; +using System.Text; + +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using Nini.Config; +using log4net; + + +namespace OpenSim.Server.Handlers.Simulation +{ + public class AgentGetHandler : BaseStreamHandler + { + private ISimulationService m_SimulationService; + private IAuthenticationService m_AuthenticationService; + + public AgentGetHandler(ISimulationService service, IAuthenticationService authentication) : + base("GET", "/agent") + { + m_SimulationService = service; + m_AuthenticationService = authentication; + } + + public override byte[] Handle(string path, Stream request, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // Not implemented yet + httpResponse.StatusCode = (int)HttpStatusCode.NotImplemented; + return new byte[] { }; + } + } + + public class AgentPostHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private ISimulationService m_SimulationService; + private IAuthenticationService m_AuthenticationService; + private bool m_AllowForeignGuests; + + public AgentPostHandler(ISimulationService service, IAuthenticationService authentication, bool foreignGuests) : + base("POST", "/agent") + { + m_SimulationService = service; + m_AuthenticationService = authentication; + m_AllowForeignGuests = foreignGuests; + } + + public override byte[] Handle(string path, Stream request, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + byte[] result = new byte[0]; + + UUID agentID; + string action; + ulong regionHandle; + if (!Utils.GetParams(path, out agentID, out regionHandle, out action)) + { + m_log.InfoFormat("[AgentPostHandler]: Invalid parameters for agent message {0}", path); + httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; + httpResponse.StatusDescription = "Invalid parameters for agent message " + path; + + return result; + } + + if (m_AuthenticationService != null) + { + // Authentication + string authority = string.Empty; + string authToken = string.Empty; + if (!Utils.GetAuthentication(httpRequest, out authority, out authToken)) + { + m_log.InfoFormat("[AgentPostHandler]: Authentication failed for agent message {0}", path); + httpResponse.StatusCode = (int)HttpStatusCode.Unauthorized; + return result; + } + if (!m_AuthenticationService.VerifyKey(agentID, authToken)) + { + m_log.InfoFormat("[AgentPostHandler]: Authentication failed for agent message {0}", path); + httpResponse.StatusCode = (int)HttpStatusCode.Forbidden; + return result; + } + m_log.DebugFormat("[AgentPostHandler]: Authentication succeeded for {0}", agentID); + } + + OSDMap args = Util.GetOSDMap(request, (int)httpRequest.ContentLength); + if (args == null) + { + httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; + httpResponse.StatusDescription = "Unable to retrieve data"; + m_log.DebugFormat("[AgentPostHandler]: Unable to retrieve data for post {0}", path); + return result; + } + + // retrieve the regionhandle + ulong regionhandle = 0; + if (args["destination_handle"] != null) + UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); + + AgentCircuitData aCircuit = new AgentCircuitData(); + try + { + aCircuit.UnpackAgentCircuitData(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[AgentPostHandler]: exception on unpacking CreateAgent message {0}", ex.Message); + httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; + httpResponse.StatusDescription = "Problems with data deserialization"; + return result; + } + + string reason = string.Empty; + + // We need to clean up a few things in the user service before I can do this + //if (m_AllowForeignGuests) + // m_regionClient.AdjustUserInformation(aCircuit); + + // Finally! + bool success = m_SimulationService.CreateAgent(regionhandle, aCircuit, out reason); + + OSDMap resp = new OSDMap(1); + + resp["success"] = OSD.FromBoolean(success); + + httpResponse.StatusCode = (int)HttpStatusCode.OK; + + return Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(resp)); + + } + } + + public class AgentPutHandler : BaseStreamHandler + { + private ISimulationService m_SimulationService; + private IAuthenticationService m_AuthenticationService; + + public AgentPutHandler(ISimulationService service, IAuthenticationService authentication) : + base("PUT", "/agent") + { + m_SimulationService = service; + m_AuthenticationService = authentication; + } + + public override byte[] Handle(string path, Stream request, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // Not implemented yet + httpResponse.StatusCode = (int)HttpStatusCode.NotImplemented; + return new byte[] { }; + } + } + + public class AgentDeleteHandler : BaseStreamHandler + { + private ISimulationService m_SimulationService; + private IAuthenticationService m_AuthenticationService; + + public AgentDeleteHandler(ISimulationService service, IAuthenticationService authentication) : + base("DELETE", "/agent") + { + m_SimulationService = service; + m_AuthenticationService = authentication; + } + + public override byte[] Handle(string path, Stream request, + OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // Not implemented yet + httpResponse.StatusCode = (int)HttpStatusCode.NotImplemented; + return new byte[] { }; + } + } + +} diff --git a/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs new file mode 100644 index 0000000000..80b22b0602 --- /dev/null +++ b/OpenSim/Server/Handlers/Simulation/SimulationServiceInConnector.cs @@ -0,0 +1,53 @@ +using System; +using Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; + +namespace OpenSim.Server.Handlers.Simulation +{ + public class SimulationServiceInConnector : ServiceConnector + { + private ISimulationService m_SimulationService; + private IAuthenticationService m_AuthenticationService; + + public SimulationServiceInConnector(IConfigSource config, IHttpServer server, IScene scene) : + base(config, server) + { + IConfig serverConfig = config.Configs["SimulationService"]; + if (serverConfig == null) + throw new Exception("No section 'SimulationService' in config file"); + + bool authentication = serverConfig.GetBoolean("RequireAuthentication", false); + + if (authentication) + m_AuthenticationService = scene.RequestModuleInterface(); + + bool foreignGuests = serverConfig.GetBoolean("AllowForeignGuests", false); + + //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_SimulationService = scene.RequestModuleInterface(); + //ServerUtils.LoadPlugin(simService, args); + if (m_SimulationService == null) + throw new Exception("No Local ISimulationService Module"); + + + + //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, foreignGuests)); + server.AddStreamHandler(new AgentPutHandler(m_SimulationService, m_AuthenticationService)); + server.AddStreamHandler(new AgentDeleteHandler(m_SimulationService, m_AuthenticationService)); + //server.AddStreamHandler(new ObjectPostHandler(m_SimulationService, authentication)); + //server.AddStreamHandler(new NeighborPostHandler(m_SimulationService, authentication)); + } + } +} diff --git a/OpenSim/Server/Handlers/Simulation/Utils.cs b/OpenSim/Server/Handlers/Simulation/Utils.cs new file mode 100644 index 0000000000..581622cb6b --- /dev/null +++ b/OpenSim/Server/Handlers/Simulation/Utils.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections; +using System.Net; + +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; +using OpenMetaverse; + +namespace OpenSim.Server.Handlers.Simulation +{ + public class Utils + { + /// + /// Extract the param from an uri. + /// + /// Something like this: /uuid/ or /uuid/handle/release + /// uuid on uuid field + /// optional action + public static bool GetParams(string path, out UUID uuid, out ulong regionHandle, out string action) + { + uuid = UUID.Zero; + action = ""; + regionHandle = 0; + + path = path.Trim(new char[] { '/' }); + string[] parts = path.Split('/'); + if (parts.Length <= 1) + { + return false; + } + else + { + if (!UUID.TryParse(parts[0], out uuid)) + return false; + + if (parts.Length >= 2) + UInt64.TryParse(parts[1], out regionHandle); + if (parts.Length >= 3) + action = parts[2]; + + return true; + } + } + + public static bool GetAuthentication(OSHttpRequest httpRequest, out string authority, out string authKey) + { + authority = string.Empty; + authKey = string.Empty; + + Uri authUri; + + string auth = httpRequest.Headers["authentication"]; + // Authentication keys look like this: + // http://orgrid.org:8002/ + if ((auth != null) && (!string.Empty.Equals(auth)) && auth != "None") + { + if (Uri.TryCreate(auth, UriKind.Absolute, out authUri)) + { + authority = authUri.Authority; + authKey = authUri.PathAndQuery.Trim('/'); + return true; + } + } + + return false; + } + + } +} diff --git a/OpenSim/Services/Interfaces/IAuthenticationService.cs b/OpenSim/Services/Interfaces/IAuthenticationService.cs new file mode 100644 index 0000000000..25ceaa6f59 --- /dev/null +++ b/OpenSim/Services/Interfaces/IAuthenticationService.cs @@ -0,0 +1,14 @@ +using System; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public interface IAuthenticationService + { + string GetNewKey(UUID userID, UUID authToken); + + bool VerifyKey(UUID userID, string key); + + bool VerifySession(UUID iserID, UUID sessionID); + } +} diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs new file mode 100644 index 0000000000..da5410b433 --- /dev/null +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -0,0 +1,81 @@ +using System; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public interface ISimulationService + { + #region Agents + + bool CreateAgent(ulong regionHandle, AgentCircuitData aCircuit, out string reason); + + /// + /// Full child agent update. + /// + /// + /// + /// + bool UpdateAgent(ulong regionHandle, AgentData data); + + /// + /// Short child agent update, mostly for position. + /// + /// + /// + /// + bool UpdateAgent(ulong regionHandle, AgentPosition data); + + bool RetrieveAgent(ulong regionHandle, UUID id, out IAgentData agent); + + /// + /// Message from receiving region to departing region, telling it got contacted by the client. + /// When sent over REST, it invokes the opaque uri. + /// + /// + /// + /// + /// + bool ReleaseAgent(ulong regionHandle, UUID id, string uri); + + /// + /// Close agent. + /// + /// + /// + /// + bool CloseAgent(ulong regionHandle, UUID id); + + #endregion Agents + + #region Objects + + /// + /// Create an object in the destination region. This message is used primarily for prim crossing. + /// + /// + /// + /// + /// + bool CreateObject(ulong regionHandle, ISceneObject sog, bool isLocalCall); + + /// + /// Create an object from the user's inventory in the destination region. + /// This message is used primarily by clients. + /// + /// + /// + /// + /// + bool CreateObject(ulong regionHandle, UUID userID, UUID itemID); + + #endregion Objects + + #region Regions + + bool HelloNeighbour(ulong regionHandle, RegionInfo thisRegion); + + #endregion Regions + + } +} diff --git a/OpenSim/SimulatorServices/SimulationService.cs b/OpenSim/SimulatorServices/SimulationService.cs new file mode 100644 index 0000000000..8f01436a5c --- /dev/null +++ b/OpenSim/SimulatorServices/SimulationService.cs @@ -0,0 +1,85 @@ +using System; +using System.Reflection; +using System.Collections.Generic; +using log4net; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Server.Handlers.Base; + + +namespace OpenSim.SimulatorServices +{ + public class SimulationService : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static bool m_Enabled = false; + + private IConfigSource m_Config; + bool m_Registered = false; + + #region IRegionModule interface + + public void Initialise(IConfigSource config) + { + m_Config = config; + + IConfig moduleConfig = config.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("AssetServices", ""); + if (name == Name) + { + m_Enabled = true; + m_log.Info("[SIM SERVICE]: SimulationService enabled"); + + } + } + + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "SimulationService"; } + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + if (!m_Registered) + { + m_Registered = true; + + m_log.Info("[SIM SERVICE]: Starting..."); + + Object[] args = new Object[] { m_Config, scene.CommsManager.HttpServer, scene }; + + ServerUtils.LoadPlugin("OpenSim.Server.Handlers.dll:SimulationServiceInConnector", args); + } + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + } + + #endregion + + } +} diff --git a/prebuild.xml b/prebuild.xml index 9523ff120b..280665703f 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1404,6 +1404,7 @@ +