clockwerk-opensim-stable – Blame information for rev 1

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