From d20cae2d03f26f92e88f28ec187de50934144fcb Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Sun, 1 Jun 2008 10:05:22 +0000 Subject: * Committing more unfinished stuff. Nothing significant at the moment. IM related. --- OpenSim/Framework/Communications/IUserService.cs | 2 + .../Framework/Communications/UserManagerBase.cs | 13 ++ OpenSim/Grid/UserServer/UserManager.cs | 48 ++++ .../Region/Communications/OGS1/OGS1UserServices.cs | 53 +++++ .../Avatar/InstantMessage/InstantMessageModule.cs | 257 ++++++++++++++++++++- 5 files changed, 362 insertions(+), 11 deletions(-) diff --git a/OpenSim/Framework/Communications/IUserService.cs b/OpenSim/Framework/Communications/IUserService.cs index 59ad188..a7f19e7 100644 --- a/OpenSim/Framework/Communications/IUserService.cs +++ b/OpenSim/Framework/Communications/IUserService.cs @@ -49,6 +49,8 @@ namespace OpenSim.Framework.Communications /// A user profile. Returns null if no user profile is found. UserProfileData GetUserProfile(LLUUID userId); + UserAgentData GetAgentByUUID(LLUUID userId); + void clearUserAgent(LLUUID avatarID); List GenerateAgentPickerRequestResponse(LLUUID QueryID, string Query); diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs index 8985bb6..fe09b03 100644 --- a/OpenSim/Framework/Communications/UserManagerBase.cs +++ b/OpenSim/Framework/Communications/UserManagerBase.cs @@ -103,7 +103,20 @@ namespace OpenSim.Framework.Communications return null; } + public UserAgentData GetAgentByUUID(LLUUID userId) + { + foreach (KeyValuePair plugin in _plugins) + { + UserAgentData agent = plugin.Value.GetAgentByUUID(userId); + if (agent != null) + { + return agent; + } + } + + return null; + } // see IUserService public UserProfileData GetUserProfile(LLUUID uuid) { diff --git a/OpenSim/Grid/UserServer/UserManager.cs b/OpenSim/Grid/UserServer/UserManager.cs index 1b47289..3e8f3a2 100644 --- a/OpenSim/Grid/UserServer/UserManager.cs +++ b/OpenSim/Grid/UserServer/UserManager.cs @@ -420,6 +420,54 @@ namespace OpenSim.Grid.UserServer return ProfileToXmlRPCResponse(userProfile); } + public XmlRpcResponse XmlRPCGetAgentMethodUUID(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + UserProfileData userProfile; + //CFK: this clogs the UserServer log and is not necessary at this time. + //CFK: Console.WriteLine("METHOD BY UUID CALLED"); + if (requestData.Contains("avatar_uuid")) + { + LLUUID guess = LLUUID.Zero; + + Helpers.TryParse((string)requestData["avatar_uuid"],out guess); + + if (guess == LLUUID.Zero) + { + return CreateUnknownUserErrorResponse(); + } + + userProfile = GetUserProfile(guess); + + if (userProfile == null) + { + return CreateUnknownUserErrorResponse(); + } + + // no agent??? + if (userProfile.CurrentAgent == null) + { + return CreateUnknownUserErrorResponse(); + } + Hashtable responseData = new Hashtable(); + + responseData["handle"]=userProfile.CurrentAgent.Handle.ToString(); + responseData["session"]=userProfile.CurrentAgent.SessionID.ToString(); + if (userProfile.CurrentAgent.AgentOnline) + responseData["agent_online"]="TRUE"; + else + responseData["agent_online"]="FALSE"; + + response.Value = responseData; + } + else + { + return CreateUnknownUserErrorResponse(); + } + + return ProfileToXmlRPCResponse(userProfile); + } public XmlRpcResponse XmlRpcResponseXmlRPCUpdateUserProfile(XmlRpcRequest request) diff --git a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs index 17b5a06..d486c40 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1UserServices.cs @@ -85,6 +85,58 @@ namespace OpenSim.Region.Communications.OGS1 (float) Convert.ToDecimal((string) data["home_look_z"])); return userData; + } + + /// + /// Get a user agent from the user server + /// + /// + /// null if the request fails + public UserAgentData GetAgentByUUID(LLUUID userId) + { + try + { + Hashtable param = new Hashtable(); + param["avatar_uuid"] = userId.ToString(); + IList parameters = new ArrayList(); + parameters.Add(param); + XmlRpcRequest req = new XmlRpcRequest("get_agent_by_uuid", parameters); + XmlRpcResponse resp = req.Send(m_parent.NetworkServersInfo.UserURL, 6000); + Hashtable respData = (Hashtable) resp.Value; + if (respData.Contains("error_type")) + { + m_log.Warn("[GRID]: " + + "Error sent by user server when trying to get agent: (" + + (string) respData["error_type"] + + "): " + (string)respData["error_desc"]); + return null; + } + LLUUID sessionid = LLUUID.Zero; + + UserAgentData userAgent = new UserAgentData(); + userAgent.Handle = Convert.ToUInt64((string)respData["handle"]); + Helpers.TryParse((string)respData["sessionid"], out sessionid); + userAgent.SessionID = sessionid; + + if ((string)respData["agent_online"] == "TRUE") + { + userAgent.AgentOnline = true; + } + else + { + userAgent.AgentOnline = false; + } + + return userAgent; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[OGS1 USER SERVICES]: Error when trying to fetch agent data by uuid from remote user server: {0}", + e); + } + + return null; } public AvatarAppearance ConvertXMLRPCDataToAvatarAppearance(Hashtable data) @@ -335,6 +387,7 @@ namespace OpenSim.Region.Communications.OGS1 return null; } + public void clearUserAgent(LLUUID avatarID) { // TODO: implement diff --git a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs index d9d2875..fdded90 100644 --- a/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/Environment/Modules/Avatar/InstantMessage/InstantMessageModule.cs @@ -27,7 +27,11 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using System.Net; +using System.Threading; using libsecondlife; +using log4net; using Nini.Config; using Nwc.XmlRpc; using OpenSim.Framework; @@ -38,11 +42,15 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage { public class InstantMessageModule : IRegionModule { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private readonly List m_scenes = new List(); + private Dictionary m_userRegionMap = new Dictionary(); #region IRegionModule Members private bool gridmode = false; + public void Initialise(Scene scene, IConfigSource config) { @@ -150,14 +158,19 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage return; } } + if (gridmode) + { + // Still here, try send via Grid + // TODO + if (client != null) + { + if (dialog != (byte)InstantMessageDialog.StartTyping && dialog != (byte)InstantMessageDialog.StopTyping && dialog != (byte)InstantMessageDialog.SessionDrop) + client.SendInstantMessage(toAgentID, fromAgentSession, "Unable to send instant message", fromAgentID, imSessionID, "System", (byte)InstantMessageDialog.BusyAutoResponse, (uint)Util.UnixTimeSinceEpoch());// SendAlertMessage("Unable to send instant message"); + } + } } - if (gridmode) - { - // Still here, try send via Grid - // TODO - - } + } // Trusty OSG1 called method. This method also gets called from the FriendsModule @@ -174,6 +187,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage } protected virtual XmlRpcResponse processXMLRPCGridInstantMessage(XmlRpcRequest request) { + bool successful = false; // various rational defaults LLUUID fromAgentID = LLUUID.Zero; LLUUID fromAgentSession = LLUUID.Zero; @@ -185,7 +199,7 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage byte dialog = (byte)0; bool fromGroup = false; byte offline = (byte)0; - uint ParentEstateID; + uint ParentEstateID=0; LLVector3 Position = LLVector3.Zero; LLUUID RegionID = LLUUID.Zero ; byte[] binaryBucket = new byte[0]; @@ -303,12 +317,48 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage Position = new LLVector3(pos_x, pos_y, pos_z); binaryBucket = (byte[])requestData["binary_bucket"]; + GridInstantMessage gim = new GridInstantMessage(); + gim.fromAgentID = fromAgentID.UUID; + gim.fromAgentName = fromAgentName; + gim.fromAgentSession = fromAgentSession.UUID; + gim.fromGroup = fromGroup; + gim.imSessionID = imSessionID.UUID; + gim.RegionID = RegionID.UUID; + gim.timestamp = timestamp; + gim.toAgentID = toAgentID.UUID; + gim.message = message; + gim.dialog = dialog; + gim.offline = offline; + gim.ParentEstateID = ParentEstateID; + gim.Position = new sLLVector3(Position); + gim.binaryBucket = binaryBucket; + + + foreach (Scene scene in m_scenes) + { + if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) + { + // Local message + ScenePresence user = (ScenePresence)scene.Entities[toAgentID]; + if (!user.IsChildAgent) + { + scene.EventManager.TriggerGridInstantMessage(gim, InstantMessageReceiver.FriendsModule | InstantMessageReceiver.GroupsModule | InstantMessageReceiver.IMModule); + } + } + } + OnGridInstantMessage(gim); + successful = true; } - return new XmlRpcResponse(); - //(string) - //(string)requestData["message"]; + XmlRpcResponse resp = new XmlRpcResponse(); + Hashtable respdata = new Hashtable(); + if (successful) + respdata["success"] = "TRUE"; + else + respdata["success"] = "FALSE"; + resp.Value = respdata; + return resp; } protected virtual void SendGridInstantMessageViaXMLRPC(IClientAPI client, LLUUID fromAgentID, @@ -316,9 +366,194 @@ namespace OpenSim.Region.Environment.Modules.Avatar.InstantMessage LLUUID imSessionID, uint timestamp, string fromAgentName, string message, byte dialog, bool fromGroup, byte offline, uint ParentEstateID, LLVector3 Position, LLUUID RegionID, - byte[] binaryBucket) + byte[] binaryBucket, ulong regionhandle, ulong prevRegionHandle) + { + UserAgentData upd = null; + + bool lookupAgent = false; + + lock (m_userRegionMap) + { + if (m_userRegionMap.ContainsKey(toAgentID) && prevRegionHandle == 0) + { + upd = new UserAgentData(); + upd.AgentOnline = true; + upd.Handle = m_userRegionMap[toAgentID]; + + } + else + { + lookupAgent = true; + + + } + } + + if (lookupAgent) + { + upd = m_scenes[0].CommsManager.UserService.GetAgentByUUID(toAgentID); + + // check if we've tried this before.. + if (upd.Handle == prevRegionHandle) + { + m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + if (client != null) + client.SendInstantMessage(toAgentID, fromAgentSession, "Unable to send instant message", fromAgentID, imSessionID, "System", (byte)InstantMessageDialog.MessageFromObject,(uint)Util.UnixTimeSinceEpoch());// SendAlertMessage("Unable to send instant message"); + return; + } + } + + if (upd != null) + { + if (upd.AgentOnline) + { + RegionInfo reginfo = m_scenes[0].CommsManager.GridService.RequestNeighbourInfo(upd.Handle); + if (reginfo != null) + { + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = fromAgentID.UUID; + msg.fromAgentSession = fromAgentSession.UUID; + msg.toAgentID = toAgentID.UUID; + msg.imSessionID = imSessionID.UUID; + msg.timestamp = timestamp; + msg.fromAgentName = fromAgentName; + msg.message = message; + msg.dialog = dialog; + msg.fromGroup = fromGroup; + msg.offline = offline; + msg.ParentEstateID = ParentEstateID; + msg.Position = new sLLVector3(Position); + msg.RegionID = RegionID.UUID; + msg.binaryBucket = binaryBucket; + + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(msg); + msgdata["region_handle"] = getLocalRegionHandleFromUUID(RegionID); + bool imresult = doIMSending(reginfo, msgdata); + if (imresult) + { + lock (m_userRegionMap) + { + if (m_userRegionMap.ContainsKey(toAgentID)) + { + m_userRegionMap[toAgentID] = upd.Handle; + } + else + { + m_userRegionMap.Add(toAgentID, upd.Handle); + } + } + m_log.Info("[GRID INSTANT MESSAGE]: Successfully sent a message"); + } + else + { + // try again, but lookup user this time. + SendGridInstantMessageViaXMLRPC(client, fromAgentID, + fromAgentSession, toAgentID, + imSessionID, timestamp, fromAgentName, + message, dialog, fromGroup, offline, + ParentEstateID, Position, RegionID, + binaryBucket, regionhandle, upd.Handle); + } + + } + } + else + { + // send Agent Offline message + if (client != null) + client.SendInstantMessage(toAgentID, fromAgentSession, "Unable to send instant message", fromAgentID, imSessionID, "System", (byte)InstantMessageDialog.MessageFromObject, (uint)Util.UnixTimeSinceEpoch());// SendAlertMessage("Unable to send instant message"); + } + } + else + { + // send Agent Offline message + if (client != null) + client.SendInstantMessage(toAgentID, fromAgentSession, "Unable to send instant message", fromAgentID, imSessionID, "System", (byte)InstantMessageDialog.MessageFromObject, (uint)Util.UnixTimeSinceEpoch());// SendAlertMessage("Unable to send instant message"); + } + + } + + private bool doIMSending(RegionInfo reginfo, Hashtable xmlrpcdata) + { + + ArrayList SendParams = new ArrayList(); + SendParams.Add(xmlrpcdata); + XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams); + try + { + + XmlRpcResponse GridResp = GridReq.Send("http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort, 3000); + + Hashtable responseData = (Hashtable)GridResp.Value; + + if (responseData.ContainsKey("success")) + { + if ((string)responseData["success"] == "TRUE") + { + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + catch (WebException) + { + m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond", "http://" + reginfo.ExternalHostName + ":" + reginfo.HttpPort); + } + + return false; + } + + private ulong getLocalRegionHandleFromUUID(LLUUID regionID) { + ulong returnhandle = 0; + lock (m_scenes) + { + foreach (Scene sn in m_scenes) + { + if (sn.RegionInfo.RegionID == regionID) + { + returnhandle = sn.RegionInfo.RegionHandle; + break; + } + } + } + return returnhandle; } + + private Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg) + { + Hashtable gim = new Hashtable(); + gim["from_agent_id"] = msg.fromAgentID.ToString(); + gim["from_agent_session"] = msg.fromAgentSession.ToString(); + gim["to_agent_id"] = msg.toAgentID.ToString(); + gim["im_session_id"] = msg.imSessionID.ToString(); + gim["timestamp"] = msg.timestamp.ToString(); + gim["from_agent_name"] = msg.fromAgentName; + gim["message"] = msg.message; + gim["dialog"] = msg.dialog; + + if (msg.fromGroup) + gim["from_group"] = "TRUE"; + else + gim["from_group"] = "FALSE"; + + gim["offline"] = msg.offline; + gim["parent_estate_id"] = msg.ParentEstateID.ToString(); + gim["position_x"] = msg.Position.x.ToString(); + gim["position_y"] = msg.Position.y.ToString(); + gim["position_z"] = msg.Position.z.ToString(); + gim["region_id"] = msg.RegionID.ToString(); + gim["binary_bucket"] = msg.binaryBucket; + return gim; + } + } } \ No newline at end of file -- cgit v1.1