From 217ffee8cb50e0a7ddfc0d4c4e4bb6a68de909d8 Mon Sep 17 00:00:00 2001 From: diva Date: Sat, 14 Feb 2009 16:37:55 +0000 Subject: [PATCH] Moved RegionUp to REST/LocalComms. The original functionality has been entirely maintained, although it will have to be revisited soon, because it's buggy. --- OpenSim/Framework/RegionInfo.cs | 69 +++++ .../Local/LocalInterregionComms.cs | 17 ++ .../REST/RESTInterregionComms.cs | 268 ++++++++++++++++-- .../Framework/Interfaces/IInterregionComms.cs | 23 +- OpenSim/Region/Framework/Scenes/Scene.cs | 11 +- .../Scenes/SceneCommunicationService.cs | 10 +- 6 files changed, 361 insertions(+), 37 deletions(-) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index a0e5ba50b1..84751bdf39 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -31,6 +31,7 @@ using System.Net.Sockets; using System.Xml; using Nini.Config; using OpenMetaverse; +using OpenMetaverse.StructuredData; namespace OpenSim.Framework { @@ -605,5 +606,73 @@ namespace OpenSim.Framework configMember.forceSetConfigurationOption("lastmap_uuid", mapUUID.ToString()); configMember.forceSetConfigurationOption("lastmap_refresh", lastMapRefresh); } + + public OSDMap PackRegionInfoData() + { + OSDMap args = new OSDMap(); + args["region_id"] = OSD.FromUUID(RegionID); + if ((RegionName != null) && !RegionName.Equals("")) + args["region_name"] = OSD.FromString(RegionName); + args["external_host_name"] = OSD.FromString(ExternalHostName); + args["http_port"] = OSD.FromString(HttpPort.ToString()); + args["server_uri"] = OSD.FromString(ServerURI); + args["region_xloc"] = OSD.FromString(RegionLocX.ToString()); + args["region_yloc"] = OSD.FromString(RegionLocY.ToString()); + args["internal_ep_address"] = OSD.FromString(InternalEndPoint.Address.ToString()); + args["internal_ep_port"] = OSD.FromString(InternalEndPoint.Port.ToString()); + if ((RemotingAddress != null) && !RemotingAddress.Equals("")) + args["remoting_address"] = OSD.FromString(RemotingAddress); + args["remoting_port"] = OSD.FromString(RemotingPort.ToString()); + args["allow_alt_ports"] = OSD.FromBoolean(m_allow_alternate_ports); + if ((proxyUrl != null) && !proxyUrl.Equals("")) + args["proxy_url"] = OSD.FromString(proxyUrl); + + return args; + } + + public void UnpackRegionInfoData(OSDMap args) + { + if (args["region_id"] != null) + RegionID = args["region_id"].AsUUID(); + if (args["region_name"] != null) + RegionName = args["region_name"].AsString(); + if (args["external_host_name"] != null) + ExternalHostName = args["external_host_name"].AsString(); + if (args["http_port"] != null) + UInt32.TryParse(args["http_port"].AsString(), out m_httpPort); + if (args["server_uri"] != null) + ServerURI = args["server_uri"].AsString(); + if (args["region_xloc"] != null) + { + uint locx; + UInt32.TryParse(args["region_xloc"].AsString(), out locx); + RegionLocX = locx; + } + if (args["region_yloc"] != null) + { + uint locy; + UInt32.TryParse(args["region_yloc"].AsString(), out locy); + RegionLocY = locy; + } + IPAddress ip_addr = null; + if (args["internal_ep_address"] != null) + { + IPAddress.TryParse(args["internal_ep_address"].AsString(), out ip_addr); + } + int port = 0; + if (args["internal_ep_port"] != null) + { + Int32.TryParse(args["internal_ep_port"].AsString(), out port); + } + InternalEndPoint = new IPEndPoint(ip_addr, port); + if (args["remoting_address"] != null) + RemotingAddress = args["remoting_address"].AsString(); + if (args["remoting_port"] != null) + UInt32.TryParse(args["remoting_port"].AsString(), out m_remotingPort); + if (args["allow_alt_ports"] != null) + m_allow_alternate_ports = args["allow_alt_ports"].AsBoolean(); + if (args["proxy_url"] != null) + proxyUrl = args["proxy_url"].AsString(); + } } } diff --git a/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs index 6e813f46c8..29bc4f79a9 100644 --- a/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/Communications/Local/LocalInterregionComms.cs @@ -227,6 +227,23 @@ namespace OpenSim.Region.CoreModules.Communications.Local return false; } + /** + * Region-related communications + */ + + public bool SendHelloNeighbour(ulong regionHandle, RegionInfo thisRegion) + { + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionHandle == regionHandle) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendHelloNeighbour"); + return s.IncomingHelloNeighbour(thisRegion); + } + } + return false; + } + #endregion /* IInterregionComms */ #region Misc diff --git a/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs index fcb3f5b508..bc98337a18 100644 --- a/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs +++ b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs @@ -45,7 +45,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST { public class RESTInterregionComms : IRegionModule, IInterregionCommsOut { - private bool initialized = false; + private static bool initialized = false; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected bool m_enabled = false; @@ -78,6 +78,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST return; InitEach(scene); + } public virtual void PostInitialise() @@ -115,8 +116,9 @@ namespace OpenSim.Region.CoreModules.Communications.REST protected virtual void AddHTTPHandlers() { - m_aScene.CommsManager.HttpServer.AddHTTPHandler("/agent/", AgentHandler); + m_aScene.CommsManager.HttpServer.AddHTTPHandler("/agent/", AgentHandler); m_aScene.CommsManager.HttpServer.AddHTTPHandler("/object/", ObjectHandler); + m_aScene.CommsManager.HttpServer.AddHTTPHandler("/region/", RegionHandler); } #endregion /* IRegionModule */ @@ -161,6 +163,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST //else // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); return false; + } public bool SendChildAgentUpdate(ulong regionHandle, AgentPosition cAgentData) @@ -178,6 +181,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST //else // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); return false; + } public bool SendReleaseAgent(ulong regionHandle, UUID id, string uri) @@ -231,6 +235,32 @@ namespace OpenSim.Region.CoreModules.Communications.REST return false; } + /** + * Region-related communications + */ + + public bool SendHelloNeighbour(ulong regionHandle, RegionInfo thisRegion) + { + // Try local first + if (m_localBackend.SendHelloNeighbour(regionHandle, thisRegion)) + { + //m_log.Debug("[REST COMMS]: LocalBackEnd SendHelloNeighbour succeeded"); + return true; + } + + // else do the remote thing + RegionInfo regInfo = m_commsManager.GridService.RequestNeighbourInfo(regionHandle); + if ((regInfo != null) && + // Don't remote-call this instance; that's a startup hickup + !((regInfo.ExternalHostName == thisRegion.ExternalHostName) && (regInfo.HttpPort == thisRegion.HttpPort))) + { + return DoHelloNeighbourCall(regInfo, thisRegion); + } + //else + // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); + return false; + } + #endregion /* IInterregionComms */ #region DoWork functions for the above public interface @@ -482,7 +512,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST WebRequest ObjectCreateRequest = WebRequest.Create(uri); ObjectCreateRequest.Method = "POST"; - ObjectCreateRequest.ContentType = "text/xml"; + ObjectCreateRequest.ContentType = "application/json"; ObjectCreateRequest.Timeout = 10000; OSDMap args = new OSDMap(2); @@ -555,6 +585,90 @@ namespace OpenSim.Region.CoreModules.Communications.REST } + protected bool DoHelloNeighbourCall(RegionInfo region, RegionInfo thisRegion) + { + string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; + //Console.WriteLine(" >>> DoHelloNeighbourCall <<< " + uri); + + WebRequest HelloNeighbourRequest = WebRequest.Create(uri); + HelloNeighbourRequest.Method = "POST"; + HelloNeighbourRequest.ContentType = "application/json"; + HelloNeighbourRequest.Timeout = 10000; + + // Fill it in + OSDMap args = null; + try + { + args = thisRegion.PackRegionInfoData(); + } + catch (Exception e) + { + m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message); + } + // Add the regionhandle of the destination region + ulong regionHandle = GetRegionHandle(region.RegionHandle); + args["destination_handle"] = OSD.FromString(regionHandle.ToString()); + + string strBuffer = ""; + byte[] buffer = new byte[1]; + try + { + strBuffer = OSDParser.SerializeJsonString(args); + UTF8Encoding str = new UTF8Encoding(); + buffer = str.GetBytes(strBuffer); + + } + catch (Exception e) + { + m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message); + // ignore. buffer will be empty, caller should check. + } + + Stream os = null; + try + { // send the Post + HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send + os = HelloNeighbourRequest.GetRequestStream(); + os.Write(buffer, 0, strBuffer.Length); //Send it + os.Close(); + //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri); + } + //catch (WebException ex) + catch + { + //m_log.InfoFormat("[REST COMMS]: Bad send on HelloNeighbour {0}", ex.Message); + + return false; + } + + // Let's wait for the response + //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall"); + + try + { + WebResponse webResponse = HelloNeighbourRequest.GetResponse(); + if (webResponse == null) + { + m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post"); + } + + StreamReader sr = new StreamReader(webResponse.GetResponseStream()); + //reply = sr.ReadToEnd().Trim(); + sr.ReadToEnd().Trim(); + sr.Close(); + //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); + + } + catch (WebException ex) + { + m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message); + // ignore, really + } + + return true; + + } + #endregion /* Do Work */ #region Incoming calls from remote instances @@ -617,33 +731,6 @@ namespace OpenSim.Region.CoreModules.Communications.REST } - protected OSDMap GetOSDMap(Hashtable request) - { - OSDMap args = null; - try - { - OSD buffer; - // We should pay attention to the content-type, but let's assume we know it's Json - buffer = OSDParser.DeserializeJson((string)request["body"]); - if (buffer.Type == OSDType.Map) - { - args = (OSDMap)buffer; - return args; - } - else - { - // uh? - m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString()); - return null; - } - } - catch (Exception ex) - { - m_log.InfoFormat("[REST COMMS]: exception on parse of REST message {0}", ex.Message); - return null; - } - } - protected virtual void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) { OSDMap args = GetOSDMap(request); @@ -868,10 +955,129 @@ namespace OpenSim.Region.CoreModules.Communications.REST responsedata["str_response_string"] = result.ToString(); } + /* + * Region-related incoming calls + * + */ + + public Hashtable RegionHandler(Hashtable request) + { + //m_log.Debug("[CONNECTION DEBUGGING]: RegionHandler Called"); + + //Console.WriteLine("---------------------------"); + //Console.WriteLine(" >> uri=" + request["uri"]); + //Console.WriteLine(" >> content-type=" + request["content-type"]); + //Console.WriteLine(" >> http-method=" + request["http-method"]); + //Console.WriteLine("---------------------------\n"); + + Hashtable responsedata = new Hashtable(); + responsedata["content_type"] = "text/html"; + + UUID regionID; + string action; + ulong regionHandle; + if (!GetParams((string)request["uri"], out regionID, out regionHandle, out action)) + { + m_log.InfoFormat("[REST COMMS]: Invalid parameters for object message {0}", request["uri"]); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + // Next, let's parse the verb + string method = (string)request["http-method"]; + if (method.Equals("POST")) + { + DoRegionPost(request, responsedata, regionID); + return responsedata; + } + //else if (method.Equals("PUT")) + //{ + // DoRegionPut(request, responsedata, regionID); + // return responsedata; + //} + //else if (method.Equals("DELETE")) + //{ + // DoRegionDelete(request, responsedata, regiontID); + // return responsedata; + //} + else + { + m_log.InfoFormat("[REST COMMS]: method {0} not supported in region message", method); + responsedata["int_response_code"] = 404; + responsedata["str_response_string"] = "false"; + + return responsedata; + } + + } + + protected virtual void DoRegionPost(Hashtable request, Hashtable responsedata, UUID id) + { + OSDMap args = GetOSDMap(request); + if (args == null) + { + responsedata["int_response_code"] = 400; + responsedata["str_response_string"] = "false"; + return; + } + + // retrieve the regionhandle + ulong regionhandle = 0; + if (args["destination_handle"] != null) + UInt64.TryParse(args["destination_handle"].AsString(), out regionhandle); + + RegionInfo aRegion = new RegionInfo(); + try + { + aRegion.UnpackRegionInfoData(args); + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on unpacking HelloNeighbour message {0}", ex.Message); + return; + } + + // This is the meaning of POST region + bool result = m_localBackend.SendHelloNeighbour(regionhandle, aRegion); + + responsedata["int_response_code"] = 200; + responsedata["str_response_string"] = result.ToString(); + } + + #endregion #region Misc - + + protected OSDMap GetOSDMap(Hashtable request) + { + OSDMap args = null; + try + { + OSD buffer; + // We should pay attention to the content-type, but let's assume we know it's Json + buffer = OSDParser.DeserializeJson((string)request["body"]); + if (buffer.Type == OSDType.Map) + { + args = (OSDMap)buffer; + return args; + } + else + { + // uh? + m_log.Debug("[REST COMMS]: Got OSD of type " + buffer.Type.ToString()); + return null; + } + } + catch (Exception ex) + { + m_log.InfoFormat("[REST COMMS]: exception on parse of REST message {0}", ex.Message); + return null; + } + } + /// /// Extract the param from an uri. /// diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs index d3f44bbcca..0b62df2f57 100644 --- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs @@ -32,8 +32,11 @@ namespace OpenSim.Region.Framework.Interfaces { public delegate bool ChildAgentUpdateReceived(AgentData data); - public interface IInterregionCommsOut + public interface IInterregionCommsOut { + + #region Agents + bool SendCreateChildAgent(ulong regionHandle, AgentCircuitData aCircuit); /// @@ -70,8 +73,26 @@ namespace OpenSim.Region.Framework.Interfaces /// bool SendCloseAgent(ulong regionHandle, UUID id); + #endregion Agents + + #region Objects + + /// + /// Create an object in the destination region. This message is used primarily for prim crossing. + /// + /// + /// + /// + /// bool SendCreateObject(ulong regionHandle, ISceneObject sog, bool isLocalCall); + #endregion Objects + + #region Regions + + bool SendHelloNeighbour(ulong regionHandle, RegionInfo thisRegion); + + #endregion Regions } // This may not be needed, but having it here for now. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c31e6f708e..b42c46ed01 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -422,6 +422,8 @@ namespace OpenSim.Region.Framework.Scenes /// True after all operations complete, throws exceptions otherwise. public override bool OtherRegionUp(RegionInfo otherRegion) { + m_log.InfoFormat("[SCENE]: Region {0} up in coords {1}-{2}", otherRegion.RegionName, otherRegion.RegionLocX, otherRegion.RegionLocY); + if (RegionInfo.RegionHandle != otherRegion.RegionHandle) { for (int i = 0; i < m_neighbours.Count; i++) @@ -517,6 +519,13 @@ namespace OpenSim.Region.Framework.Scenes return found; } + + // Alias IncomingHelloNeighbour OtherRegionUp, for now + public bool IncomingHelloNeighbour(RegionInfo neighbour) + { + return OtherRegionUp(neighbour); + } + /// /// Given float seconds, this will restart the region. /// @@ -2569,7 +2578,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void InformClientOfNeighbor(ScenePresence presence, RegionInfo region) { - m_sceneGridService.InformNeighborChildAgent(presence, region, m_neighbours); + m_sceneGridService.InformNeighborChildAgent(presence, region); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 2f0bbb231d..4c10e2c882 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -459,7 +459,7 @@ namespace OpenSim.Region.Framework.Scenes /// This informs a single neighboring region about agent "avatar". /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// - public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region, List neighbours) + public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region) { AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo(); agent.BaseFolder = UUID.Zero; @@ -493,8 +493,10 @@ namespace OpenSim.Region.Framework.Scenes m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here"); //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port); - bool regionAccepted = - m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle); + //bool regionAccepted = + // m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle); + + bool regionAccepted = m_interregionCommsOut.SendHelloNeighbour(regionhandle, region); if (regionAccepted) { @@ -519,7 +521,7 @@ namespace OpenSim.Region.Framework.Scenes { //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); - + List neighbours = new List(); // This stays uncached because we don't already know about our neighbors at this point. neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);