/// <summary> /// Enqueues a presence update, sending info about user 'talkingAbout' to user 'receiver'. /// </summary> /// <param name="talkingAbout">We are sending presence information about this user.</param> /// <param name="receiver">We are sending the presence update to this user</param> private void enqueuePresenceUpdate(UserPresenceData talkingAbout, UserPresenceData receiver) { UserAgentData p2Handle = m_userDataBaseService.GetUserAgentData(receiver.agentData.AgentID); if (p2Handle != null) { if (receiver.lookupUserRegionYN) { // this is incomplete, just filling in one field, but just calling // m_regionModule.GetRegionInfo (again) here isn't a solution. // Maybe we should be treating it as if p2Handle got a null above, // and asynchronously trying to update the regionData again later. receiver.regionData.regionHandle = p2Handle.Handle; } else { receiver.lookupUserRegionYN = true; // TODO Huh? } PresenceInformer friendlistupdater = new PresenceInformer(); friendlistupdater.presence1 = talkingAbout; friendlistupdater.presence2 = receiver; friendlistupdater.OnGetRegionData += m_regionModule.GetRegionInfo; friendlistupdater.OnDone += PresenceUpdateDone; WaitCallback cb = new WaitCallback(friendlistupdater.go); ThreadPool.QueueUserWorkItem(cb); } else { m_log.WarnFormat("[PRESENCE]: no data found for user {0}", receiver.agentData.AgentID); // Skip because we can't find any data on the user } }
/// <summary> /// Does the necessary work to subscribe one agent to another's presence notifications /// Gets called by ProcessFriendListSubscriptions. You shouldn't call this directly /// unless you know what you're doing /// </summary> /// <param name="userpresence">P1</param> /// <param name="friendpresence">P2</param> /// <param name="uFriendListItem"></param> private void SubscribeToPresenceUpdates(UserPresenceData userpresence, UserPresenceData friendpresence, FriendListItem uFriendListItem) { // Can the friend see me online? if ((uFriendListItem.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) { // tell user to update friend about user's presence changes if (!userpresence.subscriptionData.Contains(friendpresence.agentData.AgentID)) { userpresence.subscriptionData.Add(friendpresence.agentData.AgentID); } // send an update about user's presence to the friend enqueuePresenceUpdate(userpresence, friendpresence); } // Can I see the friend online? if ((uFriendListItem.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) { // tell friend to update user about friend's presence changes if (!friendpresence.subscriptionData.Contains(userpresence.agentData.AgentID)) { friendpresence.subscriptionData.Add(userpresence.agentData.AgentID); } // send an update about friend's presence to user. enqueuePresenceUpdate(friendpresence, userpresence); } }
/// <summary> /// Enqueues a presence update, sending info about user 'talkingAbout' to user 'receiver'. /// </summary> /// <param name="talkingAbout">We are sending presence information about this user.</param> /// <param name="receiver">We are sending the presence update to this user</param> private void enqueuePresenceUpdate(UserPresenceData talkingAbout, UserPresenceData receiver) { UserAgentData p2Handle = m_userDataBaseService.GetUserAgentData(receiver.agentData.AgentID); if (p2Handle != null) { if (receiver.lookupUserRegionYN) { receiver.regionData.regionHandle = p2Handle.Handle; } else { receiver.lookupUserRegionYN = true; // TODO Huh? } PresenceInformer friendlistupdater = new PresenceInformer(); friendlistupdater.presence1 = talkingAbout; friendlistupdater.presence2 = receiver; friendlistupdater.OnGetRegionData += m_regionModule.GetRegionInfo; friendlistupdater.OnDone += PresenceUpdateDone; WaitCallback cb = new WaitCallback(friendlistupdater.go); ThreadPool.QueueUserWorkItem(cb); } else { m_log.WarnFormat("no data found for user {0}", receiver.agentData.AgentID); // Skip because we can't find any data on the user } }
/// <summary> /// Informs a region about an Agent /// </summary> /// <param name="TalkingAbout">User to talk about</param> /// <param name="UserToUpdate">User we're sending this too (contains the region)</param> public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) { // TODO: Fill in pertenant Presence Data from 'TalkingAbout' RegionProfileData whichRegion = new RegionProfileData(); if (lookupRegion) { handlerGetRegionData = OnGetRegionData; if (handlerGetRegionData != null) { whichRegion = handlerGetRegionData(UserToUpdate.regionData.regionHandle); } //RegionProfileData rp = RegionProfileData.RequestSimProfileData(UserToUpdate.regionData.regionHandle, gridserverurl, gridserversendkey, gridserverrecvkey); //whichRegion = rp; } else { whichRegion = UserToUpdate.regionData; } //whichRegion.httpServerURI if (whichRegion != null) { Hashtable PresenceParams = new Hashtable(); PresenceParams.Add("agent_id",TalkingAbout.agentData.AgentID.ToString()); PresenceParams.Add("notify_id",UserToUpdate.agentData.AgentID.ToString()); if (TalkingAbout.OnlineYN) PresenceParams.Add("status","TRUE"); else PresenceParams.Add("status","FALSE"); ArrayList SendParams = new ArrayList(); SendParams.Add(PresenceParams); m_log.InfoFormat("[PRESENCE]: Informing {0}@{1} at {2} about {3}", TalkingAbout.agentData.firstname + " " + TalkingAbout.agentData.lastname, whichRegion.regionName, whichRegion.httpServerURI, UserToUpdate.agentData.firstname + " " + UserToUpdate.agentData.lastname); // Send XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); try { // XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); RegionReq.Send(whichRegion.httpServerURI, 6000); } catch (WebException) { m_log.WarnFormat("[INFORM]: failed notifying region {0} containing user {1} about {2}", whichRegion.regionName, UserToUpdate.agentData.firstname + " " + UserToUpdate.agentData.lastname, TalkingAbout.agentData.firstname + " " + TalkingAbout.agentData.lastname); } } else { m_log.Info("[PRESENCEUPDATER]: Region data was null skipping"); } handlerDone = OnDone; if (handlerDone != null) { handlerDone(this); } }
/// <summary> /// UserServer sends an expect_user method /// this handles the method and provisions the /// necessary info for presence to work /// </summary> /// <param name="request">UserServer Data</param> /// <returns></returns> public XmlRpcResponse UserLoggedOn(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable requestData = (Hashtable)request.Params[0]; AgentCircuitData agentData = new AgentCircuitData(); agentData.SessionID = new UUID((string)requestData["sessionid"]); agentData.SecureSessionID = new UUID((string)requestData["secure_session_id"]); agentData.FirstName = (string)requestData["firstname"]; agentData.LastName = (string)requestData["lastname"]; agentData.AgentID = new UUID((string)requestData["agentid"]); agentData.CircuitCode = Convert.ToUInt32(requestData["circuit_code"]); agentData.CapsPath = (string)requestData["caps_path"]; if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1")) { agentData.child = true; } else { agentData.startpos = new Vector3(Convert.ToSingle(requestData["positionx"]), Convert.ToSingle(requestData["positiony"]), Convert.ToSingle(requestData["positionz"])); agentData.child = false; } ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); m_log.InfoFormat("[LOGON]: User {0} {1} logged into region {2} as {3} agent, building indexes for user", agentData.FirstName, agentData.LastName, regionHandle, agentData.child ? "child" : "root"); UserPresenceData up = new UserPresenceData(); up.agentData = agentData; up.friendData = GetUserFriendList(agentData.AgentID); // Null reference exception in een by Vinhold on GW grid in enqueuePresenceUpdate with a null receiver.regionData // Should never be null but GetRegionInfo() can return that. Probably crash/quit/disconnect during login. RegionProfileData regionData = m_regionModule.GetRegionInfo(regionHandle); if (regionData != null) // else go with non-null default UserPresenceData.regionData { up.regionData = regionData; up.OnlineYN = true; up.lookupUserRegionYN = false; ProcessFriendListSubscriptions(up); } return(new XmlRpcResponse()); }
/// <summary> /// Logoff Processor. Call this to clean up agent presence data and send logoff presence notifications /// </summary> /// <param name="AgentID"></param> private void ProcessLogOff(UUID AgentID) { m_log.Info("[LOGOFF]: Processing Logoff"); UserPresenceData userPresence = null; lock (m_presences) { m_presences.TryGetValue(AgentID, out userPresence); } if (userPresence != null) // found the user { List <UUID> AgentsNeedingNotification = userPresence.subscriptionData; userPresence.OnlineYN = false; for (int i = 0; i < AgentsNeedingNotification.Count; i++) { UserPresenceData friendPresence = null; lock (m_presences) { m_presences.TryGetValue(AgentsNeedingNotification[i], out friendPresence); } // This might need to be enumerated and checked before we try to remove it. if (friendPresence != null) { lock (friendPresence) { // no updates for this user anymore friendPresence.subscriptionData.Remove(AgentID); // set user's entry in the friend's list to offline (if it exists) if (friendPresence.friendData.ContainsKey(AgentID)) { friendPresence.friendData[AgentID].onlinestatus = false; } } enqueuePresenceUpdate(userPresence, friendPresence); } } } }
/// <summary> /// UserServer sends an expect_user method /// this handles the method and provisions the /// necessary info for presence to work /// </summary> /// <param name="request">UserServer Data</param> /// <returns></returns> public XmlRpcResponse UserLoggedOn(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable requestData = (Hashtable)request.Params[0]; AgentCircuitData agentData = new AgentCircuitData(); agentData.SessionID = new UUID((string)requestData["sessionid"]); agentData.SecureSessionID = new UUID((string)requestData["secure_session_id"]); agentData.firstname = (string)requestData["firstname"]; agentData.lastname = (string)requestData["lastname"]; agentData.AgentID = new UUID((string)requestData["agentid"]); agentData.circuitcode = Convert.ToUInt32(requestData["circuit_code"]); agentData.CapsPath = (string)requestData["caps_path"]; if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1")) { agentData.child = true; } else { agentData.startpos = new Vector3(Convert.ToSingle(requestData["positionx"]), Convert.ToSingle(requestData["positiony"]), Convert.ToSingle(requestData["positionz"])); agentData.child = false; } ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); m_log.InfoFormat("[LOGON]: User {0} {1} logged into region {2} as {3} agent, building indexes for user", agentData.firstname, agentData.lastname, regionHandle, agentData.child ? "child" : "root"); UserPresenceData up = new UserPresenceData(); up.agentData = agentData; up.friendData = GetUserFriendList(agentData.AgentID); up.regionData = m_regionModule.GetRegionInfo(regionHandle); up.OnlineYN = true; up.lookupUserRegionYN = false; ProcessFriendListSubscriptions(up); return(new XmlRpcResponse()); }
/// <summary> /// Process Friendlist subscriptions for a user /// The login method calls this for a User /// </summary> /// <param name="userpresence">The Agent we're processing the friendlist subscriptions for</param> private void ProcessFriendListSubscriptions(UserPresenceData userpresence) { lock (m_presences) { m_presences[userpresence.agentData.AgentID] = userpresence; } Dictionary <UUID, FriendListItem> uFriendList = userpresence.friendData; foreach (KeyValuePair <UUID, FriendListItem> pair in uFriendList) { UserPresenceData friendup = null; lock (m_presences) { m_presences.TryGetValue(pair.Key, out friendup); } if (friendup != null) { SubscribeToPresenceUpdates(userpresence, friendup, pair.Value); } } }
/// <summary> /// Informs a region about an Agent /// </summary> /// <param name="TalkingAbout">User to talk about</param> /// <param name="UserToUpdate">User we're sending this too (contains the region)</param> public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) { // TODO: Fill in pertenant Presence Data from 'TalkingAbout' RegionProfileData whichRegion = new RegionProfileData(); if (lookupRegion) { handlerGetRegionData = OnGetRegionData; if (handlerGetRegionData != null) { whichRegion = handlerGetRegionData(UserToUpdate.regionData.regionHandle); } //RegionProfileData rp = RegionProfileData.RequestSimProfileData(UserToUpdate.regionData.regionHandle, gridserverurl, gridserversendkey, gridserverrecvkey); //whichRegion = rp; } else { whichRegion = UserToUpdate.regionData; } //whichRegion.httpServerURI if (whichRegion != null) { Hashtable PresenceParams = new Hashtable(); PresenceParams.Add("agent_id", TalkingAbout.agentData.AgentID.ToString()); PresenceParams.Add("notify_id", UserToUpdate.agentData.AgentID.ToString()); if (TalkingAbout.OnlineYN) { PresenceParams.Add("status", "TRUE"); } else { PresenceParams.Add("status", "FALSE"); } ArrayList SendParams = new ArrayList(); SendParams.Add(PresenceParams); m_log.InfoFormat("[PRESENCE]: Informing {0}@{1} at {2} about {3}", TalkingAbout.agentData.firstname + " " + TalkingAbout.agentData.lastname, whichRegion.regionName, whichRegion.httpServerURI, UserToUpdate.agentData.firstname + " " + UserToUpdate.agentData.lastname); // Send XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); try { // XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); RegionReq.Send(whichRegion.httpServerURI, 6000); } catch (WebException) { m_log.WarnFormat("[INFORM]: failed notifying region {0} containing user {1} about {2}", whichRegion.regionName, UserToUpdate.agentData.firstname + " " + UserToUpdate.agentData.lastname, TalkingAbout.agentData.firstname + " " + TalkingAbout.agentData.lastname); } } else { m_log.Info("[PRESENCEUPDATER]: Region data was null skipping"); } handlerDone = OnDone; if (handlerDone != null) { handlerDone(this); } }
/// <summary> /// UserServer sends an expect_user method /// this handles the method and provisions the /// necessary info for presence to work /// </summary> /// <param name="request">UserServer Data</param> /// <returns></returns> public XmlRpcResponse UserLoggedOn(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable requestData = (Hashtable)request.Params[0]; AgentCircuitData agentData = new AgentCircuitData(); agentData.SessionID = new UUID((string)requestData["sessionid"]); agentData.SecureSessionID = new UUID((string)requestData["secure_session_id"]); agentData.FirstName = (string)requestData["firstname"]; agentData.LastName = (string)requestData["lastname"]; agentData.AgentID = new UUID((string)requestData["agentid"]); agentData.CircuitCode = Convert.ToUInt32(requestData["circuit_code"]); agentData.CapsPath = (string)requestData["caps_path"]; if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1")) { agentData.child = true; } else { agentData.startpos = new Vector3(Convert.ToSingle(requestData["positionx"]), Convert.ToSingle(requestData["positiony"]), Convert.ToSingle(requestData["positionz"])); agentData.child = false; } ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); m_log.InfoFormat("[LOGON]: User {0} {1} logged into region {2} as {3} agent, building indexes for user", agentData.FirstName, agentData.LastName, regionHandle, agentData.child ? "child" : "root"); UserPresenceData up = new UserPresenceData(); up.agentData = agentData; up.friendData = GetUserFriendList(agentData.AgentID); up.regionData = m_regionModule.GetRegionInfo(regionHandle); up.OnlineYN = true; up.lookupUserRegionYN = false; ProcessFriendListSubscriptions(up); return new XmlRpcResponse(); }
/// <summary> /// Enqueues a presence update, sending info about user 'talkingAbout' to user 'receiver'. /// </summary> /// <param name="talkingAbout">We are sending presence information about this user.</param> /// <param name="receiver">We are sending the presence update to this user</param> private void enqueuePresenceUpdate(UserPresenceData talkingAbout, UserPresenceData receiver) { UserAgentData p2Handle = m_userDataBaseService.GetUserAgentData(receiver.agentData.AgentID); if (p2Handle != null) { if (receiver.lookupUserRegionYN) { receiver.regionData.regionHandle = p2Handle.Handle; } else { receiver.lookupUserRegionYN = true; // TODO Huh? } PresenceInformer friendlistupdater = new PresenceInformer(); friendlistupdater.presence1 = talkingAbout; friendlistupdater.presence2 = receiver; friendlistupdater.OnGetRegionData += m_regionModule.GetRegionInfo; friendlistupdater.OnDone += PresenceUpdateDone; WaitCallback cb = new WaitCallback(friendlistupdater.go); ThreadPool.QueueUserWorkItem(cb); } else { m_log.WarnFormat("[PRESENCE]: no data found for user {0}", receiver.agentData.AgentID); // Skip because we can't find any data on the user } }
/// <summary> /// Process Friendlist subscriptions for a user /// The login method calls this for a User /// </summary> /// <param name="userpresence">The Agent we're processing the friendlist subscriptions for</param> private void ProcessFriendListSubscriptions(UserPresenceData userpresence) { lock (m_presences) { m_presences[userpresence.agentData.AgentID] = userpresence; } Dictionary<UUID, FriendListItem> uFriendList = userpresence.friendData; foreach (KeyValuePair<UUID, FriendListItem> pair in uFriendList) { UserPresenceData friendup = null; lock (m_presences) { m_presences.TryGetValue(pair.Key, out friendup); } if (friendup != null) { SubscribeToPresenceUpdates(userpresence, friendup, pair.Value); } } }