From 134f86e8d5c414409631b25b8c6f0ee45fbd8631 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Thu, 3 Nov 2016 21:44:39 +1000 Subject: Initial update to OpenSim 0.8.2.1 source code. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 289 ++++++++++++++------- .../Avatar/XmlRpcGroups/GroupsModule.cs | 272 ++++++++++++------- .../SimianGroupsServicesConnectorModule.cs | 6 +- .../Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs | 214 ++++++++++++++- .../XmlRpcGroupsServicesConnectorModule.cs | 71 +++-- 5 files changed, 621 insertions(+), 231 deletions(-) (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups') diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 2802e2f..e1b6abb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -55,8 +55,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IGroupsServicesConnector m_groupData = null; // Config Options - private bool m_groupMessagingEnabled = false; - private bool m_debugEnabled = true; + private bool m_groupMessagingEnabled; + private bool m_debugEnabled; /// /// If enabled, module only tries to send group IMs to online users by querying cached presence information. @@ -113,7 +113,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_messageOnlineAgentsOnly) m_usersOnlineCache = new ExpiringCache(); - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + m_debugEnabled = groupsConfig.GetBoolean("MessagingDebugEnabled", m_debugEnabled); } m_log.InfoFormat( @@ -127,6 +127,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; scene.RegisterModuleInterface(this); + + scene.AddCommand( + "Debug", + this, + "debug groups messaging verbose", + "debug groups messaging verbose ", + "This setting turns on very verbose groups messaging debugging", + HandleDebugGroupsMessagingVerbose); } public void RegionLoaded(Scene scene) @@ -218,6 +226,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + private void HandleDebugGroupsMessagingVerbose(object modules, string[] args) + { + if (args.Length < 5) + { + MainConsole.Instance.Output("Usage: debug groups messaging verbose "); + return; + } + + bool verbose = false; + if (!bool.TryParse(args[4], out verbose)) + { + MainConsole.Instance.Output("Usage: debug groups messaging verbose "); + return; + } + + m_debugEnabled = verbose; + + MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); + } + /// /// Not really needed, but does confirm that the group exists. /// @@ -237,11 +265,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return false; } } - + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { - List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); + SendMessageToGroup(im, groupID, new UUID(im.fromAgentID), null); + } + + public void SendMessageToGroup( + GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func sendCondition) + { + int requestStartTick = Environment.TickCount; + + List groupMembers = m_groupData.GetGroupMembers(sendingAgentForGroupCalls, groupID); int groupMembersCount = groupMembers.Count; + HashSet attemptDeliveryUuidSet = null; if (m_messageOnlineAgentsOnly) { @@ -257,10 +294,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); } - HashSet onlineAgentsUuidSet = new HashSet(); - Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); + attemptDeliveryUuidSet + = new HashSet(Array.ConvertAll(onlineAgents, pi => pi.UserID)); + + //Array.ForEach(onlineAgents, pi => attemptDeliveryUuidSet.Add(pi.UserID)); - groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); + //groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) // m_log.DebugFormat( @@ -269,26 +308,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } else { + attemptDeliveryUuidSet + = new HashSet(groupMembers.ConvertAll(gmd => gmd.AgentID.ToString())); + if (m_debugEnabled) m_log.DebugFormat( "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", groupID, groupMembers.Count); - } - - int requestStartTick = Environment.TickCount; + } foreach (GroupMembersData member in groupMembers) { - if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) + if (sendCondition != null) + { + if (!sendCondition(member)) + { + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition", + member.AgentID); + + continue; + } + } + else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); + continue; } // Copy Message GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = groupID.Guid; + msg.imSessionID = im.imSessionID; msg.fromAgentName = im.fromAgentName; msg.message = im.message; msg.dialog = im.dialog; @@ -304,26 +359,51 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.toAgentID = member.AgentID.Guid; - IClientAPI client = GetActiveClient(member.AgentID); - if (client == null) + if (attemptDeliveryUuidSet.Contains(member.AgentID.ToString())) { - // If they're not local, forward across the grid - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); - m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + IClientAPI client = GetActiveClient(member.AgentID); + if (client == null) + { + int startTick = Environment.TickCount; + + // If they're not local, forward across the grid + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: Delivering to {0} via grid took {1} ms", + member.AgentID, Environment.TickCount - startTick); + } + else + { + int startTick = Environment.TickCount; + + ProcessMessageFromGroupSession(msg, client); + + // Deliver locally, directly + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: Delivering to {0} locally took {1} ms", + member.AgentID, Environment.TickCount - startTick); + } } else { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - ProcessMessageFromGroupSession(msg); + int startTick = Environment.TickCount; + + m_msgTransferModule.HandleUndeliverableMessage(msg, delegate(bool success) { }); + + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: Handling undeliverable message for {0} took {1} ms", + member.AgentID, Environment.TickCount - startTick); } } - // Temporary for assessing how long it still takes to send messages to large online groups. - if (m_messageOnlineAgentsOnly) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", - groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); + "[GROUPS-MESSAGING]: Total SendMessageToGroup for group {0} with {1} members, {2} candidates for delivery took {3} ms", + groupID, groupMembersCount, attemptDeliveryUuidSet.Count(), Environment.TickCount - requestStartTick); } #region SimGridEventHandlers @@ -348,7 +428,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Any other message type will not be delivered to a client by the // Instant Message Module - if (m_debugEnabled) { m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -362,13 +441,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) { - ProcessMessageFromGroupSession(msg); + IClientAPI client = null; + + if (msg.dialog == (byte)InstantMessageDialog.SessionSend) + { + client = GetActiveClient(new UUID(msg.toAgentID)); + + if (client != null) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name); + } + else + { + m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); + + return; + } + } + + ProcessMessageFromGroupSession(msg, client); } } - private void ProcessMessageFromGroupSession(GridInstantMessage msg) + private void ProcessMessageFromGroupSession(GridInstantMessage msg, IClientAPI client) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: Session message from {0} going to agent {1}, sessionID {2}, type {3}", + msg.fromAgentName, msg.toAgentID, msg.imSessionID, (InstantMessageDialog)msg.dialog); UUID AgentID = new UUID(msg.fromAgentID); UUID GroupID = new UUID(msg.imSessionID); @@ -392,74 +493,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Add them to the session for now, and Invite them m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - UUID toAgentID = new UUID(msg.toAgentID); - IClientAPI activeClient = GetActiveClient(toAgentID); - if (activeClient != null) + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); + if (groupInfo != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); - if (groupInfo != null) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); - - // Force? open the group session dialog??? - // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); - IEventQueue eq = activeClient.Scene.RequestModuleInterface(); - eq.ChatterboxInvitation( - GroupID - , groupInfo.GroupName - , new UUID(msg.fromAgentID) - , msg.message - , new UUID(msg.toAgentID) - , msg.fromAgentName - , msg.dialog - , msg.timestamp - , msg.offline == 1 - , (int)msg.ParentEstateID - , msg.Position - , 1 - , new UUID(msg.imSessionID) - , msg.fromGroup - , Utils.StringToBytes(groupInfo.GroupName) - ); - - eq.ChatterBoxSessionAgentListUpdates( - new UUID(GroupID) - , new UUID(msg.fromAgentID) - , new UUID(msg.toAgentID) - , false //canVoiceChat - , false //isModerator - , false //text mute - ); - } + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); + + // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); + IEventQueue eq = client.Scene.RequestModuleInterface(); + eq.ChatterboxInvitation( + GroupID + , groupInfo.GroupName + , new UUID(msg.fromAgentID) + , msg.message + , new UUID(msg.toAgentID) + , msg.fromAgentName + , msg.dialog + , msg.timestamp + , msg.offline == 1 + , (int)msg.ParentEstateID + , msg.Position + , 1 + , new UUID(msg.imSessionID) + , msg.fromGroup + , Utils.StringToBytes(groupInfo.GroupName) + ); + + eq.ChatterBoxSessionAgentListUpdates( + new UUID(GroupID) + , new UUID(msg.fromAgentID) + , new UUID(msg.toAgentID) + , false //canVoiceChat + , false //isModerator + , false //text mute + ); } + + break; } else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) { // User hasn't dropped, so they're in the session, // maybe we should deliver it. - IClientAPI client = GetActiveClient(new UUID(msg.toAgentID)); - if (client != null) - { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} locally", client.Name); - client.SendInstantMessage(msg); - } - else - { - m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); - } + client.SendInstantMessage(msg); } + break; default: - m_log.WarnFormat("[GROUPS-MESSAGING]: I don't know how to proccess a {0} message.", ((InstantMessageDialog)msg.dialog).ToString()); - break; + client.SendInstantMessage(msg); + + break;; } } #endregion - #region ClientEvents private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { @@ -548,15 +637,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Don't log any normal IMs (privacy!) if (m_debugEnabled && im.dialog != (byte)InstantMessageDialog.MessageFromAgent) { - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", ((InstantMessageDialog)im.dialog).ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID.ToString()); - m_log.WarnFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromGroup({0})", im.fromGroup ? "True" : "False"); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: Dialog({0})", (InstantMessageDialog)im.dialog); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentID({0})", im.fromAgentID); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: fromAgentName({0})", im.fromAgentName); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: imSessionID({0})", im.imSessionID); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: message({0})", im.message); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: offline({0})", im.offline); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: toAgentID({0})", im.toAgentID); + m_log.DebugFormat("[GROUPS-MESSAGING]: IM: binaryBucket({0})", OpenMetaverse.Utils.BytesToHexString(im.binaryBucket, "BinaryBucket")); } } @@ -567,7 +656,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private IClientAPI GetActiveClient(UUID agentID) { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); IClientAPI child = null; @@ -579,12 +669,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (!sp.IsChildAgent) { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name); + return sp.ControllingClient; } else { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name); + child = sp.ControllingClient; } } @@ -593,12 +687,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // If we didn't find a root, then just return whichever child we found, or null if none if (child == null) { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); } else { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); } + return child; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 29f9591..1565da9 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -35,10 +35,10 @@ using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; +using System.Text; using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups @@ -76,9 +76,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private List m_sceneList = new List(); - private IMessageTransferModule m_msgTransferModule = null; + private IMessageTransferModule m_msgTransferModule; + + private IGroupsMessagingModule m_groupsMessagingModule; - private IGroupsServicesConnector m_groupData = null; + private IGroupsServicesConnector m_groupData; // Configuration settings private bool m_groupsEnabled = false; @@ -184,10 +186,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_msgTransferModule == null) { m_groupsEnabled = false; - m_log.Warn("[GROUPS]: Could not get MessageTransferModule"); + m_log.Warn("[GROUPS]: Could not get IMessageTransferModule"); } } + if (m_groupsMessagingModule == null) + { + m_groupsMessagingModule = scene.RequestModuleInterface(); + + // No message transfer module, no notices, group invites, rejects, ejects, etc + if (m_groupsMessagingModule == null) + m_log.Warn("[GROUPS]: Could not get IGroupsMessagingModule"); + } + lock (m_sceneList) { m_sceneList.Add(scene); @@ -250,7 +261,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; - client.OnDirFindQuery += OnDirFindQuery; client.OnRequestAvatarProperties += OnRequestAvatarProperties; // Used for Notices and Group Invites/Accept/Reject @@ -303,21 +313,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } */ - void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) - { - if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) - { - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", - System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); - - // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); - } - - } - private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -361,7 +356,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: {0} called for {1}, message type {2}", + System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name, (InstantMessageDialog)im.dialog); // Group invitations if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) @@ -437,81 +435,160 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string Subject = im.message.Substring(0, im.message.IndexOf('|')); string Message = im.message.Substring(Subject.Length + 1); + InventoryItemBase item = null; + bool hasAttachment = false; + UUID itemID = UUID.Zero; //Assignment to quiet compiler + UUID ownerID = UUID.Zero; //Assignment to quiet compiler byte[] bucket; - if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) - { - bucket = new byte[19]; - bucket[0] = 0; //dunno - bucket[1] = 0; //dunno - GroupID.ToBytes(bucket, 2); - bucket[18] = 0; //dunno - } - else + if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0) { string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); binBucket = binBucket.Remove(0, 14).Trim(); - if (m_debugEnabled) + + OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); + if (binBucketOSD is OSD) { - m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); + OSDMap binBucketMap = (OSDMap)binBucketOSD; + + itemID = binBucketMap["item_id"].AsUUID(); + ownerID = binBucketMap["owner_id"].AsUUID(); + + //Attempt to get the details of the attached item. + //If sender doesn't own the attachment, the item + //variable will be set to null and attachment will + //not be included with the group notice. + Scene scene = (Scene)remoteClient.Scene; + item = new InventoryItemBase(itemID, ownerID); + item = scene.InventoryService.GetItem(item); - OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); - - foreach (string key in binBucketOSD.Keys) + if (item != null) { - if (binBucketOSD.ContainsKey(key)) - { - m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString()); - } + //Got item details so include the attachment. + hasAttachment = true; } } - - // treat as if no attachment + else + { + m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType()); + } + } + + if (hasAttachment) + { + //Bucket contains information about attachment. + // + //Byte offset and description of bucket data: + //0: 1 byte indicating if attachment is present + //1: 1 byte indicating the type of attachment + //2: 16 bytes - Group UUID + //18: 16 bytes - UUID of the attachment owner + //34: 16 bytes - UUID of the attachment + //50: variable - Name of the attachment + //??: NUL byte to terminate the attachment name + byte[] name = Encoding.UTF8.GetBytes(item.Name); + bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name + bucket[0] = 1; //Has attachment flag + bucket[1] = (byte)item.InvType; //Type of Attachment + GroupID.ToBytes(bucket, 2); + ownerID.ToBytes(bucket, 18); + itemID.ToBytes(bucket, 34); + name.CopyTo(bucket, 50); + } + else + { bucket = new byte[19]; - bucket[0] = 0; //dunno - bucket[1] = 0; //dunno + bucket[0] = 0; //Has attachment flag + bucket[1] = 0; //Type of attachment GroupID.ToBytes(bucket, 2); - bucket[18] = 0; //dunno + bucket[18] = 0; //NUL terminate name of attachment } - m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); if (OnNewGroupNotice != null) { OnNewGroupNotice(GroupID, NoticeID); } - // Send notice out to everyone that wants notices - foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) + if (m_debugEnabled) { - if (m_debugEnabled) + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) { - UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); - if (targetUser != null) + if (m_debugEnabled) { - m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); - } - else - { - m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); + UserAccount targetUser + = m_sceneList[0].UserAccountService.GetUserAccount( + remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); + + if (targetUser != null) + { + m_log.DebugFormat( + "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", + NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); + } + else + { + m_log.DebugFormat( + "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", + NoticeID, member.AgentID, member.AcceptNotices); + } } } + } - if (member.AcceptNotices) - { - // Build notice IIM - GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); + GridInstantMessage msg + = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); - msg.toAgentID = member.AgentID.Guid; - OutgoingInstantMessage(msg, member.AgentID); - } + if (m_groupsMessagingModule != null) + m_groupsMessagingModule.SendMessageToGroup( + msg, GroupID, remoteClient.AgentId, gmd => gmd.AcceptNotices); + } + } + + if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted) + { + //Is bucket large enough to hold UUID of the attachment? + if (im.binaryBucket.Length < 16) + return; + + UUID noticeID = new UUID(im.imSessionID); + + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS]: Requesting notice {0} for {1}", noticeID, remoteClient.AgentId); + + GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID); + if (notice != null) + { + UUID giver = new UUID(notice.BinaryBucket, 18); + UUID attachmentUUID = new UUID(notice.BinaryBucket, 34); + + if (m_debugEnabled) + m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); + + string message; + InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, + giver, attachmentUUID, out message); + + if (itemCopy == null) + { + remoteClient.SendAgentAlertMessage(message, false); + return; } + + remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); + } + else + { + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.", + noticeID, remoteClient.AgentId); } } - + // Interop, received special 210 code for ejecting a group member // this only works within the comms servers domain, and won't work hypergrid - // TODO:FIXME: Use a presense server of some kind to find out where the + // TODO:FIXME: Use a presence server of some kind to find out where the // client actually is, and try contacting that region directly to notify them, // or provide the notification via xmlrpc update queue if ((im.dialog == 210)) @@ -764,7 +841,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); return UUID.Zero; } - money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); + money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate); } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); @@ -889,26 +966,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (data != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); - - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = data.GroupID.Guid; - msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; - msg.message = data.noticeData.Subject + "|" + data.Message; - msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested; - msg.fromGroup = true; - msg.offline = (byte)0; - msg.ParentEstateID = 0; - msg.Position = Vector3.Zero; - msg.RegionID = UUID.Zero.Guid; - msg.binaryBucket = data.BinaryBucket; + GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested); OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); } - } public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) @@ -916,10 +977,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = UUID.Zero.Guid; + byte[] bucket; + + msg.imSessionID = groupNoticeID.Guid; msg.toAgentID = agentID.Guid; msg.dialog = dialog; - // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice; msg.fromGroup = true; msg.offline = (byte)0; msg.ParentEstateID = 0; @@ -933,13 +995,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.timestamp = info.noticeData.Timestamp; msg.fromAgentName = info.noticeData.FromName; msg.message = info.noticeData.Subject + "|" + info.Message; - msg.binaryBucket = info.BinaryBucket; + + if (info.BinaryBucket[0] > 0) + { + //32 is due to not needing space for two of the UUIDs. + //(Don't need UUID of attachment or its owner in IM) + //50 offset gets us to start of attachment name. + //We are skipping the attachment flag, type, and + //the three UUID fields at the start of the bucket. + bucket = new byte[info.BinaryBucket.Length-32]; + bucket[0] = 1; //Has attachment + bucket[1] = info.BinaryBucket[1]; + Array.Copy(info.BinaryBucket, 50, + bucket, 18, info.BinaryBucket.Length-50); + } + else + { + bucket = new byte[19]; + bucket[0] = 0; //No attachment + bucket[1] = 0; //Attachment type + bucket[18] = 0; //NUL terminate name + } + + info.GroupID.ToBytes(bucket, 2); + msg.binaryBucket = bucket; } else { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); + msg.fromAgentID = UUID.Zero.Guid; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = string.Empty; msg.message = string.Empty; msg.binaryBucket = new byte[0]; @@ -1063,7 +1150,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Message to ejector // Interop, received special 210 code for ejecting a group member // this only works within the comms servers domain, and won't work hypergrid - // TODO:FIXME: Use a presense server of some kind to find out where the + // TODO:FIXME: Use a presence server of some kind to find out where the // client actually is, and try contacting that region directly to notify them, // or provide the notification via xmlrpc update queue @@ -1178,6 +1265,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } + public List FindGroups(IClientAPI remoteClient, string query) + { + return m_groupData.FindGroups(GetRequestingAgentID(remoteClient), query); + } + + #endregion #region Client/Update Tools @@ -1222,7 +1315,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); AgentData.Add(AgentDataMap); - OSDArray GroupData = new OSDArray(data.Length); OSDArray NewGroupData = new OSDArray(data.Length); @@ -1288,7 +1380,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups presence.Grouptitle = Title; if (! presence.IsChildAgent) - presence.SendAvatarDataToAllAgents(); + presence.SendAvatarDataToAllClients(); } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 7bae8f7..1cb4747 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -42,7 +42,6 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; @@ -212,8 +211,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); - if ((m_groupsServerURI == null) || - (m_groupsServerURI == string.Empty)) + if (string.IsNullOrEmpty(m_groupsServerURI)) { m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; @@ -438,7 +436,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return null; } } - else if ((groupName != null) && (groupName != string.Empty)) + else if (!string.IsNullOrEmpty(groupName)) { if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) { diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs index c1bdacb..9a42bac 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs @@ -26,15 +26,25 @@ */ using System; +using System.Collections; +using System.Collections.Generic; +using System.Net; using System.Reflection; using Nini.Config; using NUnit.Framework; using OpenMetaverse; +using OpenMetaverse.Messages.Linden; +using OpenMetaverse.Packets; +using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.ClientStack.Linden; +using OpenSim.Region.CoreModules.Avatar.InstantMessage; +using OpenSim.Region.CoreModules.Framework; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups; using OpenSim.Tests.Common; -using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests { @@ -44,11 +54,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests [TestFixture] public class GroupsModuleTests : OpenSimTestCase { + [SetUp] + public override void SetUp() + { + base.SetUp(); + + uint port = 9999; + uint sslPort = 9998; + + // This is an unfortunate bit of clean up we have to do because MainServer manages things through static + // variables and the VM is not restarted between tests. + MainServer.RemoveHttpServer(port); + + BaseHttpServer server = new BaseHttpServer(port, false, sslPort, ""); + MainServer.AddHttpServer(server); + MainServer.Instance = server; + } + [Test] - public void TestBasic() + public void TestSendAgentGroupDataUpdate() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); TestScene scene = new SceneHelpers().SetupScene(); IConfigSource configSource = new IniConfigSource(); @@ -56,8 +83,185 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests config.Set("Enabled", true); config.Set("Module", "GroupsModule"); config.Set("DebugEnabled", true); + + GroupsModule gm = new GroupsModule(); + EventQueueGetModule eqgm = new EventQueueGetModule(); + + // We need a capabilities module active so that adding the scene presence creates an event queue in the + // EventQueueGetModule SceneHelpers.SetupSceneModules( - scene, configSource, new object[] { new MockGroupsServicesConnector() }); + scene, configSource, gm, new MockGroupsServicesConnector(), new CapabilitiesModule(), eqgm); + + ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseStem("1")); + + gm.SendAgentGroupDataUpdate(sp.ControllingClient); + + Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); + + Assert.That((int)eventsResponse["int_response_code"], Is.EqualTo((int)HttpStatusCode.OK)); + +// Console.WriteLine("Response [{0}]", (string)eventsResponse["str_response_string"]); + + OSDMap rawOsd = (OSDMap)OSDParser.DeserializeLLSDXml((string)eventsResponse["str_response_string"]); + OSDArray eventsOsd = (OSDArray)rawOsd["events"]; + + bool foundUpdate = false; + foreach (OSD osd in eventsOsd) + { + OSDMap eventOsd = (OSDMap)osd; + + if (eventOsd["message"] == "AgentGroupDataUpdate") + foundUpdate = true; + } + + Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response"); + + // TODO: More checking of more actual event data. + } + + [Test] + public void TestSendGroupNotice() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + TestScene scene = new SceneHelpers().SetupScene(); + + MessageTransferModule mtm = new MessageTransferModule(); + GroupsModule gm = new GroupsModule(); + GroupsMessagingModule gmm = new GroupsMessagingModule(); + MockGroupsServicesConnector mgsc = new MockGroupsServicesConnector(); + + IConfigSource configSource = new IniConfigSource(); + + { + IConfig config = configSource.AddConfig("Messaging"); + config.Set("MessageTransferModule", mtm.Name); + } + + { + IConfig config = configSource.AddConfig("Groups"); + config.Set("Enabled", true); + config.Set("Module", gm.Name); + config.Set("DebugEnabled", true); + config.Set("MessagingModule", gmm.Name); + config.Set("MessagingEnabled", true); + } + + SceneHelpers.SetupSceneModules(scene, configSource, mgsc, mtm, gm, gmm); + + UUID userId = TestHelpers.ParseTail(0x1); + string subjectText = "newman"; + string messageText = "Hello"; + string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText); + + ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); + TestClient tc = (TestClient)sp.ControllingClient; + + UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true); + gm.JoinGroupRequest(tc, groupID); + + // Create a second user who doesn't want to receive notices + ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2)); + TestClient tc2 = (TestClient)sp2.ControllingClient; + gm.JoinGroupRequest(tc2, groupID); + gm.SetGroupAcceptNotices(tc2, groupID, false, true); + + List spReceivedMessages = new List(); + tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im); + + List sp2ReceivedMessages = new List(); + tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im); + + GridInstantMessage noticeIm = new GridInstantMessage(); + noticeIm.fromAgentID = userId.Guid; + noticeIm.toAgentID = groupID.Guid; + noticeIm.message = combinedSubjectMessage; + noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice; + + tc.HandleImprovedInstantMessage(noticeIm); + + Assert.That(spReceivedMessages.Count, Is.EqualTo(1)); + Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage)); + + List notices = mgsc.GetGroupNotices(UUID.Zero, groupID); + Assert.AreEqual(1, notices.Count); + + // OpenSimulator (possibly also SL) transport the notice ID as the session ID! + Assert.AreEqual(notices[0].NoticeID.Guid, spReceivedMessages[0].imSessionID); + + Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0)); + } + + /// + /// Run test with the MessageOnlineUsersOnly flag set. + /// + [Test] + public void TestSendGroupNoticeOnlineOnly() + { + TestHelpers.InMethod(); + // TestHelpers.EnableLogging(); + + TestScene scene = new SceneHelpers().SetupScene(); + + MessageTransferModule mtm = new MessageTransferModule(); + GroupsModule gm = new GroupsModule(); + GroupsMessagingModule gmm = new GroupsMessagingModule(); + + IConfigSource configSource = new IniConfigSource(); + + { + IConfig config = configSource.AddConfig("Messaging"); + config.Set("MessageTransferModule", mtm.Name); + } + + { + IConfig config = configSource.AddConfig("Groups"); + config.Set("Enabled", true); + config.Set("Module", gm.Name); + config.Set("DebugEnabled", true); + config.Set("MessagingModule", gmm.Name); + config.Set("MessagingEnabled", true); + config.Set("MessageOnlineUsersOnly", true); + } + + SceneHelpers.SetupSceneModules(scene, configSource, new MockGroupsServicesConnector(), mtm, gm, gmm); + + UUID userId = TestHelpers.ParseTail(0x1); + string subjectText = "newman"; + string messageText = "Hello"; + string combinedSubjectMessage = string.Format("{0}|{1}", subjectText, messageText); + + ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); + TestClient tc = (TestClient)sp.ControllingClient; + + UUID groupID = gm.CreateGroup(tc, "group1", null, true, UUID.Zero, 0, true, true, true); + gm.JoinGroupRequest(tc, groupID); + + // Create a second user who doesn't want to receive notices + ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x2)); + TestClient tc2 = (TestClient)sp2.ControllingClient; + gm.JoinGroupRequest(tc2, groupID); + gm.SetGroupAcceptNotices(tc2, groupID, false, true); + + List spReceivedMessages = new List(); + tc.OnReceivedInstantMessage += im => spReceivedMessages.Add(im); + + List sp2ReceivedMessages = new List(); + tc2.OnReceivedInstantMessage += im => sp2ReceivedMessages.Add(im); + + GridInstantMessage noticeIm = new GridInstantMessage(); + noticeIm.fromAgentID = userId.Guid; + noticeIm.toAgentID = groupID.Guid; + noticeIm.message = combinedSubjectMessage; + noticeIm.dialog = (byte)InstantMessageDialog.GroupNotice; + + tc.HandleImprovedInstantMessage(noticeIm); + + Assert.That(spReceivedMessages.Count, Is.EqualTo(1)); + Assert.That(spReceivedMessages[0].message, Is.EqualTo(combinedSubjectMessage)); + + Assert.That(sp2ReceivedMessages.Count, Is.EqualTo(0)); } } } \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 1101851..20555e4 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -41,7 +41,6 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; @@ -168,8 +167,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); - if ((m_groupsServerURI == null) || - (m_groupsServerURI == string.Empty)) + if (string.IsNullOrEmpty(m_groupsServerURI)) { m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; @@ -354,7 +352,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { param["GroupID"] = GroupID.ToString(); } - if ((GroupName != null) && (GroupName != string.Empty)) + if (!string.IsNullOrEmpty(GroupName)) { param["Name"] = GroupName.ToString(); } @@ -1013,7 +1011,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups Hashtable respData = (Hashtable)resp.Value; if (respData.Contains("error") && !respData.Contains("succeed")) { - LogRespDataToConsoleError(respData); + LogRespDataToConsoleError(requestingAgentID, function, param, respData); } return respData; @@ -1041,20 +1039,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return error; } - private void LogRespDataToConsoleError(Hashtable respData) + private void LogRespDataToConsoleError(UUID requestingAgentID, string function, Hashtable param, Hashtable respData) { - m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); - - foreach (string key in respData.Keys) - { - m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key); - - string[] lines = respData[key].ToString().Split(new char[] { '\n' }); - foreach (string line in lines) - { - m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line); - } - } + m_log.ErrorFormat( + "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}", + function, requestingAgentID, Util.PrettyFormatToSingleLine(param), Util.PrettyFormatToSingleLine(respData)); } /// @@ -1146,28 +1135,38 @@ namespace Nwc.XmlRpc request.AllowWriteStreamBuffering = true; request.KeepAlive = !_disableKeepAlive; - Stream stream = request.GetRequestStream(); - XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII); - _serializer.Serialize(xml, this); - xml.Flush(); - xml.Close(); - - HttpWebResponse response = (HttpWebResponse)request.GetResponse(); - StreamReader input = new StreamReader(response.GetResponseStream()); - - string inputXml = input.ReadToEnd(); - XmlRpcResponse resp; - try + using (Stream stream = request.GetRequestStream()) { - resp = (XmlRpcResponse)_deserializer.Deserialize(inputXml); + using (XmlTextWriter xml = new XmlTextWriter(stream, Encoding.ASCII)) + { + _serializer.Serialize(xml, this); + xml.Flush(); + } } - catch (Exception e) + + XmlRpcResponse resp; + + using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { - RequestResponse = inputXml; - throw e; + using (Stream s = response.GetResponseStream()) + { + using (StreamReader input = new StreamReader(s)) + { + string inputXml = input.ReadToEnd(); + + try + { + resp = (XmlRpcResponse)_deserializer.Deserialize(inputXml); + } + catch (Exception e) + { + RequestResponse = inputXml; + throw e; + } + } + } } - input.Close(); - response.Close(); + return resp; } } -- cgit v1.1