123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- /*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- using System;
- using System.Collections.Generic;
- using System.Reflection;
- using System.Text.RegularExpressions;
- using log4net;
- using Nini.Config;
- using OpenSim.Framework;
- using OpenSim.Region.Framework.Interfaces;
- using OpenSim.Region.Framework.Scenes;
- namespace OpenSim.Region.OptionalModules.Avatar.Chat
- {
- // An instance of this class exists for each unique combination of
- // IRC chat interface characteristics, as determined by the supplied
- // configuration file.
- internal class ChannelState
- {
- private static readonly ILog m_log =
- LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- private static Regex arg = new Regex(@"\[[^\[\]]*\]");
- private static int _idk_ = 0;
- private static int DEBUG_CHANNEL = 2147483647;
- // These are the IRC Connector configurable parameters with hard-wired
- // default values (retained for compatability).
- internal string Server = null;
- internal string Password = null;
- internal string IrcChannel = null;
- internal string BaseNickname = "OSimBot";
- internal uint Port = 6667;
- internal string User = null;
- internal bool ClientReporting = true;
- internal bool RelayChat = true;
- internal bool RelayPrivateChannels = false;
- internal int RelayChannel = 1;
- internal List<int> ValidInWorldChannels = new List<int>();
- // Connector agnostic parameters. These values are NOT shared with the
- // connector and do not differentiate at an IRC level
- internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}";
- internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}";
- internal int RelayChannelOut = -1;
- internal bool RandomizeNickname = true;
- internal bool CommandsEnabled = false;
- internal int CommandChannel = -1;
- internal int ConnectDelay = 10;
- internal int PingDelay = 15;
- internal string DefaultZone = "Sim";
- internal string _accessPassword = String.Empty;
- internal Regex AccessPasswordRegex = null;
- internal List<string> ExcludeList = new List<string>();
- internal string AccessPassword
- {
- get { return _accessPassword; }
- set
- {
- _accessPassword = value;
- AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword),
- RegexOptions.Compiled);
- }
- }
- // IRC connector reference
- internal IRCConnector irc = null;
- internal int idn = _idk_++;
- // List of regions dependent upon this connection
- internal List<RegionState> clientregions = new List<RegionState>();
- // Needed by OpenChannel
- internal ChannelState()
- {
- }
- // This constructor is used by the Update* methods. A copy of the
- // existing channel state is created, and distinguishing characteristics
- // are copied across.
- internal ChannelState(ChannelState model)
- {
- Server = model.Server;
- Password = model.Password;
- IrcChannel = model.IrcChannel;
- Port = model.Port;
- BaseNickname = model.BaseNickname;
- RandomizeNickname = model.RandomizeNickname;
- User = model.User;
- CommandsEnabled = model.CommandsEnabled;
- CommandChannel = model.CommandChannel;
- RelayChat = model.RelayChat;
- RelayPrivateChannels = model.RelayPrivateChannels;
- RelayChannelOut = model.RelayChannelOut;
- RelayChannel = model.RelayChannel;
- ValidInWorldChannels = model.ValidInWorldChannels;
- PrivateMessageFormat = model.PrivateMessageFormat;
- NoticeMessageFormat = model.NoticeMessageFormat;
- ClientReporting = model.ClientReporting;
- AccessPassword = model.AccessPassword;
- DefaultZone = model.DefaultZone;
- ConnectDelay = model.ConnectDelay;
- PingDelay = model.PingDelay;
- }
-
- // Read the configuration file, performing variable substitution and any
- // necessary aliasing. See accompanying documentation for how this works.
- // If you don't need variables, then this works exactly as before.
- // If either channel or server are not specified, the request fails.
- internal static void OpenChannel(RegionState rs, IConfig config)
- {
- // Create a new instance of a channel. This may not actually
- // get used if an equivalent channel already exists.
- ChannelState cs = new ChannelState();
- // Read in the configuration file and filter everything for variable
- // subsititution.
- m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
- cs.Server = Substitute(rs, config.GetString("server", null));
- m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
- cs.Password = Substitute(rs, config.GetString("password", null));
- // probably not a good idea to put a password in the log file
- cs.User = Substitute(rs, config.GetString("user", null));
- cs.IrcChannel = Substitute(rs, config.GetString("channel", null));
- m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
- cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port))));
- m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
- cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname));
- m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
- cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname))));
- m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
- cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname))));
- m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
- cs.User = Substitute(rs, config.GetString("username", cs.User));
- m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
- cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled))));
- m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
- cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel))));
- m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
- cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel))));
- m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
- cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString("relay_chat", Convert.ToString(cs.RelayChat))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat);
- cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
- cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
- cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
- cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
- cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel))));
- m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
- cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat));
- m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
- cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat));
- m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
- cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0;
- m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
- cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting))));
- m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
- cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone));
- m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
- cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay))));
- m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
- cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay))));
- m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
- cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword));
- m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
- string[] excludes = config.GetString("exclude_list", "").Trim().Split(new Char[] { ',' });
- cs.ExcludeList = new List<string>(excludes.Length);
- foreach (string name in excludes)
- {
- cs.ExcludeList.Add(name.Trim().ToLower());
- }
-
- // Fail if fundamental information is still missing
- if (cs.Server == null || cs.IrcChannel == null || cs.BaseNickname == null || cs.User == null)
- throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}", cs.idn, rs.Region));
- m_log.InfoFormat("[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region);
- m_log.InfoFormat("[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server);
- m_log.InfoFormat("[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel);
- m_log.InfoFormat("[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port);
- m_log.InfoFormat("[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname);
- m_log.InfoFormat("[IRC-Channel-{0}] User = {1}", cs.idn, cs.User);
- // Set the channel state for this region
- if (cs.RelayChat)
- {
- cs.ValidInWorldChannels.Add(0);
- cs.ValidInWorldChannels.Add(DEBUG_CHANNEL);
- }
- if (cs.RelayPrivateChannels)
- cs.ValidInWorldChannels.Add(cs.RelayChannelOut);
- rs.cs = Integrate(rs, cs);
- }
- // An initialized channel state instance is passed in. If an identical
- // channel state instance already exists, then the existing instance
- // is used to replace the supplied value.
- // If the instance matches with respect to IRC, then the underlying
- // IRCConnector is assigned to the supplied channel state and the
- // updated value is returned.
- // If there is no match, then the supplied instance is completed by
- // creating and assigning an instance of an IRC connector.
- private static ChannelState Integrate(RegionState rs, ChannelState p_cs)
- {
- ChannelState cs = p_cs;
- // Check to see if we have an existing server/channel setup that can be used
- // In the absence of variable substitution this will always resolve to the
- // same ChannelState instance, and the table will only contains a single
- // entry, so the performance considerations for the existing behavior are
- // zero. Only the IRC connector is shared, the ChannelState still contains
- // values that, while independent of the IRC connetion, do still distinguish
- // this region's behavior.
- lock (IRCBridgeModule.m_channels)
- {
- foreach (ChannelState xcs in IRCBridgeModule.m_channels)
- {
- 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.
- if (cs.irc == null)
- {
- m_log.DebugFormat("[IRC-Channel-{0}] New channel required", cs.idn);
- 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}",
- cs.idn, rs.Region, cs.DefaultZone,
- cs.CommandsEnabled ? "enabled" : "not enabled",
- cs.RelayPrivateChannels ? "relayed" : "not relayed");
- }
- else
- {
- string txt = String.Format("[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}",
- cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
- m_log.Error(txt);
- throw new Exception(txt);
- }
- }
- else
- {
- m_log.InfoFormat("[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}",
- cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
- }
- 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;
- }
- // These routines allow differentiating changes to
- // the underlying channel state. If necessary, a
- // new channel state will be created.
- internal ChannelState UpdateServer(RegionState rs, string server)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.Server = server;
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdatePort(RegionState rs, string port)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.Port = Convert.ToUInt32(port);
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdateChannel(RegionState rs, string channel)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.IrcChannel = channel;
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdateNickname(RegionState rs, string nickname)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.BaseNickname = nickname;
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdateClientReporting(RegionState rs, string cr)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.ClientReporting = Convert.ToBoolean(cr);
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdateRelayIn(RegionState rs, string channel)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.RelayChannel = Convert.ToInt32(channel);
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- internal ChannelState UpdateRelayOut(RegionState rs, string channel)
- {
- RemoveRegion(rs);
- ChannelState cs = new ChannelState(this);
- cs.RelayChannelOut = Convert.ToInt32(channel);
- cs = Integrate(rs, cs);
- cs.AddRegion(rs);
- return cs;
- }
- // Determine whether or not this is a 'new' channel. Only those
- // attributes that uniquely distinguish an IRC connection should
- // be included here (and only those attributes should really be
- // in the ChannelState structure)
- private bool IsAConnectionMatchFor(ChannelState cs)
- {
- return (
- Server == cs.Server &&
- IrcChannel == cs.IrcChannel &&
- Port == cs.Port &&
- BaseNickname == cs.BaseNickname &&
- User == cs.User
- );
- }
- // This level of obsessive matching allows us to produce
- // a minimal overhead int he case of a server which does
- // need to differentiate IRC at a region level.
- private bool IsAPerfectMatchFor(ChannelState cs)
- {
- return (IsAConnectionMatchFor(cs) &&
- RelayChannelOut == cs.RelayChannelOut &&
- PrivateMessageFormat == cs.PrivateMessageFormat &&
- NoticeMessageFormat == cs.NoticeMessageFormat &&
- RandomizeNickname == cs.RandomizeNickname &&
- AccessPassword == cs.AccessPassword &&
- CommandsEnabled == cs.CommandsEnabled &&
- CommandChannel == cs.CommandChannel &&
- DefaultZone == cs.DefaultZone &&
- RelayPrivateChannels == cs.RelayPrivateChannels &&
- RelayChannel == cs.RelayChannel &&
- RelayChat == cs.RelayChat &&
- ClientReporting == cs.ClientReporting
- );
- }
- // This function implements the variable substitution mechanism
- // for the configuration values. Each string read from the
- // configuration file is scanned for '[...]' enclosures. Each
- // one that is found is replaced by either a runtime variable
- // (%xxx) or an existing configuration key. When no further
- // substitution is possible, the remaining string is returned
- // to the caller. This allows for arbitrarily nested
- // enclosures.
- private static string Substitute(RegionState rs, string instr)
- {
- string result = instr;
- if (result == null || result.Length == 0)
- return result;
- // Repeatedly scan the string until all possible
- // substitutions have been performed.
- // m_log.DebugFormat("[IRC-Channel] Parse[1]: {0}", result);
- while (arg.IsMatch(result))
- {
- string vvar = arg.Match(result).ToString();
- string var = vvar.Substring(1,vvar.Length-2).Trim();
- switch (var.ToLower())
- {
- case "%region" :
- result = result.Replace(vvar, rs.Region);
- break;
- case "%host" :
- result = result.Replace(vvar, rs.Host);
- break;
- case "%master1" :
- result = result.Replace(vvar, rs.MA1);
- break;
- case "%master2" :
- result = result.Replace(vvar, rs.MA2);
- break;
- case "%locx" :
- result = result.Replace(vvar, rs.LocX);
- break;
- case "%locy" :
- result = result.Replace(vvar, rs.LocY);
- break;
- case "%k" :
- result = result.Replace(vvar, rs.IDK);
- break;
- default :
- 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}>",
- 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}>",
- idn, IrcChannel, Server, Port);
- irc.Open();
- }
- // These are called by each region that attaches to this channel. The call affects
- // only the relationship of the region with the channel. Not the channel to IRC
- // relationship (unless it is closed and we want it open).
- public void Open(RegionState rs)
- {
- AddRegion(rs);
- 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}>",
- idn, rs.Region, IrcChannel, Server, Port);
- if (!clientregions.Contains(rs))
- {
- clientregions.Add(rs);
- lock (irc) irc.depends++;
- }
- }
- // Remove a client region from the channel. If this is the last
- // region, then clean up the channel. The connector will clean itself
- // up if it finds itself about to be GC'd.
- public void RemoveRegion(RegionState rs)
- {
- m_log.InfoFormat("[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>",
- idn, rs.Region, IrcChannel, Server, Port);
- if (clientregions.Contains(rs))
- {
- clientregions.Remove(rs);
- lock (irc) irc.depends--;
- }
- }
- // This function is lifted from the IRCConnector because it
- // contains information that is not differentiating from an
- // IRC point-of-view.
- public static void OSChat(IRCConnector p_irc, OSChatMessage c, bool cmsg)
- {
- // m_log.DebugFormat("[IRC-OSCHAT] from {0}:{1}", p_irc.Server, p_irc.IrcChannel);
- try
- {
- // Scan through the set of unique channel configuration for those
- // that belong to this connector. And then forward the message to
- // all regions known to those channels.
- // Note that this code is responsible for completing some of the
- // settings for the inbound OSChatMessage
- lock (IRCBridgeModule.m_channels)
- {
- foreach (ChannelState cs in IRCBridgeModule.m_channels)
- {
- if (p_irc == cs.irc)
- {
- // 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)
- {
- m_log.ErrorFormat("[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message);
- m_log.Debug(ex);
- }
- }
- }
- }
|