29 using System.Collections.Generic;
30 using System.Reflection;
31 using System.Text.RegularExpressions;
34 using OpenSim.Framework;
35 using OpenSim.Region.Framework.Interfaces;
36 using OpenSim.Region.Framework.Scenes;
45 internal class ChannelState
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private static Regex arg =
new Regex(
@"(?<!\\)\[[^\[\]]*(?<!\\)\]");
52 private static int _idk_ = 0;
53 private static int DEBUG_CHANNEL = 2147483647;
58 internal string Server = null;
59 internal string Password = null;
60 internal string IrcChannel = null;
61 internal string BaseNickname =
"OSimBot";
62 internal uint Port = 6667;
63 internal string User = null;
65 internal bool ClientReporting =
true;
66 internal bool RelayChat =
true;
67 internal bool RelayPrivateChannels =
false;
68 internal int RelayChannel = 1;
69 internal List<int> ValidInWorldChannels =
new List<int>();
74 internal string PrivateMessageFormat =
"PRIVMSG {0} :<{2}> {1} {3}";
75 internal string NoticeMessageFormat =
"PRIVMSG {0} :<{2}> {3}";
76 internal int RelayChannelOut = -1;
77 internal bool RandomizeNickname =
true;
78 internal bool CommandsEnabled =
false;
79 internal int CommandChannel = -1;
80 internal int ConnectDelay = 10;
81 internal int PingDelay = 15;
82 internal string DefaultZone =
"Sim";
84 internal string _accessPassword = String.Empty;
85 internal Regex AccessPasswordRegex = null;
86 internal List<string> ExcludeList =
new List<string>();
87 internal string AccessPassword
89 get {
return _accessPassword; }
92 _accessPassword = value;
93 AccessPasswordRegex =
new Regex(
String.Format(
@"^{0},\s*(?<avatar>[^,]+),\s*(?<message>.+)$", _accessPassword),
94 RegexOptions.Compiled);
104 internal int idn = _idk_++;
108 internal List<RegionState> clientregions =
new List<RegionState>();
112 internal ChannelState()
120 internal ChannelState(ChannelState model)
122 Server = model.Server;
123 Password = model.Password;
124 IrcChannel = model.IrcChannel;
126 BaseNickname = model.BaseNickname;
127 RandomizeNickname = model.RandomizeNickname;
129 CommandsEnabled = model.CommandsEnabled;
130 CommandChannel = model.CommandChannel;
131 RelayChat = model.RelayChat;
132 RelayPrivateChannels = model.RelayPrivateChannels;
133 RelayChannelOut = model.RelayChannelOut;
134 RelayChannel = model.RelayChannel;
135 ValidInWorldChannels = model.ValidInWorldChannels;
136 PrivateMessageFormat = model.PrivateMessageFormat;
137 NoticeMessageFormat = model.NoticeMessageFormat;
138 ClientReporting = model.ClientReporting;
139 AccessPassword = model.AccessPassword;
140 DefaultZone = model.DefaultZone;
141 ConnectDelay = model.ConnectDelay;
142 PingDelay = model.PingDelay;
150 internal static void OpenChannel(RegionState rs, IConfig config)
156 ChannelState cs =
new ChannelState();
161 m_log.DebugFormat(
"[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
163 cs.Server = Substitute(rs, config.GetString(
"server", null));
164 m_log.DebugFormat(
"[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
165 cs.Password = Substitute(rs, config.GetString(
"password", null));
167 cs.User = Substitute(rs, config.GetString(
"user", null));
168 cs.IrcChannel = Substitute(rs, config.GetString(
"channel", null));
169 m_log.DebugFormat(
"[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
170 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString(
"port", Convert.ToString(cs.Port))));
171 m_log.DebugFormat(
"[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
172 cs.BaseNickname = Substitute(rs, config.GetString(
"nick", cs.BaseNickname));
173 m_log.DebugFormat(
"[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
174 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString(
"randomize_nick", Convert.ToString(cs.RandomizeNickname))));
175 m_log.DebugFormat(
"[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
176 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString(
"nicknum", Convert.ToString(cs.RandomizeNickname))));
177 m_log.DebugFormat(
"[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
178 cs.User = Substitute(rs, config.GetString(
"username", cs.User));
179 m_log.DebugFormat(
"[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
180 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString(
"commands_enabled", Convert.ToString(cs.CommandsEnabled))));
181 m_log.DebugFormat(
"[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
182 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString(
"commandchannel", Convert.ToString(cs.CommandChannel))));
183 m_log.DebugFormat(
"[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
184 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString(
"command_channel", Convert.ToString(cs.CommandChannel))));
185 m_log.DebugFormat(
"[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
186 cs.RelayChat = Convert.ToBoolean(Substitute(rs, config.GetString(
"relay_chat", Convert.ToString(cs.RelayChat))));
187 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayChat : <{1}>", cs.idn, cs.RelayChat);
188 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString(
"relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
189 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
190 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString(
"useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
191 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
192 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString(
"relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
193 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
194 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString(
"relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
195 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
196 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString(
"inchannel", Convert.ToString(cs.RelayChannel))));
197 m_log.DebugFormat(
"[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
198 cs.PrivateMessageFormat = Substitute(rs, config.GetString(
"msgformat", cs.PrivateMessageFormat));
199 m_log.DebugFormat(
"[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
200 cs.NoticeMessageFormat = Substitute(rs, config.GetString(
"noticeformat", cs.NoticeMessageFormat));
201 m_log.DebugFormat(
"[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
202 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString(
"verbosity", cs.ClientReporting ?
"1" :
"0"))) > 0;
203 m_log.DebugFormat(
"[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
204 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString(
"report_clients", Convert.ToString(cs.ClientReporting))));
205 m_log.DebugFormat(
"[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
206 cs.DefaultZone = Substitute(rs, config.GetString(
"fallback_region", cs.DefaultZone));
207 m_log.DebugFormat(
"[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
208 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString(
"connect_delay", Convert.ToString(cs.ConnectDelay))));
209 m_log.DebugFormat(
"[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
210 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString(
"ping_delay", Convert.ToString(cs.PingDelay))));
211 m_log.DebugFormat(
"[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
212 cs.AccessPassword = Substitute(rs, config.GetString(
"access_password", cs.AccessPassword));
213 m_log.DebugFormat(
"[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
214 string[] excludes = config.GetString(
"exclude_list",
"").Trim().Split(
new Char[] {
',' });
215 cs.ExcludeList =
new List<string>(excludes.Length);
216 foreach (
string name
in excludes)
218 cs.ExcludeList.Add(name.Trim().ToLower());
223 if (cs.Server == null)
224 throw new Exception(
String.Format(
"[IRC-Channel-{0}] Invalid configuration for region {1}: server missing", cs.idn, rs.Region));
225 else if (cs.IrcChannel == null)
226 throw new Exception(
String.Format(
"[IRC-Channel-{0}] Invalid configuration for region {1}: channel missing", cs.idn, rs.Region));
227 else if (cs.BaseNickname == null)
228 throw new Exception(
String.Format(
"[IRC-Channel-{0}] Invalid configuration for region {1}: nick missing", cs.idn, rs.Region));
229 else if (cs.User == null)
230 throw new Exception(
String.Format(
"[IRC-Channel-{0}] Invalid configuration for region {1}: user missing", cs.idn, rs.Region));
232 m_log.InfoFormat(
"[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region);
233 m_log.InfoFormat(
"[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server);
234 m_log.InfoFormat(
"[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel);
235 m_log.InfoFormat(
"[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port);
236 m_log.InfoFormat(
"[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname);
237 m_log.InfoFormat(
"[IRC-Channel-{0}] User = {1}", cs.idn, cs.User);
243 cs.ValidInWorldChannels.Add(0);
244 cs.ValidInWorldChannels.Add(DEBUG_CHANNEL);
247 if (cs.RelayPrivateChannels)
248 cs.ValidInWorldChannels.Add(cs.RelayChannelOut);
250 rs.cs = Integrate(rs, cs);
263 private static ChannelState Integrate(RegionState rs, ChannelState p_cs)
266 ChannelState cs = p_cs;
281 if (cs.IsAPerfectMatchFor(xcs))
283 m_log.DebugFormat(
"[IRC-Channel-{0}] Channel state matched", cs.idn);
287 if (cs.IsAConnectionMatchFor(xcs))
289 m_log.DebugFormat(
"[IRC-Channel-{0}] Channel matched", cs.idn);
302 m_log.DebugFormat(
"[IRC-Channel-{0}] New channel required", cs.idn);
307 IRCBridgeModule.m_channels.Add(cs);
309 m_log.InfoFormat(
"[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
310 cs.idn, rs.Region, cs.DefaultZone,
311 cs.CommandsEnabled ?
"enabled" :
"not enabled",
312 cs.RelayPrivateChannels ?
"relayed" :
"not relayed");
316 string txt = String.Format(
"[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}",
317 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
319 throw new Exception(txt);
324 m_log.InfoFormat(
"[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}",
325 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
328 m_log.InfoFormat(
"[IRC-Channel-{0}] Region {1} associated with channel {2} on server {3}:{4}",
329 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
342 internal ChannelState UpdateServer(RegionState rs,
string server)
345 ChannelState cs =
new ChannelState(
this);
347 cs = Integrate(rs, cs);
352 internal ChannelState UpdatePort(RegionState rs,
string port)
355 ChannelState cs =
new ChannelState(
this);
356 cs.Port = Convert.ToUInt32(port);
357 cs = Integrate(rs, cs);
362 internal ChannelState UpdateChannel(RegionState rs,
string channel)
365 ChannelState cs =
new ChannelState(
this);
366 cs.IrcChannel = channel;
367 cs = Integrate(rs, cs);
372 internal ChannelState UpdateNickname(RegionState rs,
string nickname)
375 ChannelState cs =
new ChannelState(
this);
376 cs.BaseNickname = nickname;
377 cs = Integrate(rs, cs);
382 internal ChannelState UpdateClientReporting(RegionState rs,
string cr)
385 ChannelState cs =
new ChannelState(
this);
386 cs.ClientReporting = Convert.ToBoolean(cr);
387 cs = Integrate(rs, cs);
392 internal ChannelState UpdateRelayIn(RegionState rs,
string channel)
395 ChannelState cs =
new ChannelState(
this);
396 cs.RelayChannel = Convert.ToInt32(channel);
397 cs = Integrate(rs, cs);
402 internal ChannelState UpdateRelayOut(RegionState rs,
string channel)
405 ChannelState cs =
new ChannelState(
this);
406 cs.RelayChannelOut = Convert.ToInt32(channel);
407 cs = Integrate(rs, cs);
417 private bool IsAConnectionMatchFor(ChannelState cs)
420 Server == cs.Server &&
421 IrcChannel == cs.IrcChannel &&
423 BaseNickname == cs.BaseNickname &&
432 private bool IsAPerfectMatchFor(ChannelState cs)
434 return (IsAConnectionMatchFor(cs) &&
435 RelayChannelOut == cs.RelayChannelOut &&
436 PrivateMessageFormat == cs.PrivateMessageFormat &&
437 NoticeMessageFormat == cs.NoticeMessageFormat &&
438 RandomizeNickname == cs.RandomizeNickname &&
439 AccessPassword == cs.AccessPassword &&
440 CommandsEnabled == cs.CommandsEnabled &&
441 CommandChannel == cs.CommandChannel &&
442 DefaultZone == cs.DefaultZone &&
443 RelayPrivateChannels == cs.RelayPrivateChannels &&
444 RelayChannel == cs.RelayChannel &&
445 RelayChat == cs.RelayChat &&
446 ClientReporting == cs.ClientReporting
459 private static string Substitute(RegionState rs,
string instr)
462 string result = instr;
464 if (
string.IsNullOrEmpty(result))
472 while (arg.IsMatch(result))
475 string vvar = arg.Match(result).ToString();
476 string var = vvar.Substring(1, vvar.Length - 2).Trim();
478 switch (var.ToLower())
481 result = result.Replace(vvar, rs.Region);
484 result = result.Replace(vvar, rs.Host);
487 result = result.Replace(vvar, rs.LocX);
490 result = result.Replace(vvar, rs.LocY);
493 result = result.Replace(vvar, rs.IDK);
496 result = result.Replace(vvar, rs.config.GetString(var, var));
503 result = result.Replace(
@"\[",
"[").Replace(
@"\]",
"]");
512 m_log.InfoFormat(
"[IRC-Channel-{0}] Closing channel <{1}> to server <{2}:{3}>",
513 idn, IrcChannel, Server, Port);
514 m_log.InfoFormat(
"[IRC-Channel-{0}] There are {1} active clients",
515 idn, clientregions.Count);
521 m_log.InfoFormat(
"[IRC-Channel-{0}] Opening channel <{1}> to server <{2}:{3}>",
522 idn, IrcChannel, Server, Port);
532 public void Open(RegionState rs)
541 public void Close(RegionState rs)
546 if (clientregions.Count == 0)
549 IRCBridgeModule.m_channels.Remove(
this);
550 m_log.InfoFormat(
"[IRC-Channel-{0}] Region {1} is last user of channel <{2}> to server <{3}:{4}>",
551 idn, rs.Region, IrcChannel, Server, Port);
552 m_log.InfoFormat(
"[IRC-Channel-{0}] Removed", idn);
559 public void AddRegion(RegionState rs)
561 m_log.InfoFormat(
"[IRC-Channel-{0}] Adding region {1} to channel <{2}> to server <{3}:{4}>",
562 idn, rs.Region, IrcChannel, Server, Port);
563 if (!clientregions.Contains(rs))
565 clientregions.Add(rs);
566 lock (irc) irc.depends++;
574 public void RemoveRegion(RegionState rs)
577 m_log.InfoFormat(
"[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>",
578 idn, rs.Region, IrcChannel, Server, Port);
580 if (clientregions.Contains(rs))
582 clientregions.Remove(rs);
583 lock (irc) irc.depends--;
615 if (cmsg && !cs.ClientReporting)
620 c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0);
622 foreach (RegionState region
in cs.clientregions)
624 region.OSChat(cs.irc, c);
633 m_log.ErrorFormat(
"[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message);
Interactive OpenSim region server