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) // We stick this agent's ID as imSession, so that it's directly available on the receiving end im.imSessionID = im.fromAgentID; im.fromAgentName = GetFriendshipRequesterName(agentID); // Try the local sim if (LocalFriendshipOffered(friendID, im)) { return(true); } // The prospective friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); return(true); } } // If the prospective friend is not online, he'll get the message upon login. return(false); }
public void RemoveFriendship(IClientAPI client, UUID exfriendID) { if (!DeleteFriendship(client.AgentId, exfriendID)) { client.SendAlertMessage("Unable to terminate friendship on this sim."); } // Update local cache RecacheFriends(client); client.SendTerminateFriend(exfriendID); // // Notify the friend // // Try local if (LocalFriendshipTerminated(client.AgentId, exfriendID)) { return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipTerminated(region, client.AgentId, exfriendID); } } }
private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) { FriendsService.Delete(agentID, exfriendID.ToString()); FriendsService.Delete(exfriendID, agentID.ToString()); // Update local cache UpdateFriendsCache(agentID); client.SendTerminateFriend(exfriendID); // // Notify the friend // // Try local if (LocalFriendshipTerminated(exfriendID)) { return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); } } }
private List <PresenceInfo> GetSessions(UUID userID) { List <PresenceInfo> presences = new List <PresenceInfo>(1); OSDMap userResponse = GetUserData(userID); if (userResponse != null) { m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID); NameValueCollection requestArgs = new NameValueCollection { { "RequestMethod", "GetSession" }, { "UserID", userID.ToString() } }; OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs); if (response["Success"].AsBoolean()) { PresenceInfo presence = ResponseToPresenceInfo(response, userResponse); if (presence != null) { presences.Add(presence); } } else { m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString()); } } return(presences); }
private void ForwardFriendshipOffer(UUID agentID, UUID friendID, GridInstantMessage im) { // !!!!!!!! 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 im.imSessionID = im.fromAgentID; // Try the local sim UserAccount account = UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, agentID); im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; if (LocalFriendshipOffered(friendID, im)) { return; } // The prospective friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); } } // If the prospective friend is not online, he'll get the message upon login. }
private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List <UUID> callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); FriendsService.StoreFriend(agentID, friendID.ToString(), 1); FriendsService.StoreFriend(friendID, agentID.ToString(), 1); // Update the local cache UpdateFriendsCache(agentID); // // Notify the friend // // Try Local if (LocalFriendshipApproved(agentID, client.Name, friendID)) { client.SendAgentOnline(new UUID[] { friendID }); return; } // The friend is not here PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); client.SendAgentOnline(new UUID[] { friendID }); } } }
public void AddFriendship(IClientAPI client, UUID friendID) { StoreFriendships(client.AgentId, friendID); // Update the local cache RecacheFriends(client); // // Notify the friend // // Try Local if (LocalFriendshipApproved(client.AgentId, client.Name, friendID)) { client.SendAgentOnline(new UUID[] { friendID }); return; } // The friend is not here PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); m_FriendsSimConnector.FriendshipApproved(region, client.AgentId, client.Name, friendID); client.SendAgentOnline(new UUID[] { friendID }); } } }
private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List <UUID> callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); FriendsService.Delete(agentID, friendID.ToString()); FriendsService.Delete(friendID, agentID.ToString()); // // Notify the friend // // Try local if (LocalFriendshipDenied(agentID, client.Name, friendID)) { return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); if (region != null) { m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); } else { m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); } } } }
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); FriendInfo[] friends = GetFriends(remoteClient.AgentId); if (friends.Length == 0) { return; } // Let's find the friend in this user's friend list FriendInfo friend = GetFriend(friends, target); if (friend != null) // Found it { // Store it on the DB if (!StoreRights(requester, target, rights)) { remoteClient.SendAlertMessage("Unable to grant rights."); return; } // Store it in the local cache int myFlags = friend.MyFlags; friend.MyFlags = rights; // Always send this back to the original client remoteClient.SendChangeUserRights(requester, target, rights); // // Notify the friend // // Try local if (LocalGrantRights(requester, target, myFlags, rights)) { return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); // TODO: You might want to send the delta to save the lookup // on the other end!! m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); } } } else { m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); } }
private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) { if (!m_Friends.ContainsKey(remoteClient.AgentId)) { return; } m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); // Let's find the friend in this user's friend list UserFriendData fd = m_Friends[remoteClient.AgentId]; FriendInfo friend = null; foreach (FriendInfo fi in fd.Friends) { if (fi.Friend == target.ToString()) { friend = fi; } } if (friend != null) // Found it { // Store it on the DB FriendsService.StoreFriend(requester, target.ToString(), rights); // Store it in the local cache int myFlags = friend.MyFlags; friend.MyFlags = rights; // Always send this back to the original client remoteClient.SendChangeUserRights(requester, target, rights); // // Notify the friend // // Try local if (LocalGrantRights(requester, target, myFlags, rights)) { return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); // TODO: You might want to send the delta to save the lookup // on the other end!! m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); } } } }
public bool Report(PresenceInfo presence) { PresenceData p = new PresenceData(); p.Data = new Dictionary<string, string>(); p.UUID = presence.PrincipalID; p.currentRegion = presence.RegionID; foreach (KeyValuePair<string, string> kvp in presence.Data) p.Data[kvp.Key] = kvp.Value; return false; }
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) { if (sessionResponse == null) { return(null); } PresenceInfo info = new PresenceInfo(); info.UserID = sessionResponse["UserID"].AsUUID().ToString(); info.RegionID = sessionResponse["SceneID"].AsUUID(); return(info); }
protected virtual void StatusNotify(List <FriendInfo> friendList, UUID userID, bool online) { foreach (FriendInfo friend in friendList) { UUID friendID; if (UUID.TryParse(friend.Friend, out friendID)) { // 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) { PresenceInfo friendSession = null; foreach (PresenceInfo pinfo in friendSessions) { if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad { friendSession = pinfo; break; } } 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); } } }
/// <summary> /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from /// itself, prevRegionHandle will be the last region handle that we tried to send. /// If the handles are the same, we look up the user's location using the grid. /// If the handles are still the same, we end. The send failed. /// </summary> /// <param name="prevRegionHandle"> /// Pass in 0 the first time this method is called. It will be called recursively with the last /// regionhandle tried /// </param> protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, GridRegion prevRegion) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; GridRegion cachedRegion = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { //They have been IMed before, look up in the cache upd = new PresenceInfo(); upd.RegionID = m_UserRegionMap[toAgentID].Region.RegionID; cachedRegion = m_UserRegionMap[toAgentID].Region; // We need to compare the current regionhandle with the previous region handle // or the recursive loop will never end because it will never try to lookup the agent again if (prevRegion != null && prevRegion.RegionID == upd.RegionID) { //If prevRegion is the same as the cache, look them up, someone moved lookupAgent = true; } } else { //Havn't IMed this person before, get their presence info lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { //Find the regions http address where the agent is string[] AgentLocations = PresenceService.GetAgentsLocations(new string[] { toAgentID.ToString() }); if (AgentLocations == null || (AgentLocations.Length == 1 && AgentLocations[0] == "Failure")) //If this is true, this doesn't exist on the presence server and we use the legacy way { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) upd = presences[0]; if (upd != null) { // check if we've tried this region before.. // This is one way to end the recursive loop if ((upd.RegionID == UUID.Zero) || (prevRegion != null && upd.RegionID == prevRegion.RegionID)) { m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } } else { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); bool imresult = doIMSending("http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = new IMPresenceInfo(); m_UserRegionMap[toAgentID].HTTPPath = "http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort; } result(true); return; } else { // This happens when the agent moves out of the last known region // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! SendGridInstantMessageViaXMLRPCAsync(im, result, cachedRegion); } return; //If this isn't here, infinite loop occurs } } if (upd != null) { if(cachedRegion == null) cachedRegion = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (cachedRegion != null) { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); bool imresult = doIMSending("http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { m_UserRegionMap[toAgentID] = new IMPresenceInfo(); m_UserRegionMap[toAgentID].Region = cachedRegion; m_UserRegionMap[toAgentID].HTTPPath = "http://" + cachedRegion.ExternalHostName + ":" + cachedRegion.HttpPort; } result(true); } else { // This happens when the agent moves out of the last known region // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! SendGridInstantMessageViaXMLRPCAsync(im, result, cachedRegion); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } }
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse) { if (sessionResponse == null) return null; PresenceInfo info = new PresenceInfo(); info.Online = true; info.UserID = sessionResponse["UserID"].AsUUID().ToString(); info.RegionID = sessionResponse["SceneID"].AsUUID(); info.Position = sessionResponse["ScenePosition"].AsVector3(); info.LookAt = sessionResponse["SceneLookAt"].AsVector3(); if (userResponse != null && userResponse["User"] is OSDMap) { OSDMap user = (OSDMap)userResponse["User"]; info.Login = user["LastLoginDate"].AsDate(); info.Logout = user["LastLogoutDate"].AsDate(); DeserializeLocation(user["HomeLocation"].AsString(), out info.HomeRegionID, out info.HomePosition, out info.HomeLookAt); } return info; }
public void FindFriend(IClientAPI remoteClient, UUID HunterID, UUID PreyID) { UUID requester = remoteClient.AgentId; if (requester != HunterID) // only allow client agent to be the hunter (?) { return; } FriendInfo[] friends = GetFriendsFromCache(requester); if (friends.Length == 0) { return; } FriendInfo friend = GetFriend(friends, PreyID); if (friend == null) { return; } if (friend.TheirFlags == -1 || (friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0) { return; } Scene hunterScene = (Scene)remoteClient.Scene; if (hunterScene == null) { return; } // check local ScenePresence sp; double px; double py; if (hunterScene.TryGetScenePresence(PreyID, out sp)) { if (sp == null) { return; } px = hunterScene.RegionInfo.WorldLocX + sp.AbsolutePosition.X; py = hunterScene.RegionInfo.WorldLocY + sp.AbsolutePosition.Y; remoteClient.SendFindAgent(HunterID, PreyID, px, py); return; } PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { PreyID.ToString() }); if (friendSessions == null || friendSessions.Length == 0) { return; } PresenceInfo friendSession = friendSessions[0]; if (friendSession == null) { return; } GridRegion region = GridService.GetRegionByUUID(hunterScene.RegionInfo.ScopeID, friendSession.RegionID); if (region == null) { return; } // we don't have presence location so point to a standard region center for now px = region.RegionLocX + 128.0; py = region.RegionLocY + 128.0; remoteClient.SendFindAgent(HunterID, PreyID, px, py); }
public PresenceInfo[] GetAgents(string[] userIDs) { List<PresenceInfo> info = new List<PresenceInfo>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { PresenceInfo ret = new PresenceInfo(); if (m_checkLastSeen && int.Parse(d.Data["LastSeen"]) + (1000 * 60 * 60) < Util.UnixTimeSinceEpoch()) { m_log.Warn("[PresenceService]: Found a user (" + d.UserID + ") that was not seen within the last hour! Logging them out."); LogoutAgent(d.SessionID); continue; } ret.UserID = d.UserID; ret.RegionID = d.RegionID; info.Add(ret); } } // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); }
private void SendGridDialogViaXMLRPCAsync(UUID avatarID, string objectName, UUID objectID, UUID ownerID, string ownerFirstName, string ownerLastName, string message, UUID textureID, int ch, string[] buttonlabels, UUID prevRegionID) { PresenceInfo upd = null; // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { avatarID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { upd = p; break; } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { //Dialog content undelivered m_log.WarnFormat("Couldn't deliver dialog to {0}", avatarID); return; } } else { //Dialog content undelivered m_log.WarnFormat("Couldn't deliver dialog to {0}", avatarID); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { Hashtable msgdata = ConvertGridDialogToXMLRPC(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); //= ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change // msgdata["region_handle"] = 0; bool imresult = doDialogSending(reginfo, msgdata); if (!imresult) { SendGridDialogViaXMLRPCAsync(avatarID, objectName, objectID, ownerID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels, prevRegionID); m_log.WarnFormat("Couldn't deliver dialog to {0}", avatarID); return; } } } }
public string[] GetAgentsLocations(string[] userIDs) { List<string> info = new List<string>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); if (data.Length != 0) { PresenceData d = data[0]; PresenceInfo ret = new PresenceInfo(); if (int.Parse(d.Data["LastSeen"]) + (1000 * 60 * 60) < Util.UnixTimeSinceEpoch()) { m_log.Warn("[PresenceService]: Found a user (" + d.UserID + ") that was not seen within the last hour! Logging them out."); LogoutAgent(d.SessionID); info.Add(""); continue; } if (d.RegionID == UUID.Zero) //Bad logout { m_log.Warn("[PresenceService]: Found a user (" + d.UserID + ") that does not have a region (UUID.Zero)! Logging them out."); LogoutAgent(d.SessionID); info.Add(""); continue; } GridRegion r = m_GridService.GetRegionByUUID(UUID.Zero, d.RegionID); if (r != null) info.Add(r.ServerURI); } else//Add a blank one info.Add(""); } // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); }
public void SendFriendsOnlineIfNeeded(IClientAPI client) { UUID agentID = client.AgentId; // Check if the online friends list is needed lock (m_NeedsListOfFriends) { if (!m_NeedsListOfFriends.Remove(agentID)) { return; } } // Send the friends online List <UUID> online = GetOnlineFriends(agentID); if (online.Count > 0) { m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); client.SendAgentOnline(online.ToArray()); } // Send outstanding friendship offers List <string> outstanding = new List <string>(); FriendInfo[] friends = GetFriends(agentID); foreach (FriendInfo fi in friends) { if (fi.TheirFlags == -1) { outstanding.Add(fi.Friend); } } GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, String.Empty, agentID, (byte)InstantMessageDialog.FriendshipOffered, "Will you be my friend?", true, Vector3.Zero); foreach (string fid in outstanding) { UUID fromAgentID; if (!UUID.TryParse(fid, out fromAgentID)) { continue; } UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); PresenceInfo presence = null; PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); if (presences != null && presences.Length > 0) { presence = presences[0]; } if (presence != null) { im.offline = 0; } im.fromAgentID = fromAgentID.Guid; im.fromAgentName = account.FirstName + " " + account.LastName; im.offline = (byte)((presence == null) ? 1 : 0); im.imSessionID = im.fromAgentID; // Finally LocalFriendshipOffered(agentID, im); } }
bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner) { bool imresult = false; GridRegion reginfo = null; if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo)) { reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID); if (reginfo != null) m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS); } if (reginfo != null) { imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im); } else { m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI); return false; } if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserLocationMap) { if (m_UserLocationMap.ContainsKey(toAgentID)) { m_UserLocationMap[toAgentID] = upd; } else { m_UserLocationMap.Add(toAgentID, upd); } } return true; } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! return TrySendInstantMessage(im, upd, false, foreigner); } }
public PresenceInfo[] GetAgents(string[] userIDs) { List<PresenceInfo> info = new List<PresenceInfo>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { PresenceInfo ret = new PresenceInfo(); ret.UserID = d.UserID; ret.RegionID = d.RegionID; ret.Online = bool.Parse(d.Data["Online"]); ret.Login = Util.ToDateTime(Convert.ToInt32( d.Data["Login"])); ret.Logout = Util.ToDateTime(Convert.ToInt32( d.Data["Logout"])); ret.Position = Vector3.Parse(d.Data["Position"]); ret.LookAt = Vector3.Parse(d.Data["LookAt"]); ret.HomeRegionID = new UUID(d.Data["HomeRegionID"]); ret.HomePosition = Vector3.Parse(d.Data["HomePosition"]); ret.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); info.Add(ret); } } // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); }
public PresenceInfo[] GetAgents(string[] userIDs) { List<PresenceInfo> info = new List<PresenceInfo>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { PresenceInfo ret = new PresenceInfo(); if (int.Parse(d.Data["LastSeen"]) + (60 * 60) < Util.UnixTimeSinceEpoch()) { LogoutAgent(d.SessionID); continue; } ret.UserID = d.UserID; ret.RegionID = d.RegionID; info.Add(ret); } } // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); }
public PresenceInfo GetAgent(UUID sessionID) { PresenceInfo ret = new PresenceInfo(); PresenceData data = m_Database.Get(sessionID); if (data == null) return null; if (int.Parse(data.Data["LastSeen"]) + (1000 * 60 * 60) < Util.UnixTimeSinceEpoch()) { LogoutAgent(sessionID); return null; } ret.UserID = data.UserID; ret.RegionID = data.RegionID; return ret; }
protected GridRegion FindDestination(UserAccount account, UUID scopeID, PresenceInfo pinfo, UUID sessionID, string startLocation, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt) { m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation); gatekeeper = null; where = "home"; position = new Vector3(128, 128, 0); lookAt = new Vector3(0, 1, 0); if (m_GridService == null) return null; if (startLocation.Equals("home")) { // logging into home region if (pinfo == null) return null; GridRegion region = null; bool tryDefaults = false; if (pinfo.HomeRegionID.Equals(UUID.Zero)) { m_log.WarnFormat( "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set", account.FirstName, account.LastName); tryDefaults = true; } else { region = m_GridService.GetRegionByUUID(scopeID, pinfo.HomeRegionID); if (null == region) { m_log.WarnFormat( "[LLOGIN SERVICE]: User {0} {1} has a recorded home region of {2} but this cannot be found by the grid service", account.FirstName, account.LastName, pinfo.HomeRegionID); tryDefaults = true; } } if (tryDefaults) { List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); if (defaults != null && defaults.Count > 0) { region = defaults[0]; where = "safe"; } else { m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a valid home and this grid does not have default locations. Attempting to find random region", account.FirstName, account.LastName); defaults = m_GridService.GetRegionsByName(scopeID, "", 1); if (defaults != null && defaults.Count > 0) { region = defaults[0]; where = "safe"; } } } return region; } else if (startLocation.Equals("last")) { // logging into last visited region where = "last"; if (pinfo == null) return null; GridRegion region = null; if (pinfo.RegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(scopeID, pinfo.RegionID)) == null) { List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); if (defaults != null && defaults.Count > 0) { region = defaults[0]; where = "safe"; } else { m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region"); defaults = m_GridService.GetRegionsByName(scopeID, "", 1); if (defaults != null && defaults.Count > 0) { region = defaults[0]; where = "safe"; } } } else { position = pinfo.Position; lookAt = pinfo.LookAt; } return region; } else { // free uri form // e.g. New Moon&135&46 New [email protected]:8002&153&34 where = "url"; Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$"); Match uriMatch = reURI.Match(startLocation); if (uriMatch == null) { m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, but can't process it", startLocation); return null; } else { position = new Vector3(float.Parse(uriMatch.Groups["x"].Value, Culture.NumberFormatInfo), float.Parse(uriMatch.Groups["y"].Value, Culture.NumberFormatInfo), float.Parse(uriMatch.Groups["z"].Value, Culture.NumberFormatInfo)); string regionName = uriMatch.Groups["region"].ToString(); if (regionName != null) { if (!regionName.Contains("@")) { List<GridRegion> regions = m_GridService.GetRegionsByName(scopeID, regionName, 1); if ((regions == null) || (regions != null && regions.Count == 0)) { m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}. Trying defaults.", startLocation, regionName); regions = m_GridService.GetDefaultRegions(scopeID); if (regions != null && regions.Count > 0) { where = "safe"; return regions[0]; } else { m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation); return null; } } return regions[0]; } else { if (m_UserAgentService == null) { m_log.WarnFormat("[LLLOGIN SERVICE]: This llogin service is not running a user agent service, as such it can't lauch agents at foreign grids"); return null; } string[] parts = regionName.Split(new char[] { '@' }); if (parts.Length < 2) { m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}", startLocation, regionName); return null; } // Valid specification of a remote grid regionName = parts[0]; string domainLocator = parts[1]; parts = domainLocator.Split(new char[] {':'}); string domainName = parts[0]; uint port = 0; if (parts.Length > 1) UInt32.TryParse(parts[1], out port); GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper); return region; } } else { List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID); if (defaults != null && defaults.Count > 0) { where = "safe"; return defaults[0]; } else return null; } } //response.LookAt = "[r0,r1,r0]"; //// can be: last, home, safe, url //response.StartLocation = "url"; } }
public PresenceInfo GetAgent(UUID sessionID) { PresenceInfo ret = new PresenceInfo(); PresenceData data = m_Database.Get(sessionID); if (data == null) return null; ret.UserID = data.UserID; ret.RegionID = data.RegionID; if (data.Data.ContainsKey("Online")) ret.Online = bool.Parse(data.Data["Online"]); if (data.Data.ContainsKey("Login")) ret.Login = Util.ToDateTime(Convert.ToInt32(data.Data["Login"])); if (data.Data.ContainsKey("Logout")) ret.Logout = Util.ToDateTime(Convert.ToInt32(data.Data["Logout"])); if (data.Data.ContainsKey("Position")) ret.Position = Vector3.Parse(data.Data["Position"]); if (data.Data.ContainsKey("LookAt")) ret.LookAt = Vector3.Parse(data.Data["LookAt"]); if (data.Data.ContainsKey("HomeRegionID")) ret.HomeRegionID = new UUID(data.Data["HomeRegionID"]); if (data.Data.ContainsKey("HomePosition")) ret.HomePosition = Vector3.Parse(data.Data["HomePosition"]); if (data.Data.ContainsKey("HomeLookAt")) ret.HomeLookAt = Vector3.Parse(data.Data["HomeLookAt"]); return ret; }
public PresenceInfo GetAgent(UUID sessionID) { PresenceInfo ret = new PresenceInfo(); PresenceData data = m_Database.Get(sessionID); if (data == null) return null; ret.UserID = data.UserID; ret.RegionID = data.RegionID; return ret; }
/// <summary> /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from /// itself, prevRegionHandle will be the last region handle that we tried to send. /// If the handles are the same, we look up the user's location using the grid. /// If the handles are still the same, we end. The send failed. /// </summary> /// <param name="prevRegionHandle"> /// Pass in 0 the first time this method is called. It will be called recursively with the last /// regionhandle tried /// </param> protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new PresenceInfo(); upd.RegionID = m_UserRegionMap[toAgentID]; // We need to compare the current regionhandle with the previous region handle // or the recursive loop will never end because it will never try to lookup the agent again if (prevRegionID == upd.RegionID) { lookupAgent = true; } } else { lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change // msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { m_UserRegionMap[toAgentID] = upd.RegionID; } else { m_UserRegionMap.Add(toAgentID, upd.RegionID); } } result(true); } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! SendGridInstantMessageViaXMLRPCAsync(im, result, upd.RegionID); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } }
byte[] Report(Dictionary<string, object> request) { PresenceInfo info = new PresenceInfo(); info.Data = new Dictionary<string, string>(); if (!request.ContainsKey("PrincipalID") || !request.ContainsKey("RegionID")) return FailureResult(); if (!UUID.TryParse(request["PrincipalID"].ToString(), out info.PrincipalID)) return FailureResult(); if (!UUID.TryParse(request["RegionID"].ToString(), out info.RegionID)) return FailureResult(); foreach (KeyValuePair<string, object> kvp in request) { if (kvp.Key == "METHOD" || kvp.Key == "PrincipalID" || kvp.Key == "RegionID") continue; info.Data[kvp.Key] = kvp.Value.ToString(); } if (m_PresenceService.Report(info)) return SuccessResult(); return FailureResult(); }
/// <summary> /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from /// itself, prevRegionHandle will be the last region handle that we tried to send. /// If the handles are the same, we look up the user's location using the grid. /// If the handles are still the same, we end. The send failed. /// </summary> /// <param name="prevRegionHandle"> /// Pass in 0 the first time this method is called. It will be called recursively with the last /// regionhandle tried /// </param> protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { uint restartloopcount = 100; restart: UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; UUID _regionID; bool lookupAgent = false; if (m_UserRegionMap.TryGetValue(toAgentID, out _regionID)) { upd = new PresenceInfo(); upd.RegionID = _regionID; // We need to compare the current regionhandle with the previous region handle // or the recursive loop will never end because it will never try to lookup the agent again if (prevRegionID == upd.RegionID) { lookupAgent = true; } } else { lookupAgent = true; } // Are we needing to look-up an agent? if (lookupAgent) { // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { if (p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change // msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. m_UserRegionMap[toAgentID] = upd.RegionID; result(true); } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This may end up in an endless loop. However, that is still nicer than the endless recursion that was previously possible. prevRegionID = upd.RegionID; if (restartloopcount-- == 0) { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to locate user after several tries (loop count exceeded)"); HandleUndeliveredMessage(im, result); } goto restart; } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); HandleUndeliveredMessage(im, result); } } else { HandleUndeliveredMessage(im, result); } }
public string[] GetAgentsLocations(string[] userIDs) { List<string> info = new List<string>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { PresenceInfo ret = new PresenceInfo(); if (int.Parse(d.Data["LastSeen"]) + (1000 * 60 * 60) < Util.UnixTimeSinceEpoch()) { LogoutAgent(d.SessionID); continue; } if (ret.RegionID == UUID.Zero) //Bad logout { LogoutAgent(d.SessionID); continue; } Services.Interfaces.GridRegion r = m_GridService.GetRegionByUUID(UUID.Zero, d.RegionID); if(r != null) info.Add("http://" + r.ExternalHostName + ":" + r.HttpPort); } } // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); }
public PresenceInfo GetAgent(UUID sessionID) { Dictionary<string, object> sendData = new Dictionary<string, object>(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); sendData["METHOD"] = "getagent"; sendData["SessionID"] = sessionID.ToString(); string reply = string.Empty; string reqString = ServerUtils.BuildQueryString(sendData); string uri = m_ServerURI + "/presence"; // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); try { reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply"); return null; } } catch (Exception e) { m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message); return null; } Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply); PresenceInfo pinfo = null; if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) { if (replyData["result"] is Dictionary<string, object>) { pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]); } else { if (replyData["result"].ToString() == "null") return null; m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString()); } } else { m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply received from presence server when querying for sessionID {0}", sessionID.ToString()); } return pinfo; }
public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner) { m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url); if (url != string.Empty) return TrySendInstantMessage(im, url, true, foreigner); else { PresenceInfo upd = new PresenceInfo(); upd.RegionID = UUID.Zero; return TrySendInstantMessage(im, upd, true, foreigner); } }
/// <summary> /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from /// itself, prevRegionHandle will be the last region handle that we tried to send. /// If the handles are the same, we look up the user's location using the grid. /// If the handles are still the same, we end. The send failed. /// </summary> /// <param name="prevRegionHandle"> /// Pass in 0 the first time this method is called. It will be called recursively with the last /// regionhandle tried /// </param> protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new PresenceInfo(); upd.RegionID = m_UserRegionMap[toAgentID]; // We need to compare the current regionhandle with the previous region handle // or the recursive loop will never end because it will never try to lookup the agent again if (prevRegionID == upd.RegionID) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentInRegionMap. prevRegion==upd.Region settingLookupAgentTrue, agentID={1}, regionID={2}", LogHeader, toAgentID, prevRegionID); lookupAgent = true; } } else { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentNOTInRegionMap. setting LookupAgentTrue", LogHeader); lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: lookupAgent IS TRUE", LogHeader); // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: got presences. p.RegionID={1}", LogHeader, p.RegionID); // Sometimes we get more than 1 session querying a single agent ID! Filter for the correct agent ID. if (p.UserID == toAgentID.ToString() && p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: regionID==prevRegionID: regionID={1}, agentID={2}", LogHeader, prevRegionID, toAgentID); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: lookupAgent=true, upd==null, agentID={1}", LogHeader, toAgentID); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: regInfoNotNull, regID={1}, regNam={2}, regURI={3}, regPort={4}", LogHeader, reginfo.RegionID, reginfo.RegionName, reginfo.ServerURI, reginfo.HttpPort); Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change // msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Updating RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); m_UserRegionMap[toAgentID] = upd.RegionID; } else { m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Add RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); m_UserRegionMap.Add(toAgentID, upd.RegionID); } } result(true); } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Calling me recursively. region={1}", LogHeader, upd.RegionID); SendGridInstantMessageViaXMLRPCAsync(im, result, upd.RegionID); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); m_log.DebugFormat("{0} Unable to deliver instant message: regionInfo==null, lookupAgent={1}, agentid={2}, region={3}", LogHeader, lookupAgent, toAgentID, upd.RegionID); HandleUndeliveredMessage(im, result); } } else { m_log.DebugFormat("{0} Unable to deliver instant message: upd==null, lookupAgent={1}, agentid={2}", LogHeader, lookupAgent, toAgentID); HandleUndeliveredMessage(im, result); } }
/// <summary> /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from /// itself, prevRegionHandle will be the last region handle that we tried to send. /// If the handles are the same, we look up the user's location using the grid. /// If the handles are still the same, we end. The send failed. /// </summary> /// <param name="prevRegionHandle"> /// Pass in 0 the first time this method is called. It will be called recursively with the last /// regionhandle tried /// </param> protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { UUID toAgentID = new UUID(im.toAgentID); PresenceInfo upd = null; bool lookupAgent = false; lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { upd = new PresenceInfo(); upd.RegionID = m_UserRegionMap[toAgentID]; // We need to compare the current regionhandle with the previous region handle // or the recursive loop will never end because it will never try to lookup the agent again if (prevRegionID == upd.RegionID) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentInRegionMap. prevRegion==upd.Region settingLookupAgentTrue, agentID={1}, regionID={2}", LogHeader, toAgentID, prevRegionID); lookupAgent = true; } } else { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: agentNOTInRegionMap. setting LookupAgentTrue", LogHeader); lookupAgent = true; } } // Are we needing to look-up an agent? if (lookupAgent) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: lookupAgent IS TRUE", LogHeader); // Non-cached user agent lookup. PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) { foreach (PresenceInfo p in presences) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: got presences. p.RegionID={1}", LogHeader, p.RegionID); // Sometimes we get more than 1 session querying a single agent ID! Filter for the correct agent ID. if (p.UserID == toAgentID.ToString() && p.RegionID != UUID.Zero) { upd = p; break; } } } if (upd != null) { // check if we've tried this before.. // This is one way to end the recursive loop // if (upd.RegionID == prevRegionID) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: regionID==prevRegionID: regionID={1}, agentID={2}", LogHeader, prevRegionID, toAgentID); HandleUndeliveredMessage(im, result); return; } } else { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); m_log.DebugFormat("{0} Unable to deliver instant message: lookupAgent=true, upd==null, agentID={1}", LogHeader, toAgentID); HandleUndeliveredMessage(im, result); return; } } if (upd != null) { GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, upd.RegionID); if (reginfo != null) { m_log.DebugFormat("{0} SendGridInstMsgViaXMLRPCAsync: regInfoNotNull, regID={1}, regNam={2}, regURI={3}, regPort={4}", LogHeader, reginfo.RegionID, reginfo.RegionName, reginfo.ServerURI, reginfo.HttpPort); Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); // Not actually used anymore, left in for compatibility // Remove at next interface change // msgdata["region_handle"] = 0; bool imresult = doIMSending(reginfo, msgdata); if (imresult) { // IM delivery successful, so store the Agent's location in our local cache. lock (m_UserRegionMap) { if (m_UserRegionMap.ContainsKey(toAgentID)) { m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Updating RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); m_UserRegionMap[toAgentID] = upd.RegionID; } else { m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Add RegionMap: agent={1}, reg={2}", LogHeader, toAgentID, upd.RegionID); m_UserRegionMap.Add(toAgentID, upd.RegionID); } } result(true); } else { // try again, but lookup user this time. // Warning, this must call the Async version // of this method or we'll be making thousands of threads // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync // The version that spawns the thread is SendGridInstantMessageViaXMLRPC // This is recursive!!!!! m_log.DebugFormat("{0} SendGridInstMgsViaXMLRPCAsync: Calling me recursively. region={1}", LogHeader, upd.RegionID); SendGridInstantMessageViaXMLRPCAsync(im, result, upd.RegionID); } } else { m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); m_log.DebugFormat("{0} Unable to deliver instant message: regionInfo==null, lookupAgent={1}, agentid={2}, region={3}", LogHeader, lookupAgent, toAgentID, upd.RegionID); HandleUndeliveredMessage(im, result); } } else { m_log.DebugFormat("{0} Unable to deliver instant message: upd==null, lookupAgent={1}, agentid={2}", LogHeader, lookupAgent, toAgentID); HandleUndeliveredMessage(im, result); } }
public void SendFriendsOnlineIfNeeded(IClientAPI client) { UUID agentID = client.AgentId; if (m_NeedsListOfFriends.Contains(agentID)) { if (!m_Friends.ContainsKey(agentID)) { m_log.DebugFormat("[FRIENDS MODULE]: agent {0} not found in local cache", agentID); return; } // // Send the friends online // List <UUID> online = GetOnlineFriends(agentID); if (online.Count > 0) { m_log.DebugFormat("[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", client.AgentId, client.Scene.RegionInfo.RegionName, online.Count); client.SendAgentOnline(online.ToArray()); } // // Send outstanding friendship offers // if (m_Friends.ContainsKey(agentID)) { List <string> outstanding = new List <string>(); foreach (FriendInfo fi in m_Friends[agentID].Friends) { if (fi.TheirFlags == -1) { outstanding.Add(fi.Friend); } } GridInstantMessage im = new GridInstantMessage(client.Scene, UUID.Zero, "", agentID, (byte)InstantMessageDialog.FriendshipOffered, "Will you be my friend?", true, Vector3.Zero); foreach (string fid in outstanding) { try { im.fromAgentID = new Guid(fid); } catch { continue; } UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, new UUID(im.fromAgentID)); im.fromAgentName = account.FirstName + " " + account.LastName; PresenceInfo presence = null; PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); if (presences != null && presences.Length > 0) { presence = presences[0]; } if (presence != null) { im.offline = 0; } im.imSessionID = im.fromAgentID; // Finally LocalFriendshipOffered(agentID, im); } } lock (m_NeedsListOfFriends) m_NeedsListOfFriends.Remove(agentID); } }
public PresenceInfo[] GetAgents(string[] userIDs) { List<PresenceInfo> info = new List<PresenceInfo>(); foreach (string userIDStr in userIDs) { PresenceData[] data = m_Database.Get("UserID", userIDStr); foreach (PresenceData d in data) { PresenceInfo ret = new PresenceInfo(); ret.UserID = d.UserID; ret.RegionID = d.RegionID; info.Add(ret); } // m_log.DebugFormat( // "[PRESENCE SERVICE]: GetAgents for {0} found {1} presences", userIDStr, data.Length); } return info.ToArray(); }
public PresenceInfo GetAgent(UUID sessionID) { Dictionary<string, object> sendData = new Dictionary<string, object>(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); sendData["METHOD"] = "getagent"; sendData["SessionID"] = sessionID.ToString(); string reply = string.Empty; string reqString = WebUtils.BuildQueryString(sendData); // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); try { List<string> serverURIs = m_registry.RequestModuleInterface<IConfigurationService>().FindValueOf("PresenceServerURI"); foreach (string m_ServerURI in serverURIs) { reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/presence", reqString); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply"); return null; } } } catch (Exception e) { m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message); } Dictionary<string, object> replyData = WebUtils.ParseXmlResponse(reply); PresenceInfo pinfo = null; if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) { if (replyData["result"] is Dictionary<string, object>) { pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]); } } return pinfo; }
private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse) { if (sessionResponse == null) return null; PresenceInfo info = new PresenceInfo(); info.UserID = sessionResponse["UserID"].AsUUID().ToString(); info.RegionID = sessionResponse["SceneID"].AsUUID(); return info; }
private void FillOutHomeData(PresenceInfo pinfo, GridRegion home) { int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize; if (home != null) { x = home.RegionLocX; y = home.RegionLocY; } Home = string.Format( "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}", x, y, pinfo.HomePosition.X, pinfo.HomePosition.Y, pinfo.HomePosition.Z, pinfo.HomeLookAt.X, pinfo.HomeLookAt.Y, pinfo.HomeLookAt.Z); }
public void SendMessageToGroup( GridInstantMessage im, UUID groupID, UUID sendingAgentForGroupCalls, Func <GroupMembersData, bool> sendCondition) { int requestStartTick = Environment.TickCount; UUID fromAgentID = new UUID(im.fromAgentID); // Unlike current XmlRpcGroups, Groups V2 can accept UUID.Zero when a perms check for the requesting agent // is not necessary. List <GroupMembersData> groupMembers = m_groupData.GetGroupMembers(UUID.Zero.ToString(), groupID); int groupMembersCount = groupMembers.Count; PresenceInfo[] onlineAgents = null; // In V2 we always only send to online members. // Sending to offline members is not an option. // We cache in order not to overwhelm the presence service on large grids with many groups. This does // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. // (assuming this is the same across all grid simulators). if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) { string[] t1 = groupMembers.ConvertAll <string>(gmd => gmd.AgentID.ToString()).ToArray(); onlineAgents = m_presenceService.GetAgents(t1); m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); } HashSet <string> onlineAgentsUuidSet = new HashSet <string>(); Array.ForEach <PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); // if (m_debugEnabled) // m_log.DebugFormat( // "[Groups.Messaging]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", // groupID, groupMembersCount, groupMembers.Count()); im.imSessionID = groupID.Guid; im.fromGroup = true; IClientAPI thisClient = GetActiveClient(fromAgentID); if (thisClient != null) { im.RegionID = thisClient.Scene.RegionInfo.RegionID.Guid; } if ((im.binaryBucket == null) || (im.binaryBucket.Length == 0) || ((im.binaryBucket.Length == 1 && im.binaryBucket[0] == 0))) { ExtendedGroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero.ToString(), groupID, null); if (groupInfo != null) { im.binaryBucket = Util.StringToBytes256(groupInfo.GroupName); } } // Send to self first of all im.toAgentID = im.fromAgentID; im.fromGroup = true; ProcessMessageFromGroupSession(im); List <UUID> regions = new List <UUID>(); List <UUID> clientsAlreadySent = new List <UUID>(); // Then send to everybody else foreach (GroupMembersData member in groupMembers) { if (member.AgentID.Guid == im.fromAgentID) { continue; } if (clientsAlreadySent.Contains(member.AgentID)) { continue; } clientsAlreadySent.Add(member.AgentID); if (sendCondition != null) { if (!sendCondition(member)) { if (m_debugEnabled) { m_log.DebugFormat( "[Groups.Messaging]: Not sending to {0} as they do not fulfill send condition", member.AgentID); } continue; } } else if (hasAgentDroppedGroupChatSession(member.AgentID.ToString(), groupID)) { // Don't deliver messages to people who have dropped this session if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: {0} has dropped session, not delivering to them", member.AgentID); } continue; } im.toAgentID = member.AgentID.Guid; IClientAPI client = GetActiveClient(member.AgentID); if (client == null) { // If they're not local, forward across the grid // BUT do it only once per region, please! Sim would be even better! if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: Delivering to {0} via Grid", member.AgentID); } bool reallySend = true; if (onlineAgents != null) { PresenceInfo presence = onlineAgents.First(p => p.UserID == member.AgentID.ToString()); if (regions.Contains(presence.RegionID)) { reallySend = false; } else { regions.Add(presence.RegionID); } } if (reallySend) { // We have to create a new IM structure because the transfer module // uses async send GridInstantMessage msg = new GridInstantMessage(im, true); m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); } } else { // Deliver locally, directly if (m_debugEnabled) { m_log.DebugFormat("[Groups.Messaging]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); } ProcessMessageFromGroupSession(im); } } if (m_debugEnabled) { m_log.DebugFormat( "[Groups.Messaging]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } }
public PresenceInfo GetAgent(UUID sessionID) { PresenceInfo ret = new PresenceInfo(); PresenceData data = m_Database.Get(sessionID); if (data == null) return null; if (m_checkLastSeen && int.Parse(data.Data["LastSeen"]) + (1000 * 60 * 60) < Util.UnixTimeSinceEpoch()) { m_log.Warn("[PresenceService]: Found a user (" + data.UserID + ") that was not seen within the last hour! Logging them out."); LogoutAgent(sessionID); return null; } ret.UserID = data.UserID; ret.RegionID = data.RegionID; return ret; }
public PresenceInfo[] GetAgents(string[] userIDs) { Dictionary<string, object> sendData = new Dictionary<string, object>(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); sendData["METHOD"] = "getagents"; sendData["uuids"] = new List<string>(userIDs); string reply = string.Empty; string reqString = WebUtils.BuildQueryString(sendData); //m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); try { List<string> serverURIs = m_registry.RequestModuleInterface<IConfigurationService>().FindValueOf(userIDs[0], "PresenceServerURI"); foreach (string m_ServerURI in serverURIs) { reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/presence", reqString); if (reply == null || (reply != null && reply == string.Empty)) { m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null or empty reply"); return null; } } } catch (Exception e) { m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message); } List<PresenceInfo> rinfos = new List<PresenceInfo>(); Dictionary<string, object> replyData = WebUtils.ParseXmlResponse(reply); if (replyData != null) { if (replyData.ContainsKey("result") && (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure")) { return new PresenceInfo[0]; } Dictionary<string, object>.ValueCollection pinfosList = replyData.Values; //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count); foreach (object presence in pinfosList) { if (presence is Dictionary<string, object>) { PresenceInfo pinfo = new PresenceInfo((Dictionary<string, object>)presence); rinfos.Add(pinfo); } else m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received invalid response type {0}", presence.GetType()); } } else m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null response"); return rinfos.ToArray(); }
public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, PresenceInfo pinfo, GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, string where, string startlocation, Vector3 position, Vector3 lookAt, string message, GridRegion home, IPEndPoint clientIP) : this() { FillOutInventoryData(invSkel, libService); CircuitCode = (int)aCircuit.circuitcode; Lastname = account.LastName; Firstname = account.FirstName; AgentID = account.PrincipalID; SessionID = aCircuit.SessionID; SecureSessionID = aCircuit.SecureSessionID; Message = message; BuddList = ConvertFriendListItem(friendsList); StartLocation = where; FillOutHomeData(pinfo, home); LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z); FillOutRegionData(destination); FillOutSeedCap(aCircuit, destination, clientIP); }