From 5e4d6cab00cb29cd088ab7b62ab13aff103b64cb Mon Sep 17 00:00:00 2001
From: onefang
Date: Sun, 19 May 2019 21:24:15 +1000
Subject: Dump OpenSim 0.9.0.1 into it's own branch.
---
.../InstantMessage/HGMessageTransferModule.cs | 31 +--
.../Avatar/InstantMessage/InstantMessageModule.cs | 69 +++--
.../Avatar/InstantMessage/MessageTransferModule.cs | 297 ++++++++++++++-------
.../Avatar/InstantMessage/MuteListModule.cs | 4 +-
.../Avatar/InstantMessage/MuteListModuleTst.cs | 229 ++++++++++++++++
.../Avatar/InstantMessage/OfflineMessageModule.cs | 132 ++++++---
.../Avatar/InstantMessage/XMuteModule.cs | 239 +++++++++++++++++
7 files changed, 824 insertions(+), 177 deletions(-)
create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
create mode 100644 OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
(limited to 'OpenSim/Region/CoreModules/Avatar/InstantMessage')
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
index a1b918a..16e2ec3 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -144,11 +144,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
// m_log.DebugFormat(
-// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
+// "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}",
// toAgentID.ToString(), scene.RegionInfo.RegionName);
- ScenePresence sp = scene.GetScenePresence(toAgentID);
- if (sp != null && !sp.IsChildAgent)
- {
+ ScenePresence sp = scene.GetScenePresence(toAgentID);
+ if (sp != null && !sp.IsChildAgent && !sp.IsDeleted)
+ {
// Local message
// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
sp.ControllingClient.SendInstantMessage(im);
@@ -159,25 +159,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
- // try child avatar second
- foreach (Scene scene in m_Scenes)
- {
-// m_log.DebugFormat(
-// "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}",
-// toAgentID, scene.RegionInfo.RegionName);
- ScenePresence sp = scene.GetScenePresence(toAgentID);
- if (sp != null)
- {
- // Local message
-// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
- sp.ControllingClient.SendInstantMessage(im);
-
- // Message sent
- result(true);
- return;
- }
- }
-
// m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
// Is the user a local user?
string url = string.Empty;
@@ -224,7 +205,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
ScenePresence sp = scene.GetScenePresence(toAgentID);
- if(sp != null && !sp.IsChildAgent)
+ if(sp != null && !sp.IsChildAgent && !sp.IsDeleted)
{
scene.EventManager.TriggerIncomingInstantMessage(gim);
successful = true;
@@ -310,7 +291,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
foreach (Scene scene in m_Scenes)
{
ScenePresence presence = scene.GetScenePresence(agentID);
- if (presence != null && !presence.IsChildAgent)
+ if (presence != null && !presence.IsChildAgent && !presence.IsDeleted)
return presence.ControllingClient;
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index c33a296..71c0a8a 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -27,6 +27,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
+using System.Timers;
using log4net;
using Mono.Addins;
using Nini.Config;
@@ -47,15 +48,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
///
/// Is this module enabled?
///
- private bool m_enabled = false;
-
- private readonly List m_scenes = new List();
+ protected bool m_enabled = false;
+
+ protected readonly List m_scenes = new List();
#region Region Module interface
- private IMessageTransferModule m_TransferModule = null;
+ protected IMessageTransferModule m_TransferModule = null;
- public void Initialise(IConfigSource config)
+ public virtual void Initialise(IConfigSource config)
{
if (config.Configs["Messaging"] != null)
{
@@ -64,11 +65,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
"InstantMessageModule")
return;
}
-
+
m_enabled = true;
}
- public void AddRegion(Scene scene)
+ public virtual void AddRegion(Scene scene)
{
if (!m_enabled)
return;
@@ -84,7 +85,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
- public void RegionLoaded(Scene scene)
+ public virtual void RegionLoaded(Scene scene)
{
if (!m_enabled)
return;
@@ -106,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
- public void RemoveRegion(Scene scene)
+ public virtual void RemoveRegion(Scene scene)
{
if (!m_enabled)
return;
@@ -117,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
- void OnClientConnect(IClientCore client)
+ protected virtual void OnClientConnect(IClientCore client)
{
IClientIM clientIM;
if (client.TryGet(out clientIM))
@@ -126,27 +127,33 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
}
- public void PostInitialise()
+ public virtual void PostInitialise()
{
}
- public void Close()
+ public virtual void Close()
{
}
- public string Name
+ public virtual string Name
{
get { return "InstantMessageModule"; }
}
- public Type ReplaceableInterface
+ public virtual Type ReplaceableInterface
{
get { return null; }
}
#endregion
-
- public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
+/*
+ public virtual void OnViewerInstantMessage(IClientAPI client, GridInstantMessage im)
+ {
+ im.fromAgentName = client.FirstName + " " + client.LastName;
+ OnInstantMessage(client, im);
+ }
+*/
+ public virtual void OnInstantMessage(IClientAPI client, GridInstantMessage im)
{
byte dialog = im.dialog;
@@ -159,10 +166,34 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
return;
}
+ //DateTime dt = DateTime.UtcNow;
+
+ // Ticks from UtcNow, but make it look like local. Evil, huh?
+ //dt = DateTime.SpecifyKind(dt, DateTimeKind.Local);
+
+ //try
+ //{
+ // // Convert that to the PST timezone
+ // TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles");
+ // dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo);
+ //}
+ //catch
+ //{
+ // //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp.");
+ //}
+
+ //// And make it look local again to fool the unix time util
+ //dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
+
+ // If client is null, this message comes from storage and IS offline
+ if (client != null)
+ im.offline = 0;
+
+ if (im.offline == 0)
+ im.timestamp = (uint)Util.UnixTimeSinceEpoch();
+
if (m_TransferModule != null)
{
- if (client != null)
- im.fromAgentName = client.FirstName + " " + client.LastName;
m_TransferModule.SendInstantMessage(im,
delegate(bool success)
{
@@ -193,7 +224,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
///
///
///
- private void OnGridInstantMessage(GridInstantMessage msg)
+ protected virtual void OnGridInstantMessage(GridInstantMessage msg)
{
// Just call the Text IM handler above
// This event won't be raised unless we have that agent,
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 2462ff8..efb9421 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool m_Enabled = false;
+ protected string m_MessageKey = String.Empty;
protected List m_Scenes = new List();
protected Dictionary m_UserRegionMap = new Dictionary();
@@ -69,14 +70,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
public virtual void Initialise(IConfigSource config)
{
IConfig cnf = config.Configs["Messaging"];
- if (cnf != null && cnf.GetString(
- "MessageTransferModule", "MessageTransferModule") !=
- "MessageTransferModule")
+ if (cnf != null)
{
- m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration");
- return;
- }
+ if (cnf.GetString("MessageTransferModule",
+ "MessageTransferModule") != "MessageTransferModule")
+ {
+ return;
+ }
+ m_MessageKey = cnf.GetString("MessageKey", String.Empty);
+ }
+ m_log.Debug("[MESSAGE TRANSFER]: Module enabled");
m_Enabled = true;
}
@@ -135,53 +139,45 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
UUID toAgentID = new UUID(im.toAgentID);
+ if (toAgentID == UUID.Zero)
+ return;
+
+ IClientAPI client = null;
+
// Try root avatar only first
foreach (Scene scene in m_Scenes)
{
-// m_log.DebugFormat(
-// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
-// toAgentID.ToString(), scene.RegionInfo.RegionName);
-
ScenePresence sp = scene.GetScenePresence(toAgentID);
- if (sp != null && !sp.IsChildAgent)
+ if (sp != null && !sp.IsDeleted && sp.ControllingClient.IsActive)
{
- // Local message
-// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
-
- sp.ControllingClient.SendInstantMessage(im);
+ // actualy don't send via child agents
+ // ims can be complex things, and not sure viewers will not mess up
+ if(sp.IsChildAgent)
+ continue;
- // Message sent
- result(true);
- return;
+ client = sp.ControllingClient;
+ if(!sp.IsChildAgent)
+ break;
}
}
- // try child avatar second
- foreach (Scene scene in m_Scenes)
+ if(client != null)
{
-// m_log.DebugFormat(
-// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
-
- ScenePresence sp = scene.GetScenePresence(toAgentID);
- if (sp != null)
- {
- // Local message
-// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
+ // Local message
+// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
- sp.ControllingClient.SendInstantMessage(im);
+ client.SendInstantMessage(im);
// Message sent
- result(true);
- return;
- }
+ result(true);
+ return;
}
-
// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
SendGridInstantMessageViaXMLRPC(im, result);
}
- public void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
+ public virtual void HandleUndeliverableMessage(GridInstantMessage im, MessageResultNotification result)
{
UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
@@ -211,10 +207,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
{
bool successful = false;
-
+
// TODO: For now, as IMs seem to be a bit unreliable on OSGrid, catch all exception that
// happen here and aren't caught and log them.
- try
+ try
{
// various rational defaults
UUID fromAgentID = UUID.Zero;
@@ -236,7 +232,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
float pos_z = 0;
//m_log.Info("Processing IM");
-
Hashtable requestData = (Hashtable)request.Params[0];
// Check if it's got all the data
if (requestData.ContainsKey("from_agent_id")
@@ -249,6 +244,19 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
&& requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
&& requestData.ContainsKey("binary_bucket"))
{
+ if (m_MessageKey != String.Empty)
+ {
+ XmlRpcResponse error_resp = new XmlRpcResponse();
+ Hashtable error_respdata = new Hashtable();
+ error_respdata["success"] = "FALSE";
+ error_resp.Value = error_respdata;
+
+ if (!requestData.Contains("message_key"))
+ return error_resp;
+ if (m_MessageKey != (string)requestData["message_key"])
+ return error_resp;
+ }
+
// Do the easy way of validating the UUIDs
UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
@@ -382,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
gim.Position = Position;
gim.binaryBucket = binaryBucket;
-
// Trigger the Instant message in the scene.
foreach (Scene scene in m_Scenes)
{
@@ -425,104 +432,191 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
return resp;
}
+
///
/// delegate for sending a grid instant message asynchronously
///
- public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
+ private delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result);
+
+ private class GIM {
+ public GridInstantMessage im;
+ public MessageResultNotification result;
+ };
- protected virtual void GridInstantMessageCompleted(IAsyncResult iar)
+ private Queue pendingInstantMessages = new Queue();
+ private int numInstantMessageThreads = 0;
+
+ private void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
{
- GridInstantMessageDelegate icon =
- (GridInstantMessageDelegate)iar.AsyncState;
- icon.EndInvoke(iar);
+ lock (pendingInstantMessages) {
+ if (numInstantMessageThreads >= 4) {
+ GIM gim = new GIM();
+ gim.im = im;
+ gim.result = result;
+ pendingInstantMessages.Enqueue(gim);
+ } else {
+ ++ numInstantMessageThreads;
+ //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: ++numInstantMessageThreads={0}", numInstantMessageThreads);
+ GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsyncMain;
+ d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
+ }
+ }
}
- protected virtual void SendGridInstantMessageViaXMLRPC(GridInstantMessage im, MessageResultNotification result)
+ private void GridInstantMessageCompleted(IAsyncResult iar)
{
- GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync;
-
- d.BeginInvoke(im, result, GridInstantMessageCompleted, d);
+ GridInstantMessageDelegate d = (GridInstantMessageDelegate)iar.AsyncState;
+ d.EndInvoke(iar);
}
///
/// Internal SendGridInstantMessage over XMLRPC method.
///
- ///
- /// This is called from within a dedicated thread.
- ///
- private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result)
+
+ ///
+ /// Pass in 0 the first time this method is called. It will be called recursively with the last
+ /// regionhandle tried
+ ///
+ private void SendGridInstantMessageViaXMLRPCAsyncMain(GridInstantMessage im, MessageResultNotification result)
+ {
+ GIM gim;
+ do {
+ try {
+ SendGridInstantMessageViaXMLRPCAsync(im, result, UUID.Zero);
+ } catch (Exception e) {
+ m_log.Error("[SendGridInstantMessageViaXMLRPC]: exception " + e.Message);
+ }
+ lock (pendingInstantMessages) {
+ if (pendingInstantMessages.Count > 0) {
+ gim = pendingInstantMessages.Dequeue();
+ im = gim.im;
+ result = gim.result;
+ } else {
+ gim = null;
+ -- numInstantMessageThreads;
+ //m_log.DebugFormat("[SendGridInstantMessageViaXMLRPC]: --numInstantMessageThreads={0}", numInstantMessageThreads);
+ }
+ }
+ } while (gim != null);
+ }
+
+ private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID)
{
+
UUID toAgentID = new UUID(im.toAgentID);
- UUID regionID;
- bool needToLookupAgent;
+ PresenceInfo upd = null;
+ bool lookupAgent = false;
lock (m_UserRegionMap)
- needToLookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID);
-
- while (true)
{
- if (needToLookupAgent)
+ if (m_UserRegionMap.ContainsKey(toAgentID))
{
- PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
-
- UUID foundRegionID = UUID.Zero;
+ upd = new PresenceInfo();
+ upd.RegionID = m_UserRegionMap[toAgentID];
- if (presences != null)
+ // We need to compare the current regionhandle with the previous region handle
+ // or the recursive loop will never end because it will never try to lookup the agent again
+ if (prevRegionID == upd.RegionID)
{
- foreach (PresenceInfo p in presences)
- {
- if (p.RegionID != UUID.Zero)
- {
- foundRegionID = p.RegionID;
- break;
- }
- }
+ lookupAgent = true;
}
-
- // If not found or the found region is the same as the last lookup, then message is undeliverable
- if (foundRegionID == UUID.Zero || foundRegionID == regionID)
- break;
- else
- regionID = foundRegionID;
}
-
- GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID);
- if (reginfo == null)
+ else
{
- m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID);
- break;
+ lookupAgent = true;
}
+ }
- // Try to send the message to the agent via the retrieved region.
- Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
- msgdata["region_handle"] = 0;
- bool imresult = doIMSending(reginfo, msgdata);
- // If the message delivery was successful, then cache the entry.
- if (imresult)
+ // Are we needing to look-up an agent?
+ if (lookupAgent)
+ {
+ // Non-cached user agent lookup.
+ PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() });
+ if (presences != null && presences.Length > 0)
{
- lock (m_UserRegionMap)
+ foreach (PresenceInfo p in presences)
{
- m_UserRegionMap[toAgentID] = regionID;
+ if (p.RegionID != UUID.Zero)
+ {
+ upd = p;
+ break;
+ }
}
- result(true);
- return;
}
- // If we reach this point in the first iteration of the while, then we may have unsuccessfully tried
- // to use a locally cached region ID. All subsequent attempts need to lookup agent details from
- // the presence service.
- needToLookupAgent = true;
+ if (upd != null)
+ {
+ // check if we've tried this before..
+ // This is one way to end the recursive loop
+ //
+ if (upd.RegionID == prevRegionID)
+ {
+ // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
+ HandleUndeliverableMessage(im, result);
+ return;
+ }
+ }
+ else
+ {
+ // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
+ HandleUndeliverableMessage(im, result);
+ return;
+ }
}
- // If we reached this point then the message was not deliverable. Remove the bad cache entry and
- // signal the delivery failure.
- lock (m_UserRegionMap)
- m_UserRegionMap.Remove(toAgentID);
+ if (upd != null)
+ {
+ GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(UUID.Zero,
+ upd.RegionID);
+ if (reginfo != null)
+ {
+ Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im);
+ // Not actually used anymore, left in for compatibility
+ // Remove at next interface change
+ //
+ msgdata["region_handle"] = 0;
+ bool imresult = doIMSending(reginfo, msgdata);
+ if (imresult)
+ {
+ // IM delivery successful, so store the Agent's location in our local cache.
+ lock (m_UserRegionMap)
+ {
+ if (m_UserRegionMap.ContainsKey(toAgentID))
+ {
+ m_UserRegionMap[toAgentID] = upd.RegionID;
+ }
+ else
+ {
+ m_UserRegionMap.Add(toAgentID, upd.RegionID);
+ }
+ }
+ result(true);
+ }
+ else
+ {
+ // try again, but lookup user this time.
+ // Warning, this must call the Async version
+ // of this method or we'll be making thousands of threads
+ // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
+ // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
- // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
- HandleUndeliverableMessage(im, result);
+ // This is recursive!!!!!
+ SendGridInstantMessageViaXMLRPCAsync(im, result,
+ upd.RegionID);
+ }
+ }
+ else
+ {
+ m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID);
+ HandleUndeliverableMessage(im, result);
+ }
+ }
+ else
+ {
+ HandleUndeliverableMessage(im, result);
+ }
}
///
@@ -622,8 +716,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
gim["position_z"] = msg.Position.Z.ToString();
gim["region_id"] = new UUID(msg.RegionID).ToString();
gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket,Base64FormattingOptions.None);
+ if (m_MessageKey != String.Empty)
+ gim["message_key"] = m_MessageKey;
return gim;
}
-
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
index 315d372..2d57193 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
@@ -118,11 +118,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
get { return null; }
}
-
+
public void Close()
{
}
-
+
private void OnNewClient(IClientAPI client)
{
client.OnMuteListRequest += OnMuteListRequest;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
new file mode 100644
index 0000000..6857f35
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModuleTst.cs
@@ -0,0 +1,229 @@
+/*
+ * 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 OpenSimulator 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.Generic;
+using System.Reflection;
+using System.Text;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Framework.Servers;
+using OpenSim.Framework.Client;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using Mono.Addins;
+
+using OpenSim.Server.Base;
+using OpenSim.Services.Interfaces;
+
+namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MuteListModuleTst")]
+ public class MuteListModuleTst : ISharedRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected bool m_Enabled = false;
+ protected List m_SceneList = new List();
+ protected IMuteListService m_service = null;
+
+ public void Initialise(IConfigSource config)
+ {
+ IConfig cnf = config.Configs["Messaging"];
+ if (cnf == null)
+ return;
+
+ if (cnf.GetString("MuteListModule", "None") != "MuteListModuleTst")
+ return;
+
+ m_Enabled = true;
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ if (!m_Enabled)
+ return;
+
+ IXfer xfer = scene.RequestModuleInterface();
+ if (xfer == null)
+ {
+ m_log.ErrorFormat("[MuteListModuleTst]: Xfer not availble in region {0}. Module Disabled", scene.Name);
+ m_Enabled = false;
+ return;
+ }
+
+ IMuteListService srv = scene.RequestModuleInterface();
+ if(srv == null)
+ {
+ m_log.ErrorFormat("[MuteListModuleTst]: MuteListService not availble in region {0}. Module Disabled", scene.Name);
+ m_Enabled = false;
+ return;
+ }
+ lock (m_SceneList)
+ {
+ if(m_service == null)
+ m_service = srv;
+ m_SceneList.Add(scene);
+ scene.EventManager.OnNewClient += OnNewClient;
+ }
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ lock (m_SceneList)
+ {
+ if(m_SceneList.Contains(scene))
+ {
+ m_SceneList.Remove(scene);
+ scene.EventManager.OnNewClient -= OnNewClient;
+ }
+ }
+ }
+
+ public void PostInitialise()
+ {
+ if (!m_Enabled)
+ return;
+
+ m_log.Debug("[MuteListModuleTst]: enabled");
+ }
+
+ public string Name
+ {
+ get { return "MuteListModuleTst"; }
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ public void Close()
+ {
+ }
+
+ private void OnNewClient(IClientAPI client)
+ {
+ client.OnMuteListRequest += OnMuteListRequest;
+ client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
+ client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
+ }
+
+ private void OnMuteListRequest(IClientAPI client, uint crc)
+ {
+ if (!m_Enabled)
+ {
+ if(crc == 0)
+ client.SendEmpytMuteList();
+ else
+ client.SendUseCachedMuteList();
+ return;
+ }
+
+ IXfer xfer = client.Scene.RequestModuleInterface();
+ if (xfer == null)
+ {
+ if(crc == 0)
+ client.SendEmpytMuteList();
+ else
+ client.SendUseCachedMuteList();
+ return;
+ }
+
+ Byte[] data = m_service.MuteListRequest(client.AgentId, crc);
+ if (data == null)
+ {
+ if(crc == 0)
+ client.SendEmpytMuteList();
+ else
+ client.SendUseCachedMuteList();
+ return;
+ }
+
+ if (data.Length == 0)
+ {
+ client.SendEmpytMuteList();
+ return;
+ }
+
+ if (data.Length == 1)
+ {
+ if(crc == 0)
+ client.SendEmpytMuteList();
+ else
+ client.SendUseCachedMuteList();
+ return;
+ }
+
+ string filename = "mutes" + client.AgentId.ToString();
+ xfer.AddNewFile(filename, data);
+ client.SendMuteListUpdate(filename);
+ }
+
+ private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
+ {
+ if (!m_Enabled)
+ return;
+
+ UUID agentID = client.AgentId;
+ if(muteType == 1) // agent
+ {
+ if(agentID == muteID)
+ return;
+ if(m_SceneList[0].Permissions.IsAdministrator(muteID))
+ {
+ OnMuteListRequest(client, 0);
+ return;
+ }
+ }
+
+ MuteData mute = new MuteData();
+ mute.AgentID = agentID;
+ mute.MuteID = muteID;
+ mute.MuteName = muteName;
+ mute.MuteType = muteType;
+ mute.MuteFlags = (int)muteFlags;
+ mute.Stamp = Util.UnixTimeSinceEpoch();
+
+ m_service.UpdateMute(mute);
+ }
+
+ private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
+ {
+ if (!m_Enabled)
+ return;
+ m_service.RemoveMute(client.AgentId, muteID, muteName);
+ }
+ }
+}
+
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 9cdb1c2..315ce1b 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -39,16 +39,25 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
+ public struct SendReply
+ {
+ public bool Success;
+ public string Message;
+ public int Disposition;
+ }
+
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OfflineMessageModule")]
public class OfflineMessageModule : ISharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private bool enabled = true;
+ private bool m_UseNewAvnCode = false;
private List m_SceneList = new List();
private string m_RestURL = String.Empty;
IMessageTransferModule m_TransferModule = null;
private bool m_ForwardOfflineGroupMessages = true;
+ private Dictionary> m_repliesSent= new Dictionary>();
public void Initialise(IConfigSource config)
{
@@ -74,6 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
}
m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages);
+ m_UseNewAvnCode = cnf.GetBoolean("UseNewAvnCode", m_UseNewAvnCode);
}
public void AddRegion(Scene scene)
@@ -138,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
{
get { return null; }
}
-
+
public void Close()
{
}
@@ -168,11 +178,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
private void OnNewClient(IClientAPI client)
{
client.OnRetrieveInstantMessages += RetrieveInstantMessages;
+ client.OnLogout += OnClientLoggedOut;
+ }
+
+ public void OnClientLoggedOut(IClientAPI client)
+ {
+ m_repliesSent.Remove(client);
}
private void RetrieveInstantMessages(IClientAPI client)
{
- if (m_RestURL != "")
+ if (m_RestURL == String.Empty)
+ {
+ return;
+ }
+ else
{
m_log.DebugFormat("[OFFLINE MESSAGING]: Retrieving stored messages for {0}", client.AgentId);
@@ -180,28 +200,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
= SynchronousRestObjectRequester.MakeRequest>(
"POST", m_RestURL + "/RetrieveMessages/", client.AgentId);
- if (msglist == null)
- {
- m_log.WarnFormat("[OFFLINE MESSAGING]: WARNING null message list.");
- return;
- }
-
- foreach (GridInstantMessage im in msglist)
+ if (msglist != null)
{
- if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
- // send it directly or else the item will be given twice
- client.SendInstantMessage(im);
- else
+ foreach (GridInstantMessage im in msglist)
{
- // Send through scene event manager so all modules get a chance
- // to look at this message before it gets delivered.
- //
- // Needed for proper state management for stored group
- // invitations
- //
- Scene s = FindScene(client.AgentId);
- if (s != null)
- s.EventManager.TriggerIncomingInstantMessage(im);
+ if (im.dialog == (byte)InstantMessageDialog.InventoryOffered)
+ // send it directly or else the item will be given twice
+ client.SendInstantMessage(im);
+ else
+ {
+ // Send through scene event manager so all modules get a chance
+ // to look at this message before it gets delivered.
+ //
+ // Needed for proper state management for stored group
+ // invitations
+ //
+
+ im.offline = 1;
+
+ Scene s = FindScene(client.AgentId);
+ if (s != null)
+ s.EventManager.TriggerIncomingInstantMessage(im);
+ }
}
}
}
@@ -213,7 +233,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
im.dialog != (byte)InstantMessageDialog.MessageFromAgent &&
im.dialog != (byte)InstantMessageDialog.GroupNotice &&
im.dialog != (byte)InstantMessageDialog.GroupInvitation &&
- im.dialog != (byte)InstantMessageDialog.InventoryOffered)
+ im.dialog != (byte)InstantMessageDialog.InventoryOffered &&
+ im.dialog != (byte)InstantMessageDialog.TaskInventoryOffered)
{
return;
}
@@ -225,22 +246,73 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
return;
}
- bool success = SynchronousRestObjectRequester.MakeRequest(
- "POST", m_RestURL+"/SaveMessage/", im, 10000);
+ if(m_UseNewAvnCode)
+ {
+ Scene scene = FindScene(new UUID(im.fromAgentID));
+ if (scene == null)
+ scene = m_SceneList[0];
- if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
+ UUID scopeID = scene.RegionInfo.ScopeID;
+ SendReply reply = SynchronousRestObjectRequester.MakeRequest(
+ "POST", m_RestURL+"/SaveMessage/?scope=" + scopeID.ToString(), im, 20000);
+
+ if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
+ {
+ IClientAPI client = FindClient(new UUID(im.fromAgentID));
+ if (client == null)
+ return;
+
+ if (string.IsNullOrEmpty(reply.Message))
+ reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved");
+
+ bool sendReply = true;
+
+ switch (reply.Disposition)
+ {
+ case 0: // Normal
+ break;
+ case 1: // Only once per user
+ if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID)))
+ sendReply = false;
+ else
+ {
+ if (!m_repliesSent.ContainsKey(client))
+ m_repliesSent[client] = new List();
+ m_repliesSent[client].Add(new UUID(im.toAgentID));
+ }
+ break;
+ }
+
+ if (sendReply)
+ {
+ client.SendInstantMessage(new GridInstantMessage(
+ null, new UUID(im.toAgentID),
+ "System", new UUID(im.fromAgentID),
+ (byte)InstantMessageDialog.MessageFromAgent,
+ reply.Message,
+ false, new Vector3()));
+ }
+ }
+ }
+ else
{
- IClientAPI client = FindClient(new UUID(im.fromAgentID));
- if (client == null)
- return;
+ bool success = SynchronousRestObjectRequester.MakeRequest(
+ "POST", m_RestURL+"/SaveMessage/", im, 20000);
+
+ if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
+ {
+ IClientAPI client = FindClient(new UUID(im.fromAgentID));
+ if (client == null)
+ return;
- client.SendInstantMessage(new GridInstantMessage(
+ client.SendInstantMessage(new GridInstantMessage(
null, new UUID(im.toAgentID),
"System", new UUID(im.fromAgentID),
(byte)InstantMessageDialog.MessageFromAgent,
"User is not logged in. "+
(success ? "Message saved." : "Message not saved"),
false, new Vector3()));
+ }
}
}
}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
new file mode 100644
index 0000000..b61e848
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/XMuteModule.cs
@@ -0,0 +1,239 @@
+/*
+ * 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 OpenSimulator 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.Generic;
+using System.Reflection;
+using System.Text;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
+using OpenSim.Framework;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes;
+using Mono.Addins;
+using OpenSim.Data.MySQL;
+using MySql.Data.MySqlClient;
+
+
+namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
+{
+ [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XMute")]
+ public class XMuteModule : ISharedRegionModule
+ {
+ private static readonly ILog m_log = LogManager.GetLogger(
+ MethodBase.GetCurrentMethod().DeclaringType);
+
+ protected bool m_Enabled = true;
+ protected List m_SceneList = new List();
+ protected MuteTableHandler m_MuteTable;
+ protected string m_DatabaseConnect;
+
+ public void Initialise(IConfigSource config)
+ {
+ IConfig cnf = config.Configs["Messaging"];
+ if (cnf == null)
+ {
+ m_Enabled = false;
+ return;
+ }
+
+ if (cnf.GetString("MuteListModule", "None") !=
+ "XMute")
+ {
+ m_Enabled = false;
+ return;
+ }
+
+ m_DatabaseConnect = cnf.GetString("MuteDatabaseConnect", String.Empty);
+ if (m_DatabaseConnect == String.Empty)
+ {
+ m_log.Debug("[XMute]: MuteDatabaseConnect missing or empty");
+ m_Enabled = false;
+ return;
+ }
+
+ m_MuteTable = new MuteTableHandler(
+ m_DatabaseConnect, "XMute", String.Empty);
+ }
+
+ public void AddRegion(Scene scene)
+ {
+ if (!m_Enabled)
+ return;
+
+ lock (m_SceneList)
+ {
+ m_SceneList.Add(scene);
+
+ scene.EventManager.OnNewClient += OnNewClient;
+ }
+ }
+
+ public void RegionLoaded(Scene scene)
+ {
+ }
+
+ public void RemoveRegion(Scene scene)
+ {
+ if (!m_Enabled)
+ return;
+
+ lock (m_SceneList)
+ {
+ m_SceneList.Remove(scene);
+ }
+ }
+
+ public void PostInitialise()
+ {
+ if (!m_Enabled)
+ return;
+
+ m_log.Debug("[XMute]: Mute list enabled");
+ }
+
+ public string Name
+ {
+ get { return "XMuteModule"; }
+ }
+
+ public Type ReplaceableInterface
+ {
+ get { return null; }
+ }
+
+ public void Close()
+ {
+ }
+
+ private void OnNewClient(IClientAPI client)
+ {
+ client.OnMuteListRequest += OnMuteListRequest;
+ client.OnUpdateMuteListEntry += OnUpdateMuteListEntry;
+ client.OnRemoveMuteListEntry += OnRemoveMuteListEntry;
+ }
+
+ private void OnMuteListRequest(IClientAPI client, uint crc)
+ {
+ string filename = "mutes"+client.AgentId.ToString();
+
+ IXfer xfer = client.Scene.RequestModuleInterface();
+ if (xfer != null)
+ {
+ MuteData[] data = m_MuteTable.Get("AgentID", client.AgentId.ToString());
+ if (data == null || data.Length == 0)
+ {
+ xfer.AddNewFile(filename, new Byte[0]);
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder(1024);
+
+ foreach (MuteData d in data)
+ sb.AppendFormat("{0} {1} {2}|{3}\n",
+ d.MuteType,
+ d.MuteID.ToString(),
+ d.MuteName,
+ d.MuteFlags);
+
+ Byte[] filedata = Util.UTF8.GetBytes(sb.ToString());
+
+ uint dataCrc = Crc32.Compute(filedata);
+
+ if (dataCrc == crc)
+ {
+ client.SendUseCachedMuteList();
+ return;
+ }
+
+ xfer.AddNewFile(filename, filedata);
+ }
+
+ client.SendMuteListUpdate(filename);
+ }
+ }
+
+ private void OnUpdateMuteListEntry(IClientAPI client, UUID muteID, string muteName, int muteType, uint muteFlags)
+ {
+ MuteData mute = new MuteData();
+
+ mute.AgentID = client.AgentId;
+ mute.MuteID = muteID;
+ mute.MuteName = muteName;
+ mute.MuteType = muteType;
+ mute.MuteFlags = (int)muteFlags;
+ mute.Stamp = Util.UnixTimeSinceEpoch();
+
+ m_MuteTable.Store(mute);
+ }
+
+ private void OnRemoveMuteListEntry(IClientAPI client, UUID muteID, string muteName)
+ {
+ m_MuteTable.Delete(new string[] { "AgentID",
+ "MuteID",
+ "MuteName" },
+ new string[] { client.AgentId.ToString(),
+ muteID.ToString(),
+ muteName });
+ }
+ }
+
+ public class MuteTableHandler : MySQLGenericTableHandler
+ {
+ public MuteTableHandler(string conn, string realm, string m) : base(conn, realm, m)
+ {
+ }
+
+ public bool Delete(string[] fields, string[] val)
+ {
+ if (fields.Length != val.Length)
+ return false;
+
+ using (MySqlCommand cmd = new MySqlCommand())
+ {
+ string text = String.Format("delete from {0} where ", m_Realm);
+
+ List terms = new List();
+
+ for (int i = 0 ; i < fields.Length ; i++)
+ {
+ terms.Add(String.Format("{0} = ?{0}", fields[i]));
+ cmd.Parameters.AddWithValue("?" + fields[i], val[i]);
+ }
+
+ text += string.Join(" and ", terms.ToArray());
+
+ cmd.CommandText = text;
+
+ if (ExecuteNonQuery(cmd) > 0)
+ return true;
+ return false;
+ }
+ }
+ }
+}
+
--
cgit v1.1