From: Michael Osias <mosias@us.ibm.com>

This patch implements the llSendRemoteData command and fixes mantis 552,
and possibly 586.
ThreadPoolClientBranch
Sean Dague 2008-02-19 19:16:21 +00:00
parent 69b1edebf6
commit 530cc24884
10 changed files with 597 additions and 218 deletions

View File

@ -38,5 +38,7 @@ namespace OpenSim.Region.Environment.Interfaces
LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body); LLUUID StartHttpRequest(uint localID, LLUUID itemID, string url, List<string> parameters, string body);
void StopHttpRequest(uint m_localID, LLUUID m_itemID); void StopHttpRequest(uint m_localID, LLUUID m_itemID);
HttpRequestClass GetNextCompletedRequest(); HttpRequestClass GetNextCompletedRequest();
void RemoveCompletedRequest(LLUUID id);
} }
} }

View File

@ -41,5 +41,8 @@ namespace OpenSim.Region.Environment.Interfaces
void ListenControl(int handle, int active); void ListenControl(int handle, int active);
void ListenRemove(int handle); void ListenRemove(int handle);
void DeleteListener(LLUUID itemID); void DeleteListener(LLUUID itemID);
uint PeekNextMessageLocalID();
LLUUID PeekNextMessageItemID();
} }
} }

View File

@ -28,6 +28,8 @@
using libsecondlife; using libsecondlife;
using OpenSim.Region.Environment.Modules; using OpenSim.Region.Environment.Modules;
using System.Collections;
using System.Collections.Generic;
namespace OpenSim.Region.Environment.Interfaces namespace OpenSim.Region.Environment.Interfaces
{ {
@ -36,9 +38,14 @@ namespace OpenSim.Region.Environment.Interfaces
LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID); LLUUID OpenXMLRPCChannel(uint localID, LLUUID itemID);
void CloseXMLRPCChannel(LLUUID channelKey); void CloseXMLRPCChannel(LLUUID channelKey);
bool hasRequests(); bool hasRequests();
RPCRequestInfo GetNextRequest();
void RemoteDataReply(string channel, string message_id, string sdata, int idata); void RemoteDataReply(string channel, string message_id, string sdata, int idata);
bool IsEnabled(); 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);
} }
} }

View File

@ -184,13 +184,15 @@ namespace OpenSim.Region.Environment.Modules
public void StopHttpRequest(uint m_localID, LLUUID m_itemID) public void StopHttpRequest(uint m_localID, LLUUID m_itemID)
{ {
lock (HttpListLock) if(m_pendingRequests != null) {
{ lock (HttpListLock)
HttpRequestClass tmpReq;
if (m_pendingRequests.TryGetValue(m_itemID, out tmpReq))
{ {
tmpReq.Stop(); HttpRequestClass tmpReq;
m_pendingRequests.Remove(m_itemID); 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) if (tmpReq.finished)
{ {
m_pendingRequests.Remove(luid);
return tmpReq; return tmpReq;
} }
} }
@ -224,6 +225,21 @@ namespace OpenSim.Region.Environment.Modules
} }
return null; 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.Name = "HttpRequestThread";
httpThread.Priority = ThreadPriority.BelowNormal; httpThread.Priority = ThreadPriority.BelowNormal;
httpThread.IsBackground = true; httpThread.IsBackground = true;
finished = false;
httpThread.Start(); httpThread.Start();
} }

View File

