From 919aed1058d61cab479c6702f4051ac1f338fc03 Mon Sep 17 00:00:00 2001
From: Adam Frisby
Date: Wed, 30 Apr 2008 21:23:37 +0000
Subject: * And more

---
 .../Modules/Grid/Interregion/IInterregionModule.cs |  16 ++
 .../Modules/Grid/Interregion/InterregionModule.cs  | 175 +++++++++++++++++++++
 .../Modules/Grid/Interregion/RemotingObject.cs     |  50 ++++++
 3 files changed, 241 insertions(+)
 create mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs
 create mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs
 create mode 100644 OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs

diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs
new file mode 100644
index 0000000..ac4062b
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Grid/Interregion/IInterregionModule.cs
@@ -0,0 +1,16 @@
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Modules.Communications.Interregion;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Grid.Interregion
+{
+    public interface IInterregionModule
+    {
+        void RegisterMethod<T>(T e);
+        bool HasInterface<T>(Location loc);
+        T RequestInterface<T>(Location loc);
+        T[] RequestInterface<T>();
+        Location GetLocationByDirection(Scene scene, InterregionModule.Direction dir);
+        void internal_CreateRemotingObjects();
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs
new file mode 100644
index 0000000..1a77ac8
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Grid/Interregion/InterregionModule.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Channels;
+using System.Runtime.Remoting.Channels.Tcp;
+using Nini.Config;
+using OpenSim.Framework;
+using OpenSim.Region.Environment.Interfaces;
+using OpenSim.Region.Environment.Modules.Grid.Interregion;
+using OpenSim.Region.Environment.Scenes;
+
+namespace OpenSim.Region.Environment.Modules.Communications.Interregion
+{
+    public class InterregionModule : IInterregionModule, IRegionModule
+    {
+        #region Direction enum
+
+        public enum Direction
+        {
+            North,
+            NorthEast,
+            East,
+            SouthEast,
+            South,
+            SouthWest,
+            West,
+            NorthWest
+        }
+
+        #endregion
+
+        private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
+        private readonly List<Location> m_myLocations = new List<Location>();
+
+        private readonly Dictionary<Location, string[]> m_neighbourInterfaces = new Dictionary<Location, string[]>();
+        private readonly Dictionary<Location, RemotingObject> m_neighbourRemote = new Dictionary<Location, RemotingObject>();
+        private IConfigSource m_config;
+        private RemotingObject m_myRemote;
+
+        private Object m_lockObject = new object();
+        private TcpChannel m_tcpChannel;
+        private int m_tcpPort = 10101;
+        private bool m_enabled = false;
+
+        #region IRegionModule Members
+
+        //TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated.
+        public void Initialise(Scene scene, IConfigSource source)
+        {
+            if (m_enabled)
+            {
+                m_myLocations.Add(new Location((int) scene.RegionInfo.RegionLocX,
+                                               (int) scene.RegionInfo.RegionLocY));
+                m_config = source;
+
+                scene.RegisterModuleInterface<IInterregionModule>(this);
+            }
+        }
+
+        //TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated.
+        public void PostInitialise()
+        {
+            if (m_enabled)
+            {
+                try
+                {
+                    m_tcpPort = m_config.Configs["Comms"].GetInt("remoting_port", m_tcpPort);
+                }
+                catch
+                {
+                }
+
+                internal_CreateRemotingObjects();
+            }
+        }
+
+        public void Close()
+        {
+            ChannelServices.UnregisterChannel(m_tcpChannel);
+        }
+
+        public string Name
+        {
+            get { return "InterregionModule"; }
+        }
+
+        public bool IsSharedModule
+        {
+            get { return true; }
+        }
+
+        #endregion
+
+        public void internal_CreateRemotingObjects()
+        {
+            lock (m_lockObject)
+            {
+                if (m_tcpChannel == null)
+                {
+                    m_myRemote = new RemotingObject(m_interfaces, m_myLocations.ToArray());
+                    m_tcpChannel = new TcpChannel(m_tcpPort);
+
+                    ChannelServices.RegisterChannel(m_tcpChannel, false);
+                    RemotingServices.Marshal(m_myRemote, "OpenSimRemote2", typeof (RemotingObject));
+                }
+            }
+        }
+
+        public void RegisterRemoteRegion(string uri)
+        {
+            RegisterRemotingInterface((RemotingObject) Activator.GetObject(typeof (RemotingObject), uri));
+        }
+
+        private void RegisterRemotingInterface(RemotingObject remote)
+        {
+            Location[] locs = remote.GetLocations();
+            string[] interfaces = remote.GetInterfaces();
+            foreach (Location loc in locs)
+            {
+                m_neighbourInterfaces[loc] = interfaces;
+                m_neighbourRemote[loc] = remote;
+            }
+        }
+
+        public void RegisterMethod<T>(T e)
+        {
+            m_interfaces[typeof (T)] = e;
+        }
+
+        public bool HasInterface<T>(Location loc)
+        {
+            foreach (string val in m_neighbourInterfaces[loc])
+            {
+                if (val == typeof (T).FullName)
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public T RequestInterface<T>(Location loc)
+        {
+            if (m_neighbourRemote.ContainsKey(loc))
+            {
+                return m_neighbourRemote[loc].RequestInterface<T>();
+            }
+            else
+            {
+                throw new IndexOutOfRangeException("No neighbour availible at that location");
+            }
+        }
+
+        public T[] RequestInterface<T>()
+        {
+            List<T> m_t = new List<T>();
+            foreach (RemotingObject remote in m_neighbourRemote.Values)
+            {
+                try
+                {
+                    m_t.Add(remote.RequestInterface<T>());
+                }
+                catch (NotSupportedException)
+                {
+                }
+            }
+            return m_t.ToArray();
+        }
+
+        public Location GetLocationByDirection(Scene scene, Direction dir)
+        {
+            return new Location(0, 0);
+        }
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs b/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs
new file mode 100644
index 0000000..2c72bb9
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Grid/Interregion/RemotingObject.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using OpenSim.Framework;
+
+namespace OpenSim.Region.Environment.Modules.Grid.Interregion
+{
+    public class RemotingObject : MarshalByRefObject
+    {
+        private readonly Location[] m_coords;
+        private readonly Dictionary<Type, Object> m_interfaces = new Dictionary<Type, object>();
+
+        public RemotingObject(Dictionary<Type, Object> myInterfaces, Location[] coords)
+        {
+            m_interfaces = myInterfaces;
+            m_coords = coords;
+        }
+
+        public Location[] GetLocations()
+        {
+            return (Location[]) m_coords.Clone();
+        }
+
+        public string[] GetInterfaces()
+        {
+            string[] interfaces = new string[m_interfaces.Count];
+            int i = 0;
+
+            foreach (KeyValuePair<Type, object> pair in m_interfaces)
+            {
+                interfaces[i++] = pair.Key.FullName;
+            }
+
+            return interfaces;
+        }
+
+        /// <summary>
+        /// Returns a registered interface availible to neighbouring regions.
+        /// </summary>
+        /// <typeparam name="T">The type of interface you wish to request</typeparam>
+        /// <returns>A MarshalByRefObject inherited from this region inheriting the interface requested.</returns>
+        /// <remarks>All registered interfaces <b>MUST</b> inherit from MarshalByRefObject and use only serialisable types.</remarks>
+        public T RequestInterface<T>()
+        {
+            if (m_interfaces.ContainsKey(typeof (T)))
+                return (T) m_interfaces[typeof (T)];
+
+            throw new NotSupportedException("No such interface registered.");
+        }
+    }
+}
\ No newline at end of file
-- 
cgit v1.1