aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
diff options
context:
space:
mode:
authorDr Scofield2008-10-30 15:31:44 +0000
committerDr Scofield2008-10-30 15:31:44 +0000
commitb222d11b124fb89965837592c4f4df27e8785165 (patch)
tree5ccbc95353b4b06d4e24c8cc2a8959c5b6052cb4 /OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
parentFrom: Alan Webb (alan_webb@us.ibm.com) (diff)
downloadopensim-SC_OLD-b222d11b124fb89965837592c4f4df27e8785165.zip
opensim-SC_OLD-b222d11b124fb89965837592c4f4df27e8785165.tar.gz
opensim-SC_OLD-b222d11b124fb89965837592c4f4df27e8785165.tar.bz2
opensim-SC_OLD-b222d11b124fb89965837592c4f4df27e8785165.tar.xz
From: Alan Webb (alan_webb@us.ibm.com)
XIRCBrigeModule is transient, will merge it with IRCBridgeModule: extends/refactors IRCBridgeModule to support channel-per-region (if desired).
Diffstat (limited to 'OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs570
1 files changed, 570 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
new file mode 100644
index 0000000..7a3eadf
--- /dev/null
+++ b/OpenSim/Region/Environment/Modules/Avatar/Chat/ChannelState.cs
@@ -0,0 +1,570 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text.RegularExpressions;
32using log4net;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Region.Environment.Interfaces;
36using OpenSim.Region.Environment.Scenes;
37
38namespace OpenSim.Region.Environment.Modules.Avatar.Chat
39{
40
41 // An instance of this class exists for each unique combination of
42 // IRC chat interface characteristics, as determined by the supplied
43 // configuration file.
44
45 internal class ChannelState
46 {
47
48 private static readonly ILog m_log =
49 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private static Regex arg = new Regex(@"\[[^\[\]]*\]");
52 private static int _idk_ = 0;
53
54 // These are the IRC Connector configurable parameters with hard-wired
55 // default values (retained for compatability).
56
57 internal string Server = null;
58 internal string IrcChannel = null;
59 internal string BaseNickname = "OSimBot";
60 internal uint Port = 6667;
61 internal string User = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot";
62
63 internal bool ClientReporting = true;
64 internal bool RelayPrivateChannels = false;
65 internal int RelayChannel = 1;
66
67 // Connector agnostic parameters. These values are NOT shared with the
68 // connector and do not differentiate at an IRC level
69
70 internal string PrivateMessageFormat = "PRIVMSG {0} :<{2}> {1} {3}";
71 internal string NoticeMessageFormat = "PRIVMSG {0} :<{2}> {3}";
72 internal int RelayChannelOut = -1;
73 internal bool RandomizeNickname = true;
74 internal string AccessPassword = "badkitty";
75 internal bool CommandsEnabled = false;
76 internal int CommandChannel = -1;
77 internal int ConnectDelay = 10;
78 internal int PingDelay = 15;
79 internal string DefaultZone = "Sim";
80
81 // IRC connector reference
82
83 internal XIRCConnector irc = null;
84
85 internal int idn = _idk_++;
86
87 // List of regions dependent upon this connection
88
89 internal List<RegionState> clientregions = new List<RegionState>();
90
91 // Needed by OpenChannel
92
93 internal ChannelState()
94 {
95 }
96
97 // This constructor is used by the Update* methods. A copy of the
98 // existing channel state is created, and distinguishing characteristics
99 // are copied across.
100
101 internal ChannelState(ChannelState model)
102 {
103 Server = model.Server;
104 IrcChannel = model.IrcChannel;
105 Port = model.Port;
106 BaseNickname = model.BaseNickname;
107 RandomizeNickname = model.RandomizeNickname;
108 User = model.User;
109 CommandsEnabled = model.CommandsEnabled;
110 CommandChannel = model.CommandChannel;
111 RelayPrivateChannels = model.RelayPrivateChannels;
112 RelayChannelOut = model.RelayChannelOut;
113 RelayChannel = model.RelayChannel;
114 PrivateMessageFormat = model.PrivateMessageFormat;
115 NoticeMessageFormat = model.NoticeMessageFormat;
116 ClientReporting = model.ClientReporting;
117 AccessPassword = model.AccessPassword;
118 DefaultZone = model.DefaultZone;
119 ConnectDelay = model.ConnectDelay;
120 PingDelay = model.PingDelay;
121 }
122
123 // Read the configuration file, performing variable substitution and any
124 // necessary aliasing. See accompanying documentation for how this works.
125 // If you don't need variables, then this works exactly as before.
126 // If either channel or server are not specified, the request fails.
127
128 internal static void OpenChannel(RegionState rs, IConfig config)
129 {
130
131 // Create a new instance of a channel. This may not actually
132 // get used if an equivalent channel already exists.
133
134 ChannelState cs = new ChannelState();
135
136 // Read in the configuration file and filter everything for variable
137 // subsititution.
138
139 m_log.DebugFormat("[IRC-Channel-{0}] Initial request by Region {1} to connect to IRC", cs.idn, rs.Region);
140
141 cs.Server = Substitute(rs, config.GetString("server", null));
142 m_log.DebugFormat("[IRC-Channel-{0}] Server : <{1}>", cs.idn, cs.Server);
143 cs.IrcChannel = Substitute(rs, config.GetString("channel", null));
144 m_log.DebugFormat("[IRC-Channel-{0}] IrcChannel : <{1}>", cs.idn, cs.IrcChannel);
145 cs.Port = Convert.ToUInt32(Substitute(rs, config.GetString("port", Convert.ToString(cs.Port))));
146 m_log.DebugFormat("[IRC-Channel-{0}] Port : <{1}>", cs.idn, cs.Port);
147 cs.BaseNickname = Substitute(rs, config.GetString("nick", cs.BaseNickname));
148 m_log.DebugFormat("[IRC-Channel-{0}] BaseNickname : <{1}>", cs.idn, cs.BaseNickname);
149 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("randomize_nick", Convert.ToString(cs.RandomizeNickname))));
150 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
151 cs.RandomizeNickname = Convert.ToBoolean(Substitute(rs, config.GetString("nicknum", Convert.ToString(cs.RandomizeNickname))));
152 m_log.DebugFormat("[IRC-Channel-{0}] RandomizeNickname : <{1}>", cs.idn, cs.RandomizeNickname);
153 cs.User = Substitute(rs, config.GetString("username", cs.User));
154 m_log.DebugFormat("[IRC-Channel-{0}] User : <{1}>", cs.idn, cs.User);
155 cs.CommandsEnabled = Convert.ToBoolean(Substitute(rs, config.GetString("commands_enabled", Convert.ToString(cs.CommandsEnabled))));
156 m_log.DebugFormat("[IRC-Channel-{0}] CommandsEnabled : <{1}>", cs.idn, cs.CommandsEnabled);
157 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("commandchannel", Convert.ToString(cs.CommandChannel))));
158 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
159 cs.CommandChannel = Convert.ToInt32(Substitute(rs, config.GetString("command_channel", Convert.ToString(cs.CommandChannel))));
160 m_log.DebugFormat("[IRC-Channel-{0}] CommandChannel : <{1}>", cs.idn, cs.CommandChannel);
161 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("relay_private_channels", Convert.ToString(cs.RelayPrivateChannels))));
162 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
163 cs.RelayPrivateChannels = Convert.ToBoolean(Substitute(rs, config.GetString("useworldcomm", Convert.ToString(cs.RelayPrivateChannels))));
164 m_log.DebugFormat("[IRC-Channel-{0}] RelayPrivateChannels : <{1}>", cs.idn, cs.RelayPrivateChannels);
165 cs.RelayChannelOut = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_out", Convert.ToString(cs.RelayChannelOut))));
166 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannelOut : <{1}>", cs.idn, cs.RelayChannelOut);
167 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("relay_private_channel_in", Convert.ToString(cs.RelayChannel))));
168 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
169 cs.RelayChannel = Convert.ToInt32(Substitute(rs, config.GetString("inchannel", Convert.ToString(cs.RelayChannel))));
170 m_log.DebugFormat("[IRC-Channel-{0}] RelayChannel : <{1}>", cs.idn, cs.RelayChannel);
171 cs.PrivateMessageFormat = Substitute(rs, config.GetString("msgformat", cs.PrivateMessageFormat));
172 m_log.DebugFormat("[IRC-Channel-{0}] PrivateMessageFormat : <{1}>", cs.idn, cs.PrivateMessageFormat);
173 cs.NoticeMessageFormat = Substitute(rs, config.GetString("noticeformat", cs.NoticeMessageFormat));
174 m_log.DebugFormat("[IRC-Channel-{0}] NoticeMessageFormat : <{1}>", cs.idn, cs.NoticeMessageFormat);
175 cs.ClientReporting = Convert.ToInt32(Substitute(rs, config.GetString("verbosity", cs.ClientReporting?"1":"0"))) > 0;
176 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
177 cs.ClientReporting = Convert.ToBoolean(Substitute(rs, config.GetString("report_clients", Convert.ToString(cs.ClientReporting))));
178 m_log.DebugFormat("[IRC-Channel-{0}] ClientReporting : <{1}>", cs.idn, cs.ClientReporting);
179 cs.AccessPassword = Substitute(rs, config.GetString("access_password", cs.AccessPassword));
180 m_log.DebugFormat("[IRC-Channel-{0}] AccessPassword : <{1}>", cs.idn, cs.AccessPassword);
181 cs.DefaultZone = Substitute(rs, config.GetString("fallback_region", cs.DefaultZone));
182 m_log.DebugFormat("[IRC-Channel-{0}] DefaultZone : <{1}>", cs.idn, cs.DefaultZone);
183 cs.ConnectDelay = Convert.ToInt32(Substitute(rs, config.GetString("connect_delay", Convert.ToString(cs.ConnectDelay))));
184 m_log.DebugFormat("[IRC-Channel-{0}] ConnectDelay : <{1}>", cs.idn, cs.ConnectDelay);
185 cs.PingDelay = Convert.ToInt32(Substitute(rs, config.GetString("ping_delay", Convert.ToString(cs.PingDelay))));
186 m_log.DebugFormat("[IRC-Channel-{0}] PingDelay : <{1}>", cs.idn, cs.PingDelay);
187
188 // Fail if fundamental information is still missing
189
190 if (cs.Server == null || cs.IrcChannel == null || cs.BaseNickname == null || cs.User == null)
191 throw new Exception(String.Format("[IRC-Channel-{0}] Invalid configuration for region {1}", cs.idn, rs.Region));
192
193 m_log.InfoFormat("[IRC-Channel-{0}] Configuration for Region {1} is valid", cs.idn, rs.Region);
194 m_log.InfoFormat("[IRC-Channel-{0}] Server = {1}", cs.idn, cs.Server);
195 m_log.InfoFormat("[IRC-Channel-{0}] Channel = {1}", cs.idn, cs.IrcChannel);
196 m_log.InfoFormat("[IRC-Channel-{0}] Port = {1}", cs.idn, cs.Port);
197 m_log.InfoFormat("[IRC-Channel-{0}] Nickname = {1}", cs.idn, cs.BaseNickname);
198 m_log.InfoFormat("[IRC-Channel-{0}] User = {1}", cs.idn, cs.User);
199
200 // Set the channel state for this region
201
202 rs.cs = Integrate(rs, cs);
203
204 }
205
206 // An initialized channel state instance is passed in. If an identical
207 // channel state instance already exists, then the existing instance
208 // is used to replace the supplied value.
209 // If the instance matches with respect to IRC, then the underlying
210 // IRCConnector is assigned to the supplied channel state and the
211 // updated value is returned.
212 // If there is no match, then the supplied instance is completed by
213 // creating and assigning an instance of an IRC connector.
214
215 private static ChannelState Integrate(RegionState rs, ChannelState p_cs)
216 {
217
218 ChannelState cs = p_cs;
219
220 // Check to see if we have an existing server/channel setup that can be used
221 // In the absence of variable substitution this will always resolve to the
222 // same ChannelState instance, and the table will only contains a single
223 // entry, so the performance considerations for the existing behavior are
224 // zero. Only the IRC connector is shared, the ChannelState still contains
225 // values that, while independent of the IRC connetion, do still distinguish
226 // this region's behavior.
227
228 foreach (ChannelState xcs in XIRCBridgeModule.m_channels)
229 {
230 if (cs.IsAPerfectMatchFor(xcs))
231 {
232 m_log.DebugFormat("[IRC-Channel-{0}] Channel state matched", cs.idn);
233 cs = xcs;
234 break;
235 }
236 if (cs.IsAConnectionMatchFor(xcs))
237 {
238 m_log.DebugFormat("[IRC-Channel-{0}] Channel matched", cs.idn);
239 cs.irc = xcs.irc;
240 break;
241 }
242 }
243
244 // No entry was found, so this is going to be a new entry.
245
246 if (cs.irc == null)
247 {
248
249 m_log.DebugFormat("[IRC-Channel-{0}] New channel required", cs.idn);
250
251 if ((cs.irc = new XIRCConnector(cs)) != null)
252 {
253 XIRCBridgeModule.m_channels.Add(cs);
254
255 m_log.InfoFormat("[IRC-Channel-{0}] New channel initialized for {1}, nick: {2}, commands {3}, private channels {4}",
256 cs.idn, rs.Region, cs.DefaultZone,
257 cs.CommandsEnabled ? "enabled" : "not enabled",
258 cs.RelayPrivateChannels ? "relayed" : "not relayed");
259 }
260 else
261 {
262 string txt = String.Format("[IRC-Channel-{0}] Region {1} failed to connect to channel {2} on server {3}:{4}",
263 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
264 m_log.Error(txt);
265 throw new Exception(txt);
266 }
267 }
268 else
269 {
270 m_log.InfoFormat("[IRC-Channel-{0}] Region {1} reusing existing connection to channel {2} on server {3}:{4}",
271 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
272 }
273
274 m_log.InfoFormat("[IRC-Channel-{0}] Region {1} connected to channel {2} on server {3}:{4}",
275 cs.idn, rs.Region, cs.IrcChannel, cs.Server, cs.Port);
276
277 // We're finally ready to commit ourselves
278
279 return cs;
280
281 }
282
283 // These routines allow differentiating changes to
284 // the underlying channel state. If necessary, a
285 // new channel state will be created.
286
287 internal ChannelState UpdateServer(RegionState rs, string server)
288 {
289 RemoveRegion(rs);
290 ChannelState cs = new ChannelState(this);
291 cs.Server = server;
292 cs = Integrate(rs, cs);
293 cs.AddRegion(rs);
294 return cs;
295 }
296
297 internal ChannelState UpdatePort(RegionState rs, string port)
298 {
299 RemoveRegion(rs);
300 ChannelState cs = new ChannelState(this);
301 cs.Port = Convert.ToUInt32(port);
302 cs = Integrate(rs, cs);
303 cs.AddRegion(rs);
304 return cs;
305 }
306
307 internal ChannelState UpdateChannel(RegionState rs, string channel)
308 {
309 RemoveRegion(rs);
310 ChannelState cs = new ChannelState(this);
311 cs.IrcChannel = channel;
312 cs = Integrate(rs, cs);
313 cs.AddRegion(rs);
314 return cs;
315 }
316
317 internal ChannelState UpdateNickname(RegionState rs, string nickname)
318 {
319 RemoveRegion(rs);
320 ChannelState cs = new ChannelState(this);
321 cs.BaseNickname = nickname;
322 cs = Integrate(rs, cs);
323 cs.AddRegion(rs);
324 return cs;
325 }
326
327 internal ChannelState UpdateClientReporting(RegionState rs, string cr)
328 {
329 RemoveRegion(rs);
330 ChannelState cs = new ChannelState(this);
331 cs.ClientReporting = Convert.ToBoolean(cr);
332 cs = Integrate(rs, cs);
333 cs.AddRegion(rs);
334 return cs;
335 }
336
337 internal ChannelState UpdateRelayIn(RegionState rs, string channel)
338 {
339 RemoveRegion(rs);
340 ChannelState cs = new ChannelState(this);
341 cs.RelayChannel = Convert.ToInt32(channel);
342 cs = Integrate(rs, cs);
343 cs.AddRegion(rs);
344 return cs;
345 }
346
347 internal ChannelState UpdateRelayOut(RegionState rs, string channel)
348 {
349 RemoveRegion(rs);
350 ChannelState cs = new ChannelState(this);
351 cs.RelayChannelOut = Convert.ToInt32(channel);
352 cs = Integrate(rs, cs);
353 cs.AddRegion(rs);
354 return cs;
355 }
356
357 // Determine whether or not this is a 'new' channel. Only those
358 // attributes that uniquely distinguish an IRC connection should
359 // be included here (and only those attributes should really be
360 // in the ChannelState structure)
361
362 private bool IsAConnectionMatchFor(ChannelState cs)
363 {
364 return (
365 Server == cs.Server &&
366 IrcChannel == cs.IrcChannel &&
367 Port == cs.Port &&
368 BaseNickname == cs.BaseNickname &&
369 User == cs.User
370 );
371 }
372
373 // This level of obsessive matching allows us to produce
374 // a minimal overhead int he case of a server which does
375 // need to differentiate IRC at a region level.
376
377 private bool IsAPerfectMatchFor(ChannelState cs)
378 {
379 return ( IsAConnectionMatchFor(cs) &&
380
381 RelayChannelOut == cs.RelayChannelOut &&
382 PrivateMessageFormat == cs.PrivateMessageFormat &&
383 NoticeMessageFormat == cs.NoticeMessageFormat &&
384 RandomizeNickname == cs.RandomizeNickname &&
385 AccessPassword == cs.AccessPassword &&
386 CommandsEnabled == cs.CommandsEnabled &&
387 CommandChannel == cs.CommandChannel &&
388 DefaultZone == cs.DefaultZone &&
389 RelayPrivateChannels == cs.RelayPrivateChannels &&
390 RelayChannel == cs.RelayChannel &&
391 ClientReporting == cs.ClientReporting
392 );
393 }
394
395 // This function implements the variable substitution mechanism
396 // for the configuration values. Each string read from the
397 // configuration file is scanned for '[...]' enclosures. Each
398 // one that is found is replaced by either a runtime variable
399 // (%xxx) or an existing configuration key. When no further
400 // substitution is possible, the remaining string is returned
401 // to the caller. This allows for arbitrarily nested
402 // enclosures.
403
404 private static string Substitute(RegionState rs, string instr)
405 {
406
407 string result = instr;
408
409 if (result == null || result.Length == 0)
410 return result;
411
412 // Repeatedly scan the string until all possible
413 // substitutions have been performed.
414
415 while (arg.IsMatch(result))
416 {
417
418 string vvar = arg.Match(result).ToString();
419 string var = vvar.Substring(1,vvar.Length-2).Trim();
420
421 switch (var.ToLower())
422 {
423 case "%region" :
424 result = result.Replace(vvar, rs.Region);
425 break;
426 case "%host" :
427 result = result.Replace(vvar, rs.Host);
428 break;
429 case "%master1" :
430 result = result.Replace(vvar, rs.MA1);
431 break;
432 case "%master2" :
433 result = result.Replace(vvar, rs.MA2);
434 break;
435 case "%locx" :
436 result = result.Replace(vvar, rs.LocX);
437 break;
438 case "%locy" :
439 result = result.Replace(vvar, rs.LocY);
440 break;
441 case "%k" :
442 result = result.Replace(vvar, rs.IDK);
443 break;
444 default :
445 result = result.Replace(vvar, rs.config.GetString(var,var));
446 break;
447 }
448 }
449
450 return result;
451
452 }
453
454 public void Close()
455 {
456
457 m_log.InfoFormat("[IRC-Channel-{0}] Closing channel <{1} to server <{2}:{3}>",
458 idn, IrcChannel, Server, Port);
459
460 m_log.InfoFormat("[IRC-Channel-{0}] There are {1} active clients",
461 idn, clientregions.Count);
462
463 irc.Close();
464
465 }
466
467 public void Open()
468 {
469 m_log.InfoFormat("[IRC-Channel-{0}] Opening channel <{1} to server <{2}:{3}>",
470 idn, IrcChannel, Server, Port);
471
472 irc.Open();
473
474 }
475
476 // These are called by each region that attaches to this channel. The call affects
477 // only the relationship of the region with the channel. Not the channel to IRC
478 // relationship (unless it is closed and we want it open).
479
480 public void Open(RegionState rs)
481 {
482 AddRegion(rs);
483 Open();
484 }
485
486 public void Close(RegionState rs)
487 {
488 RemoveRegion(rs);
489 }
490
491 // Add a client region to this channel if it is not already known
492
493 public void AddRegion(RegionState rs)
494 {
495 m_log.InfoFormat("[IRC-Channel-{0}] Adding region {1} to channel <{2} to server <{3}:{4}>",
496 idn, rs.Region, IrcChannel, Server, Port);
497 if (!clientregions.Contains(rs))
498 {
499 clientregions.Add(rs);
500 lock (irc) irc.depends++;
501 }
502 }
503
504 // Remove a client region from the channel. If this is the last
505 // region, then clean up the channel. The connector will clean itself
506 // up if it finds itself about to be GC'd.
507
508 public void RemoveRegion(RegionState rs)
509 {
510
511 m_log.InfoFormat("[IRC-Channel-{0}] Removing region {1} from channel <{2} to server <{3}:{4}>",
512 idn, rs.Region, IrcChannel, Server, Port);
513
514 if (clientregions.Contains(rs))
515 {
516 clientregions.Remove(rs);
517 lock (irc) irc.depends--;
518 }
519
520 }
521
522 // This function is lifted from the IRCConnector because it
523 // contains information that is not differentiating from an
524 // IRC point-of-view.
525
526 public static void OSChat(XIRCConnector p_irc, OSChatMessage c, bool cmsg)
527 {
528
529 // m_log.DebugFormat("[IRC-OSCHAT] from {0}:{1}", p_irc.Server, p_irc.IrcChannel);
530
531 try
532 {
533
534 // Scan through the set of unique channel configuration for those
535 // that belong to this connector. And then forward the message to
536 // all regions known to those channels.
537 // Note that this code is responsible for completing some of the
538 // settings for the inbound OSChatMessage
539
540 foreach (ChannelState cs in XIRCBridgeModule.m_channels)
541 {
542 if ( p_irc == cs.irc)
543 {
544
545 // This non-IRC differentiator moved to here
546
547 if (cmsg && !cs.ClientReporting)
548 continue;
549
550 // This non-IRC differentiator moved to here
551
552 c.Channel = (cs.RelayPrivateChannels ? cs.RelayChannel : 0);
553
554 foreach (RegionState region in cs.clientregions)
555 {
556 region.OSChat(cs.irc, c);
557 }
558
559 }
560 }
561
562 }
563 catch (Exception ex)
564 {
565 m_log.ErrorFormat("[IRC-OSCHAT]: BroadcastSim Exception: {0}", ex.Message);
566 m_log.Debug(ex);
567 }
568 }
569 }
570}