From 6f00175d891c211adf8dcbb3778f777b0c0749bb Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Sat, 23 Feb 2008 02:51:54 +0000 Subject: [PATCH] * Rex merges, Messaging server --- OpenSim/Grid/MessagingServer/Main.cs | 317 +++--- .../Grid/MessagingServer/MessageService.cs | 958 +++++++++--------- .../Grid/MessagingServer/UserPresenceData.cs | 106 +- 3 files changed, 688 insertions(+), 693 deletions(-) diff --git a/OpenSim/Grid/MessagingServer/Main.cs b/OpenSim/Grid/MessagingServer/Main.cs index 4540621ae4..6ac70f022c 100644 --- a/OpenSim/Grid/MessagingServer/Main.cs +++ b/OpenSim/Grid/MessagingServer/Main.cs @@ -1,160 +1,157 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ - -using System; -using System.Collections.Generic; -using System.IO; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Framework.Console; -using OpenSim.Framework.Servers; - -namespace OpenSim.Grid.MessagingServer -{ - /// - /// - public class OpenMessage_Main : conscmd_callback - { - private MessageServerConfig Cfg; - - //public UserManager m_userManager; - //public UserLoginService m_loginService; - - private LogBase m_console; - private LLUUID m_lastCreatedUser = LLUUID.Random(); - - [STAThread] - public static void Main(string[] args) - { - Console.WriteLine("Launching MessagingServer..."); - - OpenMessage_Main messageserver = new OpenMessage_Main(); - - messageserver.Startup(); - messageserver.Work(); - } - - private OpenMessage_Main() - { - if (!Directory.Exists(Util.logDir())) - { - Directory.CreateDirectory(Util.logDir()); - } - m_console = - new LogBase((Path.Combine(Util.logDir(), "opengrid-messagingserver-console.log")), "OpenMessage", this, true); - MainLog.Instance = m_console; - } - - private void Work() - { - m_console.Notice("Enter help for a list of commands\n"); - - while (true) - { - m_console.MainLogPrompt(); - } - } - - public void Startup() - { - Cfg = new MessageServerConfig("MESSAGING SERVER", (Path.Combine(Util.configDir(), "MessagingServer_Config.xml"))); - - - - MainLog.Instance.Verbose("REGION", "Starting HTTP process"); - BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); - - //httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); - - //httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName); - //httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID); - //httpServer.AddXmlRPCHandler("get_avatar_picker_avatar", m_userManager.XmlRPCGetAvatarPickerAvatar); - //httpServer.AddXmlRPCHandler("add_new_user_friend", m_userManager.XmlRpcResponseXmlRPCAddUserFriend); - //httpServer.AddXmlRPCHandler("remove_user_friend", m_userManager.XmlRpcResponseXmlRPCRemoveUserFriend); - //httpServer.AddXmlRPCHandler("update_user_friend_perms", m_userManager.XmlRpcResponseXmlRPCUpdateUserFriendPerms); - //httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList); - - - //httpServer.AddStreamHandler( - //new RestStreamHandler("DELETE", "/usersessions/", m_userManager.RestDeleteUserSessionMethod)); - - httpServer.Start(); - m_console.Status("SERVER", "Messageserver 0.4 - Startup complete"); - } - - - public void do_create(string what) - { - switch (what) - { - case "user": - - try - { - //userID = - //m_userManager.AddUserProfile(tempfirstname, templastname, tempMD5Passwd, regX, regY); - } catch (Exception ex) - { - m_console.Error("SERVER", "Error creating user: {0}", ex.ToString()); - } - - try - { - //RestObjectPoster.BeginPostObject(m_userManager._config.InventoryUrl + "CreateInventory/", - //userID.UUID); - } - catch (Exception ex) - { - m_console.Error("SERVER", "Error creating inventory for user: {0}", ex.ToString()); - } - // m_lastCreatedUser = userID; - break; - } - } - - public void RunCmd(string cmd, string[] cmdparams) - { - switch (cmd) - { - case "help": - m_console.Notice("shutdown - shutdown the message server (USE CAUTION!)"); - break; - - case "shutdown": - m_console.Close(); - Environment.Exit(0); - break; - } - } - - public void Show(string ShowWhat) - { - } - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; + +namespace OpenSim.Grid.MessagingServer +{ + /// + /// + public class OpenMessage_Main : BaseOpenSimServer, conscmd_callback + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MessageServerConfig Cfg; + + //public UserManager m_userManager; + //public UserLoginService m_loginService; + + private LLUUID m_lastCreatedUser = LLUUID.Random(); + + [STAThread] + public static void Main(string[] args) + { + log4net.Config.XmlConfigurator.Configure(); + + m_log.Info("Launching MessagingServer..."); + + OpenMessage_Main messageserver = new OpenMessage_Main(); + + messageserver.Startup(); + messageserver.Work(); + } + + private OpenMessage_Main() + { + m_console = new ConsoleBase("OpenMessage", this); + MainConsole.Instance = m_console; + } + + private void Work() + { + m_console.Notice("Enter help for a list of commands\n"); + + while (true) + { + m_console.Prompt(); + } + } + + public void Startup() + { + Cfg = new MessageServerConfig("MESSAGING SERVER", (Path.Combine(Util.configDir(), "MessagingServer_Config.xml"))); + + m_log.Info("[REGION]: Starting HTTP process"); + BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); + + //httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); + + //httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName); + //httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID); + //httpServer.AddXmlRPCHandler("get_avatar_picker_avatar", m_userManager.XmlRPCGetAvatarPickerAvatar); + //httpServer.AddXmlRPCHandler("add_new_user_friend", m_userManager.XmlRpcResponseXmlRPCAddUserFriend); + //httpServer.AddXmlRPCHandler("remove_user_friend", m_userManager.XmlRpcResponseXmlRPCRemoveUserFriend); + //httpServer.AddXmlRPCHandler("update_user_friend_perms", m_userManager.XmlRpcResponseXmlRPCUpdateUserFriendPerms); + //httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList); + + + //httpServer.AddStreamHandler( + //new RestStreamHandler("DELETE", "/usersessions/", m_userManager.RestDeleteUserSessionMethod)); + + httpServer.Start(); + m_log.Info("[SERVER]: Messageserver 0.5 - Startup complete"); + } + + public void do_create(string what) + { + switch (what) + { + case "user": + + try + { + //userID = + //m_userManager.AddUserProfile(tempfirstname, templastname, tempMD5Passwd, regX, regY); + } catch (Exception ex) + { + m_console.Error("[SERVER]: Error creating user: {0}", ex.ToString()); + } + + try + { + //RestObjectPoster.BeginPostObject(m_userManager._config.InventoryUrl + "CreateInventory/", + //userID.UUID); + } + catch (Exception ex) + { + m_console.Error("[SERVER]: Error creating inventory for user: {0}", ex.ToString()); + } + // m_lastCreatedUser = userID; + break; + } + } + + public override void RunCmd(string cmd, string[] cmdparams) + { + base.RunCmd(cmd, cmdparams); + + switch (cmd) + { + case "help": + m_console.Notice("shutdown - shutdown the message server (USE CAUTION!)"); + break; + + case "shutdown": + m_console.Close(); + Environment.Exit(0); + break; + } + } + + public void Show(string ShowWhat) + { + } + } +} diff --git a/OpenSim/Grid/MessagingServer/MessageService.cs b/OpenSim/Grid/MessagingServer/MessageService.cs index 14615205dc..059a6b0932 100644 --- a/OpenSim/Grid/MessagingServer/MessageService.cs +++ b/OpenSim/Grid/MessagingServer/MessageService.cs @@ -1,480 +1,478 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Net; -using System.Net.Sockets; -using System.Collections; -using System.Collections.Generic; -//using System.Xml; -using libsecondlife; -using Nwc.XmlRpc; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Framework.Data; -using OpenSim.Framework.Servers; -using FriendRights = libsecondlife.FriendRights; - -namespace OpenSim.Grid.MessagingServer -{ - public class MessageService - { - private LogBase m_log; - private MessageServerConfig m_cfg; - - //A hashtable of all current presences this server knows about - private Hashtable m_presences = new Hashtable(); - - //a hashtable of all current regions this server knows about - private Hashtable m_regionInfoCache = new Hashtable(); - - //A hashtable containing lists of UUIDs keyed by UUID for fast backreferencing - private Hashtable m_presence_BackReferences = new Hashtable(); - - // Hashtable containing work units that need to be processed - private Hashtable m_unProcessedWorkUnits = new Hashtable(); - - - public MessageService(LogBase log, MessageServerConfig cfg) - { - m_log = log; - m_cfg = cfg; - } - - - #region RegionComms Methods - - /// - /// Informs a region about an Agent - /// - /// User to talk about - /// User we're sending this too (contains the region) - public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) - { - // TODO: Fill in pertenant Presence Data from 'TalkingAbout' - - RegionProfileData whichRegion = UserToUpdate.regionData; - //whichRegion.httpServerURI - - Hashtable PresenceParams = new Hashtable(); - ArrayList SendParams = new ArrayList(); - SendParams.Add(PresenceParams); - - MainLog.Instance.Verbose("PRESENCE", "Informing " + whichRegion.regionName + " at " + whichRegion.httpServerURI); - // Send - XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); - XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); - } - - - #endregion - - #region FriendList Methods - - - /// - /// Process Friendlist subscriptions for a user - /// The login method calls this for a User - /// - /// The Agent we're processing the friendlist subscriptions - public void ProcessFriendListSubscriptions(UserPresenceData userpresence) - { - List uFriendList = userpresence.friendData; - for (int i = 0; i < uFriendList.Count; i++) - { - m_presence_BackReferences.Add(userpresence.agentData.AgentID, uFriendList[i].Friend); - m_presence_BackReferences.Add(uFriendList[i].Friend, userpresence.agentData.AgentID); - - if (m_presences.Contains(uFriendList[i].Friend)) - { - UserPresenceData friendup = (UserPresenceData)m_presences[uFriendList[i]]; - // Add backreference - - SubscribeToPresenceUpdates(userpresence, friendup, uFriendList[i],i); - } - } - - m_presences.Add(userpresence.agentData.AgentID, userpresence); - } - - /// - /// 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 - /// - /// P1 - /// P2 - /// - /// - public void SubscribeToPresenceUpdates(UserPresenceData userpresence, UserPresenceData friendpresence, - FriendListItem uFriendListItem, int uFriendListIndex) - { - - if ((uFriendListItem.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) - { - // Subscribe and Send Out updates - if (!friendpresence.subscriptionData.Contains(friendpresence.agentData.AgentID)) - { - userpresence.subscriptionData.Add(friendpresence.agentData.AgentID); - //Send Region Notice.... - - } - else - { - // we need to send out online status update, but the user is already subscribed - - } - SendRegionPresenceUpdate(friendpresence, userpresence); - } - if ((uFriendListItem.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) - { - if (!friendpresence.subscriptionData.Contains(userpresence.agentData.AgentID)) - { - friendpresence.subscriptionData.Add(userpresence.agentData.AgentID); - //Send Region Notice.... - } - else - { - // we need to send out online status update, but the user is already subscribed - - } - SendRegionPresenceUpdate(userpresence, friendpresence); - } - - } - - - /// - /// Adds a backreference so presence specific data doesn't have to be - /// enumerated for each logged in user every time someone logs on or off. - /// - /// - /// - public void addBackReference(LLUUID agentID, LLUUID friendID) - { - if (m_presence_BackReferences.Contains(friendID)) - { - List presenseBackReferences = (List)m_presence_BackReferences[friendID]; - if (!presenseBackReferences.Contains(agentID)) - { - presenseBackReferences.Add(agentID); - } - m_presence_BackReferences[friendID] = presenseBackReferences; - } - else - { - List presenceBackReferences = new List(); - presenceBackReferences.Add(agentID); - m_presence_BackReferences[friendID] = presenceBackReferences; - } - } - - /// - /// Removes a backreference to free up some memory - /// - /// - /// - public void removeBackReference(LLUUID agentID, LLUUID friendID) - { - if (m_presence_BackReferences.Contains(friendID)) - { - List presenseBackReferences = (List)m_presence_BackReferences[friendID]; - if (presenseBackReferences.Contains(agentID)) - { - presenseBackReferences.Remove(agentID); - } - - // If there are no more backreferences for this agent, - // remove it to free up memory. - if (presenseBackReferences.Count == 0) - { - m_presence_BackReferences.Remove(agentID); - } - } - } - /// - /// Logoff Processor. Call this to clean up agent presence data and send logoff presence notifications - /// - /// - private void ProcessLogOff(LLUUID AgentID) - { - if (m_presences.Contains(AgentID)) - { - UserPresenceData AgentData = (UserPresenceData)m_presences[AgentID]; - - if (m_presence_BackReferences.Contains(AgentID)) - { - List AgentsNeedingNotification = (List)m_presence_BackReferences[AgentID]; - for (int i = 0; i < AgentsNeedingNotification.Count; i++) - { - // TODO: Do Region Notifications - if (m_presences.Contains(AgentsNeedingNotification[i])) - { - UserPresenceData friendd = (UserPresenceData)m_presences[AgentsNeedingNotification[i]]; - - // This might need to be enumerated and checked before we try to remove it. - friendd.subscriptionData.Remove(AgentID); - - List fl = friendd.friendData; - for (int j = 0; j < fl.Count; j++) - { - if (fl[j].Friend == AgentID) - { - fl[j].onlinestatus = false; - } - - } - friendd.friendData = fl; - - SendRegionPresenceUpdate(AgentData, friendd); - - } - removeBackReference(AgentID, AgentsNeedingNotification[i]); - - } - } - } - } - - - #endregion - - #region UserServer Comms - - /// - /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner - /// - /// The agent that we're retreiving the friends Data. - public List GetUserFriendList(LLUUID friendlistowner) - { - List buddylist = new List(); - - try - { - Hashtable param = new Hashtable(); - param["ownerID"] = friendlistowner.UUID.ToString(); - - IList parameters = new ArrayList(); - parameters.Add(param); - XmlRpcRequest req = new XmlRpcRequest("get_user_friend_list", parameters); - XmlRpcResponse resp = req.Send(m_cfg.UserServerURL, 3000); - Hashtable respData = (Hashtable)resp.Value; - - if (respData.Contains("avcount")) - { - buddylist = ConvertXMLRPCDataToFriendListItemList(respData); - } - - } - catch (WebException e) - { - MainLog.Instance.Warn("Error when trying to fetch Avatar's friends list: " + - e.Message); - // Return Empty list (no friends) - } - return buddylist; - - } - - /// - /// Converts XMLRPC Friend List to FriendListItem Object - /// - /// XMLRPC response data Hashtable - /// - public List ConvertXMLRPCDataToFriendListItemList(Hashtable data) - { - List buddylist = new List(); - int buddycount = Convert.ToInt32((string)data["avcount"]); - - - for (int i = 0; i < buddycount; i++) - { - FriendListItem buddylistitem = new FriendListItem(); - - buddylistitem.FriendListOwner = new LLUUID((string)data["ownerID" + i.ToString()]); - buddylistitem.Friend = new LLUUID((string)data["friendID" + i.ToString()]); - buddylistitem.FriendListOwnerPerms = (uint)Convert.ToInt32((string)data["ownerPerms" + i.ToString()]); - buddylistitem.FriendPerms = (uint)Convert.ToInt32((string)data["friendPerms" + i.ToString()]); - - buddylist.Add(buddylistitem); - } - - - return buddylist; - } - /// - /// UserServer sends an expect_user method - /// this handles the method and provisions the - /// necessary info for presence to work - /// - /// UserServer Data - /// - public XmlRpcResponse UserLoggedOn(XmlRpcRequest request) - { - - Hashtable requestData = (Hashtable)request.Params[0]; - AgentCircuitData agentData = new AgentCircuitData(); - agentData.SessionID = new LLUUID((string)requestData["session_id"]); - agentData.SecureSessionID = new LLUUID((string)requestData["secure_session_id"]); - agentData.firstname = (string)requestData["firstname"]; - agentData.lastname = (string)requestData["lastname"]; - agentData.AgentID = new LLUUID((string)requestData["agent_id"]); - 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 LLVector3(Convert.ToUInt32(requestData["startpos_x"]), - Convert.ToUInt32(requestData["startpos_y"]), - Convert.ToUInt32(requestData["startpos_z"])); - agentData.child = false; - } - - ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); - - UserPresenceData up = new UserPresenceData(); - up.agentData = agentData; - List flData = GetUserFriendList(agentData.AgentID); - up.friendData = flData; - RegionProfileData riData = GetRegionInfo(regionHandle); - up.regionData = riData; - - ProcessFriendListSubscriptions(up); - - - return new XmlRpcResponse(); - } - - /// - /// The UserServer got a Logoff message - /// Cleanup time for that user. Send out presence notifications - /// - /// - /// - public XmlRpcResponse UserLoggedOff(XmlRpcRequest request) - { - - Hashtable requestData = (Hashtable)request.Params[0]; - - LLUUID AgentID = new LLUUID((string)requestData["agent_id"]); - - - ProcessLogOff(AgentID); - - - return new XmlRpcResponse(); - } - - #endregion - #region regioninfo gathering - - /// - /// Gets and caches a RegionInfo object from the gridserver based on regionhandle - /// if the regionhandle is already cached, use the cached values - /// - /// handle to the XY of the region we're looking for - /// A RegionInfo object to stick in the presence info - public RegionProfileData GetRegionInfo(ulong regionhandle) - { - RegionProfileData regionInfo = null; - if (m_regionInfoCache.Contains(regionhandle)) - { - regionInfo = (RegionProfileData)m_regionInfoCache[regionhandle]; - } - else - { - regionInfo = RequestRegionInfo(regionhandle); - } - return regionInfo; - } - /// - /// Get RegionProfileData from the GridServer - /// We'll Cache this information and use it for presence updates - /// - /// - /// - public RegionProfileData RequestRegionInfo(ulong regionHandle) - { RegionProfileData regionProfile = null; - try - { - - Hashtable requestData = new Hashtable(); - requestData["region_handle"] = regionHandle.ToString(); - requestData["authkey"] = m_cfg.GridSendKey; - ArrayList SendParams = new ArrayList(); - SendParams.Add(requestData); - XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); - XmlRpcResponse GridResp = GridReq.Send(m_cfg.GridServerURL, 3000); - - Hashtable responseData = (Hashtable)GridResp.Value; - - if (responseData.ContainsKey("error")) - { - m_log.Error("GRID","error received from grid server" + responseData["error"]); - return null; - } - - uint regX = Convert.ToUInt32((string)responseData["region_locx"]); - uint regY = Convert.ToUInt32((string)responseData["region_locy"]); - string internalIpStr = (string)responseData["sim_ip"]; - uint port = Convert.ToUInt32(responseData["sim_port"]); - string externalUri = (string)responseData["sim_uri"]; - string neighbourExternalUri = externalUri; - - regionProfile = new RegionProfileData(); - regionProfile.httpPort = (uint)Convert.ToInt32((string)responseData["http_port"]); - regionProfile.httpServerURI = "http://" + internalIpStr + ":" + regionProfile.httpPort + "/"; - regionProfile.regionHandle = Helpers.UIntsToLong((regX * 256), (regY * 256)); - regionProfile.regionLocX = regX; - regionProfile.regionLocY = regY; - - regionProfile.remotingPort = Convert.ToUInt32((string)responseData["remoting_port"]); - regionProfile.UUID = new LLUUID((string)responseData["region_UUID"]); - regionProfile.regionName = (string)responseData["region_name"]; - - m_regionInfoCache.Add(regionHandle, regionProfile); - } - catch (WebException) - { - MainLog.Instance.Error("GRID", - "Region lookup failed for: " + regionHandle.ToString() + - " - Is the GridServer down?"); - return null; - } - - - return regionProfile; - } - #endregion - } - -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Net; +using System.Net.Sockets; +using System.Collections; +using System.Collections.Generic; +//using System.Xml; +using libsecondlife; +using Nwc.XmlRpc; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Data; +using OpenSim.Framework.Servers; +using FriendRights = libsecondlife.FriendRights; + +namespace OpenSim.Grid.MessagingServer +{ + public class MessageService + { + private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private MessageServerConfig m_cfg; + + //A hashtable of all current presences this server knows about + private Hashtable m_presences = new Hashtable(); + + //a hashtable of all current regions this server knows about + private Hashtable m_regionInfoCache = new Hashtable(); + + //A hashtable containing lists of UUIDs keyed by UUID for fast backreferencing + private Hashtable m_presence_BackReferences = new Hashtable(); + + // Hashtable containing work units that need to be processed + private Hashtable m_unProcessedWorkUnits = new Hashtable(); + + public MessageService(MessageServerConfig cfg) + { + m_cfg = cfg; + } + + #region RegionComms Methods + + /// + /// Informs a region about an Agent + /// + /// User to talk about + /// User we're sending this too (contains the region) + public void SendRegionPresenceUpdate(UserPresenceData TalkingAbout, UserPresenceData UserToUpdate) + { + // TODO: Fill in pertenant Presence Data from 'TalkingAbout' + + RegionProfileData whichRegion = UserToUpdate.regionData; + //whichRegion.httpServerURI + + Hashtable PresenceParams = new Hashtable(); + ArrayList SendParams = new ArrayList(); + SendParams.Add(PresenceParams); + + m_log.Info("[PRESENCE]: Informing " + whichRegion.regionName + " at " + whichRegion.httpServerURI); + // Send + XmlRpcRequest RegionReq = new XmlRpcRequest("presence_update", SendParams); + XmlRpcResponse RegionResp = RegionReq.Send(whichRegion.httpServerURI, 6000); + } + + + #endregion + + #region FriendList Methods + + + /// + /// Process Friendlist subscriptions for a user + /// The login method calls this for a User + /// + /// The Agent we're processing the friendlist subscriptions + public void ProcessFriendListSubscriptions(UserPresenceData userpresence) + { + List uFriendList = userpresence.friendData; + for (int i = 0; i < uFriendList.Count; i++) + { + m_presence_BackReferences.Add(userpresence.agentData.AgentID, uFriendList[i].Friend); + m_presence_BackReferences.Add(uFriendList[i].Friend, userpresence.agentData.AgentID); + + if (m_presences.Contains(uFriendList[i].Friend)) + { + UserPresenceData friendup = (UserPresenceData)m_presences[uFriendList[i]]; + // Add backreference + + SubscribeToPresenceUpdates(userpresence, friendup, uFriendList[i],i); + } + } + + m_presences.Add(userpresence.agentData.AgentID, userpresence); + } + + /// + /// 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 + /// + /// P1 + /// P2 + /// + /// + public void SubscribeToPresenceUpdates(UserPresenceData userpresence, UserPresenceData friendpresence, + FriendListItem uFriendListItem, int uFriendListIndex) + { + + if ((uFriendListItem.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0) + { + // Subscribe and Send Out updates + if (!friendpresence.subscriptionData.Contains(friendpresence.agentData.AgentID)) + { + userpresence.subscriptionData.Add(friendpresence.agentData.AgentID); + //Send Region Notice.... + + } + else + { + // we need to send out online status update, but the user is already subscribed + + } + SendRegionPresenceUpdate(friendpresence, userpresence); + } + if ((uFriendListItem.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0) + { + if (!friendpresence.subscriptionData.Contains(userpresence.agentData.AgentID)) + { + friendpresence.subscriptionData.Add(userpresence.agentData.AgentID); + //Send Region Notice.... + } + else + { + // we need to send out online status update, but the user is already subscribed + + } + SendRegionPresenceUpdate(userpresence, friendpresence); + } + + } + + + /// + /// Adds a backreference so presence specific data doesn't have to be + /// enumerated for each logged in user every time someone logs on or off. + /// + /// + /// + public void addBackReference(LLUUID agentID, LLUUID friendID) + { + if (m_presence_BackReferences.Contains(friendID)) + { + List presenseBackReferences = (List)m_presence_BackReferences[friendID]; + if (!presenseBackReferences.Contains(agentID)) + { + presenseBackReferences.Add(agentID); + } + m_presence_BackReferences[friendID] = presenseBackReferences; + } + else + { + List presenceBackReferences = new List(); + presenceBackReferences.Add(agentID); + m_presence_BackReferences[friendID] = presenceBackReferences; + } + } + + /// + /// Removes a backreference to free up some memory + /// + /// + /// + public void removeBackReference(LLUUID agentID, LLUUID friendID) + { + if (m_presence_BackReferences.Contains(friendID)) + { + List presenseBackReferences = (List)m_presence_BackReferences[friendID]; + if (presenseBackReferences.Contains(agentID)) + { + presenseBackReferences.Remove(agentID); + } + + // If there are no more backreferences for this agent, + // remove it to free up memory. + if (presenseBackReferences.Count == 0) + { + m_presence_BackReferences.Remove(agentID); + } + } + } + /// + /// Logoff Processor. Call this to clean up agent presence data and send logoff presence notifications + /// + /// + private void ProcessLogOff(LLUUID AgentID) + { + if (m_presences.Contains(AgentID)) + { + UserPresenceData AgentData = (UserPresenceData)m_presences[AgentID]; + + if (m_presence_BackReferences.Contains(AgentID)) + { + List AgentsNeedingNotification = (List)m_presence_BackReferences[AgentID]; + for (int i = 0; i < AgentsNeedingNotification.Count; i++) + { + // TODO: Do Region Notifications + if (m_presences.Contains(AgentsNeedingNotification[i])) + { + UserPresenceData friendd = (UserPresenceData)m_presences[AgentsNeedingNotification[i]]; + + // This might need to be enumerated and checked before we try to remove it. + friendd.subscriptionData.Remove(AgentID); + + List fl = friendd.friendData; + for (int j = 0; j < fl.Count; j++) + { + if (fl[j].Friend == AgentID) + { + fl[j].onlinestatus = false; + } + + } + friendd.friendData = fl; + + SendRegionPresenceUpdate(AgentData, friendd); + + } + removeBackReference(AgentID, AgentsNeedingNotification[i]); + + } + } + } + } + + + #endregion + + #region UserServer Comms + + /// + /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for LLUUID friendslistowner + /// + /// The agent that we're retreiving the friends Data. + public List GetUserFriendList(LLUUID friendlistowner) + { + List buddylist = new List(); + + try + { + Hashtable param = new Hashtable(); + param["ownerID"] = friendlistowner.UUID.ToString(); + + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_user_friend_list", parameters); + XmlRpcResponse resp = req.Send(m_cfg.UserServerURL, 3000); + Hashtable respData = (Hashtable)resp.Value; + + if (respData.Contains("avcount")) + { + buddylist = ConvertXMLRPCDataToFriendListItemList(respData); + } + + } + catch (WebException e) + { + m_log.Warn("Error when trying to fetch Avatar's friends list: " + + e.Message); + // Return Empty list (no friends) + } + return buddylist; + + } + + /// + /// Converts XMLRPC Friend List to FriendListItem Object + /// + /// XMLRPC response data Hashtable + /// + public List ConvertXMLRPCDataToFriendListItemList(Hashtable data) + { + List buddylist = new List(); + int buddycount = Convert.ToInt32((string)data["avcount"]); + + + for (int i = 0; i < buddycount; i++) + { + FriendListItem buddylistitem = new FriendListItem(); + + buddylistitem.FriendListOwner = new LLUUID((string)data["ownerID" + i.ToString()]); + buddylistitem.Friend = new LLUUID((string)data["friendID" + i.ToString()]); + buddylistitem.FriendListOwnerPerms = (uint)Convert.ToInt32((string)data["ownerPerms" + i.ToString()]); + buddylistitem.FriendPerms = (uint)Convert.ToInt32((string)data["friendPerms" + i.ToString()]); + + buddylist.Add(buddylistitem); + } + + + return buddylist; + } + /// + /// UserServer sends an expect_user method + /// this handles the method and provisions the + /// necessary info for presence to work + /// + /// UserServer Data + /// + public XmlRpcResponse UserLoggedOn(XmlRpcRequest request) + { + + Hashtable requestData = (Hashtable)request.Params[0]; + AgentCircuitData agentData = new AgentCircuitData(); + agentData.SessionID = new LLUUID((string)requestData["session_id"]); + agentData.SecureSessionID = new LLUUID((string)requestData["secure_session_id"]); + agentData.firstname = (string)requestData["firstname"]; + agentData.lastname = (string)requestData["lastname"]; + agentData.AgentID = new LLUUID((string)requestData["agent_id"]); + 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 LLVector3(Convert.ToUInt32(requestData["startpos_x"]), + Convert.ToUInt32(requestData["startpos_y"]), + Convert.ToUInt32(requestData["startpos_z"])); + agentData.child = false; + } + + ulong regionHandle = Convert.ToUInt64((string)requestData["regionhandle"]); + + UserPresenceData up = new UserPresenceData(); + up.agentData = agentData; + List flData = GetUserFriendList(agentData.AgentID); + up.friendData = flData; + RegionProfileData riData = GetRegionInfo(regionHandle); + up.regionData = riData; + + ProcessFriendListSubscriptions(up); + + + return new XmlRpcResponse(); + } + + /// + /// The UserServer got a Logoff message + /// Cleanup time for that user. Send out presence notifications + /// + /// + /// + public XmlRpcResponse UserLoggedOff(XmlRpcRequest request) + { + + Hashtable requestData = (Hashtable)request.Params[0]; + + LLUUID AgentID = new LLUUID((string)requestData["agent_id"]); + + + //ProcessLogOff(AgentID); + + + return new XmlRpcResponse(); + } + + #endregion + #region regioninfo gathering + + /// + /// Gets and caches a RegionInfo object from the gridserver based on regionhandle + /// if the regionhandle is already cached, use the cached values + /// + /// handle to the XY of the region we're looking for + /// A RegionInfo object to stick in the presence info + public RegionProfileData GetRegionInfo(ulong regionhandle) + { + RegionProfileData regionInfo = null; + if (m_regionInfoCache.Contains(regionhandle)) + { + regionInfo = (RegionProfileData)m_regionInfoCache[regionhandle]; + } + else + { + regionInfo = RequestRegionInfo(regionhandle); + } + return regionInfo; + } + /// + /// Get RegionProfileData from the GridServer + /// We'll Cache this information and use it for presence updates + /// + /// + /// + public RegionProfileData RequestRegionInfo(ulong regionHandle) + { RegionProfileData regionProfile = null; + try + { + + Hashtable requestData = new Hashtable(); + requestData["region_handle"] = regionHandle.ToString(); + requestData["authkey"] = m_cfg.GridSendKey; + ArrayList SendParams = new ArrayList(); + SendParams.Add(requestData); + XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams); + XmlRpcResponse GridResp = GridReq.Send(m_cfg.GridServerURL, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("error")) + { + m_log.Error("[GRID]: error received from grid server" + responseData["error"]); + return null; + } + + uint regX = Convert.ToUInt32((string)responseData["region_locx"]); + uint regY = Convert.ToUInt32((string)responseData["region_locy"]); + string internalIpStr = (string)responseData["sim_ip"]; + uint port = Convert.ToUInt32(responseData["sim_port"]); + string externalUri = (string)responseData["sim_uri"]; + string neighbourExternalUri = externalUri; + + regionProfile = new RegionProfileData(); + regionProfile.httpPort = (uint)Convert.ToInt32((string)responseData["http_port"]); + regionProfile.httpServerURI = "http://" + internalIpStr + ":" + regionProfile.httpPort + "/"; + regionProfile.regionHandle = Helpers.UIntsToLong((regX * Constants.RegionSize), (regY * Constants.RegionSize)); + regionProfile.regionLocX = regX; + regionProfile.regionLocY = regY; + + regionProfile.remotingPort = Convert.ToUInt32((string)responseData["remoting_port"]); + regionProfile.UUID = new LLUUID((string)responseData["region_UUID"]); + regionProfile.regionName = (string)responseData["region_name"]; + + m_regionInfoCache.Add(regionHandle, regionProfile); + } + catch (WebException) + { + m_log.Error("[GRID]: " + + "Region lookup failed for: " + regionHandle.ToString() + + " - Is the GridServer down?"); + return null; + } + + + return regionProfile; + } + #endregion + } + +} diff --git a/OpenSim/Grid/MessagingServer/UserPresenceData.cs b/OpenSim/Grid/MessagingServer/UserPresenceData.cs index 3e55e89fff..5470d32713 100644 --- a/OpenSim/Grid/MessagingServer/UserPresenceData.cs +++ b/OpenSim/Grid/MessagingServer/UserPresenceData.cs @@ -1,53 +1,53 @@ -/* -* Copyright (c) Contributors, http://opensimulator.org/ -* See CONTRIBUTORS.TXT for a full list of copyright holders. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are met: -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* * Neither the name of the OpenSim Project nor the -* names of its contributors may be used to endorse or promote products -* derived from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY -* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY -* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -*/ -using System; -using System.Collections; -using System.Collections.Generic; -using libsecondlife; -using OpenSim.Framework; -using OpenSim.Framework.Data; - - -namespace OpenSim.Grid.MessagingServer -{ - public class UserPresenceData - { - public AgentCircuitData agentData = new AgentCircuitData(); - public RegionProfileData regionData = new RegionProfileData(); - public string httpURI = ""; - public List friendData = new List (); - public List subscriptionData = new List(); - - public UserPresenceData() - { - - - } - - } -} +/* +* Copyright (c) Contributors, http://opensimulator.org/ +* See CONTRIBUTORS.TXT for a full list of copyright holders. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the OpenSim Project nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*/ +using System; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using OpenSim.Framework; +using OpenSim.Framework.Data; + + +namespace OpenSim.Grid.MessagingServer +{ + public class UserPresenceData + { + public AgentCircuitData agentData = new AgentCircuitData(); + public RegionProfileData regionData = new RegionProfileData(); + public string httpURI = String.Empty; + public List friendData = new List (); + public List subscriptionData = new List(); + + public UserPresenceData() + { + + + } + + } +}