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. --- .../Avatar/Animations/AnimationsCommandModule.cs | 31 +- .../Avatar/Appearance/AppearanceInfoModule.cs | 42 +- .../Avatar/Attachments/AttachmentsCommandModule.cs | 43 +- .../Avatar/Attachments/TempAttachmentsModule.cs | 29 +- .../OptionalModules/Avatar/Chat/ChannelState.cs | 27 +- .../OptionalModules/Avatar/Chat/IRCBridgeModule.cs | 4 +- .../OptionalModules/Avatar/Chat/IRCConnector.cs | 58 +-- .../OptionalModules/Avatar/Chat/RegionState.cs | 43 +- .../Avatar/Concierge/ConciergeModule.cs | 87 ++-- .../Avatar/Friends/FriendsCommandsModule.cs | 20 +- .../Avatar/SitStand/SitStandCommandsModule.cs | 22 +- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 64 +-- .../Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs | 183 +++++--- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 237 +++++----- .../Avatar/XmlRpcGroups/GroupsModule.cs | 517 +++++++++++---------- .../XmlRpcGroups/IGroupsServicesConnector.cs | 7 +- .../SimianGroupsServicesConnectorModule.cs | 95 ++-- .../Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs | 23 +- .../XmlRpcGroupsServicesConnectorModule.cs | 86 ++-- 19 files changed, 841 insertions(+), 777 deletions(-) (limited to 'OpenSim/Region/OptionalModules/Avatar') diff --git a/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs index 84211a9..0698cec 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Animations/AnimationsCommandModule.cs @@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Animation; using OpenSim.Services.Interfaces; +using AnimationSet = OpenSim.Region.Framework.Scenes.Animation.AnimationSet; namespace OpenSim.Region.OptionalModules.Avatar.Animations { @@ -56,41 +57,41 @@ namespace OpenSim.Region.OptionalModules.Avatar.Animations private List m_scenes = new List(); public string Name { get { return "Animations Command Module"; } } - + public Type ReplaceableInterface { get { return null; } } - + public void Initialise(IConfigSource source) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE"); } - + public void PostInitialise() { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE"); } - + public void Close() { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE"); } - + public void AddRegion(Scene scene) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); } - + public void RemoveRegion(Scene scene) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Remove(scene); - } - + } + public void RegionLoaded(Scene scene) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Add(scene); @@ -155,18 +156,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Animations string cma = spa.CurrentMovementAnimation; cdl.AddRow( - "Current movement anim", + "Current movement anim", string.Format("{0}, {1}", DefaultAvatarAnimations.GetDefaultAnimation(cma), cma)); UUID defaultAnimId = anims.DefaultAnimation.AnimID; cdl.AddRow( - "Default anim", + "Default anim", string.Format("{0}, {1}", defaultAnimId, sp.Animator.GetAnimName(defaultAnimId))); UUID implicitDefaultAnimId = anims.ImplicitDefaultAnimation.AnimID; cdl.AddRow( - "Implicit default anim", - string.Format("{0}, {1}", + "Implicit default anim", + string.Format("{0}, {1}", implicitDefaultAnimId, sp.Animator.GetAnimName(implicitDefaultAnimId))); cdl.AddToStringBuilder(sb); @@ -197,4 +198,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Animations sb.Append("\n"); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 2f9bb1e..60ae0cb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -54,43 +54,43 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance private List m_scenes = new List(); // private IAvatarFactoryModule m_avatarFactory; - - public string Name { get { return "Appearance Information Module"; } } - + + public string Name { get { return "Appearance Information Module"; } } + public Type ReplaceableInterface { get { return null; } } - + public void Initialise(IConfigSource source) { // m_log.DebugFormat("[APPEARANCE INFO MODULE]: INITIALIZED MODULE"); } - + public void PostInitialise() { // m_log.DebugFormat("[APPEARANCE INFO MODULE]: POST INITIALIZED MODULE"); } - + public void Close() { // m_log.DebugFormat("[APPEARANCE INFO MODULE]: CLOSED MODULE"); } - + public void AddRegion(Scene scene) { -// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); +// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); } - + public void RemoveRegion(Scene scene) { // m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Remove(scene); - } - + } + public void RegionLoaded(Scene scene) { // m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Add(scene); @@ -99,7 +99,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance "show appearance [ ]", "Synonym for 'appearance show'", HandleShowAppearanceCommand); - + scene.AddCommand( "Users", this, "appearance show", "appearance show [ ]", @@ -222,7 +222,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance } lock (m_scenes) - { + { foreach (Scene scene in m_scenes) { if (targetNameSupplied) @@ -344,7 +344,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance if (targetNameSupplied) { - lock (m_scenes) + lock (m_scenes) { foreach (Scene scene in m_scenes) { @@ -360,12 +360,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance cdt.AddColumn("Name", ConsoleDisplayUtil.UserNameSize); cdt.AddColumn("Wearables", 2); - lock (m_scenes) + lock (m_scenes) { foreach (Scene scene in m_scenes) { scene.ForEachRootScenePresence( - sp => + sp => { int count = 0; @@ -428,7 +428,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance uuidGatherer.AddForInspection(wi.AssetID); uuidGatherer.GatherAll(); - string[] assetStrings + string[] assetStrings = Array.ConvertAll(uuidGatherer.GatheredUuids.Keys.ToArray(), u => u.ToString()); bool[] existChecks = scene.AssetService.AssetsExist(assetStrings); @@ -438,10 +438,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance cdt.AddColumn("Type", 10); cdt.AddColumn("UUID", ConsoleDisplayUtil.UuidSize); cdt.AddColumn("Found", 5); - + for (int k = 0; k < existChecks.Length; k++) cdt.AddRow( - (AssetType)uuidGatherer.GatheredUuids[new UUID(assetStrings[k])], + (AssetType)uuidGatherer.GatheredUuids[new UUID(assetStrings[k])], assetStrings[k], existChecks[k] ? "yes" : "no"); sb.Append(cdt.ToString()); diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 0333747..3685041 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -55,41 +55,41 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments // private IAvatarFactoryModule m_avatarFactory; public string Name { get { return "Attachments Command Module"; } } - + public Type ReplaceableInterface { get { return null; } } - + public void Initialise(IConfigSource source) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: INITIALIZED MODULE"); } - + public void PostInitialise() { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: POST INITIALIZED MODULE"); } - + public void Close() { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: CLOSED MODULE"); } - + public void AddRegion(Scene scene) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); } - + public void RemoveRegion(Scene scene) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Remove(scene); - } - + } + public void RegionLoaded(Scene scene) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); - + lock (m_scenes) m_scenes.Add(scene); @@ -144,14 +144,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments private void GetAttachmentsReport(ScenePresence sp, StringBuilder sb) { - sb.AppendFormat("Attachments for {0}\n", sp.Name); + sb.AppendFormat("Attachments for {0}\n\n", sp.Name); - ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); - ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); - ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); - ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); - ct.Columns.Add(new ConsoleDisplayTableColumn("Position", 15)); + ConsoleDisplayList ct = new ConsoleDisplayList(); // sb.AppendFormat( // " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n", @@ -177,17 +172,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments // attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID, // (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos); - ct.AddRow( - attachmentObject.Name, - attachmentObject.LocalId, - attachmentObject.FromItemID, - ((AttachmentPoint)attachmentObject.AttachmentPoint), - attachmentObject.RootPart.AttachedPos); + ct.Indent = 2; + ct.AddRow("Attachment Name", attachmentObject.Name); + ct.AddRow("Local ID", attachmentObject.LocalId); + ct.AddRow("Item ID", attachmentObject.UUID); + ct.AddRow("From Item ID", attachmentObject.FromItemID); + ct.AddRow("Attach Point", ((AttachmentPoint)attachmentObject.AttachmentPoint)); + ct.AddRow("Position", attachmentObject.RootPart.AttachedPos + "\n\n"); // } } ct.AddToStringBuilder(sb); - sb.Append("\n"); } } } \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index 535bf67..c3f3851 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -125,7 +125,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments SendConsoleOutput(agentID, "Command parameter error"); return; } - + m_scene.StoreExtraSetting("auto_grant_attach_perms", val); SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); @@ -134,11 +134,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); - if (hostPart == null) return 0; - if (hostPart.ParentGroup.IsAttachment) + SceneObjectGroup hostgroup = hostPart.ParentGroup; + + if (hostgroup== null || hostgroup.IsAttachment) return 0; IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); @@ -155,33 +156,33 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments ScenePresence target; if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) return 0; - - if (target.UUID != hostPart.ParentGroup.OwnerID) + + if (target.UUID != hostgroup.OwnerID) { - uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); + uint effectivePerms = hostgroup.EffectiveOwnerPerms; if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) return 0; - hostPart.ParentGroup.SetOwnerId(target.UUID); - hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); + hostgroup.SetOwner(target.UUID, target.ControllingClient.ActiveGroupId); if (m_scene.Permissions.PropagatePermissions()) { - foreach (SceneObjectPart child in hostPart.ParentGroup.Parts) + foreach (SceneObjectPart child in hostgroup.Parts) { child.Inventory.ChangeInventoryOwner(target.UUID); child.TriggerScriptChangedEvent(Changed.OWNER); child.ApplyNextOwnerPermissions(); } + hostgroup.InvalidateEffectivePerms(); } - hostPart.ParentGroup.RootPart.ObjectSaleType = 0; - hostPart.ParentGroup.RootPart.SalePrice = 10; + hostgroup.RootPart.ObjectSaleType = 0; + hostgroup.RootPart.SalePrice = 10; - hostPart.ParentGroup.HasGroupChanged = true; - hostPart.ParentGroup.RootPart.SendPropertiesToClient(target.ControllingClient); - hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); + hostgroup.HasGroupChanged = true; + hostgroup.RootPart.SendPropertiesToClient(target.ControllingClient); + hostgroup.RootPart.ScheduleFullUpdate(); } return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true) ? 1 : 0; diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs index b5d9fda..27ab32f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/ChannelState.cs @@ -38,7 +38,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Avatar.Chat { - // An instance of this class exists for each unique combination of + // An instance of this class exists for each unique combination of // IRC chat interface characteristics, as determined by the supplied // configuration file. @@ -48,7 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private static Regex arg = new Regex(@"\[[^\[\]]*\]"); + private static Regex arg = new Regex(@"(?", idn, from, + // m_log.DebugFormat("[IRC-Connector-{0}] PrivMsg to IRC from {1}: <{2}>", idn, from, // String.Format(pattern, m_ircChannel, from, region, msg)); // One message to the IRC server @@ -521,11 +506,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat c.Message = data["msg"]; c.Type = ChatTypeEnum.Region; c.Position = CenterOfRegion; - c.From = data["nick"]; + c.From = data["nick"] + "@IRC"; c.Sender = null; c.SenderUUID = UUID.Zero; - // Is message "\001ACTION foo bar\001"? + // Is message "\001ACTION foo bar\001"? // Then change to: "/me foo bar" if ((1 == c.Message[0]) && c.Message.Substring(1).StartsWith("ACTION")) @@ -623,8 +608,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat string parms = String.Empty; // ":" indicates that a prefix is present - // There are NEVER more than 17 real - // fields. A parameter that starts with + // There are NEVER more than 17 real + // fields. A parameter that starts with // ":" indicates that the remainder of the // line is a single parameter value. @@ -659,6 +644,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat version = commArgs[2]; usermod = commArgs[3]; chanmod = commArgs[4]; + + m_writer.WriteLine(String.Format("JOIN {0}", m_ircChannel)); + m_writer.Flush(); + m_log.InfoFormat("[IRC-Connector-{0}]: sent request to join {1} ", idn, m_ircChannel); + break; case "005": // Server information break; @@ -721,11 +711,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat case "PONG": break; case "JOIN": - if (m_pending) - { - m_log.InfoFormat("[IRC-Connector-{0}] [{1}] Connected", idn, cmd); - m_pending = false; - } + m_log.DebugFormat("[IRC-Connector-{0}] [{1}] parms = <{2}>", idn, cmd, parms); eventIrcJoin(pfx, cmd, parms); break; @@ -767,7 +753,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat if (IrcChannel.StartsWith(":")) IrcChannel = IrcChannel.Substring(1); - m_log.DebugFormat("[IRC-Connector-{0}] Event: IRCJoin {1}:{2}", idn, m_server, m_ircChannel); + if(IrcChannel == m_ircChannel) + { + m_log.InfoFormat("[IRC-Connector-{0}] Joined requested channel {1} at {2}", idn, IrcChannel,m_server); + m_pending = false; + } + else + m_log.InfoFormat("[IRC-Connector-{0}] Joined unknown channel {1} at {2}", idn, IrcChannel,m_server); BroadcastSim(IrcUser, "/me joins {0}", IrcChannel); } @@ -881,7 +873,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat } // Being marked connected is not enough to ping. Socket establishment can sometimes take a long - // time, in which case the watch dog might try to ping the server before the socket has been + // time, in which case the watch dog might try to ping the server before the socket has been // set up, with nasty side-effects. else if (_pdk_ == 0) diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs index 6ea542c..a3ef83b 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/RegionState.cs @@ -389,39 +389,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat } m_log.DebugFormat("[IRC-Region {0}] heard on channel {1} : {2}", Region, msg.Channel, msg.Message); - string txt = msg.Message; - if (null != avatar) + if (null != avatar && cs.RelayChat && (msg.Channel == 0 || msg.Channel == DEBUG_CHANNEL)) { - if ((!cs.RelayChat) || (msg.Channel != 0 && msg.Channel != DEBUG_CHANNEL)) - return; + string txt = msg.Message; + if (txt.StartsWith("/me ")) + txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4)); + + cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt); + return; } - else + + if (null == avatar && cs.RelayPrivateChannels && null != cs.AccessPassword && + msg.Channel == cs.RelayChannelOut) { - if (cs.RelayPrivateChannels && msg.Channel == cs.RelayChannelOut) + Match m = cs.AccessPasswordRegex.Match(msg.Message); + if (null != m) { - if (null != cs.AccessPassword) - { - Match m = cs.AccessPasswordRegex.Match(msg.Message); - if (null != m) - { - if (m.Groups["avatar"].ToString() != "") - fromName = m.Groups["avatar"].ToString(); - if (m.Groups["message"].ToString() != "") - txt = m.Groups["message"].ToString(); - } - } + m_log.DebugFormat("[IRC] relaying message from {0}: {1}", m.Groups["avatar"].ToString(), + m.Groups["message"].ToString()); + cs.irc.PrivMsg(cs.PrivateMessageFormat, m.Groups["avatar"].ToString(), + scene.RegionInfo.RegionName, m.Groups["message"].ToString()); } - fromName = "OBJECT: " + fromName; } - - if (txt.StartsWith("/me ")) - txt = String.Format("{0} {1}", fromName, msg.Message.Substring(4)); - m_log.DebugFormat("[IRC] relaying message from {0}: {1}", fromName, txt); - cs.irc.PrivMsg(cs.PrivateMessageFormat, fromName, Region, txt); } - // This method gives the region an opportunity to interfere with + // This method gives the region an opportunity to interfere with // message delivery. For now we just enforce the enable/disable // flag. @@ -435,7 +428,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat } } - // This supports any local message traffic that might be needed in + // This supports any local message traffic that might be needed in // support of command processing. At present there is none. internal void LocalChat(string msg) diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index c48e585..a5dc0ad 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -53,15 +53,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private const int DEBUG_CHANNEL = 2147483647; +// private const int DEBUG_CHANNEL = 2147483647; use base value - private List m_scenes = new List(); + private new List m_scenes = new List(); private List m_conciergedScenes = new List(); private bool m_replacingChatModule = false; - private IConfig m_config; - private string m_whoami = "conferencier"; private Regex m_regions = null; private string m_welcomes = null; @@ -72,63 +70,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge private string m_brokerURI = String.Empty; private int m_brokerUpdateTimeout = 300; - internal object m_syncy = new object(); + internal new object m_syncy = new object(); - internal bool m_enabled = false; + internal new bool m_enabled = false; #region ISharedRegionModule Members - public override void Initialise(IConfigSource config) + public override void Initialise(IConfigSource configSource) { - m_config = config.Configs["Concierge"]; + IConfig config = configSource.Configs["Concierge"]; - if (null == m_config) + if (config == null) return; - if (!m_config.GetBoolean("enabled", false)) + if (!config.GetBoolean("enabled", false)) return; m_enabled = true; - // check whether ChatModule has been disabled: if yes, // then we'll "stand in" try { - if (config.Configs["Chat"] == null) + if (configSource.Configs["Chat"] == null) { // if Chat module has not been configured it's // enabled by default, so we are not going to // replace it. m_replacingChatModule = false; } - else + else { - m_replacingChatModule = !config.Configs["Chat"].GetBoolean("enabled", true); + m_replacingChatModule = !configSource.Configs["Chat"].GetBoolean("enabled", true); } } catch (Exception) { m_replacingChatModule = false; } - + m_log.InfoFormat("[Concierge] {0} ChatModule", m_replacingChatModule ? "replacing" : "not replacing"); // take note of concierge channel and of identity - m_conciergeChannel = config.Configs["Concierge"].GetInt("concierge_channel", m_conciergeChannel); - m_whoami = m_config.GetString("whoami", "conferencier"); - m_welcomes = m_config.GetString("welcomes", m_welcomes); - m_announceEntering = m_config.GetString("announce_entering", m_announceEntering); - m_announceLeaving = m_config.GetString("announce_leaving", m_announceLeaving); - m_xmlRpcPassword = m_config.GetString("password", m_xmlRpcPassword); - m_brokerURI = m_config.GetString("broker", m_brokerURI); - m_brokerUpdateTimeout = m_config.GetInt("broker_timeout", m_brokerUpdateTimeout); - + m_conciergeChannel = configSource.Configs["Concierge"].GetInt("concierge_channel", m_conciergeChannel); + m_whoami = config.GetString("whoami", "conferencier"); + m_welcomes = config.GetString("welcomes", m_welcomes); + m_announceEntering = config.GetString("announce_entering", m_announceEntering); + m_announceLeaving = config.GetString("announce_leaving", m_announceLeaving); + m_xmlRpcPassword = config.GetString("password", m_xmlRpcPassword); + m_brokerURI = config.GetString("broker", m_brokerURI); + m_brokerUpdateTimeout = config.GetInt("broker_timeout", m_brokerUpdateTimeout); + m_log.InfoFormat("[Concierge] reporting as \"{0}\" to our users", m_whoami); // calculate regions Regex if (m_regions == null) { - string regions = m_config.GetString("regions", String.Empty); + string regions = config.GetString("regions", String.Empty); if (!String.IsNullOrEmpty(regions)) { m_regions = new Regex(@regions, RegexOptions.Compiled | RegexOptions.IgnoreCase); @@ -136,7 +133,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge } } - public override void AddRegion(Scene scene) { if (!m_enabled) return; @@ -211,7 +207,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge { } - new public Type ReplaceableInterface + new public Type ReplaceableInterface { get { return null; } } @@ -282,7 +278,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge // range of chat to cover the whole // region. however, we don't do this for whisper // (got to have some privacy) - if (c.Type != ChatTypeEnum.Whisper) + if (c.Type != ChatTypeEnum.Whisper) { base.OnChatBroadcast(sender, c); return; @@ -300,17 +296,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge { client.OnLogout += OnClientLoggedOut; - if (m_replacingChatModule) + if (m_replacingChatModule) client.OnChatFromClient += OnChatFromClient; } - + public void OnClientLoggedOut(IClientAPI client) { client.OnLogout -= OnClientLoggedOut; client.OnConnectionClosed -= OnClientLoggedOut; - + if (m_conciergedScenes.Contains(client.Scene)) { Scene scene = client.Scene as Scene; @@ -328,7 +324,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge Scene scene = agent.Scene; m_log.DebugFormat("[Concierge]: {0} enters {1}", agent.Name, scene.RegionInfo.RegionName); WelcomeAvatar(agent, scene); - AnnounceToAgentsRegion(scene, String.Format(m_announceEntering, agent.Name, + AnnounceToAgentsRegion(scene, String.Format(m_announceEntering, agent.Name, scene.RegionInfo.RegionName, scene.GetRootAgentCount())); UpdateBroker(scene); } @@ -341,7 +337,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge { Scene scene = agent.Scene; m_log.DebugFormat("[Concierge]: {0} leaves {1}", agent.Name, scene.RegionInfo.RegionName); - AnnounceToAgentsRegion(scene, String.Format(m_announceLeaving, agent.Name, + AnnounceToAgentsRegion(scene, String.Format(m_announceLeaving, agent.Name, scene.RegionInfo.RegionName, scene.GetRootAgentCount())); UpdateBroker(scene); } @@ -378,7 +374,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge scene.ForEachRootScenePresence(delegate(ScenePresence sp) { - list.Append(String.Format(" \n", sp.Name, sp.UUID)); + list.Append(String.Format(" \n", sp.Name, sp.UUID)); }); list.Append(""); @@ -441,7 +437,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge private void UpdateBrokerDone(IAsyncResult result) { BrokerState bs = null; - try + try { bs = result.AsyncState as BrokerState; HttpWebRequest updatePost = bs.Poster; @@ -454,19 +450,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge catch (WebException we) { m_log.ErrorFormat("[Concierge] broker update to {0} failed with status {1}", bs.Uri, we.Status); - if (null != we.Response) + if (null != we.Response) { using (HttpWebResponse resp = we.Response as HttpWebResponse) { m_log.ErrorFormat("[Concierge] response from {0} status code: {1}", bs.Uri, resp.StatusCode); m_log.ErrorFormat("[Concierge] response from {0} status desc: {1}", bs.Uri, resp.StatusDescription); m_log.ErrorFormat("[Concierge] response from {0} server: {1}", bs.Uri, resp.Server); - - if (resp.ContentLength > 0) + + if (resp.ContentLength > 0) { - StreamReader content = new StreamReader(resp.GetResponseStream()); - m_log.ErrorFormat("[Concierge] response from {0} content: {1}", bs.Uri, content.ReadToEnd()); - content.Close(); + using(StreamReader content = new StreamReader(resp.GetResponseStream())) + m_log.ErrorFormat("[Concierge] response from {0} content: {1}", bs.Uri, content.ReadToEnd()); } } } @@ -480,12 +475,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge // welcome file there: if yes, send it to the agent if (!String.IsNullOrEmpty(m_welcomes)) { - string[] welcomes = new string[] { + string[] welcomes = new string[] { Path.Combine(m_welcomes, agent.Scene.RegionInfo.RegionName), Path.Combine(m_welcomes, "DEFAULT")}; foreach (string welcome in welcomes) { - if (File.Exists(welcome)) + if (File.Exists(welcome)) { try { @@ -504,7 +499,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge { m_log.ErrorFormat("[Concierge]: welcome file {0} is malformed: {1}", welcome, fe); } - } + } return; } m_log.DebugFormat("[Concierge]: no welcome message for region {0}", scene.RegionInfo.RegionName); @@ -516,7 +511,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge // protected void AnnounceToAgentsRegion(Scene scene, string msg) // { // ScenePresence agent = null; - // if ((client.Scene is Scene) && (client.Scene as Scene).TryGetScenePresence(client.AgentId, out agent)) + // if ((client.Scene is Scene) && (client.Scene as Scene).TryGetScenePresence(client.AgentId, out agent)) // AnnounceToAgentsRegion(agent, msg); // else // m_log.DebugFormat("[Concierge]: could not find an agent for client {0}", client.Name); @@ -591,7 +586,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge string regionName = (string)requestData["region"]; IScene scene = m_scenes.Find(delegate(IScene s) { return s.RegionInfo.RegionName == regionName; }); - if (scene == null) + if (scene == null) throw new Exception(String.Format("unknown region \"{0}\"", regionName)); if (!m_conciergedScenes.Contains(scene)) diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs index 4e84364..31fc56a 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -61,31 +61,31 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends private IPresenceService m_presenceService; // private IAvatarFactoryModule m_avatarFactory; - - public string Name { get { return "Appearance Information Module"; } } - + + public string Name { get { return "Appearance Information Module"; } } + public Type ReplaceableInterface { get { return null; } } - + public void Initialise(IConfigSource source) { // m_log.DebugFormat("[FRIENDS COMMAND MODULE]: INITIALIZED MODULE"); } - + public void PostInitialise() { // m_log.DebugFormat("[FRIENDS COMMAND MODULE]: POST INITIALIZED MODULE"); } - + public void Close() { // m_log.DebugFormat("[FRIENDS COMMAND MODULE]: CLOSED MODULE"); } - + public void AddRegion(Scene scene) { // m_log.DebugFormat("[FRIENDS COMMANDO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); } - + public void RemoveRegion(Scene scene) { // m_log.DebugFormat("[FRIENDS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); @@ -107,7 +107,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends m_scene.AddCommand( "Friends", this, "friends show", "friends show [--cache] ", - "Show the friends for the given user if they exist.\n", + "Show the friends for the given user if they exist.", "The --cache option will show locally cached information for that user.", HandleFriendsShowCommand); } @@ -197,4 +197,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.Friends } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs index 5a6b284..1b5ee04 100644 --- a/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/SitStand/SitStandCommandsModule.cs @@ -54,34 +54,34 @@ namespace OpenSim.Region.OptionalModules.Avatar.SitStand private Scene m_scene; public string Name { get { return "SitStand Command Module"; } } - + public Type ReplaceableInterface { get { return null; } } - + public void Initialise(IConfigSource source) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: INITIALIZED MODULE"); } - + public void PostInitialise() { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: POST INITIALIZED MODULE"); } - + public void Close() { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: CLOSED MODULE"); } - + public void AddRegion(Scene scene) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); } - + public void RemoveRegion(Scene scene) { // m_log.DebugFormat("[ATTACHMENTS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); - } - + } + public void RegionLoaded(Scene scene) { // m_log.DebugFormat("[ANIMATIONS COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); @@ -143,7 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.SitStand if (sitPart != null) { MainConsole.Instance.OutputFormat( - "Sitting {0} on {1} {2} in {3}", + "Sitting {0} on {1} {2} in {3}", sp.Name, sitPart.ParentGroup.Name, sitPart.ParentGroup.UUID, m_scene.Name); sp.HandleAgentRequestSit(sp.ControllingClient, sp.UUID, sitPart.UUID, Vector3.Zero); @@ -202,14 +202,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.SitStand foreach (ScenePresence sp in scenePresences) { - if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name)) + if (!sp.IsChildAgent && nameRegex.IsMatch(sp.Name)) scenePresencesMatched.Add(sp); } } else { ScenePresence sp = m_scene.GetScenePresence(firstName, lastName); - + if (sp != null && !sp.IsChildAgent) scenePresencesMatched.Add(sp); } diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 45af212..c6d7fe6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice if (String.IsNullOrEmpty(m_freeSwitchRealm) || String.IsNullOrEmpty(m_freeSwitchAPIPrefix)) { - m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured. Not starting."); + m_log.Error("[FreeSwitchVoice]: Freeswitch service mis-configured. Not starting."); return; } @@ -168,9 +168,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix), FreeSwitchSLVoiceBuddyHTTPHandler); - + MainServer.Instance.AddHTTPHandler(String.Format("{0}/viv_watcher.php", m_freeSwitchAPIPrefix), - FreeSwitchSLVoiceWatcherHTTPHandler); + FreeSwitchSLVoiceWatcherHTTPHandler); m_log.InfoFormat("[FreeSwitchVoice]: using FreeSwitch server {0}", m_freeSwitchRealm); @@ -302,7 +302,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice public void OnRegisterCaps(Scene scene, UUID agentID, Caps caps) { m_log.DebugFormat( - "[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}", + "[FreeSwitchVoice]: OnRegisterCaps() called with agentID {0} caps {1} in scene {2}", agentID, caps, scene.RegionInfo.RegionName); string capsBase = "/CAPS/" + caps.CapsObjectPath; @@ -352,7 +352,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice { m_log.DebugFormat( "[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request: {0}, path: {1}, param: {2}", request, path, param); - + ScenePresence avatar = scene.GetScenePresence(agentID); if (avatar == null) { @@ -423,9 +423,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice UUID agentID, Caps caps) { m_log.DebugFormat( - "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}", + "[FreeSwitchVoice][PARCELVOICE]: ParcelVoiceInfoRequest() on {0} for {1}", scene.RegionInfo.RegionName, agentID); - + ScenePresence avatar = scene.GetScenePresence(agentID); string avatarName = avatar.Name; @@ -512,7 +512,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice m_log.DebugFormat("[FreeSwitchVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", avatarName, request, path, param); - + return "true"; } @@ -575,7 +575,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice public Hashtable FreeSwitchSLVoiceGetPreloginHTTPHandler(Hashtable request) { - m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceGetPreloginHTTPHandler called"); +// m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceGetPreloginHTTPHandler called"); Hashtable response = new Hashtable(); response["content_type"] = "text/xml"; @@ -610,7 +610,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice public Hashtable FreeSwitchSLVoiceBuddyHTTPHandler(Hashtable request) { m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceBuddyHTTPHandler called"); - + Hashtable response = new Hashtable(); response["int_response_code"] = 200; response["str_response_string"] = string.Empty; @@ -678,16 +678,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice // Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); // // m_log.DebugFormat( -// "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}", +// "[FREESWITCH]: FreeSwitchSLVoiceBuddyHTTPHandler() response {0}", // normalizeEndLines.Replace((string)response["str_response_string"],"")); - + return response; } public Hashtable FreeSwitchSLVoiceWatcherHTTPHandler(Hashtable request) { m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceWatcherHTTPHandler called"); - + Hashtable response = new Hashtable(); response["int_response_code"] = 200; response["content-type"] = "text/xml"; @@ -700,8 +700,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice StringBuilder resp = new StringBuilder(); resp.Append(""); - - // FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work. If we don't + + // FIXME: This is enough of a response to stop viewer 2 complaining about a login failure and get voice to work. If we don't // give an OK response, then viewer 2 engages in an continuous viv_signin.php, viv_buddy.php, viv_watcher.php loop // Viewer 1 appeared happy to ignore the lack of reply and still works with this reply. // @@ -711,22 +711,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice lib_session {0} {0} - ", auth_token)); - + ", auth_token)); + response["str_response_string"] = resp.ToString(); - + // Regex normalizeEndLines = new Regex(@"(\r\n|\n)", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.Multiline); // // m_log.DebugFormat( -// "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}", +// "[FREESWITCH]: FreeSwitchSLVoiceWatcherHTTPHandler() response {0}", // normalizeEndLines.Replace((string)response["str_response_string"],"")); - + return response; } - + public Hashtable FreeSwitchSLVoiceSigninHTTPHandler(Hashtable request) { - m_log.Debug("[FreeSwitchVoice]: FreeSwitchSLVoiceSigninHTTPHandler called"); + //m_log.Debug("[FreeSwitchVoice] FreeSwitchSLVoiceSigninHTTPHandler called"); // string requestbody = (string)request["body"]; // string uri = (string)request["uri"]; // string contenttype = (string)request["content-type"]; @@ -771,10 +771,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice ", userid, pos, avatarName); - response["int_response_code"] = 200; - + response["int_response_code"] = 200; + // m_log.DebugFormat("[FreeSwitchVoice]: Sending FreeSwitchSLVoiceSigninHTTPHandler response"); - + return response; } @@ -859,23 +859,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice response["keepalive"] = false; response["int_response_code"] = 500; - Hashtable requestBody = ParseRequestBody((string)request["body"]); + Hashtable requestBody = ParseRequestBody((string)request["body"]); - string section = (string) requestBody["section"]; + string section = (string) requestBody["section"]; if (section == "directory") { string eventCallingFunction = (string)requestBody["Event-Calling-Function"]; m_log.DebugFormat( - "[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'", - eventCallingFunction); - + "[FreeSwitchVoice]: Received request for config section directory, event calling function '{0}'", + eventCallingFunction); + response = m_FreeswitchService.HandleDirectoryRequest(requestBody); } else if (section == "dialplan") - { + { m_log.DebugFormat("[FreeSwitchVoice]: Received request for config section dialplan"); - + response = m_FreeswitchService.HandleDialplanRequest(requestBody); } else diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index dd44564..defaa9c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -114,13 +114,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice private static Dictionary m_parents = new Dictionary(); private static bool m_dumpXml; - + private IConfig m_config; private object m_Lock; public void Initialise(IConfigSource config) { + MainConsole.Instance.Commands.AddCommand("vivox", false, "vivox debug", "vivox debug |", "Set vivox debugging", HandleDebug); m_config = config.Configs["VivoxVoice"]; @@ -152,22 +153,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // Validate against constraints and default if necessary if (m_vivoxChannelRollOff < CHAN_ROLL_OFF_MIN || m_vivoxChannelRollOff > CHAN_ROLL_OFF_MAX) { - m_log.WarnFormat("[VivoxVoice] Invalid value for roll off ({0}), reset to {1}.", + m_log.WarnFormat("[VivoxVoice] Invalid value for roll off ({0}), reset to {1}.", m_vivoxChannelRollOff, CHAN_ROLL_OFF_DEFAULT); m_vivoxChannelRollOff = CHAN_ROLL_OFF_DEFAULT; } if (m_vivoxChannelMaximumRange < CHAN_MAX_RANGE_MIN || m_vivoxChannelMaximumRange > CHAN_MAX_RANGE_MAX) { - m_log.WarnFormat("[VivoxVoice] Invalid value for maximum range ({0}), reset to {1}.", + m_log.WarnFormat("[VivoxVoice] Invalid value for maximum range ({0}), reset to {1}.", m_vivoxChannelMaximumRange, CHAN_MAX_RANGE_DEFAULT); m_vivoxChannelMaximumRange = CHAN_MAX_RANGE_DEFAULT; } - if (m_vivoxChannelClampingDistance < CHAN_CLAMPING_DISTANCE_MIN || + if (m_vivoxChannelClampingDistance < CHAN_CLAMPING_DISTANCE_MIN || m_vivoxChannelClampingDistance > CHAN_CLAMPING_DISTANCE_MAX) { - m_log.WarnFormat("[VivoxVoice] Invalid value for clamping distance ({0}), reset to {1}.", + m_log.WarnFormat("[VivoxVoice] Invalid value for clamping distance ({0}), reset to {1}.", m_vivoxChannelClampingDistance, CHAN_CLAMPING_DISTANCE_DEFAULT); m_vivoxChannelClampingDistance = CHAN_CLAMPING_DISTANCE_DEFAULT; } @@ -179,7 +180,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice case "presentation" : break; case "auditorium" : break; default : - m_log.WarnFormat("[VivoxVoice] Invalid value for channel mode ({0}), reset to {1}.", + m_log.WarnFormat("[VivoxVoice] Invalid value for channel mode ({0}), reset to {1}.", m_vivoxChannelMode, CHAN_MODE_DEFAULT); m_vivoxChannelMode = CHAN_MODE_DEFAULT; break; @@ -190,7 +191,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice case "positional" : break; case "channel" : break; default : - m_log.WarnFormat("[VivoxVoice] Invalid value for channel type ({0}), reset to {1}.", + m_log.WarnFormat("[VivoxVoice] Invalid value for channel type ({0}), reset to {1}.", m_vivoxChannelType, CHAN_TYPE_DEFAULT); m_vivoxChannelType = CHAN_TYPE_DEFAULT; break; @@ -229,7 +230,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice public void AddRegion(Scene scene) { - if (m_pluginEnabled) + if (m_pluginEnabled) { lock (vlock) { @@ -237,13 +238,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice string sceneUUID = scene.RegionInfo.RegionID.ToString(); string sceneName = scene.RegionInfo.RegionName; - + // Make sure that all local channels are deleted. // So we have to search for the children, and then do an // iteration over the set of chidren identified. // This assumes that there is just one directory per // region. - + if (VivoxTryGetDirectory(sceneUUID + "D", out channelId)) { m_log.DebugFormat("[VivoxVoice]: region {0}: uuid {1}: located directory id {2}", @@ -262,7 +263,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice { if (!IsOK(VivoxDeleteChannel(channelId, id))) m_log.WarnFormat("[VivoxVoice] Channel delete failed {0}:{1}:{2}", i, channelId, id); - } + } } } } @@ -310,7 +311,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice public void RemoveRegion(Scene scene) { - if (m_pluginEnabled) + if (m_pluginEnabled) { lock (vlock) { @@ -318,7 +319,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice string sceneUUID = scene.RegionInfo.RegionID.ToString(); string sceneName = scene.RegionInfo.RegionName; - + // Make sure that all local channels are deleted. // So we have to search for the children, and then do an // iteration over the set of chidren identified. @@ -342,7 +343,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice { if (!IsOK(VivoxDeleteChannel(channelId, id))) m_log.WarnFormat("[VivoxVoice] Channel delete failed {0}:{1}:{2}", i, channelId, id); - } + } } } } @@ -352,7 +353,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // Remove the channel umbrella entry - lock (m_parents) + lock (m_parents) { if (m_parents.ContainsKey(sceneUUID)) { @@ -374,7 +375,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice VivoxLogout(); } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -395,11 +396,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // (login, region crossing). We contribute two capabilities to // the set of capabilities handed back to the client: // ProvisionVoiceAccountRequest and ParcelVoiceInfoRequest. - // + // // ProvisionVoiceAccountRequest allows the client to obtain // the voice account credentials for the avatar it is // controlling (e.g., user name, password, etc). - // + // // ParcelVoiceInfoRequest is invoked whenever the client // changes from one region or parcel to another. // @@ -475,8 +476,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice avatarName = avatar.Name; m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID); - m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", - request, path, param); +// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", +// request, path, param); XmlElement resp; bool retry = false; @@ -492,9 +493,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice if (XmlFind(resp, "response.level0.status", out code)) { - if (code != "OK") + if (code != "OK") { - if (XmlFind(resp, "response.level0.body.code", out code)) + if (XmlFind(resp, "response.level0.body.code", out code)) { // If the request was recognized, then this should be set to something switch (code) @@ -529,27 +530,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice switch (code) { case "201" : // Account expired - m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : expired credentials", + m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : expired credentials", avatarName); m_adminConnected = false; retry = DoAdminLogin(); break; - + case "202" : // Missing credentials - m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : missing credentials", + m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : missing credentials", avatarName); break; - + case "212" : // Not authorized m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : not authorized", avatarName); break; - + case "300" : // Required parameter missing - m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : parameter missing", + m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : parameter missing", avatarName); break; - + case "400" : // Create failed m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Create account information failed : create failed", avatarName); @@ -557,7 +558,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice } } break; - + case "404" : // Failed to retrieve account m_log.ErrorFormat("[VivoxVoice]: avatar \"{0}\": Get account information failed : retrieve failed"); // [AMW] Sleep and retry for a fixed period? Or just abandon? @@ -574,7 +575,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: Get Account Request failed for \"{0}\"", avatarName); throw new Exception("Unable to execute request"); } - + // Unconditionally change the password on each request VivoxPassword(agentname, password); @@ -583,7 +584,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); - m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); +// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); return r; } @@ -612,7 +613,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice string avatarName = avatar.Name; // - check whether we have a region channel in our cache - // - if not: + // - if not: // create it and cache it // - send it to the client // - send channel_uri: as "sip:regionID@m_sipDomain" @@ -621,7 +622,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice LLSDParcelVoiceInfoResponse parcelVoiceInfo; string channel_uri; - if (null == scene.LandChannel) + if (null == scene.LandChannel) throw new Exception(String.Format("region \"{0}\": avatar \"{1}\": land data not yet available", scene.RegionInfo.RegionName, avatarName)); @@ -630,24 +631,28 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // voice, if all do retrieve or obtain the parcel // voice channel LandData land = scene.GetLandData(avatar.AbsolutePosition); + if (land == null) + { + return ""; + } - m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", - scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); +// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", +// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}", // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); // TODO: EstateSettings don't seem to get propagated... if (!scene.RegionInfo.EstateSettings.AllowVoice) { - m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": voice not enabled in estate settings", - scene.RegionInfo.RegionName); + //m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": voice not enabled in estate settings", + // scene.RegionInfo.RegionName); channel_uri = String.Empty; } if ((land.Flags & (uint)ParcelFlags.AllowVoiceChat) == 0) { - m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", - scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); + //m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": voice not enabled for parcel", + // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName); channel_uri = String.Empty; } else @@ -662,15 +667,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); - m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", - scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); +// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", +// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); return r; } catch (Exception e) { - m_log.ErrorFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2}, retry later", + m_log.ErrorFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2}, retry later", scene.RegionInfo.RegionName, avatarName, e.Message); - m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2} failed", + m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": avatar \"{1}\": {2} failed", scene.RegionInfo.RegionName, avatarName, e.ToString()); return ""; @@ -690,11 +695,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice public string ChatSessionRequest(Scene scene, string request, string path, string param, UUID agentID, Caps caps) { - ScenePresence avatar = scene.GetScenePresence(agentID); - string avatarName = avatar.Name; +// ScenePresence avatar = scene.GetScenePresence(agentID); +// string avatarName = avatar.Name; - m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", - avatarName, request, path, param); +// m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", +// avatarName, request, path, param); return "true"; } @@ -716,17 +721,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice { landName = String.Format("{0}:{1}", scene.RegionInfo.RegionName, land.Name); landUUID = land.GlobalID.ToString(); - m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", + m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", landName, land.LocalID, landUUID); } else { landName = String.Format("{0}:{1}", scene.RegionInfo.RegionName, scene.RegionInfo.RegionName); landUUID = scene.RegionInfo.RegionID.ToString(); - m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", + m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parcel id {1}: using channel name {2}", landName, land.LocalID, landUUID); } - + lock (vlock) { // Added by Adam to help debug channel not availible errors. @@ -737,7 +742,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice else throw new Exception("vivox channel uri not available"); - m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parent channel id {1}: retrieved parcel channel_uri {2} ", + m_log.DebugFormat("[VivoxVoice]: Region:Parcel \"{0}\": parent channel id {1}: retrieved parcel channel_uri {2} ", landName, parentId, channelUri); } @@ -767,6 +772,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return VivoxCall(requrl, false); } + private static readonly string m_vivoxGetAccountPath = "http://{0}/api2/viv_get_acct.php?auth_token={1}&user_name={2}"; /// @@ -779,6 +785,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return VivoxCall(requrl, true); } + private static readonly string m_vivoxNewAccountPath = "http://{0}/api2/viv_adm_acct_new.php?username={1}&pwd={2}&auth_token={3}"; /// @@ -793,6 +800,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return VivoxCall(requrl, true); } + private static readonly string m_vivoxPasswordPath = "http://{0}/api2/viv_adm_password.php?user_name={1}&new_pwd={2}&auth_token={3}"; /// @@ -804,18 +812,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return VivoxCall(requrl, true); } + private static readonly string m_vivoxChannelPath = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_name={2}&auth_token={3}"; /// /// Create a channel. - /// Once again, there a multitude of options possible. In the simplest case + /// Once again, there a multitude of options possible. In the simplest case /// we specify only the name and get a non-persistent cannel in return. Non /// persistent means that the channel gets deleted if no-one uses it for /// 5 hours. To accomodate future requirements, it may be a good idea to /// initially create channels under the umbrella of a parent ID based upon /// the region name. That way we have a context for side channels, if those /// are required in a later phase. - /// + /// /// In this case the call handles parent and description as optional values. /// private bool VivoxTryCreateChannel(string parent, string channelId, string description, out string channelUri) @@ -837,7 +846,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice requrl = String.Format("{0}&chan_dist_model={1}", requrl, m_vivoxChannelDistanceModel); requrl = String.Format("{0}&chan_max_range={1}", requrl, m_vivoxChannelMaximumRange); requrl = String.Format("{0}&chan_clamping_distance={1}", requrl, m_vivoxChannelClampingDistance); - + XmlElement resp = VivoxCall(requrl, true); if (XmlFind(resp, "response.level0.body.chan_uri", out channelUri)) return true; @@ -880,7 +889,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// /// Retrieve a channel. - /// Once again, there a multitude of options possible. In the simplest case + /// Once again, there a multitude of options possible. In the simplest case /// we specify only the name and get a non-persistent cannel in return. Non /// persistent means that the channel gets deleted if no-one uses it for /// 5 hours. To accomodate future requirements, it may be a good idea to @@ -889,7 +898,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// are required in a later phase. /// In this case the call handles parent and description as optional values. /// - private bool VivoxTryGetChannel(string channelParent, string channelName, + private bool VivoxTryGetChannel(string channelParent, string channelName, out string channelId, out string channelUri) { string count; @@ -997,7 +1006,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice string type; // skip if not a directory - if (!XmlFind(resp, "response.level0.channel-search.channels.channels.level4.type", i, out type) || + if (!XmlFind(resp, "response.level0.channel-search.channels.channels.level4.type", i, out type) || type != "dir") continue; @@ -1019,7 +1028,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return false; } - // private static readonly string m_vivoxChannelById = "http://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; + // private static readonly string m_vivoxChannelById = "https://{0}/api2/viv_chan_mod.php?mode={1}&chan_id={2}&auth_token={3}"; // private XmlElement VivoxGetChannelById(string parent, string channelid) // { @@ -1035,7 +1044,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// /// Delete a channel. - /// Once again, there a multitude of options possible. In the simplest case + /// Once again, there a multitude of options possible. In the simplest case /// we specify only the name and get a non-persistent cannel in return. Non /// persistent means that the channel gets deleted if no-one uses it for /// 5 hours. To accomodate future requirements, it may be a good idea to @@ -1044,6 +1053,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// are required in a later phase. /// In this case the call handles parent and description as optional values. /// + private XmlElement VivoxDeleteChannel(string parent, string channelid) { string requrl = String.Format(m_vivoxChannelDel, m_vivoxServer, "delete", channelid, m_authToken); @@ -1059,6 +1069,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// /// Return information on channels in the given directory /// + private XmlElement VivoxListChildren(string channelid) { string requrl = String.Format(m_vivoxChannelSearch, m_vivoxServer, channelid, m_authToken); @@ -1087,7 +1098,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // return VivoxGetChannelById(null, id); // } // } - // } + // } // } // } @@ -1095,12 +1106,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // return VivoxGetChannel(null, Guid.NewGuid().ToString()); // } - + /// /// This method handles the WEB side of making a request over the /// Vivox interface. The returned values are tansferred to a has /// table which is returned as the result. - /// The outcome of the call can be determined by examining the + /// The outcome of the call can be determined by examining the /// status value in the hash table. /// private XmlElement VivoxCall(string requrl, bool admin) @@ -1114,9 +1125,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice return null; doc = new XmlDocument(); + doc.XmlResolver = null; // Let's serialize all calls to Vivox. Most of these are driven by - // the clients (CAPs), when the user arrives at the region. We don't + // the clients (CAPs), when the user arrives at the region. We don't // want to issue many simultaneous http requests to Vivox, because mono // doesn't like that lock (m_Lock) @@ -1124,7 +1136,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice try { // Otherwise prepare the request - m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); + //m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); @@ -1135,7 +1147,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice using (HttpWebResponse rsp = (HttpWebResponse)req.GetResponse()) using (Stream s = rsp.GetResponseStream()) using (XmlTextReader rdr = new XmlTextReader(s)) - doc.Load(rdr); + { + rdr.ProhibitDtd = true; + doc.Load(rdr); + } } catch (Exception e) { @@ -1162,7 +1177,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// /// Login has been factored in this way because it gets called - /// from several places in the module, and we want it to work + /// from several places in the module, and we want it to work /// the same way each time. /// private bool DoAdminLogin() @@ -1177,15 +1192,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice XmlElement resp = null; resp = VivoxLogin(m_vivoxAdminUser, m_vivoxAdminPassword); - - if (XmlFind(resp, "response.level0.body.status", out status)) + + if (XmlFind(resp, "response.level0.body.status", out status)) { if (status == "Ok") { m_log.Info("[VivoxVoice] Admin connection established"); if (XmlFind(resp, "response.level0.body.auth_token", out m_authToken)) { - if (m_dumpXml) m_log.DebugFormat("[VivoxVoice] Auth Token <{0}>", + if (m_dumpXml) m_log.DebugFormat("[VivoxVoice] Auth Token <{0}>", m_authToken); m_adminConnected = true; } @@ -1204,9 +1219,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// /// The XmlScan routine is provided to aid in the - /// reverse engineering of incompletely + /// reverse engineering of incompletely /// documented packets returned by the Vivox - /// voice server. It is only called if the + /// voice server. It is only called if the /// m_dumpXml switch is set. /// private void XmlScanl(XmlElement e, int index) @@ -1251,7 +1266,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice private bool XmlFind(XmlElement root, string tag, int nth, out string result) { if (root == null || tag == null || tag == String.Empty) - { + { result = String.Empty; return false; } @@ -1262,7 +1277,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice { int nth = 0; if (root == null || tag == null || tag == String.Empty) - { + { result = String.Empty; return false; } @@ -1273,7 +1288,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice /// XmlSearch is initially called by XmlFind, and then /// recursively called by itself until the document /// supplied to XmlFind is either exhausted or the name hierarchy - /// is matched. + /// is matched. /// /// If the hierarchy is matched, the value is returned in /// result, and true returned as the function's @@ -1287,7 +1302,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice result = String.Empty; return false; } - + if (tags.Length-index == 1) { if (nth == 0) @@ -1324,5 +1339,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice result = String.Empty; return false; } + + private void HandleDebug(string module, string[] cmd) + { + if (cmd.Length < 3) + { + MainConsole.Instance.Output("Error: missing on/off flag"); + return; + } + + if (cmd[2] == "on") + m_dumpXml = true; + else if (cmd[2] == "off") + m_dumpXml = false; + else + MainConsole.Instance.Output("Error: only on and off are supported"); + } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index e1b6abb..8791235 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -125,7 +125,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (!m_groupMessagingEnabled) return; - + scene.RegisterModuleInterface(this); scene.AddCommand( @@ -136,7 +136,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups "This setting turns on very verbose groups messaging debugging", HandleDebugGroupsMessagingVerbose); } - + public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -205,7 +205,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_msgTransferModule = null; } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -253,7 +253,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); if (groupInfo != null) @@ -270,7 +270,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { SendMessageToGroup(im, groupID, new UUID(im.fromAgentID), null); } - + public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func sendCondition) { @@ -294,28 +294,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); } - attemptDeliveryUuidSet + 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(); - - // if (m_debugEnabled) -// m_log.DebugFormat( -// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", -// groupID, groupMembersCount, groupMembers.Count()); } else { - attemptDeliveryUuidSet + 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); - } + } foreach (GroupMembersData member in groupMembers) { @@ -323,9 +314,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (!sendCondition(member)) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition", + "[GROUPS-MESSAGING]: Not sending to {0} as they do not fulfill send condition", member.AgentID); continue; @@ -334,7 +325,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups else if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) { // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( "[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); @@ -369,9 +360,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // If they're not local, forward across the grid m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS-MESSAGING]: Delivering to {0} via grid took {1} ms", + "[GROUPS-MESSAGING]: Delivering to {0} via grid took {1} ms", member.AgentID, Environment.TickCount - startTick); } else @@ -381,21 +372,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ProcessMessageFromGroupSession(msg, client); // Deliver locally, directly - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS-MESSAGING]: Delivering to {0} locally took {1} ms", + "[GROUPS-MESSAGING]: Delivering to {0} locally took {1} ms", member.AgentID, Environment.TickCount - startTick); } } - else + else if(im.dialog != (byte)InstantMessageDialog.SessionAdd && + im.dialog != (byte)InstantMessageDialog.SessionDrop) { int startTick = Environment.TickCount; m_msgTransferModule.HandleUndeliverableMessage(msg, delegate(bool success) { }); - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS-MESSAGING]: Handling undeliverable message for {0} took {1} ms", + "[GROUPS-MESSAGING]: Handling undeliverable message for {0} took {1} ms", member.AgentID, Environment.TickCount - startTick); } } @@ -405,7 +397,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups "[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 void OnClientLogin(IClientAPI client) @@ -425,7 +417,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // The instant message module will only deliver messages of dialog types: // MessageFromAgent, StartTyping, StopTyping, MessageFromObject // - // Any other message type will not be delivered to a client by the + // Any other message type will not be delivered to a client by the // Instant Message Module if (m_debugEnabled) @@ -436,28 +428,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // Incoming message from a group - if ((msg.fromGroup == true) && + if ((msg.fromGroup == true) && ((msg.dialog == (byte)InstantMessageDialog.SessionSend) || (msg.dialog == (byte)InstantMessageDialog.SessionAdd) || (msg.dialog == (byte)InstantMessageDialog.SessionDrop))) { IClientAPI client = null; - if (msg.dialog == (byte)InstantMessageDialog.SessionSend) - { - client = GetActiveClient(new UUID(msg.toAgentID)); + 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); + if (client == null) + { + m_log.WarnFormat("[GROUPS-MESSAGING]: Received a message over the grid for a client that isn't here: {0}", msg.toAgentID); - return; - } + return; } ProcessMessageFromGroupSession(msg, client); @@ -466,83 +450,101 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void ProcessMessageFromGroupSession(GridInstantMessage msg, IClientAPI client) { - if (m_debugEnabled) + 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 fromAgentID = new UUID(msg.fromAgentID); UUID GroupID = new UUID(msg.imSessionID); + IEventQueue eq = client.Scene.RequestModuleInterface(); switch (msg.dialog) { case (byte)InstantMessageDialog.SessionAdd: - m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); + m_groupData.AgentInvitedToGroupChatSession(fromAgentID, GroupID); + if(eq != null) + eq.ChatterBoxSessionAgentListUpdates( + GroupID + , fromAgentID + , client.AgentId + , false //canVoiceChat + , false //isModerator + , false //text mute + , true // enter + ); break; case (byte)InstantMessageDialog.SessionDrop: - m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); + m_groupData.AgentDroppedFromGroupChatSession(fromAgentID, GroupID); + if(eq != null) + eq.ChatterBoxSessionAgentListUpdates( + GroupID + , fromAgentID + , client.AgentId + , false //canVoiceChat + , false //isModerator + , false //text mute + , false // leave + ); break; case (byte)InstantMessageDialog.SessionSend: - if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) - && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID, GroupID) - ) + if (!m_groupData.hasAgentDroppedGroupChatSession(client.AgentId, GroupID)) { - // Agent not in session and hasn't dropped from session - // Add them to the session for now, and Invite them - m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - - GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); - if (groupInfo != null) + if(!m_groupData.hasAgentBeenInvitedToGroupChatSession(client.AgentId, GroupID)) { - 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 - ); + 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"); + + if(eq != null) + { + eq.ChatterboxInvitation( + GroupID + , groupInfo.GroupName + , fromAgentID + , msg.message + , client.AgentId + , 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) + ); + } + } + } + else + { + client.SendInstantMessage(msg); } - break; - } - else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) - { - // User hasn't dropped, so they're in the session, - // maybe we should deliver it. - client.SendInstantMessage(msg); +// if (!m_groupData.hasAgentBeenInvitedToGroupChatSession(fromAgentID, GroupID)) + { + m_groupData.AgentInvitedToGroupChatSession(fromAgentID, GroupID); + eq.ChatterBoxSessionAgentListUpdates( + GroupID + , fromAgentID + , client.AgentId + , false //canVoiceChat + , false //isModerator + , false //text mute + , true // enter + ); + } } - break; default: client.SendInstantMessage(msg); - break;; } } @@ -559,41 +561,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups DebugGridInstantMessage(im); } + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + // Start group IM session if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) { if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); - UUID GroupID = new UUID(im.imSessionID); - UUID AgentID = new UUID(im.fromAgentID); - GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); - + if (groupInfo != null) { m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); - IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); - queue.ChatterBoxSessionAgentListUpdates( - GroupID - , AgentID - , new UUID(im.toAgentID) - , false //canVoiceChat - , false //isModerator - , false //text mute - ); + // we need to send here a list of known participants. + im.dialog = (byte)InstantMessageDialog.SessionAdd; + SendMessageToGroup(im, GroupID); } } // Send a message from locally connected client to a group if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) { - UUID GroupID = new UUID(im.imSessionID); - UUID AgentID = new UUID(im.fromAgentID); - - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); //If this agent is sending a message, then they want to be in the session @@ -601,6 +594,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendMessageToGroup(im, GroupID); } + + if ((im.dialog == (byte)InstantMessageDialog.SessionDrop)) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); + + m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); + + SendMessageToGroup(im, GroupID); + } } #endregion @@ -656,7 +659,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private IClientAPI GetActiveClient(UUID agentID) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); IClientAPI child = null; @@ -669,14 +672,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (!sp.IsChildAgent) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", sp.ControllingClient.Name); return sp.ControllingClient; } else { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", sp.ControllingClient.Name); child = sp.ControllingClient; @@ -687,12 +690,12 @@ 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) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); } else { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 1565da9..65d50bb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -50,19 +50,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// ; To use this module, you must specify the following in your OpenSim.ini /// [GROUPS] /// Enabled = true - /// + /// /// Module = GroupsModule /// NoticesEnabled = true /// DebugEnabled = true - /// + /// /// GroupsServicesConnectorModule = XmlRpcGroupsServicesConnector /// XmlRpcServiceURL = http://osflotsam.org/xmlrpc.php /// XmlRpcServiceReadKey = 1234 /// XmlRpcServiceWriteKey = 1234 - /// + /// /// MessagingModule = GroupsMessagingModule /// MessagingEnabled = true - /// + /// /// ; Disables HTTP Keep-Alive for Groups Module HTTP Requests, work around for /// ; a problem discovered on some Windows based region servers. Only disable /// ; if you see a large number (dozens) of the following Exceptions: @@ -79,7 +79,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IMessageTransferModule m_msgTransferModule; private IGroupsMessagingModule m_groupsMessagingModule; - + private IGroupsServicesConnector m_groupData; // Configuration settings @@ -205,10 +205,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnMakeRootAgent += OnMakeRoot; + scene.EventManager.OnMakeChildAgent += OnMakeChild; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - // The InstantMessageModule itself doesn't do this, - // so lets see if things explode if we don't do it - // scene.EventManager.OnClientClosed += OnClientClosed; + scene.EventManager.OnClientClosed += OnClientClosed; } @@ -217,6 +217,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (!m_groupsEnabled) return; + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnMakeRootAgent -= OnMakeRoot; + scene.EventManager.OnMakeChildAgent -= OnMakeChild; + scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; + scene.EventManager.OnClientClosed -= OnClientClosed; if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); lock (m_sceneList) @@ -233,7 +240,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -255,84 +262,124 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion #region EventHandlers + + private void OnMakeRoot(ScenePresence sp) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; + // Used for Notices and Group Invites/Accept/Reject + sp.ControllingClient.OnInstantMessage += OnInstantMessage; + + // comented out because some viewers no longer suport it + // sp.ControllingClient.AddGenericPacketHandler("avatargroupsrequest", AvatarGroupsRequest); + + // Send out group data update for compatibility. + // There might be some problem with the thread we're generating this on but not + // doing the update at this time causes problems (Mantis #7920 and #7915) + // TODO: move sending this update to a later time in the rootification of the client. + if(!sp.haveGroupInformation) + SendAgentGroupDataUpdate(sp.ControllingClient, false); + } + + private void OnMakeChild(ScenePresence sp) + { + if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + sp.ControllingClient.OnInstantMessage -= OnInstantMessage; + } + private void OnNewClient(IClientAPI client) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; client.OnRequestAvatarProperties += OnRequestAvatarProperties; - // Used for Notices and Group Invites/Accept/Reject - client.OnInstantMessage += OnInstantMessage; - // Send client their groups information. - SendAgentGroupDataUpdate(client, client.AgentId); } +/* this should be the right message to ask for other avatars groups + + private void AvatarGroupsRequest(Object sender, string method, List args) + { + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + if (!(sender is IClientAPI)) + return; + + IClientAPI remoteClient = (IClientAPI)sender; + + UUID avatarID; + UUID.TryParse(args[0], out avatarID); + + if (avatarID != UUID.Zero) + { + GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); + remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); + } + } +*/ + + // this should not be used to send groups memberships, but some viewers do expect it + // it does send unnecessary memberships, when viewers just want other properties information private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } - /* - * This becomes very problematic in a shared module. In a shared module you may have more then one - * reference to IClientAPI's, one for 0 or 1 root connections, and 0 or more child connections. - * The OnClientClosed event does not provide anything to indicate which one of those should be closed - * nor does it provide what scene it was from so that the specific reference can be looked up. - * The InstantMessageModule.cs does not currently worry about unregistering the handles, - * and it should be an issue, since it's the client that references us not the other way around - * , so as long as we don't keep a reference to the client laying around, the client can still be GC'ed - private void OnClientClosed(UUID AgentId) + + private void OnClientClosed(UUID AgentId, Scene scene) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (scene == null) + return; - lock (m_ActiveClients) + ScenePresence sp = scene.GetScenePresence(AgentId); + IClientAPI client = sp.ControllingClient; + if (client != null) { - if (m_ActiveClients.ContainsKey(AgentId)) + client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; + client.OnRequestAvatarProperties -= OnRequestAvatarProperties; + // make child possible not called? + client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + client.OnInstantMessage -= OnInstantMessage; + } + +/* + lock (m_ActiveClients) { - IClientAPI client = m_ActiveClients[AgentId]; - client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; - client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; - client.OnDirFindQuery -= OnDirFindQuery; - client.OnInstantMessage -= OnInstantMessage; + if (m_ActiveClients.ContainsKey(AgentId)) + { + IClientAPI client = m_ActiveClients[AgentId]; + client.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; + client.OnAgentDataUpdateRequest -= OnAgentDataUpdateRequest; + client.OnDirFindQuery -= OnDirFindQuery; + client.OnInstantMessage -= OnInstantMessage; - m_ActiveClients.Remove(AgentId); - } + m_ActiveClients.Remove(AgentId); + } else - { - if (m_debugEnabled) m_log.WarnFormat("[GROUPS]: Client closed that wasn't registered here."); + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS]: Client closed that wasn't registered here."); + } } - - - } +*/ } - */ private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID activeGroupID = UUID.Zero; - string activeGroupTitle = string.Empty; - string activeGroupName = string.Empty; - ulong activeGroupPowers = (ulong)GroupPowers.None; - - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID); - if (membership != null) - { - activeGroupID = membership.GroupID; - activeGroupTitle = membership.GroupTitle; - activeGroupPowers = membership.GroupPowers; - } - - SendAgentDataUpdate(remoteClient, dataForAgentID, activeGroupID, activeGroupName, activeGroupPowers, activeGroupTitle); + // this a private message for own agent only + if (dataForAgentID != GetRequestingAgentID(remoteClient)) + return; - SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); + SendAgentGroupDataUpdate(remoteClient, false); + // its a info request not a change, so nothing is sent to others + // they do get the group title with the avatar object update on arrivel to a region } private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) @@ -340,7 +387,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); string GroupName; - + GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null); if (group != null) { @@ -356,9 +403,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS]: {0} called for {1}, message type {2}", + "[GROUPS]: {0} called for {1}, message type {2}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name, (InstantMessageDialog)im.dialog); // Group invitations @@ -403,11 +450,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OutgoingInstantMessage(msg, inviteInfo.AgentID); - UpdateAllClientsWithGroupInfo(inviteInfo.AgentID); - - // TODO: If the inviter is still online, they need an agent dataupdate - // and maybe group membership updates for the invitee - + IClientAPI inviteeClient = GetActiveRootClient(inviteInfo.AgentID); + if(inviteeClient !=null) + { + SendAgentGroupDataUpdate(inviteeClient,true); + } m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } @@ -459,8 +506,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups //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); + item = scene.InventoryService.GetItem(ownerID, itemID); if (item != null) { @@ -523,20 +569,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (targetUser != null) { m_log.DebugFormat( - "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", + "[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})", + "[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, member.AgentID, member.AcceptNotices); } } } } - GridInstantMessage msg + GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); if (m_groupsMessagingModule != null) @@ -553,7 +599,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups UUID noticeID = new UUID(im.imSessionID); - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Requesting notice {0} for {1}", noticeID, remoteClient.AgentId); GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID); @@ -579,10 +625,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } else { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( - "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.", - noticeID, remoteClient.AgentId); + "[GROUPS]: Could not find notice {0} for {1} on GroupNoticeInventoryAccepted.", + noticeID, remoteClient.AgentId); } } @@ -598,15 +644,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // so we need to send local updates to the agent. UUID ejecteeID = new UUID(im.toAgentID); - + im.imSessionID = UUID.Zero.Guid; im.dialog = (byte)InstantMessageDialog.MessageFromAgent; OutgoingInstantMessage(im, ejecteeID); - IClientAPI ejectee = GetActiveClient(ejecteeID); + IClientAPI ejectee = GetActiveRootClient(ejecteeID); if (ejectee != null) { UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); + SendAgentGroupDataUpdate(ejectee,true); } } } @@ -626,7 +673,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups case (byte)InstantMessageDialog.GroupInvitation: case (byte)InstantMessageDialog.GroupNotice: UUID toAgentID = new UUID(msg.toAgentID); - IClientAPI localClient = GetActiveClient(toAgentID); + IClientAPI localClient = GetActiveRootClient(toAgentID); if (localClient != null) { localClient.SendInstantMessage(msg); @@ -651,18 +698,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { return m_groupData.GetGroupRecord(UUID.Zero, UUID.Zero, name); } - + public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + UUID agentID = GetRequestingAgentID(remoteClient); + m_groupData.SetAgentActiveGroup(agentID, agentID, groupID); - // Changing active group changes title, active powers, all kinds of things - // anyone who is in any region that can see this client, should probably be - // updated with new group info. At a minimum, they should get ScenePresence - // updated with new title. - UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); + // llClientView does this + SendAgentGroupDataUpdate(remoteClient, true); } /// @@ -672,7 +717,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); @@ -695,10 +739,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( "[GROUPS]: GroupMembersRequest called for {0} from client {1}", groupID, remoteClient.Name); - + List data = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID); if (m_debugEnabled) @@ -710,7 +754,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } return data; - } public List GroupRoleDataRequest(IClientAPI remoteClient, UUID groupID) @@ -744,7 +787,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupProfileData profile = new GroupProfileData(); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); if (groupInfo != null) { @@ -770,7 +812,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups profile.MemberTitle = memberInfo.GroupTitle; profile.PowersMask = memberInfo.GroupPowers; } - +/* + this should save xmlrpc calls, but seems to return wrong GroupMembershipCount and GroupRolesCount + UUID agent = GetRequestingAgentID(remoteClient); + GroupProfileData profile = m_groupData.GetMemberGroupProfile(agent, groupID, agent); +*/ return profile; } @@ -783,7 +829,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) { - if (m_debugEnabled) + if (m_debugEnabled) m_log.DebugFormat( "[GROUPS]: {0} called with groupID={1}, agentID={2}", System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); @@ -791,6 +837,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return m_groupData.GetAgentGroupMembership(UUID.Zero, agentID, groupID); } + public GroupMembershipData GetActiveMembershipData(UUID agentID) + { + return m_groupData.GetAgentActiveMembership(agentID, agentID); + } + public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -811,7 +862,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) + GroupRecord groupRecord = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name); + + if (groupRecord != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; @@ -824,31 +877,31 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (avatar != null) { - if (avatar.UserLevel < m_levelGroupCreate) + if (avatar.GodController.UserLevel < m_levelGroupCreate) { - remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient permissions to create a group."); + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient permissions to create a group."); return UUID.Zero; } } // check funds - // is there is a money module present ? + // is there a money module present ? IMoneyModule money = scene.RequestModuleInterface(); - if (money != null) + if (money != null && money.GroupCreationCharge > 0) { - // do the transaction, that is if the agent has got sufficient funds + // do the transaction, that is if the agent has sufficient funds if (!money.AmountCovered(remoteClient.AgentId, money.GroupCreationCharge)) { - remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got insufficient funds to create a group."); + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient funds to create a group."); return UUID.Zero; } - money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate); + money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, MoneyTransactionType.GroupCreate, name); } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); - remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); + remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, true); return groupID; } @@ -873,7 +926,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (membership != null) { return membership.GroupTitle; - } + } return string.Empty; } @@ -889,10 +942,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - - UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); - } + SendDataUpdate(remoteClient, true); + } public void GroupRoleUpdate(IClientAPI remoteClient, UUID groupID, UUID roleID, string name, string description, string title, ulong powers, byte updateType) { @@ -929,7 +981,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, false); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -947,7 +999,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups case 1: // Remove m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); - + break; default: m_log.ErrorFormat("[GROUPS]: {0} does not understand changes == {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, changes); @@ -955,7 +1007,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, false); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) @@ -983,7 +1035,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.toAgentID = agentID.Guid; msg.dialog = dialog; msg.fromGroup = true; - msg.offline = (byte)0; + msg.offline = (byte)1; // Allow this message to be stored for offline use msg.ParentEstateID = 0; msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; @@ -1035,14 +1087,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return msg; } - public void SendAgentGroupDataUpdate(IClientAPI remoteClient) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); - } - public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -1050,10 +1094,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Should check to see if OpenEnrollment, or if there's an outstanding invitation m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); + // check funds + // is there a money module present ? + GroupRecord groupRecord = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); + IMoneyModule money = remoteClient.Scene.RequestModuleInterface(); + if (money != null && groupRecord.MembershipFee > 0) + { + // do the transaction, that is if the agent has sufficient funds + if (!money.AmountCovered(GetRequestingAgentID(remoteClient), groupRecord.MembershipFee)) { + remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have insufficient funds to join the group."); + return; + } + money.ApplyCharge(GetRequestingAgentID(remoteClient), groupRecord.MembershipFee, MoneyTransactionType.GroupJoin, groupRecord.GroupName); + } + remoteClient.SendJoinGroupReply(groupID, true); - // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, true); } public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) @@ -1068,7 +1125,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, true); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) @@ -1120,17 +1177,41 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); - - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, ejecteeID); - if ((groupInfo == null) || (account == null)) - { + if (groupInfo == null) return; - } + + + IClientAPI ejecteeClient = GetActiveRootClient(ejecteeID); // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); - - msg.imSessionID = UUID.Zero.Guid; + + string ejecteeName = "Unknown member"; + // if local send a normal message + if(ejecteeClient != null) + { + msg.imSessionID = UUID.Zero.Guid; + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; + // also execute and send update + ejecteeClient.SendAgentDropGroup(groupID); + SendAgentGroupDataUpdate(ejecteeClient,true); + ejecteeName = ejecteeClient.Name; + } + else // send + { + // 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 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 + + msg.imSessionID = groupInfo.GroupID.Guid; + msg.dialog = (byte)210; //interop + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(regionInfo.ScopeID, ejecteeID); + if (account != null) + ejecteeName = account.FirstName + " " + account.LastName; + } + msg.fromAgentID = agentID.Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; @@ -1138,7 +1219,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.timestamp = 0; msg.fromAgentName = agentName; msg.message = string.Format("You have been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName); - msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; +// msg.fromGroup = false; msg.offline = (byte)0; msg.ParentEstateID = 0; @@ -1148,11 +1229,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OutgoingInstantMessage(msg, ejecteeID); // 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 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 msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -1160,15 +1236,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.toAgentID = agentID.Guid; msg.timestamp = 0; msg.fromAgentName = agentName; - if (account != null) - { - msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, account.FirstName + " " + account.LastName); - } - else - { - msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, "Unknown member"); - } - msg.dialog = (byte)210; //interop + + msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", agentName, groupInfo.GroupName, ejecteeName); + +// msg.dialog = (byte)210; //interop + msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.MessageFromAgent; msg.fromGroup = false; msg.offline = (byte)0; msg.ParentEstateID = 0; @@ -1176,11 +1248,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.RegionID = regionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; OutgoingInstantMessage(msg, agentID); - - - // SL sends out messages to everyone in the group - // Who all should receive updates and what should they be updated with? - UpdateAllClientsWithGroupInfo(ejecteeID); } public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) @@ -1275,6 +1342,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #region Client/Update Tools + private IClientAPI GetActiveRootClient(UUID agentID) + { + foreach (Scene scene in m_sceneList) + { + ScenePresence sp = scene.GetScenePresence(agentID); + if (sp != null && !sp.IsChildAgent && !sp.IsDeleted) + { + return sp.ControllingClient; + } + } + return null; + } + /// /// Try to find an active IClientAPI reference for agentID giving preference to root connections /// @@ -1286,7 +1366,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups foreach (Scene scene in m_sceneList) { ScenePresence sp = scene.GetScenePresence(agentID); - if (sp != null) + if (sp != null && !sp.IsDeleted) { if (!sp.IsChildAgent) { @@ -1303,67 +1383,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return child; } - /// - /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. - /// - private void SendGroupMembershipInfoViaCaps(IClientAPI remoteClient, UUID dataForAgentID, GroupMembershipData[] data) - { - if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDArray AgentData = new OSDArray(1); - OSDMap AgentDataMap = new OSDMap(1); - AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); - AgentData.Add(AgentDataMap); - - OSDArray GroupData = new OSDArray(data.Length); - OSDArray NewGroupData = new OSDArray(data.Length); - - foreach (GroupMembershipData membership in data) - { - if (GetRequestingAgentID(remoteClient) != dataForAgentID) - { - if (!membership.ListInProfile) - { - // If we're sending group info to remoteclient about another agent, - // filter out groups the other agent doesn't want to share. - continue; - } - } - - OSDMap GroupDataMap = new OSDMap(6); - OSDMap NewGroupDataMap = new OSDMap(1); - - GroupDataMap.Add("GroupID", OSD.FromUUID(membership.GroupID)); - GroupDataMap.Add("GroupPowers", OSD.FromULong(membership.GroupPowers)); - GroupDataMap.Add("AcceptNotices", OSD.FromBoolean(membership.AcceptNotices)); - GroupDataMap.Add("GroupInsigniaID", OSD.FromUUID(membership.GroupPicture)); - GroupDataMap.Add("Contribution", OSD.FromInteger(membership.Contribution)); - GroupDataMap.Add("GroupName", OSD.FromString(membership.GroupName)); - NewGroupDataMap.Add("ListInProfile", OSD.FromBoolean(membership.ListInProfile)); - - GroupData.Add(GroupDataMap); - NewGroupData.Add(NewGroupDataMap); - } - - OSDMap llDataStruct = new OSDMap(3); - llDataStruct.Add("AgentData", AgentData); - llDataStruct.Add("GroupData", GroupData); - llDataStruct.Add("NewGroupData", NewGroupData); - - if (m_debugEnabled) - { - m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct)); - } - - IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); - - if (queue != null) - { - queue.Enqueue(queue.BuildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); - } - - } - private void SendScenePresenceUpdate(UUID AgentID, string Title) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Updating scene title for {0} with title: {1}", AgentID, Title); @@ -1380,54 +1399,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups presence.Grouptitle = Title; if (! presence.IsChildAgent) - presence.SendAvatarDataToAllClients(); + presence.SendAvatarDataToAllAgents(); } } } } - /// - /// Send updates to all clients who might be interested in groups data for dataForClientID - /// - private void UpdateAllClientsWithGroupInfo(UUID dataForClientID) + public void SendAgentGroupDataUpdate(IClientAPI remoteClient) { - if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Probably isn't nessesary to update every client in every scene. - // Need to examine client updates and do only what's nessesary. - lock (m_sceneList) - { - foreach (Scene scene in m_sceneList) - { - scene.ForEachClient(delegate(IClientAPI client) { SendAgentGroupDataUpdate(client, dataForClientID); }); - } - } + SendAgentGroupDataUpdate(remoteClient, true); } /// - /// Update remoteClient with group information about dataForAgentID + /// Tell remoteClient about its agent groups, and optionally send title to others /// - private void SendAgentGroupDataUpdate(IClientAPI remoteClient, UUID dataForAgentID) + private void SendAgentGroupDataUpdate(IClientAPI remoteClient, bool tellOthers) { if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called for {1}", System.Reflection.MethodBase.GetCurrentMethod().Name, remoteClient.Name); + // NPCs currently don't have a CAPs structure or event queues. There is a strong argument for conveying this information + // to them anyway since it makes writing server-side bots a lot easier, but for now we don't do anything. + if (remoteClient.SceneAgent.PresenceType == PresenceType.Npc) + return; + // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - OnAgentDataUpdateRequest(remoteClient, dataForAgentID, UUID.Zero); + UUID agentID = GetRequestingAgentID(remoteClient); - // Need to send a group membership update to the client - // UDP version doesn't seem to behave nicely. But we're going to send it out here - // with an empty group membership to hopefully remove groups being displayed due - // to the core Groups Stub - remoteClient.SendGroupMembership(new GroupMembershipData[0]); + SendDataUpdate(remoteClient, tellOthers); - GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, dataForAgentID); - SendGroupMembershipInfoViaCaps(remoteClient, dataForAgentID, membershipArray); - remoteClient.SendAvatarGroupsReply(dataForAgentID, membershipArray); + GroupMembershipData[] membershipArray = GetProfileListedGroupMemberships(remoteClient, agentID); + remoteClient.UpdateGroupMembership(membershipArray); - if (remoteClient.AgentId == dataForAgentID) - remoteClient.RefreshGroupMembership(); - } + remoteClient.SendAgentGroupDataUpdate(agentID, membershipArray); + } /// /// Get a list of groups memberships for the agent that are marked "ListInProfile" @@ -1465,7 +1470,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups membershipArray = membershipData.ToArray(); } } - + if (m_debugEnabled) { m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); @@ -1478,13 +1483,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return membershipArray; } - - private void SendAgentDataUpdate(IClientAPI remoteClient, UUID dataForAgentID, UUID activeGroupID, string activeGroupName, ulong activeGroupPowers, string activeGroupTitle) + //tell remoteClient about its agent group info, and optionally send title to others + private void SendDataUpdate(IClientAPI remoteClient, bool tellOthers) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); + UUID activeGroupID = UUID.Zero; + string activeGroupTitle = string.Empty; + string activeGroupName = string.Empty; + ulong activeGroupPowers = (ulong)GroupPowers.None; + + UUID agentID = GetRequestingAgentID(remoteClient); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(agentID, agentID); + if (membership != null) + { + activeGroupID = membership.GroupID; + activeGroupTitle = membership.GroupTitle; + activeGroupPowers = membership.GroupPowers; + activeGroupName = membership.GroupName; + } + + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, agentID); string firstname, lastname; if (account != null) { @@ -1497,9 +1516,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups lastname = "Unknown"; } - remoteClient.SendAgentDataUpdate(dataForAgentID, activeGroupID, firstname, + remoteClient.SendAgentDataUpdate(agentID, activeGroupID, firstname, lastname, activeGroupPowers, activeGroupName, activeGroupTitle); + + + if (tellOthers) + SendScenePresenceUpdate(agentID, activeGroupTitle); + + ScenePresence sp = (ScenePresence)remoteClient.SceneAgent; + if (sp != null) + sp.Grouptitle = activeGroupTitle; } #endregion @@ -1510,7 +1537,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - IClientAPI localClient = GetActiveClient(msgTo); + IClientAPI localClient = GetActiveRootClient(msgTo); if (localClient != null) { if (m_debugEnabled) m_log.InfoFormat("[GROUPS]: MsgTo ({0}) is local, delivering directly", localClient.Name); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 6b5b40a..08c7096 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// The UUID of the user making the request. /// - /// The ID of the record to retrieve. + /// The ID of the record to retrieve. /// GroupName may be specified instead, in which case this parameter will be UUID.Zero /// /// @@ -51,7 +51,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// GroupID may be specified instead, in which case this parmeter will be null. /// GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); - + GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID); + List FindGroups(UUID RequestingAgentID, string search); List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); @@ -88,7 +89,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// If the user is a member of the group then the data structure is returned. If not, then null is returned. /// GroupMembershipData GetAgentGroupMembership(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - + /// /// Get information about the groups to which a user belongs. /// diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index 1cb4747..98c7ed4 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -48,16 +48,16 @@ using OpenSim.Services.Interfaces; /*************************************************************************** * Simian Data Map * =============== - * + * * OwnerID -> Type -> Key * ----------------------- - * + * * UserID -> Group -> ActiveGroup * + GroupID - * + * * UserID -> GroupSessionDropped -> GroupID * UserID -> GroupSessionInvited -> GroupID - * + * * UserID -> GroupMember -> GroupID * + SelectedRoleID [UUID] * + AcceptNotices [bool] @@ -65,9 +65,9 @@ using OpenSim.Services.Interfaces; * + Contribution [int] * * UserID -> GroupRole[GroupID] -> RoleID - * - * - * GroupID -> Group -> GroupName + * + * + * GroupID -> Group -> GroupName * + Charter * + ShowInList * + InsigniaID @@ -79,17 +79,17 @@ using OpenSim.Services.Interfaces; * + EveryonePowers * + OwnerRoleID * + OwnersPowers - * + * * GroupID -> GroupRole -> RoleID * + Name * + Description * + Title * + Powers - * + * * GroupID -> GroupMemberInvite -> InviteID * + AgentID * + RoleID - * + * * GroupID -> GroupNotice -> NoticeID * + TimeStamp [uint] * + FromName [string] @@ -106,12 +106,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | GroupPowers.VoteOnProposal; // Would this be cleaner as (GroupPowers)ulong.MaxValue; @@ -168,12 +168,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; private Dictionary m_pendingRequests = new Dictionary(); - + private ExpiringCache m_memoryCache; private int m_cacheTimeout = 30; // private IUserAccountService m_accountService = null; - + #region Region Module interfaceBase Members @@ -229,10 +229,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout); } - + m_memoryCache = new ExpiringCache(); - + // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; @@ -244,7 +244,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void Close() { - m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -288,8 +287,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, - int membershipFee, bool openEnrollment, bool allowPublish, + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -314,7 +313,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); - + AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); return GroupID; @@ -326,8 +325,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, - UUID insigniaID, int membershipFee, bool openEnrollment, + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -351,7 +350,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -394,7 +393,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -435,7 +434,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { return null; } - } + } else if (!string.IsNullOrEmpty(groupName)) { if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) @@ -482,7 +481,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); } - + MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); @@ -490,7 +489,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; - MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); + MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); Dictionary Members; if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) @@ -547,7 +546,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { GroupMemberInfo = new OSDMap(); } - + GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); GroupMemberInfo["Contribution"] = OSD.FromInteger(0); @@ -625,7 +624,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Remove Group Member information for this group SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); - // By using a Simian Generics Type consisting of a prefix and a groupID, + // By using a Simian Generics Type consisting of a prefix and a groupID, // combined with RoleID as key allows us to get a list of roles a particular member // of a group is assigned to. string GroupRoleMemberType = "GroupRole" + groupID.ToString(); @@ -697,7 +696,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { data.members = 0; } - + // TODO: sort results? // data.searchOrder = order; @@ -722,8 +721,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); - data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); - + data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); + /////////////////////////////// // Agent Specific Information: // @@ -731,7 +730,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) { data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); - } + } /////////////////////////////// // Role Specific Information: @@ -741,8 +740,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { data.GroupTitle = GroupRoleInfo["Title"].AsString(); data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); - } - + } + /////////////////////////////// // Group Specific Information: // @@ -760,7 +759,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); - } + } } return data; @@ -795,7 +794,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); } } - + return memberships; } @@ -1018,7 +1017,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); - + } #endregion @@ -1251,7 +1250,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { "OwnerID", ownerID.ToString() }, { "Type", type } }; - + OSDMap response = CachedPostRequest(requestArgs); @@ -1358,7 +1357,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups || requestArgs["RequestMethod"] == "AddGeneric") { m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: clearing generics cache"); - + // Any and all updates cause the cache to clear m_memoryCache.Clear(); @@ -1384,14 +1383,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_memoryCache.TryGetValue(CacheKey, out response)) return response; - + if (! m_pendingRequests.ContainsKey(CacheKey)) { m_pendingRequests.Add(CacheKey,true); firstRequest = true; } } - + if (firstRequest) { // if it wasn't in the cache, pass the request to the Simian Grid Services @@ -1403,7 +1402,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { m_log.ErrorFormat("[SIMIAN GROUPS CONNECTOR]: request failed {0}", CacheKey); } - + // and cache the response lock (m_memoryCache) { @@ -1421,7 +1420,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // { // m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: query not in the cache"); // Util.PrintCallStack(); - + // // if it wasn't in the cache, pass the request to the Simian Grid Services // response = WebUtil.PostToService(m_groupsServerURI, requestArgs); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs index 9a42bac..ccfcd8b 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs @@ -74,14 +74,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests [Test] public void TestSendAgentGroupDataUpdate() { +/* AgentGroupDataUpdate is udp TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - + TestScene scene = new SceneHelpers().SetupScene(); IConfigSource configSource = new IniConfigSource(); - IConfig config = configSource.AddConfig("Groups"); + IConfig config = configSource.AddConfig("Groups"); config.Set("Enabled", true); - config.Set("Module", "GroupsModule"); + config.Set("Module", "GroupsModule"); config.Set("DebugEnabled", true); GroupsModule gm = new GroupsModule(); @@ -98,6 +99,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests Hashtable eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); + if((int)eventsResponse["int_response_code"] != (int)HttpStatusCode.OK) + { + eventsResponse = eqgm.GetEvents(UUID.Zero, sp.UUID); + if((int)eventsResponse["int_response_code"] != (int)HttpStatusCode.OK) + 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"]); @@ -116,7 +124,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests Assert.That(foundUpdate, Is.True, "Did not find AgentGroupDataUpdate in response"); - // TODO: More checking of more actual event data. + // TODO: More checking of more actual event data. +*/ } [Test] @@ -124,7 +133,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - + TestScene scene = new SceneHelpers().SetupScene(); MessageTransferModule mtm = new MessageTransferModule(); @@ -135,12 +144,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests IConfigSource configSource = new IniConfigSource(); { - IConfig config = configSource.AddConfig("Messaging"); + IConfig config = configSource.AddConfig("Messaging"); config.Set("MessageTransferModule", mtm.Name); } { - IConfig config = configSource.AddConfig("Groups"); + IConfig config = configSource.AddConfig("Groups"); config.Set("Enabled", true); config.Set("Module", gm.Name); config.Set("DebugEnabled", true); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 20555e4..fab7e8c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -53,17 +53,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; - public const GroupPowers DefaultEveryonePowers - = GroupPowers.AllowSetHome - | GroupPowers.Accountable - | GroupPowers.JoinChat - | GroupPowers.AllowVoiceChat - | GroupPowers.ReceiveNotices - | GroupPowers.StartProposal + public const GroupPowers DefaultEveryonePowers + = GroupPowers.AllowSetHome + | GroupPowers.Accountable + | GroupPowers.JoinChat + | GroupPowers.AllowVoiceChat + | GroupPowers.ReceiveNotices + | GroupPowers.StartProposal | GroupPowers.VoteOnProposal; // Would this be cleaner as (GroupPowers)ulong.MaxValue? - public const GroupPowers DefaultOwnerPowers + public const GroupPowers DefaultOwnerPowers = GroupPowers.Accountable | GroupPowers.AllowEditLand | GroupPowers.AllowFly @@ -114,7 +114,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupsServerURI = string.Empty; - private bool m_disableKeepAlive = false; + private bool m_disableKeepAlive = true; private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; @@ -174,13 +174,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_disableKeepAlive = groupsConfig.GetBoolean("XmlRpcDisableKeepAlive", false); + m_disableKeepAlive = groupsConfig.GetBoolean("XmlRpcDisableKeepAlive", true); m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); - m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) { m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled."); @@ -200,7 +200,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void Close() { - m_log.DebugFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -383,10 +382,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID); GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData); - - MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; - MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; - + if(MemberInfo != null) + { + MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; + MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; + } return MemberGroupProfile; } @@ -666,6 +666,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.ListInProfile = ((string)membership["ListInProfile"]) == "1"; data.AgentPowers = ulong.Parse((string)membership["AgentPowers"]); data.Title = (string)membership["Title"]; + if(membership.ContainsKey("OnlineStatus")) + data.OnlineStatus = (string)membership["OnlineStatus"]; members.Add(data); } @@ -803,11 +805,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) { + if (m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID)) + m_groupsAgentsInvitedToChatSession[groupID].Remove(agentID); + // If not in dropped list, add if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) - { m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); - } } } @@ -818,9 +821,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // If nessesary, remove from dropped list if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) - { m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); - } + + if (!m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID)) + m_groupsAgentsInvitedToChatSession[groupID].Add(agentID); } private void CreateGroupChatSessionTracking(UUID groupID) @@ -975,35 +979,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups try { - resp = req.Send(m_groupsServerURI, 10000); - - if ((m_cacheTimeout > 0) && (CacheKey != null)) - { - m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); - } + resp = req.Send(m_groupsServerURI); } catch (Exception e) { m_log.ErrorFormat( - "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}", - function, m_groupsServerURI); - - m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}{1}", e.Message, e.StackTrace); + "[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method {0} at {1}: {2}", + function, m_groupsServerURI, e.Message); - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + if(m_debugEnabled) { - m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", e.StackTrace); + + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + { + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); + } + + foreach (string key in param.Keys) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); + } } - foreach (string key in param.Keys) + if ((m_cacheTimeout > 0) && (CacheKey != null)) { - m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); + m_memoryCache.AddOrUpdate(CacheKey, resp, 10.0); } - Hashtable respData = new Hashtable(); respData.Add("error", e.ToString()); return respData; } + + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, 10.0); + } } if (resp.Value is Hashtable) @@ -1042,7 +1053,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void LogRespDataToConsoleError(UUID requestingAgentID, string function, Hashtable param, Hashtable respData) { m_log.ErrorFormat( - "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}", + "[XMLRPC-GROUPS-CONNECTOR]: Error when calling {0} for {1} with params {2}. Response params are {3}", function, requestingAgentID, Util.PrettyFormatToSingleLine(param), Util.PrettyFormatToSingleLine(respData)); } @@ -1134,6 +1145,7 @@ namespace Nwc.XmlRpc request.ContentType = "text/xml"; request.AllowWriteStreamBuffering = true; request.KeepAlive = !_disableKeepAlive; + request.Timeout = 30000; using (Stream stream = request.GetRequestStream()) { @@ -1141,7 +1153,7 @@ namespace Nwc.XmlRpc { _serializer.Serialize(xml, this); xml.Flush(); - } + } } XmlRpcResponse resp; -- cgit v1.1