opensim-development – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 eva 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 OpenSimulator 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  
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Net;
32 using System.Reflection;
33 using System.Threading;
34 using log4net;
35 using Nini.Config;
36 using Mono.Addins;
37 using OpenMetaverse;
38 using OpenMetaverse.Messages.Linden;
39 using OpenMetaverse.Packets;
40 using OpenMetaverse.StructuredData;
41 using OpenSim.Framework;
42 using OpenSim.Framework.Console;
43 using OpenSim.Framework.Servers;
44 using OpenSim.Framework.Servers.HttpServer;
45 using OpenSim.Region.Framework.Interfaces;
46 using OpenSim.Region.Framework.Scenes;
47 using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
48 using Caps=OpenSim.Framework.Capabilities.Caps;
49  
50 namespace OpenSim.Region.ClientStack.Linden
51 {
52 public struct QueueItem
53 {
54 public int id;
55 public OSDMap body;
56 }
57  
58 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")]
59 public class EventQueueGetModule : IEventQueue, INonSharedRegionModule
60 {
61 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62 private static string LogHeader = "[EVENT QUEUE GET MODULE]";
63  
64 /// <value>
65 /// Debug level.
66 /// </value>
67 public int DebugLevel { get; set; }
68  
69 // Viewer post requests timeout in 60 secs
70 // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
71 //
72 private const int VIEWER_TIMEOUT = 60 * 1000;
73 // Just to be safe, we work on a 10 sec shorter cycle
74 private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
75  
76 protected Scene m_scene;
77  
78 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
79  
80 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
81 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
82 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
83  
84 #region INonSharedRegionModule methods
85 public virtual void Initialise(IConfigSource config)
86 {
87 }
88  
89 public void AddRegion(Scene scene)
90 {
91 m_scene = scene;
92 scene.RegisterModuleInterface<IEventQueue>(this);
93  
94 scene.EventManager.OnClientClosed += ClientClosed;
95 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
96  
97 MainConsole.Instance.Commands.AddCommand(
98 "Debug",
99 false,
100 "debug eq",
101 "debug eq [0|1|2]",
102 "Turn on event queue debugging\n"
103 + " <= 0 - turns off all event queue logging\n"
104 + " >= 1 - turns on outgoing event logging\n"
105 + " >= 2 - turns on poll notification",
106 HandleDebugEq);
107  
108 MainConsole.Instance.Commands.AddCommand(
109 "Debug",
110 false,
111 "show eq",
112 "show eq",
113 "Show contents of event queues for logged in avatars. Used for debugging.",
114 HandleShowEq);
115 }
116  
117 public void RemoveRegion(Scene scene)
118 {
119 if (m_scene != scene)
120 return;
121  
122 scene.EventManager.OnClientClosed -= ClientClosed;
123 scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
124  
125 scene.UnregisterModuleInterface<IEventQueue>(this);
126 m_scene = null;
127 }
128  
129 public void RegionLoaded(Scene scene)
130 {
131 }
132  
133 public virtual void Close()
134 {
135 }
136  
137 public virtual string Name
138 {
139 get { return "EventQueueGetModule"; }
140 }
141  
142 public Type ReplaceableInterface
143 {
144 get { return null; }
145 }
146  
147 #endregion
148  
149 protected void HandleDebugEq(string module, string[] args)
150 {
151 int debugLevel;
152  
153 if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
154 {
155 MainConsole.Instance.OutputFormat("Usage: debug eq [0|1|2]");
156 }
157 else
158 {
159 DebugLevel = debugLevel;
160 MainConsole.Instance.OutputFormat(
161 "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName);
162 }
163 }
164  
165 protected void HandleShowEq(string module, string[] args)
166 {
167 MainConsole.Instance.OutputFormat("For scene {0}", m_scene.Name);
168  
169 lock (queues)
170 {
171 foreach (KeyValuePair<UUID, Queue<OSD>> kvp in queues)
172 {
173 MainConsole.Instance.OutputFormat(
174 "For agent {0} there are {1} messages queued for send.",
175 kvp.Key, kvp.Value.Count);
176 }
177 }
178 }
179  
180 /// <summary>
181 /// Always returns a valid queue
182 /// </summary>
183 /// <param name="agentId"></param>
184 /// <returns></returns>
185 private Queue<OSD> TryGetQueue(UUID agentId)
186 {
187 lock (queues)
188 {
189 if (!queues.ContainsKey(agentId))
190 {
191 m_log.DebugFormat(
192 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
193 agentId, m_scene.RegionInfo.RegionName);
194 queues[agentId] = new Queue<OSD>();
195 }
196  
197 return queues[agentId];
198 }
199 }
200  
201 /// <summary>
202 /// May return a null queue
203 /// </summary>
204 /// <param name="agentId"></param>
205 /// <returns></returns>
206 private Queue<OSD> GetQueue(UUID agentId)
207 {
208 lock (queues)
209 {
210 if (queues.ContainsKey(agentId))
211 {
212 return queues[agentId];
213 }
214 else
215 return null;
216 }
217 }
218  
219 #region IEventQueue Members
220  
221 public bool Enqueue(OSD ev, UUID avatarID)
222 {
223 //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
224 try
225 {
226 Queue<OSD> queue = GetQueue(avatarID);
227 if (queue != null)
228 {
229 lock (queue)
230 queue.Enqueue(ev);
231 }
232 else
233 {
234 OSDMap evMap = (OSDMap)ev;
235 m_log.WarnFormat(
236 "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
237 avatarID, evMap["message"], m_scene.Name);
238 }
239 }
240 catch (NullReferenceException e)
241 {
242 m_log.Error("[EVENTQUEUE] Caught exception: " + e);
243 return false;
244 }
245  
246 return true;
247 }
248  
249 #endregion
250  
251 private void ClientClosed(UUID agentID, Scene scene)
252 {
253 //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
254  
255 lock (queues)
256 queues.Remove(agentID);
257  
258 List<UUID> removeitems = new List<UUID>();
259 lock (m_AvatarQueueUUIDMapping)
260 m_AvatarQueueUUIDMapping.Remove(agentID);
261  
262 UUID searchval = UUID.Zero;
263  
264 removeitems.Clear();
265  
266 lock (m_QueueUUIDAvatarMapping)
267 {
268 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys)
269 {
270 searchval = m_QueueUUIDAvatarMapping[ky];
271  
272 if (searchval == agentID)
273 {
274 removeitems.Add(ky);
275 }
276 }
277  
278 foreach (UUID ky in removeitems)
279 m_QueueUUIDAvatarMapping.Remove(ky);
280 }
281  
282 // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
283  
284 }
285  
286 /// <summary>
287 /// Generate an Event Queue Get handler path for the given eqg uuid.
288 /// </summary>
289 /// <param name='eqgUuid'></param>
290 private string GenerateEqgCapPath(UUID eqgUuid)
291 {
292 return string.Format("/CAPS/EQG/{0}/", eqgUuid);
293 }
294  
295 public void OnRegisterCaps(UUID agentID, Caps caps)
296 {
297 // Register an event queue for the client
298  
299 m_log.DebugFormat(
300 "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
301 agentID, caps, m_scene.RegionInfo.RegionName);
302  
303 // Let's instantiate a Queue for this agent right now
304 TryGetQueue(agentID);
305  
306 UUID eventQueueGetUUID;
307  
308 lock (m_AvatarQueueUUIDMapping)
309 {
310 // Reuse open queues. The client does!
311 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
312 {
313 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
314 eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
315 }
316 else
317 {
318 eventQueueGetUUID = UUID.Random();
319 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
320 }
321 }
322  
323 lock (m_QueueUUIDAvatarMapping)
324 {
325 if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID))
326 m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID);
327 }
328  
329 lock (m_AvatarQueueUUIDMapping)
330 {
331 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
332 m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
333 }
334  
335 caps.RegisterPollHandler(
336 "EventQueueGet",
337 new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
338  
339 Random rnd = new Random(Environment.TickCount);
340 lock (m_ids)
341 {
342 if (!m_ids.ContainsKey(agentID))
343 m_ids.Add(agentID, rnd.Next(30000000));
344 }
345 }
346  
347 public bool HasEvents(UUID requestID, UUID agentID)
348 {
349 // Don't use this, because of race conditions at agent closing time
350 //Queue<OSD> queue = TryGetQueue(agentID);
351  
352 Queue<OSD> queue = GetQueue(agentID);
353 if (queue != null)
354 lock (queue)
355 {
356 //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
357 return queue.Count > 0;
358 }
359  
360 return false;
361 }
362  
363 /// <summary>
364 /// Logs a debug line for an outbound event queue message if appropriate.
365 /// </summary>
366 /// <param name='element'>Element containing message</param>
367 private void LogOutboundDebugMessage(OSD element, UUID agentId)
368 {
369 if (element is OSDMap)
370 {
371 OSDMap ev = (OSDMap)element;
372 m_log.DebugFormat(
373 "Eq OUT {0,-30} to {1,-20} {2,-20}",
374 ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name);
375 }
376 }
377  
378 public Hashtable GetEvents(UUID requestID, UUID pAgentId)
379 {
380 if (DebugLevel >= 2)
381 m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name);
382  
383 Queue<OSD> queue = GetQueue(pAgentId);
384 if (queue == null)
385 {
386 return NoEvents(requestID, pAgentId);
387 }
388  
389 OSD element;
390 lock (queue)
391 {
392 if (queue.Count == 0)
393 return NoEvents(requestID, pAgentId);
394 element = queue.Dequeue(); // 15s timeout
395 }
396  
397 int thisID = 0;
398 lock (m_ids)
399 thisID = m_ids[pAgentId];
400  
401 OSDArray array = new OSDArray();
402 if (element == null) // didn't have an event in 15s
403 {
404 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
405 array.Add(EventQueueHelper.KeepAliveEvent());
406 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
407 }
408 else
409 {
410 if (DebugLevel > 0)
411 LogOutboundDebugMessage(element, pAgentId);
412  
413 array.Add(element);
414  
415 lock (queue)
416 {
417 while (queue.Count > 0)
418 {
419 element = queue.Dequeue();
420  
421 if (DebugLevel > 0)
422 LogOutboundDebugMessage(element, pAgentId);
423  
424 array.Add(element);
425 thisID++;
426 }
427 }
428 }
429  
430 OSDMap events = new OSDMap();
431 events.Add("events", array);
432  
433 events.Add("id", new OSDInteger(thisID));
434 lock (m_ids)
435 {
436 m_ids[pAgentId] = thisID + 1;
437 }
438 Hashtable responsedata = new Hashtable();
439 responsedata["int_response_code"] = 200;
440 responsedata["content_type"] = "application/xml";
441 responsedata["keepalive"] = false;
442 responsedata["reusecontext"] = false;
443 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
444 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
445 return responsedata;
446 }
447  
448 public Hashtable NoEvents(UUID requestID, UUID agentID)
449 {
450 Hashtable responsedata = new Hashtable();
451 responsedata["int_response_code"] = 502;
452 responsedata["content_type"] = "text/plain";
453 responsedata["keepalive"] = false;
454 responsedata["reusecontext"] = false;
455 responsedata["str_response_string"] = "Upstream error: ";
456 responsedata["error_status_text"] = "Upstream error:";
457 responsedata["http_protocol_version"] = "HTTP/1.0";
458 return responsedata;
459 }
460  
461 // public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
462 // {
463 // // TODO: this has to be redone to not busy-wait (and block the thread),
464 // // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
465 //
466 //// if (m_log.IsDebugEnabled)
467 //// {
468 //// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
469 //// foreach (object key in request.Keys)
470 //// {
471 //// debug += key.ToString() + "=" + request[key].ToString() + " ";
472 //// }
473 //// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
474 //// }
475 //
476 // Queue<OSD> queue = TryGetQueue(agentID);
477 // OSD element;
478 //
479 // lock (queue)
480 // element = queue.Dequeue(); // 15s timeout
481 //
482 // Hashtable responsedata = new Hashtable();
483 //
484 // int thisID = 0;
485 // lock (m_ids)
486 // thisID = m_ids[agentID];
487 //
488 // if (element == null)
489 // {
490 // //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
491 // if (thisID == -1) // close-request
492 // {
493 // m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
494 // responsedata["int_response_code"] = 404; //501; //410; //404;
495 // responsedata["content_type"] = "text/plain";
496 // responsedata["keepalive"] = false;
497 // responsedata["str_response_string"] = "Closed EQG";
498 // return responsedata;
499 // }
500 // responsedata["int_response_code"] = 502;
501 // responsedata["content_type"] = "text/plain";
502 // responsedata["keepalive"] = false;
503 // responsedata["str_response_string"] = "Upstream error: ";
504 // responsedata["error_status_text"] = "Upstream error:";
505 // responsedata["http_protocol_version"] = "HTTP/1.0";
506 // return responsedata;
507 // }
508 //
509 // OSDArray array = new OSDArray();
510 // if (element == null) // didn't have an event in 15s
511 // {
512 // // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
513 // array.Add(EventQueueHelper.KeepAliveEvent());
514 // //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
515 // }
516 // else
517 // {
518 // array.Add(element);
519 //
520 // if (element is OSDMap)
521 // {
522 // OSDMap ev = (OSDMap)element;
523 // m_log.DebugFormat(
524 // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
525 // ev["message"], m_scene.GetScenePresence(agentID).Name);
526 // }
527 //
528 // lock (queue)
529 // {
530 // while (queue.Count > 0)
531 // {
532 // element = queue.Dequeue();
533 //
534 // if (element is OSDMap)
535 // {
536 // OSDMap ev = (OSDMap)element;
537 // m_log.DebugFormat(
538 // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
539 // ev["message"], m_scene.GetScenePresence(agentID).Name);
540 // }
541 //
542 // array.Add(element);
543 // thisID++;
544 // }
545 // }
546 // }
547 //
548 // OSDMap events = new OSDMap();
549 // events.Add("events", array);
550 //
551 // events.Add("id", new OSDInteger(thisID));
552 // lock (m_ids)
553 // {
554 // m_ids[agentID] = thisID + 1;
555 // }
556 //
557 // responsedata["int_response_code"] = 200;
558 // responsedata["content_type"] = "application/xml";
559 // responsedata["keepalive"] = false;
560 // responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
561 //
562 // m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
563 //
564 // return responsedata;
565 // }
566  
567 // public Hashtable EventQueuePath2(Hashtable request)
568 // {
569 // string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
570 // // pull off the last "/" in the path.
571 // Hashtable responsedata = new Hashtable();
572 // capuuid = capuuid.Substring(0, capuuid.Length - 1);
573 // capuuid = capuuid.Replace("/CAPS/EQG/", "");
574 // UUID AvatarID = UUID.Zero;
575 // UUID capUUID = UUID.Zero;
576 //
577 // // parse the path and search for the avatar with it registered
578 // if (UUID.TryParse(capuuid, out capUUID))
579 // {
580 // lock (m_QueueUUIDAvatarMapping)
581 // {
582 // if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
583 // {
584 // AvatarID = m_QueueUUIDAvatarMapping[capUUID];
585 // }
586 // }
587 //
588 // if (AvatarID != UUID.Zero)
589 // {
590 // return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
591 // }
592 // else
593 // {
594 // responsedata["int_response_code"] = 404;
595 // responsedata["content_type"] = "text/plain";
596 // responsedata["keepalive"] = false;
597 // responsedata["str_response_string"] = "Not Found";
598 // responsedata["error_status_text"] = "Not Found";
599 // responsedata["http_protocol_version"] = "HTTP/1.0";
600 // return responsedata;
601 // // return 404
602 // }
603 // }
604 // else
605 // {
606 // responsedata["int_response_code"] = 404;
607 // responsedata["content_type"] = "text/plain";
608 // responsedata["keepalive"] = false;
609 // responsedata["str_response_string"] = "Not Found";
610 // responsedata["error_status_text"] = "Not Found";
611 // responsedata["http_protocol_version"] = "HTTP/1.0";
612 // return responsedata;
613 // // return 404
614 // }
615 // }
616  
617 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
618 {
619 // This is a fallback element to keep the client from loosing EventQueueGet
620 // Why does CAPS fail sometimes!?
621 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
622 string capuuid = path.Replace("/CAPS/EQG/","");
623 capuuid = capuuid.Substring(0, capuuid.Length - 1);
624  
625 // UUID AvatarID = UUID.Zero;
626 UUID capUUID = UUID.Zero;
627 if (UUID.TryParse(capuuid, out capUUID))
628 {
629 /* Don't remove this yet code cleaners!
630 * Still testing this!
631 *
632 lock (m_QueueUUIDAvatarMapping)
633 {
634 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
635 {
636 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
637 }
638 }
639  
640  
641 if (AvatarID != UUID.Zero)
642 {
643 // Repair the CAP!
644 //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
645 //string capsBase = "/CAPS/EQG/";
646 //caps.RegisterHandler("EventQueueGet",
647 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
648 //delegate(Hashtable m_dhttpMethod)
649 //{
650 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
651 //}));
652 // start new ID sequence.
653 Random rnd = new Random(System.Environment.TickCount);
654 lock (m_ids)
655 {
656 if (!m_ids.ContainsKey(AvatarID))
657 m_ids.Add(AvatarID, rnd.Next(30000000));
658 }
659  
660  
661 int thisID = 0;
662 lock (m_ids)
663 thisID = m_ids[AvatarID];
664  
665 BlockingLLSDQueue queue = GetQueue(AvatarID);
666 OSDArray array = new OSDArray();
667 LLSD element = queue.Dequeue(15000); // 15s timeout
668 if (element == null)
669 {
670  
671 array.Add(EventQueueHelper.KeepAliveEvent());
672 }
673 else
674 {
675 array.Add(element);
676 while (queue.Count() > 0)
677 {
678 array.Add(queue.Dequeue(1));
679 thisID++;
680 }
681 }
682 OSDMap events = new OSDMap();
683 events.Add("events", array);
684  
685 events.Add("id", new LLSDInteger(thisID));
686  
687 lock (m_ids)
688 {
689 m_ids[AvatarID] = thisID + 1;
690 }
691  
692 return events;
693 }
694 else
695 {
696 return new LLSD();
697 }
698 *
699 */
700 }
701 else
702 {
703 //return new LLSD();
704 }
705  
706 return new OSDString("shutdown404!");
707 }
708  
709 public void DisableSimulator(ulong handle, UUID avatarID)
710 {
711 OSD item = EventQueueHelper.DisableSimulator(handle);
712 Enqueue(item, avatarID);
713 }
714  
715 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
716 {
717 m_log.DebugFormat("{0} EnableSimulator. handle={1}, avatarID={2}, regionSize={3},{4}>",
718 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
719  
720 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
721 Enqueue(item, avatarID);
722 }
723  
724 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath,
725 ulong regionHandle, int regionSizeX, int regionSizeY)
726 {
727 m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, avatarID={2}, regionSize={3},{4}>",
728 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
729 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
730 Enqueue(item, avatarID);
731 }
732  
733 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
734 IPEndPoint regionExternalEndPoint,
735 uint locationID, uint flags, string capsURL,
736 UUID avatarID, int regionSizeX, int regionSizeY)
737 {
738 m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, avatarID={2}, regionSize=<{3},{4}>",
739 LogHeader, regionHandle, avatarID, regionSizeX, regionSizeY);
740  
741 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
742 locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
743 Enqueue(item, avatarID);
744 }
745  
746 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
747 IPEndPoint newRegionExternalEndPoint,
748 string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
749 {
750 m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
751 LogHeader, handle, avatarID, regionSizeX, regionSizeY);
752  
753 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
754 capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
755 Enqueue(item, avatarID);
756 }
757  
758 public void ChatterboxInvitation(UUID sessionID, string sessionName,
759 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
760 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
761 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
762 {
763 OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
764 timeStamp, offline, parentEstateID, position, ttl, transactionID,
765 fromGroup, binaryBucket);
766 Enqueue(item, toAgent);
767 //m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
768  
769 }
770  
771 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
772 bool isModerator, bool textMute)
773 {
774 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
775 isModerator, textMute);
776 Enqueue(item, fromAgent);
777 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
778 }
779  
780 public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID)
781 {
782 OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage);
783 Enqueue(item, avatarID);
784 }
785  
786 public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
787 {
788 OSD item = EventQueueHelper.GroupMembership(groupUpdate);
789 Enqueue(item, avatarID);
790 }
791  
792 public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
793 {
794 OSD item = EventQueueHelper.PlacesQuery(groupUpdate);
795 Enqueue(item, avatarID);
796 }
797  
798 public OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono)
799 {
800 return EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, running, mono);
801 }
802  
803 public OSD BuildEvent(string eventName, OSD eventBody)
804 {
805 return EventQueueHelper.BuildEvent(eventName, eventBody);
806 }
807  
808 public void partPhysicsProperties(uint localID, byte physhapetype,
809 float density, float friction, float bounce, float gravmod,UUID avatarID)
810 {
811 OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype,
812 density, friction, bounce, gravmod);
813 Enqueue(item, avatarID);
814 }
815 }
816 }