2008-09-27 18:33:54 +00:00
/ *
* Copyright ( c ) Contributors , http : //opensimulator.org/
* See CONTRIBUTORS . TXT for a full list of copyright holders .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2009-06-01 06:37:14 +00:00
* * Neither the name of the OpenSimulator Project nor the
2008-09-27 18:33:54 +00:00
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ` ` AS IS ' ' AND ANY
* EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* /
2009-01-02 20:22:35 +00:00
2009-02-12 18:59:45 +00:00
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Net ;
using System.Reflection ;
using System.Threading ;
using log4net ;
using Nini.Config ;
2011-04-30 20:24:25 +00:00
using Mono.Addins ;
2009-02-12 18:59:45 +00:00
using OpenMetaverse ;
2010-08-30 01:28:31 +00:00
using OpenMetaverse.Messages.Linden ;
2009-02-12 18:59:45 +00:00
using OpenMetaverse.Packets ;
using OpenMetaverse.StructuredData ;
using OpenSim.Framework ;
2011-11-24 20:27:11 +00:00
using OpenSim.Framework.Console ;
2009-02-12 18:59:45 +00:00
using OpenSim.Framework.Servers ;
2009-05-04 20:15:39 +00:00
using OpenSim.Framework.Servers.HttpServer ;
2009-02-12 18:59:45 +00:00
using OpenSim.Region.Framework.Interfaces ;
using OpenSim.Region.Framework.Scenes ;
using BlockingLLSDQueue = OpenSim . Framework . BlockingQueue < OpenMetaverse . StructuredData . OSD > ;
2009-06-18 14:33:35 +00:00
using Caps = OpenSim . Framework . Capabilities . Caps ;
2008-09-27 09:42:31 +00:00
2011-04-30 16:24:15 +00:00
namespace OpenSim.Region.ClientStack.Linden
2008-09-27 09:42:31 +00:00
{
2008-09-27 22:05:36 +00:00
public struct QueueItem
{
public int id ;
2008-11-19 06:25:34 +00:00
public OSDMap body ;
2008-09-27 22:05:36 +00:00
}
2012-11-13 02:08:02 +00:00
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")]
2012-11-10 16:48:31 +00:00
public class EventQueueGetModule : IEventQueue , INonSharedRegionModule
2008-09-27 09:42:31 +00:00
{
private static readonly ILog m_log = LogManager . GetLogger ( MethodBase . GetCurrentMethod ( ) . DeclaringType ) ;
2011-11-24 20:27:11 +00:00
/// <value>
/// Debug level.
/// </value>
public int DebugLevel { get ; set ; }
protected Scene m_scene ;
2008-09-27 22:05:36 +00:00
private Dictionary < UUID , int > m_ids = new Dictionary < UUID , int > ( ) ;
2008-09-27 09:42:31 +00:00
2009-07-29 02:15:45 +00:00
private Dictionary < UUID , Queue < OSD > > queues = new Dictionary < UUID , Queue < OSD > > ( ) ;
2008-10-01 04:16:41 +00:00
private Dictionary < UUID , UUID > m_QueueUUIDAvatarMapping = new Dictionary < UUID , UUID > ( ) ;
private Dictionary < UUID , UUID > m_AvatarQueueUUIDMapping = new Dictionary < UUID , UUID > ( ) ;
2008-09-27 18:33:54 +00:00
2012-11-10 16:48:31 +00:00
#region INonSharedRegionModule methods
public virtual void Initialise ( IConfigSource config )
2008-09-27 09:42:31 +00:00
{
2012-11-10 16:48:31 +00:00
}
2008-09-27 23:06:28 +00:00
2012-11-10 16:48:31 +00:00
public void AddRegion ( Scene scene )
{
m_scene = scene ;
scene . RegisterModuleInterface < IEventQueue > ( this ) ;
scene . EventManager . OnClientClosed + = ClientClosed ;
scene . EventManager . OnMakeChildAgent + = MakeChildAgent ;
scene . EventManager . OnRegisterCaps + = OnRegisterCaps ;
MainConsole . Instance . Commands . AddCommand (
"Debug" ,
false ,
"debug eq" ,
"debug eq [0|1|2]" ,
"Turn on event queue debugging\n"
+ " <= 0 - turns off all event queue logging\n"
+ " >= 1 - turns on outgoing event logging\n"
+ " >= 2 - turns on poll notification" ,
HandleDebugEq ) ;
2008-09-27 09:42:31 +00:00
}
2012-11-10 16:48:31 +00:00
public void RemoveRegion ( Scene scene )
2008-09-27 09:42:31 +00:00
{
2012-11-10 16:48:31 +00:00
if ( m_scene ! = scene )
return ;
scene . EventManager . OnClientClosed - = ClientClosed ;
scene . EventManager . OnMakeChildAgent - = MakeChildAgent ;
scene . EventManager . OnRegisterCaps - = OnRegisterCaps ;
scene . UnregisterModuleInterface < IEventQueue > ( this ) ;
m_scene = null ;
2008-09-27 09:42:31 +00:00
}
2012-11-10 16:48:31 +00:00
public void RegionLoaded ( Scene scene )
2008-09-27 09:42:31 +00:00
{
}
2009-03-19 07:06:30 +00:00
public virtual void Close ( )
2008-09-27 09:42:31 +00:00
{
}
2009-03-19 07:06:30 +00:00
public virtual string Name
2008-09-27 09:42:31 +00:00
{
get { return "EventQueueGetModule" ; }
}
2012-11-10 16:48:31 +00:00
public Type ReplaceableInterface
2008-09-27 09:42:31 +00:00
{
2012-11-10 16:48:31 +00:00
get { return null ; }
2008-09-27 09:42:31 +00:00
}
2012-11-10 16:48:31 +00:00
2008-09-27 09:42:31 +00:00
# endregion
2011-11-24 20:27:11 +00:00
protected void HandleDebugEq ( string module , string [ ] args )
{
int debugLevel ;
if ( ! ( args . Length = = 3 & & int . TryParse ( args [ 2 ] , out debugLevel ) ) )
{
MainConsole . Instance . OutputFormat ( "Usage: debug eq [0|1]" ) ;
}
else
{
DebugLevel = debugLevel ;
MainConsole . Instance . OutputFormat (
"Set event queue debug level to {0} in {1}" , DebugLevel , m_scene . RegionInfo . RegionName ) ;
}
}
2008-12-19 20:31:32 +00:00
/// <summary>
/// Always returns a valid queue
/// </summary>
/// <param name="agentId"></param>
/// <returns></returns>
2009-07-29 02:15:45 +00:00
private Queue < OSD > TryGetQueue ( UUID agentId )
2008-09-27 09:42:31 +00:00
{
2008-10-10 13:46:43 +00:00
lock ( queues )
2008-09-27 18:33:54 +00:00
{
2008-10-10 13:46:43 +00:00
if ( ! queues . ContainsKey ( agentId ) )
{
2010-09-12 17:43:49 +00:00
/ *
2009-01-06 21:39:55 +00:00
m_log . DebugFormat (
"[EVENTQUEUE]: Adding new queue for agent {0} in region {1}" ,
agentId , m_scene . RegionInfo . RegionName ) ;
2010-08-30 01:28:31 +00:00
* /
2009-07-29 02:15:45 +00:00
queues [ agentId ] = new Queue < OSD > ( ) ;
2008-10-10 13:46:43 +00:00
}
2009-01-06 21:39:55 +00:00
2008-10-10 13:46:43 +00:00
return queues [ agentId ] ;
2008-09-27 18:33:54 +00:00
}
}
2008-09-27 09:42:31 +00:00
2008-12-19 20:31:32 +00:00
/// <summary>
/// May return a null queue
/// </summary>
/// <param name="agentId"></param>
/// <returns></returns>
2009-07-29 02:15:45 +00:00
private Queue < OSD > GetQueue ( UUID agentId )
2008-12-19 20:31:32 +00:00
{
lock ( queues )
{
if ( queues . ContainsKey ( agentId ) )
{
return queues [ agentId ] ;
}
else
return null ;
}
}
2008-09-27 18:33:54 +00:00
#region IEventQueue Members
2008-12-19 20:31:32 +00:00
2008-11-19 06:25:34 +00:00
public bool Enqueue ( OSD ev , UUID avatarID )
2008-09-27 18:33:54 +00:00
{
2009-01-06 21:39:55 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
2008-10-10 14:46:01 +00:00
try
{
2009-07-29 02:15:45 +00:00
Queue < OSD > queue = GetQueue ( avatarID ) ;
2008-12-19 20:31:32 +00:00
if ( queue ! = null )
2011-09-24 00:10:23 +00:00
lock ( queue )
queue . Enqueue ( ev ) ;
2009-01-06 21:39:55 +00:00
}
2011-09-24 00:10:23 +00:00
catch ( NullReferenceException e )
2008-10-10 14:46:01 +00:00
{
2009-01-06 21:39:55 +00:00
m_log . Error ( "[EVENTQUEUE] Caught exception: " + e ) ;
2008-10-10 14:46:01 +00:00
return false ;
}
2009-01-06 21:39:55 +00:00
2008-09-27 18:33:54 +00:00
return true ;
2008-09-27 09:42:31 +00:00
}
2008-12-19 20:31:32 +00:00
2008-09-27 09:42:31 +00:00
# endregion
2012-05-17 23:38:29 +00:00
private void ClientClosed ( UUID agentID , Scene scene )
2008-09-27 09:42:31 +00:00
{
2012-05-17 23:38:29 +00:00
// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
2008-12-22 06:10:36 +00:00
2008-12-24 05:05:22 +00:00
int count = 0 ;
2012-05-17 23:38:29 +00:00
while ( queues . ContainsKey ( agentID ) & & queues [ agentID ] . Count > 0 & & count + + < 5 )
2008-12-24 05:05:22 +00:00
{
2008-12-22 05:59:29 +00:00
Thread . Sleep ( 1000 ) ;
2008-12-24 05:05:22 +00:00
}
2008-12-22 05:59:29 +00:00
2008-10-10 13:46:43 +00:00
lock ( queues )
{
2012-05-17 23:38:29 +00:00
queues . Remove ( agentID ) ;
2008-10-10 13:46:43 +00:00
}
2011-10-24 22:16:03 +00:00
2008-10-03 09:53:49 +00:00
List < UUID > removeitems = new List < UUID > ( ) ;
lock ( m_AvatarQueueUUIDMapping )
{
foreach ( UUID ky in m_AvatarQueueUUIDMapping . Keys )
{
2011-10-24 22:16:03 +00:00
// m_log.DebugFormat("[EVENTQUEUE]: Found key {0} in m_AvatarQueueUUIDMapping while looking for {1}", ky, AgentID);
2012-05-17 23:38:29 +00:00
if ( ky = = agentID )
2008-10-03 09:53:49 +00:00
{
removeitems . Add ( ky ) ;
}
}
foreach ( UUID ky in removeitems )
{
2011-10-24 22:16:03 +00:00
UUID eventQueueGetUuid = m_AvatarQueueUUIDMapping [ ky ] ;
2008-10-03 09:53:49 +00:00
m_AvatarQueueUUIDMapping . Remove ( ky ) ;
2012-05-17 23:38:29 +00:00
string eqgPath = GenerateEqgCapPath ( eventQueueGetUuid ) ;
MainServer . Instance . RemovePollServiceHTTPHandler ( "" , eqgPath ) ;
2012-05-18 02:50:23 +00:00
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Removed EQG handler {0} for {1} in {2}",
// eqgPath, agentID, m_scene.RegionInfo.RegionName);
2011-10-24 22:16:03 +00:00
}
2008-10-03 09:53:49 +00:00
}
2011-10-24 22:16:03 +00:00
2008-10-03 09:53:49 +00:00
UUID searchval = UUID . Zero ;
removeitems . Clear ( ) ;
lock ( m_QueueUUIDAvatarMapping )
{
foreach ( UUID ky in m_QueueUUIDAvatarMapping . Keys )
{
searchval = m_QueueUUIDAvatarMapping [ ky ] ;
2012-05-17 23:38:29 +00:00
if ( searchval = = agentID )
2008-10-03 09:53:49 +00:00
{
removeitems . Add ( ky ) ;
}
}
foreach ( UUID ky in removeitems )
m_QueueUUIDAvatarMapping . Remove ( ky ) ;
}
2008-09-27 09:42:31 +00:00
}
private void MakeChildAgent ( ScenePresence avatar )
{
2008-10-03 09:53:49 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: Make Child agent {0} in region {1}.", avatar.UUID, m_scene.RegionInfo.RegionName);
//lock (m_ids)
// {
//if (m_ids.ContainsKey(avatar.UUID))
//{
2008-09-28 02:57:53 +00:00
// close the event queue.
2008-09-30 05:39:52 +00:00
//m_ids[avatar.UUID] = -1;
2008-10-03 09:53:49 +00:00
//}
//}
2008-09-27 09:42:31 +00:00
}
2008-09-27 18:33:54 +00:00
2012-05-17 23:38:29 +00:00
/// <summary>
/// Generate an Event Queue Get handler path for the given eqg uuid.
/// </summary>
/// <param name='eqgUuid'></param>
private string GenerateEqgCapPath ( UUID eqgUuid )
{
return string . Format ( "/CAPS/EQG/{0}/" , eqgUuid ) ;
}
2008-09-27 09:42:31 +00:00
public void OnRegisterCaps ( UUID agentID , Caps caps )
{
2009-01-06 21:39:55 +00:00
// Register an event queue for the client
2011-05-03 02:45:47 +00:00
2009-01-06 21:39:55 +00:00
//m_log.DebugFormat(
2011-05-03 02:45:47 +00:00
// "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
2009-01-06 21:39:55 +00:00
// agentID, caps, m_scene.RegionInfo.RegionName);
2008-12-19 23:58:13 +00:00
// Let's instantiate a Queue for this agent right now
TryGetQueue ( agentID ) ;
2012-05-17 23:38:29 +00:00
UUID eventQueueGetUUID ;
2008-10-01 04:16:41 +00:00
lock ( m_AvatarQueueUUIDMapping )
{
// Reuse open queues. The client does!
if ( m_AvatarQueueUUIDMapping . ContainsKey ( agentID ) )
{
2010-08-30 01:28:31 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
2012-05-17 23:38:29 +00:00
eventQueueGetUUID = m_AvatarQueueUUIDMapping [ agentID ] ;
2008-10-01 04:16:41 +00:00
}
else
{
2012-05-17 23:38:29 +00:00
eventQueueGetUUID = UUID . Random ( ) ;
2009-01-06 21:39:55 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
2008-10-01 04:16:41 +00:00
}
}
lock ( m_QueueUUIDAvatarMapping )
{
2012-05-17 23:38:29 +00:00
if ( ! m_QueueUUIDAvatarMapping . ContainsKey ( eventQueueGetUUID ) )
m_QueueUUIDAvatarMapping . Add ( eventQueueGetUUID , agentID ) ;
2008-10-01 04:16:41 +00:00
}
lock ( m_AvatarQueueUUIDMapping )
{
if ( ! m_AvatarQueueUUIDMapping . ContainsKey ( agentID ) )
2012-05-17 23:38:29 +00:00
m_AvatarQueueUUIDMapping . Add ( agentID , eventQueueGetUUID ) ;
2008-10-01 04:16:41 +00:00
}
2012-05-17 23:38:29 +00:00
string eventQueueGetPath = GenerateEqgCapPath ( eventQueueGetUUID ) ;
2008-10-03 09:53:49 +00:00
// Register this as a caps handler
2011-11-24 21:27:35 +00:00
// FIXME: Confusingly, we need to register separate as a capability so that the client is told about
// EventQueueGet when it receive capability information, but then we replace the rest handler immediately
// afterwards with the poll service. So for now, we'll pass a null instead to simplify code reading, but
// really it should be possible to directly register the poll handler as a capability.
2012-05-17 23:38:29 +00:00
caps . RegisterHandler ( "EventQueueGet" , new RestHTTPHandler ( "POST" , eventQueueGetPath , null ) ) ;
2011-11-24 21:27:35 +00:00
// delegate(Hashtable m_dhttpMethod)
// {
// return ProcessQueue(m_dhttpMethod, agentID, caps);
// }));
2011-05-03 02:45:47 +00:00
2008-10-03 09:53:49 +00:00
// This will persist this beyond the expiry of the caps handlers
2012-05-03 00:45:49 +00:00
// TODO: Add EventQueueGet name/description for diagnostics
2009-07-29 02:15:45 +00:00
MainServer . Instance . AddPollServiceHTTPHandler (
2012-05-17 23:38:29 +00:00
eventQueueGetPath ,
2012-07-06 19:51:18 +00:00
new PollServiceEventArgs ( null , HasEvents , GetEvents , NoEvents , agentID , 1000 ) ) ;
2008-10-03 09:53:49 +00:00
2012-05-18 02:50:23 +00:00
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Registered EQG handler {0} for {1} in {2}",
// eventQueueGetPath, agentID, m_scene.RegionInfo.RegionName);
2012-05-17 23:38:29 +00:00
2009-02-12 09:53:12 +00:00
Random rnd = new Random ( Environment . TickCount ) ;
2008-09-27 22:05:36 +00:00
lock ( m_ids )
{
if ( ! m_ids . ContainsKey ( agentID ) )
m_ids . Add ( agentID , rnd . Next ( 30000000 ) ) ;
}
2008-09-27 09:42:31 +00:00
}
2008-09-27 18:33:54 +00:00
2009-09-21 17:11:40 +00:00
public bool HasEvents ( UUID requestID , UUID agentID )
2009-07-29 02:15:45 +00:00
{
2009-08-11 23:47:36 +00:00
// Don't use this, because of race conditions at agent closing time
//Queue<OSD> queue = TryGetQueue(agentID);
2009-07-31 20:53:35 +00:00
2009-08-11 23:47:36 +00:00
Queue < OSD > queue = GetQueue ( agentID ) ;
if ( queue ! = null )
lock ( queue )
2011-09-24 00:10:23 +00:00
return queue . Count > 0 ;
2009-08-11 23:47:36 +00:00
return false ;
2009-07-29 02:15:45 +00:00
}
2012-05-18 02:43:36 +00:00
/// <summary>
/// Logs a debug line for an outbound event queue message if appropriate.
/// </summary>
/// <param name='element'>Element containing message</param>
private void LogOutboundDebugMessage ( OSD element , UUID agentId )
{
if ( element is OSDMap )
{
OSDMap ev = ( OSDMap ) element ;
m_log . DebugFormat (
"Eq OUT {0,-30} to {1,-20} {2,-20}" ,
ev [ "message" ] , m_scene . GetScenePresence ( agentId ) . Name , m_scene . RegionInfo . RegionName ) ;
}
}
2012-09-26 15:17:49 +00:00
public Hashtable GetEvents ( UUID requestID , UUID pAgentId )
2009-07-29 02:15:45 +00:00
{
2012-05-18 02:43:36 +00:00
if ( DebugLevel > = 2 )
m_log . DebugFormat ( "POLLED FOR EQ MESSAGES BY {0} in {1}" , pAgentId , m_scene . RegionInfo . RegionName ) ;
2011-11-24 21:27:35 +00:00
2009-07-29 02:15:45 +00:00
Queue < OSD > queue = TryGetQueue ( pAgentId ) ;
2009-07-31 20:53:35 +00:00
OSD element ;
lock ( queue )
{
if ( queue . Count = = 0 )
2009-09-21 17:11:40 +00:00
return NoEvents ( requestID , pAgentId ) ;
2009-07-31 20:53:35 +00:00
element = queue . Dequeue ( ) ; // 15s timeout
}
2009-07-29 02:15:45 +00:00
int thisID = 0 ;
lock ( m_ids )
thisID = m_ids [ pAgentId ] ;
OSDArray array = new OSDArray ( ) ;
if ( element = = null ) // didn't have an event in 15s
{
// Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
array . Add ( EventQueueHelper . KeepAliveEvent ( ) ) ;
2010-08-30 01:28:31 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", pAgentId, m_scene.RegionInfo.RegionName);
2009-07-29 02:15:45 +00:00
}
else
{
2012-05-18 02:43:36 +00:00
if ( DebugLevel > 0 )
LogOutboundDebugMessage ( element , pAgentId ) ;
2011-11-24 20:27:11 +00:00
2009-07-29 02:15:45 +00:00
array . Add ( element ) ;
2011-11-24 20:27:11 +00:00
2009-07-31 20:53:35 +00:00
lock ( queue )
2009-07-29 02:15:45 +00:00
{
2009-07-31 20:53:35 +00:00
while ( queue . Count > 0 )
{
2011-11-24 20:27:11 +00:00
element = queue . Dequeue ( ) ;
2012-05-18 02:43:36 +00:00
if ( DebugLevel > 0 )
LogOutboundDebugMessage ( element , pAgentId ) ;
2011-11-24 20:27:11 +00:00
array . Add ( element ) ;
2009-07-31 20:53:35 +00:00
thisID + + ;
}
2009-07-29 02:15:45 +00:00
}
}
OSDMap events = new OSDMap ( ) ;
events . Add ( "events" , array ) ;
events . Add ( "id" , new OSDInteger ( thisID ) ) ;
lock ( m_ids )
{
m_ids [ pAgentId ] = thisID + 1 ;
}
Hashtable responsedata = new Hashtable ( ) ;
responsedata [ "int_response_code" ] = 200 ;
responsedata [ "content_type" ] = "application/xml" ;
2009-07-30 18:16:00 +00:00
responsedata [ "keepalive" ] = false ;
responsedata [ "reusecontext" ] = false ;
2009-07-29 02:15:45 +00:00
responsedata [ "str_response_string" ] = OSDParser . SerializeLLSDXmlString ( events ) ;
2010-08-30 01:28:31 +00:00
//m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
2009-07-29 02:15:45 +00:00
return responsedata ;
}
2009-09-21 17:11:40 +00:00
public Hashtable NoEvents ( UUID requestID , UUID agentID )
2009-07-29 02:15:45 +00:00
{
Hashtable responsedata = new Hashtable ( ) ;
responsedata [ "int_response_code" ] = 502 ;
responsedata [ "content_type" ] = "text/plain" ;
2009-07-30 18:16:00 +00:00
responsedata [ "keepalive" ] = false ;
responsedata [ "reusecontext" ] = false ;
2009-07-29 02:15:45 +00:00
responsedata [ "str_response_string" ] = "Upstream error: " ;
responsedata [ "error_status_text" ] = "Upstream error:" ;
responsedata [ "http_protocol_version" ] = "HTTP/1.0" ;
return responsedata ;
}
2011-11-24 21:27:35 +00:00
// public Hashtable ProcessQueue(Hashtable request, UUID agentID, Caps caps)
// {
// // TODO: this has to be redone to not busy-wait (and block the thread),
// // TODO: as soon as we have a non-blocking way to handle HTTP-requests.
/ /
//// if (m_log.IsDebugEnabled)
//// {
//// String debug = "[EVENTQUEUE]: Got request for agent {0} in region {1} from thread {2}: [ ";
//// foreach (object key in request.Keys)
//// {
//// debug += key.ToString() + "=" + request[key].ToString() + " ";
//// }
//// m_log.DebugFormat(debug + " ]", agentID, m_scene.RegionInfo.RegionName, System.Threading.Thread.CurrentThread.Name);
//// }
/ /
// Queue<OSD> queue = TryGetQueue(agentID);
// OSD element;
/ /
// lock (queue)
// element = queue.Dequeue(); // 15s timeout
/ /
// Hashtable responsedata = new Hashtable();
/ /
// int thisID = 0;
// lock (m_ids)
// thisID = m_ids[agentID];
/ /
// if (element == null)
// {
// //m_log.ErrorFormat("[EVENTQUEUE]: Nothing to process in " + m_scene.RegionInfo.RegionName);
// if (thisID == -1) // close-request
2008-10-08 17:56:37 +00:00
// {
2011-11-24 21:27:35 +00:00
// m_log.ErrorFormat("[EVENTQUEUE]: 404 in " + m_scene.RegionInfo.RegionName);
// responsedata["int_response_code"] = 404; //501; //410; //404;
// responsedata["content_type"] = "text/plain";
// responsedata["keepalive"] = false;
// responsedata["str_response_string"] = "Closed EQG";
// return responsedata;
2008-10-08 17:56:37 +00:00
// }
2011-11-24 21:27:35 +00:00
// responsedata["int_response_code"] = 502;
// responsedata["content_type"] = "text/plain";
// responsedata["keepalive"] = false;
// responsedata["str_response_string"] = "Upstream error: ";
// responsedata["error_status_text"] = "Upstream error:";
// responsedata["http_protocol_version"] = "HTTP/1.0";
// return responsedata;
2008-10-08 17:56:37 +00:00
// }
2011-11-24 21:27:35 +00:00
/ /
// OSDArray array = new OSDArray();
// if (element == null) // didn't have an event in 15s
// {
// // Send it a fake event to keep the client polling! It doesn't like 502s like the proxys say!
// array.Add(EventQueueHelper.KeepAliveEvent());
// //m_log.DebugFormat("[EVENTQUEUE]: adding fake event for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
// }
// else
// {
// array.Add(element);
/ /
// if (element is OSDMap)
// {
// OSDMap ev = (OSDMap)element;
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
// ev["message"], m_scene.GetScenePresence(agentID).Name);
// }
/ /
// lock (queue)
// {
// while (queue.Count > 0)
// {
// element = queue.Dequeue();
/ /
// if (element is OSDMap)
// {
// OSDMap ev = (OSDMap)element;
// m_log.DebugFormat(
// "[EVENT QUEUE GET MODULE]: Eq OUT {0} to {1}",
// ev["message"], m_scene.GetScenePresence(agentID).Name);
// }
/ /
// array.Add(element);
// thisID++;
// }
// }
// }
/ /
// OSDMap events = new OSDMap();
// events.Add("events", array);
/ /
// events.Add("id", new OSDInteger(thisID));
// lock (m_ids)
// {
// m_ids[agentID] = thisID + 1;
// }
/ /
// responsedata["int_response_code"] = 200;
// responsedata["content_type"] = "application/xml";
// responsedata["keepalive"] = false;
// responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
/ /
// m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", agentID, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
/ /
// return responsedata;
// }
2008-10-03 09:53:49 +00:00
2011-11-24 21:27:35 +00:00
// public Hashtable EventQueuePath2(Hashtable request)
// {
// string capuuid = (string)request["uri"]; //path.Replace("/CAPS/EQG/","");
// // pull off the last "/" in the path.
// Hashtable responsedata = new Hashtable();
// capuuid = capuuid.Substring(0, capuuid.Length - 1);
// capuuid = capuuid.Replace("/CAPS/EQG/", "");
// UUID AvatarID = UUID.Zero;
// UUID capUUID = UUID.Zero;
/ /
// // parse the path and search for the avatar with it registered
// if (UUID.TryParse(capuuid, out capUUID))
// {
// lock (m_QueueUUIDAvatarMapping)
// {
// if (m_QueueUUIDAvatarMapping.ContainsKey(capUUID))
// {
// AvatarID = m_QueueUUIDAvatarMapping[capUUID];
// }
// }
//
// if (AvatarID != UUID.Zero)
// {
// return ProcessQueue(request, AvatarID, m_scene.CapsModule.GetCapsForUser(AvatarID));
// }
// else
// {
// responsedata["int_response_code"] = 404;
// responsedata["content_type"] = "text/plain";
// responsedata["keepalive"] = false;
// responsedata["str_response_string"] = "Not Found";
// responsedata["error_status_text"] = "Not Found";
// responsedata["http_protocol_version"] = "HTTP/1.0";
// return responsedata;
// // return 404
// }
// }
// else
// {
// responsedata["int_response_code"] = 404;
// responsedata["content_type"] = "text/plain";
// responsedata["keepalive"] = false;
// responsedata["str_response_string"] = "Not Found";
// responsedata["error_status_text"] = "Not Found";
// responsedata["http_protocol_version"] = "HTTP/1.0";
// return responsedata;
// // return 404
// }
// }
2008-10-03 09:53:49 +00:00
2008-11-19 06:25:34 +00:00
public OSD EventQueueFallBack ( string path , OSD request , string endpoint )
2008-10-01 04:16:41 +00:00
{
// This is a fallback element to keep the client from loosing EventQueueGet
// Why does CAPS fail sometimes!?
m_log . Warn ( "[EVENTQUEUE]: In the Fallback handler! We lost the Queue in the rest handler!" ) ;
string capuuid = path . Replace ( "/CAPS/EQG/" , "" ) ;
capuuid = capuuid . Substring ( 0 , capuuid . Length - 1 ) ;
2008-10-03 14:18:17 +00:00
// UUID AvatarID = UUID.Zero;
2008-10-01 04:16:41 +00:00
UUID capUUID = UUID . Zero ;
if ( UUID . TryParse ( capuuid , out capUUID ) )
{
2008-10-03 09:53:49 +00:00
/ * Don ' t remove this yet code cleaners !
* Still testing this !
*
2008-10-01 04:16:41 +00:00
lock ( m_QueueUUIDAvatarMapping )
{
if ( m_QueueUUIDAvatarMapping . ContainsKey ( capUUID ) )
{
AvatarID = m_QueueUUIDAvatarMapping [ capUUID ] ;
}
}
2008-10-03 09:53:49 +00:00
2008-10-01 04:16:41 +00:00
if ( AvatarID ! = UUID . Zero )
{
2008-10-03 09:53:49 +00:00
// Repair the CAP!
2009-06-18 14:33:35 +00:00
//OpenSim.Framework.Capabilities.Caps caps = m_scene.GetCapsHandlerForUser(AvatarID);
2008-10-03 09:53:49 +00:00
//string capsBase = "/CAPS/EQG/";
//caps.RegisterHandler("EventQueueGet",
//new RestHTTPHandler("POST", capsBase + capUUID.ToString() + "/",
//delegate(Hashtable m_dhttpMethod)
//{
// return ProcessQueue(m_dhttpMethod, AvatarID, caps);
//}));
// start new ID sequence.
Random rnd = new Random ( System . Environment . TickCount ) ;
lock ( m_ids )
{
if ( ! m_ids . ContainsKey ( AvatarID ) )
m_ids . Add ( AvatarID , rnd . Next ( 30000000 ) ) ;
}
2008-10-01 04:16:41 +00:00
int thisID = 0 ;
lock ( m_ids )
thisID = m_ids [ AvatarID ] ;
BlockingLLSDQueue queue = GetQueue ( AvatarID ) ;
2008-11-19 06:25:34 +00:00
OSDArray array = new OSDArray ( ) ;
2008-10-01 04:16:41 +00:00
LLSD element = queue . Dequeue ( 15000 ) ; // 15s timeout
if ( element = = null )
{
array . Add ( EventQueueHelper . KeepAliveEvent ( ) ) ;
}
else
{
array . Add ( element ) ;
while ( queue . Count ( ) > 0 )
{
array . Add ( queue . Dequeue ( 1 ) ) ;
thisID + + ;
}
}
2008-11-19 06:25:34 +00:00
OSDMap events = new OSDMap ( ) ;
2008-10-01 04:16:41 +00:00
events . Add ( "events" , array ) ;
events . Add ( "id" , new LLSDInteger ( thisID ) ) ;
lock ( m_ids )
{
m_ids [ AvatarID ] = thisID + 1 ;
}
return events ;
}
else
{
return new LLSD ( ) ;
}
2008-10-03 09:53:49 +00:00
*
* /
2008-10-01 04:16:41 +00:00
}
else
{
2008-10-03 09:53:49 +00:00
//return new LLSD();
2008-10-01 04:16:41 +00:00
}
2009-01-06 21:39:55 +00:00
2008-11-19 06:25:34 +00:00
return new OSDString ( "shutdown404!" ) ;
2008-10-01 04:16:41 +00:00
}
2009-02-06 16:55:34 +00:00
public void DisableSimulator ( ulong handle , UUID avatarID )
{
OSD item = EventQueueHelper . DisableSimulator ( handle ) ;
Enqueue ( item , avatarID ) ;
}
2009-03-19 07:06:30 +00:00
public virtual void EnableSimulator ( ulong handle , IPEndPoint endPoint , UUID avatarID )
2009-02-06 16:55:34 +00:00
{
OSD item = EventQueueHelper . EnableSimulator ( handle , endPoint ) ;
Enqueue ( item , avatarID ) ;
}
2009-03-19 07:06:30 +00:00
public virtual void EstablishAgentCommunication ( UUID avatarID , IPEndPoint endPoint , string capsPath )
2009-02-06 16:55:34 +00:00
{
OSD item = EventQueueHelper . EstablishAgentCommunication ( avatarID , endPoint . ToString ( ) , capsPath ) ;
Enqueue ( item , avatarID ) ;
}
2009-03-19 07:06:30 +00:00
public virtual void TeleportFinishEvent ( ulong regionHandle , byte simAccess ,
2009-02-06 16:55:34 +00:00
IPEndPoint regionExternalEndPoint ,
uint locationID , uint flags , string capsURL ,
UUID avatarID )
{
OSD item = EventQueueHelper . TeleportFinishEvent ( regionHandle , simAccess , regionExternalEndPoint ,
locationID , flags , capsURL , avatarID ) ;
Enqueue ( item , avatarID ) ;
}
2009-03-19 07:06:30 +00:00
public virtual void CrossRegion ( ulong handle , Vector3 pos , Vector3 lookAt ,
2009-02-06 16:55:34 +00:00
IPEndPoint newRegionExternalEndPoint ,
string capsURL , UUID avatarID , UUID sessionID )
{
OSD item = EventQueueHelper . CrossRegion ( handle , pos , lookAt , newRegionExternalEndPoint ,
capsURL , avatarID , sessionID ) ;
Enqueue ( item , avatarID ) ;
}
public void ChatterboxInvitation ( UUID sessionID , string sessionName ,
UUID fromAgent , string message , UUID toAgent , string fromName , byte dialog ,
uint timeStamp , bool offline , int parentEstateID , Vector3 position ,
uint ttl , UUID transactionID , bool fromGroup , byte [ ] binaryBucket )
{
OSD item = EventQueueHelper . ChatterboxInvitation ( sessionID , sessionName , fromAgent , message , toAgent , fromName , dialog ,
timeStamp , offline , parentEstateID , position , ttl , transactionID ,
fromGroup , binaryBucket ) ;
Enqueue ( item , toAgent ) ;
2009-07-05 07:17:12 +00:00
//m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
2009-02-06 16:55:34 +00:00
}
public void ChatterBoxSessionAgentListUpdates ( UUID sessionID , UUID fromAgent , UUID toAgent , bool canVoiceChat ,
bool isModerator , bool textMute )
{
OSD item = EventQueueHelper . ChatterBoxSessionAgentListUpdates ( sessionID , fromAgent , canVoiceChat ,
isModerator , textMute ) ;
Enqueue ( item , toAgent ) ;
2009-07-05 07:17:12 +00:00
//m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
2009-02-06 16:55:34 +00:00
}
2010-08-30 01:28:31 +00:00
public void ParcelProperties ( ParcelPropertiesMessage parcelPropertiesMessage , UUID avatarID )
2009-02-06 16:55:34 +00:00
{
2010-09-12 17:43:49 +00:00
OSD item = EventQueueHelper . ParcelProperties ( parcelPropertiesMessage ) ;
2009-02-06 16:55:34 +00:00
Enqueue ( item , avatarID ) ;
}
public void GroupMembership ( AgentGroupDataUpdatePacket groupUpdate , UUID avatarID )
{
OSD item = EventQueueHelper . GroupMembership ( groupUpdate ) ;
Enqueue ( item , avatarID ) ;
}
2011-11-24 20:27:11 +00:00
2009-12-31 03:45:10 +00:00
public void QueryReply ( PlacesReplyPacket groupUpdate , UUID avatarID )
{
OSD item = EventQueueHelper . PlacesQuery ( groupUpdate ) ;
Enqueue ( item , avatarID ) ;
}
2011-04-30 16:24:15 +00:00
public OSD ScriptRunningEvent ( UUID objectID , UUID itemID , bool running , bool mono )
{
return EventQueueHelper . ScriptRunningReplyEvent ( objectID , itemID , running , mono ) ;
}
public OSD BuildEvent ( string eventName , OSD eventBody )
{
return EventQueueHelper . BuildEvent ( eventName , eventBody ) ;
}
2012-03-15 02:24:13 +00:00
public void partPhysicsProperties ( uint localID , byte physhapetype ,
float density , float friction , float bounce , float gravmod , UUID avatarID )
{
OSD item = EventQueueHelper . partPhysicsProperties ( localID , physhapetype ,
density , friction , bounce , gravmod ) ;
Enqueue ( item , avatarID ) ;
}
2008-09-27 09:42:31 +00:00
}
}