aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/HypergridService
diff options
context:
space:
mode:
authorMelanie2011-06-09 02:05:04 +0100
committerMelanie2011-06-09 02:05:04 +0100
commit326c46ba70cea70ddfe4aef9a6b73edff63e126a (patch)
tree5e76347b0d77f58717d8e5e4f3b8787ff01a18d7 /OpenSim/Services/HypergridService
parentMake the last otem in a list created with llCSV2List findable (diff)
parentConsistency fix on the last commit. (diff)
downloadopensim-SC_OLD-326c46ba70cea70ddfe4aef9a6b73edff63e126a.zip
opensim-SC_OLD-326c46ba70cea70ddfe4aef9a6b73edff63e126a.tar.gz
opensim-SC_OLD-326c46ba70cea70ddfe4aef9a6b73edff63e126a.tar.bz2
opensim-SC_OLD-326c46ba70cea70ddfe4aef9a6b73edff63e126a.tar.xz
Merge branch 'master' into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Services/HypergridService')
-rw-r--r--OpenSim/Services/HypergridService/HGInstantMessageService.cs349
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs2
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs252
3 files changed, 597 insertions, 6 deletions
diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
new file mode 100644
index 0000000..ded589d
--- /dev/null
+++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
@@ -0,0 +1,349 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.InstantMessage;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
41
42using OpenMetaverse;
43using log4net;
44using Nini.Config;
45
46namespace OpenSim.Services.HypergridService
47{
48 /// <summary>
49 /// Inter-grid IM
50 /// </summary>
51 public class HGInstantMessageService : IInstantMessage
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours
58
59 static bool m_Initialized = false;
60
61 protected static IGridService m_GridService;
62 protected static IPresenceService m_PresenceService;
63 protected static IUserAgentService m_UserAgentService;
64
65 protected static IInstantMessageSimConnector m_IMSimConnector;
66
67 protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
68 private static ExpiringCache<UUID, GridRegion> m_RegionCache;
69
70 private static string m_RestURL;
71 private static bool m_ForwardOfflineGroupMessages;
72 private static bool m_InGatekeeper;
73
74 public HGInstantMessageService(IConfigSource config)
75 : this(config, null)
76 {
77 }
78
79 public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector)
80 {
81 if (imConnector != null)
82 m_IMSimConnector = imConnector;
83
84 if (!m_Initialized)
85 {
86 m_Initialized = true;
87
88 IConfig serverConfig = config.Configs["HGInstantMessageService"];
89 if (serverConfig == null)
90 throw new Exception(String.Format("No section HGInstantMessageService in config file"));
91
92 string gridService = serverConfig.GetString("GridService", String.Empty);
93 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
94 string userAgentService = serverConfig.GetString("UserAgentService", String.Empty);
95 m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false);
96 m_log.DebugFormat("[HG IM SERVICE]: Starting... InRobust? {0}", m_InGatekeeper);
97
98
99 if (gridService == string.Empty || presenceService == string.Empty)
100 throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function."));
101
102 Object[] args = new Object[] { config };
103 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
104 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
105 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
106
107 m_RegionCache = new ExpiringCache<UUID, GridRegion>();
108
109 IConfig cnf = config.Configs["Messaging"];
110 if (cnf == null)
111 {
112 return;
113 }
114
115 m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty);
116 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false);
117
118 }
119 }
120
121 public bool IncomingInstantMessage(GridInstantMessage im)
122 {
123 m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID);
124 UUID toAgentID = new UUID(im.toAgentID);
125
126 bool success = false;
127 if (m_IMSimConnector != null)
128 {
129 //m_log.DebugFormat("[XXX] SendIMToRegion local im connector");
130 success = m_IMSimConnector.SendInstantMessage(im);
131 }
132 else
133 {
134 success = TrySendInstantMessage(im, "", true, false);
135 }
136
137 if (!success && m_InGatekeeper) // we do this only in the Gatekeeper IM service
138 UndeliveredMessage(im);
139
140 return success;
141 }
142
143 public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner)
144 {
145 m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url);
146 if (url != string.Empty)
147 return TrySendInstantMessage(im, url, true, foreigner);
148 else
149 {
150 PresenceInfo upd = new PresenceInfo();
151 upd.RegionID = UUID.Zero;
152 return TrySendInstantMessage(im, upd, true, foreigner);
153 }
154
155 }
156
157 protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner)
158 {
159 UUID toAgentID = new UUID(im.toAgentID);
160
161 PresenceInfo upd = null;
162 string url = string.Empty;
163
164 bool lookupAgent = false;
165
166 lock (m_UserLocationMap)
167 {
168 if (m_UserLocationMap.ContainsKey(toAgentID))
169 {
170 object o = m_UserLocationMap[toAgentID];
171 if (o is PresenceInfo)
172 upd = (PresenceInfo)o;
173 else if (o is string)
174 url = (string)o;
175
176 // We need to compare the current location with the previous
177 // or the recursive loop will never end because it will never try to lookup the agent again
178 if (!firstTime)
179 {
180 lookupAgent = true;
181 upd = null;
182 }
183 }
184 else
185 {
186 lookupAgent = true;
187 }
188 }
189
190 //m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no"));
191
192 // Are we needing to look-up an agent?
193 if (lookupAgent)
194 {
195 // Non-cached user agent lookup.
196 PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() });
197 if (presences != null && presences.Length > 0)
198 {
199 foreach (PresenceInfo p in presences)
200 {
201 if (p.RegionID != UUID.Zero)
202 {
203 //m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID);
204 upd = p;
205 break;
206 }
207 }
208 }
209
210 if (upd == null && !foreigner)
211 {
212 // Let's check with the UAS if the user is elsewhere
213 m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service");
214 url = m_UserAgentService.LocateUser(toAgentID);
215 }
216
217 // check if we've tried this before..
218 // This is one way to end the recursive loop
219 //
220 if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) ||
221 (previousLocation is string && upd == null && previousLocation.Equals(url))))
222 {
223 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
224 m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url);
225
226 return false;
227 }
228 }
229
230 if (upd != null)
231 {
232 // ok, the user is around somewhere. Let's send back the reply with "success"
233 // even though the IM may still fail. Just don't keep the caller waiting for
234 // the entire time we're trying to deliver the IM
235 return SendIMToRegion(upd, im, toAgentID, foreigner);
236 }
237 else if (url != string.Empty)
238 {
239 // ok, the user is around somewhere. Let's send back the reply with "success"
240 // even though the IM may still fail. Just don't keep the caller waiting for
241 // the entire time we're trying to deliver the IM
242 return ForwardIMToGrid(url, im, toAgentID, foreigner);
243 }
244 else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty)
245 {
246 return ForwardIMToGrid((string)previousLocation, im, toAgentID, foreigner);
247 }
248 else
249 m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID);
250 return false;
251 }
252
253 bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner)
254 {
255 bool imresult = false;
256 GridRegion reginfo = null;
257 if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo))
258 {
259 reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID);
260 if (reginfo != null)
261 m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS);
262 }
263
264 if (reginfo != null)
265 {
266 imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im);
267 }
268 else
269 {
270 m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI);
271 return false;
272 }
273
274 if (imresult)
275 {
276 // IM delivery successful, so store the Agent's location in our local cache.
277 lock (m_UserLocationMap)
278 {
279 if (m_UserLocationMap.ContainsKey(toAgentID))
280 {
281 m_UserLocationMap[toAgentID] = upd;
282 }
283 else
284 {
285 m_UserLocationMap.Add(toAgentID, upd);
286 }
287 }
288 return true;
289 }
290 else
291 {
292 // try again, but lookup user this time.
293 // Warning, this must call the Async version
294 // of this method or we'll be making thousands of threads
295 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
296 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
297
298 // This is recursive!!!!!
299 return TrySendInstantMessage(im, upd, false, foreigner);
300 }
301 }
302
303 bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID, bool foreigner)
304 {
305 if (InstantMessageServiceConnector.SendInstantMessage(url, im))
306 {
307 // IM delivery successful, so store the Agent's location in our local cache.
308 lock (m_UserLocationMap)
309 {
310 if (m_UserLocationMap.ContainsKey(toAgentID))
311 {
312 m_UserLocationMap[toAgentID] = url;
313 }
314 else
315 {
316 m_UserLocationMap.Add(toAgentID, url);
317 }
318 }
319
320 return true;
321 }
322 else
323 {
324 // try again, but lookup user this time.
325
326 // This is recursive!!!!!
327 return TrySendInstantMessage(im, url, false, foreigner);
328 }
329
330 }
331
332 private bool UndeliveredMessage(GridInstantMessage im)
333 {
334 if (m_RestURL != string.Empty && (im.offline != 0)
335 && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages)))
336 {
337 m_log.DebugFormat("[HG IM SERVICE]: Message saved");
338 return SynchronousRestObjectPoster.BeginPostObject<GridInstantMessage, bool>(
339 "POST", m_RestURL + "/SaveMessage/", im);
340
341 }
342
343 else
344 {
345 return false;
346 }
347 }
348 }
349}
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
index 9ee1ae4..4eb61ba 100644
--- a/OpenSim/Services/HypergridService/HGInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -134,6 +134,7 @@ namespace OpenSim.Services.HypergridService
134 134
135 public override InventoryFolderBase GetRootFolder(UUID principalID) 135 public override InventoryFolderBase GetRootFolder(UUID principalID)
136 { 136 {
137 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
137 // Warp! Root folder for travelers 138 // Warp! Root folder for travelers
138 XInventoryFolder[] folders = m_Database.GetFolders( 139 XInventoryFolder[] folders = m_Database.GetFolders(
139 new string[] { "agentID", "folderName"}, 140 new string[] { "agentID", "folderName"},
@@ -171,6 +172,7 @@ namespace OpenSim.Services.HypergridService
171 172
172 public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 173 public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
173 { 174 {
175 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
174 return GetRootFolder(principalID); 176 return GetRootFolder(principalID);
175 } 177 }
176 178
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 09e785f..41d5a88 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -31,10 +31,12 @@ using System.Net;
31using System.Reflection; 31using System.Reflection;
32 32
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
34using OpenSim.Services.Connectors.Hypergrid; 35using OpenSim.Services.Connectors.Hypergrid;
35using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion; 37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37using OpenSim.Server.Base; 38using OpenSim.Server.Base;
39using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38 40
39using OpenMetaverse; 41using OpenMetaverse;
40using log4net; 42using log4net;
@@ -63,19 +65,35 @@ namespace OpenSim.Services.HypergridService
63 protected static IGridService m_GridService; 65 protected static IGridService m_GridService;
64 protected static GatekeeperServiceConnector m_GatekeeperConnector; 66 protected static GatekeeperServiceConnector m_GatekeeperConnector;
65 protected static IGatekeeperService m_GatekeeperService; 67 protected static IGatekeeperService m_GatekeeperService;
68 protected static IFriendsService m_FriendsService;
69 protected static IPresenceService m_PresenceService;
70 protected static IUserAccountService m_UserAccountService;
71 protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
72 protected static FriendsSimConnector m_FriendsSimConnector; // grid
66 73
67 protected static string m_GridName; 74 protected static string m_GridName;
68 75
69 protected static bool m_BypassClientVerification; 76 protected static bool m_BypassClientVerification;
70 77
71 public UserAgentService(IConfigSource config) 78 public UserAgentService(IConfigSource config) : this(config, null)
72 { 79 {
80 }
81
82 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
83 {
84 // Let's set this always, because we don't know the sequence
85 // of instantiations
86 if (friendsConnector != null)
87 m_FriendsLocalSimConnector = friendsConnector;
88
73 if (!m_Initialized) 89 if (!m_Initialized)
74 { 90 {
75 m_Initialized = true; 91 m_Initialized = true;
76 92
77 m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); 93 m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
78 94
95 m_FriendsSimConnector = new FriendsSimConnector();
96
79 IConfig serverConfig = config.Configs["UserAgentService"]; 97 IConfig serverConfig = config.Configs["UserAgentService"];
80 if (serverConfig == null) 98 if (serverConfig == null)
81 throw new Exception(String.Format("No section UserAgentService in config file")); 99 throw new Exception(String.Format("No section UserAgentService in config file"));
@@ -83,6 +101,9 @@ namespace OpenSim.Services.HypergridService
83 string gridService = serverConfig.GetString("GridService", String.Empty); 101 string gridService = serverConfig.GetString("GridService", String.Empty);
84 string gridUserService = serverConfig.GetString("GridUserService", String.Empty); 102 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
85 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); 103 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty);
104 string friendsService = serverConfig.GetString("FriendsService", String.Empty);
105 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
106 string userAccountService = serverConfig.GetString("UserAccountService", String.Empty);
86 107
87 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); 108 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false);
88 109
@@ -94,6 +115,9 @@ namespace OpenSim.Services.HypergridService
94 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 115 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
95 m_GatekeeperConnector = new GatekeeperServiceConnector(); 116 m_GatekeeperConnector = new GatekeeperServiceConnector();
96 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args); 117 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
118 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
119 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
120 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
97 121
98 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 122 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
99 if (m_GridName == string.Empty) 123 if (m_GridName == string.Empty)
@@ -155,12 +179,17 @@ namespace OpenSim.Services.HypergridService
155 string myExternalIP = string.Empty; 179 string myExternalIP = string.Empty;
156 string gridName = gatekeeper.ServerURI; 180 string gridName = gatekeeper.ServerURI;
157 181
158 m_log.DebugFormat("[USER AGENT SERVICE]: m_grid - {0}, gn - {1}", m_GridName, gridName); 182 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
159 183
160 if (m_GridName == gridName) 184 if (m_GridName == gridName)
161 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 185 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
162 else 186 else
187 {
163 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); 188 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason);
189 if (success)
190 // Report them as nowhere
191 m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero);
192 }
164 193
165 if (!success) 194 if (!success)
166 { 195 {
@@ -168,8 +197,11 @@ namespace OpenSim.Services.HypergridService
168 agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason); 197 agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason);
169 198
170 // restore the old travel info 199 // restore the old travel info
171 lock (m_TravelingAgents) 200 if(reason != "Logins Disabled")
172 m_TravelingAgents[agentCircuit.SessionID] = old; 201 {
202 lock (m_TravelingAgents)
203 m_TravelingAgents[agentCircuit.SessionID] = old;
204 }
173 205
174 return false; 206 return false;
175 } 207 }
@@ -179,6 +211,7 @@ namespace OpenSim.Services.HypergridService
179 if (clientIP != null) 211 if (clientIP != null)
180 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 212 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
181 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; 213 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
214
182 return true; 215 return true;
183 } 216 }
184 217
@@ -289,6 +322,213 @@ namespace OpenSim.Services.HypergridService
289 return false; 322 return false;
290 } 323 }
291 324
325 public List<UUID> StatusNotification(List<string> friends, UUID foreignUserID, bool online)
326 {
327 if (m_FriendsService == null || m_PresenceService == null)
328 {
329 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing");
330 return new List<UUID>();
331 }
332
333 List<UUID> localFriendsOnline = new List<UUID>();
334
335 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count);
336
337 // First, let's double check that the reported friends are, indeed, friends of that user
338 // And let's check that the secret matches
339 List<string> usersToBeNotified = new List<string>();
340 foreach (string uui in friends)
341 {
342 UUID localUserID;
343 string secret = string.Empty, tmp = string.Empty;
344 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
345 {
346 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
347 foreach (FriendInfo finfo in friendInfos)
348 {
349 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret))
350 {
351 // great!
352 usersToBeNotified.Add(localUserID.ToString());
353 }
354 }
355 }
356 }
357
358 // Now, let's send the notifications
359 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count);
360
361 // First, let's send notifications to local users who are online in the home grid
362 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
363 if (friendSessions != null && friendSessions.Length > 0)
364 {
365 PresenceInfo friendSession = null;
366 foreach (PresenceInfo pinfo in friendSessions)
367 if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents
368 {
369 friendSession = pinfo;
370 break;
371 }
372
373 if (friendSession != null)
374 {
375 ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online);
376 usersToBeNotified.Remove(friendSession.UserID.ToString());
377 UUID id;
378 if (UUID.TryParse(friendSession.UserID, out id))
379 localFriendsOnline.Add(id);
380
381 }
382 }
383
384 // Lastly, let's notify the rest who may be online somewhere else
385 foreach (string user in usersToBeNotified)
386 {
387 UUID id = new UUID(user);
388 if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
389 {
390 string url = m_TravelingAgents[id].GridExternalName;
391 // forward
392 m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
393 }
394 }
395
396 // and finally, let's send the online friends
397 if (online)
398 {
399 return localFriendsOnline;
400 }
401 else
402 return new List<UUID>();
403 }
404
405 protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online)
406 {
407 UUID userID;
408 if (UUID.TryParse(user, out userID))
409 {
410 if (m_FriendsLocalSimConnector != null)
411 {
412 m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
413 m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online);
414 }
415 else
416 {
417 GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
418 if (region != null)
419 {
420 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
421 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online);
422 }
423 }
424 }
425 }
426
427 public List<UUID> GetOnlineFriends(UUID foreignUserID, List<string> friends)
428 {
429 List<UUID> online = new List<UUID>();
430
431 if (m_FriendsService == null || m_PresenceService == null)
432 {
433 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing");
434 return online;
435 }
436
437 m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count);
438
439 // First, let's double check that the reported friends are, indeed, friends of that user
440 // And let's check that the secret matches and the rights
441 List<string> usersToBeNotified = new List<string>();
442 foreach (string uui in friends)
443 {
444 UUID localUserID;
445 string secret = string.Empty, tmp = string.Empty;
446 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
447 {
448 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
449 foreach (FriendInfo finfo in friendInfos)
450 {
451 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) &&
452 (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1))
453 {
454 // great!
455 usersToBeNotified.Add(localUserID.ToString());
456 }
457 }
458 }
459 }
460
461 // Now, let's find out their status
462 m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count);
463
464 // First, let's send notifications to local users who are online in the home grid
465 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
466 if (friendSessions != null && friendSessions.Length > 0)
467 {
468 foreach (PresenceInfo pi in friendSessions)
469 {
470 UUID presenceID;
471 if (UUID.TryParse(pi.UserID, out presenceID))
472 online.Add(presenceID);
473 }
474 }
475
476 return online;
477 }
478
479 public Dictionary<string, object> GetServerURLs(UUID userID)
480 {
481 if (m_UserAccountService == null)
482 {
483 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing");
484 return new Dictionary<string, object>();
485 }
486 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID);
487 if (account != null)
488 return account.ServiceURLs;
489
490 return new Dictionary<string, object>();
491 }
492
493 public string LocateUser(UUID userID)
494 {
495 foreach (TravelingAgentInfo t in m_TravelingAgents.Values)
496 {
497 if (t == null)
498 {
499 m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis");
500 continue;
501 }
502 if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName))
503 return t.GridExternalName;
504 }
505
506 return string.Empty;
507 }
508
509 public string GetUUI(UUID userID, UUID targetUserID)
510 {
511 // Let's see if it's a local user
512 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID);
513 if (account != null)
514 return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ;
515
516 // Let's try the list of friends
517 FriendInfo[] friends = m_FriendsService.GetFriends(userID);
518 if (friends != null && friends.Length > 0)
519 {
520 foreach (FriendInfo f in friends)
521 if (f.Friend.StartsWith(targetUserID.ToString()))
522 {
523 // Let's remove the secret
524 UUID id; string tmp = string.Empty, secret = string.Empty;
525 if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret))
526 return f.Friend.Replace(secret, "0");
527 }
528 }
529
530 return string.Empty;
531 }
292 } 532 }
293 533
294 class TravelingAgentInfo 534 class TravelingAgentInfo