From c1af982ff4c02bf45cb2a2977a4aa4dc8ac45027 Mon Sep 17 00:00:00 2001 From: "Huaiyu (Kitty) Liu" Date: Tue, 21 Dec 2010 17:15:30 -0800 Subject: [PATCH] Added code to initiate listener or start connecting to remote listeners. --- .../SymmetricSync/RegionSyncModule.cs | 151 +++++++++++++----- .../SymmetricSync/SyncConnector.cs | 84 +++++++++- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 3 files changed, 195 insertions(+), 42 deletions(-) diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs index e54c8e742d..79228dc099 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/RegionSyncModule.cs @@ -35,32 +35,29 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - IConfig syncConfig = config.Configs["RegionSyncModule"]; + IConfig m_sysConfig = config.Configs["RegionSyncModule"]; m_active = false; - if (syncConfig == null) + if (m_sysConfig == null) { m_log.Warn("[REGION SYNC MODULE] No RegionSyncModule config section found. Shutting down."); return; } - else if (!syncConfig.GetBoolean("Enabled", false)) + else if (!m_sysConfig.GetBoolean("Enabled", false)) { m_log.Warn("[REGION SYNC MODULE] RegionSyncModule is not enabled. Shutting down."); return; } - m_actorID = syncConfig.GetString("ActorID", ""); + m_actorID = m_sysConfig.GetString("ActorID", ""); if (m_actorID == "") { m_log.Error("ActorID not defined in [RegionSyncModule] section in config file"); return; } - m_isSyncRelay = syncConfig.GetBoolean("IsSyncRelay", false); + m_isSyncRelay = m_sysConfig.GetBoolean("IsSyncRelay", false); - m_isSyncListenerLocal = syncConfig.GetBoolean("IsSyncListenerLocal", false); - string listenerAddrDefault = syncConfig.GetString("ServerIPAddress", "127.0.0.1"); - m_syncListenerAddr = syncConfig.GetString("SyncListenerIPAddress", listenerAddrDefault); - m_syncListenerPort = syncConfig.GetInt("SyncListenerPort", 13000); + m_isSyncListenerLocal = m_sysConfig.GetBoolean("IsSyncListenerLocal", false); m_active = true; @@ -91,7 +88,12 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //For now, we use start topology, and ScenePersistence actor is always the one to start the listener. if (m_isSyncListenerLocal) { - StartSyncListener(); + StartLocalSyncListener(); + } + else + { + //Start connecting to the remote listener. TO BE IMPLEMENTED. + //For now, the connection will be started by manually typing in "sync start". } } @@ -147,7 +149,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule get { return m_isSyncRelay; } } - private RegionSyncListener m_regionSyncListener = null; + private RegionSyncListener m_localSyncListener = null; public void SendObjectUpdates(List sog) { @@ -225,18 +227,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule //private bool m_active = true; private bool m_isSyncListenerLocal = false; - private string m_syncListenerAddr; - public string SyncListenerAddr - { - get { return m_syncListenerAddr; } - } - - private int m_syncListenerPort; - public int SyncListenerPort - { - get { return m_syncListenerPort; } - } + //private RegionSyncListenerInfo m_localSyncListenerInfo + private HashSet m_remoteSyncListeners; private Scene m_scene; public Scene LocalScene @@ -244,44 +237,82 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule get { return m_scene; } } + private IConfig m_sysConfig = null; + + //The list of SyncConnectors. ScenePersistence could have multiple SyncConnectors, each connecting to a differerent actor. + //An actor could have several SyncConnectors as well, each connecting to a ScenePersistence that hosts a portion of the objects/avatars + //the actor operates on. private HashSet m_syncConnectors=null; private object m_syncConnectorsLock = new object(); + + //Timers for periodically status report has not been implemented yet. private System.Timers.Timer m_statsTimer = new System.Timers.Timer(1000); - - private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e) { //TO BE IMPLEMENTED m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet implemented."); } - private void StartSyncListener() + private void StartLocalSyncListener() { - m_regionSyncListener = new RegionSyncListener(m_syncListenerAddr, m_syncListenerPort, this); - m_regionSyncListener.Start(); + RegionSyncListenerInfo localSyncListenerInfo = GetLocalSyncListenerInfo(); + m_localSyncListener = new RegionSyncListener(localSyncListenerInfo, this); + m_localSyncListener.Start(); //STATS TIMER: TO BE IMPLEMENTED //m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); //m_statsTimer.Start(); } + //Get the information for local IP:Port for listening incoming connection requests. + //For now, we use configuration to access the information. Might be replaced by some Grid Service later on. + private RegionSyncListenerInfo GetLocalSyncListenerInfo() + { + string listenerAddrDefault = m_sysConfig.GetString("ServerIPAddress", "127.0.0.1"); + string addr = m_sysConfig.GetString("SyncListenerIPAddress", listenerAddrDefault); + int port = m_sysConfig.GetInt("SyncListenerPort", 13000); + RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); + + return info; + } + + //Get the information for remote [IP:Port] to connect to for synchronization purpose. + //For example, an actor may need to connect to several ScenePersistence's if the objects it operates are hosted collectively + //by these ScenePersistence. + //For now, we use configuration to access the information. Might be replaced by some Grid Service later on. + //And for now, we assume there is only 1 remote listener to connect to. + private void GetRemoteSyncListenerInfo() + { + string listenerAddrDefault = m_sysConfig.GetString("ServerIPAddress", "127.0.0.1"); + string addr = m_sysConfig.GetString("SyncListenerIPAddress", listenerAddrDefault); + int port = m_sysConfig.GetInt("SyncListenerPort", 13000); + RegionSyncListenerInfo info = new RegionSyncListenerInfo(addr, port); + + if (m_remoteSyncListeners == null) + { + m_remoteSyncListeners = new HashSet(); + m_remoteSyncListeners.Add(info); + } + } + private void SyncStart(Object[] args) { if (m_isSyncListenerLocal) { - if (m_regionSyncListener.IsListening) + if (m_localSyncListener.IsListening) { m_log.Warn("[REGION SYNC MODULE]: RegionSyncListener is local, already started"); } else { - StartSyncListener(); + StartLocalSyncListener(); } } else { - + GetRemoteSyncListenerInfo(); + StartSyncConnections(); } } @@ -289,14 +320,15 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { if (m_isSyncListenerLocal) { - if (m_regionSyncListener.IsListening) + if (m_localSyncListener.IsListening) { - m_regionSyncListener.Shutdown(); + m_localSyncListener.Shutdown(); } } else { - + //Shutdown all sync connectors + StopAllSyncConnectors(); } } @@ -306,6 +338,21 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule m_log.Warn("[REGION SYNC MODULE]: SyncStatus() TO BE IMPLEMENTED !!!"); } + //Start connections to each remote listener. + //For now, there is only one remote listener. + private void StartSyncConnections() + { + foreach (RegionSyncListenerInfo remoteListener in m_remoteSyncListeners) + { + SyncConnector syncConnector = new SyncConnector(remoteListener); + if (syncConnector.Start()) + { + AddSyncConnector(syncConnector); + } + } + } + + public void AddSyncConnector(TcpClient tcpclient) { //IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address; @@ -347,15 +394,40 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule } } + public void StopAllSyncConnectors() + { + lock (m_syncConnectorsLock) + { + foreach (SyncConnector syncConnector in m_syncConnectors) + { + syncConnector.Stop(); + } + + m_syncConnectors.Clear(); + } + } + #endregion //RegionSyncModule members and functions } + public class RegionSyncListenerInfo + { + public IPAddress Addr; + public int Port; + + //TO ADD: reference to RegionInfo that describes the shape/size of the space that the listener is associated with + + public RegionSyncListenerInfo(string addr, int port) + { + Addr = IPAddress.Parse(addr); + Port = port; + } + } public class RegionSyncListener { - private IPAddress m_addr; - private Int32 m_port; + private RegionSyncListenerInfo m_listenerInfo; private RegionSyncModule m_regionSyncModule; private ILog m_log; @@ -369,10 +441,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule get { return m_isListening; } } - public RegionSyncListener(string addr, int port, RegionSyncModule regionSyncModule) + public RegionSyncListener(RegionSyncListenerInfo listenerInfo, RegionSyncModule regionSyncModule) { - m_addr = IPAddress.Parse(addr); - m_port = port; + m_listenerInfo = listenerInfo; m_regionSyncModule = regionSyncModule; m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); @@ -405,7 +476,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule // When connected, start the ReceiveLoop for the new client private void Listen() { - m_listener = new TcpListener(m_addr, m_port); + m_listener = new TcpListener(m_listenerInfo.Addr, m_listenerInfo.Port); try { @@ -414,7 +485,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule while (true) { // *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error - m_log.WarnFormat("[REGION SYNC SERVER] Listening for new connections on {0}:{1}...", m_addr.ToString(), m_port.ToString()); + m_log.WarnFormat("[REGION SYNC SERVER] Listening for new connections on {0}:{1}...", m_listenerInfo.Addr.ToString(), m_listenerInfo.Port.ToString()); TcpClient tcpclient = m_listener.AcceptTcpClient(); //pass the tcpclient information to RegionSyncModule, who will then create a SyncConnector diff --git a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs index 661e190c02..90869b1a2f 100755 --- a/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs +++ b/OpenSim/Region/CoreModules/RegionSync/RegionSyncModule/SymmetricSync/SyncConnector.cs @@ -2,19 +2,101 @@ * Copyright (c) Contributors: TO BE FILLED */ - +using System; using System.Collections.Generic; using System.Net.Sockets; +using System.Threading; +using log4net; namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule { public class SyncConnector { private TcpClient m_tcpConnection = null; + private RegionSyncListenerInfo m_remoteListenerInfo = null; + private Thread m_rcvLoop; + private string LogHeader = "[SYNC CONNECTOR]"; + // The logfile + private ILog m_log; public SyncConnector(TcpClient tcpclient) { m_tcpConnection = tcpclient; } + + public SyncConnector(RegionSyncListenerInfo listenerInfo) + { + m_remoteListenerInfo = listenerInfo; + } + + //Start the connection + public bool Start() + { + m_tcpConnection = new TcpClient(); + try + { + m_tcpConnection.Connect(m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port); + } + catch (Exception e) + { + m_log.WarnFormat("{0} [Start] Could not connect to RegionSyncServer at {1}:{2}", LogHeader, m_remoteListenerInfo.Addr, m_remoteListenerInfo.Port); + m_log.Warn(e.Message); + return false; + } + + m_rcvLoop = new Thread(new ThreadStart(ReceiveLoop)); + m_rcvLoop.Name = "SyncConnector ReceiveLoop"; + m_log.WarnFormat("{0} Starting {1} thread", LogHeader, m_rcvLoop.Name); + m_rcvLoop.Start(); + + return true; + } + + public void Stop() + { + // The remote scene will remove our avatars automatically when we disconnect + //m_rcvLoop.Abort(); + + // Close the connection + m_tcpConnection.Client.Close(); + m_tcpConnection.Close(); + } + + // *** This is the main thread loop for each sync connection + private void ReceiveLoop() + { + m_log.WarnFormat("{0} Thread running: {1}", LogHeader, m_rcvLoop.Name); + while (true && m_tcpConnection.Connected) + { + RegionSyncMessage msg; + // Try to get the message from the network stream + try + { + msg = new RegionSyncMessage(m_tcpConnection.GetStream()); + //m_log.WarnFormat("{0} Received: {1}", LogHeader, msg.ToString()); + } + // If there is a problem reading from the client, shut 'er down. + catch + { + //ShutdownClient(); + Stop(); + return; + } + // Try handling the message + try + { + HandleMessage(msg); + } + catch (Exception e) + { + m_log.WarnFormat("{0} Encountered an exception: {1} (MSGTYPE = {2})", LogHeader, e.Message, msg.ToString()); + } + } + } + + private void HandleMessage(RegionSyncMessage msg) + { + + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b56647c32b..a7fdd4bb3d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1414,7 +1414,7 @@ namespace OpenSim.Region.Framework.Scenes // If it's a client manager, just send prim updates // This will get fixed later to only send to locally logged in presences rather than all presences // but requires pulling apart the concept of a client from the concept of a presence/avatar - if (IsSyncedClient() || !RegionSyncEnabled) + if (IsSyncedClient()) { ForEachScenePresence(delegate(ScenePresence sp) { sp.SendPrimUpdates(); });