Added code to initiate listener or start connecting to remote listeners.

dsg
Huaiyu (Kitty) Liu 2010-12-21 17:15:30 -08:00
parent cb49cfe6c5
commit c1af982ff4
3 changed files with 195 additions and 42 deletions

View File

@ -35,32 +35,29 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IConfig syncConfig = config.Configs["RegionSyncModule"]; IConfig m_sysConfig = config.Configs["RegionSyncModule"];
m_active = false; m_active = false;
if (syncConfig == null) if (m_sysConfig == null)
{ {
m_log.Warn("[REGION SYNC MODULE] No RegionSyncModule config section found. Shutting down."); m_log.Warn("[REGION SYNC MODULE] No RegionSyncModule config section found. Shutting down.");
return; 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."); m_log.Warn("[REGION SYNC MODULE] RegionSyncModule is not enabled. Shutting down.");
return; return;
} }
m_actorID = syncConfig.GetString("ActorID", ""); m_actorID = m_sysConfig.GetString("ActorID", "");
if (m_actorID == "") if (m_actorID == "")
{ {
m_log.Error("ActorID not defined in [RegionSyncModule] section in config file"); m_log.Error("ActorID not defined in [RegionSyncModule] section in config file");
return; return;
} }
m_isSyncRelay = syncConfig.GetBoolean("IsSyncRelay", false); m_isSyncRelay = m_sysConfig.GetBoolean("IsSyncRelay", false);
m_isSyncListenerLocal = syncConfig.GetBoolean("IsSyncListenerLocal", false); m_isSyncListenerLocal = m_sysConfig.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_active = true; 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. //For now, we use start topology, and ScenePersistence actor is always the one to start the listener.
if (m_isSyncListenerLocal) 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; } get { return m_isSyncRelay; }
} }
private RegionSyncListener m_regionSyncListener = null; private RegionSyncListener m_localSyncListener = null;
public void SendObjectUpdates(List<SceneObjectGroup> sog) public void SendObjectUpdates(List<SceneObjectGroup> sog)
{ {
@ -225,18 +227,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
//private bool m_active = true; //private bool m_active = true;
private bool m_isSyncListenerLocal = false; private bool m_isSyncListenerLocal = false;
private string m_syncListenerAddr; //private RegionSyncListenerInfo m_localSyncListenerInfo
public string SyncListenerAddr
{
get { return m_syncListenerAddr; }
}
private int m_syncListenerPort;
public int SyncListenerPort
{
get { return m_syncListenerPort; }
}
private HashSet<RegionSyncListenerInfo> m_remoteSyncListeners;
private Scene m_scene; private Scene m_scene;
public Scene LocalScene public Scene LocalScene
@ -244,44 +237,82 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
get { return m_scene; } 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<SyncConnector> m_syncConnectors=null; private HashSet<SyncConnector> m_syncConnectors=null;
private object m_syncConnectorsLock = new object(); 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 System.Timers.Timer m_statsTimer = new System.Timers.Timer(1000);
private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e) private void StatsTimerElapsed(object source, System.Timers.ElapsedEventArgs e)
{ {
//TO BE IMPLEMENTED //TO BE IMPLEMENTED
m_log.Warn("[REGION SYNC MODULE]: StatsTimerElapsed -- NOT yet 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); RegionSyncListenerInfo localSyncListenerInfo = GetLocalSyncListenerInfo();
m_regionSyncListener.Start(); m_localSyncListener = new RegionSyncListener(localSyncListenerInfo, this);
m_localSyncListener.Start();
//STATS TIMER: TO BE IMPLEMENTED //STATS TIMER: TO BE IMPLEMENTED
//m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed); //m_statsTimer.Elapsed += new System.Timers.ElapsedEventHandler(StatsTimerElapsed);
//m_statsTimer.Start(); //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<RegionSyncListenerInfo>();
m_remoteSyncListeners.Add(info);
}
}
private void SyncStart(Object[] args) private void SyncStart(Object[] args)
{ {
if (m_isSyncListenerLocal) if (m_isSyncListenerLocal)
{ {
if (m_regionSyncListener.IsListening) if (m_localSyncListener.IsListening)
{ {
m_log.Warn("[REGION SYNC MODULE]: RegionSyncListener is local, already started"); m_log.Warn("[REGION SYNC MODULE]: RegionSyncListener is local, already started");
} }
else else
{ {
StartSyncListener(); StartLocalSyncListener();
} }
} }
else else
{ {
GetRemoteSyncListenerInfo();
StartSyncConnections();
} }
} }
@ -289,14 +320,15 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
if (m_isSyncListenerLocal) if (m_isSyncListenerLocal)
{ {
if (m_regionSyncListener.IsListening) if (m_localSyncListener.IsListening)
{ {
m_regionSyncListener.Shutdown(); m_localSyncListener.Shutdown();
} }
} }
else 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 !!!"); 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) public void AddSyncConnector(TcpClient tcpclient)
{ {
//IPAddress addr = ((IPEndPoint)tcpclient.Client.RemoteEndPoint).Address; //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 #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 public class RegionSyncListener
{ {
private IPAddress m_addr; private RegionSyncListenerInfo m_listenerInfo;
private Int32 m_port;
private RegionSyncModule m_regionSyncModule; private RegionSyncModule m_regionSyncModule;
private ILog m_log; private ILog m_log;
@ -369,10 +441,9 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
get { return m_isListening; } get { return m_isListening; }
} }
public RegionSyncListener(string addr, int port, RegionSyncModule regionSyncModule) public RegionSyncListener(RegionSyncListenerInfo listenerInfo, RegionSyncModule regionSyncModule)
{ {
m_addr = IPAddress.Parse(addr); m_listenerInfo = listenerInfo;
m_port = port;
m_regionSyncModule = regionSyncModule; m_regionSyncModule = regionSyncModule;
m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 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 // When connected, start the ReceiveLoop for the new client
private void Listen() private void Listen()
{ {
m_listener = new TcpListener(m_addr, m_port); m_listener = new TcpListener(m_listenerInfo.Addr, m_listenerInfo.Port);
try try
{ {
@ -414,7 +485,7 @@ namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
while (true) while (true)
{ {
// *** Move/Add TRY/CATCH to here, but we don't want to spin loop on the same error // *** 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(); TcpClient tcpclient = m_listener.AcceptTcpClient();
//pass the tcpclient information to RegionSyncModule, who will then create a SyncConnector //pass the tcpclient information to RegionSyncModule, who will then create a SyncConnector

View File

@ -2,19 +2,101 @@
* Copyright (c) Contributors: TO BE FILLED * Copyright (c) Contributors: TO BE FILLED
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading;
using log4net;
namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule namespace OpenSim.Region.CoreModules.RegionSync.RegionSyncModule
{ {
public class SyncConnector public class SyncConnector
{ {
private TcpClient m_tcpConnection = null; 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) public SyncConnector(TcpClient tcpclient)
{ {
m_tcpConnection = 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)
{
}
} }
} }

View File

@ -1414,7 +1414,7 @@ namespace OpenSim.Region.Framework.Scenes
// If it's a client manager, just send prim updates // 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 // 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 // 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(); }); ForEachScenePresence(delegate(ScenePresence sp) { sp.SendPrimUpdates(); });