From e187972377c19bdd85093677c4c54034e4f9196e Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Tue, 25 Nov 2008 15:19:00 +0000 Subject: * Apply http://opensimulator.org/mantis/view.php?id=2640 * This is Diva's hypergrid patch, as perviously discussed on the opensim-dev mailing list * Applied some minor prebuild.xml jiggling to resolve a dependency issue * Thanks Diva! --- .../Hypergrid/HGGridServicesStandalone.cs | 928 +++++++++++++++++++++ 1 file changed, 928 insertions(+) create mode 100644 OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs (limited to 'OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs') diff --git a/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs b/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs new file mode 100644 index 0000000..4dc26e0 --- /dev/null +++ b/OpenSim/Region/Communications/Hypergrid/HGGridServicesStandalone.cs @@ -0,0 +1,928 @@ +/** + * Copyright (c) 2008, Contributors. All rights reserved. + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the Organizations nor the names of Individual + * Contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Channels; +using System.Runtime.Remoting.Channels.Tcp; +using System.Security.Authentication; + +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Servers; +using OpenSim.Region.Communications.Local; +using OpenSim.Region.Communications.OGS1; +using OpenSim.Region.Environment.Scenes; + +using OpenMetaverse; +using Nwc.XmlRpc; +using log4net; + +namespace OpenSim.Region.Communications.Hypergrid +{ + public class HGGridServicesStandalone : HGGridServices + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Encapsulate local backend services for manipulation of local regions + /// + protected LocalBackEndServices m_localBackend = new LocalBackEndServices(); + + private Dictionary m_deadRegionCache = new Dictionary(); + + public LocalBackEndServices LocalBackend + { + get { return m_localBackend; } + } + + public override string gdebugRegionName + { + get { return m_localBackend.gdebugRegionName; } + set { m_localBackend.gdebugRegionName = value; } + } + + public override bool RegionLoginsEnabled + { + get { return m_localBackend.RegionLoginsEnabled; } + set { m_localBackend.RegionLoginsEnabled = value; } + } + + + public HGGridServicesStandalone(NetworkServersInfo servers_info, BaseHttpServer httpServe, AssetCache asscache, SceneManager sman) + : base(servers_info, httpServe, asscache, sman) + { + //Respond to Grid Services requests + httpServer.AddXmlRPCHandler("logoff_user", LogOffUser); + httpServer.AddXmlRPCHandler("check", PingCheckReply); + httpServer.AddXmlRPCHandler("land_data", LandData); + + StartRemoting(); + } + + #region IGridServices interface + + public override RegionCommsListener RegisterRegion(RegionInfo regionInfo) + { + if (!regionInfo.RegionID.Equals(UUID.Zero)) + { + m_regionsOnInstance.Add(regionInfo); + return m_localBackend.RegisterRegion(regionInfo); + } + else + return base.RegisterRegion(regionInfo); + + } + + public override bool DeregisterRegion(RegionInfo regionInfo) + { + bool success = m_localBackend.DeregisterRegion(regionInfo); + if (!success) + success = base.DeregisterRegion(regionInfo); + return success; + } + + public override List RequestNeighbours(uint x, uint y) + { + List neighbours = m_localBackend.RequestNeighbours(x, y); + List remotes = base.RequestNeighbours(x, y); + neighbours.AddRange(remotes); + + return neighbours; + } + + public override RegionInfo RequestNeighbourInfo(UUID Region_UUID) + { + RegionInfo info = m_localBackend.RequestNeighbourInfo(Region_UUID); + if (info == null) + info = base.RequestNeighbourInfo(Region_UUID); + return info; + } + + public override RegionInfo RequestNeighbourInfo(ulong regionHandle) + { + RegionInfo info = m_localBackend.RequestNeighbourInfo(regionHandle); + //m_log.Info("[HGrid] Request neighbor info, local backend returned " + info); + if (info == null) + info = base.RequestNeighbourInfo(regionHandle); + return info; + } + + public override RegionInfo RequestClosestRegion(string regionName) + { + RegionInfo info = m_localBackend.RequestClosestRegion(regionName); + if (info == null) + info = base.RequestClosestRegion(regionName); + return info; + } + + public override List RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY) + { + //m_log.Info("[HGrid] Request map blocks " + minX + "-" + minY + "-" + maxX + "-" + maxY); + List neighbours = m_localBackend.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); + List remotes = base.RequestNeighbourMapBlocks(minX, minY, maxX, maxY); + neighbours.AddRange(remotes); + + return neighbours; + } + + public override LandData RequestLandData(ulong regionHandle, uint x, uint y) + { + LandData land = m_localBackend.RequestLandData(regionHandle, x, y); + if (land == null) + land = base.RequestLandData(regionHandle, x, y); + return land; + } + + public override List RequestNamedRegions(string name, int maxNumber) + { + List infos = m_localBackend.RequestNamedRegions(name, maxNumber); + List remotes = base.RequestNamedRegions(name, maxNumber); + infos.AddRange(remotes); + return infos; + } + + #endregion + + #region XML Request Handlers + + /// + /// A ping / version check + /// + /// + /// + public virtual XmlRpcResponse PingCheckReply(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + Hashtable respData = new Hashtable(); + respData["online"] = "true"; + + m_localBackend.PingCheckReply(respData); + + response.Value = respData; + + return response; + } + + + // Grid Request Processing + /// + /// Ooops, our Agent must be dead if we're getting this request! + /// + /// + /// + public XmlRpcResponse LogOffUser(XmlRpcRequest request) + { + m_log.Debug("[HGrid]: LogOff User Called"); + + Hashtable requestData = (Hashtable)request.Params[0]; + string message = (string)requestData["message"]; + UUID agentID = UUID.Zero; + UUID RegionSecret = UUID.Zero; + UUID.TryParse((string)requestData["agent_id"], out agentID); + UUID.TryParse((string)requestData["region_secret"], out RegionSecret); + + ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); + + m_localBackend.TriggerLogOffUser(regionHandle, agentID, RegionSecret, message); + + return new XmlRpcResponse(); + } + + /// + /// Someone asked us about parcel-information + /// + /// + /// + public XmlRpcResponse LandData(XmlRpcRequest request) + { + Hashtable requestData = (Hashtable)request.Params[0]; + ulong regionHandle = Convert.ToUInt64(requestData["region_handle"]); + uint x = Convert.ToUInt32(requestData["x"]); + uint y = Convert.ToUInt32(requestData["y"]); + m_log.DebugFormat("[HGrid]: Got XML reqeuest for land data at {0}, {1} in region {2}", x, y, regionHandle); + + LandData landData = m_localBackend.RequestLandData(regionHandle, x, y); + Hashtable hash = new Hashtable(); + if (landData != null) + { + // for now, only push out the data we need for answering a ParcelInfoReqeust + hash["AABBMax"] = landData.AABBMax.ToString(); + hash["AABBMin"] = landData.AABBMin.ToString(); + hash["Area"] = landData.Area.ToString(); + hash["AuctionID"] = landData.AuctionID.ToString(); + hash["Description"] = landData.Description; + hash["Flags"] = landData.Flags.ToString(); + hash["GlobalID"] = landData.GlobalID.ToString(); + hash["Name"] = landData.Name; + hash["OwnerID"] = landData.OwnerID.ToString(); + hash["SalePrice"] = landData.SalePrice.ToString(); + hash["SnapshotID"] = landData.SnapshotID.ToString(); + hash["UserLocation"] = landData.UserLocation.ToString(); + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + } + + #endregion + + #region Remoting + + /// + /// Start listening for .net remoting calls from other regions. + /// + private void StartRemoting() + { + m_log.Info("[HGrid]: Start remoting..."); + TcpChannel ch; + try + { + ch = new TcpChannel((int)NetworkServersInfo.RemotingListenerPort); + ChannelServices.RegisterChannel(ch, false); // Disabled security as Mono doesn't support this. + } + catch (Exception ex) + { + m_log.Error("[HGrid]: Exception while attempting to listen on TCP port " + (int)NetworkServersInfo.RemotingListenerPort + "."); + throw (ex); + } + + WellKnownServiceTypeEntry wellType = + new WellKnownServiceTypeEntry(typeof(OGS1InterRegionRemoting), "InterRegions", + WellKnownObjectMode.Singleton); + RemotingConfiguration.RegisterWellKnownServiceType(wellType); + InterRegionSingleton.Instance.OnArrival += TriggerExpectAvatarCrossing; + InterRegionSingleton.Instance.OnChildAgent += IncomingChildAgent; + InterRegionSingleton.Instance.OnPrimGroupArrival += IncomingPrim; + InterRegionSingleton.Instance.OnPrimGroupNear += TriggerExpectPrimCrossing; + InterRegionSingleton.Instance.OnRegionUp += TriggerRegionUp; + InterRegionSingleton.Instance.OnChildAgentUpdate += TriggerChildAgentUpdate; + InterRegionSingleton.Instance.OnTellRegionToCloseChildConnection += TriggerTellRegionToCloseChildConnection; + } + + + #endregion + + #region IInterRegionCommunications interface (Methods called by regions in this instance) + + public override bool ChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + int failures = 0; + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionHandle)) + { + failures = m_deadRegionCache[regionHandle]; + } + } + if (failures <= 3) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.ChildAgentUpdate(regionHandle, cAgentData)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.ChildAgentUpdate(regionHandle, cAgentData); + } + else + { + m_log.Warn("[HGrid]: remoting object not found"); + } + remObject = null; + + return retValue; + } + NoteDeadRegion(regionHandle); + + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + + m_log.WarnFormat( + "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", + regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + + m_log.WarnFormat( + "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", + regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + + m_log.WarnFormat( + "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", + regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + + m_log.WarnFormat( + "[HGrid]: Remoting Error: Unable to connect to adjacent region: {0} {1},{2}", + regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + + m_log.WarnFormat("[HGrid]: Unable to connect to adjacent region: {0} {1},{2}", + regInfo.RegionName, regInfo.RegionLocX, regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + + return false; + } + } + else + { + //m_log.Info("[INTERREGION]: Skipped Sending Child Update to a region because it failed too many times:" + regionHandle.ToString()); + return false; + } + } + + /// + /// Inform a region that a child agent will be on the way from a client. + /// + /// + /// + /// + public override bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + + if (m_localBackend.InformRegionOfChildAgent(regionHandle, agentData)) + { + return true; + } + return base.InformRegionOfChildAgent(regionHandle, agentData); + } + + // UGLY! + public override bool RegionUp(SerializableRegionInfo region, ulong regionhandle) + { + if (m_localBackend.RegionUp(region, regionhandle)) + return true; + return base.RegionUp(region, regionhandle); + } + + /// + /// + /// + /// + /// + /// + public override bool InformRegionOfPrimCrossing(ulong regionHandle, UUID primID, string objData, int XMLMethod) + { + int failures = 0; + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionHandle)) + { + failures = m_deadRegionCache[regionHandle]; + } + } + if (failures <= 1) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.InformRegionOfPrimCrossing(regionHandle, primID, objData, XMLMethod)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + //don't want to be creating a new link to the remote instance every time like we are here + bool retValue = false; + + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = remObject.InformRegionOfPrimCrossing(regionHandle, primID.Guid, objData, XMLMethod); + } + else + { + m_log.Warn("[HGrid]: Remoting object not found"); + } + remObject = null; + + return retValue; + } + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Invalid Credential Exception: Invalid Credentials : " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Unknown exception: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0}", e); + return false; + } + } + else + { + return false; + } + } + + /// + /// + /// + /// + /// + /// + /// + public override bool ExpectAvatarCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isFlying) + { + + RegionInfo[] regions = m_regionsOnInstance.ToArray(); + bool banned = false; + bool localregion = false; + + for (int i = 0; i < regions.Length; i++) + { + if (regions[i] != null) + { + if (regions[i].RegionHandle == regionHandle) + { + localregion = true; + if (regions[i].EstateSettings.IsBanned(agentID)) + { + banned = true; + break; + } + } + } + } + + if (banned) + return false; + if (localregion) + return m_localBackend.ExpectAvatarCrossing(regionHandle, agentID, position, isFlying); + + return base.ExpectAvatarCrossing(regionHandle, agentID, position, isFlying); + + } + + public override bool ExpectPrimCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isPhysical) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + bool retValue = false; + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + retValue = + remObject.ExpectAvatarCrossing(regionHandle, agentID.Guid, new sLLVector3(position), + isPhysical); + } + else + { + m_log.Warn("[HGrid]: Remoting object not found"); + } + remObject = null; + + return retValue; + } + //TODO need to see if we know about where this region is and use .net remoting + // to inform it. + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Invalid Credential Exception: Invalid Credentials : " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Unknown exception: Unable to connect to adjacent region: " + regionHandle); + m_log.DebugFormat("[HGrid]: {0}", e); + return false; + } + } + + public override bool TellRegionToCloseChildConnection(ulong regionHandle, UUID agentID) + { + RegionInfo regInfo = null; + try + { + if (m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID)) + { + return true; + } + + regInfo = RequestNeighbourInfo(regionHandle); + if (regInfo != null) + { + // bool retValue = false; + OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject( + typeof(OGS1InterRegionRemoting), + "tcp://" + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions"); + + if (remObject != null) + { + // retValue = + remObject.TellRegionToCloseChildConnection(regionHandle, agentID.Guid); + } + else + { + m_log.Warn("[HGrid]: Remoting object not found"); + } + remObject = null; + + return true; + } + //TODO need to see if we know about where this region is and use .net remoting + // to inform it. + NoteDeadRegion(regionHandle); + return false; + } + catch (RemotingException) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Remoting Error: Unable to connect to adjacent region to tell it to close child agents: " + regInfo.RegionName + + " " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + //m_log.Debug(e.ToString()); + return false; + } + catch (SocketException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGridS]: Socket Error: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + + " - Is this neighbor up?"); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (InvalidCredentialException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Invalid Credentials: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (AuthenticationException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: Authentication exception: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (WebException e) + { + NoteDeadRegion(regionHandle); + m_log.Warn("[HGrid]: WebException exception: Unable to connect to adjacent region using tcp://" + + regInfo.RemotingAddress + + ":" + regInfo.RemotingPort + + "/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY); + m_log.DebugFormat("[HGrid]: {0} {1}", e.Source, e.Message); + return false; + } + catch (Exception e) + { + NoteDeadRegion(regionHandle); + // This line errors with a Null Reference Exception.. Why? @.@ + //m_log.Warn("Unknown exception: Unable to connect to adjacent region using tcp://" + regInfo.RemotingAddress + + // ":" + regInfo.RemotingPort + + //"/InterRegions - @ " + regInfo.RegionLocX + "," + regInfo.RegionLocY + " - This is likely caused by an incompatibility in the protocol between this sim and that one"); + m_log.DebugFormat("[HGrid]: {0}", e); + return false; + } + } + + public override bool AcknowledgeAgentCrossed(ulong regionHandle, UUID agentId) + { + return m_localBackend.AcknowledgeAgentCrossed(regionHandle, agentId); + } + + public override bool AcknowledgePrimCrossed(ulong regionHandle, UUID primId) + { + return m_localBackend.AcknowledgePrimCrossed(regionHandle, primId); + } + + #endregion + + #region Methods triggered by calls from external instances + + /// + /// + /// + /// + /// + /// + public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData) + { + HGIncomingChildAgent(regionHandle, agentData); + + m_log.Info("[HGrid]: " + gdebugRegionName + ": Incoming HGrid Agent " + agentData.firstname + " " + agentData.lastname); + + return m_localBackend.IncomingChildAgent(regionHandle, agentData); + } + + public bool TriggerRegionUp(RegionUpData regionData, ulong regionhandle) + { + m_log.Info( + "[HGrid]: " + + m_localBackend._gdebugRegionName + "Incoming HGrid RegionUpReport: " + "(" + regionData.X + + "," + regionData.Y + "). Giving this region a fresh set of 'dead' tries"); + + RegionInfo nRegionInfo = new RegionInfo(); + nRegionInfo.SetEndPoint("127.0.0.1", regionData.PORT); + nRegionInfo.ExternalHostName = regionData.IPADDR; + nRegionInfo.RegionLocX = regionData.X; + nRegionInfo.RegionLocY = regionData.Y; + + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(nRegionInfo.RegionHandle)) + { + m_deadRegionCache.Remove(nRegionInfo.RegionHandle); + } + } + + return m_localBackend.TriggerRegionUp(nRegionInfo, regionhandle); + } + + public bool TriggerChildAgentUpdate(ulong regionHandle, ChildAgentDataUpdate cAgentData) + { + //m_log.Info("[INTER]: Incoming HGrid Child Agent Data Update"); + + return m_localBackend.TriggerChildAgentUpdate(regionHandle, cAgentData); + } + + /// + /// + /// + /// + /// + /// + public bool IncomingPrim(ulong regionHandle, UUID primID, string objData, int XMLMethod) + { + m_localBackend.TriggerExpectPrim(regionHandle, primID, objData, XMLMethod); + + return true; + } + + /// + /// + /// + /// + /// + /// + /// + public bool TriggerExpectAvatarCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isFlying) + { + return m_localBackend.TriggerExpectAvatarCrossing(regionHandle, agentID, position, isFlying); + } + + public bool TriggerExpectPrimCrossing(ulong regionHandle, UUID agentID, Vector3 position, bool isPhysical) + { + return m_localBackend.TriggerExpectPrimCrossing(regionHandle, agentID, position, isPhysical); + } + + public bool TriggerTellRegionToCloseChildConnection(ulong regionHandle, UUID agentID) + { + return m_localBackend.TriggerTellRegionToCloseChildConnection(regionHandle, agentID); + } + + int timeOut = 10; //10 seconds + /// + /// Check that a region is available for TCP comms. This is necessary for .NET remoting between regions. + /// + /// + /// + /// + /// + public bool CheckRegion(string address, uint port, bool retry) + { + bool available = false; + bool timed_out = true; + + IPAddress ia; + IPAddress.TryParse(address, out ia); + IPEndPoint m_EndPoint = new IPEndPoint(ia, (int)port); + + AsyncCallback callback = delegate(IAsyncResult iar) + { + Socket s = (Socket)iar.AsyncState; + try + { + s.EndConnect(iar); + available = true; + timed_out = false; + } + catch (Exception e) + { + m_log.DebugFormat( + "[HGrid]: Callback EndConnect exception: {0}:{1}", e.Message, e.StackTrace); + } + + s.Close(); + }; + + try + { + Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + IAsyncResult ar = socket.BeginConnect(m_EndPoint, callback, socket); + ar.AsyncWaitHandle.WaitOne(timeOut * 1000, false); + } + catch (Exception e) + { + m_log.DebugFormat( + "[HGrid]: CheckRegion Socket Setup exception: {0}:{1}", e.Message, e.StackTrace); + + return false; + } + + if (timed_out) + { + m_log.DebugFormat( + "[HGrid]: socket [{0}] timed out ({1}) waiting to obtain a connection.", + m_EndPoint, timeOut * 1000); + + if (retry) + { + return CheckRegion(address, port, false); + } + } + + return available; + } + + public override bool CheckRegion(string address, uint port) + { + return CheckRegion(address, port, true); + } + + public void NoteDeadRegion(ulong regionhandle) + { + lock (m_deadRegionCache) + { + if (m_deadRegionCache.ContainsKey(regionhandle)) + { + m_deadRegionCache[regionhandle] = m_deadRegionCache[regionhandle] + 1; + } + else + { + m_deadRegionCache.Add(regionhandle, 1); + } + } + + } + + #endregion + + + } +} -- cgit v1.1