HG friends: Status notifications working. Also initial logins get the online friends in other grids.
parent
336665e035
commit
24f28d3534
|
@ -139,7 +139,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
if (moduleConfig != null)
|
||||
{
|
||||
string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
|
||||
m_log.DebugFormat("[XXX] {0} compared to {1}", name, Name);
|
||||
if (name == Name)
|
||||
{
|
||||
InitModule(config);
|
||||
|
@ -183,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
{
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
public virtual void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
@ -302,6 +301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
{
|
||||
UUID agentID = client.AgentId;
|
||||
|
||||
//m_log.DebugFormat("[XXX]: OnClientLogin!");
|
||||
// Inform the friends that this user is online
|
||||
StatusChange(agentID, true);
|
||||
|
||||
|
@ -405,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
}
|
||||
|
||||
if (friendList.Count > 0)
|
||||
{
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
GetOnlineFriends(userID, friendList, online);
|
||||
|
||||
return online;
|
||||
}
|
||||
|
||||
protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
|
||||
{
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find the client for a ID
|
||||
/// </summary>
|
||||
|
@ -472,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
Util.FireAndForget(
|
||||
delegate
|
||||
{
|
||||
foreach (FriendInfo fi in friendList)
|
||||
{
|
||||
//m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID);
|
||||
// Notify about this user status
|
||||
StatusNotify(fi, agentID, online);
|
||||
}
|
||||
m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
|
||||
// Notify about this user status
|
||||
StatusNotify(friendList, agentID, online);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void StatusNotify(FriendInfo friend, UUID userID, bool online)
|
||||
protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
|
||||
{
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
foreach (FriendInfo friend in friendList)
|
||||
{
|
||||
// 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() });
|
||||
if (friendSessions != null && friendSessions.Length > 0)
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
{
|
||||
PresenceInfo friendSession = null;
|
||||
foreach (PresenceInfo pinfo in friendSessions)
|
||||
if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
|
||||
{
|
||||
friendSession = pinfo;
|
||||
break;
|
||||
}
|
||||
// Try local
|
||||
if (LocalStatusNotification(userID, friendID, online))
|
||||
return;
|
||||
|
||||
if (friendSession != null)
|
||||
// The friend is not here [as root]. Let's forward.
|
||||
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
|
||||
if (friendSessions != null && friendSessions.Length > 0)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
//m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
|
||||
m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
|
||||
}
|
||||
}
|
||||
PresenceInfo friendSession = null;
|
||||
foreach (PresenceInfo pinfo in friendSessions)
|
||||
if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
|
||||
{
|
||||
friendSession = pinfo;
|
||||
break;
|
||||
}
|
||||
|
||||
// Friend is not online. Ignore.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
|
||||
if (friendSession != null)
|
||||
{
|
||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||
//m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
|
||||
m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
|
||||
}
|
||||
}
|
||||
|
||||
// Friend is not online. Ignore.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -670,7 +673,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
FriendInfo[] friends = GetFriends(remoteClient.AgentId);
|
||||
if (friends.Length == 0)
|
||||
{
|
||||
m_log.DebugFormat("[XXX]: agent {0} has no friends", requester);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
|||
namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule
|
||||
public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
|
@ -56,6 +56,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
get { return "HGFriendsModule"; }
|
||||
}
|
||||
|
||||
public override void AddRegion(Scene scene)
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return;
|
||||
|
||||
base.AddRegion(scene);
|
||||
scene.RegisterModuleInterface<IFriendsSimConnector>(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IFriendsSimConnector
|
||||
|
||||
/// <summary>
|
||||
/// Notify the user that the friend's status changed
|
||||
/// </summary>
|
||||
/// <param name="userID">user to be notified</param>
|
||||
/// <param name="friendID">friend whose status changed</param>
|
||||
/// <param name="online">status</param>
|
||||
/// <returns></returns>
|
||||
public bool StatusNotify(UUID userID, UUID friendID, bool online)
|
||||
{
|
||||
return LocalStatusNotification(friendID, userID, online);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override bool FetchFriendslist(IClientAPI client)
|
||||
|
@ -103,6 +128,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
return false;
|
||||
}
|
||||
|
||||
protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
|
||||
{
|
||||
// Let's single out the UUIs
|
||||
List<string> localFriends = new List<string>();
|
||||
List<string> foreignFriends = new List<string>();
|
||||
string tmp = string.Empty;
|
||||
|
||||
foreach (string s in friendList)
|
||||
{
|
||||
UUID id;
|
||||
if (UUID.TryParse(s, out id))
|
||||
localFriends.Add(s);
|
||||
else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
|
||||
{
|
||||
foreignFriends.Add(s);
|
||||
// add it here too, who knows maybe the foreign friends happens to be on this grid
|
||||
localFriends.Add(id.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// OK, see who's present on this grid
|
||||
List<string> toBeRemoved = new List<string>();
|
||||
PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
|
||||
foreach (PresenceInfo pi in presence)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
{
|
||||
online.Add(presenceID);
|
||||
foreach (string s in foreignFriends)
|
||||
if (s.StartsWith(pi.UserID))
|
||||
toBeRemoved.Add(s);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string s in toBeRemoved)
|
||||
foreignFriends.Remove(s);
|
||||
|
||||
// OK, let's send this up the stack, and leave a closure here
|
||||
// collecting online friends in other grids
|
||||
Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
|
||||
|
||||
}
|
||||
|
||||
private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
|
||||
{
|
||||
// let's divide the friends on a per-domain basis
|
||||
Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
|
||||
foreach (string friend in foreignFriends)
|
||||
{
|
||||
UUID friendID;
|
||||
if (!UUID.TryParse(friend, out friendID))
|
||||
{
|
||||
// it's a foreign friend
|
||||
string url = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
|
||||
{
|
||||
if (!friendsPerDomain.ContainsKey(url))
|
||||
friendsPerDomain[url] = new List<string>();
|
||||
friendsPerDomain[url].Add(friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, call those worlds
|
||||
|
||||
foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
|
||||
{
|
||||
List<string> ids = new List<string>();
|
||||
foreach (string f in kvp.Value)
|
||||
ids.Add(f);
|
||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
|
||||
List<UUID> online = uConn.GetOnlineFriends(userID, ids);
|
||||
// Finally send the notifications to the user
|
||||
// this whole process may take a while, so let's check at every
|
||||
// iteration that the user is still here
|
||||
IClientAPI client = LocateClientObject(userID);
|
||||
if (client != null)
|
||||
client.SendAgentOnline(online.ToArray());
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
|
||||
{
|
||||
// First, let's divide the friends on a per-domain basis
|
||||
Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
|
||||
foreach (FriendInfo friend in friendList)
|
||||
{
|
||||
UUID friendID;
|
||||
if (UUID.TryParse(friend.Friend, out friendID))
|
||||
{
|
||||
if (!friendsPerDomain.ContainsKey("local"))
|
||||
friendsPerDomain["local"] = new List<FriendInfo>();
|
||||
friendsPerDomain["local"].Add(friend);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it's a foreign friend
|
||||
string url = string.Empty, tmp = string.Empty;
|
||||
if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
|
||||
{
|
||||
// Let's try our luck in the local sim. Who knows, maybe it's here
|
||||
if (LocalStatusNotification(userID, friendID, online))
|
||||
continue;
|
||||
|
||||
if (!friendsPerDomain.ContainsKey(url))
|
||||
friendsPerDomain[url] = new List<FriendInfo>();
|
||||
friendsPerDomain[url].Add(friend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the local friends, just call the base method
|
||||
// Let's do this first of all
|
||||
if (friendsPerDomain.ContainsKey("local"))
|
||||
base.StatusNotify(friendsPerDomain["local"], userID, online);
|
||||
|
||||
foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
|
||||
{
|
||||
if (kvp.Key != "local")
|
||||
{
|
||||
// For the others, call the user agent service
|
||||
List<string> ids = new List<string>();
|
||||
foreach (FriendInfo f in kvp.Value)
|
||||
ids.Add(f.Friend);
|
||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
|
||||
uConn.StatusNotification(ids, userID, online);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
|
||||
{
|
||||
first = "Unknown"; last = "User";
|
||||
|
@ -172,7 +331,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
|||
{
|
||||
string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
||||
|
||||
m_log.DebugFormat("[XXX] GetFriendsFromService to {0}", agentUUI);
|
||||
finfos = FriendsService.GetFriends(agentUUI);
|
||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
|||
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
|
||||
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
|
||||
|
||||
new UserAgentServerConnector(m_Config, MainServer.Instance);
|
||||
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
|
||||
new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
|
||||
new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
|
||||
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
|
||||
}
|
||||
|
|
|
@ -140,16 +140,20 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
|||
|
||||
byte[] NewFriendship(Dictionary<string, object> request)
|
||||
{
|
||||
m_log.DebugFormat("[XXX] 1");
|
||||
if (!VerifyServiceKey(request))
|
||||
return FailureResult();
|
||||
|
||||
m_log.DebugFormat("[XXX] 2");
|
||||
// OK, can proceed
|
||||
FriendInfo friend = new FriendInfo(request);
|
||||
UUID friendID;
|
||||
string tmp = string.Empty;
|
||||
m_log.DebugFormat("[XXX] 3");
|
||||
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
|
||||
return FailureResult();
|
||||
|
||||
|
||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
||||
|
||||
// If the friendship already exists, return fail
|
||||
|
|
|
@ -54,13 +54,19 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
|||
private IUserAgentService m_HomeUsersService;
|
||||
|
||||
public UserAgentServerConnector(IConfigSource config, IHttpServer server) :
|
||||
this(config, server, null)
|
||||
{
|
||||
}
|
||||
|
||||
public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) :
|
||||
base(config, server, String.Empty)
|
||||
{
|
||||
IConfig gridConfig = config.Configs["UserAgentService"];
|
||||
if (gridConfig != null)
|
||||
{
|
||||
string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
|
||||
Object[] args = new Object[] { config };
|
||||
|
||||
Object[] args = new Object[] { config, friendsConnector };
|
||||
m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args);
|
||||
}
|
||||
if (m_HomeUsersService == null)
|
||||
|
@ -75,6 +81,9 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
|||
server.AddXmlRPCHandler("verify_client", VerifyClient, false);
|
||||
server.AddXmlRPCHandler("logout_agent", LogoutAgent, false);
|
||||
|
||||
server.AddXmlRPCHandler("status_notification", StatusNotification, false);
|
||||
server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false);
|
||||
|
||||
server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler);
|
||||
}
|
||||
|
||||
|
@ -194,5 +203,78 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
|||
|
||||
}
|
||||
|
||||
public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
hash["result"] = "false";
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID") && requestData.ContainsKey("online"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
List<string> ids = new List<string>();
|
||||
foreach (object key in requestData.Keys)
|
||||
{
|
||||
if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
|
||||
ids.Add(requestData[key].ToString());
|
||||
}
|
||||
bool online = false;
|
||||
bool.TryParse(requestData["online"].ToString(), out online);
|
||||
|
||||
hash["result"] = "true";
|
||||
|
||||
// let's spawn a thread for this, because it may take a long time...
|
||||
Util.FireAndForget(delegate { m_HomeUsersService.StatusNotification(ids, userID, online); });
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
|
||||
Hashtable requestData = (Hashtable)request.Params[0];
|
||||
//string host = (string)requestData["host"];
|
||||
//string portstr = (string)requestData["port"];
|
||||
if (requestData.ContainsKey("userID"))
|
||||
{
|
||||
string userID_str = (string)requestData["userID"];
|
||||
UUID userID = UUID.Zero;
|
||||
UUID.TryParse(userID_str, out userID);
|
||||
List<string> ids = new List<string>();
|
||||
foreach (object key in requestData.Keys)
|
||||
{
|
||||
if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
|
||||
ids.Add(requestData[key].ToString());
|
||||
}
|
||||
|
||||
// let's spawn a thread for this, because it may take a long time...
|
||||
List<UUID> online = m_HomeUsersService.GetOnlineFriends(userID, ids);
|
||||
if (online.Count > 0)
|
||||
{
|
||||
int i = 0;
|
||||
foreach (UUID id in online)
|
||||
{
|
||||
hash["friend_" + i.ToString()] = id.ToString();
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
XmlRpcResponse response = new XmlRpcResponse();
|
||||
response.Value = hash;
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -404,6 +404,97 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
|||
GetBoolResponse(request, out reason);
|
||||
}
|
||||
|
||||
public void StatusNotification(List<string> friends, UUID userID, bool online)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
hash["userID"] = userID.ToString();
|
||||
hash["online"] = online.ToString();
|
||||
int i = 0;
|
||||
foreach (string s in friends)
|
||||
{
|
||||
hash["friend_" + i.ToString()] = s;
|
||||
i++;
|
||||
}
|
||||
|
||||
IList paramList = new ArrayList();
|
||||
paramList.Add(hash);
|
||||
|
||||
XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
|
||||
string reason = string.Empty;
|
||||
GetBoolResponse(request, out reason);
|
||||
|
||||
}
|
||||
|
||||
public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
|
||||
{
|
||||
Hashtable hash = new Hashtable();
|
||||
hash["userID"] = userID.ToString();
|
||||
int i = 0;
|
||||
foreach (string s in friends)
|
||||
{
|
||||
hash["friend_" + i.ToString()] = s;
|
||||
i++;
|
||||
}
|
||||
|
||||
IList paramList = new ArrayList();
|
||||
paramList.Add(hash);
|
||||
|
||||
XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
|
||||
string reason = string.Empty;
|
||||
|
||||
// Send and get reply
|
||||
List<UUID> online = new List<UUID>();
|
||||
XmlRpcResponse response = null;
|
||||
try
|
||||
{
|
||||
response = request.Send(m_ServerURL, 10000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
|
||||
reason = "Exception: " + e.Message;
|
||||
return online;
|
||||
}
|
||||
|
||||
if (response.IsFault)
|
||||
{
|
||||
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
|
||||
reason = "XMLRPC Fault";
|
||||
return online;
|
||||
}
|
||||
|
||||
hash = (Hashtable)response.Value;
|
||||
//foreach (Object o in hash)
|
||||
// m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
|
||||
try
|
||||
{
|
||||
if (hash == null)
|
||||
{
|
||||
m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
|
||||
reason = "Internal error 1";
|
||||
return online;
|
||||
}
|
||||
|
||||
// Here is the actual response
|
||||
foreach (object key in hash.Keys)
|
||||
{
|
||||
if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
|
||||
{
|
||||
UUID uuid;
|
||||
if (UUID.TryParse(hash[key].ToString(), out uuid))
|
||||
online.Add(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
|
||||
reason = "Exception: " + e.Message;
|
||||
}
|
||||
|
||||
return online;
|
||||
}
|
||||
|
||||
private bool GetBoolResponse(XmlRpcRequest request, out string reason)
|
||||
{
|
||||
|
|
|
@ -31,10 +31,12 @@ using System.Net;
|
|||
using System.Reflection;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Services.Connectors.Friends;
|
||||
using OpenSim.Services.Connectors.Hypergrid;
|
||||
using OpenSim.Services.Interfaces;
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
using OpenSim.Server.Base;
|
||||
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
|
||||
|
||||
using OpenMetaverse;
|
||||
using log4net;
|
||||
|
@ -63,19 +65,34 @@ namespace OpenSim.Services.HypergridService
|
|||
protected static IGridService m_GridService;
|
||||
protected static GatekeeperServiceConnector m_GatekeeperConnector;
|
||||
protected static IGatekeeperService m_GatekeeperService;
|
||||
protected static IFriendsService m_FriendsService;
|
||||
protected static IPresenceService m_PresenceService;
|
||||
protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
|
||||
protected static FriendsSimConnector m_FriendsSimConnector; // grid
|
||||
|
||||
protected static string m_GridName;
|
||||
|
||||
protected static bool m_BypassClientVerification;
|
||||
|
||||
public UserAgentService(IConfigSource config)
|
||||
public UserAgentService(IConfigSource config) : this(config, null)
|
||||
{
|
||||
}
|
||||
|
||||
public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
|
||||
{
|
||||
// Let's set this always, because we don't know the sequence
|
||||
// of instantiations
|
||||
if (friendsConnector != null)
|
||||
m_FriendsLocalSimConnector = friendsConnector;
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
m_Initialized = true;
|
||||
|
||||
m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
|
||||
|
||||
|
||||
m_FriendsSimConnector = new FriendsSimConnector();
|
||||
|
||||
IConfig serverConfig = config.Configs["UserAgentService"];
|
||||
if (serverConfig == null)
|
||||
throw new Exception(String.Format("No section UserAgentService in config file"));
|
||||
|
@ -83,6 +100,8 @@ namespace OpenSim.Services.HypergridService
|
|||
string gridService = serverConfig.GetString("GridService", String.Empty);
|
||||
string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
|
||||
string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty);
|
||||
string friendsService = serverConfig.GetString("FriendsService", String.Empty);
|
||||
string presenceService = serverConfig.GetString("PresenceService", String.Empty);
|
||||
|
||||
m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false);
|
||||
|
||||
|
@ -94,6 +113,8 @@ namespace OpenSim.Services.HypergridService
|
|||
m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
|
||||
m_GatekeeperConnector = new GatekeeperServiceConnector();
|
||||
m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
|
||||
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
|
||||
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
|
||||
|
||||
m_GridName = serverConfig.GetString("ExternalName", string.Empty);
|
||||
if (m_GridName == string.Empty)
|
||||
|
@ -156,11 +177,16 @@ namespace OpenSim.Services.HypergridService
|
|||
string gridName = gatekeeper.ServerURI;
|
||||
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
|
||||
|
||||
|
||||
if (m_GridName == gridName)
|
||||
success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
|
||||
else
|
||||
{
|
||||
success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason);
|
||||
if (success)
|
||||
// Report them as nowhere
|
||||
m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
|
@ -179,6 +205,7 @@ namespace OpenSim.Services.HypergridService
|
|||
if (clientIP != null)
|
||||
m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
|
||||
m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -291,6 +318,145 @@ namespace OpenSim.Services.HypergridService
|
|||
return false;
|
||||
}
|
||||
|
||||
public void StatusNotification(List<string> friends, UUID foreignUserID, bool online)
|
||||
{
|
||||
if (m_FriendsService == null || m_PresenceService == null)
|
||||
{
|
||||
m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing");
|
||||
return;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count);
|
||||
|
||||
// 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("[USER AGENT 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, friendSession.UserID, foreignUserID, online);
|
||||
usersToBeNotified.Remove(friendSession.UserID.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly, let's notify the rest who may be online somewhere else
|
||||
foreach (string user in usersToBeNotified)
|
||||
{
|
||||
UUID id = new UUID(user);
|
||||
if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
|
||||
{
|
||||
string url = m_TravelingAgents[id].GridExternalName;
|
||||
// forward
|
||||
m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void ForwardStatusNotificationToSim(UUID regionID, string user, UUID foreignUserID, bool online)
|
||||
{
|
||||
UUID userID;
|
||||
if (UUID.TryParse(user, out userID))
|
||||
{
|
||||
if (m_FriendsLocalSimConnector != null)
|
||||
{
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
|
||||
m_FriendsLocalSimConnector.StatusNotify(userID, foreignUserID, online);
|
||||
}
|
||||
else
|
||||
{
|
||||
GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
|
||||
if (region != null)
|
||||
{
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, user, foreignUserID, (online ? "online" : "offline"));
|
||||
m_FriendsSimConnector.StatusNotify(region, userID, foreignUserID, online);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<UUID> GetOnlineFriends(UUID foreignUserID, List<string> friends)
|
||||
{
|
||||
List<UUID> online = new List<UUID>();
|
||||
|
||||
if (m_FriendsService == null || m_PresenceService == null)
|
||||
{
|
||||
m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing");
|
||||
return online;
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count);
|
||||
|
||||
// First, let's double check that the reported friends are, indeed, friends of that user
|
||||
// And let's check that the secret matches and the rights
|
||||
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) &&
|
||||
(finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1))
|
||||
{
|
||||
// great!
|
||||
usersToBeNotified.Add(localUserID.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now, let's find out their status
|
||||
m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", 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)
|
||||
{
|
||||
foreach (PresenceInfo pi in friendSessions)
|
||||
{
|
||||
UUID presenceID;
|
||||
if (UUID.TryParse(pi.UserID, out presenceID))
|
||||
online.Add(presenceID);
|
||||
}
|
||||
}
|
||||
|
||||
return online;
|
||||
}
|
||||
}
|
||||
|
||||
class TravelingAgentInfo
|
||||
|
|
|
@ -55,6 +55,9 @@ namespace OpenSim.Services.Interfaces
|
|||
void LogoutAgent(UUID userID, UUID sessionID);
|
||||
GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
|
||||
|
||||
void StatusNotification(List<string> friends, UUID userID, bool online);
|
||||
List<UUID> GetOnlineFriends(UUID userID, List<string> friends);
|
||||
|
||||
bool AgentIsComingHome(UUID sessionID, string thisGridExternalName);
|
||||
bool VerifyAgent(UUID sessionID, string token);
|
||||
bool VerifyClient(UUID sessionID, string reportedIP);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the OpenSimulator Project nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenSim.Framework;
|
||||
using OpenMetaverse;
|
||||
|
||||
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||
|
||||
namespace OpenSim.Services.Interfaces
|
||||
{
|
||||
public interface IFriendsSimConnector
|
||||
{
|
||||
bool StatusNotify(UUID userID, UUID friendID, bool online);
|
||||
}
|
||||
}
|
|
@ -126,6 +126,9 @@
|
|||
GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
|
||||
GridService = "OpenSim.Services.GridService.dll:GridService"
|
||||
GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService"
|
||||
PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
|
||||
FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
|
||||
|
||||
|
||||
|
||||
;; The interface that local users get when they are in other grids
|
||||
|
|
Loading…
Reference in New Issue