diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | 362 |
1 files changed, 220 insertions, 142 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 7d73b3e..5c721d4 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs | |||
@@ -39,6 +39,7 @@ using OpenMetaverse.Messages.Linden; | |||
39 | using OpenMetaverse.Packets; | 39 | using OpenMetaverse.Packets; |
40 | using OpenMetaverse.StructuredData; | 40 | using OpenMetaverse.StructuredData; |
41 | using OpenSim.Framework; | 41 | using OpenSim.Framework; |
42 | using OpenSim.Framework.Console; | ||
42 | using OpenSim.Framework.Servers; | 43 | using OpenSim.Framework.Servers; |
43 | using OpenSim.Framework.Servers.HttpServer; | 44 | using OpenSim.Framework.Servers.HttpServer; |
44 | using OpenSim.Region.Framework.Interfaces; | 45 | using OpenSim.Region.Framework.Interfaces; |
@@ -58,9 +59,15 @@ namespace OpenSim.Region.ClientStack.Linden | |||
58 | public class EventQueueGetModule : IEventQueue, IRegionModule | 59 | public class EventQueueGetModule : IEventQueue, IRegionModule |
59 | { | 60 | { |
60 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 61 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
61 | protected Scene m_scene = null; | 62 | |
63 | /// <value> | ||
64 | /// Debug level. | ||
65 | /// </value> | ||
66 | public int DebugLevel { get; set; } | ||
67 | |||
68 | protected Scene m_scene; | ||
62 | private IConfigSource m_gConfig; | 69 | private IConfigSource m_gConfig; |
63 | bool enabledYN = false; | 70 | bool enabledYN; |
64 | 71 | ||
65 | private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); | 72 | private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>(); |
66 | 73 | ||
@@ -97,6 +104,15 @@ namespace OpenSim.Region.ClientStack.Linden | |||
97 | scene.EventManager.OnClientClosed += ClientClosed; | 104 | scene.EventManager.OnClientClosed += ClientClosed; |
98 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; | 105 | scene.EventManager.OnMakeChildAgent += MakeChildAgent; |
99 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; | 106 | scene.EventManager.OnRegisterCaps += OnRegisterCaps; |
107 | |||
108 | MainConsole.Instance.Commands.AddCommand( | ||
109 | "event queue", | ||
110 | false, | ||
111 | "debug eq", | ||
112 | "debug eq [0|1]", | ||
113 | "debug eq 1 will turn on event queue debugging. This will log all outgoing event queue messages to clients.\n" | ||
114 | + "debug eq 1 will turn off event queue debugging.", | ||
115 | HandleDebugEq); | ||
100 | } | 116 | } |
101 | else | 117 | else |
102 | { | 118 | { |
@@ -128,6 +144,22 @@ namespace OpenSim.Region.ClientStack.Linden | |||
128 | } | 144 | } |
129 | #endregion | 145 | #endregion |
130 | 146 | ||
147 | protected void HandleDebugEq(string module, string[] args) | ||
148 | { | ||
149 | int debugLevel; | ||
150 | |||
151 | if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel))) | ||
152 | { | ||
153 | MainConsole.Instance.OutputFormat("Usage: debug eq [0|1]"); | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | DebugLevel = debugLevel; | ||
158 | MainConsole.Instance.OutputFormat( | ||
159 | "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName); | ||
160 | } | ||
161 | } | ||
162 | |||
131 | /// <summary> | 163 | /// <summary> |
132 | /// Always returns a valid queue | 164 | /// Always returns a valid queue |
133 | /// </summary> | 165 | /// </summary> |
@@ -314,16 +346,22 @@ namespace OpenSim.Region.ClientStack.Linden | |||
314 | } | 346 | } |
315 | 347 | ||
316 | // Register this as a caps handler | 348 | // Register this as a caps handler |
349 | // FIXME: Confusingly, we need to register separate as a capability so that the client is told about | ||
350 | // EventQueueGet when it receive capability information, but then we replace the rest handler immediately | ||
351 | // afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but | ||
352 | // really it should be possible to directly register the poll handler as a capability. | ||
317 | caps.RegisterHandler("EventQueueGet", | 353 | caps.RegisterHandler("EventQueueGet", |
318 | new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", | 354 | new RestHTTPHandler("POST", capsBase + EventQueueGetUUID.ToString() + "/", null)); |
319 | delegate(Hashtable m_dhttpMethod) | 355 | // delegate(Hashtable m_dhttpMethod) |
320 | { | 356 | // { |
321 | return ProcessQueue(m_dhttpMethod, agentID, caps); | 357 | // return ProcessQueue(m_dhttpMethod, agentID, caps); |
322 | })); | 358 | // })); |
323 | 359 | ||
324 | // This will persist this beyond the expiry of the caps handlers | 360 | // This will persist this beyond the expiry of the caps handlers |
325 | MainServer.Instance.AddPollServiceHTTPHandler( | 361 | MainServer.Instance.AddPollServiceHTTPHandler( |
326 | capsBase + EventQueueGetUUID.ToString() + "/", EventQueuePoll, new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); | 362 | capsBase + EventQueueGetUUID.ToString() + "/", |
363 | EventQueuePoll, | ||
364 | new PollServiceEventArgs(null, HasEvents, GetEvents, NoEvents, agentID)); | ||
327 | 365 | ||
328 | Random rnd = new Random(Environment.TickCount); | 366 | Random rnd = new Random(Environment.TickCount); |
329 | lock (m_ids) | 367 | lock (m_ids) |
@@ -348,6 +386,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
348 | 386 | ||
349 | public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) | 387 | public Hashtable GetEvents(UUID requestID, UUID pAgentId, string request) |
350 | { | 388 | { |
389 | // m_log.DebugFormat("[EVENT QUEUE GET MODULE]: Invoked GetEvents() for {0}", pAgentId); | ||
390 | |||
351 | Queue<OSD> queue = TryGetQueue(pAgentId); | 391 | Queue<OSD> queue = TryGetQueue(pAgentId); |
352 | OSD element; | 392 | OSD element; |
353 | lock (queue) | 393 | lock (queue) |
@@ -370,12 +410,31 @@ namespace OpenSim.Region.ClientStack.Linden | |||
370 | } | 410 | } |
371 | else | 411 | else |
372 | { | 412 | { |
413 | if (DebugLevel > 0 && element is OSDMap) | ||
414 | { | ||
415 | OSDMap ev = (OSDMap)element; | ||
416 | m_log.DebugFormat( | ||
417 | "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", | ||
418 | ev["message"], m_scene.GetScenePresence(pAgentId).Name); | ||
419 | } | ||
420 | |||
373 | array.Add(element); | 421 | array.Add(element); |
422 | |||
374 | lock (queue) | 423 | lock (queue) |
375 | { | 424 | { |
376 | while (queue.Count > 0) | 425 | while (queue.Count > 0) |
377 | { | 426 | { |
378 | array.Add(queue.Dequeue()); | 427 | element = queue.Dequeue(); |
428 | |||
429 | if (DebugLevel > 0 && element is OSDMap) | ||
430 | { | ||
431 | OSDMap ev = (OSDMap)element; | ||
432 | m_log.DebugFormat( | ||
433 | "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", | ||
434 | ev["message"], m_scene.GetScenePresence(pAgentId).Name); | ||
435 | } | ||
436 | |||
437 | array.Add(element); | ||
379 | thisID++; | 438 | thisID++; |
380 | } | 439 | } |
381 | } | 440 | } |
@@ -412,148 +471,166 @@ namespace OpenSim.Region.ClientStack.Linden | |||
412 | return responsedata; | 471 | return responsedata; |
413 | } | 472 | } |
414 | 473 | ||
415 | public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps) | 474 | // public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps) |
416 | { | 475 | // { |
417 | // TODO: this has to be redone to not busy-wait (and block the thread), | 476 | // // TODO: this has to be redone to not busy-wait (and block the thread), |
418 | // TODO: as soon as we have a non-blocking way to handle HTTP-requests. | 477 | // // TODO: as soon as we have a non-blocking way to handle HTTP-requests. |
419 | 478 | // | |
420 | // if (m_log.IsDebugEnabled) | 479 | //// if (m_log.IsDebugEnabled) |
421 | // { | 480 | //// { |
422 | // String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ "; | 481 | //// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ "; |
423 | // foreach (object key in request.Keys) | 482 | //// foreach (object key in request.Keys) |
483 | //// { | ||
484 | //// debug += key.ToString() + "=" + request[key].ToString() + " "; | ||
485 | //// } | ||
486 | //// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name); | ||
487 | //// } | ||
488 | // | ||
489 | // Queue<OSD> queue = TryGetQueue(agentID); | ||
490 | // OSD element; | ||
491 | // | ||
492 | // lock (queue) | ||
493 | // element = queue.Dequeue(); // 15s timeout | ||
494 | // | ||
495 | // Hashtable responsedata = new Hashtable(); | ||
496 | // | ||
497 | // int thisID = 0; | ||
498 | // lock (m_ids) | ||
499 | // thisID = m_ids[agentID]; | ||
500 | // | ||
501 | // if (element == null) | ||
502 | // { | ||
503 | // //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName); | ||
504 | // if (thisID == -1) // close-request | ||
424 | // { | 505 | // { |
425 | // debug += key.ToString() + "=" + request[key].ToString() + " "; | 506 | // m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName); |
507 | // responsedata["int_response_code"] = 404; //501; //410; //404; | ||
508 | // responsedata["content_type"] = "text/plain"; | ||
509 | // responsedata["keepalive"] = false; | ||
510 | // responsedata["str_response_string"] = "Closed EQG"; | ||
511 | // return responsedata; | ||
426 | // } | 512 | // } |
427 | // m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name); | 513 | // responsedata["int_response_code"] = 502; |
514 | // responsedata["content_type"] = "text/plain"; | ||
515 | // responsedata["keepalive"] = false; | ||
516 | // responsedata["str_response_string"] = "Upstream error: "; | ||
517 | // responsedata["error_status_text"] = "Upstream error:"; | ||
518 | // responsedata["http_protocol_version"] = "HTTP/1.0"; | ||
519 | // return responsedata; | ||
428 | // } | 520 | // } |
429 | 521 | // | |
430 | Queue<OSD> queue = TryGetQueue(agentID); | 522 | // OSDArray array = new OSDArray(); |
431 | OSD element; | 523 | // if (element == null) // didn't have an event in 15s |
432 | 524 | // { | |
433 | lock (queue) | 525 | // // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! |
434 | element = queue.Dequeue(); // 15s timeout | 526 | // array.Add(EventQueueHelper.KeepAliveEvent()); |
435 | 527 | // //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | |
436 | Hashtable responsedata = new Hashtable(); | 528 | // } |
437 | 529 | // else | |
438 | int thisID = 0; | 530 | // { |
439 | lock (m_ids) | 531 | // array.Add(element); |
440 | thisID = m_ids[agentID]; | 532 | // |
441 | 533 | // if (element is OSDMap) | |
442 | if (element == null) | 534 | // { |
443 | { | 535 | // OSDMap ev = (OSDMap)element; |
444 | //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName); | 536 | // m_log.DebugFormat( |
445 | if (thisID == -1) // close-request | 537 | // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", |
446 | { | 538 | // ev["message"], m_scene.GetScenePresence(agentID).Name); |
447 | m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName); | 539 | // } |
448 | responsedata["int_response_code"] = 404; //501; //410; //404; | 540 | // |
449 | responsedata["content_type"] = "text/plain"; | 541 | // lock (queue) |
450 | responsedata["keepalive"] = false; | 542 | // { |
451 | responsedata["str_response_string"] = "Closed EQG"; | 543 | // while (queue.Count > 0) |
452 | return responsedata; | 544 | // { |
453 | } | 545 | // element = queue.Dequeue(); |
454 | responsedata["int_response_code"] = 502; | 546 | // |
455 | responsedata["content_type"] = "text/plain"; | 547 | // if (element is OSDMap) |
456 | responsedata["keepalive"] = false; | 548 | // { |
457 | responsedata["str_response_string"] = "Upstream error: "; | 549 | // OSDMap ev = (OSDMap)element; |
458 | responsedata["error_status_text"] = "Upstream error:"; | 550 | // m_log.DebugFormat( |
459 | responsedata["http_protocol_version"] = "HTTP/1.0"; | 551 | // "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}", |
460 | return responsedata; | 552 | // ev["message"], m_scene.GetScenePresence(agentID).Name); |
461 | } | 553 | // } |
462 | 554 | // | |
463 | OSDArray array = new OSDArray(); | 555 | // array.Add(element); |
464 | if (element == null) // didn't have an event in 15s | 556 | // thisID++; |
465 | { | 557 | // } |
466 | // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say! | 558 | // } |
467 | array.Add(EventQueueHelper.KeepAliveEvent()); | 559 | // } |
468 | //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); | 560 | // |
469 | } | 561 | // OSDMap events = new OSDMap(); |
470 | else | 562 | // events.Add("events", array); |
471 | { | 563 | // |
472 | array.Add(element); | 564 | // events.Add("id", new OSDInteger(thisID)); |
473 | 565 | // lock (m_ids) | |
474 | lock (queue) | 566 | // { |
475 | { | 567 | // m_ids[agentID] = thisID + 1; |
476 | while (queue.Count > 0) | 568 | // } |
477 | { | 569 | // |
478 | array.Add(queue.Dequeue()); | 570 | // responsedata["int_response_code"] = 200; |
479 | thisID++; | 571 | // responsedata["content_type"] = "application/xml"; |
480 | } | 572 | // responsedata["keepalive"] = false; |
481 | } | 573 | // responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); |
482 | } | 574 | // |
483 | 575 | // m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); | |
484 | OSDMap events = new OSDMap(); | 576 | // |
485 | events.Add("events", array); | 577 | // return responsedata; |
486 | 578 | // } | |
487 | events.Add("id", new OSDInteger(thisID)); | ||
488 | lock (m_ids) | ||
489 | { | ||
490 | m_ids[agentID] = thisID + 1; | ||
491 | } | ||
492 | |||
493 | responsedata["int_response_code"] = 200; | ||
494 | responsedata["content_type"] = "application/xml"; | ||
495 | responsedata["keepalive"] = false; | ||
496 | responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events); | ||
497 | //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]); | ||
498 | |||
499 | return responsedata; | ||
500 | } | ||
501 | 579 | ||
502 | public Hashtable EventQueuePoll(Hashtable request) | 580 | public Hashtable EventQueuePoll(Hashtable request) |
503 | { | 581 | { |
504 | return new Hashtable(); | 582 | return new Hashtable(); |
505 | } | 583 | } |
506 | 584 | ||
507 | public Hashtable EventQueuePath2(Hashtable request) | 585 | // public Hashtable EventQueuePath2(Hashtable request) |
508 | { | 586 | // { |
509 | string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); | 587 | // string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/",""); |
510 | // pull off the last "/" in the path. | 588 | // // pull off the last "/" in the path. |
511 | Hashtable responsedata = new Hashtable(); | 589 | // Hashtable responsedata = new Hashtable(); |
512 | capuuid = capuuid.Substring(0, capuuid.Length - 1); | 590 | // capuuid = capuuid.Substring(0, capuuid.Length - 1); |
513 | capuuid = capuuid.Replace("/CAPS/EQG/", ""); | 591 | // capuuid = capuuid.Replace("/CAPS/EQG/", ""); |
514 | UUID AvatarID = UUID.Zero; | 592 | // UUID AvatarID = UUID.Zero; |
515 | UUID capUUID = UUID.Zero; | 593 | // UUID capUUID = UUID.Zero; |
516 | 594 | // | |
517 | // parse the path and search for the avatar with it registered | 595 | // // parse the path and search for the avatar with it registered |
518 | if (UUID.TryParse(capuuid, out capUUID)) | 596 | // if (UUID.TryParse(capuuid, out capUUID)) |
519 | { | 597 | // { |
520 | lock (m_QueueUUIDAvatarMapping) | 598 | // lock (m_QueueUUIDAvatarMapping) |
521 | { | 599 | // { |
522 | if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) | 600 | // if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID)) |
523 | { | 601 | // { |
524 | AvatarID = m_QueueUUIDAvatarMapping[capUUID]; | 602 | // AvatarID = m_QueueUUIDAvatarMapping[capUUID]; |
525 | } | 603 | // } |
526 | } | 604 | // } |
527 | 605 | // | |
528 | if (AvatarID != UUID.Zero) | 606 | // if (AvatarID != UUID.Zero) |
529 | { | 607 | // { |
530 | return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID)); | 608 | // return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID)); |
531 | } | 609 | // } |
532 | else | 610 | // else |
533 | { | 611 | // { |
534 | responsedata["int_response_code"] = 404; | 612 | // responsedata["int_response_code"] = 404; |
535 | responsedata["content_type"] = "text/plain"; | 613 | // responsedata["content_type"] = "text/plain"; |
536 | responsedata["keepalive"] = false; | 614 | // responsedata["keepalive"] = false; |
537 | responsedata["str_response_string"] = "Not Found"; | 615 | // responsedata["str_response_string"] = "Not Found"; |
538 | responsedata["error_status_text"] = "Not Found"; | 616 | // responsedata["error_status_text"] = "Not Found"; |
539 | responsedata["http_protocol_version"] = "HTTP/1.0"; | 617 | // responsedata["http_protocol_version"] = "HTTP/1.0"; |
540 | return responsedata; | 618 | // return responsedata; |
541 | // return 404 | 619 | // // return 404 |
542 | } | 620 | // } |
543 | } | 621 | // } |
544 | else | 622 | // else |
545 | { | 623 | // { |
546 | responsedata["int_response_code"] = 404; | 624 | // responsedata["int_response_code"] = 404; |
547 | responsedata["content_type"] = "text/plain"; | 625 | // responsedata["content_type"] = "text/plain"; |
548 | responsedata["keepalive"] = false; | 626 | // responsedata["keepalive"] = false; |
549 | responsedata["str_response_string"] = "Not Found"; | 627 | // responsedata["str_response_string"] = "Not Found"; |
550 | responsedata["error_status_text"] = "Not Found"; | 628 | // responsedata["error_status_text"] = "Not Found"; |
551 | responsedata["http_protocol_version"] = "HTTP/1.0"; | 629 | // responsedata["http_protocol_version"] = "HTTP/1.0"; |
552 | return responsedata; | 630 | // return responsedata; |
553 | // return 404 | 631 | // // return 404 |
554 | } | 632 | // } |
555 | 633 | // } | |
556 | } | ||
557 | 634 | ||
558 | public OSD EventQueueFallBack(string path, OSD request, string endpoint) | 635 | public OSD EventQueueFallBack(string path, OSD request, string endpoint) |
559 | { | 636 | { |
@@ -717,6 +794,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
717 | OSD item = EventQueueHelper.GroupMembership(groupUpdate); | 794 | OSD item = EventQueueHelper.GroupMembership(groupUpdate); |
718 | Enqueue(item, avatarID); | 795 | Enqueue(item, avatarID); |
719 | } | 796 | } |
797 | |||
720 | public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID) | 798 | public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID) |
721 | { | 799 | { |
722 | OSD item = EventQueueHelper.PlacesQuery(groupUpdate); | 800 | OSD item = EventQueueHelper.PlacesQuery(groupUpdate); |