@ -84,8 +84,8 @@ namespace OpenSim.Region.Environment.Modules
m_scene = scene; m_scene = scene;
m_scene.RegisterModuleInterface<IWorldComm>(this); m_scene.RegisterModuleInterface<IWorldComm>(this);
m_listenerManager = new ListenerManager(); m_listenerManager = new ListenerManager();
m_pending = new Queue<ListenerInfo>();
m_scene.EventManager.OnNewClient += NewClient; m_scene.EventManager.OnNewClient += NewClient;
m_pending = new Queue<ListenerInfo>();
} }
public void PostInitialise() public void PostInitialise()
@ -139,9 +139,12 @@ namespace OpenSim.Region.Environment.Modules
public void DeleteListener(LLUUID itemID) 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 // If they are in proximity, then if they are
// listeners, if so add them to the pending queue // 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; 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! // Dont process if this message is from itself!
if (eb.ToString().Equals(sourceItemID) || if (li.GetHostID().ToString().Equals(sourceItemID) ||
sPart.UUID.ToString().Equals(sourceItemID)) sPart.UUID.ToString().Equals(sourceItemID))
continue; continue;
@ -196,7 +199,10 @@ namespace OpenSim.Region.Environment.Modules
); );
if (isListener != null) if (isListener != null)
{ {
m_pending.Enqueue(isListener); lock (CommListLock)
{
m_pending.Enqueue(isListener);
}
} }
} }
break; break;
@ -210,7 +216,10 @@ namespace OpenSim.Region.Environment.Modules
); );
if (isListener != null) if (isListener != null)
{ {
m_pending.Enqueue(isListener); lock (CommListLock)
{
m_pending.Enqueue(isListener);
}
} }
} }
break; break;
@ -223,14 +232,17 @@ namespace OpenSim.Region.Environment.Modules
); );
if (isListener != null) if (isListener != null)
{ {
m_pending.Enqueue(isListener); lock (CommListLock)
{
m_pending.Enqueue(isListener);
}
} }
} }
break; break;
case ChatTypeEnum.Broadcast: case ChatTypeEnum.Broadcast:
ListenerInfo isListen = ListenerInfo isListen =
m_listenerManager.IsListenerMatch(sourceItemID, eb, channel, name, msg); m_listenerManager.IsListenerMatch(sourceItemID, li.GetItemID(), channel, name, msg);
if (isListen != null) if (isListen != null)
{ {
ListenerInfo isListener = m_listenerManager.IsListenerMatch( ListenerInfo isListener = m_listenerManager.IsListenerMatch(
@ -238,19 +250,24 @@ namespace OpenSim.Region.Environment.Modules
); );
if (isListener != null) if (isListener != null)
{ {
m_pending.Enqueue(isListener); lock (CommListLock)
{
m_pending.Enqueue(isListener);
}
} }
} }
break; break;
} }
} }
;
} }
} }
public bool HasMessages() public bool HasMessages()
{ {
return (m_pending.Count > 0); if (m_pending != null)
return (m_pending.Count > 0);
else
return false;
} }
public ListenerInfo GetNextMessage() public ListenerInfo GetNextMessage()
@ -264,6 +281,17 @@ namespace OpenSim.Region.Environment.Modules
return li; return li;
} }
public uint PeekNextMessageLocalID()
{
return m_pending.Peek().GetLocalID();
}
public LLUUID PeekNextMessageItemID()
{
return m_pending.Peek().GetItemID();
}
} }
// hostID: the ID of the ScenePart // hostID: the ID of the ScenePart
@ -280,8 +308,7 @@ namespace OpenSim.Region.Environment.Modules
m_listeners = new Dictionary<int, ListenerInfo>(); m_listeners = new Dictionary<int, ListenerInfo>();
} }
public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
string msg)
{ {
if (m_listeners.Count < m_MaxListeners) if (m_listeners.Count < m_MaxListeners)
{ {
@ -410,6 +437,11 @@ namespace OpenSim.Region.Environment.Modules
} }
return null; return null;
} }
public Dictionary<int, ListenerInfo>.ValueCollection GetListeners()
{
return m_listeners.Values;
}
} }
public class ListenerInfo public class ListenerInfo
@ -425,21 +457,20 @@ namespace OpenSim.Region.Environment.Modules
private string m_message; // The message private string m_message; // The message
private bool m_active; // Listener is active or not 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, public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
string message)
{ {
Initialise(localID, handle, ItemID, hostID, channel, name, id, 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, 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); Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
m_sourceItemID = sourceItemID; m_sourceItemID = sourceItemID;
} }
private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, 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_handle = handle;
m_channel = channel; m_channel = channel;
@ -511,5 +542,6 @@ namespace OpenSim.Region.Environment.Modules
{ {
return m_id; return m_id;
} }
} }
} }

View File

