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); } m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); }
// 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 ); }
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); }
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 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 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 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); }
// 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); }
// 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); IDK = Convert.ToString(_idk_++); showAlert = config.GetBoolean("alert_show", false); string alertServerInfo = String.Empty; if (showAlert) { bool showAlertServerInfo = config.GetBoolean("alert_show_serverinfo", true); if (showAlertServerInfo) { alertServerInfo = String.Format("\nServer: {0}\nPort: {1}\nChannel: {2}\n\n", config.GetString("server", ""), config.GetString("port", ""), config.GetString("channel", "")); } string alertPreMessage = config.GetString("alert_msg_pre", "This region is linked to Irc."); string alertPostMessage = config.GetString("alert_msg_post", "Everything you say in public chat can be listened."); alertMessage = String.Format("{0}\n{1}{2}", alertPreMessage, alertServerInfo, alertPostMessage); dialogModule = scene.RequestModuleInterface <IDialogModule>(); } // 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); }
// 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 ); }
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); } }
// 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; }
// 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 ); }
// 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 ); }
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; }
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 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 UpdateChannel(RegionState rs, string channel) { RemoveRegion(rs); ChannelState cs = new ChannelState(this); cs.IrcChannel = channel; cs = Integrate(rs, cs); cs.AddRegion(rs); return 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; }
// 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; }
// 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); }
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 (m_randomizeNick) m_nick = m_baseNick + Util.RandomClass.Next(1, 99); else m_nick = m_baseNick; m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); }
// 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)); cs.fromwhere = Substitute(rs, config.GetString("fromwhere", 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) { throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}: server missing", cs.idn, rs.Region)); } else if (cs.IrcChannel == null) { throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}: channel missing", cs.idn, rs.Region)); } else if (cs.BaseNickname == null) { throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}: nick missing", cs.idn, rs.Region)); } else if (cs.User == null) { throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}: user missing", 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); }
// 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()); } } }
public void ListenerRun() { string inputLine; int resetk = m_resetk; 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 <string, string> 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 && (m_resetk == resetk)) { Reconnect(); } }
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; }
// 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()); } } }