diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 9ba4e4953d..ed0211956c 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs @@ -194,6 +194,22 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage Util.FireAndForget(delegate { bool success = m_IMService.OutgoingInstantMessage(im, url); + if (!success && account == null) + { + // One last chance + string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI); + if (recipientUUI != string.Empty) + { + UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret)) + { + success = m_IMService.OutgoingInstantMessage(im, u); + if (success) + UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last); + } + } + } result(success); }); @@ -254,6 +270,64 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage result(false); } + private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent) + { + // Let's call back the fromAgent's user agent service + // Maybe that service knows about the toAgent + IClientAPI client = LocateClientObject(fromAgent); + if (client != null) + { + AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if (circuit != null) + { + if (circuit.ServiceURLs.ContainsKey("HomeURI")) + { + string uasURL = circuit.ServiceURLs["HomeURI"].ToString(); + m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL); + UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL); + return uasConn.GetUUI(fromAgent, toAgent); + } + } + } + + return string.Empty; + } + + + /// + /// Find the scene for an agent + /// + private Scene GetClientScene(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null && !presence.IsChildAgent) + return scene; + } + } + + return null; + } + + /// + /// Find the client for a ID + /// + public IClientAPI LocateClientObject(UUID agentID) + { + Scene scene = GetClientScene(agentID); + if (scene != null) + { + ScenePresence presence = scene.GetScenePresence(agentID); + if (presence != null) + return presence.ControllingClient; + } + + return null; + } + #region IInstantMessageSimConnector public bool SendInstantMessage(GridInstantMessage im) { diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index f4472c7dc0..6743a2e7c8 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -65,6 +65,10 @@ namespace OpenSim.Server.Base /// public static T LoadPlugin(string dllName, Object[] args) where T:class { + // This is good to debug configuration problems + //if (dllName == string.Empty) + // Util.PrintCallStack(); + string[] parts = dllName.Split(new char[] {':'}); dllName = parts[0]; diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs index 942d96073b..eb184a57ba 100644 --- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs +++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs @@ -54,6 +54,8 @@ namespace OpenSim.Server.Handlers.Hypergrid private IUserAgentService m_HomeUsersService; private string[] m_AuthorizedCallers; + private bool m_VerifyCallers = false; + public UserAgentServerConnector(IConfigSource config, IHttpServer server) : this(config, server, null) { @@ -76,6 +78,7 @@ namespace OpenSim.Server.Handlers.Hypergrid string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); bool proxy = gridConfig.GetBoolean("HasProxy", false); + m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false); string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1"); csv = csv.Replace(" ", ""); m_AuthorizedCallers = csv.Split(','); @@ -91,6 +94,7 @@ namespace OpenSim.Server.Handlers.Hypergrid server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false); server.AddXmlRPCHandler("locate_user", LocateUser, false); + server.AddXmlRPCHandler("get_uui", GetUUI, false); server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); } @@ -324,13 +328,17 @@ namespace OpenSim.Server.Handlers.Hypergrid { Hashtable hash = new Hashtable(); - bool authorized = false; - foreach (string s in m_AuthorizedCallers) - if (s == remoteClient.Address.ToString()) - { - authorized = true; - break; - } + bool authorized = true; + if (m_VerifyCallers) + { + authorized = false; + foreach (string s in m_AuthorizedCallers) + if (s == remoteClient.Address.ToString()) + { + authorized = true; + break; + } + } if (authorized) { @@ -354,5 +362,40 @@ namespace OpenSim.Server.Handlers.Hypergrid return response; } + + /// + /// Locates the user. + /// This is a sensitive operation, only authorized IP addresses can perform it. + /// + /// + /// + /// + public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable hash = new Hashtable(); + + Hashtable requestData = (Hashtable)request.Params[0]; + //string host = (string)requestData["host"]; + //string portstr = (string)requestData["port"]; + if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID")) + { + string userID_str = (string)requestData["userID"]; + UUID userID = UUID.Zero; + UUID.TryParse(userID_str, out userID); + + string tuserID_str = (string)requestData["targetUserID"]; + UUID targetUserID = UUID.Zero; + UUID.TryParse(tuserID_str, out targetUserID); + string uui = m_HomeUsersService.GetUUI(userID, targetUserID); + if (uui != string.Empty) + hash["UUI"] = uui; + } + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = hash; + return response; + + } + } } diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 50036b36e8..1c01563014 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -576,6 +576,7 @@ namespace OpenSim.Services.Connectors.Hypergrid XmlRpcResponse response = null; try { + m_log.DebugFormat("[XXX]: Calling locate_user on {0}", m_ServerURL); response = request.Send(m_ServerURL, 10000); } catch (Exception e) @@ -618,6 +619,66 @@ namespace OpenSim.Services.Connectors.Hypergrid return url; } + public string GetUUI(UUID userID, UUID targetUserID) + { + Hashtable hash = new Hashtable(); + hash["userID"] = userID.ToString(); + hash["targetUserID"] = targetUserID.ToString(); + + IList paramList = new ArrayList(); + paramList.Add(hash); + + XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList); + string reason = string.Empty; + + // Send and get reply + string uui = string.Empty; + XmlRpcResponse response = null; + try + { + m_log.DebugFormat("[XXX]: Calling get_uuid on {0}", m_ServerURL); + response = request.Send(m_ServerURL, 10000); + } + catch (Exception e) + { + m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); + reason = "Exception: " + e.Message; + return uui; + } + + if (response.IsFault) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); + reason = "XMLRPC Fault"; + return uui; + } + + hash = (Hashtable)response.Value; + //foreach (Object o in hash) + // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); + try + { + if (hash == null) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL); + reason = "Internal error 1"; + return uui; + } + + // Here's the actual response + if (hash.ContainsKey("UUI")) + uui = hash["UUI"].ToString(); + + } + catch (Exception e) + { + m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response."); + reason = "Exception: " + e.Message; + } + + return uui; + } + private bool GetBoolResponse(XmlRpcRequest request, out string reason) { //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL); diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs index 65ee7c7aeb..2a922de5a4 100644 --- a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs +++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs @@ -80,6 +80,7 @@ namespace OpenSim.Services.Connectors.InstantMessage } else { + m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url); return false; } } diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs index 6178ca1d7b..ca0fd7f350 100644 --- a/OpenSim/Services/HypergridService/HGInstantMessageService.cs +++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs @@ -64,8 +64,8 @@ namespace OpenSim.Services.HypergridService protected static IInstantMessageSimConnector m_IMSimConnector; - protected Dictionary m_UserLocationMap = new Dictionary(); - private ExpiringCache m_RegionCache; + protected static Dictionary m_UserLocationMap = new Dictionary(); + private static ExpiringCache m_RegionCache; public HGInstantMessageService(IConfigSource config) : this(config, null) @@ -155,6 +155,8 @@ namespace OpenSim.Services.HypergridService if (!firstTime) { lookupAgent = true; + upd = null; + url = string.Empty; } } else @@ -168,7 +170,6 @@ namespace OpenSim.Services.HypergridService // Are we needing to look-up an agent? if (lookupAgent) { - bool isPresent = false; // Non-cached user agent lookup. PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() }); if (presences != null && presences.Length > 0) @@ -177,17 +178,17 @@ namespace OpenSim.Services.HypergridService { if (p.RegionID != UUID.Zero) { + m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID); upd = p; break; } - else - isPresent = true; } } - if (upd == null && isPresent) + if (upd == null) { // Let's check with the UAS if the user is elsewhere + m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service"); url = m_UserAgentService.LocateUser(toAgentID); } @@ -197,10 +198,10 @@ namespace OpenSim.Services.HypergridService // This is one way to end the recursive loop // if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) || - (previousLocation is string && previousLocation.Equals(url)))) + (previousLocation is string && upd == null && previousLocation.Equals(url)))) { // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - m_log.DebugFormat("[XXX] Fail 1 {0} {1}", previousLocation, url); + m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url); return false; } @@ -242,9 +243,14 @@ namespace OpenSim.Services.HypergridService } 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) { diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 59ad043cef..387547e252 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -485,6 +485,30 @@ namespace OpenSim.Services.HypergridService return string.Empty; } + + public string GetUUI(UUID userID, UUID targetUserID) + { + // Let's see if it's a local user + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID); + if (account != null) + return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ; + + // Let's try the list of friends + FriendInfo[] friends = m_FriendsService.GetFriends(userID); + if (friends != null && friends.Length > 0) + { + foreach (FriendInfo f in friends) + if (f.Friend.StartsWith(targetUserID.ToString())) + { + // Let's remove the secret + UUID id; string tmp = string.Empty, secret = string.Empty; + if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret)) + return f.Friend.Replace(secret, "0"); + } + } + + return string.Empty; + } } class TravelingAgentInfo diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index 3ab6d4f88b..753c20523c 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -57,6 +57,9 @@ namespace OpenSim.Services.Interfaces Dictionary GetServerURLs(UUID userID); string LocateUser(UUID userID); + // Tries to get the universal user identifier for the targetUserId + // on behalf of the userID + string GetUUI(UUID userID, UUID targetUserID); void StatusNotification(List friends, UUID userID, bool online); List GetOnlineFriends(UUID userID, List friends); diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 0d79e77b7a..bfefe32cff 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -21,7 +21,7 @@ ; * [[@]/][:] ; * [Startup] -ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector" +ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector" ; * This is common for all services, it's the network setup for the entire ; * server instance, if none is specified above @@ -316,7 +316,10 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" GridService = "OpenSim.Services.GridService.dll:GridService" GatekeeperService = "OpenSim.Services.HypergridService.dll:GatekeeperService" - + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" + ; If you run this user agent server behind a proxy, set this to true ; HasProxy = false @@ -344,3 +347,14 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" ProfileServerURI = "http://127.0.0.1:8002/user" + +[HGFriendsService] + LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.GridService.dll:GridService" + PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" + UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" + diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index bc8bc0fdab..b2ecc79e8a 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -93,6 +93,12 @@ ;; uncomment the next line. You may want to do this on sims that have licensed content. ; OutboundPermission = False +[UserAgentService] + ; + ; === HG ONLY === + ; Change this to your user agent server + ; + UserAgentServerURI = "http://mygridserver.com:8002" [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index 5142d90eda..d2cf89875a 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -24,12 +24,14 @@ EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" LandServices = "RemoteLandServicesConnector" + FriendsModule = "HGFriendsModule" LandServiceInConnector = true NeighbourServiceInConnector = true SimulationServiceInConnector = true LibraryModule = true + [SimulationDataStore] LocalServiceModule = "OpenSim.Services.Connectors.dll:SimulationDataService" @@ -63,3 +65,12 @@ [Friends] Connector = "OpenSim.Services.Connectors.dll:FriendsServicesConnector" + +[Messaging] + MessageTransferModule = HGMessageTransferModule + +[HGInstantMessageService] + LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInstantMessageService" + GridService = "OpenSim.Services.Connectors.dll:GridServicesConnector" + PresenceService = "OpenSim.Services.Connectors.dll:PresenceServicesConnector" + UserAgentService = "OpenSim.Services.Connectors.dll:UserAgentServiceConnector" \ No newline at end of file