HG Friends: allow the establishment of HG friendships without requiring co-presence in the same sim. Using avatar picker, users can now search for names such as "first.last@grid.com:9000", find them, and request friendship. Friendship requests are stored if target user is offline. TESTED ON STANDALONE ONLY.
parent
d1256536b5
commit
d08ad6459a
File diff suppressed because it is too large
Load Diff
|
@ -550,7 +550,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
UUID principalID = new UUID(im.fromAgentID);
|
UUID principalID = new UUID(im.fromAgentID);
|
||||||
UUID friendID = new UUID(im.toAgentID);
|
UUID friendID = new UUID(im.toAgentID);
|
||||||
|
|
||||||
m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2}", principalID, im.fromAgentName, friendID);
|
m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2} ({3})", principalID, client.FirstName + client.LastName, friendID, im.fromAgentName);
|
||||||
|
|
||||||
|
// Check that the friendship doesn't exist yet
|
||||||
|
FriendInfo[] finfos = GetFriends(principalID);
|
||||||
|
if (finfos != null)
|
||||||
|
{
|
||||||
|
FriendInfo f = GetFriend(finfos, friendID);
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
client.SendAgentAlertMessage("This person is already your friend. Please delete it first if you want to reestablish the friendship.", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This user wants to be friends with the other user.
|
// This user wants to be friends with the other user.
|
||||||
// Let's add the relation backwards, in case the other is not online
|
// Let's add the relation backwards, in case the other is not online
|
||||||
|
@ -561,7 +573,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
|
protected virtual bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
|
||||||
{
|
{
|
||||||
// !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
|
// !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
|
||||||
// We stick this agent's ID as imSession, so that it's directly available on the receiving end
|
// We stick this agent's ID as imSession, so that it's directly available on the receiving end
|
||||||
|
@ -570,7 +582,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
|
|
||||||
// Try the local sim
|
// Try the local sim
|
||||||
if (LocalFriendshipOffered(friendID, im))
|
if (LocalFriendshipOffered(friendID, im))
|
||||||
return;
|
{
|
||||||
|
m_log.DebugFormat("[XXX]: LocalFriendshipOffered successes");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// The prospective friend is not here [as root]. Let's forward.
|
// The prospective friend is not here [as root]. Let's forward.
|
||||||
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
|
PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
|
||||||
|
@ -581,9 +596,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
{
|
{
|
||||||
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
|
||||||
m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message);
|
m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the prospective friend is not online, he'll get the message upon login.
|
// If the prospective friend is not online, he'll get the message upon login.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string GetFriendshipRequesterName(UUID agentID)
|
protected virtual string GetFriendshipRequesterName(UUID agentID)
|
||||||
|
@ -592,7 +609,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
|
return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
protected virtual void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
|
m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID);
|
||||||
|
|
||||||
|
@ -603,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
{
|
{
|
||||||
StoreFriendships(client.AgentId, friendID);
|
StoreFriendships(client.AgentId, friendID);
|
||||||
|
|
||||||
// Update the local cache
|
// Update the local cache.
|
||||||
RecacheFriends(client);
|
RecacheFriends(client);
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -756,7 +773,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
|
|
||||||
#region Local
|
#region Local
|
||||||
|
|
||||||
public bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
|
public virtual bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
|
||||||
{
|
{
|
||||||
IClientAPI friendClient = LocateClientObject(toID);
|
IClientAPI friendClient = LocateClientObject(toID);
|
||||||
if (friendClient != null)
|
if (friendClient != null)
|
||||||
|
@ -912,7 +929,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
return FriendsService.GetFriends(client.AgentId);
|
return FriendsService.GetFriends(client.AgentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecacheFriends(IClientAPI client)
|
protected void RecacheFriends(IClientAPI client)
|
||||||
{
|
{
|
||||||
// FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event
|
// FIXME: Ideally, we want to avoid doing this here since it sits the EventManager.OnMakeRootAgent event
|
||||||
// is on the critical path for transferring an avatar from one region to another.
|
// is on the critical path for transferring an avatar from one region to another.
|
||||||
|
|
|
@ -61,6 +61,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected HGFriendsServicesConnector m_HGFriendsConnector = new HGFriendsServicesConnector();
|
||||||
|
|
||||||
#region ISharedRegionModule
|
#region ISharedRegionModule
|
||||||
public override string Name
|
public override string Name
|
||||||
{
|
{
|
||||||
|
@ -94,6 +96,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
protected override void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
|
||||||
|
{
|
||||||
|
// Update the local cache. Yes, we need to do it right here
|
||||||
|
// because the HGFriendsService placed something on the DB
|
||||||
|
// from under the sim
|
||||||
|
base.OnApproveFriendRequest(client, agentID, friendID, callingCardFolders);
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool CacheFriends(IClientAPI client)
|
protected override bool CacheFriends(IClientAPI client)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entered CacheFriends for {0}", client.Name);
|
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entered CacheFriends for {0}", client.Name);
|
||||||
|
@ -183,91 +193,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetOnlineFriends for {0}", userID);
|
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetOnlineFriends for {0}", userID);
|
||||||
}
|
}
|
||||||
|
|
||||||
//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)
|
protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
|
// m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
|
||||||
|
@ -335,12 +260,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// fid is not a UUID...
|
// fid is not a UUID...
|
||||||
string url = string.Empty, tmp = string.Empty;
|
string url = string.Empty, tmp = string.Empty, f = string.Empty, l = string.Empty;
|
||||||
if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
|
m_log.DebugFormat("[YYY]: FID {0}", fid);
|
||||||
|
if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out f, out l, out tmp))
|
||||||
{
|
{
|
||||||
IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
|
m_log.DebugFormat("[YYY]: Adding user {0} {1} {2}", f, l, url);
|
||||||
userMan.AddUser(agentID, first, last, url);
|
m_uMan.AddUser(agentID, f, l, url);
|
||||||
|
|
||||||
|
string name = m_uMan.GetUserName(agentID);
|
||||||
|
string[] parts = name.Trim().Split(new char[] {' '});
|
||||||
|
if (parts.Length == 2)
|
||||||
|
{
|
||||||
|
first = parts[0];
|
||||||
|
last = parts[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first = f;
|
||||||
|
last = l;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -348,13 +286,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
|
|
||||||
protected override string GetFriendshipRequesterName(UUID agentID)
|
protected override string GetFriendshipRequesterName(UUID agentID)
|
||||||
{
|
{
|
||||||
// For the time being we assume that HG friendship requests can only happen
|
return m_uMan.GetUserName(agentID);
|
||||||
// when avies are on the same region.
|
|
||||||
IClientAPI client = LocateClientObject(agentID);
|
|
||||||
if (client != null)
|
|
||||||
return client.FirstName + " " + client.LastName;
|
|
||||||
else
|
|
||||||
return base.GetFriendshipRequesterName(agentID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string FriendshipMessage(string friendID)
|
protected override string FriendshipMessage(string friendID)
|
||||||
|
@ -392,10 +324,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
|
AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
|
||||||
if (agentClientCircuit != null)
|
if (agentClientCircuit != null)
|
||||||
{
|
{
|
||||||
string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
//[XXX] string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
||||||
|
|
||||||
finfos = FriendsService.GetFriends(agentUUI);
|
finfos = FriendsService.GetFriends(client.AgentId.ToString());
|
||||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, client.AgentId.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
|
// m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting GetFriendsFromService for {0}", client.Name);
|
||||||
|
@ -454,16 +386,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
|
friendIsLocal = UserManagementModule.IsLocalGridUser(friendID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are they both local users?
|
// Is the requester a local user?
|
||||||
if (agentIsLocal && friendIsLocal)
|
if (agentIsLocal)
|
||||||
{
|
{
|
||||||
// local grid users
|
// local grid users
|
||||||
m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Friendship requester is local. Storing backwards.");
|
||||||
|
|
||||||
base.StoreBackwards(friendID, agentID);
|
base.StoreBackwards(friendID, agentID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// no provision for this temporary friendship state
|
// no provision for this temporary friendship state when user is not local
|
||||||
//FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
|
//FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,12 +434,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
|
agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
|
||||||
agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
|
||||||
agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
||||||
|
RecacheFriends(agentClient);
|
||||||
}
|
}
|
||||||
if (friendClient != null)
|
if (friendClient != null)
|
||||||
{
|
{
|
||||||
friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
|
friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
|
||||||
friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
|
friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
|
||||||
friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
|
||||||
|
RecacheFriends(friendClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
|
m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
|
||||||
|
@ -515,14 +450,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
// Generate a random 8-character hex number that will sign this friendship
|
// Generate a random 8-character hex number that will sign this friendship
|
||||||
string secret = UUID.Random().ToString().Substring(0, 8);
|
string secret = UUID.Random().ToString().Substring(0, 8);
|
||||||
|
|
||||||
|
string theFriendUUID = friendUUI + ";" + secret;
|
||||||
|
string agentUUID = agentUUI + ";" + secret;
|
||||||
|
|
||||||
if (agentIsLocal) // agent is local, 'friend' is foreigner
|
if (agentIsLocal) // agent is local, 'friend' is foreigner
|
||||||
{
|
{
|
||||||
// This may happen when the agent returned home, in which case the friend is not there
|
// This may happen when the agent returned home, in which case the friend is not there
|
||||||
// We need to look for its information in the friends list itself
|
// We need to look for its information in the friends list itself
|
||||||
|
FriendInfo[] finfos = null;
|
||||||
bool confirming = false;
|
bool confirming = false;
|
||||||
if (friendUUI == string.Empty)
|
if (friendUUI == string.Empty)
|
||||||
{
|
{
|
||||||
FriendInfo[] finfos = GetFriends(agentID);
|
finfos = GetFriends(agentID);
|
||||||
foreach (FriendInfo finfo in finfos)
|
foreach (FriendInfo finfo in finfos)
|
||||||
{
|
{
|
||||||
if (finfo.TheirFlags == -1)
|
if (finfo.TheirFlags == -1)
|
||||||
|
@ -530,29 +469,57 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||||
{
|
{
|
||||||
friendUUI = finfo.Friend;
|
friendUUI = finfo.Friend;
|
||||||
|
theFriendUUID = friendUUI;
|
||||||
|
UUID utmp = UUID.Zero; String url = String.Empty; String first = String.Empty, last = String.Empty, tmp = String.Empty;
|
||||||
|
// If it's confirming the friendship, we already have the full UUI with the secret
|
||||||
|
if (Util.ParseUniversalUserIdentifier(theFriendUUID, out utmp, out url, out first, out last, out secret))
|
||||||
|
{
|
||||||
|
agentUUID = agentUUI + ";" + secret;
|
||||||
|
m_uMan.AddUser(utmp, first, last, url);
|
||||||
|
}
|
||||||
confirming = true;
|
confirming = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!confirming)
|
||||||
|
{
|
||||||
|
friendUUI = m_uMan.GetUserUUI(friendID);
|
||||||
|
theFriendUUID = friendUUI + ";" + secret;
|
||||||
|
}
|
||||||
|
|
||||||
// If it's confirming the friendship, we already have the full friendUUI with the secret
|
friendFriendService = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
|
||||||
string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
|
|
||||||
|
// m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
|
||||||
|
// agentUUI, friendUUI, agentFriendService, friendFriendService);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete any previous friendship relations
|
||||||
|
DeletePreviousRelations(agentID, friendID);
|
||||||
|
|
||||||
// store in the local friends service a reference to the foreign friend
|
// store in the local friends service a reference to the foreign friend
|
||||||
FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
|
FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
|
||||||
// and also the converse
|
// and also the converse
|
||||||
FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
|
FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
|
||||||
|
|
||||||
if (!confirming && friendClientCircuit != null)
|
//if (!confirming)
|
||||||
{
|
//{
|
||||||
// store in the foreign friends service a reference to the local agent
|
// store in the foreign friends service a reference to the local agent
|
||||||
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
|
HGFriendsServicesConnector friendsConn = null;
|
||||||
friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
|
if (friendClientCircuit != null) // the friend is here, validate session
|
||||||
}
|
friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
|
||||||
|
else // the friend is not here, he initiated the request in his home world
|
||||||
|
friendsConn = new HGFriendsServicesConnector(friendFriendService);
|
||||||
|
|
||||||
|
friendsConn.NewFriendship(friendID, agentUUID);
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
else if (friendIsLocal) // 'friend' is local, agent is foreigner
|
else if (friendIsLocal) // 'friend' is local, agent is foreigner
|
||||||
{
|
{
|
||||||
|
// Delete any previous friendship relations
|
||||||
|
DeletePreviousRelations(agentID, friendID);
|
||||||
|
|
||||||
// store in the local friends service a reference to the foreign agent
|
// store in the local friends service a reference to the foreign agent
|
||||||
FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
|
FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
|
||||||
// and also the converse
|
// and also the converse
|
||||||
|
@ -582,6 +549,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
// my brain hurts now
|
// my brain hurts now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DeletePreviousRelations(UUID a1, UUID a2)
|
||||||
|
{
|
||||||
|
// Delete any previous friendship relations
|
||||||
|
FriendInfo[] finfos = null;
|
||||||
|
FriendInfo f = null;
|
||||||
|
finfos = GetFriends(a1);
|
||||||
|
if (finfos != null)
|
||||||
|
{
|
||||||
|
f = GetFriend(finfos, a2);
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
FriendsService.Delete(a1, f.Friend);
|
||||||
|
// and also the converse
|
||||||
|
FriendsService.Delete(f.Friend, a1.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finfos = GetFriends(a2);
|
||||||
|
if (finfos != null)
|
||||||
|
{
|
||||||
|
f = GetFriend(finfos, a1);
|
||||||
|
if (f != null)
|
||||||
|
{
|
||||||
|
FriendsService.Delete(a2, f.Friend);
|
||||||
|
// and also the converse
|
||||||
|
FriendsService.Delete(f.Friend, a2.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
|
protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
|
||||||
{
|
{
|
||||||
Boolean agentIsLocal = true;
|
Boolean agentIsLocal = true;
|
||||||
|
@ -684,5 +681,74 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||||
friendConn.DeleteFriendship(foreignUser, localUser, secret);
|
friendConn.DeleteFriendship(foreignUser, localUser, secret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (base.ForwardFriendshipOffer(agentID, friendID, im))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// OK, that didn't work, so let's try to find this user somewhere
|
||||||
|
if (!m_uMan.IsLocalGridUser(friendID))
|
||||||
|
{
|
||||||
|
string friendsURL = m_uMan.GetUserServerURL(friendID, "FriendsServerURI");
|
||||||
|
if (friendsURL != string.Empty)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Forwading friendship from {0} to {1} @ {2}", agentID, friendID, friendsURL);
|
||||||
|
GridRegion region = new GridRegion();
|
||||||
|
region.ServerURI = friendsURL;
|
||||||
|
|
||||||
|
string name = im.fromAgentName;
|
||||||
|
if (m_uMan.IsLocalGridUser(agentID))
|
||||||
|
{
|
||||||
|
IClientAPI agentClient = LocateClientObject(agentID);
|
||||||
|
AgentCircuitData agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
|
||||||
|
string agentHomeService = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
agentHomeService = agentClientCircuit.ServiceURLs["HomeURI"].ToString();
|
||||||
|
string lastname = "@" + new Uri(agentHomeService).Authority;
|
||||||
|
string firstname = im.fromAgentName.Replace(" ", ".");
|
||||||
|
name = firstname + lastname;
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Key HomeURI not found for user {0}", agentID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (NullReferenceException)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Null HomeUri for local user {0}", agentID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[HGFRIENDS MODULE]: Malformed HomeUri {0} for local user {1}", agentHomeService, agentID);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_HGFriendsConnector.FriendshipOffered(region, agentID, friendID, im.message, name);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool LocalFriendshipOffered(UUID toID, GridInstantMessage im)
|
||||||
|
{
|
||||||
|
if (base.LocalFriendshipOffered(toID, im))
|
||||||
|
{
|
||||||
|
if (im.fromAgentName.Contains("@"))
|
||||||
|
{
|
||||||
|
string[] parts = im.fromAgentName.Split(new char[] { '@' });
|
||||||
|
if (parts.Length == 2)
|
||||||
|
m_uMan.AddUser(new UUID(im.fromAgentID), parts[0], "http://" + parts[1]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -71,43 +71,52 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
|
|
||||||
protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users)
|
protected override void AddAdditionalUsers(UUID avatarID, string query, List<UserData> users)
|
||||||
{
|
{
|
||||||
string[] words = query.Split(new char[] { ' ' });
|
if (query.Contains("@")) // First.Last@foo.com, maybe?
|
||||||
|
|
||||||
for (int i = 0; i < words.Length; i++)
|
|
||||||
{
|
{
|
||||||
if (words[i].Length < 3)
|
string[] words = query.Split(new char[] { '@' });
|
||||||
|
if (words.Length != 2)
|
||||||
{
|
{
|
||||||
if (i != words.Length - 1)
|
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Malformed address {0}", query);
|
||||||
Array.Copy(words, i + 1, words, i, words.Length - i - 1);
|
return;
|
||||||
Array.Resize(ref words, words.Length - 1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (words.Length == 0 || words.Length > 2)
|
words[0] = words[0].Trim(); // it has at least 1
|
||||||
return;
|
words[1] = words[1].Trim();
|
||||||
|
|
||||||
if (words.Length == 2) // First.Last @foo.com, maybe?
|
if (words[0] == String.Empty) // query was @foo.com?
|
||||||
{
|
{
|
||||||
bool found = false;
|
foreach (UserData d in m_UserCache.Values)
|
||||||
|
{
|
||||||
|
if (d.LastName.ToLower().StartsWith("@" + words[1].ToLower()))
|
||||||
|
users.Add(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're done
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// words.Length == 2 and words[0] != string.empty
|
||||||
|
// first.last@foo.com ?
|
||||||
foreach (UserData d in m_UserCache.Values)
|
foreach (UserData d in m_UserCache.Values)
|
||||||
{
|
{
|
||||||
if (d.LastName.StartsWith("@") &&
|
if (d.LastName.StartsWith("@") &&
|
||||||
d.FirstName.ToLower().Equals(words[0].ToLower()) &&
|
d.FirstName.ToLower().Equals(words[0].ToLower()) &&
|
||||||
d.LastName.ToLower().Equals(words[1].ToLower()))
|
d.LastName.ToLower().Equals("@" + words[1].ToLower()))
|
||||||
{
|
{
|
||||||
users.Add(d);
|
users.Add(d);
|
||||||
found = true;
|
// It's cached. We're done
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && words[1].StartsWith("@") && words[0].Contains(".")) // This is it! Let's ask the other world
|
// This is it! Let's ask the other world
|
||||||
|
if (words[0].Contains("."))
|
||||||
{
|
{
|
||||||
string[] names = words[0].Split(new char[] { '.' });
|
string[] names = words[0].Split(new char[] { '.' });
|
||||||
if (names.Length >= 2)
|
if (names.Length >= 2)
|
||||||
{
|
{
|
||||||
|
|
||||||
string uriStr = "http://" + words[1].Substring(1); // remove the @
|
string uriStr = "http://" + words[1];
|
||||||
// Let's check that the last name is a valid address
|
// Let's check that the last name is a valid address
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -115,6 +124,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
}
|
}
|
||||||
catch (UriFormatException)
|
catch (UriFormatException)
|
||||||
{
|
{
|
||||||
|
m_log.DebugFormat("[USER MANAGEMENT MODULE]: Malformed address {0}", uriStr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,26 +135,26 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
UserData ud = new UserData();
|
UserData ud = new UserData();
|
||||||
ud.Id = userID;
|
ud.Id = userID;
|
||||||
ud.FirstName = words[0];
|
ud.FirstName = words[0];
|
||||||
ud.LastName = words[1];
|
ud.LastName = "@" + words[1];
|
||||||
users.Add(ud);
|
users.Add(ud);
|
||||||
AddUser(userID, ud.FirstName, ud.LastName, uriStr);
|
AddUser(userID, names[0], names[1], uriStr);
|
||||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0} {1} found", words[0], words[1]);
|
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0} {1} not found", words[0], words[1]);
|
m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} not found", words[0], words[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
//else
|
||||||
{
|
//{
|
||||||
foreach (UserData d in m_UserCache.Values)
|
// foreach (UserData d in m_UserCache.Values)
|
||||||
{
|
// {
|
||||||
if (d.LastName.StartsWith("@") &&
|
// if (d.LastName.StartsWith("@") &&
|
||||||
(d.FirstName.ToLower().StartsWith(query.ToLower()) ||
|
// (d.FirstName.ToLower().StartsWith(query.ToLower()) ||
|
||||||
d.LastName.ToLower().StartsWith(query.ToLower())))
|
// d.LastName.ToLower().StartsWith(query.ToLower())))
|
||||||
users.Add(d);
|
// users.Add(d);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,7 +299,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
|
|
||||||
public string GetUserName(UUID uuid)
|
public string GetUserName(UUID uuid)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
|
|
||||||
string[] names = GetUserNames(uuid);
|
string[] names = GetUserNames(uuid);
|
||||||
if (names.Length == 2)
|
if (names.Length == 2)
|
||||||
{
|
{
|
||||||
|
@ -340,9 +339,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
|
|
||||||
if (userdata.HomeURL != null && userdata.HomeURL != string.Empty)
|
if (userdata.HomeURL != null && userdata.HomeURL != string.Empty)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
//m_log.DebugFormat(
|
||||||
"[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
|
// "[USER MANAGEMENT MODULE]: Did not find url type {0} so requesting urls from '{1}' for {2}",
|
||||||
serverType, userdata.HomeURL, userID);
|
// serverType, userdata.HomeURL, userID);
|
||||||
|
|
||||||
UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
|
UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
|
||||||
userdata.ServerURLs = uConn.GetServerURLs(userID);
|
userdata.ServerURLs = uConn.GetServerURLs(userID);
|
||||||
|
@ -401,11 +400,15 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
|
|
||||||
public void AddUser(UUID uuid, string first, string last, string homeURL)
|
public void AddUser(UUID uuid, string first, string last, string homeURL)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
|
||||||
|
|
||||||
AddUser(uuid, homeURL + ";" + first + " " + last);
|
AddUser(uuid, homeURL + ";" + first + " " + last);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddUser (UUID id, string creatorData)
|
public void AddUser (UUID id, string creatorData)
|
||||||
{
|
{
|
||||||
|
//m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
|
||||||
|
|
||||||
UserData oldUser;
|
UserData oldUser;
|
||||||
//lock the whole block - prevent concurrent update
|
//lock the whole block - prevent concurrent update
|
||||||
lock (m_UserCache)
|
lock (m_UserCache)
|
||||||
|
@ -431,9 +434,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
|
|
||||||
|
|
||||||
UserAccount account = m_Scenes [0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id);
|
UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id);
|
||||||
|
|
||||||
if (account != null)
|
if (account != null)
|
||||||
{
|
{
|
||||||
|
@ -482,9 +484,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
|
||||||
lock (m_UserCache)
|
lock (m_UserCache)
|
||||||
m_UserCache[user.Id] = user;
|
m_UserCache[user.Id] = user;
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
//m_log.DebugFormat(
|
||||||
// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
|
// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
|
||||||
// user.Id, user.FirstName, user.LastName, user.HomeURL);
|
// user.Id, user.FirstName, user.LastName, user.HomeURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLocalGridUser(UUID uuid)
|
public bool IsLocalGridUser(UUID uuid)
|
||||||
|
|
|
@ -48,8 +48,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||||
private static bool m_Enabled = false;
|
private static bool m_Enabled = false;
|
||||||
|
|
||||||
private IConfigSource m_Config;
|
private IConfigSource m_Config;
|
||||||
bool m_Registered = false;
|
private bool m_Registered = false;
|
||||||
GatekeeperServiceInConnector m_HypergridHandler;
|
private string m_LocalServiceDll = String.Empty;
|
||||||
|
private GatekeeperServiceInConnector m_HypergridHandler;
|
||||||
|
private UserAgentServerConnector m_UASHandler;
|
||||||
|
|
||||||
#region IRegionModule interface
|
#region IRegionModule interface
|
||||||
|
|
||||||
|
@ -63,6 +65,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||||
if (m_Enabled)
|
if (m_Enabled)
|
||||||
{
|
{
|
||||||
m_log.Info("[HGGRID IN CONNECTOR]: Hypergrid Service In Connector enabled");
|
m_log.Info("[HGGRID IN CONNECTOR]: Hypergrid Service In Connector enabled");
|
||||||
|
IConfig fconfig = config.Configs["FriendsService"];
|
||||||
|
if (fconfig != null)
|
||||||
|
{
|
||||||
|
m_LocalServiceDll = fconfig.GetString("LocalServiceModule", m_LocalServiceDll);
|
||||||
|
if (m_LocalServiceDll == String.Empty)
|
||||||
|
m_log.WarnFormat("[HGGRID IN CONNECTOR]: Friends LocalServiceModule config missing");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,7 +100,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||||
{
|
{
|
||||||
if (!m_Enabled)
|
if (!m_Enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene scene)
|
public void RemoveRegion(Scene scene)
|
||||||
|
@ -112,14 +120,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
|
||||||
m_log.Info("[HypergridService]: Starting...");
|
m_log.Info("[HypergridService]: Starting...");
|
||||||
|
|
||||||
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
|
ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
|
||||||
|
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
|
||||||
|
Object[] args = new Object[] { m_Config };
|
||||||
|
IFriendsService friendsService = ServerUtils.LoadPlugin<IFriendsService>(m_LocalServiceDll, args);
|
||||||
|
|
||||||
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
|
m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
|
||||||
|
|
||||||
IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
|
m_UASHandler = new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
|
||||||
new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
|
|
||||||
new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
|
new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
|
||||||
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
|
|
||||||
|
new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService", friendsConn);
|
||||||
}
|
}
|
||||||
scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
|
scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
|
||||||
|
scene.RegisterModuleInterface<IUserAgentService>(m_UASHandler.HomeUsersService);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -36,36 +36,42 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
{
|
{
|
||||||
public class HGFriendsServerConnector : ServiceConnector
|
public class HGFriendsServerConnector : ServiceConnector
|
||||||
{
|
{
|
||||||
private IFriendsService m_FriendsService;
|
|
||||||
private IUserAgentService m_UserAgentService;
|
private IUserAgentService m_UserAgentService;
|
||||||
|
private IHGFriendsService m_TheService;
|
||||||
private string m_ConfigName = "HGFriendsService";
|
private string m_ConfigName = "HGFriendsService";
|
||||||
|
|
||||||
|
// Called from Robust
|
||||||
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) :
|
||||||
base(config, server, configName)
|
this(config, server, configName, null)
|
||||||
{
|
{
|
||||||
if (configName != string.Empty)
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from standalone configurations
|
||||||
|
public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName, IFriendsSimConnector localConn)
|
||||||
|
: base(config, server, configName)
|
||||||
|
{
|
||||||
|
if (configName != string.Empty)
|
||||||
m_ConfigName = configName;
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config, m_ConfigName, localConn };
|
||||||
|
|
||||||
IConfig serverConfig = config.Configs[m_ConfigName];
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
if (serverConfig == null)
|
if (serverConfig == null)
|
||||||
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||||
|
|
||||||
string theService = serverConfig.GetString("LocalServiceModule",
|
string theService = serverConfig.GetString("LocalServiceModule",
|
||||||
String.Empty);
|
String.Empty);
|
||||||
|
|
||||||
if (theService == String.Empty)
|
if (theService == String.Empty)
|
||||||
throw new Exception("No LocalServiceModule in config file");
|
throw new Exception("No LocalServiceModule in config file");
|
||||||
|
m_TheService = ServerUtils.LoadPlugin<IHGFriendsService>(theService, args);
|
||||||
Object[] args = new Object[] { config };
|
|
||||||
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
|
|
||||||
|
|
||||||
theService = serverConfig.GetString("UserAgentService", string.Empty);
|
theService = serverConfig.GetString("UserAgentService", string.Empty);
|
||||||
if (theService == String.Empty)
|
if (theService == String.Empty)
|
||||||
throw new Exception("No UserAgentService in " + m_ConfigName);
|
throw new Exception("No UserAgentService in " + m_ConfigName);
|
||||||
|
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, new Object[] { config, localConn });
|
||||||
|
|
||||||
m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, args);
|
server.AddStreamHandler(new HGFriendsServerPostHandler(m_TheService, m_UserAgentService, localConn));
|
||||||
|
|
||||||
server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ using System.Collections.Generic;
|
||||||
using OpenSim.Server.Base;
|
using OpenSim.Server.Base;
|
||||||
using OpenSim.Services.Interfaces;
|
using OpenSim.Services.Interfaces;
|
||||||
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
|
using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
|
||||||
|
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Servers.HttpServer;
|
using OpenSim.Framework.Servers.HttpServer;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
@ -49,15 +50,22 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private IFriendsService m_FriendsService;
|
|
||||||
private IUserAgentService m_UserAgentService;
|
private IUserAgentService m_UserAgentService;
|
||||||
|
private IFriendsSimConnector m_FriendsLocalSimConnector;
|
||||||
|
private IHGFriendsService m_TheService;
|
||||||
|
|
||||||
public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) :
|
public HGFriendsServerPostHandler(IHGFriendsService service, IUserAgentService uas, IFriendsSimConnector friendsConn) :
|
||||||
base("POST", "/hgfriends")
|
base("POST", "/hgfriends")
|
||||||
{
|
{
|
||||||
m_FriendsService = service;
|
m_TheService = service;
|
||||||
m_UserAgentService = uservice;
|
m_UserAgentService = uas;
|
||||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On");
|
m_FriendsLocalSimConnector = friendsConn;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On ({0})",
|
||||||
|
(m_FriendsLocalSimConnector == null ? "robust" : "standalone"));
|
||||||
|
|
||||||
|
if (m_TheService == null)
|
||||||
|
m_log.ErrorFormat("[HGFRIENDS HANDLER]: TheService is null!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] Handle(string path, Stream requestData,
|
public override byte[] Handle(string path, Stream requestData,
|
||||||
|
@ -90,6 +98,26 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
|
|
||||||
case "deletefriendship":
|
case "deletefriendship":
|
||||||
return DeleteFriendship(request);
|
return DeleteFriendship(request);
|
||||||
|
|
||||||
|
/* Same as inter-sim */
|
||||||
|
case "friendship_offered":
|
||||||
|
return FriendshipOffered(request);
|
||||||
|
|
||||||
|
case "validate_friendship_offered":
|
||||||
|
return ValidateFriendshipOffered(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);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
|
m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
|
||||||
}
|
}
|
||||||
|
@ -126,39 +154,20 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
return FailureResult();
|
return FailureResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID);
|
int perms = m_TheService.GetFriendPerms(principalID, friendID);
|
||||||
foreach (FriendInfo finfo in friendsInfo)
|
if (perms < 0)
|
||||||
{
|
return FailureResult("Friend not found");
|
||||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
|
||||||
return SuccessResult(finfo.TheirFlags.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return FailureResult("Friend not found");
|
return SuccessResult(perms.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] NewFriendship(Dictionary<string, object> request)
|
byte[] NewFriendship(Dictionary<string, object> request)
|
||||||
{
|
{
|
||||||
if (!VerifyServiceKey(request))
|
bool verified = VerifyServiceKey(request);
|
||||||
return FailureResult();
|
|
||||||
|
|
||||||
// OK, can proceed
|
|
||||||
FriendInfo friend = new FriendInfo(request);
|
FriendInfo friend = new FriendInfo(request);
|
||||||
UUID friendID;
|
|
||||||
string tmp = string.Empty;
|
|
||||||
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
|
|
||||||
return FailureResult();
|
|
||||||
|
|
||||||
|
bool success = m_TheService.NewFriendship(friend, verified);
|
||||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
|
||||||
|
|
||||||
// If the friendship already exists, return fail
|
|
||||||
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
|
||||||
foreach (FriendInfo finfo in finfos)
|
|
||||||
if (finfo.Friend.StartsWith(friendID.ToString()))
|
|
||||||
return FailureResult();
|
|
||||||
|
|
||||||
// the user needs to confirm when he gets home
|
|
||||||
bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
|
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
return SuccessResult();
|
return SuccessResult();
|
||||||
|
@ -174,25 +183,53 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
secret = request["SECRET"].ToString();
|
secret = request["SECRET"].ToString();
|
||||||
|
|
||||||
if (secret == string.Empty)
|
if (secret == string.Empty)
|
||||||
return FailureResult();
|
return BoolResult(false);
|
||||||
|
|
||||||
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
bool success = m_TheService.DeleteFriendship(friend, secret);
|
||||||
foreach (FriendInfo finfo in finfos)
|
|
||||||
{
|
|
||||||
// We check the secret here
|
|
||||||
if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
|
|
||||||
{
|
|
||||||
m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
|
||||||
m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
|
|
||||||
m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
|
|
||||||
|
|
||||||
return SuccessResult();
|
return BoolResult(success);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FailureResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] FriendshipOffered(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
UUID fromID = UUID.Zero;
|
||||||
|
UUID toID = UUID.Zero;
|
||||||
|
string message = string.Empty;
|
||||||
|
string name = string.Empty;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[HGFRIENDS HANDLER]: Friendship offered");
|
||||||
|
if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
|
||||||
|
return BoolResult(false);
|
||||||
|
|
||||||
|
if (!UUID.TryParse(request["ToID"].ToString(), out toID))
|
||||||
|
return BoolResult(false);
|
||||||
|
|
||||||
|
message = request["Message"].ToString();
|
||||||
|
|
||||||
|
if (!UUID.TryParse(request["FromID"].ToString(), out fromID))
|
||||||
|
return BoolResult(false);
|
||||||
|
|
||||||
|
if (request.ContainsKey("FromName"))
|
||||||
|
name = request["FromName"].ToString();
|
||||||
|
|
||||||
|
bool success = m_TheService.FriendshipOffered(fromID, name, toID, message);
|
||||||
|
|
||||||
|
return BoolResult(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] ValidateFriendshipOffered(Dictionary<string, object> request)
|
||||||
|
{
|
||||||
|
FriendInfo friend = new FriendInfo(request);
|
||||||
|
UUID friendID = UUID.Zero;
|
||||||
|
if (!UUID.TryParse(friend.Friend, out friendID))
|
||||||
|
return BoolResult(false);
|
||||||
|
|
||||||
|
bool success = m_TheService.ValidateFriendshipOffered(friend.PrincipalID, friendID);
|
||||||
|
|
||||||
|
return BoolResult(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Misc
|
#region Misc
|
||||||
|
@ -205,10 +242,15 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request["KEY"] == null || request["SESSIONID"] == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
string serviceKey = request["KEY"].ToString();
|
string serviceKey = request["KEY"].ToString();
|
||||||
string sessionStr = request["SESSIONID"].ToString();
|
string sessionStr = request["SESSIONID"].ToString();
|
||||||
|
|
||||||
UUID sessionID;
|
UUID sessionID;
|
||||||
UUID.TryParse(sessionStr, out sessionID);
|
if (!UUID.TryParse(sessionStr, out sessionID) || serviceKey == string.Empty)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
|
if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
|
||||||
{
|
{
|
||||||
|
@ -256,7 +298,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
|
|
||||||
doc.AppendChild(rootElement);
|
doc.AppendChild(rootElement);
|
||||||
|
|
||||||
XmlElement result = doc.CreateElement("", "Result", "");
|
XmlElement result = doc.CreateElement("", "RESULT", "");
|
||||||
result.AppendChild(doc.CreateTextNode("Success"));
|
result.AppendChild(doc.CreateTextNode("Success"));
|
||||||
|
|
||||||
rootElement.AppendChild(result);
|
rootElement.AppendChild(result);
|
||||||
|
@ -289,7 +331,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
|
|
||||||
doc.AppendChild(rootElement);
|
doc.AppendChild(rootElement);
|
||||||
|
|
||||||
XmlElement result = doc.CreateElement("", "Result", "");
|
XmlElement result = doc.CreateElement("", "RESULT", "");
|
||||||
result.AppendChild(doc.CreateTextNode("Failure"));
|
result.AppendChild(doc.CreateTextNode("Failure"));
|
||||||
|
|
||||||
rootElement.AppendChild(result);
|
rootElement.AppendChild(result);
|
||||||
|
@ -302,6 +344,28 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
return DocToBytes(doc);
|
return DocToBytes(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] BoolResult(bool value)
|
||||||
|
{
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
|
||||||
|
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
|
||||||
|
"", "");
|
||||||
|
|
||||||
|
doc.AppendChild(xmlnode);
|
||||||
|
|
||||||
|
XmlElement rootElement = doc.CreateElement("", "ServerResponse",
|
||||||
|
"");
|
||||||
|
|
||||||
|
doc.AppendChild(rootElement);
|
||||||
|
|
||||||
|
XmlElement result = doc.CreateElement("", "RESULT", "");
|
||||||
|
result.AppendChild(doc.CreateTextNode(value.ToString()));
|
||||||
|
|
||||||
|
rootElement.AppendChild(result);
|
||||||
|
|
||||||
|
return DocToBytes(doc);
|
||||||
|
}
|
||||||
|
|
||||||
private byte[] DocToBytes(XmlDocument doc)
|
private byte[] DocToBytes(XmlDocument doc)
|
||||||
{
|
{
|
||||||
MemoryStream ms = new MemoryStream();
|
MemoryStream ms = new MemoryStream();
|
||||||
|
@ -313,6 +377,7 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
return ms.ToArray();
|
return ms.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,11 @@ namespace OpenSim.Server.Handlers.Hypergrid
|
||||||
// MethodBase.GetCurrentMethod().DeclaringType);
|
// MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private IUserAgentService m_HomeUsersService;
|
private IUserAgentService m_HomeUsersService;
|
||||||
|
public IUserAgentService HomeUsersService
|
||||||
|
{
|
||||||
|
get { return m_HomeUsersService; }
|
||||||
|
}
|
||||||
|
|
||||||
private string[] m_AuthorizedCallers;
|
private string[] m_AuthorizedCallers;
|
||||||
|
|
||||||
private bool m_VerifyCallers = false;
|
private bool m_VerifyCallers = false;
|
||||||
|
|
|
@ -43,7 +43,17 @@ namespace OpenSim.Services.Connectors.Friends
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
protected virtual string ServicePath()
|
||||||
|
{
|
||||||
|
return "friends";
|
||||||
|
}
|
||||||
|
|
||||||
public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message)
|
public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message)
|
||||||
|
{
|
||||||
|
return FriendshipOffered(region, userID, friendID, message, String.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message, string userName)
|
||||||
{
|
{
|
||||||
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
Dictionary<string, object> sendData = new Dictionary<string, object>();
|
||||||
//sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
|
//sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
|
||||||
|
@ -53,9 +63,10 @@ namespace OpenSim.Services.Connectors.Friends
|
||||||
sendData["FromID"] = userID.ToString();
|
sendData["FromID"] = userID.ToString();
|
||||||
sendData["ToID"] = friendID.ToString();
|
sendData["ToID"] = friendID.ToString();
|
||||||
sendData["Message"] = message;
|
sendData["Message"] = message;
|
||||||
|
if (userName != String.Empty)
|
||||||
|
sendData["FromName"] = userName;
|
||||||
|
|
||||||
return Call(region, sendData);
|
return Call(region, sendData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID)
|
public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID)
|
||||||
|
@ -138,8 +149,11 @@ namespace OpenSim.Services.Connectors.Friends
|
||||||
if (region == null)
|
if (region == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: region: {0}", region.ExternalHostName + ":" + region.HttpPort);
|
string path = ServicePath();
|
||||||
string uri = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/friends";
|
if (!region.ServerURI.EndsWith("/"))
|
||||||
|
path = "/" + path;
|
||||||
|
string uri = region.ServerURI + path;
|
||||||
|
m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,7 +40,7 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Services.Connectors.Hypergrid
|
namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
{
|
{
|
||||||
public class HGFriendsServicesConnector
|
public class HGFriendsServicesConnector : FriendsSimConnector
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
private static readonly ILog m_log =
|
||||||
LogManager.GetLogger(
|
LogManager.GetLogger(
|
||||||
|
@ -66,6 +66,11 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
m_SessionID = sessionID;
|
m_SessionID = sessionID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override string ServicePath()
|
||||||
|
{
|
||||||
|
return "hgfriends";
|
||||||
|
}
|
||||||
|
|
||||||
#region IFriendsService
|
#region IFriendsService
|
||||||
|
|
||||||
public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
|
public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
|
||||||
|
@ -187,23 +192,69 @@ namespace OpenSim.Services.Connectors.Hypergrid
|
||||||
{
|
{
|
||||||
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
||||||
|
|
||||||
if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
|
if (replyData.ContainsKey("RESULT"))
|
||||||
{
|
{
|
||||||
bool success = false;
|
if (replyData["RESULT"].ToString().ToLower() == "true")
|
||||||
Boolean.TryParse(replyData["Result"].ToString(), out success);
|
return true;
|
||||||
return success;
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response",
|
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
|
||||||
PrincipalID, Friend);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply");
|
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ValidateFriendshipOffered(UUID fromID, UUID toID)
|
||||||
|
{
|
||||||
|
FriendInfo finfo = new FriendInfo();
|
||||||
|
finfo.PrincipalID = fromID;
|
||||||
|
finfo.Friend = toID.ToString();
|
||||||
|
|
||||||
|
Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
|
||||||
|
|
||||||
|
sendData["METHOD"] = "validate_friendship_offered";
|
||||||
|
|
||||||
|
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 false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reply != string.Empty)
|
||||||
|
{
|
||||||
|
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
|
||||||
|
|
||||||
|
if (replyData.ContainsKey("RESULT"))
|
||||||
|
{
|
||||||
|
if (replyData["RESULT"].ToString().ToLower() == "true")
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
* 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 System.Collections.Generic;
|
||||||
|
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;
|
||||||
|
using Nini.Config;
|
||||||
|
|
||||||
|
namespace OpenSim.Services.HypergridService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// W2W social networking
|
||||||
|
/// </summary>
|
||||||
|
public class HGFriendsService : IHGFriendsService
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log =
|
||||||
|
LogManager.GetLogger(
|
||||||
|
MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
static bool m_Initialized = false;
|
||||||
|
|
||||||
|
protected static IGridUserService m_GridUserService;
|
||||||
|
protected static IGridService m_GridService;
|
||||||
|
protected static IGatekeeperService m_GatekeeperService;
|
||||||
|
protected static IFriendsService m_FriendsService;
|
||||||
|
protected static IPresenceService m_PresenceService;
|
||||||
|
protected static IUserAccountService m_UserAccountService;
|
||||||
|
protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
|
||||||
|
protected static FriendsSimConnector m_FriendsSimConnector; // grid
|
||||||
|
|
||||||
|
private static string m_ConfigName = "HGFriendsService";
|
||||||
|
|
||||||
|
public HGFriendsService(IConfigSource config, String configName, IFriendsSimConnector localSimConn)
|
||||||
|
{
|
||||||
|
if (m_FriendsLocalSimConnector == null)
|
||||||
|
m_FriendsLocalSimConnector = localSimConn;
|
||||||
|
|
||||||
|
if (!m_Initialized)
|
||||||
|
{
|
||||||
|
m_Initialized = true;
|
||||||
|
|
||||||
|
if (configName != String.Empty)
|
||||||
|
m_ConfigName = configName;
|
||||||
|
|
||||||
|
Object[] args = new Object[] { config };
|
||||||
|
|
||||||
|
IConfig serverConfig = config.Configs[m_ConfigName];
|
||||||
|
if (serverConfig == null)
|
||||||
|
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
|
||||||
|
|
||||||
|
string theService = serverConfig.GetString("FriendsService", string.Empty);
|
||||||
|
if (theService == String.Empty)
|
||||||
|
throw new Exception("No FriendsService in config file " + m_ConfigName);
|
||||||
|
m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
|
||||||
|
|
||||||
|
theService = serverConfig.GetString("UserAccountService", string.Empty);
|
||||||
|
if (theService == String.Empty)
|
||||||
|
throw new Exception("No UserAccountService in " + m_ConfigName);
|
||||||
|
m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(theService, args);
|
||||||
|
|
||||||
|
theService = serverConfig.GetString("GridService", string.Empty);
|
||||||
|
if (theService == String.Empty)
|
||||||
|
throw new Exception("No GridService in " + m_ConfigName);
|
||||||
|
m_GridService = ServerUtils.LoadPlugin<IGridService>(theService, args);
|
||||||
|
|
||||||
|
theService = serverConfig.GetString("PresenceService", string.Empty);
|
||||||
|
if (theService == String.Empty)
|
||||||
|
throw new Exception("No PresenceService in " + m_ConfigName);
|
||||||
|
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(theService, args);
|
||||||
|
|
||||||
|
m_FriendsSimConnector = new FriendsSimConnector();
|
||||||
|
|
||||||
|
m_log.DebugFormat("[HGFRIENDS SERVICE]: Starting...");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IHGFriendsService
|
||||||
|
|
||||||
|
public int GetFriendPerms(UUID userID, UUID friendID)
|
||||||
|
{
|
||||||
|
FriendInfo[] friendsInfo = m_FriendsService.GetFriends(userID);
|
||||||
|
foreach (FriendInfo finfo in friendsInfo)
|
||||||
|
{
|
||||||
|
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||||
|
return finfo.TheirFlags;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NewFriendship(FriendInfo friend, bool verified)
|
||||||
|
{
|
||||||
|
UUID friendID;
|
||||||
|
string tmp = string.Empty, url = String.Empty, first = String.Empty, last = String.Empty;
|
||||||
|
if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out first, out last, out tmp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_log.DebugFormat("[HGFRIENDS SERVICE]: New friendship {0} {1} ({2})", friend.PrincipalID, friend.Friend, verified);
|
||||||
|
|
||||||
|
// Does the friendship already exist?
|
||||||
|
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
||||||
|
foreach (FriendInfo finfo in finfos)
|
||||||
|
{
|
||||||
|
if (finfo.Friend.StartsWith(friendID.ToString()))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Verified user session. But the user needs to confirm friendship when he gets home
|
||||||
|
if (verified)
|
||||||
|
return m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
|
||||||
|
|
||||||
|
// Does the reverted friendship exist? meaning that this user initiated the request
|
||||||
|
finfos = m_FriendsService.GetFriends(friendID);
|
||||||
|
bool userInitiatedOffer = false;
|
||||||
|
foreach (FriendInfo finfo in finfos)
|
||||||
|
{
|
||||||
|
if (friend.Friend.StartsWith(finfo.PrincipalID.ToString()) && finfo.Friend.StartsWith(friend.PrincipalID.ToString()) && finfo.TheirFlags == -1)
|
||||||
|
{
|
||||||
|
userInitiatedOffer = true;
|
||||||
|
// Let's delete the existing friendship relations that was stored
|
||||||
|
m_FriendsService.Delete(friendID, finfo.Friend);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userInitiatedOffer)
|
||||||
|
{
|
||||||
|
m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 1);
|
||||||
|
m_FriendsService.StoreFriend(friend.Friend, friend.PrincipalID.ToString(), 1);
|
||||||
|
// notify the user
|
||||||
|
ForwardToSim("ApproveFriendshipRequest", friendID, Util.UniversalName(first, last, url), "", friend.PrincipalID, "");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DeleteFriendship(FriendInfo friend, string secret)
|
||||||
|
{
|
||||||
|
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
|
||||||
|
foreach (FriendInfo finfo in finfos)
|
||||||
|
{
|
||||||
|
// We check the secret here. Or if the friendship request was initiated here, and was declined
|
||||||
|
if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
|
||||||
|
{
|
||||||
|
m_log.DebugFormat("[HGFRIENDS SERVICE]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
|
||||||
|
m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
|
||||||
|
m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool FriendshipOffered(UUID fromID, string fromName, UUID toID, string message)
|
||||||
|
{
|
||||||
|
UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, toID);
|
||||||
|
if (account == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// OK, we have that user here.
|
||||||
|
// So let's send back the call, but start a thread to continue
|
||||||
|
// with the verification and the actual action.
|
||||||
|
|
||||||
|
Util.FireAndForget(delegate { ProcessFriendshipOffered(fromID, fromName, toID, message); });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateFriendshipOffered(UUID fromID, UUID toID)
|
||||||
|
{
|
||||||
|
FriendInfo[] finfos = m_FriendsService.GetFriends(toID.ToString());
|
||||||
|
foreach (FriendInfo fi in finfos)
|
||||||
|
{
|
||||||
|
if (fi.Friend.StartsWith(fromID.ToString()) && fi.TheirFlags == -1)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion IHGFriendsService
|
||||||
|
|
||||||
|
#region Aux
|
||||||
|
|
||||||
|
private void ProcessFriendshipOffered(UUID fromID, String fromName, UUID toID, String message)
|
||||||
|
{
|
||||||
|
// Great, it's a genuine request. Let's proceed.
|
||||||
|
// But now we need to confirm that the requester is who he says he is
|
||||||
|
// before we act on the friendship request.
|
||||||
|
|
||||||
|
if (!fromName.Contains("@"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string[] parts = fromName.Split(new char[] {'@'});
|
||||||
|
if (parts.Length != 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string uriStr = "http://" + parts[1];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new Uri(uriStr);
|
||||||
|
}
|
||||||
|
catch (UriFormatException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uriStr);
|
||||||
|
Dictionary<string, object> servers = uasConn.GetServerURLs(fromID);
|
||||||
|
if (!servers.ContainsKey("FriendsServerURI"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(servers["FriendsServerURI"].ToString());
|
||||||
|
if (!friendsConn.ValidateFriendshipOffered(fromID, toID))
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[HGFRIENDS SERVICE]: Friendship request from {0} to {1} is invalid. Impersonations?", fromID, toID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fromUUI = Util.UniversalIdentifier(fromID, parts[0], "@" + parts[1], uriStr);
|
||||||
|
// OK, we're good!
|
||||||
|
ForwardToSim("FriendshipOffered", fromID, fromName, fromUUI, toID, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ForwardToSim(string op, UUID fromID, string name, String fromUUI, UUID toID, string message)
|
||||||
|
{
|
||||||
|
PresenceInfo session = null;
|
||||||
|
GridRegion region = null;
|
||||||
|
PresenceInfo[] sessions = m_PresenceService.GetAgents(new string[] { toID.ToString() });
|
||||||
|
if (sessions != null && sessions.Length > 0)
|
||||||
|
session = sessions[0];
|
||||||
|
if (session != null)
|
||||||
|
region = m_GridService.GetRegionByUUID(UUID.Zero, session.RegionID);
|
||||||
|
|
||||||
|
switch (op)
|
||||||
|
{
|
||||||
|
case "FriendshipOffered":
|
||||||
|
// Let's store backwards
|
||||||
|
string secret = UUID.Random().ToString().Substring(0, 8);
|
||||||
|
m_FriendsService.StoreFriend(toID.ToString(), fromUUI + ";" + secret, 0);
|
||||||
|
if (m_FriendsLocalSimConnector != null) // standalone
|
||||||
|
{
|
||||||
|
GridInstantMessage im = new GridInstantMessage(null, fromID, name, toID,
|
||||||
|
(byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero);
|
||||||
|
// !! HACK
|
||||||
|
im.imSessionID = im.fromAgentID;
|
||||||
|
return m_FriendsLocalSimConnector.LocalFriendshipOffered(toID, im);
|
||||||
|
}
|
||||||
|
else if (region != null) // grid
|
||||||
|
return m_FriendsSimConnector.FriendshipOffered(region, fromID, toID, message, name);
|
||||||
|
break;
|
||||||
|
case "ApproveFriendshipRequest":
|
||||||
|
if (m_FriendsLocalSimConnector != null) // standalone
|
||||||
|
return m_FriendsLocalSimConnector.LocalFriendshipApproved(fromID, name, toID);
|
||||||
|
else if (region != null) //grid
|
||||||
|
return m_FriendsSimConnector.FriendshipApproved(region, fromID, name, toID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Aux
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,6 +81,17 @@ namespace OpenSim.Services.Interfaces
|
||||||
public interface IFriendsSimConnector
|
public interface IFriendsSimConnector
|
||||||
{
|
{
|
||||||
bool StatusNotify(UUID userID, UUID friendID, bool online);
|
bool StatusNotify(UUID userID, UUID friendID, bool online);
|
||||||
|
bool LocalFriendshipOffered(UUID toID, GridInstantMessage im);
|
||||||
|
bool LocalFriendshipApproved(UUID userID, string userName, UUID friendID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IHGFriendsService
|
||||||
|
{
|
||||||
|
int GetFriendPerms(UUID userID, UUID friendID);
|
||||||
|
bool NewFriendship(FriendInfo finfo, bool verified);
|
||||||
|
bool DeleteFriendship(FriendInfo finfo, string secret);
|
||||||
|
bool FriendshipOffered(UUID from, string fromName, UUID to, string message);
|
||||||
|
bool ValidateFriendshipOffered(UUID fromID, UUID toID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IInstantMessageSimConnector
|
public interface IInstantMessageSimConnector
|
||||||
|
|
|
@ -159,8 +159,12 @@
|
||||||
UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
||||||
|
|
||||||
[HGFriendsService]
|
[HGFriendsService]
|
||||||
LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService"
|
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService"
|
||||||
UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
|
UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
|
||||||
|
FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService"
|
||||||
|
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
|
||||||
|
GridService = "OpenSim.Services.GridService.dll:GridService"
|
||||||
|
PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
|
||||||
|
|
||||||
[HGInstantMessageService]
|
[HGInstantMessageService]
|
||||||
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService"
|
LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService"
|
||||||
|
|
Loading…
Reference in New Issue