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 m_interfaces = new Dictionary(); private readonly List m_myLocations = new List(); private readonly Dictionary m_neighbourInterfaces = new Dictionary(); private readonly Dictionary m_neighbourRemote = new Dictionary(); private IConfigSource m_config; private bool m_enabled = false; private Object m_lockObject = new object(); private RemotingObject m_myRemote; private TcpChannel m_tcpChannel; private int m_tcpPort = 10101; #region IInterregionModule Members 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 RegisterMethod(T e) { m_interfaces[typeof (T)] = e; } public bool HasInterface(Location loc) { foreach (string val in m_neighbourInterfaces[loc]) { if (val == typeof (T).FullName) { return true; } } return false; } public T RequestInterface(Location loc) { if (m_neighbourRemote.ContainsKey(loc)) { return m_neighbourRemote[loc].RequestInterface(); } else { throw new IndexOutOfRangeException("No neighbour availible at that location"); } } public T[] RequestInterface() { List m_t = new List(); foreach (RemotingObject remote in m_neighbourRemote.Values) { try { m_t.Add(remote.RequestInterface()); } catch (NotSupportedException) { } } return m_t.ToArray(); } public Location GetLocationByDirection(Scene scene, Direction dir) { return new Location(0, 0); } #endregion //TODO: This prevents us from registering new scenes after PostInitialise if we want comms updated. #region IRegionModule Members 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(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 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; } } } }