From db24e57cab88217e49c3c564a2c025a44199520e Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Sun, 28 Feb 2010 08:36:13 -0800 Subject: [PATCH] Friends connectors finished. Status notification working across the board. One last bug: friends online upon login are not being sent to the user. --- .../Avatar/Friends/FriendsModule.cs | 185 ++++++++++++------ .../Avatar/Friends/FriendsRequestHandler.cs | 155 ++++++++++++++- .../Connectors/Friends/FriendsSimConnector.cs | 112 ++++++++++- 3 files changed, 385 insertions(+), 67 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 7e7d9e9cb3..cc3a3ee4d7 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -115,6 +115,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } + public IScene Scene + { + get + { + if (m_Scenes.Count > 0) + return m_Scenes[0]; + else + return null; + } + } + public void Initialise(IConfigSource config) { IConfig friendsConfig = config.Configs["Friends"]; @@ -276,6 +287,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void SendPresence(UUID agentID) { + // Inform the friends that this user is online + StatusChange(agentID, true); + + // Now send the list of online friends to this user if (!m_Friends.ContainsKey(agentID)) { m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID); @@ -291,11 +306,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List online = GetOnlineFriends(agentID); - m_log.DebugFormat("[FRIENDS]: User {0} has {1} friends online", agentID, online.Count); + m_log.DebugFormat("[FRIENDS]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); client.SendAgentOnline(online.ToArray()); - // Now inform the friends that this user is online - StatusChange(agentID, true); } List GetOnlineFriends(UUID userID) @@ -315,7 +328,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends foreach (PresenceInfo pi in presence) { if (pi.Online) + { online.Add(new UUID(pi.UserID)); + //m_log.DebugFormat("[XXX] {0} friend online {1}", userID, pi.UserID); + } } return online; @@ -324,13 +340,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // // Find the client for a ID // - private IClientAPI LocateClientObject(UUID agentID) + public IClientAPI LocateClientObject(UUID agentID) { - Scene scene=GetClientScene(agentID); + Scene scene = GetClientScene(agentID); if(scene == null) return null; - ScenePresence presence=scene.GetScenePresence(agentID); + ScenePresence presence = scene.GetScenePresence(agentID); if(presence == null) return null; @@ -386,19 +402,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (UUID.TryParse(friend.Friend, out friendID)) { - IClientAPI friendClient = LocateClientObject(friendID); - if (friendClient != null) - { - //m_log.DebugFormat("[FRIENDS]: Notify {0} that user {1} is {2}", friend.Friend, userID, online); - // the friend in this sim as root agent - if (online) - friendClient.SendAgentOnline(new UUID[] { userID }); - else - friendClient.SendAgentOffline(new UUID[] { userID }); - // we're done + // Try local + if (LocalStatusNotification(userID, friendID, online)) return; - } - + // The friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); @@ -438,14 +445,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // We stick this agent's ID as imSession, so that it's directly available on the receiving end im.imSessionID = im.fromAgentID; - IClientAPI friendClient = LocateClientObject(friendID); - if (friendClient != null) - { - // the prospective friend in this sim as root agent - friendClient.SendInstantMessage(im); - // we're done - return ; - } + // Try the local sim + if (LocalFriendshipOffered(friendID, im)) + return; // The prospective friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); @@ -471,26 +473,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Notify the friend // - IClientAPI friendClient = LocateClientObject(friendID); - if (friendClient != null) + // Try Local + if (LocalFriendshipApproved(agentID, client.Name, friendID)) { - // the prospective friend in this sim as root agent - GridInstantMessage im = new GridInstantMessage(client.Scene, client.AgentId, client.Name, friendID, - (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, client.AgentId.ToString(), false, Vector3.Zero); - friendClient.SendInstantMessage(im); client.SendAgentOnline(new UUID[] { friendID }); - // update the local cache - m_Friends[friendID].Friends = FriendsService.GetFriends(friendID); - // we're done return; } + // The friend is not here PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipApproved(region, agentID, friendID); + m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); client.SendAgentOnline(new UUID[] { friendID }); } @@ -507,24 +503,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Notify the friend // - IClientAPI friendClient = LocateClientObject(friendID); - if (friendClient != null) - { - // the prospective friend in this sim as root agent - - GridInstantMessage im = new GridInstantMessage(client.Scene, client.AgentId, client.Name, friendID, - (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, client.AgentId.ToString(), false, Vector3.Zero); - friendClient.SendInstantMessage(im); - // we're done + // Try local + if (LocalFriendshipDenied(agentID, client.Name, friendID)) return; - } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipDenied(region, agentID, friendID); + m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); } } @@ -542,16 +530,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Notify the friend // - IClientAPI friendClient = LocateClientObject(exfriendID); - if (friendClient != null) - { - // the friend in this sim as root agent - friendClient.SendTerminateFriend(exfriendID); - // update local cache - m_Friends[exfriendID].Friends = FriendsService.GetFriends(exfriendID); - // we're done + // Try local + if (LocalFriendshipTerminated(exfriendID)) return; - } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); @@ -587,5 +568,97 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_FriendsSimConnector.GrantRights(region, requester, target); } } + + #region Local + + public bool LocalFriendshipOffered(UUID toID, GridInstantMessage im) + { + IClientAPI friendClient = LocateClientObject(toID); + if (friendClient != null) + { + // the prospective friend in this sim as root agent + friendClient.SendInstantMessage(im); + // we're done + return true; + } + return false; + } + + public bool LocalFriendshipApproved(UUID userID, string userName, UUID friendID) + { + IClientAPI friendClient = LocateClientObject(friendID); + if (friendClient != null) + { + // the prospective friend in this sim as root agent + GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID, + (byte)OpenMetaverse.InstantMessageDialog.FriendshipAccepted, userID.ToString(), false, Vector3.Zero); + friendClient.SendInstantMessage(im); + // update the local cache + m_Friends[friendID].Friends = FriendsService.GetFriends(friendID); + // we're done + return true; + } + + return false; + } + + public bool LocalFriendshipDenied(UUID userID, string userName, UUID friendID) + { + IClientAPI friendClient = LocateClientObject(friendID); + if (friendClient != null) + { + // the prospective friend in this sim as root agent + + GridInstantMessage im = new GridInstantMessage(Scene, userID, userName, friendID, + (byte)OpenMetaverse.InstantMessageDialog.FriendshipDeclined, userID.ToString(), false, Vector3.Zero); + friendClient.SendInstantMessage(im); + // we're done + return true; + } + + return false; + } + + public bool LocalFriendshipTerminated(UUID exfriendID) + { + IClientAPI friendClient = LocateClientObject(exfriendID); + if (friendClient != null) + { + // the friend in this sim as root agent + friendClient.SendTerminateFriend(exfriendID); + // update local cache + m_Friends[exfriendID].Friends = FriendsService.GetFriends(exfriendID); + // we're done + return true; + } + + return false; + } + + public bool LocalGrantRights() + { + // TODO + return true; + } + + public bool LocalStatusNotification(UUID userID, UUID friendID, bool online) + { + IClientAPI friendClient = LocateClientObject(friendID); + if (friendClient != null) + { + //m_log.DebugFormat("[FRIENDS]: Notify {0} that user {1} is {2}", friend.Friend, userID, online); + // the friend in this sim as root agent + if (online) + friendClient.SendAgentOnline(new UUID[] { userID }); + else + friendClient.SendAgentOffline(new UUID[] { userID }); + // we're done + return true; + } + + return false; + } + #endregion + } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs index cde54ed3fd..e7b74a90d0 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs @@ -75,8 +75,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends switch (method) { - case "TEST": - break; + case "friendship_offered": + return FriendshipOffered(request); + case "friendship_approved": + return FriendshipApproved(request); + case "friendship_denied": + return FriendshipDenied(request); + case "friendship_terminated": + return FriendshipTerminated(request); + case "grant_rights": + return GrantRights(request); + case "status": + return StatusNotification(request); } } catch (Exception e) @@ -87,6 +97,146 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return FailureResult(); } + byte[] FriendshipOffered(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + string message = string.Empty; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) + return FailureResult(); + + message = request["Message"].ToString(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, "", toID, + (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero); + + if (m_FriendsModule.LocalFriendshipOffered(toID, im)) + return SuccessResult(); + + return FailureResult(); + } + + byte[] FriendshipApproved(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + string fromName = string.Empty; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) + return FailureResult(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + if (request.ContainsKey("FromName")) + fromName = request["FromName"].ToString(); + + if (m_FriendsModule.LocalFriendshipApproved(fromID, fromName, toID)) + return SuccessResult(); + + return FailureResult(); + } + + byte[] FriendshipDenied(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + string fromName = string.Empty; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) + return FailureResult(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + if (request.ContainsKey("FromName")) + fromName = request["FromName"].ToString(); + + if (m_FriendsModule.LocalFriendshipDenied(fromID, fromName, toID)) + return SuccessResult(); + + return FailureResult(); + } + + byte[] FriendshipTerminated(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) + return FailureResult(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + if (m_FriendsModule.LocalFriendshipTerminated(toID)) + return SuccessResult(); + + return FailureResult(); + } + + byte[] GrantRights(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID")) + return FailureResult(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + if (m_FriendsModule.LocalGrantRights(/* ??? */)) + return SuccessResult(); + + return FailureResult(); + } + + byte[] StatusNotification(Dictionary request) + { + UUID fromID = UUID.Zero; + UUID toID = UUID.Zero; + bool online = false; + + if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID") || !request.ContainsKey("Online")) + return FailureResult(); + + if (!UUID.TryParse(request["FromID"].ToString(), out fromID)) + return FailureResult(); + + if (!UUID.TryParse(request["ToID"].ToString(), out toID)) + return FailureResult(); + + if (!Boolean.TryParse(request["Online"].ToString(), out online)) + return FailureResult(); + + if (m_FriendsModule.LocalStatusNotification(fromID, toID, online)) + return SuccessResult(); + + return FailureResult(); + } + + #region Misc + private byte[] FailureResult() { return BoolResult(false); @@ -130,5 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return ms.ToArray(); } + #endregion } } diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs index 081e354d3d..490c8cfed3 100644 --- a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs +++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs @@ -27,45 +27,139 @@ using System; using System.Collections.Generic; +using System.Reflection; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers.HttpServer; using OpenMetaverse; +using log4net; namespace OpenSim.Services.Connectors.Friends { public class FriendsSimConnector { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "friendship_offered"; + + sendData["FromID"] = userID.ToString(); + sendData["ToID"] = friendID.ToString(); + sendData["Message"] = message; + + return Call(region, sendData); + } - public bool FriendshipApproved(GridRegion region, UUID userID, UUID friendID) + public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "friendship_approved"; + + sendData["FromID"] = userID.ToString(); + sendData["FromName"] = userName; + sendData["ToID"] = friendID.ToString(); + + return Call(region, sendData); } - public bool FriendshipDenied(GridRegion region, UUID userID, UUID friendID) + public bool FriendshipDenied(GridRegion region, UUID userID, string userName, UUID friendID) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "friendship_denied"; + + sendData["FromID"] = userID.ToString(); + sendData["FromName"] = userName; + sendData["ToID"] = friendID.ToString(); + + return Call(region, sendData); } public bool FriendshipTerminated(GridRegion region, UUID userID, UUID friendID) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "friendship_terminated"; + + sendData["FromID"] = userID.ToString(); + sendData["ToID"] = friendID.ToString(); + + return Call(region, sendData); } - public bool GrantRights(GridRegion region, UUID requester, UUID target) + public bool GrantRights(GridRegion region, UUID userID, UUID friendID) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "grant_rights"; + + sendData["FromID"] = userID.ToString(); + sendData["ToID"] = friendID.ToString(); + + return Call(region, sendData); } public bool StatusNotify(GridRegion region, UUID userID, UUID friendID, bool online) { - return true; + Dictionary sendData = new Dictionary(); + //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "status"; + + sendData["FromID"] = userID.ToString(); + sendData["ToID"] = friendID.ToString(); + sendData["Online"] = online.ToString(); + + return Call(region, sendData); + } + + private bool Call(GridRegion region, Dictionary sendData) + { + string reqString = ServerUtils.BuildQueryString(sendData); + // m_log.DebugFormat("[FRIENDS CONNECTOR]: queryString = {0}", reqString); + try + { + string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + url + "/friends", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("RESULT")) + { + if (replyData["RESULT"].ToString().ToLower() == "true") + return true; + else + return false; + } + else + m_log.DebugFormat("[FRIENDS CONNECTOR]: reply data does not contain result field"); + + } + else + m_log.DebugFormat("[FRIENDS CONNECTOR]: received empty reply"); + } + catch (Exception e) + { + m_log.DebugFormat("[FRIENDS CONNECTOR]: Exception when contacting remote sim: {0}", e.Message); + } + + return false; } } }