From d51ce47b2d7635b17f3dd429158e8f59b78b83aa Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Thu, 1 May 2008 14:31:30 +0000 Subject: Update svn properties. Minor formatting cleanup. --- .../Modules/Scripting/XMLRPC/XMLRPCModule.cs | 1342 ++++++++++---------- 1 file changed, 671 insertions(+), 671 deletions(-) (limited to 'OpenSim/Region/Environment/Modules/Scripting/XMLRPC') diff --git a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs index 6ca8136..a039d42 100644 --- a/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/Environment/Modules/Scripting/XMLRPC/XMLRPCModule.cs @@ -1,672 +1,672 @@ -/* - * 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. - * * Neither the name of the OpenSim Project nor the - * 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. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Reflection; -using System.Threading; -using libsecondlife; -using log4net; -using Nini.Config; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Servers; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes; - -/***************************************************** - * - * XMLRPCModule - * - * Module for accepting incoming communications from - * external XMLRPC client and calling a remote data - * procedure for a registered data channel/prim. - * - * - * 1. On module load, open a listener port - * 2. Attach an XMLRPC handler - * 3. When a request is received: - * 3.1 Parse into components: channel key, int, string - * 3.2 Look up registered channel listeners - * 3.3 Call the channel (prim) remote data method - * 3.4 Capture the response (llRemoteDataReply) - * 3.5 Return response to client caller - * 3.6 If no response from llRemoteDataReply within - * RemoteReplyScriptTimeout, generate script timeout fault - * - * Prims in script must: - * 1. Open a remote data channel - * 1.1 Generate a channel ID - * 1.2 Register primid,channelid pair with module - * 2. Implement the remote data procedure handler - * - * llOpenRemoteDataChannel - * llRemoteDataReply - * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) - * llCloseRemoteDataChannel - * - * **************************************************/ - -namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC -{ - public class XMLRPCModule : IRegionModule, IXMLRPC - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_name = "XMLRPCModule"; - - // - private Dictionary m_openChannels; - private Dictionary m_pendingSRDResponses; - private int m_remoteDataPort = 0; - - private Dictionary m_rpcPending; - private Dictionary m_rpcPendingResponses; - private List m_scenes = new List(); - private int RemoteReplyScriptTimeout = 9000; - private int RemoteReplyScriptWait = 300; - private object XMLRPCListLock = new object(); - - #region IRegionModule Members - - public void Initialise(Scene scene, IConfigSource config) - { - try - { - m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); - } - catch (Exception) - { - } - - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - - scene.RegisterModuleInterface(this); - } - } - - public void PostInitialise() - { - if (IsEnabled()) - { - m_openChannels = 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); - httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); - httpServer.Start(); - } - } - - public void Close() - { - } - - public string Name - { - get { return m_name; } - } - - public bool IsSharedModule - { - get { return true; } - } - - #endregion - - #region IXMLRPC Members - - public bool IsEnabled() - { - return (m_remoteDataPort > 0); - } - - /********************************************** - * OpenXMLRPCChannel - * - * Generate a LLUUID channel key and add it and - * the prim id to dictionary - * - * First check if there is a channel assigned for - * this itemID. If there is, then someone called - * llOpenRemoteDataChannel twice. Just return the - * original channel. Other option is to delete the - * current channel and assign a new one. - * - * ********************************************/ - - public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) - { - LLUUID channel = new LLUUID(); - - //Is a dupe? - foreach (RPCChannelInfo ci in m_openChannels.Values) - { - if (ci.GetItemID().Equals(itemID)) - { - // return the original channel ID for this item - channel = ci.GetChannelID(); - break; - } - } - - if (channel == LLUUID.Zero) - { - channel = LLUUID.Random(); - RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); - lock (XMLRPCListLock) - { - m_openChannels.Add(channel, rpcChanInfo); - } - } - - return channel; - } - - // Delete channels based on itemID - // for when a script is deleted - public void DeleteChannels(LLUUID itemID) - { - if (m_openChannels != null) - { - ArrayList tmp = new ArrayList(); - - lock (XMLRPCListLock) - { - foreach (RPCChannelInfo li in m_openChannels.Values) - { - if (li.GetItemID().Equals(itemID)) - { - tmp.Add(itemID); - } - } - - IEnumerator tmpEnumerator = tmp.GetEnumerator(); - while (tmpEnumerator.MoveNext()) - m_openChannels.Remove((LLUUID) tmpEnumerator.Current); - } - } - } - - /********************************************** - * Remote Data Reply - * - * Response to RPC message - * - *********************************************/ - - public void RemoteDataReply(string channel, string message_id, string sdata, int idata) - { - RPCRequestInfo rpcInfo; - LLUUID message_key = new LLUUID(message_id); - - if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) - { - rpcInfo.SetStrRetval(sdata); - rpcInfo.SetIntRetval(idata); - rpcInfo.SetProcessed(true); - m_rpcPendingResponses.Remove(message_key); - } - } - - /********************************************** - * CloseXMLRPCChannel - * - * Remove channel from dictionary - * - *********************************************/ - - public void CloseXMLRPCChannel(LLUUID channelKey) - { - if (m_openChannels.ContainsKey(channelKey)) - m_openChannels.Remove(channelKey); - } - - - public bool hasRequests() - { - lock (XMLRPCListLock) - { - if (m_rpcPending != null) - return (m_rpcPending.Count > 0); - else - return false; - } - } - - 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 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()); - } - } - } - } - - #endregion - - public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - - 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"]); - RPCChannelInfo rpcChanInfo; - if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) - { - string intVal = (string) requestData["IntValue"]; - string strVal = (string) requestData["StringValue"]; - - RPCRequestInfo rpcInfo; - - lock (XMLRPCListLock) - { - rpcInfo = - new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, - intVal); - m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); - } - - int timeoutCtr = 0; - - while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) - { - Thread.Sleep(RemoteReplyScriptWait); - timeoutCtr += RemoteReplyScriptWait; - } - if (rpcInfo.IsProcessed()) - { - 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"); - rpcInfo = null; - } - } - else - { - response.SetFault(-1, "Invalid channel"); - } - } - - return response; - } - } - - public class RPCRequestInfo - { - private LLUUID m_ChannelKey; - private string m_IntVal; - private LLUUID m_ItemID; - private uint m_localID; - private LLUUID m_MessageID; - private bool m_processed; - private int m_respInt; - private string m_respStr; - private string m_StrVal; - - 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 class RPCChannelInfo - { - private LLUUID m_ChannelKey; - private LLUUID m_itemID; - private uint m_localID; - - 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 class SendRemoteDataRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public string channel; - public string destURL; - public bool finished; - private Thread httpThread; - public int idata; - public LLUUID m_itemID; - public uint m_localID; - public LLUUID reqID; - public XmlRpcRequest request; - public int response_idata; - public string response_sdata; - public string sdata; - - public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) - { - this.channel = channel; - 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(); - ThreadTracker.Add(httpThread); - - 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 (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; - } - } +/* + * 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. + * * Neither the name of the OpenSim Project nor the + * 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. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Threading; +using libsecondlife; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes; + +/***************************************************** + * + * XMLRPCModule + * + * Module for accepting incoming communications from + * external XMLRPC client and calling a remote data + * procedure for a registered data channel/prim. + * + * + * 1. On module load, open a listener port + * 2. Attach an XMLRPC handler + * 3. When a request is received: + * 3.1 Parse into components: channel key, int, string + * 3.2 Look up registered channel listeners + * 3.3 Call the channel (prim) remote data method + * 3.4 Capture the response (llRemoteDataReply) + * 3.5 Return response to client caller + * 3.6 If no response from llRemoteDataReply within + * RemoteReplyScriptTimeout, generate script timeout fault + * + * Prims in script must: + * 1. Open a remote data channel + * 1.1 Generate a channel ID + * 1.2 Register primid,channelid pair with module + * 2. Implement the remote data procedure handler + * + * llOpenRemoteDataChannel + * llRemoteDataReply + * remote_data(integer type, key channel, key messageid, string sender, integer ival, string sval) + * llCloseRemoteDataChannel + * + * **************************************************/ + +namespace OpenSim.Region.Environment.Modules.Scripting.XMLRPC +{ + public class XMLRPCModule : IRegionModule, IXMLRPC + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_name = "XMLRPCModule"; + + // + private Dictionary m_openChannels; + private Dictionary m_pendingSRDResponses; + private int m_remoteDataPort = 0; + + private Dictionary m_rpcPending; + private Dictionary m_rpcPendingResponses; + private List m_scenes = new List(); + private int RemoteReplyScriptTimeout = 9000; + private int RemoteReplyScriptWait = 300; + private object XMLRPCListLock = new object(); + + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) + { + try + { + m_remoteDataPort = config.Configs["Network"].GetInt("remoteDataPort", m_remoteDataPort); + } + catch (Exception) + { + } + + if (!m_scenes.Contains(scene)) + { + m_scenes.Add(scene); + + scene.RegisterModuleInterface(this); + } + } + + public void PostInitialise() + { + if (IsEnabled()) + { + m_openChannels = 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); + httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); + httpServer.Start(); + } + } + + public void Close() + { + } + + public string Name + { + get { return m_name; } + } + + public bool IsSharedModule + { + get { return true; } + } + + #endregion + + #region IXMLRPC Members + + public bool IsEnabled() + { + return (m_remoteDataPort > 0); + } + + /********************************************** + * OpenXMLRPCChannel + * + * Generate a LLUUID channel key and add it and + * the prim id to dictionary + * + * First check if there is a channel assigned for + * this itemID. If there is, then someone called + * llOpenRemoteDataChannel twice. Just return the + * original channel. Other option is to delete the + * current channel and assign a new one. + * + * ********************************************/ + + public LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID) + { + LLUUID channel = new LLUUID(); + + //Is a dupe? + foreach (RPCChannelInfo ci in m_openChannels.Values) + { + if (ci.GetItemID().Equals(itemID)) + { + // return the original channel ID for this item + channel = ci.GetChannelID(); + break; + } + } + + if (channel == LLUUID.Zero) + { + channel = LLUUID.Random(); + RPCChannelInfo rpcChanInfo = new RPCChannelInfo(localID, itemID, channel); + lock (XMLRPCListLock) + { + m_openChannels.Add(channel, rpcChanInfo); + } + } + + return channel; + } + + // Delete channels based on itemID + // for when a script is deleted + public void DeleteChannels(LLUUID itemID) + { + if (m_openChannels != null) + { + ArrayList tmp = new ArrayList(); + + lock (XMLRPCListLock) + { + foreach (RPCChannelInfo li in m_openChannels.Values) + { + if (li.GetItemID().Equals(itemID)) + { + tmp.Add(itemID); + } + } + + IEnumerator tmpEnumerator = tmp.GetEnumerator(); + while (tmpEnumerator.MoveNext()) + m_openChannels.Remove((LLUUID) tmpEnumerator.Current); + } + } + } + + /********************************************** + * Remote Data Reply + * + * Response to RPC message + * + *********************************************/ + + public void RemoteDataReply(string channel, string message_id, string sdata, int idata) + { + RPCRequestInfo rpcInfo; + LLUUID message_key = new LLUUID(message_id); + + if (m_rpcPendingResponses.TryGetValue(message_key, out rpcInfo)) + { + rpcInfo.SetStrRetval(sdata); + rpcInfo.SetIntRetval(idata); + rpcInfo.SetProcessed(true); + m_rpcPendingResponses.Remove(message_key); + } + } + + /********************************************** + * CloseXMLRPCChannel + * + * Remove channel from dictionary + * + *********************************************/ + + public void CloseXMLRPCChannel(LLUUID channelKey) + { + if (m_openChannels.ContainsKey(channelKey)) + m_openChannels.Remove(channelKey); + } + + + public bool hasRequests() + { + lock (XMLRPCListLock) + { + if (m_rpcPending != null) + return (m_rpcPending.Count > 0); + else + return false; + } + } + + 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 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()); + } + } + } + } + + #endregion + + public XmlRpcResponse XmlRpcRemoteData(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + + 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"]); + RPCChannelInfo rpcChanInfo; + if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) + { + string intVal = (string) requestData["IntValue"]; + string strVal = (string) requestData["StringValue"]; + + RPCRequestInfo rpcInfo; + + lock (XMLRPCListLock) + { + rpcInfo = + new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, + intVal); + m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo); + } + + int timeoutCtr = 0; + + while (!rpcInfo.IsProcessed() && (timeoutCtr < RemoteReplyScriptTimeout)) + { + Thread.Sleep(RemoteReplyScriptWait); + timeoutCtr += RemoteReplyScriptWait; + } + if (rpcInfo.IsProcessed()) + { + 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"); + rpcInfo = null; + } + } + else + { + response.SetFault(-1, "Invalid channel"); + } + } + + return response; + } + } + + public class RPCRequestInfo + { + private LLUUID m_ChannelKey; + private string m_IntVal; + private LLUUID m_ItemID; + private uint m_localID; + private LLUUID m_MessageID; + private bool m_processed; + private int m_respInt; + private string m_respStr; + private string m_StrVal; + + 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 class RPCChannelInfo + { + private LLUUID m_ChannelKey; + private LLUUID m_itemID; + private uint m_localID; + + 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 class SendRemoteDataRequest + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public string channel; + public string destURL; + public bool finished; + private Thread httpThread; + public int idata; + public LLUUID m_itemID; + public uint m_localID; + public LLUUID reqID; + public XmlRpcRequest request; + public int response_idata; + public string response_sdata; + public string sdata; + + public SendRemoteDataRequest(uint localID, LLUUID itemID, string channel, string dest, int idata, string sdata) + { + this.channel = channel; + 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(); + ThreadTracker.Add(httpThread); + + 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 (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; + } + } } \ No newline at end of file -- cgit v1.1