Fixed the IRC code so that it deals with regions coming and
going.
0.6.1-post-fixes
Dr Scofield 2008-11-14 10:50:36 +00:00
parent 4e0a424f9f
commit 62317ded9f
4 changed files with 133 additions and 114 deletions

View File

@ -256,20 +256,25 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// values that, while independent of the IRC connetion, do still distinguish
// this region's behavior.
foreach (ChannelState xcs in IRCBridgeModule.m_channels)
lock (IRCBridgeModule.m_channels)
{
if (cs.IsAPerfectMatchFor(xcs))
foreach (ChannelState xcs in IRCBridgeModule.m_channels)
{
m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn);
cs = xcs;
break;
}
if (cs.IsAConnectionMatchFor(xcs))
{
m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn);
cs.irc = xcs.irc;
break;
if (cs.IsAPerfectMatchFor(xcs))
{
m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn);
cs = xcs;
break;
}
if (cs.IsAConnectionMatchFor(xcs))
{
m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn);
cs.irc = xcs.irc;
break;
}
}
}
// No entry was found, so this is going to be a new entry.
@ -281,6 +286,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
if ((cs.irc = new IRCConnector(cs)) != null)
{
IRCBridgeModule.m_channels.Add(cs);
m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
@ -302,11 +308,12 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
}
m_log.InfoFormat("[IRC-Channel-{0}] Region {1} connected to channel {2} on server {3}:{4}",
m_log.InfoFormat("[IRC-Channel-{0}] Region {1} associated with channel {2} on server {3}:{4}",
cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
// We're finally ready to commit ourselves
return cs;
}
@ -443,6 +450,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// Repeatedly scan the string until all possible
// substitutions have been performed.
// m_log.DebugFormat("[IRC-Channel] Parse[1]: {0}", result);
while (arg.IsMatch(result))
{
@ -476,28 +485,26 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
result = result.Replace(vvar, rs.config.GetString(var,var));
break;
}
// m_log.DebugFormat("[IRC-Channel] Parse[2]: {0}", result);
}
// m_log.DebugFormat("[IRC-Channel] Parse[3]: {0}", result);
return result;
}
public void Close()
{
m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1} to server <{2}:{3}>",
m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1}> to server <{2}:{3}>",
idn, IrcChannel, Server, Port);
m_log.InfoFormat("[IRC-Channel-{0}] There are {1} active clients",
idn, clientregions.Count);
irc.Close();
}
public void Open()
{
m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1} to server <{2}:{3}>",
m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1}> to server <{2}:{3}>",
idn, IrcChannel, Server, Port);
irc.Open();
@ -514,16 +521,30 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
Open();
}
// Close is called to ensure that the IRC session is terminated if this is the
// only client.
public void Close(RegionState rs)
{
RemoveRegion(rs);
lock (IRCBridgeModule.m_channels)
{
if (clientregions.Count == 0)
{
Close();
IRCBridgeModule.m_channels.Remove(this);
m_log.InfoFormat("[IRC-Channel-{0}] Region {1} is last user of channel <{2}> to server <{3}:{4}>",
idn, rs.Region, IrcChannel, Server, Port);
m_log.InfoFormat("[IRC-Channel-{0}] Removed", idn);
}
}
}
// Add a client region to this channel if it is not already known
public void AddRegion(RegionState rs)
{
m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2} to server <{3}:{4}>",
m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2}> to server <{3}:{4}>",
idn, rs.Region, IrcChannel, Server, Port);
if (!clientregions.Contains(rs))
{
@ -568,28 +589,30 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// Note that this code is responsible for completing some of the
// settings for the inbound OSChatMessage
foreach (ChannelState cs in IRCBridgeModule.m_channels)
lock (IRCBridgeModule.m_channels)
{
if ( p_irc == cs.irc)
foreach (ChannelState cs in IRCBridgeModule.m_channels)
{
// This non-IRC differentiator moved to here
if (cmsg && !cs.ClientReporting)
continue;
// This non-IRC differentiator moved to here
c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0);
foreach (RegionState region in cs.clientregions)
if ( p_irc == cs.irc)
{
region.OSChat(cs.irc, c);
}
// This non-IRC differentiator moved to here
if (cmsg && !cs.ClientReporting)
continue;
// This non-IRC differentiator moved to here
c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0);
foreach (RegionState region in cs.clientregions)
{
region.OSChat(cs.irc, c);
}
}
}
}
}
catch (Exception ex)
{

View File

@ -49,11 +49,13 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
internal static bool enabled = false;
internal static IConfig m_config = null;
internal static List<RegionState> m_regions = new List<RegionState>();
internal static List<ChannelState> m_channels = new List<ChannelState>();
internal static List<RegionState> m_regions = new List<RegionState>();
internal static string password = String.Empty;
internal RegionState region = null;
#region IRegionModule Members
public string Name
@ -63,7 +65,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
public bool IsSharedModule
{
get { return true; }
get { return false; }
}
public void Initialise(Scene scene, IConfigSource config)
@ -110,13 +112,18 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// Iff the IRC bridge is enabled, then each new region may be
// connected to IRC. But it should NOT be obligatory (and it
// is not).
// We have to do ALL of the startup here because PostInitialize
// is not called when a region gets created in-flight from the
// command line.
if (enabled)
{
try
{
m_log.InfoFormat("[IRC-Bridge] Connecting region {0}", scene.RegionInfo.RegionName);
m_regions.Add(new RegionState(scene, m_config));
region = new RegionState(scene, m_config);
lock(m_regions) m_regions.Add(region);
region.Open();
}
catch (Exception e)
{
@ -131,37 +138,17 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
}
// Called after all region modules have been loaded.
// Iff the IRC bridge is enabled, then start all of the
// configured channels. The set of channels is a side
// effect of RegionState creation.
// This module can be called in-flight in which case PostInitialize
// is not called following Initialize. So no use is made of this
// call.
public void PostInitialise()
{
if (!enabled)
return;
foreach (RegionState region in m_regions)
{
m_log.InfoFormat("[IRC-Bridge] Opening connection for {0}:{1} on IRC server {2}:{3}",
region.Region, region.cs.BaseNickname, region.cs.Server, region.cs.IrcChannel);
try
{
region.Open();
}
catch (Exception e)
{
m_log.ErrorFormat("[IRC-Bridge] Open failed for {0}:{1} on IRC server {2}:{3} : {4}",
region.Region, region.cs.BaseNickname, region.cs.Server, region.cs.IrcChannel,
e.Message);
}
}
}
// Called immediately before the region module is unloaded. Close all
// associated channels.
// Called immediately before the region module is unloaded. Cleanup
// the region.
public void Close()
{
@ -169,47 +156,14 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
if (!enabled)
return;
// Stop each of the region sessions
foreach (RegionState region in m_regions)
{
m_log.InfoFormat("[IRC-Bridge] Closing connection for {0}:{1} on IRC server {2}:{3}",
region.Region, region.cs.BaseNickname, region.cs.Server, region.cs.IrcChannel);
try
{
region.Close();
}
catch (Exception e)
{
m_log.ErrorFormat("[IRC-Bridge] Close failed for {0}:{1} on IRC server {2}:{3} : {4}",
region.Region, region.cs.BaseNickname, region.cs.Server, region.cs.IrcChannel,
e.Message);
}
}
// Perform final cleanup of the channels (they now have no active clients)
foreach (ChannelState channel in m_channels)
{
m_log.InfoFormat("[IRC-Bridge] Closing connection for {0} on IRC server {1}:{2}",
channel.BaseNickname, channel.Server, channel.IrcChannel);
try
{
channel.Close();
}
catch (Exception e)
{
m_log.ErrorFormat("[IRC-Bridge] Close failed for {0} on IRC server {1}:{2} : {3}",
channel.BaseNickname, channel.Server, channel.IrcChannel,
e.Message);
}
}
region.Close();
lock(m_regions) m_regions.Remove(region);
}
#endregion
public XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request)
public static XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request)
{
m_log.Info("[IRC-Bridge]: XML RPC Admin Entry");

View File

@ -57,6 +57,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
private const int WD_INTERVAL = 1000; // base watchdog interval
private static int PING_PERIOD = 15; // WD intervals per PING
private static int ICCD_PERIOD = 10; // WD intervals between Connects
private static int L_TIMEOUT = 10; // Login time out interval
private static int _idk_ = 0; // core connector identifier
private static int _pdk_ = 0; // ping interval counter
@ -118,6 +119,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
}
private bool m_connected = false; // connection status
private bool m_pending = false; // login disposition
private int m_timeout = L_TIMEOUT; // login timeout counter
public bool Connected
{
get { return m_connected; }
@ -326,6 +329,8 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
if (m_connected) return;
m_connected = true;
m_pending = true;
m_timeout = L_TIMEOUT;
m_tcp = new TcpClient(m_server, (int)m_port);
m_stream = m_tcp.GetStream();
@ -349,8 +354,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
m_writer.Flush();
m_log.InfoFormat("[IRC-Connector-{0}]: {1} has joined {2}", idn, m_nick, m_ircChannel);
m_log.InfoFormat("[IRC-Connector-{0}] Connected", idn);
m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel);
}
catch (Exception e)
@ -358,6 +362,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
m_log.ErrorFormat("[IRC-Connector-{0}] cannot connect {1} to {2}:{3}: {4}",
idn, m_nick, m_server, m_port, e.Message);
m_connected = false;
m_pending = false;
}
}
@ -396,6 +401,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
try { m_tcp.Close(); } catch (Exception) {}
m_connected = false;
m_pending = false;
}
@ -516,7 +522,12 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
// m_log.Debug(e);
}
// This is potentially circular, but harmless if so.
// The connection is marked as not connected the first time
// through reconnect.
if (m_enabled) Reconnect();
}
private Regex RE = new Regex(@":(?<nick>[\w-]*)!(?<user>\S*) PRIVMSG (?<channel>\S+) :(?<msg>.*)",
@ -615,7 +626,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
case "003" : // Welcome ...
break;
case "004" : // Server information
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
commArgs = parms.Split(CS_SPACE);
c_server = commArgs[1];
m_server = c_server;
@ -639,10 +650,10 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
case "366" : // End-of-Name list marker
case "372" : // MOTD body
case "375" : // MOTD start
m_log.InfoFormat("[IRC-Connector-{0}] {1}", idn, parms.Split(CS_SPACE,2)[1]);
m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
break;
case "376" : // MOTD end
m_log.InfoFormat("[IRC-Connector-{0}] {1}", idn, parms.Split(CS_SPACE,2)[1]);
m_log.InfoFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
motd = true;
break;
case "451" : // Not registered
@ -650,7 +661,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
case "433" : // Nickname in use
// Gen a new name
m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
m_log.ErrorFormat("[IRC-Connector-{0}]: IRC SERVER reports NicknameInUse, trying {1}", idn, m_nick);
m_log.ErrorFormat("[IRC-Connector-{0}]: [{1}] IRC SERVER reports NicknameInUse, trying {2}", idn, cmd, m_nick);
// Retry
m_writer.WriteLine(String.Format("NICK {0}", m_nick));
m_writer.Flush();
@ -659,43 +670,57 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel));
m_writer.Flush();
break;
case "479" : // Bad channel name, etc. This will never work, so disable the connection
m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] Connector disabled", idn, cmd);
m_enabled = false;
m_connected = false;
m_pending = false;
break;
case "NOTICE" :
m_log.WarnFormat("[IRC-Connector-{0}] {1}", idn, parms.Split(CS_SPACE,2)[1]);
m_log.WarnFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
break;
case "ERROR" :
m_log.ErrorFormat("[IRC-Connector-{0}] {1}", idn, parms.Split(CS_SPACE,2)[1]);
m_log.ErrorFormat("[IRC-Connector-{0}] [{1}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]);
if (parms.Contains("reconnect too fast"))
ICCD_PERIOD++;
m_pending = false;
Reconnect();
break;
case "PING" :
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
m_writer.WriteLine(String.Format("PONG {0}", parms));
m_writer.Flush();
break;
case "PONG" :
break;
case "JOIN":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
if (m_pending)
{
m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd);
m_pending = false;
}
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcJoin(pfx, cmd, parms);
break;
case "PART":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcPart(pfx, cmd, parms);
break;
case "MODE":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcMode(pfx, cmd, parms);
break;
case "NICK":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcNickChange(pfx, cmd, parms);
break;
case "KICK":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcKick(pfx, cmd, parms);
break;
case "QUIT":
m_log.DebugFormat("[IRC-Connector-{0}] parms = <{1}>", idn, parms);
m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms);
eventIrcQuit(pfx, cmd, parms);
break;
default :
@ -813,6 +838,18 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
}
else
{
if (connector.m_pending)
{
if (connector.m_timeout == 0)
{
m_log.ErrorFormat("[IRC-Watchdog] Login timed-out for connector {0}, reconnecting", connector.idn);
connector.Reconnect();
}
else
connector.m_timeout--;
}
if (_pdk_ == 0)
{
try
@ -827,6 +864,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
connector.Reconnect();
}
}
}
}
}

View File

@ -123,6 +123,10 @@ namespace OpenSim.Region.Environment.Modules.Avatar.Chat
}
// Called by IRCBridgeModule.Close immediately prior to unload
// of the module for this region. This happens when the region
// is being removed or the server is terminating. The IRC
// BridgeModule will remove the region from the region list
// when control returns.
public void Close()
{