From 530cc2488461a4ef68a06eaba42698fcdc09f459 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Tue, 19 Feb 2008 19:16:21 +0000 Subject: [PATCH] From: Michael Osias This patch implements the llSendRemoteData command and fixes mantis 552, and possibly 586. --- .../Environment/Interfaces/IHttpRequests.cs | 2 + .../Environment/Interfaces/IWorldComm.cs | 5 +- .../Region/Environment/Interfaces/IXMLRPC.cs | 13 +- .../Modules/ScriptsHttpRequests.cs | 31 +- .../Environment/Modules/WorldCommModule.cs | 72 ++- .../Environment/Modules/XMLRPCModule.cs | 524 +++++++++++++----- .../ScriptEngine/Common/LSL_BaseClass.cs | 4 + .../Common/LSL_BuiltIn_Commands.cs | 4 +- .../AsyncLSLCommandManager.cs | 106 +++- .../Common/ScriptEngineBase/ScriptManager.cs | 54 +- 10 files changed, 597 insertions(+), 218 deletions(-) diff --git a/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs b/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs index 6aa8f357e7..946abef6e3 100644 --- a/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs +++ b/OpenSim/Region/Environment/Interfaces/IHttpRequests.cs @@ -38,5 +38,7 @@ namespace OpenSim.Region.Environment.Interfaces LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List parameters, string body); void StopHttpRequest(uint m_localID, LLUUID m_itemID); HttpRequestClass GetNextCompletedRequest(); + void RemoveCompletedRequest(LLUUID id); + } } \ No newline at end of file diff --git a/OpenSim/Region/Environment/Interfaces/IWorldComm.cs b/OpenSim/Region/Environment/Interfaces/IWorldComm.cs index 7567bb2e06..89c3d6f3e2 100644 --- a/OpenSim/Region/Environment/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Environment/Interfaces/IWorldComm.cs @@ -41,5 +41,8 @@ namespace OpenSim.Region.Environment.Interfaces void ListenControl(int handle, int active); void ListenRemove(int handle); void DeleteListener(LLUUID itemID); + uint PeekNextMessageLocalID(); + LLUUID PeekNextMessageItemID(); + } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs b/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs index 82b692d40f..4d22df587c 100644 --- a/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs +++ b/OpenSim/Region/Environment/Interfaces/IXMLRPC.cs @@ -28,6 +28,8 @@ using libsecondlife; using OpenSim.Region.Environment.Modules; +using System.Collections; +using System.Collections.Generic; namespace OpenSim.Region.Environment.Interfaces { @@ -36,9 +38,14 @@ namespace OpenSim.Region.Environment.Interfaces LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID); void CloseXMLRPCChannel(LLUUID channelKey); bool hasRequests(); - RPCRequestInfo GetNextRequest(); void RemoteDataReply(string channel, string message_id, string sdata, int idata); bool IsEnabled(); - void DeleteChannel(LLUUID itemID); + RPCRequestInfo GetNextCompletedRequest(); + void RemoveCompletedRequest(LLUUID id); + void DeleteChannels(LLUUID itemID); + LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata); + SendRemoteDataRequest GetNextCompletedSRDRequest(); + void RemoveCompletedSRDRequest(LLUUID id); + void CancelSRDRequests(LLUUID itemID); } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs b/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs index e3de13b82b..f38f35489a 100644 --- a/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs +++ b/OpenSim/Region/Environment/Modules/ScriptsHttpRequests.cs @@ -184,13 +184,15 @@ namespace OpenSim.Region.Environment.Modules public void StopHttpRequest(uint m_localID, LLUUID m_itemID) { - lock (HttpListLock) - { - HttpRequestClass tmpReq; - if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) + if(m_pendingRequests != null) { + lock (HttpListLock) { - tmpReq.Stop(); - m_pendingRequests.Remove(m_itemID); + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq)) + { + tmpReq.Stop(); + m_pendingRequests.Remove(m_itemID); + } } } } @@ -216,7 +218,6 @@ namespace OpenSim.Region.Environment.Modules { if (tmpReq.finished) { - m_pendingRequests.Remove(luid); return tmpReq; } } @@ -224,6 +225,21 @@ namespace OpenSim.Region.Environment.Modules } return null; } + + public void RemoveCompletedRequest(LLUUID id) + { + lock (HttpListLock) + { + HttpRequestClass tmpReq; + if (m_pendingRequests.TryGetValue(id, out tmpReq)) + { + tmpReq.Stop(); + tmpReq = null; + m_pendingRequests.Remove(id); + } + } + } + } // @@ -269,6 +285,7 @@ namespace OpenSim.Region.Environment.Modules httpThread.Name = "HttpRequestThread"; httpThread.Priority = ThreadPriority.BelowNormal; httpThread.IsBackground = true; + finished = false; httpThread.Start(); } diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs index a426eda580..b6d4e3d6cf 100644 --- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs +++ b/OpenSim/Region/Environment/Modules/WorldCommModule.cs @@ -84,8 +84,8 @@ namespace OpenSim.Region.Environment.Modules m_scene = scene; m_scene.RegisterModuleInterface(this); m_listenerManager = new ListenerManager(); - m_pending = new Queue(); m_scene.EventManager.OnNewClient += NewClient; + m_pending = new Queue(); } public void PostInitialise() @@ -139,9 +139,12 @@ namespace OpenSim.Region.Environment.Modules public void DeleteListener(LLUUID itemID) { - lock (ListLock) + if (m_listenerManager != null) { - m_listenerManager.DeleteListener(itemID); + lock (ListLock) + { + m_listenerManager.DeleteListener(itemID); + } } } @@ -167,14 +170,14 @@ namespace OpenSim.Region.Environment.Modules // If they are in proximity, then if they are // listeners, if so add them to the pending queue - foreach (LLUUID eb in m_scene.Entities.Keys) + foreach (ListenerInfo li in m_listenerManager.GetListeners()) { EntityBase sPart; - m_scene.Entities.TryGetValue(eb, out sPart); + m_scene.Entities.TryGetValue(li.GetHostID(), out sPart); // Dont process if this message is from itself! - if (eb.ToString().Equals(sourceItemID) || + if (li.GetHostID().ToString().Equals(sourceItemID) || sPart.UUID.ToString().Equals(sourceItemID)) continue; @@ -196,7 +199,10 @@ namespace OpenSim.Region.Environment.Modules ); if (isListener != null) { - m_pending.Enqueue(isListener); + lock (CommListLock) + { + m_pending.Enqueue(isListener); + } } } break; @@ -210,7 +216,10 @@ namespace OpenSim.Region.Environment.Modules ); if (isListener != null) { - m_pending.Enqueue(isListener); + lock (CommListLock) + { + m_pending.Enqueue(isListener); + } } } break; @@ -223,14 +232,17 @@ namespace OpenSim.Region.Environment.Modules ); if (isListener != null) { - m_pending.Enqueue(isListener); + lock (CommListLock) + { + m_pending.Enqueue(isListener); + } } } break; case ChatTypeEnum.Broadcast: ListenerInfo isListen = - m_listenerManager.IsListenerMatch(sourceItemID, eb, channel, name, msg); + m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg); if (isListen != null) { ListenerInfo isListener = m_listenerManager.IsListenerMatch( @@ -238,19 +250,24 @@ namespace OpenSim.Region.Environment.Modules ); if (isListener != null) { - m_pending.Enqueue(isListener); + lock (CommListLock) + { + m_pending.Enqueue(isListener); + } } } break; } } - ; } } public bool HasMessages() { - return (m_pending.Count > 0); + if (m_pending != null) + return (m_pending.Count > 0); + else + return false; } public ListenerInfo GetNextMessage() @@ -264,6 +281,17 @@ namespace OpenSim.Region.Environment.Modules return li; } + + public uint PeekNextMessageLocalID() + { + return m_pending.Peek().GetLocalID(); + } + + public LLUUID PeekNextMessageItemID() + { + return m_pending.Peek().GetItemID(); + } + } // hostID: the ID of the ScenePart @@ -280,8 +308,7 @@ namespace OpenSim.Region.Environment.Modules m_listeners = new Dictionary(); } - public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, - string msg) + public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg) { if (m_listeners.Count < m_MaxListeners) { @@ -410,6 +437,11 @@ namespace OpenSim.Region.Environment.Modules } return null; } + + public Dictionary.ValueCollection GetListeners() + { + return m_listeners.Values; + } } public class ListenerInfo @@ -425,21 +457,20 @@ namespace OpenSim.Region.Environment.Modules private string m_message; // The message private bool m_active; // Listener is active or not - public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, - string message) + public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message) { Initialise(localID, handle, ItemID, hostID, channel, name, id, message); } public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, - string message, LLUUID sourceItemID) + string message, LLUUID sourceItemID) { Initialise(localID, handle, ItemID, hostID, channel, name, id, message); m_sourceItemID = sourceItemID; } private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, - LLUUID id, string message) + LLUUID id, string message) { m_handle = handle; m_channel = channel; @@ -511,5 +542,6 @@ namespace OpenSim.Region.Environment.Modules { return m_id; } + } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/XMLRPCModule.cs index edd1df80e2..48a4c7c41c 100644 --- a/OpenSim/Region/Environment/Modules/XMLRPCModule.cs +++ b/OpenSim/Region/Environment/Modules/XMLRPCModule.cs @@ -78,19 +78,20 @@ namespace OpenSim.Region.Environment.Modules private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - private Queue rpcQueue = new Queue(); private object XMLRPCListLock = new object(); private string m_name = "XMLRPCModule"; private int RemoteReplyScriptWait = 300; - private int RemoteReplyScriptTimeout = 900; + private int RemoteReplyScriptTimeout = 9000; private int m_remoteDataPort = 0; private List m_scenes = new List(); // private Dictionary m_openChannels; - // - private Dictionary m_pendingResponse; + private Dictionary m_rpcPending; + private Dictionary m_rpcPendingResponses; + + private Dictionary m_pendingSRDResponses; public void Initialise(Scene scene, IConfigSource config) { @@ -115,13 +116,15 @@ namespace OpenSim.Region.Environment.Modules if (IsEnabled()) { m_openChannels = new Dictionary(); - m_pendingResponse = new Dictionary(); + m_rpcPending = new Dictionary(); + m_rpcPendingResponses = new Dictionary(); + m_pendingSRDResponses = new Dictionary(); // Start http server // Attach xmlrpc handlers m_log.Info("[REMOTE_DATA]: " + "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); - BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); + BaseHttpServer httpServer = new BaseHttpServer((uint)m_remoteDataPort); httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); httpServer.Start(); } @@ -188,18 +191,28 @@ namespace OpenSim.Region.Environment.Modules return channel; } - public void DeleteChannel(LLUUID itemID) + // Delete channels based on itemID + // for when a script is deleted + public void DeleteChannels(LLUUID itemID) { - foreach (RPCChannelInfo li in m_openChannels.Values) + if (m_openChannels != null) { + ArrayList tmp = new ArrayList(); - if (li.GetItemID().Equals(itemID)) + lock (XMLRPCListLock) { + foreach (RPCChannelInfo li in m_openChannels.Values) + { + if (li.GetItemID().Equals(itemID)) + { + tmp.Add(itemID); + } + } - m_openChannels.Remove(li.GetChannelID()); - return; - + System.Collections.IEnumerator tmpEnumerator = tmp.GetEnumerator(); + while ( tmpEnumerator.MoveNext() ) + m_openChannels.Remove((LLUUID)tmpEnumerator.Current); } } @@ -218,15 +231,12 @@ namespace OpenSim.Region.Environment.Modules RPCRequestInfo rpcInfo; LLUUID message_key = new LLUUID(message_id); - if (m_pendingResponse.TryGetValue(message_key, out rpcInfo)) + if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) { - rpcInfo.SetRetval(sdata); + rpcInfo.SetStrRetval(sdata); + rpcInfo.SetIntRetval(idata); rpcInfo.SetProcessed(true); - - lock (XMLRPCListLock) - { - m_pendingResponse.Remove(message_key); - } + m_rpcPendingResponses.Remove(message_key); } } @@ -248,18 +258,18 @@ namespace OpenSim.Region.Environment.Modules { XmlRpcResponse response = new XmlRpcResponse(); - Hashtable requestData = (Hashtable) request.Params[0]; + Hashtable requestData = (Hashtable)request.Params[0]; bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && requestData.Contains("StringValue")); if (GoodXML) { - LLUUID channel = new LLUUID((string) requestData["Channel"]); + LLUUID channel = new LLUUID((string)requestData["Channel"]); RPCChannelInfo rpcChanInfo; if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) { - string intVal = (string) requestData["IntValue"]; - string strVal = (string) requestData["StringValue"]; + string intVal = (string)requestData["IntValue"]; + string strVal = (string)requestData["StringValue"]; RPCRequestInfo rpcInfo; @@ -268,7 +278,7 @@ namespace OpenSim.Region.Environment.Modules rpcInfo = new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, intVal); - rpcQueue.Enqueue(rpcInfo); + m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); } int timeoutCtr = 0; @@ -280,16 +290,20 @@ namespace OpenSim.Region.Environment.Modules } if (rpcInfo.IsProcessed()) { - response.Value = rpcInfo.GetRetval(); + Hashtable param = new Hashtable(); + param["StringValue"] = rpcInfo.GetStrRetval(); + param["IntValue"] = Convert.ToString(rpcInfo.GetIntRetval()); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + + response.Value = parameters; rpcInfo = null; } else { response.SetFault(-1, "Script timeout"); - lock (XMLRPCListLock) - { - m_pendingResponse.Remove(rpcInfo.GetMessageID()); - } + rpcInfo = null; } } else @@ -303,129 +317,365 @@ namespace OpenSim.Region.Environment.Modules public bool hasRequests() { - return (rpcQueue.Count > 0); + lock (XMLRPCListLock) + { + if (m_rpcPending != null) + return (m_rpcPending.Count > 0); + else + return false; + } } - public RPCRequestInfo GetNextRequest() + public RPCRequestInfo GetNextCompletedRequest() + { + if (m_rpcPending != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_rpcPending.Keys) + { + RPCRequestInfo tmpReq; + + if (m_rpcPending.TryGetValue(luid, out tmpReq)) + { + + if (!tmpReq.IsProcessed()) return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedRequest(LLUUID id) { lock (XMLRPCListLock) { - RPCRequestInfo rpcInfo = rpcQueue.Dequeue(); - m_pendingResponse.Add(rpcInfo.GetMessageID(), rpcInfo); - return rpcInfo; + RPCRequestInfo tmp; + if (m_rpcPending.TryGetValue(id, out tmp)) + { + m_rpcPending.Remove(id); + m_rpcPendingResponses.Add(id, tmp); + } + else + { + Console.WriteLine("UNABLE TO REMOVE COMPLETED REQUEST"); + } + } + } + + public LLUUID SendRemoteData(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + + SendRemoteDataRequest req = new SendRemoteDataRequest( + localID, itemID, channel, dest, idata, sdata + ); + m_pendingSRDResponses.Add(req.GetReqID(), req); + return req.process(); + + } + + public SendRemoteDataRequest GetNextCompletedSRDRequest() + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (LLUUID luid in m_pendingSRDResponses.Keys) + { + SendRemoteDataRequest tmpReq; + + if (m_pendingSRDResponses.TryGetValue(luid, out tmpReq)) + { + if (tmpReq.finished) + return tmpReq; + } + } + } + } + return null; + } + + public void RemoveCompletedSRDRequest(LLUUID id) + { + lock (XMLRPCListLock) + { + SendRemoteDataRequest tmpReq; + if (m_pendingSRDResponses.TryGetValue(id, out tmpReq)) + { + m_pendingSRDResponses.Remove(id); + } + } + } + + public void CancelSRDRequests(LLUUID itemID) + { + if (m_pendingSRDResponses != null) + { + lock (XMLRPCListLock) + { + foreach (SendRemoteDataRequest li in m_pendingSRDResponses.Values) + { + if (li.m_itemID.Equals(itemID)) + m_pendingSRDResponses.Remove(li.GetReqID()); + } + } } } } + /************************************************************** + * + * Class RPCRequestInfo + * + * Holds details about incoming requests until they are picked + * from the queue by LSLLongCmdHandler + * ***********************************************************/ - /************************************************************** - * - * Class RPCRequestInfo - * - * Holds details about incoming requests until they are picked - * from the queue by LSLLongCmdHandler - * ***********************************************************/ - - public class RPCRequestInfo - { - private string m_StrVal; - private string m_IntVal; - private bool m_processed; - private string m_resp; - private uint m_localID; - private LLUUID m_ItemID; - private LLUUID m_MessageID; - private LLUUID m_ChannelKey; - - public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) + public class RPCRequestInfo { - m_localID = localID; - m_StrVal = strVal; - m_IntVal = intVal; - m_ItemID = itemID; - m_ChannelKey = channelKey; - m_MessageID = LLUUID.Random(); - m_processed = false; - m_resp = String.Empty; + private string m_StrVal; + private string m_IntVal; + private bool m_processed; + private string m_respStr; + private int m_respInt; + private uint m_localID; + private LLUUID m_ItemID; + private LLUUID m_MessageID; + private LLUUID m_ChannelKey; + + public RPCRequestInfo(uint localID, LLUUID itemID, LLUUID channelKey, string strVal, string intVal) + { + m_localID = localID; + m_StrVal = strVal; + m_IntVal = intVal; + m_ItemID = itemID; + m_ChannelKey = channelKey; + m_MessageID = LLUUID.Random(); + m_processed = false; + m_respStr = String.Empty; + m_respInt = 0; + } + + public bool IsProcessed() + { + return m_processed; + } + + public LLUUID GetChannelKey() + { + return m_ChannelKey; + } + + public void SetProcessed(bool processed) + { + m_processed = processed; + } + + public void SetStrRetval(string resp) + { + m_respStr = resp; + } + + public string GetStrRetval() + { + return m_respStr; + } + public void SetIntRetval(int resp) + { + m_respInt = resp; + } + + public int GetIntRetval() + { + return m_respInt; + } + public uint GetLocalID() + { + return m_localID; + } + + public LLUUID GetItemID() + { + return m_ItemID; + } + + public string GetStrVal() + { + return m_StrVal; + } + + public int GetIntValue() + { + return int.Parse(m_IntVal); + } + + public LLUUID GetMessageID() + { + return m_MessageID; + } } - public bool IsProcessed() + public class RPCChannelInfo { - return m_processed; + private LLUUID m_itemID; + private uint m_localID; + private LLUUID m_ChannelKey; + + public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) + { + m_ChannelKey = channelID; + m_localID = localID; + m_itemID = itemID; + } + + public LLUUID GetItemID() + { + return m_itemID; + } + + public LLUUID GetChannelID() + { + return m_ChannelKey; + } + + public uint GetLocalID() + { + return m_localID; + } + } - public LLUUID GetChannelKey() + public class SendRemoteDataRequest { - return m_ChannelKey; + + public LLUUID reqID; + public string destURL; + public string channel; + public string sdata; + public int idata; + public bool finished; + public string response_sdata; + public int response_idata; + public XmlRpcRequest request; + private Thread httpThread; + public LLUUID m_itemID; + public uint m_localID; + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + + this.channel = channel; + this.destURL = dest; + this.idata = idata; + this.sdata = sdata; + m_itemID = itemID; + m_localID = localID; + + reqID = LLUUID.Random(); + + } + + public LLUUID process() + { + httpThread = new Thread(SendRequest); + httpThread.Name = "HttpRequestThread"; + httpThread.Priority = ThreadPriority.BelowNormal; + httpThread.IsBackground = true; + finished = false; + httpThread.Start(); + + return reqID; + + } + + /* + * TODO: More work on the response codes. Right now + * returning 200 for success or 499 for exception + */ + + public void SendRequest() + { + + Hashtable param = new Hashtable(); + + // Check if channel is an LLUUID + // if not, use as method name + LLUUID parseUID; + string mName = "llRemoteData"; + if( (channel != null) && (channel != "") ) + if( !LLUUID.TryParse(channel, out parseUID) ) + mName = channel; + else + param["Channel"] = channel; + + param["StringValue"] = sdata; + param["IntValue"] = Convert.ToString(idata); + + ArrayList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest(mName, parameters); + try + { + XmlRpcResponse resp = req.Send(destURL, 30000); + if (resp != null) + { + Hashtable respParms; + if(resp.Value.GetType().Equals(Type.GetType("System.Collections.Hashtable"))) { + respParms = (Hashtable)resp.Value; + } + else { + ArrayList respData = (ArrayList)resp.Value; + respParms = (Hashtable)respData[0]; + } + if (respParms != null) + { + if (respParms.Contains("StringValue")) + { + sdata = (string)respParms["StringValue"]; + } + if (respParms.Contains("IntValue")) + { + idata = Convert.ToInt32((string)respParms["IntValue"]); + } + if (respParms.Contains("faultString")) + { + sdata = (string)respParms["faultString"]; + } + if (respParms.Contains("faultCode")) + { + idata = Convert.ToInt32(respParms["faultCode"]); + } + } + } + } + catch (System.Net.WebException we) + { + sdata = we.Message; + m_log.Warn("[SendRemoteDataRequest]: Request failed"); + m_log.Warn(we.StackTrace); + } + + finished = true; + + } + + public void Stop() + { + try + { + httpThread.Abort(); + } + catch (Exception) + { + } + } + + public LLUUID GetReqID() + { + return reqID; + } + } - public void SetProcessed(bool processed) - { - m_processed = processed; - } - - public void SetRetval(string resp) - { - m_resp = resp; - } - - public string GetRetval() - { - return m_resp; - } - - public uint GetLocalID() - { - return m_localID; - } - - public LLUUID GetItemID() - { - return m_ItemID; - } - - public string GetStrVal() - { - return m_StrVal; - } - - public int GetIntValue() - { - return int.Parse(m_IntVal); - } - - public LLUUID GetMessageID() - { - return m_MessageID; - } - } - - public class RPCChannelInfo - { - private LLUUID m_itemID; - private uint m_localID; - private LLUUID m_ChannelKey; - - public RPCChannelInfo(uint localID, LLUUID itemID, LLUUID channelID) - { - m_ChannelKey = channelID; - m_localID = localID; - m_itemID = itemID; - } - - public LLUUID GetItemID() - { - return m_itemID; - } - - public LLUUID GetChannelID() - { - return m_ChannelKey; - } - - public uint GetLocalID() - { - return m_localID; - } - - } -} +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs index 771349080f..60a1cb3693 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BaseClass.cs @@ -2091,6 +2091,10 @@ namespace OpenSim.Region.ScriptEngine.Common public const int REMOTE_DATA_CHANNEL = 1; public const int REMOTE_DATA_REQUEST = 2; public const int REMOTE_DATA_REPLY = 3; + public const int HTTP_METHOD = 0; + public const int HTTP_MIMETYPE = 1; + public const int HTTP_BODY_MAXLENGTH = 2; + public const int HTTP_VERIFY_CERT = 3; public const int PRIM_MATERIAL = 2; public const int PRIM_PHYSICS = 3; diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs index c07f6d76e6..1ab2a43b25 100644 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs @@ -2880,8 +2880,8 @@ namespace OpenSim.Region.ScriptEngine.Common public string llSendRemoteData(string channel, string dest, int idata, string sdata) { m_host.AddScriptLPS(1); - NotImplemented("llSendRemoteData"); - return String.Empty; + IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface(); + return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); } public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs index 1afe71c10c..0491612387 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs @@ -125,8 +125,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase comms.DeleteListener(itemID); IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface(); - xmlrpc.DeleteChannel(itemID); + xmlrpc.DeleteChannels(itemID); + xmlrpc.CancelSRDRequests(itemID); + } #region TIMER @@ -238,24 +240,29 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase // implemented here yet anyway. Should be fixed if/when maxsize // is supported - object[] resobj = new object[] + if (m_ScriptEngine.m_ScriptManager.GetScript(httpInfo.localID, httpInfo.itemID) != null) + { + iHttpReq.RemoveCompletedRequest(httpInfo.reqID); + object[] resobj = new object[] { httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body }; - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj ); - httpInfo.Stop(); - httpInfo = null; + } httpInfo = iHttpReq.GetNextCompletedRequest(); + } } #endregion + #region Check llRemoteData channels + public void CheckXMLRPCRequests() { if (m_ScriptEngine.World == null) @@ -265,47 +272,96 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase if (xmlrpc != null) { - while (xmlrpc.hasRequests()) - { - RPCRequestInfo rInfo = xmlrpc.GetNextRequest(); - //Console.WriteLine("PICKED REQUEST"); + RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest(); - //Deliver data to prim's remote_data handler - object[] resobj = new object[] + while (rInfo != null) + { + if (m_ScriptEngine.m_ScriptManager.GetScript(rInfo.GetLocalID(), rInfo.GetItemID()) != null) + { + xmlrpc.RemoveCompletedRequest(rInfo.GetMessageID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] { 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty, rInfo.GetIntValue(), rInfo.GetStrVal() }; - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj ); + + } + + rInfo = xmlrpc.GetNextCompletedRequest(); + } + + SendRemoteDataRequest srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + + while (srdInfo != null) + { + if (m_ScriptEngine.m_ScriptManager.GetScript(srdInfo.m_localID, srdInfo.m_itemID) != null) + { + xmlrpc.RemoveCompletedSRDRequest(srdInfo.GetReqID()); + + //Deliver data to prim's remote_data handler + object[] resobj = new object[] + { + 3, srdInfo.channel.ToString(), srdInfo.GetReqID().ToString(), String.Empty, + srdInfo.idata, + srdInfo.sdata + }; + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + srdInfo.m_localID, srdInfo.m_itemID, "remote_data", EventQueueManager.llDetectNull, resobj + ); + + } + + srdInfo = xmlrpc.GetNextCompletedSRDRequest(); + + } + + } } + #endregion + + #region Check llListeners + public void CheckListeners() { if (m_ScriptEngine.World == null) return; IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface(); - while (comms.HasMessages()) + if (comms != null) { - ListenerInfo lInfo = comms.GetNextMessage(); - - //Deliver data to prim's listen handler - object[] resobj = new object[] + while (comms.HasMessages()) + { + if (m_ScriptEngine.m_ScriptManager.GetScript( + comms.PeekNextMessageLocalID(), comms.PeekNextMessageItemID()) != null) { - lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() - }; + ListenerInfo lInfo = comms.GetNextMessage(); - m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( - lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj - ); + //Deliver data to prim's listen handler + object[] resobj = new object[] + { + lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() + }; + + m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( + lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj + ); + } + + } } } + #endregion + /// /// If set to true then threads and stuff should try to make a graceful exit /// @@ -317,4 +373,4 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase private bool _PleaseShutdown = false; } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs index 641453e6c4..d47cab84e6 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs @@ -67,6 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase private Queue LUQueue = new Queue(); private static bool PrivateThread; private int LoadUnloadMaxQueueSize; + private Object scriptLock = new Object(); // Load/Unload structure private struct LUStruct @@ -304,7 +305,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); IScript Script = GetScript(localID, itemID); if (Script == null) + { return; + } //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined ///#if DEBUG /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); @@ -331,37 +334,42 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase public IScript GetScript(uint localID, LLUUID itemID) { - if (Scripts.ContainsKey(localID) == false) - return null; + lock (scriptLock) + { + if (Scripts.ContainsKey(localID) == false) + return null; - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == false) - return null; + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == false) + return null; - // Get script - IScript Script; - Obj.TryGetValue(itemID, out Script); - - return Script; + // Get script + IScript Script; + Obj.TryGetValue(itemID, out Script); + return Script; + } } public void SetScript(uint localID, LLUUID itemID, IScript Script) { - // Create object if it doesn't exist - if (Scripts.ContainsKey(localID) == false) + lock (scriptLock) { - Scripts.Add(localID, new Dictionary()); + // Create object if it doesn't exist + if (Scripts.ContainsKey(localID) == false) + { + Scripts.Add(localID, new Dictionary()); + } + + // Delete script if it exists + Dictionary Obj; + Scripts.TryGetValue(localID, out Obj); + if (Obj.ContainsKey(itemID) == true) + Obj.Remove(itemID); + + // Add to object + Obj.Add(itemID, Script); } - - // Delete script if it exists - Dictionary Obj; - Scripts.TryGetValue(localID, out Obj); - if (Obj.ContainsKey(itemID) == true) - Obj.Remove(itemID); - - // Add to object - Obj.Add(itemID, Script); } public void RemoveScript(uint localID, LLUUID itemID)