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);
                }
            }
        }
Exemple #4
0
        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 });
                }
            }
        }
Exemple #7
0
        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);
                    }
                }
            }
        }
Exemple #9
0
        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);
            }
        }
Exemple #10
0
        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);
                    }
                }
            }
        }
Exemple #11
0
        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;
        }
Exemple #12
0
        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);
        }
Exemple #13
0
        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;
        }
Exemple #16
0
        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();
        }
Exemple #18
0
        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);
            }
        }
Exemple #36
0
        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);
            
        }