aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/Caps
diff options
context:
space:
mode:
authorDiva Canto2011-04-30 09:24:15 -0700
committerDiva Canto2011-04-30 09:24:15 -0700
commitd8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48 (patch)
tree4958279e2c75dcfa50021a8e559fb6ddc0a76725 /OpenSim/Region/ClientStack/Linden/Caps
parentDelaying starting the scripts on TPs and crossings until the agent is root. (diff)
downloadopensim-SC-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.zip
opensim-SC-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.gz
opensim-SC-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.bz2
opensim-SC-d8ee0cbe1cf93ca521f52ce39aa2a15cb5784e48.tar.xz
First stab at cleaning up Caps. Compiles. Untested.
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps')
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs729
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs399
2 files changed, 1128 insertions, 0 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
new file mode 100644
index 0000000..fe97bf2
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -0,0 +1,729 @@
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
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Threading;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.Messages.Linden;
38using OpenMetaverse.Packets;
39using OpenMetaverse.StructuredData;
40using OpenSim.Framework;
41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
46using Caps=OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Region.ClientStack.Linden
49{
50 public struct QueueItem
51 {
52 public int id;
53 public OSDMap body;
54 }
55
56 public class EventQueueGetModule : IEventQueue, IRegionModule
57 {
58 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59 protected Scene m_scene = null;
60 private IConfigSource m_gConfig;
61 bool enabledYN = false;
62
63 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
64
65 private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
66 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
67 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
68
69 #region IRegionModule methods
70 public virtual void Initialise(Scene scene, IConfigSource config)
71 {
72 m_gConfig = config;
73
74 IConfig startupConfig = m_gConfig.Configs["Startup"];
75
76 ReadConfigAndPopulate(scene, startupConfig, "Startup");
77
78 if (enabledYN)
79 {
80 m_scene = scene;
81 scene.RegisterModuleInterface<IEventQueue>(this);
82
83 // Register fallback handler
84 // Why does EQG Fail on region crossings!
85
86 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
87
88 scene.EventManager.OnNewClient += OnNewClient;
89
90 // TODO: Leaving these open, or closing them when we
91 // become a child is incorrect. It messes up TP in a big
92 // way. CAPS/EQ need to be active as long as the UDP
93 // circuit is there.
94
95 scene.EventManager.OnClientClosed += ClientClosed;
96 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
97 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
98 }
99 else
100 {
101 m_gConfig = null;
102 }
103
104 }
105
106 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
107 {
108 enabledYN = startupConfig.GetBoolean("EventQueue", true);
109 }
110
111 public void PostInitialise()
112 {
113 }
114
115 public virtual void Close()
116 {
117 }
118
119 public virtual string Name
120 {
121 get { return "EventQueueGetModule"; }
122 }
123
124 public bool IsSharedModule
125 {
126 get { return false; }
127 }
128 #endregion
129
130 /// <summary>
131 /// Always returns a valid queue
132 /// </summary>
133 /// <param name="agentId"></param>
134 /// <returns></returns>
135 private Queue<OSD> TryGetQueue(UUID agentId)
136 {
137 lock (queues)
138 {
139 if (!queues.ContainsKey(agentId))
140 {
141 /*
142 m_log.DebugFormat(
143 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
144 agentId, m_scene.RegionInfo.RegionName);
145 */
146 queues[agentId] = new Queue<OSD>();
147 }
148
149 return queues[agentId];
150 }
151 }
152
153 /// <summary>
154 /// May return a null queue
155 /// </summary>
156 /// <param name="agentId"></param>
157 /// <returns></returns>
158 private Queue<OSD> GetQueue(UUID agentId)
159 {
160 lock (queues)
161 {
162 if (queues.ContainsKey(agentId))
163 {
164 return queues[agentId];
165 }
166 else
167 return null;
168 }
169 }
170
171 #region IEventQueue Members
172
173 public bool Enqueue(OSD ev, UUID avatarID)
174 {
175 //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
176 try
177 {
178 Queue<OSD> queue = GetQueue(avatarID);
179 if (queue != null)
180 queue.Enqueue(ev);
181 }
182 catch(NullReferenceException e)
183 {
184 m_log.Error("[EVENTQUEUE] Caught exception: " + e);
185 return false;
186 }
187
188 return true;
189 }
190
191 #endregion
192
193 private void OnNewClient(IClientAPI client)
194 {
195 //client.OnLogout += ClientClosed;
196 }
197
198// private void ClientClosed(IClientAPI client)
199// {
200// ClientClosed(client.AgentId);
201// }
202
203 private void ClientClosed(UUID AgentID, Scene scene)
204 {
205 //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
206
207 int count = 0;
208 while (queues.ContainsKey(AgentID) && queues[AgentID].Count > 0 && count++ < 5)
209 {
210 Thread.Sleep(1000);
211 }
212
213 lock (queues)
214 {
215 queues.Remove(AgentID);
216 }
217 List<UUID> removeitems = new List<UUID>();
218 lock (m_AvatarQueueUUIDMapping)
219 {
220 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
221 {
222 if (ky == AgentID)
223 {
224 removeitems.Add(ky);
225 }
226 }
227
228 foreach (UUID ky in removeitems)
229 {
230 m_AvatarQueueUUIDMapping.Remove(ky);
231 MainServer.Instance.RemovePollServiceHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
232 }
233
234 }
235 UUID searchval = UUID.Zero;
236
237 removeitems.Clear();
238
239 lock (m_QueueUUIDAvatarMapping)
240 {
241 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys)
242 {
243 searchval = m_QueueUUIDAvatarMapping[ky];
244
245 if (searchval == AgentID)
246 {
247 removeitems.Add(ky);
248 }
249 }
250
251 foreach (UUID ky in removeitems)
252 m_QueueUUIDAvatarMapping.Remove(ky);
253
254 }
255 }
256
257 private void MakeChildAgent(ScenePresence avatar)
258 {
259 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
260 //lock (m_ids)
261 // {
262 //if (m_ids.ContainsKey(avatar.UUID))
263 //{
264 // close the event queue.
265 //m_ids[avatar.UUID] = -1;
266 //}
267 //}
268 }
269
270 public void OnRegisterCaps(UUID agentID, Caps caps)
271 {
272 // Register an event queue for the client
273
274 //m_log.DebugFormat(
275 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
276 // agentID, caps, m_scene.RegionInfo.RegionName);
277
278 // Let's instantiate a Queue for this agent right now
279 TryGetQueue(agentID);
280
281 string capsBase = "/CAPS/EQG/";
282 UUID EventQueueGetUUID = UUID.Zero;
283
284 lock (m_AvatarQueueUUIDMapping)
285 {
286 // Reuse open queues. The client does!
287 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
288 {
289 //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
290 EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
291 }
292 else
293 {
294 EventQueueGetUUID = UUID.Random();
295 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
296 }
297 }
298
299 lock (m_QueueUUIDAvatarMapping)
300 {
301 if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
302 m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
303 }
304
305 lock (m_AvatarQueueUUIDMapping)
306 {
307 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
308 m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
309 }
310
311 // Register this as a caps handler
312 caps.RegisterHandler("EventQueueGet",
313 new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/",
314 delegate(Hashtable m_dhttpMethod)
315 {
316 return ProcessQueue(m_dhttpMethod, agentID, caps);
317 }));
318
319 // This will persist this beyond the expiry of the caps handlers
320 MainServer.Instance.AddPollServiceHTTPHandler(
321 capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID));
322
323 Random rnd = new Random(Environment.TickCount);
324 lock (m_ids)
325 {
326 if (!m_ids.ContainsKey(agentID))
327 m_ids.Add(agentID, rnd.Next(30000000));
328 }
329 }
330
331 public bool HasEvents(UUID requestID, UUID agentID)
332 {
333 // Don't use this, because of race conditions at agent closing time
334 //Queue<OSD> queue = TryGetQueue(agentID);
335
336 Queue<OSD> queue = GetQueue(agentID);
337 if (queue != null)
338 lock (queue)
339 {
340 if (queue.Count > 0)
341 return true;
342 else
343 return false;
344 }
345 return false;
346 }
347
348 public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request)
349 {
350 Queue<OSD> queue = TryGetQueue(pAgentId);
351 OSD element;
352 lock (queue)
353 {
354 if (queue.Count == 0)
355 return NoEvents(requestID, pAgentId);
356 element = queue.Dequeue(); // 15s timeout
357 }
358
359
360
361 int thisID = 0;
362 lock (m_ids)
363 thisID = m_ids[pAgentId];
364
365 OSDArray array = new OSDArray();
366 if (element == null) // didn't have an event in 15s
367 {
368 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
369 array.Add(EventQueueHelper.KeepAliveEvent());
370 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
371 }
372 else
373 {
374 array.Add(element);
375 lock (queue)
376 {
377 while (queue.Count > 0)
378 {
379 array.Add(queue.Dequeue());
380 thisID++;
381 }
382 }
383 }
384
385 OSDMap events = new OSDMap();
386 events.Add("events", array);
387
388 events.Add("id", new OSDInteger(thisID));
389 lock (m_ids)
390 {
391 m_ids[pAgentId] = thisID + 1;
392 }
393 Hashtable responsedata = new Hashtable();
394 responsedata["int_response_code"] = 200;
395 responsedata["content_type"] = "application/xml";
396 responsedata["keepalive"] = false;
397 responsedata["reusecontext"] = false;
398 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
399 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
400 return responsedata;
401 }
402
403 public Hashtable NoEvents(UUID requestID, UUID agentID)
404 {
405 Hashtable responsedata = new Hashtable();
406 responsedata["int_response_code"] = 502;
407 responsedata["content_type"] = "text/plain";
408 responsedata["keepalive"] = false;
409 responsedata["reusecontext"] = false;
410 responsedata["str_response_string"] = "Upstream error: ";
411 responsedata["error_status_text"] = "Upstream error:";
412 responsedata["http_protocol_version"] = "HTTP/1.0";
413 return responsedata;
414 }
415
416 public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
417 {
418 // TODO: this has to be redone to not busy-wait (and block the thread),
419 // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
420
421// if (m_log.IsDebugEnabled)
422// {
423// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
424// foreach (object key in request.Keys)
425// {
426// debug += key.ToString() + "=" + request[key].ToString() + " ";
427// }
428// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
429// }
430
431 Queue<OSD> queue = TryGetQueue(agentID);
432 OSD element = queue.Dequeue(); // 15s timeout
433
434 Hashtable responsedata = new Hashtable();
435
436 int thisID = 0;
437 lock (m_ids)
438 thisID = m_ids[agentID];
439
440 if (element == null)
441 {
442 //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
443 if (thisID == -1) // close-request
444 {
445 m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
446 responsedata["int_response_code"] = 404; //501; //410; //404;
447 responsedata["content_type"] = "text/plain";
448 responsedata["keepalive"] = false;
449 responsedata["str_response_string"] = "Closed EQG";
450 return responsedata;
451 }
452 responsedata["int_response_code"] = 502;
453 responsedata["content_type"] = "text/plain";
454 responsedata["keepalive"] = 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 OSDArray array = new OSDArray();
462 if (element == null) // didn't have an event in 15s
463 {
464 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
465 array.Add(EventQueueHelper.KeepAliveEvent());
466 //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
467 }
468 else
469 {
470 array.Add(element);
471 while (queue.Count > 0)
472 {
473 array.Add(queue.Dequeue());
474 thisID++;
475 }
476 }
477
478 OSDMap events = new OSDMap();
479 events.Add("events", array);
480
481 events.Add("id", new OSDInteger(thisID));
482 lock (m_ids)
483 {
484 m_ids[agentID] = thisID + 1;
485 }
486
487 responsedata["int_response_code"] = 200;
488 responsedata["content_type"] = "application/xml";
489 responsedata["keepalive"] = false;
490 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
491 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
492
493 return responsedata;
494 }
495
496 public Hashtable EventQueuePoll(Hashtable request)
497 {
498 return new Hashtable();
499 }
500
501 public Hashtable EventQueuePath2(Hashtable request)
502 {
503 string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
504 // pull off the last "/" in the path.
505 Hashtable responsedata = new Hashtable();
506 capuuid = capuuid.Substring(0, capuuid.Length - 1);
507 capuuid = capuuid.Replace("/CAPS/EQG/", "");
508 UUID AvatarID = UUID.Zero;
509 UUID capUUID = UUID.Zero;
510
511 // parse the path and search for the avatar with it registered
512 if (UUID.TryParse(capuuid, out capUUID))
513 {
514 lock (m_QueueUUIDAvatarMapping)
515 {
516 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
517 {
518 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
519 }
520 }
521 if (AvatarID != UUID.Zero)
522 {
523 return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsHandlerForUser(AvatarID));
524 }
525 else
526 {
527 responsedata["int_response_code"] = 404;
528 responsedata["content_type"] = "text/plain";
529 responsedata["keepalive"] = false;
530 responsedata["str_response_string"] = "Not Found";
531 responsedata["error_status_text"] = "Not Found";
532 responsedata["http_protocol_version"] = "HTTP/1.0";
533 return responsedata;
534 // return 404
535 }
536 }
537 else
538 {
539 responsedata["int_response_code"] = 404;
540 responsedata["content_type"] = "text/plain";
541 responsedata["keepalive"] = false;
542 responsedata["str_response_string"] = "Not Found";
543 responsedata["error_status_text"] = "Not Found";
544 responsedata["http_protocol_version"] = "HTTP/1.0";
545 return responsedata;
546 // return 404
547 }
548
549 }
550
551 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
552 {
553 // This is a fallback element to keep the client from loosing EventQueueGet
554 // Why does CAPS fail sometimes!?
555 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
556 string capuuid = path.Replace("/CAPS/EQG/","");
557 capuuid = capuuid.Substring(0, capuuid.Length - 1);
558
559// UUID AvatarID = UUID.Zero;
560 UUID capUUID = UUID.Zero;
561 if (UUID.TryParse(capuuid, out capUUID))
562 {
563/* Don't remove this yet code cleaners!
564 * Still testing this!
565 *
566 lock (m_QueueUUIDAvatarMapping)
567 {
568 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
569 {
570 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
571 }
572 }
573
574
575 if (AvatarID != UUID.Zero)
576 {
577 // Repair the CAP!
578 //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
579 //string capsBase = "/CAPS/EQG/";
580 //caps.RegisterHandler("EventQueueGet",
581 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
582 //delegate(Hashtable m_dhttpMethod)
583 //{
584 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
585 //}));
586 // start new ID sequence.
587 Random rnd = new Random(System.Environment.TickCount);
588 lock (m_ids)
589 {
590 if (!m_ids.ContainsKey(AvatarID))
591 m_ids.Add(AvatarID, rnd.Next(30000000));
592 }
593
594
595 int thisID = 0;
596 lock (m_ids)
597 thisID = m_ids[AvatarID];
598
599 BlockingLLSDQueue queue = GetQueue(AvatarID);
600 OSDArray array = new OSDArray();
601 LLSD element = queue.Dequeue(15000); // 15s timeout
602 if (element == null)
603 {
604
605 array.Add(EventQueueHelper.KeepAliveEvent());
606 }
607 else
608 {
609 array.Add(element);
610 while (queue.Count() > 0)
611 {
612 array.Add(queue.Dequeue(1));
613 thisID++;
614 }
615 }
616 OSDMap events = new OSDMap();
617 events.Add("events", array);
618
619 events.Add("id", new LLSDInteger(thisID));
620
621 lock (m_ids)
622 {
623 m_ids[AvatarID] = thisID + 1;
624 }
625
626 return events;
627 }
628 else
629 {
630 return new LLSD();
631 }
632*
633*/
634 }
635 else
636 {
637 //return new LLSD();
638 }
639
640 return new OSDString("shutdown404!");
641 }
642
643 public void DisableSimulator(ulong handle, UUID avatarID)
644 {
645 OSD item = EventQueueHelper.DisableSimulator(handle);
646 Enqueue(item, avatarID);
647 }
648
649 public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID)
650 {
651 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint);
652 Enqueue(item, avatarID);
653 }
654
655 public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath)
656 {
657 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath);
658 Enqueue(item, avatarID);
659 }
660
661 public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
662 IPEndPoint regionExternalEndPoint,
663 uint locationID, uint flags, string capsURL,
664 UUID avatarID)
665 {
666 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
667 locationID, flags, capsURL, avatarID);
668 Enqueue(item, avatarID);
669 }
670
671 public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
672 IPEndPoint newRegionExternalEndPoint,
673 string capsURL, UUID avatarID, UUID sessionID)
674 {
675 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
676 capsURL, avatarID, sessionID);
677 Enqueue(item, avatarID);
678 }
679
680 public void ChatterboxInvitation(UUID sessionID, string sessionName,
681 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
682 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
683 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
684 {
685 OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
686 timeStamp, offline, parentEstateID, position, ttl, transactionID,
687 fromGroup, binaryBucket);
688 Enqueue(item, toAgent);
689 //m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
690
691 }
692
693 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat,
694 bool isModerator, bool textMute)
695 {
696 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
697 isModerator, textMute);
698 Enqueue(item, toAgent);
699 //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
700 }
701
702 public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID)
703 {
704 OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage);
705 Enqueue(item, avatarID);
706 }
707
708 public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
709 {
710 OSD item = EventQueueHelper.GroupMembership(groupUpdate);
711 Enqueue(item, avatarID);
712 }
713 public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
714 {
715 OSD item = EventQueueHelper.PlacesQuery(groupUpdate);
716 Enqueue(item, avatarID);
717 }
718
719 public OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono)
720 {
721 return EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, running, mono);
722 }
723
724 public OSD BuildEvent(string eventName, OSD eventBody)
725 {
726 return EventQueueHelper.BuildEvent(eventName, eventBody);
727 }
728 }
729}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
new file mode 100644
index 0000000..3f49aba
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs
@@ -0,0 +1,399 @@
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
28using System;
29using System.Net;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenMetaverse.StructuredData;
33using OpenMetaverse.Messages.Linden;
34
35namespace OpenSim.Region.ClientStack.Linden
36{
37 public class EventQueueHelper
38 {
39 private EventQueueHelper() {} // no construction possible, it's an utility class
40
41 private static byte[] ulongToByteArray(ulong uLongValue)
42 {
43 // Reverse endianness of RegionHandle
44 return new byte[]
45 {
46 (byte)((uLongValue >> 56) % 256),
47 (byte)((uLongValue >> 48) % 256),
48 (byte)((uLongValue >> 40) % 256),
49 (byte)((uLongValue >> 32) % 256),
50 (byte)((uLongValue >> 24) % 256),
51 (byte)((uLongValue >> 16) % 256),
52 (byte)((uLongValue >> 8) % 256),
53 (byte)(uLongValue % 256)
54 };
55 }
56
57// private static byte[] uintToByteArray(uint uIntValue)
58// {
59// byte[] result = new byte[4];
60// Utils.UIntToBytesBig(uIntValue, result, 0);
61// return result;
62// }
63
64 public static OSD BuildEvent(string eventName, OSD eventBody)
65 {
66 OSDMap llsdEvent = new OSDMap(2);
67 llsdEvent.Add("message", new OSDString(eventName));
68 llsdEvent.Add("body", eventBody);
69
70 return llsdEvent;
71 }
72
73 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint)
74 {
75 OSDMap llsdSimInfo = new OSDMap(3);
76
77 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
78 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
79 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
80
81 OSDArray arr = new OSDArray(1);
82 arr.Add(llsdSimInfo);
83
84 OSDMap llsdBody = new OSDMap(1);
85 llsdBody.Add("SimulatorInfo", arr);
86
87 return BuildEvent("EnableSimulator", llsdBody);
88 }
89
90 public static OSD DisableSimulator(ulong handle)
91 {
92 //OSDMap llsdSimInfo = new OSDMap(1);
93
94 //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle)));
95
96 //OSDArray arr = new OSDArray(1);
97 //arr.Add(llsdSimInfo);
98
99 OSDMap llsdBody = new OSDMap(0);
100 //llsdBody.Add("SimulatorInfo", arr);
101
102 return BuildEvent("DisableSimulator", llsdBody);
103 }
104
105 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
106 IPEndPoint newRegionExternalEndPoint,
107 string capsURL, UUID agentID, UUID sessionID)
108 {
109 OSDArray lookAtArr = new OSDArray(3);
110 lookAtArr.Add(OSD.FromReal(lookAt.X));
111 lookAtArr.Add(OSD.FromReal(lookAt.Y));
112 lookAtArr.Add(OSD.FromReal(lookAt.Z));
113
114 OSDArray positionArr = new OSDArray(3);
115 positionArr.Add(OSD.FromReal(pos.X));
116 positionArr.Add(OSD.FromReal(pos.Y));
117 positionArr.Add(OSD.FromReal(pos.Z));
118
119 OSDMap infoMap = new OSDMap(2);
120 infoMap.Add("LookAt", lookAtArr);
121 infoMap.Add("Position", positionArr);
122
123 OSDArray infoArr = new OSDArray(1);
124 infoArr.Add(infoMap);
125
126 OSDMap agentDataMap = new OSDMap(2);
127 agentDataMap.Add("AgentID", OSD.FromUUID(agentID));
128 agentDataMap.Add("SessionID", OSD.FromUUID(sessionID));
129
130 OSDArray agentDataArr = new OSDArray(1);
131 agentDataArr.Add(agentDataMap);
132
133 OSDMap regionDataMap = new OSDMap(4);
134 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
135 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
136 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
137 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
138
139 OSDArray regionDataArr = new OSDArray(1);
140 regionDataArr.Add(regionDataMap);
141
142 OSDMap llsdBody = new OSDMap(3);
143 llsdBody.Add("Info", infoArr);
144 llsdBody.Add("AgentData", agentDataArr);
145 llsdBody.Add("RegionData", regionDataArr);
146
147 return BuildEvent("CrossedRegion", llsdBody);
148 }
149
150 public static OSD TeleportFinishEvent(
151 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
152 uint locationID, uint flags, string capsURL, UUID agentID)
153 {
154 OSDMap info = new OSDMap();
155 info.Add("AgentID", OSD.FromUUID(agentID));
156 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
157 info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle)));
158 info.Add("SeedCapability", OSD.FromString(capsURL));
159 info.Add("SimAccess", OSD.FromInteger(simAccess));
160 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
161 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
162 info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
163
164 OSDArray infoArr = new OSDArray();
165 infoArr.Add(info);
166
167 OSDMap body = new OSDMap();
168 body.Add("Info", infoArr);
169
170 return BuildEvent("TeleportFinish", body);
171 }
172
173 public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono)
174 {
175 OSDMap script = new OSDMap();
176 script.Add("ObjectID", OSD.FromUUID(objectID));
177 script.Add("ItemID", OSD.FromUUID(itemID));
178 script.Add("Running", OSD.FromBoolean(running));
179 script.Add("Mono", OSD.FromBoolean(mono));
180
181 OSDArray scriptArr = new OSDArray();
182 scriptArr.Add(script);
183
184 OSDMap body = new OSDMap();
185 body.Add("Script", scriptArr);
186
187 return BuildEvent("ScriptRunningReply", body);
188 }
189
190 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap)
191 {
192 OSDMap body = new OSDMap(3);
193 body.Add("agent-id", new OSDUUID(agentID));
194 body.Add("sim-ip-and-port", new OSDString(simIpAndPort));
195 body.Add("seed-capability", new OSDString(seedcap));
196
197 return BuildEvent("EstablishAgentCommunication", body);
198 }
199
200 public static OSD KeepAliveEvent()
201 {
202 return BuildEvent("FAKEEVENT", new OSDMap());
203 }
204
205 public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate)
206 {
207 OSDMap body = new OSDMap(4);
208
209 body.Add("agent_id", new OSDUUID(agentID));
210 body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0));
211 body.Add("god_level", new OSDInteger(godLevel));
212 body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0));
213
214 return body;
215 }
216
217 public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent,
218 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
219 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
220 {
221 OSDMap messageParams = new OSDMap(15);
222 messageParams.Add("type", new OSDInteger((int)dialog));
223
224 OSDArray positionArray = new OSDArray(3);
225 positionArray.Add(OSD.FromReal(position.X));
226 positionArray.Add(OSD.FromReal(position.Y));
227 positionArray.Add(OSD.FromReal(position.Z));
228 messageParams.Add("position", positionArray);
229
230 messageParams.Add("region_id", new OSDUUID(UUID.Zero));
231 messageParams.Add("to_id", new OSDUUID(toAgent));
232 messageParams.Add("source", new OSDInteger(0));
233
234 OSDMap data = new OSDMap(1);
235 data.Add("binary_bucket", OSD.FromBinary(binaryBucket));
236 messageParams.Add("data", data);
237 messageParams.Add("message", new OSDString(message));
238 messageParams.Add("id", new OSDUUID(transactionID));
239 messageParams.Add("from_name", new OSDString(fromName));
240 messageParams.Add("timestamp", new OSDInteger((int)timeStamp));
241 messageParams.Add("offline", new OSDInteger(offline ? 1 : 0));
242 messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID));
243 messageParams.Add("ttl", new OSDInteger((int)ttl));
244 messageParams.Add("from_id", new OSDUUID(fromAgent));
245 messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0));
246
247 return messageParams;
248 }
249
250 public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent,
251 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
252 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket,
253 bool checkEstate, int godLevel, bool limitedToEstate)
254 {
255 OSDMap im = new OSDMap(2);
256 im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent,
257 fromName, dialog, timeStamp, offline, parentEstateID,
258 position, ttl, transactionID, fromGroup, binaryBucket));
259
260 im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate));
261
262 return im;
263 }
264
265
266 public static OSD ChatterboxInvitation(UUID sessionID, string sessionName,
267 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
268 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
269 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
270 {
271 OSDMap body = new OSDMap(5);
272 body.Add("session_id", new OSDUUID(sessionID));
273 body.Add("from_name", new OSDString(fromName));
274 body.Add("session_name", new OSDString(sessionName));
275 body.Add("from_id", new OSDUUID(fromAgent));
276
277 body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent,
278 fromName, dialog, timeStamp, offline, parentEstateID, position,
279 ttl, transactionID, fromGroup, binaryBucket, true, 0, true));
280
281 OSDMap chatterboxInvitation = new OSDMap(2);
282 chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation"));
283 chatterboxInvitation.Add("body", body);
284 return chatterboxInvitation;
285 }
286
287 public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID,
288 UUID agentID, bool canVoiceChat, bool isModerator, bool textMute)
289 {
290 OSDMap body = new OSDMap();
291 OSDMap agentUpdates = new OSDMap();
292 OSDMap infoDetail = new OSDMap();
293 OSDMap mutes = new OSDMap();
294
295 mutes.Add("text", OSD.FromBoolean(textMute));
296 infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat));
297 infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator));
298 infoDetail.Add("mutes", mutes);
299 OSDMap info = new OSDMap();
300 info.Add("info", infoDetail);
301 agentUpdates.Add(agentID.ToString(), info);
302 body.Add("agent_updates", agentUpdates);
303 body.Add("session_id", OSD.FromUUID(sessionID));
304 body.Add("updates", new OSD());
305
306 OSDMap chatterBoxSessionAgentListUpdates = new OSDMap();
307 chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates"));
308 chatterBoxSessionAgentListUpdates.Add("body", body);
309
310 return chatterBoxSessionAgentListUpdates;
311 }
312
313 public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket)
314 {
315 OSDMap groupUpdate = new OSDMap();
316 groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate"));
317
318 OSDMap body = new OSDMap();
319 OSDArray agentData = new OSDArray();
320 OSDMap agentDataMap = new OSDMap();
321 agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID));
322 agentData.Add(agentDataMap);
323 body.Add("AgentData", agentData);
324
325 OSDArray groupData = new OSDArray();
326
327 foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData)
328 {
329 OSDMap groupDataMap = new OSDMap();
330 groupDataMap.Add("ListInProfile", OSD.FromBoolean(false));
331 groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID));
332 groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID));
333 groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution));
334 groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers)));
335 groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName)));
336 groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices));
337
338 groupData.Add(groupDataMap);
339
340 }
341 body.Add("GroupData", groupData);
342 groupUpdate.Add("body", body);
343
344 return groupUpdate;
345 }
346
347 public static OSD PlacesQuery(PlacesReplyPacket PlacesReply)
348 {
349 OSDMap placesReply = new OSDMap();
350 placesReply.Add("message", OSD.FromString("PlacesReplyMessage"));
351
352 OSDMap body = new OSDMap();
353 OSDArray agentData = new OSDArray();
354 OSDMap agentDataMap = new OSDMap();
355 agentDataMap.Add("AgentID", OSD.FromUUID(PlacesReply.AgentData.AgentID));
356 agentDataMap.Add("QueryID", OSD.FromUUID(PlacesReply.AgentData.QueryID));
357 agentDataMap.Add("TransactionID", OSD.FromUUID(PlacesReply.TransactionData.TransactionID));
358 agentData.Add(agentDataMap);
359 body.Add("AgentData", agentData);
360
361 OSDArray QueryData = new OSDArray();
362
363 foreach (PlacesReplyPacket.QueryDataBlock groupDataBlock in PlacesReply.QueryData)
364 {
365 OSDMap QueryDataMap = new OSDMap();
366 QueryDataMap.Add("ActualArea", OSD.FromInteger(groupDataBlock.ActualArea));
367 QueryDataMap.Add("BillableArea", OSD.FromInteger(groupDataBlock.BillableArea));
368 QueryDataMap.Add("Description", OSD.FromBinary(groupDataBlock.Desc));
369 QueryDataMap.Add("Dwell", OSD.FromInteger((int)groupDataBlock.Dwell));
370 QueryDataMap.Add("Flags", OSD.FromString(Convert.ToString(groupDataBlock.Flags)));
371 QueryDataMap.Add("GlobalX", OSD.FromInteger((int)groupDataBlock.GlobalX));
372 QueryDataMap.Add("GlobalY", OSD.FromInteger((int)groupDataBlock.GlobalY));
373 QueryDataMap.Add("GlobalZ", OSD.FromInteger((int)groupDataBlock.GlobalZ));
374 QueryDataMap.Add("Name", OSD.FromBinary(groupDataBlock.Name));
375 QueryDataMap.Add("OwnerID", OSD.FromUUID(groupDataBlock.OwnerID));
376 QueryDataMap.Add("SimName", OSD.FromBinary(groupDataBlock.SimName));
377 QueryDataMap.Add("SnapShotID", OSD.FromUUID(groupDataBlock.SnapshotID));
378 QueryDataMap.Add("ProductSku", OSD.FromInteger(0));
379 QueryDataMap.Add("Price", OSD.FromInteger(groupDataBlock.Price));
380
381 QueryData.Add(QueryDataMap);
382 }
383 body.Add("QueryData", QueryData);
384 placesReply.Add("QueryData[]", body);
385
386 return placesReply;
387 }
388
389 public static OSD ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage)
390 {
391 OSDMap message = new OSDMap();
392 message.Add("message", OSD.FromString("ParcelProperties"));
393 OSD message_body = parcelPropertiesMessage.Serialize();
394 message.Add("body", message_body);
395 return message;
396 }
397
398 }
399}