diff options
author | UbitUmarov | 2015-09-01 11:43:07 +0100 |
---|---|---|
committer | UbitUmarov | 2015-09-01 11:43:07 +0100 |
commit | fb78b182520fc9bb0f971afd0322029c70278ea6 (patch) | |
tree | b4e30d383938fdeef8c92d1d1c2f44bb61d329bd /OpenSim/Region/ClientStack/Linden/Caps/EventQueue | |
parent | lixo (diff) | |
parent | Mantis #7713: fixed bug introduced by 1st MOSES patch. (diff) | |
download | opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.zip opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.gz opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.bz2 opensim-SC-fb78b182520fc9bb0f971afd0322029c70278ea6.tar.xz |
Merge remote-tracking branch 'os/master'
Diffstat (limited to '')
3 files changed, 1453 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..9b9f6a7 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -0,0 +1,830 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Net; | ||
32 | using System.Reflection; | ||
33 | using System.Threading; | ||
34 | using log4net; | ||
35 | using Nini.Config; | ||
36 | using Mono.Addins; | ||
37 | using OpenMetaverse; | ||
38 | using OpenMetaverse.Messages.Linden; | ||
39 | using OpenMetaverse.Packets; | ||
40 | using OpenMetaverse.StructuredData; | ||
41 | using OpenSim.Framework; | ||
42 | using OpenSim.Framework.Console; | ||
43 | using OpenSim.Framework.Servers; | ||
44 | using OpenSim.Framework.Servers.HttpServer; | ||
45 | using OpenSim.Region.Framework.Interfaces; | ||
46 | using OpenSim.Region.Framework.Scenes; | ||
47 | using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>; | ||
48 | using Caps=OpenSim.Framework.Capabilities.Caps; | ||
49 | |||
50 | namespace OpenSim.Region.ClientStack.Linden | ||
51 | { | ||
52 | public struct QueueItem | ||
53 | { | ||
54 | public int id; | ||
55 | public OSDMap body; | ||
56 | } | ||
57 | |||
58 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")] | ||
59 | public class EventQueueGetModule : IEventQueue, INonSharedRegionModule | ||
60 | { | ||
61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
62 | private static string LogHeader = "[EVENT QUEUE GET MODULE]"; | ||
63 | |||
64 | /// <value> | ||
65 | /// Debug level. | ||
66 | /// </value> | ||
67 | public int DebugLevel { get; set; } | ||
68 | |||
69 | // Viewer post requests timeout in 60 secs | ||
70 | // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44 | ||
71 | // | ||
72 | private const int VIEWER_TIMEOUT = 60 * 1000; | ||
73 | // Just to be safe, we work on a 10 sec shorter cycle | ||
74 | private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000); | ||
75 | |||
76 | protected Scene m_scene; | ||
77 | |||
78 | private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); | ||
79 | |||
80 | private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>(); | ||
81 | private Dictionary<UUID, UUID> m_QueueUUIDAvatarMapping = new Dictionary<UUID, UUID>(); | ||
82 | private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>(); | ||
83 | |||
84 | #region INonSharedRegionModule methods | ||
85 | public virtual void Initialise(IConfigSource config) | ||
86 | { | ||
87 | } | ||
88 | |||
89 | public void AddRegion(Scene scene) | ||
90 | { | ||
91 | m_scene = scene; | ||
92 | scene.RegisterModuleInterface<IEventQueue>(this); | ||
93 | |||
94 | scene.EventManager.OnClientClosed += ClientClosed; | ||
95 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | ||
96 | |||
97 | MainConsole.Instance.Commands.AddCommand( | ||
98 | "Debug", | ||
99 | false, | ||
100 | "debug eq", | ||
101 | "debug eq [0|1|2]", | ||
102 | "Turn on event queue debugging\n" | ||
103 | + " <= 0 - turns off all event queue logging\n" | ||
104 | + " >= 1 - turns on event queue setup and outgoing event logging\n" | ||
105 | + " >= 2 - turns on poll notification", | ||
106 | HandleDebugEq); | ||
107 | |||
108 | MainConsole.Instance.Commands.AddCommand( | ||
109 | "Debug", | ||
110 | false, | ||
111 | "show eq", | ||
112 | "show eq", | ||
113 | "Show contents of event queues for logged in avatars. Used for debugging.", | ||
114 | HandleShowEq); | ||
115 | } | ||
116 | |||
117 | public void RemoveRegion(Scene scene) | ||
118 | { | ||
119 | if (m_scene != scene) | ||
120 | return; | ||
121 | |||
122 | scene.EventManager.OnClientClosed -= ClientClosed; | ||
123 | scene.EventManager.OnRegisterCaps -= OnRegisterCaps; | ||
124 | |||
125 | scene.UnregisterModuleInterface<IEventQueue>(this); | ||
126 | m_scene = null; | ||
127 | } | ||
128 | |||
129 | public void RegionLoaded(Scene scene) | ||
130 | { | ||
131 | } | ||
132 | |||
133 | public virtual void Close() | ||
134 | { | ||
135 | } | ||
136 | |||
137 | public virtual string Name | ||
138 | { | ||
139 | get { return "EventQueueGetModule"; } | ||
140 | } | ||
141 | |||
142 | public Type ReplaceableInterface | ||
143 | { | ||
144 | get { return null; } | ||
145 | } | ||
146 | |||
147 | #endregion | ||
148 | |||
149 | protected void HandleDebugEq(string module, string[] args) | ||
150 | { | ||
151 | int debugLevel; | ||
152 | |||
153 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | ||
154 | { | ||
155 | MainConsole.Instance.OutputFormat("Usage: debug eq [0|1|2]"); | ||
156 | } | ||
157 | else | ||
158 | { | ||
159 | DebugLevel = debugLevel; | ||
160 | MainConsole.Instance.OutputFormat( | ||
161 | "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | protected void HandleShowEq(string module, string[] args) | ||
166 | { | ||
167 | MainConsole.Instance.OutputFormat("For scene {0}", m_scene.Name); | ||
168 | |||
169 | lock (queues) | ||
170 | { | ||
171 | foreach (KeyValuePair<UUID, Queue<OSD>> kvp in queues) | ||
172 | { | ||
173 | MainConsole.Instance.OutputFormat( | ||
174 | "For agent {0} there are {1} messages queued for send.", | ||
175 | kvp.Key, kvp.Value.Count); | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /// <summary> | ||
181 | /// Always returns a valid queue | ||
182 | /// </summary> | ||
183 | /// <param name="agentId"></param> | ||
184 | /// <returns></returns> | ||
185 | private Queue<OSD> TryGetQueue(UUID agentId) | ||
186 | { | ||
187 | lock (queues) | ||
188 | { | ||
189 | if (!queues.ContainsKey(agentId)) | ||
190 | { | ||
191 | if (DebugLevel > 0) | ||
192 | m_log.DebugFormat( | ||
193 | "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}", | ||
194 | agentId, m_scene.RegionInfo.RegionName); | ||
195 | |||
196 | queues[agentId] = new Queue<OSD>(); | ||
197 | } | ||
198 | |||
199 | return queues[agentId]; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /// <summary> | ||
204 | /// May return a null queue | ||
205 | /// </summary> | ||
206 | /// <param name="agentId"></param> | ||
207 | /// <returns></returns> | ||
208 | private Queue<OSD> GetQueue(UUID agentId) | ||
209 | { | ||
210 | lock (queues) | ||
211 | { | ||
212 | if (queues.ContainsKey(agentId)) | ||
213 | { | ||
214 | return queues[agentId]; | ||
215 | } | ||
216 | else | ||
217 | return null; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | #region IEventQueue Members | ||
222 | |||
223 | public bool Enqueue(OSD ev, UUID avatarID) | ||
224 | { | ||
225 | //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName); | ||
226 | try | ||
227 | { | ||
228 | Queue<OSD> queue = GetQueue(avatarID); | ||
229 | if (queue != null) | ||
230 | { | ||
231 | lock (queue) | ||
232 | queue.Enqueue(ev); | ||
233 | } | ||
234 | else if (DebugLevel > 0) | ||
235 | { | ||
236 | ScenePresence sp = m_scene.GetScenePresence(avatarID); | ||
237 | |||
238 | // This assumes that an NPC should never have a queue. | ||
239 | if (sp != null && sp.PresenceType != PresenceType.Npc) | ||
240 | { | ||
241 | OSDMap evMap = (OSDMap)ev; | ||
242 | m_log.WarnFormat( | ||
243 | "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} {1} when placing message {2} in region {3}", | ||
244 | sp.Name, sp.UUID, evMap["message"], m_scene.Name); | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | catch (NullReferenceException e) | ||
249 | { | ||
250 | m_log.Error("[EVENTQUEUE] Caught exception: " + e); | ||
251 | return false; | ||
252 | } | ||
253 | |||
254 | return true; | ||
255 | } | ||
256 | |||
257 | #endregion | ||
258 | |||
259 | private void ClientClosed(UUID agentID, Scene scene) | ||
260 | { | ||
261 | //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | ||
262 | |||
263 | lock (queues) | ||
264 | queues.Remove(agentID); | ||
265 | |||
266 | List<UUID> removeitems = new List<UUID>(); | ||
267 | lock (m_AvatarQueueUUIDMapping) | ||
268 | m_AvatarQueueUUIDMapping.Remove(agentID); | ||
269 | |||
270 | UUID searchval = UUID.Zero; | ||
271 | |||
272 | removeitems.Clear(); | ||
273 | |||
274 | lock (m_QueueUUIDAvatarMapping) | ||
275 | { | ||
276 | foreach (UUID ky in m_QueueUUIDAvatarMapping.Keys) | ||
277 | { | ||
278 | searchval = m_QueueUUIDAvatarMapping[ky]; | ||
279 | |||
280 | if (searchval == agentID) | ||
281 | { | ||
282 | removeitems.Add(ky); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | foreach (UUID ky in removeitems) | ||
287 | m_QueueUUIDAvatarMapping.Remove(ky); | ||
288 | } | ||
289 | |||
290 | // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | ||
291 | |||
292 | } | ||
293 | |||
294 | /// <summary> | ||
295 | /// Generate an Event Queue Get handler path for the given eqg uuid. | ||
296 | /// </summary> | ||
297 | /// <param name='eqgUuid'></param> | ||
298 | private string GenerateEqgCapPath(UUID eqgUuid) | ||
299 | { | ||
300 | return string.Format("/CAPS/EQG/{0}/", eqgUuid); | ||
301 | } | ||
302 | |||
303 | public void OnRegisterCaps(UUID agentID, Caps caps) | ||
304 | { | ||
305 | // Register an event queue for the client | ||
306 | |||
307 | if (DebugLevel > 0) | ||
308 | m_log.DebugFormat( | ||
309 | "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}", | ||
310 | agentID, caps, m_scene.RegionInfo.RegionName); | ||
311 | |||
312 | // Let's instantiate a Queue for this agent right now | ||
313 | TryGetQueue(agentID); | ||
314 | |||
315 | UUID eventQueueGetUUID; | ||
316 | |||
317 | lock (m_AvatarQueueUUIDMapping) | ||
318 | { | ||
319 | // Reuse open queues. The client does! | ||
320 | if (m_AvatarQueueUUIDMapping.ContainsKey(agentID)) | ||
321 | { | ||
322 | //m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!"); | ||
323 | eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID]; | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | eventQueueGetUUID = UUID.Random(); | ||
328 | //m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!"); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | lock (m_QueueUUIDAvatarMapping) | ||
333 | { | ||
334 | if (!m_QueueUUIDAvatarMapping.ContainsKey(eventQueueGetUUID)) | ||
335 | m_QueueUUIDAvatarMapping.Add(eventQueueGetUUID, agentID); | ||
336 | } | ||
337 | |||
338 | lock (m_AvatarQueueUUIDMapping) | ||
339 | { | ||
340 | if (!m_AvatarQueueUUIDMapping.ContainsKey(agentID)) | ||
341 | m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID); | ||
342 | } | ||
343 | |||
344 | caps.RegisterPollHandler( | ||
345 | "EventQueueGet", | ||
346 | new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS)); | ||
347 | |||
348 | Random rnd = new Random(Environment.TickCount); | ||
349 | lock (m_ids) | ||
350 | { | ||
351 | if (!m_ids.ContainsKey(agentID)) | ||
352 | m_ids.Add(agentID, rnd.Next(30000000)); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | public bool HasEvents(UUID requestID, UUID agentID) | ||
357 | { | ||
358 | // Don't use this, because of race conditions at agent closing time | ||
359 | //Queue<OSD> queue = TryGetQueue(agentID); | ||
360 | |||
361 | Queue<OSD> queue = GetQueue(agentID); | ||
362 | if (queue != null) | ||
363 | lock (queue) | ||
364 | { | ||
365 | //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count); | ||
366 | return queue.Count > 0; | ||
367 | } | ||
368 | |||
369 | return false; | ||
370 | } | ||
371 | |||
372 | /// <summary> | ||
373 | /// Logs a debug line for an outbound event queue message if appropriate. | ||
374 | /// </summary> | ||
375 | /// <param name='element'>Element containing message</param> | ||
376 | private void LogOutboundDebugMessage(OSD element, UUID agentId) | ||
377 | { | ||
378 | if (element is OSDMap) | ||
379 | { | ||
380 | OSDMap ev = (OSDMap)element; | ||
381 | m_log.DebugFormat( | ||
382 | "Eq OUT {0,-30} to {1,-20} {2,-20}", | ||
383 | ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | public Hashtable GetEvents(UUID requestID, UUID pAgentId) | ||
388 | { | ||
389 | if (DebugLevel >= 2) | ||
390 | m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name); | ||
391 | |||
392 | Queue<OSD> queue = GetQueue(pAgentId); | ||
393 | if (queue == null) | ||
394 | { | ||
395 | return NoEvents(requestID, pAgentId); | ||
396 | } | ||
397 | |||
398 | OSD element; | ||
399 | lock (queue) | ||
400 | { | ||
401 | if (queue.Count == 0) | ||
402 | return NoEvents(requestID, pAgentId); | ||
403 | element = queue.Dequeue(); // 15s timeout | ||
404 | } | ||
405 | |||
406 | int thisID = 0; | ||
407 | lock (m_ids) | ||
408 | thisID = m_ids[pAgentId]; | ||
409 | |||
410 | OSDArray array = new OSDArray(); | ||
411 | if (element == null) // didn't have an event in 15s | ||
412 | { | ||
413 | // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! | ||
414 | array.Add(EventQueueHelper.KeepAliveEvent()); | ||
415 | //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | if (DebugLevel > 0) | ||
420 | LogOutboundDebugMessage(element, pAgentId); | ||
421 | |||
422 | array.Add(element); | ||
423 | |||
424 | lock (queue) | ||
425 | { | ||
426 | while (queue.Count > 0) | ||
427 | { | ||
428 | element = queue.Dequeue(); | ||
429 | |||
430 | if (DebugLevel > 0) | ||
431 | LogOutboundDebugMessage(element, pAgentId); | ||
432 | |||
433 | array.Add(element); | ||
434 | thisID++; | ||
435 | } | ||
436 | } | ||
437 | } | ||
438 | |||
439 | OSDMap events = new OSDMap(); | ||
440 | events.Add("events", array); | ||
441 | |||
442 | events.Add("id", new OSDInteger(thisID)); | ||
443 | lock (m_ids) | ||
444 | { | ||
445 | m_ids[pAgentId] = thisID + 1; | ||
446 | } | ||
447 | Hashtable responsedata = new Hashtable(); | ||
448 | responsedata["int_response_code"] = 200; | ||
449 | responsedata["content_type"] = "application/xml"; | ||
450 | responsedata["keepalive"] = false; | ||
451 | responsedata["reusecontext"] = false; | ||
452 | responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); | ||
453 | //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); | ||
454 | return responsedata; | ||
455 | } | ||
456 | |||
457 | public Hashtable NoEvents(UUID requestID, UUID agentID) | ||
458 | { | ||
459 | Hashtable responsedata = new Hashtable(); | ||
460 | responsedata["int_response_code"] = 502; | ||
461 | responsedata["content_type"] = "text/plain"; | ||
462 | responsedata["keepalive"] = false; | ||
463 | responsedata["reusecontext"] = false; | ||
464 | responsedata["str_response_string"] = "Upstream error: "; | ||
465 | responsedata["error_status_text"] = "Upstream error:"; | ||
466 | responsedata["http_protocol_version"] = "HTTP/1.0"; | ||
467 | return responsedata; | ||
468 | } | ||
469 | |||
470 | // public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps) | ||
471 | // { | ||
472 | // // TODO: this has to be redone to not busy-wait (and block the thread), | ||
473 | // // TODO: as soon as we have a non-blocking way to handle HTTP-requests. | ||
474 | // | ||
475 | //// if (m_log.IsDebugEnabled) | ||
476 | //// { | ||
477 | //// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ "; | ||
478 | //// foreach (object key in request.Keys) | ||
479 | //// { | ||
480 | //// debug += key.ToString() + "=" + request[key].ToString() + " "; | ||
481 | //// } | ||
482 | //// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name); | ||
483 | //// } | ||
484 | // | ||
485 | // Queue<OSD> queue = TryGetQueue(agentID); | ||
486 | // OSD element; | ||
487 | // | ||
488 | // lock (queue) | ||
489 | // element = queue.Dequeue(); // 15s timeout | ||
490 | // | ||
491 | // Hashtable responsedata = new Hashtable(); | ||
492 | // | ||
493 | // int thisID = 0; | ||
494 | // lock (m_ids) | ||
495 | // thisID = m_ids[agentID]; | ||
496 | // | ||
497 | // if (element == null) | ||
498 | // { | ||
499 | // //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName); | ||
500 | // if (thisID == -1) // close-request | ||
501 | // { | ||
502 | // m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName); | ||
503 | // responsedata["int_response_code"] = 404; //501; //410; //404; | ||
504 | // responsedata["content_type"] = "text/plain"; | ||
505 | // responsedata["keepalive"] = false; | ||
506 | // responsedata["str_response_string"] = "Closed EQG"; | ||
507 | // return responsedata; | ||
508 | // } | ||
509 | // responsedata["int_response_code"] = 502; | ||
510 | // responsedata["content_type"] = "text/plain"; | ||
511 | // responsedata["keepalive"] = false; | ||
512 | // responsedata["str_response_string"] = "Upstream error: "; | ||
513 | // responsedata["error_status_text"] = "Upstream error:"; | ||
514 | // responsedata["http_protocol_version"] = "HTTP/1.0"; | ||
515 | // return responsedata; | ||
516 | // } | ||
517 | // | ||
518 | // OSDArray array = new OSDArray(); | ||
519 | // if (element == null) // didn't have an event in 15s | ||
520 | // { | ||
521 | // // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! | ||
522 | // array.Add(EventQueueHelper.KeepAliveEvent()); | ||
523 | // //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | ||
524 | // } | ||
525 | // else | ||
526 | // { | ||
527 | // array.Add(element); | ||
528 | // | ||
529 | // if (element is OSDMap) | ||
530 | // { | ||
531 | // OSDMap ev = (OSDMap)element; | ||
532 | // m_log.DebugFormat( | ||
533 | // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", | ||
534 | // ev["message"], m_scene.GetScenePresence(agentID).Name); | ||
535 | // } | ||
536 | // | ||
537 | // lock (queue) | ||
538 | // { | ||
539 | // while (queue.Count > 0) | ||
540 | // { | ||
541 | // element = queue.Dequeue(); | ||
542 | // | ||
543 | // if (element is OSDMap) | ||
544 | // { | ||
545 | // OSDMap ev = (OSDMap)element; | ||
546 | // m_log.DebugFormat( | ||
547 | // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", | ||
548 | // ev["message"], m_scene.GetScenePresence(agentID).Name); | ||
549 | // } | ||
550 | // | ||
551 | // array.Add(element); | ||
552 | // thisID++; | ||
553 | // } | ||
554 | // } | ||
555 | // } | ||
556 | // | ||
557 | // OSDMap events = new OSDMap(); | ||
558 | // events.Add("events", array); | ||
559 | // | ||
560 | // events.Add("id", new OSDInteger(thisID)); | ||
561 | // lock (m_ids) | ||
562 | // { | ||
563 | // m_ids[agentID] = thisID + 1; | ||
564 | // } | ||
565 | // | ||
566 | // responsedata["int_response_code"] = 200; | ||
567 | // responsedata["content_type"] = "application/xml"; | ||
568 | // responsedata["keepalive"] = false; | ||
569 | // responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); | ||
570 | // | ||
571 | // m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); | ||
572 | // | ||
573 | // return responsedata; | ||
574 | // } | ||
575 | |||
576 | // public Hashtable EventQueuePath2(Hashtable request) | ||
577 | // { | ||
578 | // string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); | ||
579 | // // pull off the last "/" in the path. | ||
580 | // Hashtable responsedata = new Hashtable(); | ||
581 | // capuuid = capuuid.Substring(0, capuuid.Length - 1); | ||
582 | // capuuid = capuuid.Replace("/CAPS/EQG/", ""); | ||
583 | // UUID AvatarID = UUID.Zero; | ||
584 | // UUID capUUID = UUID.Zero; | ||
585 | // | ||
586 | // // parse the path and search for the avatar with it registered | ||
587 | // if (UUID.TryParse(capuuid, out capUUID)) | ||
588 | // { | ||
589 | // lock (m_QueueUUIDAvatarMapping) | ||
590 | // { | ||
591 | // if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) | ||
592 | // { | ||
593 | // AvatarID = m_QueueUUIDAvatarMapping[capUUID]; | ||
594 | // } | ||
595 | // } | ||
596 | // | ||
597 | // if (AvatarID != UUID.Zero) | ||
598 | // { | ||
599 | // return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID)); | ||
600 | // } | ||
601 | // else | ||
602 | // { | ||
603 | // responsedata["int_response_code"] = 404; | ||
604 | // responsedata["content_type"] = "text/plain"; | ||
605 | // responsedata["keepalive"] = false; | ||
606 | // responsedata["str_response_string"] = "Not Found"; | ||
607 | // responsedata["error_status_text"] = "Not Found"; | ||
608 | // responsedata["http_protocol_version"] = "HTTP/1.0"; | ||
609 | // return responsedata; | ||
610 | // // return 404 | ||
611 | // } | ||
612 | // } | ||
613 | // else | ||
614 | // { | ||
615 | // responsedata["int_response_code"] = 404; | ||
616 | // responsedata["content_type"] = "text/plain"; | ||
617 | // responsedata["keepalive"] = false; | ||
618 | // responsedata["str_response_string"] = "Not Found"; | ||
619 | // responsedata["error_status_text"] = "Not Found"; | ||
620 | // responsedata["http_protocol_version"] = "HTTP/1.0"; | ||
621 | // return responsedata; | ||
622 | // // return 404 | ||
623 | // } | ||
624 | // } | ||
625 | |||
626 | public OSD EventQueueFallBack(string path, OSD request, string endpoint) | ||
627 | { | ||
628 | // This is a fallback element to keep the client from loosing EventQueueGet | ||
629 | // Why does CAPS fail sometimes!? | ||
630 | m_log.Warn("[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!"); | ||
631 | string capuuid = path.Replace("/CAPS/EQG/",""); | ||
632 | capuuid = capuuid.Substring(0, capuuid.Length - 1); | ||
633 | |||
634 | // UUID AvatarID = UUID.Zero; | ||
635 | UUID capUUID = UUID.Zero; | ||
636 | if (UUID.TryParse(capuuid, out capUUID)) | ||
637 | { | ||
638 | /* Don't remove this yet code cleaners! | ||
639 | * Still testing this! | ||
640 | * | ||
641 | lock (m_QueueUUIDAvatarMapping) | ||
642 | { | ||
643 | if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) | ||
644 | { | ||
645 | AvatarID = m_QueueUUIDAvatarMapping[capUUID]; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | |||
650 | if (AvatarID != UUID.Zero) | ||
651 | { | ||
652 | // Repair the CAP! | ||
653 | //OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID); | ||
654 | //string capsBase = "/CAPS/EQG/"; | ||
655 | //caps.RegisterHandler("EventQueueGet", | ||
656 | //new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/", | ||
657 | //delegate(Hashtable m_dhttpMethod) | ||
658 | //{ | ||
659 | // return ProcessQueue(m_dhttpMethod, AvatarID, caps); | ||
660 | //})); | ||
661 | // start new ID sequence. | ||
662 | Random rnd = new Random(System.Environment.TickCount); | ||
663 | lock (m_ids) | ||
664 | { | ||
665 | if (!m_ids.ContainsKey(AvatarID)) | ||
666 | m_ids.Add(AvatarID, rnd.Next(30000000)); | ||
667 | } | ||
668 | |||
669 | |||
670 | int thisID = 0; | ||
671 | lock (m_ids) | ||
672 | thisID = m_ids[AvatarID]; | ||
673 | |||
674 | BlockingLLSDQueue queue = GetQueue(AvatarID); | ||
675 | OSDArray array = new OSDArray(); | ||
676 | LLSD element = queue.Dequeue(15000); // 15s timeout | ||
677 | if (element == null) | ||
678 | { | ||
679 | |||
680 | array.Add(EventQueueHelper.KeepAliveEvent()); | ||
681 | } | ||
682 | else | ||
683 | { | ||
684 | array.Add(element); | ||
685 | while (queue.Count() > 0) | ||
686 | { | ||
687 | array.Add(queue.Dequeue(1)); | ||
688 | thisID++; | ||
689 | } | ||
690 | } | ||
691 | OSDMap events = new OSDMap(); | ||
692 | events.Add("events", array); | ||
693 | |||
694 | events.Add("id", new LLSDInteger(thisID)); | ||
695 | |||
696 | lock (m_ids) | ||
697 | { | ||
698 | m_ids[AvatarID] = thisID + 1; | ||
699 | } | ||
700 | |||
701 | return events; | ||
702 | } | ||
703 | else | ||
704 | { | ||
705 | return new LLSD(); | ||
706 | } | ||
707 | * | ||
708 | */ | ||
709 | } | ||
710 | else | ||
711 | { | ||
712 | //return new LLSD(); | ||
713 | } | ||
714 | |||
715 | return new OSDString("shutdown404!"); | ||
716 | } | ||
717 | |||
718 | public void DisableSimulator(ulong handle, UUID avatarID) | ||
719 | { | ||
720 | OSD item = EventQueueHelper.DisableSimulator(handle); | ||
721 | Enqueue(item, avatarID); | ||
722 | } | ||
723 | |||
724 | public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) | ||
725 | { | ||
726 | if (DebugLevel > 0) | ||
727 | m_log.DebugFormat("{0} EnableSimulator. handle={1}, endPoint={2}, avatarID={3}", | ||
728 | LogHeader, handle, endPoint, avatarID, regionSizeX, regionSizeY); | ||
729 | |||
730 | OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY); | ||
731 | Enqueue(item, avatarID); | ||
732 | } | ||
733 | |||
734 | public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath, | ||
735 | ulong regionHandle, int regionSizeX, int regionSizeY) | ||
736 | { | ||
737 | if (DebugLevel > 0) | ||
738 | m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, endPoint={2}, avatarID={3}", | ||
739 | LogHeader, regionHandle, endPoint, avatarID, regionSizeX, regionSizeY); | ||
740 | |||
741 | OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY); | ||
742 | Enqueue(item, avatarID); | ||
743 | } | ||
744 | |||
745 | public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess, | ||
746 | IPEndPoint regionExternalEndPoint, | ||
747 | uint locationID, uint flags, string capsURL, | ||
748 | UUID avatarID, int regionSizeX, int regionSizeY) | ||
749 | { | ||
750 | if (DebugLevel > 0) | ||
751 | m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, endPoint={2}, avatarID={3}", | ||
752 | LogHeader, regionHandle, regionExternalEndPoint, avatarID, regionSizeX, regionSizeY); | ||
753 | |||
754 | OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint, | ||
755 | locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY); | ||
756 | Enqueue(item, avatarID); | ||
757 | } | ||
758 | |||
759 | public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, | ||
760 | IPEndPoint newRegionExternalEndPoint, | ||
761 | string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY) | ||
762 | { | ||
763 | if (DebugLevel > 0) | ||
764 | m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>", | ||
765 | LogHeader, handle, avatarID, regionSizeX, regionSizeY); | ||
766 | |||
767 | OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint, | ||
768 | capsURL, avatarID, sessionID, regionSizeX, regionSizeY); | ||
769 | Enqueue(item, avatarID); | ||
770 | } | ||
771 | |||
772 | public void ChatterboxInvitation(UUID sessionID, string sessionName, | ||
773 | UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, | ||
774 | uint timeStamp, bool offline, int parentEstateID, Vector3 position, | ||
775 | uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) | ||
776 | { | ||
777 | OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog, | ||
778 | timeStamp, offline, parentEstateID, position, ttl, transactionID, | ||
779 | fromGroup, binaryBucket); | ||
780 | Enqueue(item, toAgent); | ||
781 | //m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item); | ||
782 | |||
783 | } | ||
784 | |||
785 | public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat, | ||
786 | bool isModerator, bool textMute) | ||
787 | { | ||
788 | OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat, | ||
789 | isModerator, textMute); | ||
790 | Enqueue(item, fromAgent); | ||
791 | //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item); | ||
792 | } | ||
793 | |||
794 | public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID) | ||
795 | { | ||
796 | OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage); | ||
797 | Enqueue(item, avatarID); | ||
798 | } | ||
799 | |||
800 | public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID) | ||
801 | { | ||
802 | OSD item = EventQueueHelper.GroupMembership(groupUpdate); | ||
803 | Enqueue(item, avatarID); | ||
804 | } | ||
805 | |||
806 | public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID) | ||
807 | { | ||
808 | OSD item = EventQueueHelper.PlacesQuery(groupUpdate); | ||
809 | Enqueue(item, avatarID); | ||
810 | } | ||
811 | |||
812 | public OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono) | ||
813 | { | ||
814 | return EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, running, mono); | ||
815 | } | ||
816 | |||
817 | public OSD BuildEvent(string eventName, OSD eventBody) | ||
818 | { | ||
819 | return EventQueueHelper.BuildEvent(eventName, eventBody); | ||
820 | } | ||
821 | |||
822 | public void partPhysicsProperties(uint localID, byte physhapetype, | ||
823 | float density, float friction, float bounce, float gravmod,UUID avatarID) | ||
824 | { | ||
825 | OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype, | ||
826 | density, friction, bounce, gravmod); | ||
827 | Enqueue(item, avatarID); | ||
828 | } | ||
829 | } | ||
830 | } \ No newline at end of file | ||
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..384af74 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs | |||
@@ -0,0 +1,433 @@ | |||
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.Net; | ||
30 | using OpenMetaverse; | ||
31 | using OpenMetaverse.Packets; | ||
32 | using OpenMetaverse.StructuredData; | ||
33 | using OpenMetaverse.Messages.Linden; | ||
34 | |||
35 | namespace 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, int regionSizeX, int regionSizeY) | ||
74 | { | ||
75 | OSDMap llsdSimInfo = new OSDMap(5); | ||
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 | llsdSimInfo.Add("RegionSizeX", OSD.FromUInteger((uint) regionSizeX)); | ||
81 | llsdSimInfo.Add("RegionSizeY", OSD.FromUInteger((uint) regionSizeY)); | ||
82 | |||
83 | OSDArray arr = new OSDArray(1); | ||
84 | arr.Add(llsdSimInfo); | ||
85 | |||
86 | OSDMap llsdBody = new OSDMap(1); | ||
87 | llsdBody.Add("SimulatorInfo", arr); | ||
88 | |||
89 | return BuildEvent("EnableSimulator", llsdBody); | ||
90 | } | ||
91 | |||
92 | public static OSD DisableSimulator(ulong handle) | ||
93 | { | ||
94 | //OSDMap llsdSimInfo = new OSDMap(1); | ||
95 | |||
96 | //llsdSimInfo.Add("Handle", new OSDBinary(regionHandleToByteArray(handle))); | ||
97 | |||
98 | //OSDArray arr = new OSDArray(1); | ||
99 | //arr.Add(llsdSimInfo); | ||
100 | |||
101 | OSDMap llsdBody = new OSDMap(0); | ||
102 | //llsdBody.Add("SimulatorInfo", arr); | ||
103 | |||
104 | return BuildEvent("DisableSimulator", llsdBody); | ||
105 | } | ||
106 | |||
107 | public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, | ||
108 | IPEndPoint newRegionExternalEndPoint, | ||
109 | string capsURL, UUID agentID, UUID sessionID, | ||
110 | int regionSizeX, int regionSizeY) | ||
111 | { | ||
112 | OSDArray lookAtArr = new OSDArray(3); | ||
113 | lookAtArr.Add(OSD.FromReal(lookAt.X)); | ||
114 | lookAtArr.Add(OSD.FromReal(lookAt.Y)); | ||
115 | lookAtArr.Add(OSD.FromReal(lookAt.Z)); | ||
116 | |||
117 | OSDArray positionArr = new OSDArray(3); | ||
118 | positionArr.Add(OSD.FromReal(pos.X)); | ||
119 | positionArr.Add(OSD.FromReal(pos.Y)); | ||
120 | positionArr.Add(OSD.FromReal(pos.Z)); | ||
121 | |||
122 | OSDMap infoMap = new OSDMap(2); | ||
123 | infoMap.Add("LookAt", lookAtArr); | ||
124 | infoMap.Add("Position", positionArr); | ||
125 | |||
126 | OSDArray infoArr = new OSDArray(1); | ||
127 | infoArr.Add(infoMap); | ||
128 | |||
129 | OSDMap agentDataMap = new OSDMap(2); | ||
130 | agentDataMap.Add("AgentID", OSD.FromUUID(agentID)); | ||
131 | agentDataMap.Add("SessionID", OSD.FromUUID(sessionID)); | ||
132 | |||
133 | OSDArray agentDataArr = new OSDArray(1); | ||
134 | agentDataArr.Add(agentDataMap); | ||
135 | |||
136 | OSDMap regionDataMap = new OSDMap(6); | ||
137 | regionDataMap.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(handle))); | ||
138 | regionDataMap.Add("SeedCapability", OSD.FromString(capsURL)); | ||
139 | regionDataMap.Add("SimIP", OSD.FromBinary(newRegionExternalEndPoint.Address.GetAddressBytes())); | ||
140 | regionDataMap.Add("SimPort", OSD.FromInteger(newRegionExternalEndPoint.Port)); | ||
141 | regionDataMap.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX)); | ||
142 | regionDataMap.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY)); | ||
143 | |||
144 | OSDArray regionDataArr = new OSDArray(1); | ||
145 | regionDataArr.Add(regionDataMap); | ||
146 | |||
147 | OSDMap llsdBody = new OSDMap(3); | ||
148 | llsdBody.Add("Info", infoArr); | ||
149 | llsdBody.Add("AgentData", agentDataArr); | ||
150 | llsdBody.Add("RegionData", regionDataArr); | ||
151 | |||
152 | return BuildEvent("CrossedRegion", llsdBody); | ||
153 | } | ||
154 | |||
155 | public static OSD TeleportFinishEvent( | ||
156 | ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, | ||
157 | uint locationID, uint flags, string capsURL, UUID agentID, | ||
158 | int regionSizeX, int regionSizeY) | ||
159 | { | ||
160 | OSDMap info = new OSDMap(); | ||
161 | info.Add("AgentID", OSD.FromUUID(agentID)); | ||
162 | info.Add("LocationID", OSD.FromInteger(4)); // TODO what is this? | ||
163 | info.Add("RegionHandle", OSD.FromBinary(ulongToByteArray(regionHandle))); | ||
164 | info.Add("SeedCapability", OSD.FromString(capsURL)); | ||
165 | info.Add("SimAccess", OSD.FromInteger(simAccess)); | ||
166 | info.Add("SimIP", OSD.FromBinary(regionExternalEndPoint.Address.GetAddressBytes())); | ||
167 | info.Add("SimPort", OSD.FromInteger(regionExternalEndPoint.Port)); | ||
168 | info.Add("TeleportFlags", OSD.FromULong(1L << 4)); // AgentManager.TeleportFlags.ViaLocation | ||
169 | info.Add("RegionSizeX", OSD.FromUInteger((uint)regionSizeX)); | ||
170 | info.Add("RegionSizeY", OSD.FromUInteger((uint)regionSizeY)); | ||
171 | |||
172 | OSDArray infoArr = new OSDArray(); | ||
173 | infoArr.Add(info); | ||
174 | |||
175 | OSDMap body = new OSDMap(); | ||
176 | body.Add("Info", infoArr); | ||
177 | |||
178 | return BuildEvent("TeleportFinish", body); | ||
179 | } | ||
180 | |||
181 | public static OSD ScriptRunningReplyEvent(UUID objectID, UUID itemID, bool running, bool mono) | ||
182 | { | ||
183 | OSDMap script = new OSDMap(); | ||
184 | script.Add("ObjectID", OSD.FromUUID(objectID)); | ||
185 | script.Add("ItemID", OSD.FromUUID(itemID)); | ||
186 | script.Add("Running", OSD.FromBoolean(running)); | ||
187 | script.Add("Mono", OSD.FromBoolean(mono)); | ||
188 | |||
189 | OSDArray scriptArr = new OSDArray(); | ||
190 | scriptArr.Add(script); | ||
191 | |||
192 | OSDMap body = new OSDMap(); | ||
193 | body.Add("Script", scriptArr); | ||
194 | |||
195 | return BuildEvent("ScriptRunningReply", body); | ||
196 | } | ||
197 | |||
198 | public static OSD EstablishAgentCommunication(UUID agentID, string simIpAndPort, string seedcap, | ||
199 | ulong regionHandle, int regionSizeX, int regionSizeY) | ||
200 | { | ||
201 | OSDMap body = new OSDMap(6) | ||
202 | { | ||
203 | {"agent-id", new OSDUUID(agentID)}, | ||
204 | {"sim-ip-and-port", new OSDString(simIpAndPort)}, | ||
205 | {"seed-capability", new OSDString(seedcap)}, | ||
206 | {"region-handle", OSD.FromULong(regionHandle)}, | ||
207 | {"region-size-x", OSD.FromInteger(regionSizeX)}, | ||
208 | {"region-size-y", OSD.FromInteger(regionSizeY)} | ||
209 | }; | ||
210 | |||
211 | return BuildEvent("EstablishAgentCommunication", body); | ||
212 | } | ||
213 | |||
214 | public static OSD KeepAliveEvent() | ||
215 | { | ||
216 | return BuildEvent("FAKEEVENT", new OSDMap()); | ||
217 | } | ||
218 | |||
219 | public static OSD AgentParams(UUID agentID, bool checkEstate, int godLevel, bool limitedToEstate) | ||
220 | { | ||
221 | OSDMap body = new OSDMap(4); | ||
222 | |||
223 | body.Add("agent_id", new OSDUUID(agentID)); | ||
224 | body.Add("check_estate", new OSDInteger(checkEstate ? 1 : 0)); | ||
225 | body.Add("god_level", new OSDInteger(godLevel)); | ||
226 | body.Add("limited_to_estate", new OSDInteger(limitedToEstate ? 1 : 0)); | ||
227 | |||
228 | return body; | ||
229 | } | ||
230 | |||
231 | public static OSD InstantMessageParams(UUID fromAgent, string message, UUID toAgent, | ||
232 | string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, | ||
233 | Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) | ||
234 | { | ||
235 | OSDMap messageParams = new OSDMap(15); | ||
236 | messageParams.Add("type", new OSDInteger((int)dialog)); | ||
237 | |||
238 | OSDArray positionArray = new OSDArray(3); | ||
239 | positionArray.Add(OSD.FromReal(position.X)); | ||
240 | positionArray.Add(OSD.FromReal(position.Y)); | ||
241 | positionArray.Add(OSD.FromReal(position.Z)); | ||
242 | messageParams.Add("position", positionArray); | ||
243 | |||
244 | messageParams.Add("region_id", new OSDUUID(UUID.Zero)); | ||
245 | messageParams.Add("to_id", new OSDUUID(toAgent)); | ||
246 | messageParams.Add("source", new OSDInteger(0)); | ||
247 | |||
248 | OSDMap data = new OSDMap(1); | ||
249 | data.Add("binary_bucket", OSD.FromBinary(binaryBucket)); | ||
250 | messageParams.Add("data", data); | ||
251 | messageParams.Add("message", new OSDString(message)); | ||
252 | messageParams.Add("id", new OSDUUID(transactionID)); | ||
253 | messageParams.Add("from_name", new OSDString(fromName)); | ||
254 | messageParams.Add("timestamp", new OSDInteger((int)timeStamp)); | ||
255 | messageParams.Add("offline", new OSDInteger(offline ? 1 : 0)); | ||
256 | messageParams.Add("parent_estate_id", new OSDInteger(parentEstateID)); | ||
257 | messageParams.Add("ttl", new OSDInteger((int)ttl)); | ||
258 | messageParams.Add("from_id", new OSDUUID(fromAgent)); | ||
259 | messageParams.Add("from_group", new OSDInteger(fromGroup ? 1 : 0)); | ||
260 | |||
261 | return messageParams; | ||
262 | } | ||
263 | |||
264 | public static OSD InstantMessage(UUID fromAgent, string message, UUID toAgent, | ||
265 | string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, | ||
266 | Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket, | ||
267 | bool checkEstate, int godLevel, bool limitedToEstate) | ||
268 | { | ||
269 | OSDMap im = new OSDMap(2); | ||
270 | im.Add("message_params", InstantMessageParams(fromAgent, message, toAgent, | ||
271 | fromName, dialog, timeStamp, offline, parentEstateID, | ||
272 | position, ttl, transactionID, fromGroup, binaryBucket)); | ||
273 | |||
274 | im.Add("agent_params", AgentParams(fromAgent, checkEstate, godLevel, limitedToEstate)); | ||
275 | |||
276 | return im; | ||
277 | } | ||
278 | |||
279 | |||
280 | public static OSD ChatterboxInvitation(UUID sessionID, string sessionName, | ||
281 | UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, | ||
282 | uint timeStamp, bool offline, int parentEstateID, Vector3 position, | ||
283 | uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket) | ||
284 | { | ||
285 | OSDMap body = new OSDMap(5); | ||
286 | body.Add("session_id", new OSDUUID(sessionID)); | ||
287 | body.Add("from_name", new OSDString(fromName)); | ||
288 | body.Add("session_name", new OSDString(sessionName)); | ||
289 | body.Add("from_id", new OSDUUID(fromAgent)); | ||
290 | |||
291 | body.Add("instantmessage", InstantMessage(fromAgent, message, toAgent, | ||
292 | fromName, dialog, timeStamp, offline, parentEstateID, position, | ||
293 | ttl, transactionID, fromGroup, binaryBucket, true, 0, true)); | ||
294 | |||
295 | OSDMap chatterboxInvitation = new OSDMap(2); | ||
296 | chatterboxInvitation.Add("message", new OSDString("ChatterBoxInvitation")); | ||
297 | chatterboxInvitation.Add("body", body); | ||
298 | return chatterboxInvitation; | ||
299 | } | ||
300 | |||
301 | public static OSD ChatterBoxSessionAgentListUpdates(UUID sessionID, | ||
302 | UUID agentID, bool canVoiceChat, bool isModerator, bool textMute) | ||
303 | { | ||
304 | OSDMap body = new OSDMap(); | ||
305 | OSDMap agentUpdates = new OSDMap(); | ||
306 | OSDMap infoDetail = new OSDMap(); | ||
307 | OSDMap mutes = new OSDMap(); | ||
308 | |||
309 | mutes.Add("text", OSD.FromBoolean(textMute)); | ||
310 | infoDetail.Add("can_voice_chat", OSD.FromBoolean(canVoiceChat)); | ||
311 | infoDetail.Add("is_moderator", OSD.FromBoolean(isModerator)); | ||
312 | infoDetail.Add("mutes", mutes); | ||
313 | OSDMap info = new OSDMap(); | ||
314 | info.Add("info", infoDetail); | ||
315 | agentUpdates.Add(agentID.ToString(), info); | ||
316 | body.Add("agent_updates", agentUpdates); | ||
317 | body.Add("session_id", OSD.FromUUID(sessionID)); | ||
318 | body.Add("updates", new OSD()); | ||
319 | |||
320 | OSDMap chatterBoxSessionAgentListUpdates = new OSDMap(); | ||
321 | chatterBoxSessionAgentListUpdates.Add("message", OSD.FromString("ChatterBoxSessionAgentListUpdates")); | ||
322 | chatterBoxSessionAgentListUpdates.Add("body", body); | ||
323 | |||
324 | return chatterBoxSessionAgentListUpdates; | ||
325 | } | ||
326 | |||
327 | public static OSD GroupMembership(AgentGroupDataUpdatePacket groupUpdatePacket) | ||
328 | { | ||
329 | OSDMap groupUpdate = new OSDMap(); | ||
330 | groupUpdate.Add("message", OSD.FromString("AgentGroupDataUpdate")); | ||
331 | |||
332 | OSDMap body = new OSDMap(); | ||
333 | OSDArray agentData = new OSDArray(); | ||
334 | OSDMap agentDataMap = new OSDMap(); | ||
335 | agentDataMap.Add("AgentID", OSD.FromUUID(groupUpdatePacket.AgentData.AgentID)); | ||
336 | agentData.Add(agentDataMap); | ||
337 | body.Add("AgentData", agentData); | ||
338 | |||
339 | OSDArray groupData = new OSDArray(); | ||
340 | |||
341 | foreach (AgentGroupDataUpdatePacket.GroupDataBlock groupDataBlock in groupUpdatePacket.GroupData) | ||
342 | { | ||
343 | OSDMap groupDataMap = new OSDMap(); | ||
344 | groupDataMap.Add("ListInProfile", OSD.FromBoolean(false)); | ||
345 | groupDataMap.Add("GroupID", OSD.FromUUID(groupDataBlock.GroupID)); | ||
346 | groupDataMap.Add("GroupInsigniaID", OSD.FromUUID(groupDataBlock.GroupInsigniaID)); | ||
347 | groupDataMap.Add("Contribution", OSD.FromInteger(groupDataBlock.Contribution)); | ||
348 | groupDataMap.Add("GroupPowers", OSD.FromBinary(ulongToByteArray(groupDataBlock.GroupPowers))); | ||
349 | groupDataMap.Add("GroupName", OSD.FromString(Utils.BytesToString(groupDataBlock.GroupName))); | ||
350 | groupDataMap.Add("AcceptNotices", OSD.FromBoolean(groupDataBlock.AcceptNotices)); | ||
351 | |||
352 | groupData.Add(groupDataMap); | ||
353 | |||
354 | } | ||
355 | body.Add("GroupData", groupData); | ||
356 | groupUpdate.Add("body", body); | ||
357 | |||
358 | return groupUpdate; | ||
359 | } | ||
360 | |||
361 | public static OSD PlacesQuery(PlacesReplyPacket PlacesReply) | ||
362 | { | ||
363 | OSDMap placesReply = new OSDMap(); | ||
364 | placesReply.Add("message", OSD.FromString("PlacesReplyMessage")); | ||
365 | |||
366 | OSDMap body = new OSDMap(); | ||
367 | OSDArray agentData = new OSDArray(); | ||
368 | OSDMap agentDataMap = new OSDMap(); | ||
369 | agentDataMap.Add("AgentID", OSD.FromUUID(PlacesReply.AgentData.AgentID)); | ||
370 | agentDataMap.Add("QueryID", OSD.FromUUID(PlacesReply.AgentData.QueryID)); | ||
371 | agentDataMap.Add("TransactionID", OSD.FromUUID(PlacesReply.TransactionData.TransactionID)); | ||
372 | agentData.Add(agentDataMap); | ||
373 | body.Add("AgentData", agentData); | ||
374 | |||
375 | OSDArray QueryData = new OSDArray(); | ||
376 | |||
377 | foreach (PlacesReplyPacket.QueryDataBlock groupDataBlock in PlacesReply.QueryData) | ||
378 | { | ||
379 | OSDMap QueryDataMap = new OSDMap(); | ||
380 | QueryDataMap.Add("ActualArea", OSD.FromInteger(groupDataBlock.ActualArea)); | ||
381 | QueryDataMap.Add("BillableArea", OSD.FromInteger(groupDataBlock.BillableArea)); | ||
382 | QueryDataMap.Add("Description", OSD.FromBinary(groupDataBlock.Desc)); | ||
383 | QueryDataMap.Add("Dwell", OSD.FromInteger((int)groupDataBlock.Dwell)); | ||
384 | QueryDataMap.Add("Flags", OSD.FromString(Convert.ToString(groupDataBlock.Flags))); | ||
385 | QueryDataMap.Add("GlobalX", OSD.FromInteger((int)groupDataBlock.GlobalX)); | ||
386 | QueryDataMap.Add("GlobalY", OSD.FromInteger((int)groupDataBlock.GlobalY)); | ||
387 | QueryDataMap.Add("GlobalZ", OSD.FromInteger((int)groupDataBlock.GlobalZ)); | ||
388 | QueryDataMap.Add("Name", OSD.FromBinary(groupDataBlock.Name)); | ||
389 | QueryDataMap.Add("OwnerID", OSD.FromUUID(groupDataBlock.OwnerID)); | ||
390 | QueryDataMap.Add("SimName", OSD.FromBinary(groupDataBlock.SimName)); | ||
391 | QueryDataMap.Add("SnapShotID", OSD.FromUUID(groupDataBlock.SnapshotID)); | ||
392 | QueryDataMap.Add("ProductSku", OSD.FromInteger(0)); | ||
393 | QueryDataMap.Add("Price", OSD.FromInteger(groupDataBlock.Price)); | ||
394 | |||
395 | QueryData.Add(QueryDataMap); | ||
396 | } | ||
397 | body.Add("QueryData", QueryData); | ||
398 | placesReply.Add("QueryData[]", body); | ||
399 | |||
400 | return placesReply; | ||
401 | } | ||
402 | |||
403 | public static OSD ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage) | ||
404 | { | ||
405 | OSDMap message = new OSDMap(); | ||
406 | message.Add("message", OSD.FromString("ParcelProperties")); | ||
407 | OSD message_body = parcelPropertiesMessage.Serialize(); | ||
408 | message.Add("body", message_body); | ||
409 | return message; | ||
410 | } | ||
411 | |||
412 | public static OSD partPhysicsProperties(uint localID, byte physhapetype, | ||
413 | float density, float friction, float bounce, float gravmod) | ||
414 | { | ||
415 | |||
416 | OSDMap physinfo = new OSDMap(6); | ||
417 | physinfo["LocalID"] = localID; | ||
418 | physinfo["Density"] = density; | ||
419 | physinfo["Friction"] = friction; | ||
420 | physinfo["GravityMultiplier"] = gravmod; | ||
421 | physinfo["Restitution"] = bounce; | ||
422 | physinfo["PhysicsShapeType"] = (int)physhapetype; | ||
423 | |||
424 | OSDArray array = new OSDArray(1); | ||
425 | array.Add(physinfo); | ||
426 | |||
427 | OSDMap llsdBody = new OSDMap(1); | ||
428 | llsdBody.Add("ObjectData", array); | ||
429 | |||
430 | return BuildEvent("ObjectPhysicsProperties", llsdBody); | ||
431 | } | ||
432 | } | ||
433 | } | ||
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs new file mode 100644 index 0000000..16a902d --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs | |||
@@ -0,0 +1,190 @@ | |||
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 log4net.Config; | ||
33 | using Nini.Config; | ||
34 | using NUnit.Framework; | ||
35 | using OpenMetaverse; | ||
36 | using OpenMetaverse.Packets; | ||
37 | using OpenMetaverse.StructuredData; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Servers; | ||
40 | using OpenSim.Framework.Servers.HttpServer; | ||
41 | using OpenSim.Region.ClientStack.Linden; | ||
42 | using OpenSim.Region.CoreModules.Framework; | ||
43 | using OpenSim.Region.Framework.Scenes; | ||
44 | using OpenSim.Region.OptionalModules.World.NPC; | ||
45 | using OpenSim.Tests.Common; | ||
46 | |||
47 | namespace OpenSim.Region.ClientStack.Linden.Tests | ||
48 | { | ||
49 | [TestFixture] | ||
50 | public class EventQueueTests : OpenSimTestCase | ||
51 | { | ||
52 | private TestScene m_scene; | ||
53 | private EventQueueGetModule m_eqgMod; | ||
54 | private NPCModule m_npcMod; | ||
55 | |||
56 | [SetUp] | ||
57 | public override void SetUp() | ||
58 | { | ||
59 | base.SetUp(); | ||
60 | |||
61 | uint port = 9999; | ||
62 | uint sslPort = 9998; | ||
63 | |||
64 | // This is an unfortunate bit of clean up we have to do because MainServer manages things through static | ||
65 | // variables and the VM is not restarted between tests. | ||
66 | MainServer.RemoveHttpServer(port); | ||
67 | |||
68 | BaseHttpServer server = new BaseHttpServer(port, false, sslPort, ""); | ||
69 | MainServer.AddHttpServer(server); | ||
70 | MainServer.Instance = server; | ||
71 | |||
72 | IConfigSource config = new IniConfigSource(); | ||
73 | config.AddConfig("Startup"); | ||
74 | config.Configs["Startup"].Set("EventQueue", "true"); | ||
75 | |||
76 | CapabilitiesModule capsModule = new CapabilitiesModule(); | ||
77 | m_eqgMod = new EventQueueGetModule(); | ||
78 | |||
79 | // For NPC test support | ||
80 | config.AddConfig("NPC"); | ||
81 | config.Configs["NPC"].Set("Enabled", "true"); | ||
82 | m_npcMod = new NPCModule(); | ||
83 | |||
84 | m_scene = new SceneHelpers().SetupScene(); | ||
85 | SceneHelpers.SetupSceneModules(m_scene, config, capsModule, m_eqgMod, m_npcMod); | ||
86 | } | ||
87 | |||
88 | [Test] | ||
89 | public void TestAddForClient() | ||
90 | { | ||
91 | TestHelpers.InMethod(); | ||
92 | // log4net.Config.XmlConfigurator.Configure(); | ||
93 | |||
94 | SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); | ||
95 | |||
96 | // TODO: Add more assertions for the other aspects of event queues | ||
97 | Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(1)); | ||
98 | } | ||
99 | |||
100 | [Test] | ||
101 | public void TestRemoveForClient() | ||
102 | { | ||
103 | TestHelpers.InMethod(); | ||
104 | // TestHelpers.EnableLogging(); | ||
105 | |||
106 | UUID spId = TestHelpers.ParseTail(0x1); | ||
107 | |||
108 | SceneHelpers.AddScenePresence(m_scene, spId); | ||
109 | m_scene.CloseAgent(spId, false); | ||
110 | |||
111 | // TODO: Add more assertions for the other aspects of event queues | ||
112 | Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); | ||
113 | } | ||
114 | |||
115 | [Test] | ||
116 | public void TestEnqueueMessage() | ||
117 | { | ||
118 | TestHelpers.InMethod(); | ||
119 | // log4net.Config.XmlConfigurator.Configure(); | ||
120 | |||
121 | ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); | ||
122 | |||
123 | string messageName = "TestMessage"; | ||
124 | |||
125 | m_eqgMod.Enqueue(m_eqgMod.BuildEvent(messageName, new OSDMap()), sp.UUID); | ||
126 | |||
127 | Hashtable eventsResponse = m_eqgMod.GetEvents(UUID.Zero, sp.UUID); | ||
128 | |||
129 | Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK)); | ||
130 | |||
131 | // Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]); | ||
132 | |||
133 | OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]); | ||
134 | OSDArray eventsOsd = (OSDArray)rawOsd["events"]; | ||
135 | |||
136 | bool foundUpdate = false; | ||
137 | foreach (OSD osd in eventsOsd) | ||
138 | { | ||
139 | OSDMap eventOsd = (OSDMap)osd; | ||
140 | |||
141 | if (eventOsd["message"] == messageName) | ||
142 | foundUpdate = true; | ||
143 | } | ||
144 | |||
145 | Assert.That(foundUpdate, Is.True, string.Format("Did not find {0} in response", messageName)); | ||
146 | } | ||
147 | |||
148 | /// <summary> | ||
149 | /// Test an attempt to put a message on the queue of a user that is not in the region. | ||
150 | /// </summary> | ||
151 | [Test] | ||
152 | public void TestEnqueueMessageNoUser() | ||
153 | { | ||
154 | TestHelpers.InMethod(); | ||
155 | TestHelpers.EnableLogging(); | ||
156 | |||
157 | string messageName = "TestMessage"; | ||
158 | |||
159 | m_eqgMod.Enqueue(m_eqgMod.BuildEvent(messageName, new OSDMap()), TestHelpers.ParseTail(0x1)); | ||
160 | |||
161 | Hashtable eventsResponse = m_eqgMod.GetEvents(UUID.Zero, TestHelpers.ParseTail(0x1)); | ||
162 | |||
163 | Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.BadGateway)); | ||
164 | } | ||
165 | |||
166 | /// <summary> | ||
167 | /// NPCs do not currently have an event queue but a caller may try to send a message anyway, so check behaviour. | ||
168 | /// </summary> | ||
169 | [Test] | ||
170 | public void TestEnqueueMessageToNpc() | ||
171 | { | ||
172 | TestHelpers.InMethod(); | ||
173 | // TestHelpers.EnableLogging(); | ||
174 | |||
175 | UUID npcId | ||
176 | = m_npcMod.CreateNPC( | ||
177 | "John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, new AvatarAppearance()); | ||
178 | |||
179 | ScenePresence npc = m_scene.GetScenePresence(npcId); | ||
180 | |||
181 | string messageName = "TestMessage"; | ||
182 | |||
183 | m_eqgMod.Enqueue(m_eqgMod.BuildEvent(messageName, new OSDMap()), npc.UUID); | ||
184 | |||
185 | Hashtable eventsResponse = m_eqgMod.GetEvents(UUID.Zero, npc.UUID); | ||
186 | |||
187 | Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.BadGateway)); | ||
188 | } | ||
189 | } | ||
190 | } \ No newline at end of file | ||