@ -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 static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
private Queue<RPCRequestInfo> rpcQueue = new Queue<RPCRequestInfo>();
private object XMLRPCListLock = new object(); private object XMLRPCListLock = new object();
private string m_name = "XMLRPCModule"; private string m_name = "XMLRPCModule";
private int RemoteReplyScriptWait = 300; private int RemoteReplyScriptWait = 300;
private int RemoteReplyScriptTimeout = 900; private int RemoteReplyScriptTimeout = 9000;
private int m_remoteDataPort = 0; private int m_remoteDataPort = 0;
private List<Scene> m_scenes = new List<Scene>(); private List<Scene> m_scenes = new List<Scene>();
// <channel id, RPCChannelInfo> // <channel id, RPCChannelInfo>
private Dictionary<LLUUID, RPCChannelInfo> m_openChannels; private Dictionary<LLUUID, RPCChannelInfo> m_openChannels;
// <channel id, RPCRequestInfo> private Dictionary<LLUUID, RPCRequestInfo> m_rpcPending;
private Dictionary<LLUUID, RPCRequestInfo> m_pendingResponse; private Dictionary<LLUUID, RPCRequestInfo> m_rpcPendingResponses;
private Dictionary<LLUUID, SendRemoteDataRequest> m_pendingSRDResponses;
public void Initialise(Scene scene, IConfigSource config) public void Initialise(Scene scene, IConfigSource config)
{ {
@ -115,13 +116,15 @@ namespace OpenSim.Region.Environment.Modules
if (IsEnabled()) if (IsEnabled())
{ {
m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>(); m_openChannels = new Dictionary<LLUUID, RPCChannelInfo>();
m_pendingResponse = new Dictionary<LLUUID, RPCRequestInfo>(); m_rpcPending = new Dictionary<LLUUID, RPCRequestInfo>();
m_rpcPendingResponses = new Dictionary<LLUUID, RPCRequestInfo>();
m_pendingSRDResponses = new Dictionary<LLUUID, SendRemoteDataRequest>();
// Start http server // Start http server
// Attach xmlrpc handlers // Attach xmlrpc handlers
m_log.Info("[REMOTE_DATA]: " + m_log.Info("[REMOTE_DATA]: " +
"Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); "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.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData);
httpServer.Start(); httpServer.Start();
} }
@ -188,18 +191,28 @@ namespace OpenSim.Region.Environment.Modules
return channel; 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()); System.Collections.IEnumerator tmpEnumerator = tmp.GetEnumerator();
return; while ( tmpEnumerator.MoveNext() )
m_openChannels.Remove((LLUUID)tmpEnumerator.Current);
} }
} }
@ -218,15 +231,12 @@ namespace OpenSim.Region.Environment.Modules
RPCRequestInfo rpcInfo; RPCRequestInfo rpcInfo;
LLUUID message_key = new LLUUID(message_id); 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); rpcInfo.SetProcessed(true);
m_rpcPendingResponses.Remove(message_key);
lock (XMLRPCListLock)
{
m_pendingResponse.Remove(message_key);
}
} }
} }
@ -248,18 +258,18 @@ namespace OpenSim.Region.Environment.Modules
{ {
XmlRpcResponse response = new XmlRpcResponse(); XmlRpcResponse response = new XmlRpcResponse();
Hashtable requestData = (Hashtable) request.Params[0]; Hashtable requestData = (Hashtable)request.Params[0];
bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") && bool GoodXML = (requestData.Contains("Channel") && requestData.Contains("IntValue") &&
requestData.Contains("StringValue")); requestData.Contains("StringValue"));
if (GoodXML) if (GoodXML)
{ {
LLUUID channel = new LLUUID((string) requestData["Channel"]); LLUUID channel = new LLUUID((string)requestData["Channel"]);
RPCChannelInfo rpcChanInfo; RPCChannelInfo rpcChanInfo;
if (m_openChannels.TryGetValue(channel, out rpcChanInfo)) if (m_openChannels.TryGetValue(channel, out rpcChanInfo))
{ {
string intVal = (string) requestData["IntValue"]; string intVal = (string)requestData["IntValue"];
string strVal = (string) requestData["StringValue"]; string strVal = (string)requestData["StringValue"];
RPCRequestInfo rpcInfo; RPCRequestInfo rpcInfo;
@ -268,7 +278,7 @@ namespace OpenSim.Region.Environment.Modules
rpcInfo = rpcInfo =
new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal, new RPCRequestInfo(rpcChanInfo.GetLocalID(), rpcChanInfo.GetItemID(), channel, strVal,
intVal); intVal);
rpcQueue.Enqueue(rpcInfo); m_rpcPending.Add(rpcInfo.GetMessageID(), rpcInfo);
} }
int timeoutCtr = 0; int timeoutCtr = 0;
@ -280,16 +290,20 @@ namespace OpenSim.Region.Environment.Modules
} }
if (rpcInfo.IsProcessed()) 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; rpcInfo = null;
} }
else else
{ {
response.SetFault(-1, "Script timeout"); response.SetFault(-1, "Script timeout");
lock (XMLRPCListLock) rpcInfo = null;
{
m_pendingResponse.Remove(rpcInfo.GetMessageID());
}
} }
} }
else else
@ -303,129 +317,365 @@ namespace OpenSim.Region.Environment.Modules
public bool hasRequests() 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) lock (XMLRPCListLock)
{ {
RPCRequestInfo rpcInfo = rpcQueue.Dequeue(); RPCRequestInfo tmp;
m_pendingResponse.Add(rpcInfo.GetMessageID(), rpcInfo); if (m_rpcPending.TryGetValue(id, out tmp))
return rpcInfo; {
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
* ***********************************************************/
/************************************************************** public class RPCRequestInfo
*
* 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)
{ {
m_localID = localID; private string m_StrVal;
m_StrVal = strVal; private string m_IntVal;
m_IntVal = intVal; private bool m_processed;
m_ItemID = itemID; private string m_respStr;
m_ChannelKey = channelKey; private int m_respInt;
m_MessageID = LLUUID.Random(); private uint m_localID;
m_processed = false; private LLUUID m_ItemID;
m_resp = String.Empty; 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;
}
}
}

View File

@ -2091,6 +2091,10 @@ namespace OpenSim.Region.ScriptEngine.Common
public const int REMOTE_DATA_CHANNEL = 1; public const int REMOTE_DATA_CHANNEL = 1;
public const int REMOTE_DATA_REQUEST = 2; public const int REMOTE_DATA_REQUEST = 2;
public const int REMOTE_DATA_REPLY = 3; 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_MATERIAL = 2;
public const int PRIM_PHYSICS = 3; public const int PRIM_PHYSICS = 3;

View File

@ -2880,8 +2880,8 @@ namespace OpenSim.Region.ScriptEngine.Common
public string llSendRemoteData(string channel, string dest, int idata, string sdata) public string llSendRemoteData(string channel, string dest, int idata, string sdata)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
NotImplemented("llSendRemoteData"); IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
return String.Empty; return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
} }
public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)

View File

@ -125,8 +125,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
comms.DeleteListener(itemID); comms.DeleteListener(itemID);
IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
xmlrpc.DeleteChannel(itemID); xmlrpc.DeleteChannels(itemID);
xmlrpc.CancelSRDRequests(itemID);
} }
#region TIMER #region TIMER
@ -238,24 +240,29 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
// implemented here yet anyway. Should be fixed if/when maxsize // implemented here yet anyway. Should be fixed if/when maxsize
// is supported // 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 httpInfo.reqID.ToString(), httpInfo.status, null, httpInfo.response_body
}; };
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj httpInfo.localID, httpInfo.itemID, "http_response", EventQueueManager.llDetectNull, resobj
); );
httpInfo.Stop(); }
httpInfo = null;
httpInfo = iHttpReq.GetNextCompletedRequest(); httpInfo = iHttpReq.GetNextCompletedRequest();
} }
} }
#endregion #endregion
#region Check llRemoteData channels
public void CheckXMLRPCRequests() public void CheckXMLRPCRequests()
{ {
if (m_ScriptEngine.World == null) if (m_ScriptEngine.World == null)
@ -265,47 +272,96 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
if (xmlrpc != null) if (xmlrpc != null)
{ {
while (xmlrpc.hasRequests()) RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest();
{
RPCRequestInfo rInfo = xmlrpc.GetNextRequest();
//Console.WriteLine("PICKED REQUEST");
//Deliver data to prim's remote_data handler while (rInfo != null)
object[] resobj = new object[] {
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, 2, rInfo.GetChannelKey().ToString(), rInfo.GetMessageID().ToString(), String.Empty,
rInfo.GetIntValue(), rInfo.GetIntValue(),
rInfo.GetStrVal() rInfo.GetStrVal()
}; };
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( m_ScriptEngine.m_EventQueueManager.AddToScriptQueue(
rInfo.GetLocalID(), rInfo.GetItemID(), "remote_data", EventQueueManager.llDetectNull, resobj 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() public void CheckListeners()
{ {
if (m_ScriptEngine.World == null) if (m_ScriptEngine.World == null)
return; return;
IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
while (comms.HasMessages()) if (comms != null)
{ {
ListenerInfo lInfo = comms.GetNextMessage(); while (comms.HasMessages())
{
//Deliver data to prim's listen handler if (m_ScriptEngine.m_ScriptManager.GetScript(
object[] resobj = new object[] comms.PeekNextMessageLocalID(), comms.PeekNextMessageItemID()) != null)
{ {
lInfo.GetChannel(), lInfo.GetName(), lInfo.GetID().ToString(), lInfo.GetMessage() ListenerInfo lInfo = comms.GetNextMessage();
};
m_ScriptEngine.m_EventQueueManager.AddToScriptQueue( //Deliver data to prim's listen handler
lInfo.GetLocalID(), lInfo.GetItemID(), "listen", EventQueueManager.llDetectNull, resobj 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
/// <summary> /// <summary>
/// If set to true then threads and stuff should try to make a graceful exit /// If set to true then threads and stuff should try to make a graceful exit
/// </summary> /// </summary>
@ -317,4 +373,4 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
private bool _PleaseShutdown = false; private bool _PleaseShutdown = false;
} }
} }

View File

@ -67,6 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
private Queue<LUStruct> LUQueue = new Queue<LUStruct>(); private Queue<LUStruct> LUQueue = new Queue<LUStruct>();
private static bool PrivateThread; private static bool PrivateThread;
private int LoadUnloadMaxQueueSize; private int LoadUnloadMaxQueueSize;
private Object scriptLock = new Object();
// Load/Unload structure // Load/Unload structure
private struct LUStruct private struct LUStruct
@ -304,7 +305,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
//ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID); //ScriptBaseInterface Script = (ScriptBaseInterface)GetScript(localID, itemID);
IScript Script = GetScript(localID, itemID); IScript Script = GetScript(localID, itemID);
if (Script == null) if (Script == null)
{
return; return;
}
//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined //cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
///#if DEBUG ///#if DEBUG
/// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName); /// Console.WriteLine("ScriptEngine: Executing event: " + FunctionName);
@ -331,37 +334,42 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
public IScript GetScript(uint localID, LLUUID itemID) public IScript GetScript(uint localID, LLUUID itemID)
{ {
if (Scripts.ContainsKey(localID) == false) lock (scriptLock)
return null; {
if (Scripts.ContainsKey(localID) == false)
return null;
Dictionary<LLUUID, IScript> Obj; Dictionary<LLUUID, IScript> Obj;
Scripts.TryGetValue(localID, out Obj); Scripts.TryGetValue(localID, out Obj);
if (Obj.ContainsKey(itemID) == false) if (Obj.ContainsKey(itemID) == false)
return null; return null;
// Get script // Get script
IScript Script; IScript Script;
Obj.TryGetValue(itemID, out Script); Obj.TryGetValue(itemID, out Script);
return Script;
return Script; }
} }
public void SetScript(uint localID, LLUUID itemID, IScript Script) public void SetScript(uint localID, LLUUID itemID, IScript Script)
{ {
// Create object if it doesn't exist lock (scriptLock)
if (Scripts.ContainsKey(localID) == false)
{ {
Scripts.Add(localID, new Dictionary<LLUUID, IScript>()); // Create object if it doesn't exist
if (Scripts.ContainsKey(localID) == false)
{
Scripts.Add(localID, new Dictionary<LLUUID, IScript>());
}
// Delete script if it exists
Dictionary<LLUUID, IScript> 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<LLUUID, IScript> 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) public void RemoveScript(uint localID, LLUUID itemID)