aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework/EventQueue
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework/EventQueue')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs630
-rw-r--r--OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs459
2 files changed, 1089 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs
new file mode 100644
index 0000000..e81466a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs
@@ -0,0 +1,630 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Net.Sockets;
33using System.Reflection;
34using System.Threading;
35using System.Xml;
36using OpenMetaverse;
37using OpenMetaverse.Packets;
38using OpenMetaverse.StructuredData;
39using log4net;
40using Nini.Config;
41using Nwc.XmlRpc;
42using OpenSim.Framework;
43using OpenSim.Framework.Communications.Cache;
44using OpenSim.Framework.Communications.Capabilities;
45using OpenSim.Framework.Servers;
46using OpenSim.Region.Framework.Interfaces;
47using OpenSim.Region.Framework.Scenes;
48
49using OSD = OpenMetaverse.StructuredData.OSD;
50using OSDMap = OpenMetaverse.StructuredData.OSDMap;
51using OSDArray = OpenMetaverse.StructuredData.OSDArray;
52using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
53using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
54
55namespace OpenSim.Region.CoreModules.Framework.EventQueue
56{
57 public struct QueueItem
58 {
59 public int id;
60 public OSDMap body;
61 }
62
63 public class EventQueueGetModule : IEventQueue, IRegionModule
64 {
65 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
66 private Scene m_scene = null;
67 private IConfigSource m_gConfig;
68 bool enabledYN = false;
69
70 private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
71
72 private Dictionary<UUID, BlockingLLSDQueue> queues = new Dictionary<UUID, BlockingLLSDQueue>();
73 private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>();
74 private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
75
76 #region IRegionModule methods
77 public void Initialise(Scene scene, IConfigSource config)
78 {
79 m_gConfig = config;
80
81 IConfig startupConfig = m_gConfig.Configs["Startup"];
82
83 ReadConfigAndPopulate(scene, startupConfig, "Startup");
84
85 if (enabledYN)
86 {
87 m_scene = scene;
88 scene.RegisterModuleInterface<IEventQueue>(this);
89
90 // Register fallback handler
91 // Why does EQG Fail on region crossings!
92
93 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
94
95 scene.EventManager.OnNewClient += OnNewClient;
96
97 // TODO: Leaving these open, or closing them when we
98 // become a child is incorrect. It messes up TP in a big
99 // way. CAPS/EQ need to be active as long as the UDP
100 // circuit is there.
101
102 scene.EventManager.OnClientClosed += ClientClosed;
103 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
104 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
105 }
106 else
107 {
108 m_gConfig = null;
109 }
110
111 }
112
113 private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p)
114 {
115 enabledYN = startupConfig.GetBoolean("EventQueue", true);
116 }
117
118 public void PostInitialise()
119 {
120 }
121
122 public void Close()
123 {
124 }
125
126 public string Name
127 {
128 get { return "EventQueueGetModule"; }
129 }
130
131 public bool IsSharedModule
132 {
133 get { return false; }
134 }
135 #endregion
136
137 /// <summary>
138 /// Always returns a valid queue
139 /// </summary>
140 /// <param name="agentId"></param>
141 /// <returns></returns>
142 private BlockingLLSDQueue TryGetQueue(UUID agentId)
143 {
144 lock (queues)
145 {
146 if (!queues.ContainsKey(agentId))
147 {
148 m_log.DebugFormat(
149 "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
150 agentId, m_scene.RegionInfo.RegionName);
151
152 queues[agentId] = new BlockingLLSDQueue();
153 }
154
155 return queues[agentId];
156 }
157 }
158
159 /// <summary>
160 /// May return a null queue
161 /// </summary>
162 /// <param name="agentId"></param>
163 /// <returns></returns>
164 private BlockingLLSDQueue GetQueue(UUID agentId)
165 {
166 lock (queues)
167 {
168 if (queues.ContainsKey(agentId))
169 {
170 return queues[agentId];
171 }
172 else
173 return null;
174 }
175 }
176
177 #region IEventQueue Members
178
179 public bool Enqueue(OSD ev, UUID avatarID)
180 {
181 //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
182 try
183 {
184 BlockingLLSDQueue queue = GetQueue(avatarID);
185 if (queue != null)
186 queue.Enqueue(ev);
187 }
188 catch(NullReferenceException e)
189 {
190 m_log.Error("[EVENTQUEUE] Caught exception: " + e);
191 return false;
192 }
193
194 return true;
195 }
196
197 #endregion
198
199 private void OnNewClient(IClientAPI client)
200 {
201 //client.OnLogout += ClientClosed;
202 }
203
204// private void ClientClosed(IClientAPI client)
205// {
206// ClientClosed(client.AgentId);
207// }
208
209 private void ClientClosed(UUID AgentID)
210 {
211 m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", AgentID, m_scene.RegionInfo.RegionName);
212
213 int count = 0;
214 while (queues.ContainsKey(AgentID) && queues[AgentID].Count() > 0 && count++ < 5)
215 {
216 Thread.Sleep(1000);
217 }
218
219 lock (queues)
220 {
221 queues.Remove(AgentID);
222 }
223 List<UUID> removeitems = new List<UUID>();
224 lock (m_AvatarQueueUUIDMapping)
225 {
226 foreach (UUID ky in m_AvatarQueueUUIDMapping.Keys)
227 {
228 if (ky == AgentID)
229 {
230 removeitems.Add(ky);
231 }
232 }
233
234 foreach (UUID ky in removeitems)
235 {
236 m_AvatarQueueUUIDMapping.Remove(ky);
237 m_scene.CommsManager.HttpServer.RemoveHTTPHandler("","/CAPS/EQG/" + ky.ToString() + "/");
238 }
239
240 }
241 UUID searchval = UUID.Zero;
242
243 removeitems.Clear();
244
245 lock (m_QueueUUIDAvatarMapping)
246 {
247 foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys)
248 {
249 searchval = m_QueueUUIDAvatarMapping[ky];
250
251 if (searchval == AgentID)
252 {
253 removeitems.Add(ky);
254 }
255 }
256
257 foreach (UUID ky in removeitems)
258 m_QueueUUIDAvatarMapping.Remove(ky);
259
260 }
261 }
262
263 private void MakeChildAgent(ScenePresence avatar)
264 {
265 //m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
266 //lock (m_ids)
267 // {
268 //if (m_ids.ContainsKey(avatar.UUID))
269 //{
270 // close the event queue.
271 //m_ids[avatar.UUID] = -1;
272 //}
273 //}
274 }
275
276 public void OnRegisterCaps(UUID agentID, Caps caps)
277 {
278 // Register an event queue for the client
279
280 //m_log.DebugFormat(
281 // "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
282 // agentID, caps, m_scene.RegionInfo.RegionName);
283
284 // Let's instantiate a Queue for this agent right now
285 TryGetQueue(agentID);
286
287 string capsBase = "/CAPS/EQG/";
288 UUID EventQueueGetUUID = UUID.Zero;
289
290 lock (m_AvatarQueueUUIDMapping)
291 {
292 // Reuse open queues. The client does!
293 if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
294 {
295 m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
296 EventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
297 }
298 else
299 {
300 EventQueueGetUUID = UUID.Random();
301 //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
302 }
303 }
304
305 lock (m_QueueUUIDAvatarMapping)
306 {
307 if (!m_QueueUUIDAvatarMapping.ContainsKey(EventQueueGetUUID))
308 m_QueueUUIDAvatarMapping.Add(EventQueueGetUUID, agentID);
309 }
310
311 lock (m_AvatarQueueUUIDMapping)
312 {
313 if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID))
314 m_AvatarQueueUUIDMapping.Add(agentID, EventQueueGetUUID);
315 }
316
317 // Register this as a caps handler
318 caps.RegisterHandler("EventQueueGet",
319 new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/",
320 delegate(Hashtable m_dhttpMethod)
321 {
322 return ProcessQueue(m_dhttpMethod, agentID, caps);
323 }));
324
325 // This will persist this beyond the expiry of the caps handlers
326 m_scene.CommsManager.HttpServer.AddHTTPHandler(
327 capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePath2);
328
329 Random rnd = new Random(System.Environment.TickCount);
330 lock (m_ids)
331 {
332 if (!m_ids.ContainsKey(agentID))
333 m_ids.Add(agentID, rnd.Next(30000000));
334 }
335 }
336
337 public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
338 {
339 // TODO: this has to be redone to not busy-wait (and block the thread),
340 // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
341
342// if (m_log.IsDebugEnabled)
343// {
344// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
345// foreach (object key in request.Keys)
346// {
347// debug += key.ToString() + "=" + request[key].ToString() + " ";
348// }
349// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
350// }
351
352 BlockingLLSDQueue queue = TryGetQueue(agentID);
353 OSD element = queue.Dequeue(15000); // 15s timeout
354
355 Hashtable responsedata = new Hashtable();
356
357 int thisID = 0;
358 lock (m_ids)
359 thisID = m_ids[agentID];
360
361 if (element == null)
362 {
363 //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
364 if (thisID == -1) // close-request
365 {
366 m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
367 responsedata["int_response_code"] = 404; //501; //410; //404;
368 responsedata["content_type"] = "text/plain";
369 responsedata["keepalive"] = false;
370 responsedata["str_response_string"] = "Closed EQG";
371 return responsedata;
372 }
373 responsedata["int_response_code"] = 502;
374 responsedata["content_type"] = "text/plain";
375 responsedata["keepalive"] = false;
376 responsedata["str_response_string"] = "Upstream error: ";
377 responsedata["error_status_text"] = "Upstream error:";
378 responsedata["http_protocol_version"] = "HTTP/1.0";
379 return responsedata;
380 }
381
382 OSDArray array = new OSDArray();
383 if (element == null) // didn't have an event in 15s
384 {
385 // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
386 array.Add(EventQueueHelper.KeepAliveEvent());
387 m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
388 }
389 else
390 {
391 array.Add(element);
392 while (queue.Count() > 0)
393 {
394 array.Add(queue.Dequeue(1));
395 thisID++;
396 }
397 }
398
399 OSDMap events = new OSDMap();
400 events.Add("events", array);
401
402 events.Add("id", new OSDInteger(thisID));
403 lock (m_ids)
404 {
405 m_ids[agentID] = thisID + 1;
406 }
407
408 responsedata["int_response_code"] = 200;
409 responsedata["content_type"] = "application/xml";
410 responsedata["keepalive"] = false;
411 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
412 //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
413
414 return responsedata;
415 }
416
417 public Hashtable EventQueuePath2(Hashtable request)
418 {
419 string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
420 // pull off the last "/" in the path.
421 Hashtable responsedata = new Hashtable();
422 capuuid = capuuid.Substring(0, capuuid.Length - 1);
423 capuuid = capuuid.Replace("/CAPS/EQG/", "");
424 UUID AvatarID = UUID.Zero;
425 UUID capUUID = UUID.Zero;
426
427 // parse the path and search for the avatar with it registered
428 if (UUID.TryParse(capuuid, out capUUID))
429 {
430 lock (m_QueueUUIDAvatarMapping)
431 {
432 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
433 {
434 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
435 }
436 }
437 if (AvatarID != UUID.Zero)
438 {
439 return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsHandlerForUser(AvatarID));
440 }
441 else
442 {
443 responsedata["int_response_code"] = 404;
444 responsedata["content_type"] = "text/plain";
445 responsedata["keepalive"] = false;
446 responsedata["str_response_string"] = "Not Found";
447 responsedata["error_status_text"] = "Not Found";
448 responsedata["http_protocol_version"] = "HTTP/1.0";
449 return responsedata;
450 // return 404
451 }
452 }
453 else
454 {
455 responsedata["int_response_code"] = 404;
456 responsedata["content_type"] = "text/plain";
457 responsedata["keepalive"] = false;
458 responsedata["str_response_string"] = "Not Found";
459 responsedata["error_status_text"] = "Not Found";
460 responsedata["http_protocol_version"] = "HTTP/1.0";
461 return responsedata;
462 // return 404
463 }
464
465 }
466
467 public OSD EventQueueFallBack(string path, OSD request, string endpoint)
468 {
469 // This is a fallback element to keep the client from loosing EventQueueGet
470 // Why does CAPS fail sometimes!?
471 m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!");
472 string capuuid = path.Replace("/CAPS/EQG/","");
473 capuuid = capuuid.Substring(0, capuuid.Length - 1);
474
475// UUID AvatarID = UUID.Zero;
476 UUID capUUID = UUID.Zero;
477 if (UUID.TryParse(capuuid, out capUUID))
478 {
479/* Don't remove this yet code cleaners!
480 * Still testing this!
481 *
482 lock (m_QueueUUIDAvatarMapping)
483 {
484 if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
485 {
486 AvatarID = m_QueueUUIDAvatarMapping[capUUID];
487 }
488 }
489
490
491 if (AvatarID != UUID.Zero)
492 {
493 // Repair the CAP!
494 //OpenSim.Framework.Communications.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
495 //string capsBase = "/CAPS/EQG/";
496 //caps.RegisterHandler("EventQueueGet",
497 //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
498 //delegate(Hashtable m_dhttpMethod)
499 //{
500 // return ProcessQueue(m_dhttpMethod, AvatarID, caps);
501 //}));
502 // start new ID sequence.
503 Random rnd = new Random(System.Environment.TickCount);
504 lock (m_ids)
505 {
506 if (!m_ids.ContainsKey(AvatarID))
507 m_ids.Add(AvatarID, rnd.Next(30000000));
508 }
509
510
511 int thisID = 0;
512 lock (m_ids)
513 thisID = m_ids[AvatarID];
514
515 BlockingLLSDQueue queue = GetQueue(AvatarID);
516 OSDArray array = new OSDArray();
517 LLSD element = queue.Dequeue(15000); // 15s timeout
518 if (element == null)
519 {
520
521 array.Add(EventQueueHelper.KeepAliveEvent());
522 }
523 else
524 {
525 array.Add(element);
526 while (queue.Count() > 0)
527 {
528 array.Add(queue.Dequeue(1));
529 thisID++;
530 }
531 }
532 OSDMap events = new OSDMap();
533 events.Add("events", array);
534
535 events.Add("id", new LLSDInteger(thisID));
536
537 lock (m_ids)
538 {
539 m_ids[AvatarID] = thisID + 1;
540 }
541
542 return events;
543 }
544 else
545 {
546 return new LLSD();
547 }
548*
549*/
550 }
551 else
552 {
553 //return new LLSD();
554 }
555
556 return new OSDString("shutdown404!");
557 }
558
559 public void DisableSimulator(ulong handle, UUID avatarID)
560 {
561 OSD item = EventQueueHelper.DisableSimulator(handle);
562 Enqueue(item, avatarID);
563 }
564
565 public void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID)
566 {
567 OSD item = EventQueueHelper.EnableSimulator(handle, endPoint);
568 Enqueue(item, avatarID);
569 }
570
571 public void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath)
572 {
573 OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath);
574 Enqueue(item, avatarID);
575 }
576
577 public void TeleportFinishEvent(ulong regionHandle, byte simAccess,
578 IPEndPoint regionExternalEndPoint,
579 uint locationID, uint flags, string capsURL,
580 UUID avatarID)
581 {
582 OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
583 locationID, flags, capsURL, avatarID);
584 Enqueue(item, avatarID);
585 }
586
587 public void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
588 IPEndPoint newRegionExternalEndPoint,
589 string capsURL, UUID avatarID, UUID sessionID)
590 {
591 OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
592 capsURL, avatarID, sessionID);
593 Enqueue(item, avatarID);
594 }
595
596 public void ChatterboxInvitation(UUID sessionID, string sessionName,
597 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
598 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
599 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
600 {
601 OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
602 timeStamp, offline, parentEstateID, position, ttl, transactionID,
603 fromGroup, binaryBucket);
604 Enqueue(item, toAgent);
605 m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
606
607 }
608
609 public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat,
610 bool isModerator, bool textMute)
611 {
612 OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
613 isModerator, textMute);
614 Enqueue(item, toAgent);
615 m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
616 }
617
618 public void ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket, UUID avatarID)
619 {
620 OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesPacket);
621 Enqueue(item, avatarID);
622 }
623
624 public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
625 {
626 OSD item = EventQueueHelper.GroupMembership(groupUpdate);
627 Enqueue(item, avatarID);
628 }
629 }
630}
diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs
new file mode 100644
index 0000000..80f6fce
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueHelper.cs
@@ -0,0 +1,459 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Net;
30using OpenMetaverse;
31using OpenMetaverse.Packets;
32using OpenMetaverse.StructuredData;
33
34namespace OpenSim.Region.CoreModules.Framework.EventQueue
35{
36 public class EventQueueHelper
37 {
38 private EventQueueHelper() {} // no construction possible, it's an utility class
39
40 private static byte[] ulongToByteArray(ulong uLongValue)
41 {
42 // Reverse endianness of RegionHandle
43 return new byte[]
44 {
45 (byte)((uLongValue >> 56) % 256),
46 (byte)((uLongValue >> 48) % 256),
47 (byte)((uLongValue >> 40) % 256),
48 (byte)((uLongValue >> 32) % 256),
49 (byte)((uLongValue >> 24) % 256),
50 (byte)((uLongValue >> 16) % 256),
51 (byte)((uLongValue >> 8) % 256),
52 (byte)(uLongValue % 256)
53 };
54 }
55
56 private static byte[] uintToByteArray(uint uIntValue)
57 {
58 byte[] resultbytes = Utils.UIntToBytes(uIntValue);
59 if (BitConverter.IsLittleEndian)
60 Array.Reverse(resultbytes);
61
62 return resultbytes;
63 }
64
65 public static OSD buildEvent(string eventName, OSD eventBody)
66 {
67 OSDMap llsdEvent = new OSDMap(2);
68 llsdEvent.Add("message", new OSDString(eventName));
69 llsdEvent.Add("body", eventBody);
70
71 return llsdEvent;
72 }
73
74 public static OSD EnableSimulator(ulong handle, IPEndPoint endPoint)
75 {
76 OSDMap llsdSimInfo = new OSDMap(3);
77
78 llsdSimInfo.Add("Handle", new OSDBinary(ulongToByteArray(handle)));
79 llsdSimInfo.Add("IP", new OSDBinary(endPoint.Address.GetAddressBytes()));
80 llsdSimInfo.Add("Port", new OSDInteger(endPoint.Port));
81
82 OSDArray arr = new OSDArray(1);
83 arr.Add(llsdSimInfo);
84
85 OSDMap llsdBody = new OSDMap(1);
86 llsdBody.Add("SimulatorInfo", arr);
87
88 return buildEvent("EnableSimulator", llsdBody);
89 }
90
91 public static OSD DisableSimulator(ulong handle)
92 {
93 //OSDMap llsdSimInfo = new OSDMap(1);
94
95 //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle)));
96
97 //OSDArray arr = new OSDArray(1);
98 //arr.Add(llsdSimInfo);
99
100 OSDMap llsdBody = new OSDMap(0);
101 //llsdBody.Add("SimulatorInfo", arr);
102
103 return buildEvent("DisableSimulator", llsdBody);
104 }
105
106 public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
107 IPEndPoint newRegionExternalEndPoint,
108 string capsURL, UUID agentID, UUID sessionID)
109 {
110 OSDArray lookAtArr = new OSDArray(3);
111 lookAtArr.Add(OSD.FromReal(lookAt.X));
112 lookAtArr.Add(OSD.FromReal(lookAt.Y));
113 lookAtArr.Add(OSD.FromReal(lookAt.Z));
114
115 OSDArray positionArr = new OSDArray(3);
116 positionArr.Add(OSD.FromReal(pos.X));
117 positionArr.Add(OSD.FromReal(pos.Y));
118 positionArr.Add(OSD.FromReal(pos.Z));
119
120 OSDMap infoMap = new OSDMap(2);
121 infoMap.Add("LookAt", lookAtArr);
122 infoMap.Add("Position", positionArr);
123
124 OSDArray infoArr = new OSDArray(1);
125 infoArr.Add(infoMap);
126
127 OSDMap agentDataMap = new OSDMap(2);
128 agentDataMap.Add("AgentID", OSD.FromUUID(agentID));
129 agentDataMap.Add("SessionID", OSD.FromUUID(sessionID));
130
131 OSDArray agentDataArr = new OSDArray(1);
132 agentDataArr.Add(agentDataMap);
133
134 OSDMap regionDataMap = new OSDMap(4);
135 regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle)));
136 regionDataMap.Add("SeedCapability", OSD.FromString(capsURL));
137 regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes()));
138 regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port));
139
140 OSDArray regionDataArr = new OSDArray(1);
141 regionDataArr.Add(regionDataMap);
142
143 OSDMap llsdBody = new OSDMap(3);
144 llsdBody.Add("Info", infoArr);
145 llsdBody.Add("AgentData", agentDataArr);
146 llsdBody.Add("RegionData", regionDataArr);
147
148 return buildEvent("CrossedRegion", llsdBody);
149 }
150
151 public static OSD TeleportFinishEvent(
152 ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
153 uint locationID, uint flags, string capsURL, UUID agentID)
154 {
155 OSDMap info = new OSDMap();
156 info.Add("AgentID", OSD.FromUUID(agentID));
157 info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this?
158 info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle)));
159 info.Add("SeedCapability", OSD.FromString(capsURL));
160 info.Add("SimAccess", OSD.FromInteger(simAccess));
161 info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes()));
162 info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port));
163 info.Add("TeleportFlags", OSD.FromBinary(1L << 4)); // AgentManager.TeleportFlags.ViaLocation
164
165 OSDArray infoArr = new OSDArray();
166 infoArr.Add(info);
167
168 OSDMap body = new OSDMap();
169 body.Add("Info", infoArr);
170
171 return buildEvent("TeleportFinish", body);
172 }
173
174 public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono)
175 {
176 OSDMap script = new OSDMap();
177 script.Add("ObjectID", OSD.FromUUID(objectID));
178 script.Add("ItemID", OSD.FromUUID(itemID));
179 script.Add("Running", OSD.FromBoolean(running));
180 script.Add("Mono", OSD.FromBoolean(mono));
181
182 OSDArray scriptArr = new OSDArray();
183 scriptArr.Add(script);
184
185 OSDMap body = new OSDMap();
186 body.Add("Script", scriptArr);
187
188 return buildEvent("ScriptRunningReply", body);
189 }
190
191 public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap)
192 {
193 OSDMap body = new OSDMap(3);
194 body.Add("agent-id", new OSDUUID(agentID));
195 body.Add("sim-ip-and-port", new OSDString(simIpAndPort));
196 body.Add("seed-capability", new OSDString(seedcap));
197
198 return buildEvent("EstablishAgentCommunication", body);
199 }
200
201 public static OSD KeepAliveEvent()
202 {
203 return buildEvent("FAKEEVENT", new OSDMap());
204 }
205
206 public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate)
207 {
208 OSDMap body = new OSDMap(4);
209
210 body.Add("agent_id", new OSDUUID(agentID));
211 body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0));
212 body.Add("god_level", new OSDInteger(godLevel));
213 body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0));
214
215 return body;
216 }
217
218 public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent,
219 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
220 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
221 {
222 OSDMap messageParams = new OSDMap(15);
223 messageParams.Add("type", new OSDInteger((int)dialog));
224
225 OSDArray positionArray = new OSDArray(3);
226 positionArray.Add(OSD.FromReal(position.X));
227 positionArray.Add(OSD.FromReal(position.Y));
228 positionArray.Add(OSD.FromReal(position.Z));
229 messageParams.Add("position", positionArray);
230
231 messageParams.Add("region_id", new OSDUUID(UUID.Zero));
232 messageParams.Add("to_id", new OSDUUID(toAgent));
233 messageParams.Add("source", new OSDInteger(0));
234
235 OSDMap data = new OSDMap(1);
236 data.Add("binary_bucket", OSD.FromBinary(binaryBucket));
237 messageParams.Add("data", data);
238 messageParams.Add("message", new OSDString(message));
239 messageParams.Add("id", new OSDUUID(transactionID));
240 messageParams.Add("from_name", new OSDString(fromName));
241 messageParams.Add("timestamp", new OSDInteger((int)timeStamp));
242 messageParams.Add("offline", new OSDInteger(offline ? 1 : 0));
243 messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID));
244 messageParams.Add("ttl", new OSDInteger((int)ttl));
245 messageParams.Add("from_id", new OSDUUID(fromAgent));
246 messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0));
247
248 return messageParams;
249 }
250
251 public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent,
252 string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID,
253 Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket,
254 bool checkEstate, int godLevel, bool limitedToEstate)
255 {
256 OSDMap im = new OSDMap(2);
257 im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent,
258 fromName, dialog, timeStamp, offline, parentEstateID,
259 position, ttl, transactionID, fromGroup, binaryBucket));
260
261 im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate));
262
263 return im;
264 }
265
266
267 public static OSD ChatterboxInvitation(UUID sessionID, string sessionName,
268 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
269 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
270 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
271 {
272 OSDMap body = new OSDMap(5);
273 body.Add("session_id", new OSDUUID(sessionID));
274 body.Add("from_name", new OSDString(fromName));
275 body.Add("session_name", new OSDString(sessionName));
276 body.Add("from_id", new OSDUUID(fromAgent));
277
278 body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent,
279 fromName, dialog, timeStamp, offline, parentEstateID, position,
280 ttl, transactionID, fromGroup, binaryBucket, true, 0, true));
281
282 OSDMap chatterboxInvitation = new OSDMap(2);
283 chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation"));
284 chatterboxInvitation.Add("body", body);
285 return chatterboxInvitation;
286 }
287
288 public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID,
289 UUID agentID, bool canVoiceChat, bool isModerator, bool textMute)
290 {
291 OSDMap body = new OSDMap();
292 OSDMap agentUpdates = new OSDMap();
293 OSDMap infoDetail = new OSDMap();
294 OSDMap mutes = new OSDMap();
295
296 mutes.Add("text", OSD.FromBoolean(textMute));
297 infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat));
298 infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator));
299 infoDetail.Add("mutes", mutes);
300 OSDMap info = new OSDMap();
301 info.Add("info", infoDetail);
302 agentUpdates.Add(agentID.ToString(), info);
303 body.Add("agent_updates", agentUpdates);
304 body.Add("session_id", OSD.FromUUID(sessionID));
305 body.Add("updates", new OSD());
306
307 OSDMap chatterBoxSessionAgentListUpdates = new OSDMap();
308 chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates"));
309 chatterBoxSessionAgentListUpdates.Add("body", body);
310
311 return chatterBoxSessionAgentListUpdates;
312 }
313
314 public static OSD ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket)
315 {
316 OSDMap parcelProperties = new OSDMap();
317 OSDMap body = new OSDMap();
318
319 OSDArray ageVerificationBlock = new OSDArray();
320 OSDMap ageVerificationMap = new OSDMap();
321 ageVerificationMap.Add("RegionDenyAgeUnverified",
322 OSD.FromBoolean(parcelPropertiesPacket.AgeVerificationBlock.RegionDenyAgeUnverified));
323 ageVerificationBlock.Add(ageVerificationMap);
324 body.Add("AgeVerificationBlock", ageVerificationBlock);
325
326 // LL sims send media info in this event queue message but it's not in the UDP
327 // packet we construct this event queue message from. This should be refactored in
328 // other areas of the code so it can all be send in the same message. Until then we will
329 // still send the media info via UDP
330
331 //OSDArray mediaData = new OSDArray();
332 //OSDMap mediaDataMap = new OSDMap();
333 //mediaDataMap.Add("MediaDesc", OSD.FromString(""));
334 //mediaDataMap.Add("MediaHeight", OSD.FromInteger(0));
335 //mediaDataMap.Add("MediaLoop", OSD.FromInteger(0));
336 //mediaDataMap.Add("MediaType", OSD.FromString("type/type"));
337 //mediaDataMap.Add("MediaWidth", OSD.FromInteger(0));
338 //mediaDataMap.Add("ObscureMedia", OSD.FromInteger(0));
339 //mediaDataMap.Add("ObscureMusic", OSD.FromInteger(0));
340 //mediaData.Add(mediaDataMap);
341 //body.Add("MediaData", mediaData);
342
343 OSDArray parcelData = new OSDArray();
344 OSDMap parcelDataMap = new OSDMap();
345 OSDArray AABBMax = new OSDArray(3);
346 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.X));
347 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Y));
348 AABBMax.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMax.Z));
349 parcelDataMap.Add("AABBMax", AABBMax);
350
351 OSDArray AABBMin = new OSDArray(3);
352 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.X));
353 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Y));
354 AABBMin.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.AABBMin.Z));
355 parcelDataMap.Add("AABBMin", AABBMin);
356
357 parcelDataMap.Add("Area", OSD.FromInteger(parcelPropertiesPacket.ParcelData.Area));
358 parcelDataMap.Add("AuctionID", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.AuctionID)));
359 parcelDataMap.Add("AuthBuyerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.AuthBuyerID));
360 parcelDataMap.Add("Bitmap", OSD.FromBinary(parcelPropertiesPacket.ParcelData.Bitmap));
361 parcelDataMap.Add("Category", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Category));
362 parcelDataMap.Add("ClaimDate", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimDate));
363 parcelDataMap.Add("ClaimPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.ClaimPrice));
364 parcelDataMap.Add("Desc", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Desc)));
365 parcelDataMap.Add("GroupID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.GroupID));
366 parcelDataMap.Add("GroupPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.GroupPrims));
367 parcelDataMap.Add("IsGroupOwned", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.IsGroupOwned));
368 parcelDataMap.Add("LandingType", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LandingType));
369 parcelDataMap.Add("LocalID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.LocalID));
370 parcelDataMap.Add("MaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.MaxPrims));
371 parcelDataMap.Add("MediaAutoScale", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.MediaAutoScale));
372 parcelDataMap.Add("MediaID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.MediaID));
373 parcelDataMap.Add("MediaURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MediaURL)));
374 parcelDataMap.Add("MusicURL", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.MusicURL)));
375 parcelDataMap.Add("Name", OSD.FromString(Utils.BytesToString(parcelPropertiesPacket.ParcelData.Name)));
376 parcelDataMap.Add("OtherCleanTime", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCleanTime));
377 parcelDataMap.Add("OtherCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherCount));
378 parcelDataMap.Add("OtherPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OtherPrims));
379 parcelDataMap.Add("OwnerID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.OwnerID));
380 parcelDataMap.Add("OwnerPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.OwnerPrims));
381 parcelDataMap.Add("ParcelFlags", OSD.FromBinary(uintToByteArray(parcelPropertiesPacket.ParcelData.ParcelFlags)));
382 parcelDataMap.Add("ParcelPrimBonus", OSD.FromReal(parcelPropertiesPacket.ParcelData.ParcelPrimBonus));
383 parcelDataMap.Add("PassHours", OSD.FromReal(parcelPropertiesPacket.ParcelData.PassHours));
384 parcelDataMap.Add("PassPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PassPrice));
385 parcelDataMap.Add("PublicCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.PublicCount));
386 parcelDataMap.Add("RegionDenyAnonymous", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyAnonymous));
387 parcelDataMap.Add("RegionDenyIdentified", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyIdentified));
388 parcelDataMap.Add("RegionDenyTransacted", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionDenyTransacted));
389
390 parcelDataMap.Add("RegionPushOverride", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.RegionPushOverride));
391 parcelDataMap.Add("RentPrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RentPrice));
392 parcelDataMap.Add("RequestResult", OSD.FromInteger(parcelPropertiesPacket.ParcelData.RequestResult));
393 parcelDataMap.Add("SalePrice", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SalePrice));
394 parcelDataMap.Add("SelectedPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelectedPrims));
395 parcelDataMap.Add("SelfCount", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SelfCount));
396 parcelDataMap.Add("SequenceID", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SequenceID));
397 parcelDataMap.Add("SimWideMaxPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideMaxPrims));
398 parcelDataMap.Add("SimWideTotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.SimWideTotalPrims));
399 parcelDataMap.Add("SnapSelection", OSD.FromBoolean(parcelPropertiesPacket.ParcelData.SnapSelection));
400 parcelDataMap.Add("SnapshotID", OSD.FromUUID(parcelPropertiesPacket.ParcelData.SnapshotID));
401 parcelDataMap.Add("Status", OSD.FromInteger((int)parcelPropertiesPacket.ParcelData.Status));
402 parcelDataMap.Add("TotalPrims", OSD.FromInteger(parcelPropertiesPacket.ParcelData.TotalPrims));
403
404 OSDArray UserLocation = new OSDArray(3);
405 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.X));
406 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Y));
407 UserLocation.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLocation.Z));
408 parcelDataMap.Add("UserLocation", UserLocation);
409
410 OSDArray UserLookAt = new OSDArray(3);
411 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.X));
412 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Y));
413 UserLookAt.Add(OSD.FromReal(parcelPropertiesPacket.ParcelData.UserLookAt.Z));
414 parcelDataMap.Add("UserLookAt", UserLookAt);
415
416 parcelData.Add(parcelDataMap);
417 body.Add("ParcelData", parcelData);
418 parcelProperties.Add("body", body);
419 parcelProperties.Add("message", OSD.FromString("ParcelProperties"));
420
421 return parcelProperties;
422 }
423
424 public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket)
425 {
426 OSDMap groupUpdate = new OSDMap();
427 groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate"));
428
429 OSDMap body = new OSDMap();
430 OSDArray agentData = new OSDArray();
431 OSDMap agentDataMap = new OSDMap();
432 agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID));
433 agentData.Add(agentDataMap);
434 body.Add("AgentData", agentData);
435
436 OSDArray groupData = new OSDArray();
437
438 foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData)
439 {
440 OSDMap groupDataMap = new OSDMap();
441 groupDataMap.Add("ListInProfile", OSD.FromBoolean(false));
442 groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID));
443 groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID));
444 groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution));
445 groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers)));
446 groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName)));
447 groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices));
448
449 groupData.Add(groupDataMap);
450
451 }
452 body.Add("GroupData", groupData);
453 groupUpdate.Add("body", body);
454
455 return groupUpdate;
456 }
457
458 }
459}