From 180be7de07014aa33bc6066f12a0819b731c1c9d Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Tue, 10 Feb 2009 13:10:57 +0000 Subject: this is step 2 of 2 of the OpenSim.Region.Environment refactor. NOTHING has been deleted or moved off to forge at this point. what has happened is that OpenSim.Region.Environment.Modules has been split in two: - OpenSim.Region.CoreModules: all those modules that are either directly or indirectly referenced from other OpenSim packages, or that provide functionality that the OpenSim developer community considers core functionality: CoreModules/Agent/AssetTransaction CoreModules/Agent/Capabilities CoreModules/Agent/TextureDownload CoreModules/Agent/TextureSender CoreModules/Agent/TextureSender/Tests CoreModules/Agent/Xfer CoreModules/Avatar/AvatarFactory CoreModules/Avatar/Chat/ChatModule CoreModules/Avatar/Combat CoreModules/Avatar/Currency/SampleMoney CoreModules/Avatar/Dialog CoreModules/Avatar/Friends CoreModules/Avatar/Gestures CoreModules/Avatar/Groups CoreModules/Avatar/InstantMessage CoreModules/Avatar/Inventory CoreModules/Avatar/Inventory/Archiver CoreModules/Avatar/Inventory/Transfer CoreModules/Avatar/Lure CoreModules/Avatar/ObjectCaps CoreModules/Avatar/Profiles CoreModules/Communications/Local CoreModules/Communications/REST CoreModules/Framework/EventQueue CoreModules/Framework/InterfaceCommander CoreModules/Hypergrid CoreModules/InterGrid CoreModules/Scripting/DynamicTexture CoreModules/Scripting/EMailModules CoreModules/Scripting/HttpRequest CoreModules/Scripting/LoadImageURL CoreModules/Scripting/VectorRender CoreModules/Scripting/WorldComm CoreModules/Scripting/XMLRPC CoreModules/World/Archiver CoreModules/World/Archiver/Tests CoreModules/World/Estate CoreModules/World/Land CoreModules/World/Permissions CoreModules/World/Serialiser CoreModules/World/Sound CoreModules/World/Sun CoreModules/World/Terrain CoreModules/World/Terrain/DefaultEffects CoreModules/World/Terrain/DefaultEffects/bin CoreModules/World/Terrain/DefaultEffects/bin/Debug CoreModules/World/Terrain/Effects CoreModules/World/Terrain/FileLoaders CoreModules/World/Terrain/FloodBrushes CoreModules/World/Terrain/PaintBrushes CoreModules/World/Terrain/Tests CoreModules/World/Vegetation CoreModules/World/Wind CoreModules/World/WorldMap - OpenSim.Region.OptionalModules: all those modules that are not core modules: OptionalModules/Avatar/Chat/IRC-stuff OptionalModules/Avatar/Concierge OptionalModules/Avatar/Voice/AsterixVoice OptionalModules/Avatar/Voice/SIPVoice OptionalModules/ContentManagementSystem OptionalModules/Grid/Interregion OptionalModules/Python OptionalModules/SvnSerialiser OptionalModules/World/NPC OptionalModules/World/TreePopulator --- .../Modules/Avatar/Chat/ChannelState.cs | 628 --------------- .../Environment/Modules/Avatar/Chat/ChatModule.cs | 287 ------- .../Modules/Avatar/Chat/IRCBridgeModule.cs | 219 ----- .../Modules/Avatar/Chat/IRCConnector.cs | 887 --------------------- .../Environment/Modules/Avatar/Chat/RegionState.cs | 424 ---------- 5 files changed, 2445 deletions(-) delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs delete mode 100644 OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs (limited to 'OpenSim/Region/Environment/Modules/Avatar/Chat') diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs deleted file mode 100644 index dfa1caa..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs +++ /dev/null @@ -1,628 +0,0 @@ -/* - * 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 OpenSim 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.Environment.Modules.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 = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; - - internal bool ClientReporting = true; - internal bool RelayChat = true; - internal bool RelayPrivateChannels = false; - internal int RelayChannel = 1; - internal List ValidInWorldChannels = new List(); - - // 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 string AccessPassword - { - get { return _accessPassword; } - set - { - _accessPassword = value; - AccessPasswordRegex = new Regex(String.Format(@"^{0},\s*(?[^,]+),\s*(?.+)$", _accessPassword), - RegexOptions.Compiled); - } - } - - - - // IRC connector reference - - internal IRCConnector irc = null; - - internal int idn = _idk_++; - - // List of regions dependent upon this connection - - internal List clientregions = new List(); - - // 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.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); - - - // 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); - } - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs deleted file mode 100644 index f234b75..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChatModule.cs +++ /dev/null @@ -1,287 +0,0 @@ -/* - * 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 OpenSim 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.IO; -using System.Net.Sockets; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class ChatModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const int DEBUG_CHANNEL = 2147483647; - - private bool m_enabled = true; - private int m_saydistance = 30; - private int m_shoutdistance = 100; - private int m_whisperdistance = 10; - private List m_scenes = new List(); - - internal object m_syncInit = new object(); - - #region IRegionModule Members - public virtual void Initialise(Scene scene, IConfigSource config) - { - // wrap this in a try block so that defaults will work if - // the config file doesn't specify otherwise. - try - { - m_enabled = config.Configs["Chat"].GetBoolean("enabled", m_enabled); - if (!m_enabled) return; - - m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); - m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); - m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); - } - catch (Exception) - { - } - - lock (m_syncInit) - { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnChatFromWorld += OnChatFromWorld; - scene.EventManager.OnChatBroadcast += OnChatBroadcast; - } - } - - m_log.InfoFormat("[CHAT] initialized for {0} w:{1} s:{2} S:{3}", scene.RegionInfo.RegionName, - m_whisperdistance, m_saydistance, m_shoutdistance); - } - public virtual void PostInitialise() - { - } - - public virtual void Close() - { - } - - public virtual string Name - { - get { return "ChatModule"; } - } - - public virtual bool IsSharedModule - { - get { return true; } - } - - #endregion - - - public virtual void OnNewClient(IClientAPI client) - { - client.OnChatFromClient += OnChatFromClient; - } - - protected OSChatMessage FixPositionOfChatMessage(OSChatMessage c) - { - ScenePresence avatar; - Scene scene = (Scene)c.Scene; - if ((avatar = scene.GetScenePresence(c.Sender.AgentId)) != null) - c.Position = avatar.AbsolutePosition; - - return c; - } - - public virtual void OnChatFromClient(Object sender, OSChatMessage c) - { - c = FixPositionOfChatMessage(c); - - // redistribute to interested subscribers - Scene scene = (Scene)c.Scene; - scene.EventManager.TriggerOnChatFromClient(sender, c); - - // early return if not on public or debug channel - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; - - // sanity check: - if (c.Sender == null) - { - m_log.ErrorFormat("[CHAT] OnChatFromClient from {0} has empty Sender field!", sender); - return; - } - - DeliverChatToAvatars(ChatSourceType.Agent, c); - } - - public virtual void OnChatFromWorld(Object sender, OSChatMessage c) - { - // early return if not on public or debug channel - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL) return; - - DeliverChatToAvatars(ChatSourceType.Object, c); - } - - protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) - { - string fromName = c.From; - UUID fromID = UUID.Zero; - string message = c.Message; - IScene scene = c.Scene; - Vector3 fromPos = c.Position; - Vector3 regionPos = new Vector3(scene.RegionInfo.RegionLocX * Constants.RegionSize, - scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - - if (c.Channel == DEBUG_CHANNEL) c.Type = ChatTypeEnum.DebugChannel; - - switch (sourceType) - { - case ChatSourceType.Agent: - if (!(scene is Scene)) - { - m_log.WarnFormat("[CHAT]: scene {0} is not a Scene object, cannot obtain scene presence for {1}", - scene.RegionInfo.RegionName, c.Sender.AgentId); - return; - } - ScenePresence avatar = (scene as Scene).GetScenePresence(c.Sender.AgentId); - fromPos = avatar.AbsolutePosition; - fromName = avatar.Name; - fromID = c.Sender.AgentId; - - break; - - case ChatSourceType.Object: - fromID = c.SenderUUID; - - break; - } - - // TODO: iterate over message - if (message.Length >= 1000) // libomv limit - message = message.Substring(0, 1000); - - // m_log.DebugFormat("[CHAT]: DCTA: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, c.Type, sourceType); - - foreach (Scene s in m_scenes) - { - s.ForEachScenePresence(delegate(ScenePresence presence) - { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, - c.Type, message, sourceType); - }); - } - } - - - static private Vector3 CenterOfRegion = new Vector3(128, 128, 30); - public virtual void OnChatBroadcast(Object sender, OSChatMessage c) - { - // unless the chat to be broadcast is of type Region, we - // drop it if its channel is neither 0 nor DEBUG_CHANNEL - if (c.Channel != 0 && c.Channel != DEBUG_CHANNEL && c.Type != ChatTypeEnum.Region) return; - - ChatTypeEnum cType = c.Type; - if (c.Channel == DEBUG_CHANNEL) - cType = ChatTypeEnum.DebugChannel; - - if (cType == ChatTypeEnum.Region) - cType = ChatTypeEnum.Say; - - if (c.Message.Length > 1100) - c.Message = c.Message.Substring(0, 1000); - - // broadcast chat works by redistributing every incoming chat - // message to each avatar in the scene. - string fromName = c.From; - - UUID fromID = UUID.Zero; - ChatSourceType sourceType = ChatSourceType.Object; - if (null != c.Sender) - { - ScenePresence avatar = (c.Scene as Scene).GetScenePresence(c.Sender.AgentId); - fromID = c.Sender.AgentId; - fromName = avatar.Name; - sourceType = ChatSourceType.Agent; - } - - // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); - - ((Scene)c.Scene).ForEachScenePresence( - delegate(ScenePresence presence) - { - // ignore chat from child agents - if (presence.IsChildAgent) return; - - IClientAPI client = presence.ControllingClient; - - // don't forward SayOwner chat from objects to - // non-owner agents - if ((c.Type == ChatTypeEnum.Owner) && - (null != c.SenderObject) && - (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) - return; - - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, - (byte)sourceType, (byte)ChatAudibleLevel.Fully); - }); - } - - - protected virtual void TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src) - { - // don't send stuff to child agents - if (presence.IsChildAgent) return; - - Vector3 fromRegionPos = fromPos + regionPos; - Vector3 toRegionPos = presence.AbsolutePosition + - new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize, - presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0); - - int dis = Math.Abs((int) Util.GetDistanceTo(toRegionPos, fromRegionPos)); - - if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || - type == ChatTypeEnum.Say && dis > m_saydistance || - type == ChatTypeEnum.Shout && dis > m_shoutdistance) - { - return; - } - - // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, - fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs deleted file mode 100644 index ccd81c7..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCBridgeModule.cs +++ /dev/null @@ -1,219 +0,0 @@ -/* - * 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 OpenSim 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; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class IRCBridgeModule : IRegionModule - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - internal static bool configured = false; - internal static bool enabled = false; - internal static IConfig m_config = null; - - internal static List m_channels = new List(); - internal static List m_regions = new List(); - - internal static string password = String.Empty; - - internal RegionState region = null; - - #region IRegionModule Members - - public string Name - { - get { return "IRCBridgeModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - public void Initialise(Scene scene, IConfigSource config) - { - // Do a once-only scan of the configuration file to make - // sure it's basically intact. - - if (!configured) - { - configured = true; - - try - { - if ((m_config = config.Configs["IRC"]) == null) - { - m_log.InfoFormat("[IRC-Bridge] module not configured"); - return; - } - - if (!m_config.GetBoolean("enabled", false)) - { - m_log.InfoFormat("[IRC-Bridge] module disabled in configuration"); - return; - } - } - catch (Exception e) - { - m_log.ErrorFormat("[IRC-Bridge] configuration failed : {0}", e.Message); - return; - } - - enabled = true; - - if (config.Configs["RemoteAdmin"] != null) - { - password = config.Configs["RemoteAdmin"].GetString("access_password", password); - scene.CommsManager.HttpServer.AddXmlRPCHandler("irc_admin", XmlRpcAdminMethod, false); - } - } - - // 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); - region = new RegionState(scene, m_config); - lock (m_regions) m_regions.Add(region); - region.Open(); - } - catch (Exception e) - { - m_log.WarnFormat("[IRC-Bridge] Region {0} not connected to IRC : {1}", scene.RegionInfo.RegionName, e.Message); - m_log.Debug(e); - } - } - else - { - m_log.WarnFormat("[IRC-Bridge] Not enabled. Connect for region {0} ignored", scene.RegionInfo.RegionName); - } - } - - // 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() - { - } - - // Called immediately before the region module is unloaded. Cleanup - // the region. - - public void Close() - { - if (!enabled) - return; - - region.Close(); - lock (m_regions) m_regions.Remove(region); - } - - #endregion - - public static XmlRpcResponse XmlRpcAdminMethod(XmlRpcRequest request) - { - m_log.Info("[IRC-Bridge]: XML RPC Admin Entry"); - - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - - try - { - Hashtable requestData = (Hashtable)request.Params[0]; - bool found = false; - string region = String.Empty; - - if (password != String.Empty) - { - if (!requestData.ContainsKey("password")) - throw new Exception("Invalid request"); - if ((string)requestData["password"] != password) - throw new Exception("Invalid request"); - } - - if (!requestData.ContainsKey("region")) - throw new Exception("No region name specified"); - region = (string)requestData["region"]; - - foreach (RegionState rs in m_regions) - { - if (rs.Region == region) - { - responseData["server"] = rs.cs.Server; - responseData["port"] = (int)rs.cs.Port; - responseData["user"] = rs.cs.User; - responseData["channel"] = rs.cs.IrcChannel; - responseData["enabled"] = rs.cs.irc.Enabled; - responseData["connected"] = rs.cs.irc.Connected; - responseData["nickname"] = rs.cs.irc.Nick; - found = true; - break; - } - } - - if (!found) throw new Exception(String.Format("Region <{0}> not found", region)); - - responseData["success"] = true; - } - catch (Exception e) - { - m_log.InfoFormat("[IRC-Bridge] XML RPC Admin request failed : {0}", e.Message); - - responseData["success"] = "false"; - responseData["error"] = e.Message; - } - finally - { - response.Value = responseData; - } - - m_log.Debug("[IRC-Bridge]: XML RPC Admin Exit"); - - return response; - } - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs deleted file mode 100644 index c3cafb0..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/IRCConnector.cs +++ /dev/null @@ -1,887 +0,0 @@ -/* - * 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 OpenSim 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.Timers; -using System.Collections.Generic; -using System.IO; -using System.Net.Sockets; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.Environment.Modules.Avatar.Chat -{ - public class IRCConnector - { - - #region Global (static) state - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - // Local constants - - private static readonly Vector3 CenterOfRegion = new Vector3(128, 128, 20); - private static readonly char[] CS_SPACE = { ' ' }; - - 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 = 25; // Login time out interval - - private static int _idk_ = 0; // core connector identifier - private static int _pdk_ = 0; // ping interval counter - private static int _icc_ = 0; // IRC connect counter - - // List of configured connectors - - private static List m_connectors = new List(); - - // Watchdog state - - private static System.Timers.Timer m_watchdog = null; - - static IRCConnector() - { - m_log.DebugFormat("[IRC-Connector]: Static initialization started"); - m_watchdog = new System.Timers.Timer(WD_INTERVAL); - m_watchdog.Elapsed += new ElapsedEventHandler(WatchdogHandler); - m_watchdog.AutoReset = true; - m_watchdog.Start(); - m_log.DebugFormat("[IRC-Connector]: Static initialization complete"); - } - - #endregion - - #region Instance state - - // Connector identity - - internal int idn = _idk_++; - - // How many regions depend upon this connection - // This count is updated by the ChannelState object and reflects the sum - // of the region clients associated with the set of associated channel - // state instances. That's why it cannot be managed here. - - internal int depends = 0; - - // Working threads - - private Thread m_listener = null; - - private Object msyncConnect = new Object(); - - internal bool m_randomizeNick = true; // add random suffix - internal string m_baseNick = null; // base name for randomizing - internal string m_nick = null; // effective nickname - - public string Nick // Public property - { - get { return m_nick; } - set { m_nick = value; } - } - - private bool m_enabled = false; // connector enablement - public bool Enabled - { - get { return m_enabled; } - } - - 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; } - } - - private string m_ircChannel; // associated channel id - public string IrcChannel - { - get { return m_ircChannel; } - set { m_ircChannel = value; } - } - - private uint m_port = 6667; // session port - public uint Port - { - get { return m_port; } - set { m_port = value; } - } - - private string m_server = null; // IRC server name - public string Server - { - get { return m_server; } - set { m_server = value; } - } - private string m_password = null; - public string Password - { - get { return m_password; } - set { m_password = value; } - } - - private string m_user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot"; - public string User - { - get { return m_user; } - } - - // Network interface - - private TcpClient m_tcp; - private NetworkStream m_stream = null; - private StreamReader m_reader; - private StreamWriter m_writer; - - // Channel characteristic info (if available) - - internal string usermod = String.Empty; - internal string chanmod = String.Empty; - internal string version = String.Empty; - internal bool motd = false; - - #endregion - - #region connector instance management - - internal IRCConnector(ChannelState cs) - { - - // Prepare network interface - - m_tcp = null; - m_writer = null; - m_reader = null; - - // Setup IRC session parameters - - m_server = cs.Server; - m_password = cs.Password; - m_baseNick = cs.BaseNickname; - m_randomizeNick = cs.RandomizeNickname; - m_ircChannel = cs.IrcChannel; - m_port = cs.Port; - m_user = cs.User; - - if (m_watchdog == null) - { - // Non-differentiating - - ICCD_PERIOD = cs.ConnectDelay; - PING_PERIOD = cs.PingDelay; - - // Smaller values are not reasonable - - if (ICCD_PERIOD < 5) - ICCD_PERIOD = 5; - - if (PING_PERIOD < 5) - PING_PERIOD = 5; - - _icc_ = ICCD_PERIOD; // get started right away! - - } - - // The last line of defense - - if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) - throw new Exception("Invalid connector configuration"); - - // Generate an initial nickname if randomizing is enabled - - if (m_randomizeNick) - { - m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - } - - // Add the newly created connector to the known connectors list - - m_connectors.Add(this); - - m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); - - } - - ~IRCConnector() - { - m_watchdog.Stop(); - Close(); - } - - // Mark the connector as connectable. Harmless if already enabled. - - public void Open() - { - if (!m_enabled) - { - - m_connectors.Add(this); - m_enabled = true; - - if (!Connected) - { - Connect(); - } - - } - } - - // Only close the connector if the dependency count is zero. - - public void Close() - { - - m_log.InfoFormat("[IRC-Connector-{0}] Closing", idn); - - lock (msyncConnect) - { - - if ((depends == 0) && Enabled) - { - - m_enabled = false; - - if (Connected) - { - m_log.DebugFormat("[IRC-Connector-{0}] Closing interface", idn); - - // Cleanup the IRC session - - try - { - m_writer.WriteLine(String.Format("QUIT :{0} to {1} wormhole to {2} closing", - m_nick, m_ircChannel, m_server)); - m_writer.Flush(); - } - catch (Exception) {} - - - m_connected = false; - - try { m_writer.Close(); } catch (Exception) {} - try { m_reader.Close(); } catch (Exception) {} - try { m_stream.Close(); } catch (Exception) {} - try { m_tcp.Close(); } catch (Exception) {} - - } - - m_connectors.Remove(this); - - } - } - - m_log.InfoFormat("[IRC-Connector-{0}] Closed", idn); - - } - - #endregion - - #region session management - - // Connect to the IRC server. A connector should always be connected, once enabled - - public void Connect() - { - - if (!m_enabled) - return; - - // Delay until next WD cycle if this is too close to the last start attempt - - while (_icc_ < ICCD_PERIOD) - return; - - m_log.DebugFormat("[IRC-Connector-{0}]: Connection request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); - - lock (msyncConnect) - { - - _icc_ = 0; - - try - { - 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(); - m_reader = new StreamReader(m_stream); - m_writer = new StreamWriter(m_stream); - - m_log.InfoFormat("[IRC-Connector-{0}]: Connected to {1}:{2}", idn, m_server, m_port); - - m_listener = new Thread(new ThreadStart(ListenerRun)); - m_listener.Name = "IRCConnectorListenerThread"; - m_listener.IsBackground = true; - m_listener.Start(); - ThreadTracker.Add(m_listener); - - // This is the message order recommended by RFC 2812 - if (m_password != null) - m_writer.WriteLine(String.Format("PASS {0}", m_password)); - m_writer.WriteLine(String.Format("NICK {0}", m_nick)); - m_writer.Flush(); - m_writer.WriteLine(m_user); - m_writer.Flush(); - m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); - m_writer.Flush(); - - m_log.InfoFormat("[IRC-Connector-{0}]: {1} has asked to join {2}", idn, m_nick, m_ircChannel); - - } - catch (Exception e) - { - 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; - } - - } - - return; - - } - - // Reconnect is used to force a re-cycle of the IRC connection. Should generally - // be a transparent event - - public void Reconnect() - { - m_log.DebugFormat("[IRC-Connector-{0}]: Reconnect request for {1} on {2}:{3}", idn, m_nick, m_server, m_ircChannel); - - // Don't do this if a Connect is in progress... - - lock (msyncConnect) - { - - if (m_connected) - { - m_log.InfoFormat("[IRC-Connector-{0}] Resetting connector", idn); - - // Mark as disconnected. This will allow the listener thread - // to exit if still in-flight. - - - // The listener thread is not aborted - it *might* actually be - // the thread that is running the Reconnect! Instead just close - // the socket and it will disappear of its own accord, once this - // processing is completed. - - try { m_writer.Close(); } catch (Exception) {} - try { m_reader.Close(); } catch (Exception) {} - try { m_tcp.Close(); } catch (Exception) {} - - m_connected = false; - m_pending = false; - - } - - } - - Connect(); - - } - - #endregion - - #region Outbound (to-IRC) message handlers - - public void PrivMsg(string pattern, string from, string region, string msg) - { - - m_log.DebugFormat("[IRC-Connector-{0}] PrivMsg to IRC from {1}: <{2}>", idn, from, - String.Format(pattern, m_ircChannel, from, region, msg)); - - // One message to the IRC server - - try - { - m_writer.WriteLine(pattern, m_ircChannel, from, region, msg); - m_writer.Flush(); - m_log.DebugFormat("[IRC-Connector-{0}]: PrivMsg from {1} in {2}: {3}", idn, from, region, msg); - } - catch (IOException) - { - m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg I/O Error: disconnected from IRC server", idn); - Reconnect(); - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Connector-{0}]: PrivMsg exception : {1}", idn, ex.Message); - m_log.Debug(ex); - } - - } - - public void Send(string msg) - { - - m_log.DebugFormat("[IRC-Connector-{0}] Send to IRC : <{1}>", idn, msg); - - try - { - m_writer.WriteLine(msg); - m_writer.Flush(); - m_log.DebugFormat("[IRC-Connector-{0}] Sent command string: {1}", idn, msg); - } - catch (IOException) - { - m_log.ErrorFormat("[IRC-Connector-{0}] Disconnected from IRC server.(Send)", idn); - Reconnect(); - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Connector-{0}] Send exception trap: {0}", idn, ex.Message); - m_log.Debug(ex); - } - - } - - #endregion - - public void ListenerRun() - { - string inputLine; - - try - { - while (m_enabled && m_connected) - { - - if ((inputLine = m_reader.ReadLine()) == null) - throw new Exception("Listener input socket closed"); - - // m_log.Info("[IRCConnector]: " + inputLine); - - if (inputLine.Contains("PRIVMSG")) - { - - Dictionary data = ExtractMsg(inputLine); - - // Any chat ??? - if (data != null) - { - - OSChatMessage c = new OSChatMessage(); - c.Message = data["msg"]; - c.Type = ChatTypeEnum.Region; - c.Position = CenterOfRegion; - c.From = data["nick"]; - c.Sender = null; - c.SenderUUID = UUID.Zero; - - // Is message "\001ACTION foo bar\001"? - // Then change to: "/me foo bar" - - if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) - c.Message = String.Format("/me {0}", c.Message.Substring(8, c.Message.Length - 9)); - - ChannelState.OSChat(this, c, false); - - } - - } - else - { - ProcessIRCCommand(inputLine); - } - } - } - catch (Exception /*e*/) - { - // m_log.ErrorFormat("[IRC-Connector-{0}]: ListenerRun exception trap: {1}", idn, e.Message); - // 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(@":(?[\w-]*)!(?\S*) PRIVMSG (?\S+) :(?.*)", - RegexOptions.Multiline); - - private Dictionary ExtractMsg(string input) - { - //examines IRC commands and extracts any private messages - // which will then be reboadcast in the Sim - - // m_log.InfoFormat("[IRC-Connector-{0}]: ExtractMsg: {1}", idn, input); - - Dictionary result = null; - MatchCollection matches = RE.Matches(input); - - // Get some direct matches $1 $4 is a - if ((matches.Count == 0) || (matches.Count != 1) || (matches[0].Groups.Count != 5)) - { - // m_log.Info("[IRCConnector]: Number of matches: " + matches.Count); - // if (matches.Count > 0) - // { - // m_log.Info("[IRCConnector]: Number of groups: " + matches[0].Groups.Count); - // } - return null; - } - - result = new Dictionary(); - result.Add("nick", matches[0].Groups[1].Value); - result.Add("user", matches[0].Groups[2].Value); - result.Add("channel", matches[0].Groups[3].Value); - result.Add("msg", matches[0].Groups[4].Value); - - return result; - } - - public void BroadcastSim(string sender, string format, params string[] args) - { - try - { - OSChatMessage c = new OSChatMessage(); - c.From = sender; - c.Message = String.Format(format, args); - c.Type = ChatTypeEnum.Region; // ChatTypeEnum.Say; - c.Position = CenterOfRegion; - c.Sender = null; - c.SenderUUID = UUID.Zero; - - ChannelState.OSChat(this, c, true); - - } - catch (Exception ex) // IRC gate should not crash Sim - { - m_log.ErrorFormat("[IRC-Connector-{0}]: BroadcastSim Exception Trap: {1}\n{2}", idn, ex.Message, ex.StackTrace); - } - } - - #region IRC Command Handlers - - public void ProcessIRCCommand(string command) - { - - string[] commArgs; - string c_server = m_server; - - string pfx = String.Empty; - string cmd = String.Empty; - string parms = String.Empty; - - // ":" indicates that a prefix is present - // There are NEVER more than 17 real - // fields. A parameter that starts with - // ":" indicates that the remainder of the - // line is a single parameter value. - - commArgs = command.Split(CS_SPACE,2); - - if (commArgs[0].StartsWith(":")) - { - pfx = commArgs[0].Substring(1); - commArgs = commArgs[1].Split(CS_SPACE,2); - } - - cmd = commArgs[0]; - parms = commArgs[1]; - - // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}>", idn, pfx, cmd); - - switch (cmd) - { - - // Messages 001-004 are always sent - // following signon. - - case "001" : // Welcome ... - case "002" : // Server information - case "003" : // Welcome ... - break; - case "004" : // Server information - 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; - version = commArgs[2]; - usermod = commArgs[3]; - chanmod = commArgs[4]; - break; - case "005" : // Server information - break; - case "042" : - case "250" : - case "251" : - case "252" : - case "254" : - case "255" : - case "265" : - case "266" : - case "332" : // Subject - case "333" : // Subject owner (?) - case "353" : // Name list - case "366" : // End-of-Name list marker - case "372" : // MOTD body - case "375" : // MOTD start - 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}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - motd = true; - break; - case "451" : // Not registered - break; - case "433" : // Nickname in use - // Gen a new name - m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - 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(); - m_writer.WriteLine(m_user); - m_writer.Flush(); - 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}] {2}", idn, cmd, parms.Split(CS_SPACE,2)[1]); - break; - case "ERROR" : - 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}] [{1}] parms = <{2}>", idn, cmd, parms); - m_writer.WriteLine(String.Format("PONG {0}", parms)); - m_writer.Flush(); - break; - case "PONG" : - break; - case "JOIN": - 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}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcPart(pfx, cmd, parms); - break; - case "MODE": - 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}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcNickChange(pfx, cmd, parms); - break; - case "KICK": - 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}] [{1}] parms = <{2}>", idn, cmd, parms); - eventIrcQuit(pfx, cmd, parms); - break; - default : - m_log.DebugFormat("[IRC-Connector-{0}] Command '{1}' ignored, parms = {2}", idn, cmd, parms); - break; - } - - // m_log.DebugFormat("[IRC-Connector-{0}] prefix = <{1}> cmd = <{2}> complete", idn, pfx, cmd); - - } - - public void eventIrcJoin(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string IrcUser = prefix.Split('!')[0]; - string IrcChannel = args[0]; - - if (IrcChannel.StartsWith(":")) - IrcChannel = IrcChannel.Substring(1); - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); - } - - public void eventIrcPart(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string IrcUser = prefix.Split('!')[0]; - string IrcChannel = args[0]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCPart {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me parts {0}", IrcChannel); - } - - public void eventIrcMode(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string UserMode = args[1]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCMode {1}:{2}", idn, m_server, m_ircChannel); - if (UserMode.Substring(0, 1) == ":") - { - UserMode = UserMode.Remove(0, 1); - } - } - - public void eventIrcNickChange(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,2); - string UserOldNick = prefix.Split('!')[0]; - string UserNewNick = args[0].Remove(0, 1); - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCNickChange {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(UserOldNick, "/me is now known as {0}", UserNewNick); - } - - public void eventIrcKick(string prefix, string command, string parms) - { - string[] args = parms.Split(CS_SPACE,3); - string UserKicker = prefix.Split('!')[0]; - string IrcChannel = args[0]; - string UserKicked = args[1]; - string KickMessage = args[2]; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCKick {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(UserKicker, "/me kicks kicks {0} off {1} saying \"{2}\"", UserKicked, IrcChannel, KickMessage); - - if (UserKicked == m_nick) - { - BroadcastSim(m_nick, "Hey, that was me!!!"); - } - - } - - public void eventIrcQuit(string prefix, string command, string parms) - { - string IrcUser = prefix.Split('!')[0]; - string QuitMessage = parms; - - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCQuit {1}:{2}", idn, m_server, m_ircChannel); - BroadcastSim(IrcUser, "/me quits saying \"{0}\"", QuitMessage); - } - - #endregion - - #region Connector Watch Dog - - // A single watch dog monitors extant connectors and makes sure that they - // are re-connected as necessary. If a connector IS connected, then it is - // pinged, but only if a PING period has elapsed. - - protected static void WatchdogHandler(Object source, ElapsedEventArgs args) - { - - // m_log.InfoFormat("[IRC-Watchdog] Status scan"); - - _pdk_ = (_pdk_+1)%PING_PERIOD; // cycle the ping trigger - _icc_++; // increment the inter-consecutive-connect-delay counter - - foreach (IRCConnector connector in m_connectors) - { - if (connector.Enabled) - { - if (!connector.Connected) - { - try - { - // m_log.DebugFormat("[IRC-Watchdog] Connecting {1}:{2}", connector.idn, connector.m_server, connector.m_ircChannel); - connector.Connect(); - } - catch (Exception e) - { - m_log.ErrorFormat("[IRC-Watchdog] Exception on connector {0}: {1} ", connector.idn, e.Message); - } - } - 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 - { - connector.m_writer.WriteLine(String.Format("PING :{0}", connector.m_server)); - connector.m_writer.Flush(); - } - catch (Exception /*e*/) - { - // m_log.ErrorFormat("[IRC-PingRun] Exception on connector {0}: {1} ", connector.idn, e.Message); - // m_log.Debug(e); - connector.Reconnect(); - } - } - - } - } - } - - // m_log.InfoFormat("[IRC-Watchdog] Status scan completed"); - - } - - #endregion - - } -} diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs deleted file mode 100644 index 78f4265..0000000 --- a/OpenSim/Region/Environment/Modules/Avatar/Chat/RegionState.cs +++ /dev/null @@ -1,424 +0,0 @@ -/* - * 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 OpenSim 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.Environment.Modules.Avatar.Chat -{ - // An instance of this class exists for every active region - - internal class RegionState - { - - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly OpenMetaverse.Vector3 CenterOfRegion = new OpenMetaverse.Vector3(128, 128, 20); - private const int DEBUG_CHANNEL = 2147483647; - - private static int _idk_ = 0; - - // Runtime variables; these values are assigned when the - // IrcState is created and remain constant thereafter. - - internal string Region = String.Empty; - internal string Host = String.Empty; - internal string LocX = String.Empty; - internal string LocY = String.Empty; - internal string MA1 = String.Empty; - internal string MA2 = String.Empty; - internal string IDK = String.Empty; - - // System values - used only be the IRC classes themselves - - internal ChannelState cs = null; // associated IRC configuration - internal Scene scene = null; // associated scene - internal IConfig config = null; // configuration file reference - internal bool enabled = true; - - // This list is used to keep track of who is here, and by - // implication, who is not. - - internal List clients = new List(); - - // Setup runtime variable values - - public RegionState(Scene p_scene, IConfig p_config) - { - - scene = p_scene; - config = p_config; - - Region = scene.RegionInfo.RegionName; - Host = scene.RegionInfo.ExternalHostName; - LocX = Convert.ToString(scene.RegionInfo.RegionLocX); - LocY = Convert.ToString(scene.RegionInfo.RegionLocY); - MA1 = scene.RegionInfo.MasterAvatarFirstName; - MA2 = scene.RegionInfo.MasterAvatarLastName; - IDK = Convert.ToString(_idk_++); - - // OpenChannel conditionally establishes a connection to the - // IRC server. The request will either succeed, or it will - // throw an exception. - - ChannelState.OpenChannel(this, config); - - // Connect channel to world events - - scene.EventManager.OnChatFromWorld += OnSimChat; - scene.EventManager.OnChatFromClient += OnSimChat; - scene.EventManager.OnMakeRootAgent += OnMakeRootAgent; - scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; - - m_log.InfoFormat("[IRC-Region {0}] Initialization complete", Region); - - } - - // Auto cleanup when abandoned - - ~RegionState() - { - if (cs != null) - cs.RemoveRegion(this); - } - - // Called by PostInitialize after all regions have been created - - public void Open() - { - cs.Open(this); - enabled = true; - } - - // 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() - { - enabled = false; - cs.Close(this); - } - - // The agent has disconnected, cleanup associated resources - - private void OnClientLoggedOut(IClientAPI client) - { - try - { - if (clients.Contains(client)) - { - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - m_log.InfoFormat("[IRC-Region {0}]: {1} has left", Region, client.Name); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", client.Name)); - } - client.OnLogout -= OnClientLoggedOut; - client.OnConnectionClosed -= OnClientLoggedOut; - clients.Remove(client); - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: ClientLoggedOut exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - } - - // This event indicates that the agent has left the building. We should treat that the same - // as if the agent has logged out (we don't want cross-region noise - or do we?) - - private void OnMakeChildAgent(ScenePresence presence) - { - - IClientAPI client = presence.ControllingClient; - - try - { - if (clients.Contains(client)) - { - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); - m_log.DebugFormat("[IRC-Region {0}] {1} has left", Region, clientName); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has left", clientName)); - } - client.OnLogout -= OnClientLoggedOut; - client.OnConnectionClosed -= OnClientLoggedOut; - clients.Remove(client); - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: MakeChildAgent exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - - } - - // An agent has entered the region (from another region). Add the client to the locally - // known clients list - - private void OnMakeRootAgent(ScenePresence presence) - { - - IClientAPI client = presence.ControllingClient; - - try - { - if (!clients.Contains(client)) - { - client.OnLogout += OnClientLoggedOut; - client.OnConnectionClosed += OnClientLoggedOut; - clients.Add(client); - if (enabled && (cs.irc.Enabled) && (cs.irc.Connected) && (cs.ClientReporting)) - { - string clientName = String.Format("{0} {1}", presence.Firstname, presence.Lastname); - m_log.DebugFormat("[IRC-Region {0}] {1} has arrived", Region, clientName); - cs.irc.PrivMsg(cs.NoticeMessageFormat, cs.irc.Nick, Region, String.Format("{0} has arrived", clientName)); - } - } - } - catch (Exception ex) - { - m_log.ErrorFormat("[IRC-Region {0}]: MakeRootAgent exception: {1}", Region, ex.Message); - m_log.Debug(ex); - } - - } - - // This handler detects chat events int he virtual world. - - public void OnSimChat(Object sender, OSChatMessage msg) - { - - // early return if this comes from the IRC forwarder - - if (cs.irc.Equals(sender)) return; - - // early return if nothing to forward - - if (msg.Message.Length == 0) return; - - // check for commands coming from avatars or in-world - // object (if commands are enabled) - - if (cs.CommandsEnabled && msg.Channel == cs.CommandChannel) - { - - m_log.DebugFormat("[IRC-Region {0}] command on channel {1}: {2}", Region, msg.Channel, msg.Message); - - string[] messages = msg.Message.Split(' '); - string command = messages[0].ToLower(); - - try - { - switch (command) - { - - // These commands potentially require a change in the - // underlying ChannelState. - - case "server": - cs.Close(this); - cs = cs.UpdateServer(this, messages[1]); - cs.Open(this); - break; - case "port": - cs.Close(this); - cs = cs.UpdatePort(this, messages[1]); - cs.Open(this); - break; - case "channel": - cs.Close(this); - cs = cs.UpdateChannel(this, messages[1]); - cs.Open(this); - break; - case "nick": - cs.Close(this); - cs = cs.UpdateNickname(this, messages[1]); - cs.Open(this); - break; - - // These may also (but are less likely) to require a - // change in ChannelState. - - case "client-reporting": - cs = cs.UpdateClientReporting(this, messages[1]); - break; - case "in-channel": - cs = cs.UpdateRelayIn(this, messages[1]); - break; - case "out-channel": - cs = cs.UpdateRelayOut(this, messages[1]); - break; - - // These are all taken to be temporary changes in state - // so the underlying connector remains intact. But note - // that with regions sharing a connector, there could - // be interference. - - case "close": - enabled = false; - cs.Close(this); - break; - - case "connect": - enabled = true; - cs.Open(this); - break; - - case "reconnect": - enabled = true; - cs.Close(this); - cs.Open(this); - break; - - // This one is harmless as far as we can judge from here. - // If it is not, then the complaints will eventually make - // that evident. - - default: - m_log.DebugFormat("[IRC-Region {0}] Forwarding unrecognized command to IRC : {1}", - Region, msg.Message); - cs.irc.Send(msg.Message); - break; - } - } - catch (Exception ex) - { - m_log.WarnFormat("[IRC-Region {0}] error processing in-world command channel input: {1}", - Region, ex.Message); - m_log.Debug(ex); - } - - return; - - } - - // The command channel remains enabled, even if we have otherwise disabled the IRC - // interface. - - if (!enabled) - return; - - // drop messages unless they are on a valid in-world - // channel as configured in the ChannelState - - if (!cs.ValidInWorldChannels.Contains(msg.Channel)) - { - m_log.DebugFormat("[IRC-Region {0}] dropping message {1} on channel {2}", Region, msg, msg.Channel); - return; - } - - ScenePresence avatar = null; - string fromName = msg.From; - - if (msg.Sender != null) - { - avatar = scene.GetScenePresence(msg.Sender.AgentId); - if (avatar != null) fromName = avatar.Name; - } - - if (!cs.irc.Connected) - { - m_log.WarnFormat("[IRC-Region {0}] IRCConnector not connected: dropping message from {1}", Region, fromName); - return; - } - - m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); - - if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) - { - string txt = msg.Message; - if (txt.StartsWith("/me ")) - txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4)); - - cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt); - return; - } - - if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && - msg.Channel == cs.RelayChannelOut) - { - Match m = cs.AccessPasswordRegex.Match(msg.Message); - if (null != m) - { - m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), - m.Groups["message"].ToString()); - cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), - scene.RegionInfo.RegionName, m.Groups["message"].ToString()); - } - } - } - - // This method gives the region an opportunity to interfere with - // message delivery. For now we just enforce the enable/disable - // flag. - - internal void OSChat(Object irc, OSChatMessage msg) - { - if (enabled) - { - // m_log.DebugFormat("[IRC-OSCHAT] Region {0} being sent message", region.Region); - msg.Scene = scene; - scene.EventManager.TriggerOnChatBroadcast(irc, msg); - } - } - - // This supports any local message traffic that might be needed in - // support of command processing. At present there is none. - - internal void LocalChat(string msg) - { - if (enabled) - { - OSChatMessage osm = new OSChatMessage(); - osm.From = "IRC Agent"; - osm.Message = msg; - osm.Type = ChatTypeEnum.Region; - osm.Position = CenterOfRegion; - osm.Sender = null; - osm.SenderUUID = OpenMetaverse.UUID.Zero; // Hmph! Still? - osm.Channel = 0; - OSChat(this, osm); - } - } - - } - -} -- cgit v1.1