aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorJustin Clarke Casey2008-03-24 19:44:25 +0000
committerJustin Clarke Casey2008-03-24 19:44:25 +0000
commit45b9114df77e43be95487fbdd2b5739bdf665c1c (patch)
treef677b731631d0a10f8023113722afb53f48244fc /OpenSim
parentImplements llGetInventoryNumber() (diff)
downloadopensim-SC-45b9114df77e43be95487fbdd2b5739bdf665c1c.zip
opensim-SC-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.gz
opensim-SC-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.bz2
opensim-SC-45b9114df77e43be95487fbdd2b5739bdf665c1c.tar.xz
From: Michael Osias <mosias@us.ibm.com>
Fixes mantis 771 - multiple uses of llListen cause duplicate events Thanks Michael!
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/Environment/Modules/WorldCommModule.cs259
1 files changed, 146 insertions, 113 deletions
diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs
index b4e1fef..e1d2fbc 100644
--- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs
+++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using libsecondlife; 31using libsecondlife;
31using Nini.Config; 32using Nini.Config;
@@ -72,8 +73,8 @@ namespace OpenSim.Region.Environment.Modules
72 private object ListLock = new object(); 73 private object ListLock = new object();
73 private string m_name = "WorldCommModule"; 74 private string m_name = "WorldCommModule";
74 private ListenerManager m_listenerManager; 75 private ListenerManager m_listenerManager;
75 private Queue<ListenerInfo> m_pending; 76 private Queue m_pendingQ;
76 77 private Queue m_pending;
77 public WorldCommModule() 78 public WorldCommModule()
78 { 79 {
79 } 80 }
@@ -84,7 +85,8 @@ namespace OpenSim.Region.Environment.Modules
84 m_scene.RegisterModuleInterface<IWorldComm>(this); 85 m_scene.RegisterModuleInterface<IWorldComm>(this);
85 m_listenerManager = new ListenerManager(); 86 m_listenerManager = new ListenerManager();
86 m_scene.EventManager.OnNewClient += NewClient; 87 m_scene.EventManager.OnNewClient += NewClient;
87 m_pending = new Queue<ListenerInfo>(); 88 m_pendingQ = new Queue();
89 m_pending = Queue.Synchronized(m_pendingQ);
88 } 90 }
89 91
90 public void PostInitialise() 92 public void PostInitialise()
@@ -125,27 +127,29 @@ namespace OpenSim.Region.Environment.Modules
125 127
126 public void ListenControl(int handle, int active) 128 public void ListenControl(int handle, int active)
127 { 129 {
128 if (active == 1) 130 if (m_listenerManager != null)
129 m_listenerManager.Activate(handle); 131 {
130 else if (active == 0) 132 if (active == 1)
131 m_listenerManager.Dectivate(handle); 133 m_listenerManager.Activate(handle);
134 else if (active == 0)
135 m_listenerManager.Dectivate(handle);
136 }
132 } 137 }
133 138
134 public void ListenRemove(int handle) 139 public void ListenRemove(int handle)
135 { 140 {
136 m_listenerManager.Remove(handle); 141 if (m_listenerManager != null)
142 {
143 m_listenerManager.Remove(handle);
144 }
137 } 145 }
138 146
139 public void DeleteListener(LLUUID itemID) 147 public void DeleteListener(LLUUID itemID)
140 { 148 {
141 if (m_listenerManager != null) 149 if (m_listenerManager != null)
142 { 150 {
143 lock (ListLock) 151 m_listenerManager.DeleteListener(itemID);
144 {
145 m_listenerManager.DeleteListener(itemID);
146 }
147 } 152 }
148
149 } 153 }
150 154
151 // This method scans nearby objects and determines if they are listeners, 155 // This method scans nearby objects and determines if they are listeners,
@@ -175,87 +179,99 @@ namespace OpenSim.Region.Environment.Modules
175 179
176 m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); 180 m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
177 181
178 // Dont process if this message is from itself! 182 if(sPart != null)
179 if (li.GetHostID().ToString().Equals(sourceItemID) || 183 {
180 sPart.UUID.ToString().Equals(sourceItemID)) 184 // Dont process if this message is from itself!
181 continue; 185 if (li.GetHostID().ToString().Equals(sourceItemID) ||
186 sPart.UUID.ToString().Equals(sourceItemID))
187 continue;
182 188
183 double dis = 0; 189 double dis = 0;
184 190
185 if (source != null) 191 if (source != null)
186 dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition); 192 dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition);
187 else 193 else
188 dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition); 194 dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition);
189 195
190 switch (type) 196 switch (type)
191 { 197 {
192 case ChatTypeEnum.Whisper: 198 case ChatTypeEnum.Whisper:
193 199
194 if ((dis < 10) && (dis > -10)) 200 if ((dis < 10) && (dis > -10))
195 {
196 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
197 sourceItemID, sPart.UUID, channel, name, msg
198 );
199 if (isListener != null)
200 { 201 {
201 lock (CommListLock) 202 if (li.GetChannel() == channel)
202 { 203 {
203 m_pending.Enqueue(isListener); 204 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
205 sourceItemID, sPart.UUID, channel, name, msg
206 );
207 if (isListener != null)
208 {
209 lock (m_pending.SyncRoot)
210 {
211 m_pending.Enqueue(isListener);
212 }
213 }
204 } 214 }
205 } 215 }
206 } 216 break;
207 break;
208 217
209 case ChatTypeEnum.Say: 218 case ChatTypeEnum.Say:
210 219
211 if ((dis < 30) && (dis > -30)) 220 if ((dis < 30) && (dis > -30))
212 {
213 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
214 sourceItemID, sPart.UUID, channel, name, msg
215 );
216 if (isListener != null)
217 { 221 {
218 lock (CommListLock) 222 if (li.GetChannel() == channel)
219 { 223 {
220 m_pending.Enqueue(isListener); 224 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
225 sourceItemID, sPart.UUID, channel, name, msg
226 );
227 if (isListener != null)
228 {
229 lock (m_pending.SyncRoot)
230 {
231 m_pending.Enqueue(isListener);
232 }
233 }
221 } 234 }
222 } 235 }
223 } 236 break;
224 break;
225 237
226 case ChatTypeEnum.Shout: 238 case ChatTypeEnum.Shout:
227 if ((dis < 100) && (dis > -100)) 239 if ((dis < 100) && (dis > -100))
228 {
229 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
230 sourceItemID, sPart.UUID, channel, name, msg
231 );
232 if (isListener != null)
233 { 240 {
234 lock (CommListLock) 241 if (li.GetChannel() == channel)
235 { 242 {
236 m_pending.Enqueue(isListener); 243 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
244 sourceItemID, sPart.UUID, channel, name, msg
245 );
246 if (isListener != null)
247 {
248 lock (m_pending.SyncRoot)
249 {
250 m_pending.Enqueue(isListener);
251 }
252 }
237 } 253 }
238 } 254 }
239 } 255 break;
240 break;
241 256
242 case ChatTypeEnum.Broadcast: 257 case ChatTypeEnum.Broadcast:
243 ListenerInfo isListen = 258 ListenerInfo isListen =
244 m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg); 259 m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg);
245 if (isListen != null) 260 if (isListen != null)
246 {
247 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
248 sourceItemID, sPart.UUID, channel, name, msg
249 );
250 if (isListener != null)
251 { 261 {
252 lock (CommListLock) 262 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
263 sourceItemID, sPart.UUID, channel, name, msg
264 );
265 if (isListener != null)
253 { 266 {
254 m_pending.Enqueue(isListener); 267 lock (m_pending.SyncRoot)
268 {
269 m_pending.Enqueue(isListener);
270 }
255 } 271 }
256 } 272 }
257 } 273 break;
258 break; 274 }
259 } 275 }
260 } 276 }
261 } 277 }
@@ -273,9 +289,9 @@ namespace OpenSim.Region.Environment.Modules
273 { 289 {
274 ListenerInfo li = null; 290 ListenerInfo li = null;
275 291
276 lock (CommListLock) 292 lock (m_pending.SyncRoot)
277 { 293 {
278 li = m_pending.Dequeue(); 294 li = (ListenerInfo) m_pending.Dequeue();
279 } 295 }
280 296
281 return li; 297 return li;
@@ -283,12 +299,12 @@ namespace OpenSim.Region.Environment.Modules
283 299
284 public uint PeekNextMessageLocalID() 300 public uint PeekNextMessageLocalID()
285 { 301 {
286 return m_pending.Peek().GetLocalID(); 302 return ((ListenerInfo)m_pending.Peek()).GetLocalID();
287 } 303 }
288 304
289 public LLUUID PeekNextMessageItemID() 305 public LLUUID PeekNextMessageItemID()
290 { 306 {
291 return m_pending.Peek().GetItemID(); 307 return ((ListenerInfo)m_pending.Peek()).GetItemID();
292 } 308 }
293 309
294 } 310 }
@@ -298,15 +314,11 @@ namespace OpenSim.Region.Environment.Modules
298 // localID: local ID of host engine 314 // localID: local ID of host engine
299 public class ListenerManager 315 public class ListenerManager
300 { 316 {
301 private Dictionary<int, ListenerInfo> m_listeners; 317 //private Dictionary<int, ListenerInfo> m_listeners;
318 private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable());
302 private object ListenersLock = new object(); 319 private object ListenersLock = new object();
303 private int m_MaxListeners = 100; 320 private int m_MaxListeners = 100;
304 321
305 public ListenerManager()
306 {
307 m_listeners = new Dictionary<int, ListenerInfo>();
308 }
309
310 public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) 322 public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
311 { 323 {
312 if (m_listeners.Count < m_MaxListeners) 324 if (m_listeners.Count < m_MaxListeners)
@@ -321,7 +333,7 @@ namespace OpenSim.Region.Environment.Modules
321 { 333 {
322 ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg); 334 ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
323 335
324 lock (ListenersLock) 336 lock (m_listeners.SyncRoot)
325 { 337 {
326 m_listeners.Add(newHandle, li); 338 m_listeners.Add(newHandle, li);
327 } 339 }
@@ -336,17 +348,30 @@ namespace OpenSim.Region.Environment.Modules
336 348
337 public void Remove(int handle) 349 public void Remove(int handle)
338 { 350 {
339 m_listeners.Remove(handle); 351 lock (m_listeners.SyncRoot)
352 {
353 m_listeners.Remove(handle);
354 }
340 } 355 }
341 356
342 public void DeleteListener(LLUUID itemID) 357 public void DeleteListener(LLUUID itemID)
343 { 358 {
344 foreach (ListenerInfo li in m_listeners.Values) 359 ArrayList removedListeners = new ArrayList();
360
361 lock (m_listeners.SyncRoot)
345 { 362 {
346 if (li.GetItemID().Equals(itemID)) 363 IDictionaryEnumerator en = m_listeners.GetEnumerator();
364 while (en.MoveNext())
365 {
366 ListenerInfo li = (ListenerInfo)en.Value;
367 if (li.GetItemID().Equals(itemID))
368 {
369 removedListeners.Add(li.GetHandle());
370 }
371 }
372 foreach (int handle in removedListeners)
347 { 373 {
348 Remove(li.GetHandle()); 374 m_listeners.Remove(handle);
349 return;
350 } 375 }
351 } 376 }
352 } 377 }
@@ -375,20 +400,23 @@ namespace OpenSim.Region.Environment.Modules
375 400
376 public void Activate(int handle) 401 public void Activate(int handle)
377 { 402 {
378 ListenerInfo li;
379 403
380 if (m_listeners.TryGetValue(handle, out li)) 404 if (m_listeners.ContainsKey(handle))
381 { 405 {
382 li.Activate(); 406 lock (m_listeners.SyncRoot)
407 {
408 ListenerInfo li = (ListenerInfo)m_listeners[handle];
409 li.Activate();
410 }
383 } 411 }
384 } 412 }
385 413
386 public void Dectivate(int handle) 414 public void Dectivate(int handle)
387 { 415 {
388 ListenerInfo li;
389 416
390 if (m_listeners.TryGetValue(handle, out li)) 417 if (m_listeners.ContainsKey(handle))
391 { 418 {
419 ListenerInfo li = (ListenerInfo)m_listeners[handle];
392 li.Deactivate(); 420 li.Deactivate();
393 } 421 }
394 } 422 }
@@ -399,36 +427,41 @@ namespace OpenSim.Region.Environment.Modules
399 string msg) 427 string msg)
400 { 428 {
401 bool isMatch = true; 429 bool isMatch = true;
402 430 lock (m_listeners.SyncRoot)
403 foreach (ListenerInfo li in m_listeners.Values)
404 { 431 {
405 if (li.GetHostID().Equals(listenerKey)) 432 IDictionaryEnumerator en = m_listeners.GetEnumerator();
433 while (en.MoveNext())
406 { 434 {
407 if (li.IsActive()) 435 ListenerInfo li = (ListenerInfo)en.Value;
436
437 if (li.GetHostID().Equals(listenerKey))
408 { 438 {
409 if (channel == li.GetChannel()) 439 if (li.IsActive())
410 { 440 {
411 if ((li.GetID().ToString().Length > 0) && 441 if (channel == li.GetChannel())
412 (!li.GetID().Equals(LLUUID.Zero)))
413 { 442 {
414 if (!li.GetID().ToString().Equals(sourceItemID)) 443 if ((li.GetID().ToString().Length > 0) &&
444 (!li.GetID().Equals(LLUUID.Zero)))
415 { 445 {
416 isMatch = false; 446 if (!li.GetID().ToString().Equals(sourceItemID))
447 {
448 isMatch = false;
449 }
417 } 450 }
418 } 451 if (isMatch && (li.GetName().Length > 0))
419 if (isMatch && (li.GetName().Length > 0))
420 {
421 if (li.GetName().Equals(name))
422 { 452 {
423 isMatch = false; 453 if (li.GetName().Equals(name))
454 {
455 isMatch = false;
456 }
457 }
458 if (isMatch)
459 {
460 return new ListenerInfo(
461 li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
462 li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
463 );
424 } 464 }
425 }
426 if (isMatch)
427 {
428 return new ListenerInfo(
429 li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
430 li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
431 );
432 } 465 }
433 } 466 }
434 } 467 }
@@ -437,7 +470,7 @@ namespace OpenSim.Region.Environment.Modules
437 return null; 470 return null;
438 } 471 }
439 472
440 public Dictionary<int, ListenerInfo>.ValueCollection GetListeners() 473 public ICollection GetListeners()
441 { 474 {
442 return m_listeners.Values; 475 return m_listeners.Values;
443 } 476 }