HG Friends: reroute the status notifications to the HGFriends service, so that they can scale better. They were previously being handled by the UAS; that is still there, but it's now obsolete and will be removed in a future release.

0.7.4.1
Diva Canto 2012-03-21 10:35:06 -07:00
parent d8bcb78b10
commit 4a9ca3ca8f
9 changed files with 248 additions and 8 deletions

View File

@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
IUserManagement m_uMan;
IUserManagement UserManagementModule
public IUserManagement UserManagementModule
{
get
{

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
@ -10,10 +11,14 @@ using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
using OpenMetaverse;
using log4net;
namespace OpenSim.Region.CoreModules.Avatar.Friends
{
public class HGStatusNotifier
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private HGFriendsModule m_FriendsModule;
public HGStatusNotifier(HGFriendsModule friendsModule)
@ -31,14 +36,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
List<string> ids = new List<string>();
foreach (FriendInfo f in kvp.Value)
ids.Add(f.Friend);
UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
List<UUID> friendsOnline = uConn.StatusNotification(ids, userID, online);
if (online && friendsOnline.Count > 0)
if (ids.Count == 0)
continue; // no one to notify. caller don't do this
m_log.DebugFormat("[HG STATUS NOTIFIER]: Notifying {0} friends in {1}", ids.Count, kvp.Key);
// ASSUMPTION: we assume that all users for one home domain
// have exactly the same set of service URLs.
// If this is ever not true, we need to change this.
UUID friendID = UUID.Zero; String tmp = String.Empty;
if (Util.ParseUniversalUserIdentifier(ids[0], out friendID, out tmp, out tmp, out tmp, out tmp))
{
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
if (client != null)
client.SendAgentOnline(friendsOnline.ToArray());
string friendsServerURI = m_FriendsModule.UserManagementModule.GetUserServerURL(friendID, "FriendsServerURI");
HGFriendsServicesConnector fConn = new HGFriendsServicesConnector(friendsServerURI);
List<UUID> friendsOnline = fConn.StatusNotification(ids, userID, online);
if (online && friendsOnline.Count > 0)
{
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
if (client != null)
client.SendAgentOnline(friendsOnline.ToArray());
}
}
}
}

View File

@ -105,6 +105,9 @@ namespace OpenSim.Server.Handlers.Hypergrid
case "validate_friendship_offered":
return ValidateFriendshipOffered(request);
case "statusnotification":
return StatusNotification(request);
/*
case "friendship_approved":
return FriendshipApproved(request);
@ -228,6 +231,59 @@ namespace OpenSim.Server.Handlers.Hypergrid
return BoolResult(success);
}
byte[] StatusNotification(Dictionary<string, object> request)
{
UUID principalID = UUID.Zero;
if (request.ContainsKey("userID"))
UUID.TryParse(request["userID"].ToString(), out principalID);
else
{
m_log.WarnFormat("[HGFRIENDS HANDLER]: no userID in request to notify");
return FailureResult();
}
bool online = true;
if (request.ContainsKey("online"))
Boolean.TryParse(request["online"].ToString(), out online);
else
{
m_log.WarnFormat("[HGFRIENDS HANDLER]: no online in request to notify");
return FailureResult();
}
List<string> friends = new List<string>();
int i = 0;
foreach (KeyValuePair<string, object> kvp in request)
{
if (kvp.Key.Equals("friend_" + i.ToString()))
{
friends.Add(kvp.Value.ToString());
i++;
}
}
List<UUID> onlineFriends = m_TheService.StatusNotification(friends, principalID, online);
Dictionary<string, object> result = new Dictionary<string, object>();
if ((onlineFriends == null) || ((onlineFriends != null) && (onlineFriends.Count == 0)))
result["RESULT"] = "NULL";
else
{
i = 0;
foreach (UUID f in onlineFriends)
{
result["friend_" + i] = f.ToString();
i++;
}
}
string xmlString = ServerUtils.BuildXmlResponse(result);
//m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
UTF8Encoding encoding = new UTF8Encoding();
return encoding.GetBytes(xmlString);
}
#endregion

View File

@ -222,6 +222,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
}
[Obsolete]
public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient)
{
Hashtable hash = new Hashtable();

View File

@ -255,6 +255,58 @@ namespace OpenSim.Services.Connectors.Hypergrid
return false;
}
public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
List<UUID> friendsOnline = new List<UUID>();
sendData["METHOD"] = "statusnotification";
sendData["userID"] = userID.ToString();
sendData["online"] = online.ToString();
int i = 0;
foreach (string s in friends)
{
sendData["friend_" + i.ToString()] = s;
i++;
}
string reply = string.Empty;
string uri = m_ServerURI + "/hgfriends";
try
{
reply = SynchronousRestFormsRequester.MakeRequest("POST",
uri,
ServerUtils.BuildQueryString(sendData));
}
catch (Exception e)
{
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
return friendsOnline;
}
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
// Here is the actual response
foreach (string key in replyData.Keys)
{
if (key.StartsWith("friend_") && replyData[key] != null)
{
UUID uuid;
if (UUID.TryParse(replyData[key].ToString(), out uuid))
friendsOnline.Add(uuid);
}
}
}
else
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Received empty reply from remote StatusNotify");
return friendsOnline;
}
#endregion
}
}

View File

@ -417,6 +417,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
GetBoolResponse(request, out reason);
}
[Obsolete]
public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
{
Hashtable hash = new Hashtable();

View File

@ -214,6 +214,91 @@ namespace OpenSim.Services.HypergridService
return false;
}
public List<UUID> StatusNotification(List<string> friends, UUID foreignUserID, bool online)
{
if (m_FriendsService == null || m_PresenceService == null)
{
m_log.WarnFormat("[HGFRIENDS SERVICE]: Unable to perform status notifications because friends or presence services are missing");
return new List<UUID>();
}
// Let's unblock the caller right now, and take it from here async
List<UUID> localFriendsOnline = new List<UUID>();
m_log.DebugFormat("[HGFRIENDS SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends of {2} status",
foreignUserID, friends.Count, (online ? "online" : "offline"));
// First, let's double check that the reported friends are, indeed, friends of that user
// And let's check that the secret matches
List<string> usersToBeNotified = new List<string>();
foreach (string uui in friends)
{
UUID localUserID;
string secret = string.Empty, tmp = string.Empty;
if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
{
FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
foreach (FriendInfo finfo in friendInfos)
{
if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret))
{
// great!
usersToBeNotified.Add(localUserID.ToString());
}
}
}
}
// Now, let's send the notifications
//m_log.DebugFormat("[HGFRIENDS SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count);
// First, let's send notifications to local users who are online in the home grid
PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
if (friendSessions != null && friendSessions.Length > 0)
{
PresenceInfo friendSession = null;
foreach (PresenceInfo pinfo in friendSessions)
if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents
{
friendSession = pinfo;
break;
}
if (friendSession != null)
{
ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online);
usersToBeNotified.Remove(friendSession.UserID.ToString());
UUID id;
if (UUID.TryParse(friendSession.UserID, out id))
localFriendsOnline.Add(id);
}
}
// Lastly, let's notify the rest who may be online somewhere else
foreach (string user in usersToBeNotified)
{
UUID id = new UUID(user);
//m_UserAgentService.LocateUser(id);
//etc...
//if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
//{
// string url = m_TravelingAgents[id].GridExternalName;
// // forward
//}
//m_log.WarnFormat("[HGFRIENDS SERVICE]: User {0} is visiting another grid. HG Status notifications still not implemented.", user);
}
// and finally, let's send the online friends
if (online)
{
return localFriendsOnline;
}
else
return new List<UUID>();
}
#endregion IHGFriendsService
#region Aux
@ -296,6 +381,28 @@ namespace OpenSim.Services.HypergridService
return false;
}
protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online)
{
UUID userID;
if (UUID.TryParse(user, out userID))
{
if (m_FriendsLocalSimConnector != null)
{
m_log.DebugFormat("[HGFRIENDS SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online);
}
else
{
GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
if (region != null)
{
m_log.DebugFormat("[HGFRIENDS SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online);
}
}
}
}
#endregion Aux
}
}

View File

@ -334,6 +334,7 @@ namespace OpenSim.Services.HypergridService
return false;
}
[Obsolete]
public List<UUID> StatusNotification(List<string> friends, UUID foreignUserID, bool online)
{
if (m_FriendsService == null || m_PresenceService == null)
@ -414,6 +415,7 @@ namespace OpenSim.Services.HypergridService
return new List<UUID>();
}
[Obsolete]
protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online)
{
UUID userID;

View File

@ -65,8 +65,8 @@ namespace OpenSim.Services.Interfaces
UUID GetUUID(String first, String last);
// Returns the local friends online
[Obsolete]
List<UUID> StatusNotification(List<string> friends, UUID userID, bool online);
//List<UUID> GetOnlineFriends(UUID userID, List<string> friends);
bool IsAgentComingHome(UUID sessionID, string thisGridExternalName);
bool VerifyAgent(UUID sessionID, string token);
@ -92,6 +92,8 @@ namespace OpenSim.Services.Interfaces
bool DeleteFriendship(FriendInfo finfo, string secret);
bool FriendshipOffered(UUID from, string fromName, UUID to, string message);
bool ValidateFriendshipOffered(UUID fromID, UUID toID);
// Returns the local friends online
List<UUID> StatusNotification(List<string> friends, UUID userID, bool online);
}
public interface IInstantMessageSimConnector