diff options
Diffstat (limited to 'OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs')
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 81 |
1 files changed, 53 insertions, 28 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 0c81bb2..5d94ff7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | |||
@@ -29,6 +29,7 @@ using System; | |||
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using System.Threading; | ||
32 | using log4net; | 33 | using log4net; |
33 | using Nini.Config; | 34 | using Nini.Config; |
34 | using Nwc.XmlRpc; | 35 | using Nwc.XmlRpc; |
@@ -79,10 +80,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
79 | protected IFriendsService m_FriendsService = null; | 80 | protected IFriendsService m_FriendsService = null; |
80 | protected FriendsSimConnector m_FriendsSimConnector; | 81 | protected FriendsSimConnector m_FriendsSimConnector; |
81 | 82 | ||
82 | protected Dictionary<UUID, UserFriendData> m_Friends = | 83 | /// <summary> |
83 | new Dictionary<UUID, UserFriendData>(); | 84 | /// Cache friends lists for users. |
85 | /// </summary> | ||
86 | /// <remarks> | ||
87 | /// This is a complex and error-prone thing to do. At the moment, we assume that the efficiency gained in | ||
88 | /// permissions checks outweighs the disadvantages of that complexity. | ||
89 | /// </remarks> | ||
90 | protected Dictionary<UUID, UserFriendData> m_Friends = new Dictionary<UUID, UserFriendData>(); | ||
84 | 91 | ||
85 | protected HashSet<UUID> m_NeedsListOfFriends = new HashSet<UUID>(); | 92 | /// <summary> |
93 | /// Maintain a record of viewers that need to be sent notifications for friends that are online. This only | ||
94 | /// needs to be done on login. Subsequent online/offline friend changes are sent by a different mechanism. | ||
95 | /// </summary> | ||
96 | protected HashSet<UUID> m_NeedsListOfOnlineFriends = new HashSet<UUID>(); | ||
86 | 97 | ||
87 | protected IPresenceService PresenceService | 98 | protected IPresenceService PresenceService |
88 | { | 99 | { |
@@ -189,6 +200,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
189 | { | 200 | { |
190 | if (!m_Enabled) | 201 | if (!m_Enabled) |
191 | return; | 202 | return; |
203 | |||
192 | m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); | 204 | m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); |
193 | 205 | ||
194 | m_Scenes.Add(scene); | 206 | m_Scenes.Add(scene); |
@@ -241,16 +253,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
241 | client.OnInstantMessage += OnInstantMessage; | 253 | client.OnInstantMessage += OnInstantMessage; |
242 | client.OnApproveFriendRequest += OnApproveFriendRequest; | 254 | client.OnApproveFriendRequest += OnApproveFriendRequest; |
243 | client.OnDenyFriendRequest += OnDenyFriendRequest; | 255 | client.OnDenyFriendRequest += OnDenyFriendRequest; |
244 | client.OnTerminateFriendship += OnTerminateFriendship; | 256 | client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); |
245 | client.OnGrantUserRights += OnGrantUserRights; | 257 | client.OnGrantUserRights += OnGrantUserRights; |
246 | 258 | ||
247 | Util.FireAndForget(delegate { FetchFriendslist(client); }); | 259 | // Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and |
260 | // return misleading results from the still empty friends cache. | ||
261 | // If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls | ||
262 | // to GetFriends() will wait until CacheFriends() completes. Locks are insufficient. | ||
263 | CacheFriends(client); | ||
248 | } | 264 | } |
249 | 265 | ||
250 | /// Fetch the friends list or increment the refcount for the existing | 266 | /// <summary> |
251 | /// friends list | 267 | /// Cache the friends list or increment the refcount for the existing friends list. |
268 | /// </summary> | ||
269 | /// <param name="client"> | ||
270 | /// </param> | ||
271 | /// <returns> | ||
252 | /// Returns true if the list was fetched, false if it wasn't | 272 | /// Returns true if the list was fetched, false if it wasn't |
253 | protected virtual bool FetchFriendslist(IClientAPI client) | 273 | /// </returns> |
274 | protected virtual bool CacheFriends(IClientAPI client) | ||
254 | { | 275 | { |
255 | UUID agentID = client.AgentId; | 276 | UUID agentID = client.AgentId; |
256 | lock (m_Friends) | 277 | lock (m_Friends) |
@@ -297,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
297 | 318 | ||
298 | private void OnMakeRootAgent(ScenePresence sp) | 319 | private void OnMakeRootAgent(ScenePresence sp) |
299 | { | 320 | { |
300 | RefetchFriends(sp.ControllingClient); | 321 | RecacheFriends(sp.ControllingClient); |
301 | } | 322 | } |
302 | 323 | ||
303 | private void OnClientLogin(IClientAPI client) | 324 | private void OnClientLogin(IClientAPI client) |
@@ -309,8 +330,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
309 | StatusChange(agentID, true); | 330 | StatusChange(agentID, true); |
310 | 331 | ||
311 | // Register that we need to send the list of online friends to this user | 332 | // Register that we need to send the list of online friends to this user |
312 | lock (m_NeedsListOfFriends) | 333 | lock (m_NeedsListOfOnlineFriends) |
313 | m_NeedsListOfFriends.Add(agentID); | 334 | m_NeedsListOfOnlineFriends.Add(agentID); |
314 | } | 335 | } |
315 | 336 | ||
316 | public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) | 337 | public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client) |
@@ -318,9 +339,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
318 | UUID agentID = client.AgentId; | 339 | UUID agentID = client.AgentId; |
319 | 340 | ||
320 | // Check if the online friends list is needed | 341 | // Check if the online friends list is needed |
321 | lock (m_NeedsListOfFriends) | 342 | lock (m_NeedsListOfOnlineFriends) |
322 | { | 343 | { |
323 | if (!m_NeedsListOfFriends.Remove(agentID)) | 344 | if (!m_NeedsListOfOnlineFriends.Remove(agentID)) |
324 | return false; | 345 | return false; |
325 | } | 346 | } |
326 | 347 | ||
@@ -328,7 +349,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
328 | List<UUID> online = GetOnlineFriends(agentID); | 349 | List<UUID> online = GetOnlineFriends(agentID); |
329 | if (online.Count > 0) | 350 | if (online.Count > 0) |
330 | { | 351 | { |
331 | m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); | 352 | m_log.DebugFormat( |
353 | "[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", | ||
354 | client.Name, client.Scene.RegionInfo.RegionName, online.Count); | ||
355 | |||
332 | client.SendAgentOnline(online.ToArray()); | 356 | client.SendAgentOnline(online.ToArray()); |
333 | } | 357 | } |
334 | 358 | ||
@@ -586,7 +610,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
586 | } | 610 | } |
587 | 611 | ||
588 | // Update the local cache | 612 | // Update the local cache |
589 | RefetchFriends(client); | 613 | RecacheFriends(client); |
590 | 614 | ||
591 | // | 615 | // |
592 | // Notify the friend | 616 | // Notify the friend |
@@ -641,14 +665,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
641 | } | 665 | } |
642 | } | 666 | } |
643 | } | 667 | } |
644 | 668 | ||
645 | private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) | 669 | public void RemoveFriendship(IClientAPI client, UUID exfriendID) |
646 | { | 670 | { |
647 | if (!DeleteFriendship(agentID, exfriendID)) | 671 | if (!DeleteFriendship(client.AgentId, exfriendID)) |
648 | client.SendAlertMessage("Unable to terminate friendship on this sim."); | 672 | client.SendAlertMessage("Unable to terminate friendship on this sim."); |
649 | 673 | ||
650 | // Update local cache | 674 | // Update local cache |
651 | RefetchFriends(client); | 675 | RecacheFriends(client); |
652 | 676 | ||
653 | client.SendTerminateFriend(exfriendID); | 677 | client.SendTerminateFriend(exfriendID); |
654 | 678 | ||
@@ -667,9 +691,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
667 | if (friendSession != null) | 691 | if (friendSession != null) |
668 | { | 692 | { |
669 | GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); | 693 | GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); |
670 | m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); | 694 | m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID); |
671 | } | 695 | } |
672 | } | 696 | } |
673 | } | 697 | } |
674 | 698 | ||
675 | private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) | 699 | private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) |
@@ -769,7 +793,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
769 | 793 | ||
770 | 794 | ||
771 | // Update the local cache | 795 | // Update the local cache |
772 | RefetchFriends(friendClient); | 796 | RecacheFriends(friendClient); |
773 | 797 | ||
774 | // we're done | 798 | // we're done |
775 | return true; | 799 | return true; |
@@ -802,7 +826,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
802 | // the friend in this sim as root agent | 826 | // the friend in this sim as root agent |
803 | friendClient.SendTerminateFriend(exfriendID); | 827 | friendClient.SendTerminateFriend(exfriendID); |
804 | // update local cache | 828 | // update local cache |
805 | RefetchFriends(friendClient); | 829 | RecacheFriends(friendClient); |
806 | // we're done | 830 | // we're done |
807 | return true; | 831 | return true; |
808 | } | 832 | } |
@@ -819,16 +843,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
819 | if (onlineBitChanged) | 843 | if (onlineBitChanged) |
820 | { | 844 | { |
821 | if ((rights & (int)FriendRights.CanSeeOnline) == 1) | 845 | if ((rights & (int)FriendRights.CanSeeOnline) == 1) |
822 | friendClient.SendAgentOnline(new UUID[] { new UUID(userID) }); | 846 | friendClient.SendAgentOnline(new UUID[] { userID }); |
823 | else | 847 | else |
824 | friendClient.SendAgentOffline(new UUID[] { new UUID(userID) }); | 848 | friendClient.SendAgentOffline(new UUID[] { userID }); |
825 | } | 849 | } |
826 | else | 850 | else |
827 | { | 851 | { |
828 | bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; | 852 | bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; |
829 | if (canEditObjectsChanged) | 853 | if (canEditObjectsChanged) |
830 | friendClient.SendChangeUserRights(userID, friendID, rights); | 854 | friendClient.SendChangeUserRights(userID, friendID, rights); |
831 | |||
832 | } | 855 | } |
833 | 856 | ||
834 | // Update local cache | 857 | // Update local cache |
@@ -847,7 +870,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
847 | IClientAPI friendClient = LocateClientObject(friendID); | 870 | IClientAPI friendClient = LocateClientObject(friendID); |
848 | if (friendClient != null) | 871 | if (friendClient != null) |
849 | { | 872 | { |
850 | // the friend in this sim as root agent | 873 | // the friend in this sim as root agent |
851 | if (online) | 874 | if (online) |
852 | friendClient.SendAgentOnline(new UUID[] { userID }); | 875 | friendClient.SendAgentOnline(new UUID[] { userID }); |
853 | else | 876 | else |
@@ -902,8 +925,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends | |||
902 | return FriendsService.GetFriends(client.AgentId); | 925 | return FriendsService.GetFriends(client.AgentId); |
903 | } | 926 | } |
904 | 927 | ||
905 | private void RefetchFriends(IClientAPI client) | 928 | private void RecacheFriends(IClientAPI client) |
906 | { | 929 | { |
930 | // FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event | ||
931 | // is on the critical path for transferring an avatar from one region to another. | ||
907 | UUID agentID = client.AgentId; | 932 | UUID agentID = client.AgentId; |
908 | lock (m_Friends) | 933 | lock (m_Friends) |
909 | { | 934 | { |