aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs92
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs162
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs3
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs4
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs84
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs91
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs172
-rw-r--r--OpenSim/Services/Interfaces/IGatekeeperService.cs3
-rw-r--r--OpenSim/Services/Interfaces/ISimulatorSocialService.cs40
9 files changed, 599 insertions, 52 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 7d94813..f82716d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -139,7 +139,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
139 if (moduleConfig != null) 139 if (moduleConfig != null)
140 { 140 {
141 string name = moduleConfig.GetString("FriendsModule", "FriendsModule"); 141 string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
142 m_log.DebugFormat("[XXX] {0} compared to {1}", name, Name);
143 if (name == Name) 142 if (name == Name)
144 { 143 {
145 InitModule(config); 144 InitModule(config);
@@ -183,7 +182,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
183 { 182 {
184 } 183 }
185 184
186 public void AddRegion(Scene scene) 185 public virtual void AddRegion(Scene scene)
187 { 186 {
188 if (!m_Enabled) 187 if (!m_Enabled)
189 return; 188 return;
@@ -302,6 +301,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
302 { 301 {
303 UUID agentID = client.AgentId; 302 UUID agentID = client.AgentId;
304 303
304 //m_log.DebugFormat("[XXX]: OnClientLogin!");
305 // Inform the friends that this user is online 305 // Inform the friends that this user is online
306 StatusChange(agentID, true); 306 StatusChange(agentID, true);
307 307
@@ -405,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
405 } 405 }
406 406
407 if (friendList.Count > 0) 407 if (friendList.Count > 0)
408 { 408 GetOnlineFriends(userID, friendList, online);
409 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
410 foreach (PresenceInfo pi in presence)
411 {
412 UUID presenceID;
413 if (UUID.TryParse(pi.UserID, out presenceID))
414 online.Add(presenceID);
415 }
416 }
417 409
418 return online; 410 return online;
419 } 411 }
420 412
413 protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
414 {
415 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
416 foreach (PresenceInfo pi in presence)
417 {
418 UUID presenceID;
419 if (UUID.TryParse(pi.UserID, out presenceID))
420 online.Add(presenceID);
421 }
422 }
423
421 /// <summary> 424 /// <summary>
422 /// Find the client for a ID 425 /// Find the client for a ID
423 /// </summary> 426 /// </summary>
@@ -472,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
472 Util.FireAndForget( 475 Util.FireAndForget(
473 delegate 476 delegate
474 { 477 {
475 foreach (FriendInfo fi in friendList) 478 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
476 { 479 // Notify about this user status
477 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); 480 StatusNotify(friendList, agentID, online);
478 // Notify about this user status
479 StatusNotify(fi, agentID, online);
480 }
481 } 481 }
482 ); 482 );
483 } 483 }
484 } 484 }
485 485
486 private void StatusNotify(FriendInfo friend, UUID userID, bool online) 486 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
487 { 487 {
488 UUID friendID; 488 foreach (FriendInfo friend in friendList)
489 if (UUID.TryParse(friend.Friend, out friendID))
490 { 489 {
491 // Try local 490 UUID friendID;
492 if (LocalStatusNotification(userID, friendID, online)) 491 if (UUID.TryParse(friend.Friend, out friendID))
493 return;
494
495 // The friend is not here [as root]. Let's forward.
496 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
497 if (friendSessions != null && friendSessions.Length > 0)
498 { 492 {
499 PresenceInfo friendSession = null; 493 // Try local
500 foreach (PresenceInfo pinfo in friendSessions) 494 if (LocalStatusNotification(userID, friendID, online))
501 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 495 return;
502 {
503 friendSession = pinfo;
504 break;
505 }
506 496
507 if (friendSession != null) 497 // The friend is not here [as root]. Let's forward.
498 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
499 if (friendSessions != null && friendSessions.Length > 0)
508 { 500 {
509 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 501 PresenceInfo friendSession = null;
510 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 502 foreach (PresenceInfo pinfo in friendSessions)
511 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); 503 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
504 {
505 friendSession = pinfo;
506 break;
507 }
508
509 if (friendSession != null)
510 {
511 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
512 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
513 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
514 }
512 } 515 }
513 }
514 516
515 // Friend is not online. Ignore. 517 // Friend is not online. Ignore.
516 } 518 }
517 else 519 else
518 { 520 {
519 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 521 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
522 }
520 } 523 }
521 } 524 }
522 525
@@ -670,7 +673,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
670 FriendInfo[] friends = GetFriends(remoteClient.AgentId); 673 FriendInfo[] friends = GetFriends(remoteClient.AgentId);
671 if (friends.Length == 0) 674 if (friends.Length == 0)
672 { 675 {
673 m_log.DebugFormat("[XXX]: agent {0} has no friends", requester);
674 return; 676 return;
675 } 677 }
676 678
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
index c55839f..b0a7567 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -46,7 +46,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
46namespace OpenSim.Region.CoreModules.Avatar.Friends 46namespace OpenSim.Region.CoreModules.Avatar.Friends
47{ 47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule 49 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
50 { 50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52 52
@@ -56,6 +56,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
56 get { return "HGFriendsModule"; } 56 get { return "HGFriendsModule"; }
57 } 57 }
58 58
59 public override void AddRegion(Scene scene)
60 {
61 if (!m_Enabled)
62 return;
63
64 base.AddRegion(scene);
65 scene.RegisterModuleInterface<IFriendsSimConnector>(this);
66 }
67
68 #endregion
69
70 #region IFriendsSimConnector
71
72 /// <summary>
73 /// Notify the user that the friend's status changed
74 /// </summary>
75 /// <param name="userID">user to be notified</param>
76 /// <param name="friendID">friend whose status changed</param>
77 /// <param name="online">status</param>
78 /// <returns></returns>
79 public bool StatusNotify(UUID userID, UUID friendID, bool online)
80 {
81 return LocalStatusNotification(friendID, userID, online);
82 }
83
59 #endregion 84 #endregion
60 85
61 protected override bool FetchFriendslist(IClientAPI client) 86 protected override bool FetchFriendslist(IClientAPI client)
@@ -103,6 +128,140 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
103 return false; 128 return false;
104 } 129 }
105 130
131 protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
132 {
133 // Let's single out the UUIs
134 List<string> localFriends = new List<string>();
135 List<string> foreignFriends = new List<string>();
136 string tmp = string.Empty;
137
138 foreach (string s in friendList)
139 {
140 UUID id;
141 if (UUID.TryParse(s, out id))
142 localFriends.Add(s);
143 else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
144 {
145 foreignFriends.Add(s);
146 // add it here too, who knows maybe the foreign friends happens to be on this grid
147 localFriends.Add(id.ToString());
148 }
149 }
150
151 // OK, see who's present on this grid
152 List<string> toBeRemoved = new List<string>();
153 PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
154 foreach (PresenceInfo pi in presence)
155 {
156 UUID presenceID;
157 if (UUID.TryParse(pi.UserID, out presenceID))
158 {
159 online.Add(presenceID);
160 foreach (string s in foreignFriends)
161 if (s.StartsWith(pi.UserID))
162 toBeRemoved.Add(s);
163 }
164 }
165
166 foreach (string s in toBeRemoved)
167 foreignFriends.Remove(s);
168
169 // OK, let's send this up the stack, and leave a closure here
170 // collecting online friends in other grids
171 Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
172
173 }
174
175 private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
176 {
177 // let's divide the friends on a per-domain basis
178 Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
179 foreach (string friend in foreignFriends)
180 {
181 UUID friendID;
182 if (!UUID.TryParse(friend, out friendID))
183 {
184 // it's a foreign friend
185 string url = string.Empty, tmp = string.Empty;
186 if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
187 {
188 if (!friendsPerDomain.ContainsKey(url))
189 friendsPerDomain[url] = new List<string>();
190 friendsPerDomain[url].Add(friend);
191 }
192 }
193 }
194
195 // Now, call those worlds
196
197 foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
198 {
199 List<string> ids = new List<string>();
200 foreach (string f in kvp.Value)
201 ids.Add(f);
202 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
203 List<UUID> online = uConn.GetOnlineFriends(userID, ids);
204 // Finally send the notifications to the user
205 // this whole process may take a while, so let's check at every
206 // iteration that the user is still here
207 IClientAPI client = LocateClientObject(userID);
208 if (client != null)
209 client.SendAgentOnline(online.ToArray());
210 else
211 break;
212 }
213
214 }
215
216 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
217 {
218 // First, let's divide the friends on a per-domain basis
219 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
220 foreach (FriendInfo friend in friendList)
221 {
222 UUID friendID;
223 if (UUID.TryParse(friend.Friend, out friendID))
224 {
225 if (!friendsPerDomain.ContainsKey("local"))
226 friendsPerDomain["local"] = new List<FriendInfo>();
227 friendsPerDomain["local"].Add(friend);
228 }
229 else
230 {
231 // it's a foreign friend
232 string url = string.Empty, tmp = string.Empty;
233 if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
234 {
235 // Let's try our luck in the local sim. Who knows, maybe it's here
236 if (LocalStatusNotification(userID, friendID, online))
237 continue;
238
239 if (!friendsPerDomain.ContainsKey(url))
240 friendsPerDomain[url] = new List<FriendInfo>();
241 friendsPerDomain[url].Add(friend);
242 }
243 }
244 }
245
246 // For the local friends, just call the base method
247 // Let's do this first of all
248 if (friendsPerDomain.ContainsKey("local"))
249 base.StatusNotify(friendsPerDomain["local"], userID, online);
250
251 foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
252 {
253 if (kvp.Key != "local")
254 {
255 // For the others, call the user agent service
256 List<string> ids = new List<string>();
257 foreach (FriendInfo f in kvp.Value)
258 ids.Add(f.Friend);
259 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
260 uConn.StatusNotification(ids, userID, online);
261 }
262 }
263 }
264
106 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last) 265 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
107 { 266 {
108 first = "Unknown"; last = "User"; 267 first = "Unknown"; last = "User";
@@ -172,7 +331,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
172 { 331 {
173 string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); 332 string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
174 333
175 m_log.DebugFormat("[XXX] GetFriendsFromService to {0}", agentUUI);
176 finfos = FriendsService.GetFriends(agentUUI); 334 finfos = FriendsService.GetFriends(agentUUI);
177 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI); 335 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
178 } 336 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index f5b6817..a5b5637 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -113,7 +113,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>(); 113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
115 115
116 new UserAgentServerConnector(m_Config, MainServer.Instance); 116 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
117 new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
117 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); 118 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
118 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService"); 119 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
119 } 120 }
diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
index a83d0e8..841811e 100644
--- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
@@ -140,16 +140,20 @@ namespace OpenSim.Server.Handlers.Hypergrid
140 140
141 byte[] NewFriendship(Dictionary<string, object> request) 141 byte[] NewFriendship(Dictionary<string, object> request)
142 { 142 {
143 m_log.DebugFormat("[XXX] 1");
143 if (!VerifyServiceKey(request)) 144 if (!VerifyServiceKey(request))
144 return FailureResult(); 145 return FailureResult();
145 146
147 m_log.DebugFormat("[XXX] 2");
146 // OK, can proceed 148 // OK, can proceed
147 FriendInfo friend = new FriendInfo(request); 149 FriendInfo friend = new FriendInfo(request);
148 UUID friendID; 150 UUID friendID;
149 string tmp = string.Empty; 151 string tmp = string.Empty;
152 m_log.DebugFormat("[XXX] 3");
150 if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp)) 153 if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
151 return FailureResult(); 154 return FailureResult();
152 155
156
153 m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend); 157 m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
154 158
155 // If the friendship already exists, return fail 159 // If the friendship already exists, return fail
diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
index 0e8ce80..7a9fb4b 100644
--- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
@@ -54,13 +54,19 @@ namespace OpenSim.Server.Handlers.Hypergrid
54 private IUserAgentService m_HomeUsersService; 54 private IUserAgentService m_HomeUsersService;
55 55
56 public UserAgentServerConnector(IConfigSource config, IHttpServer server) : 56 public UserAgentServerConnector(IConfigSource config, IHttpServer server) :
57 this(config, server, null)
58 {
59 }
60
61 public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) :
57 base(config, server, String.Empty) 62 base(config, server, String.Empty)
58 { 63 {
59 IConfig gridConfig = config.Configs["UserAgentService"]; 64 IConfig gridConfig = config.Configs["UserAgentService"];
60 if (gridConfig != null) 65 if (gridConfig != null)
61 { 66 {
62 string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); 67 string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
63 Object[] args = new Object[] { config }; 68
69 Object[] args = new Object[] { config, friendsConnector };
64 m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args); 70 m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args);
65 } 71 }
66 if (m_HomeUsersService == null) 72 if (m_HomeUsersService == null)
@@ -75,6 +81,9 @@ namespace OpenSim.Server.Handlers.Hypergrid
75 server.AddXmlRPCHandler("verify_client", VerifyClient, false); 81 server.AddXmlRPCHandler("verify_client", VerifyClient, false);
76 server.AddXmlRPCHandler("logout_agent", LogoutAgent, false); 82 server.AddXmlRPCHandler("logout_agent", LogoutAgent, false);
77 83
84 server.AddXmlRPCHandler("status_notification", StatusNotification, false);
85 server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false);
86
78 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); 87 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler);
79 } 88 }
80 89
@@ -194,5 +203,78 @@ namespace OpenSim.Server.Handlers.Hypergrid
194 203
195 } 204 }
196 205
206 public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient)
207 {
208 Hashtable hash = new Hashtable();
209 hash["result"] = "false";
210
211 Hashtable requestData = (Hashtable)request.Params[0];
212 //string host = (string)requestData["host"];
213 //string portstr = (string)requestData["port"];
214 if (requestData.ContainsKey("userID") && requestData.ContainsKey("online"))
215 {
216 string userID_str = (string)requestData["userID"];
217 UUID userID = UUID.Zero;
218 UUID.TryParse(userID_str, out userID);
219 List<string> ids = new List<string>();
220 foreach (object key in requestData.Keys)
221 {
222 if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
223 ids.Add(requestData[key].ToString());
224 }
225 bool online = false;
226 bool.TryParse(requestData["online"].ToString(), out online);
227
228 hash["result"] = "true";
229
230 // let's spawn a thread for this, because it may take a long time...
231 Util.FireAndForget(delegate { m_HomeUsersService.StatusNotification(ids, userID, online); });
232 }
233
234 XmlRpcResponse response = new XmlRpcResponse();
235 response.Value = hash;
236 return response;
237
238 }
239
240 public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient)
241 {
242 Hashtable hash = new Hashtable();
243
244 Hashtable requestData = (Hashtable)request.Params[0];
245 //string host = (string)requestData["host"];
246 //string portstr = (string)requestData["port"];
247 if (requestData.ContainsKey("userID"))
248 {
249 string userID_str = (string)requestData["userID"];
250 UUID userID = UUID.Zero;
251 UUID.TryParse(userID_str, out userID);
252 List<string> ids = new List<string>();
253 foreach (object key in requestData.Keys)
254 {
255 if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
256 ids.Add(requestData[key].ToString());
257 }
258
259 // let's spawn a thread for this, because it may take a long time...
260 List<UUID> online = m_HomeUsersService.GetOnlineFriends(userID, ids);
261 if (online.Count > 0)
262 {
263 int i = 0;
264 foreach (UUID id in online)
265 {
266 hash["friend_" + i.ToString()] = id.ToString();
267 i++;
268 }
269
270 }
271 }
272
273 XmlRpcResponse response = new XmlRpcResponse();
274 response.Value = hash;
275 return response;
276
277 }
278
197 } 279 }
198} 280}
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index c40a347..46d30df 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -404,6 +404,97 @@ namespace OpenSim.Services.Connectors.Hypergrid
404 GetBoolResponse(request, out reason); 404 GetBoolResponse(request, out reason);
405 } 405 }
406 406
407 public void StatusNotification(List<string> friends, UUID userID, bool online)
408 {
409 Hashtable hash = new Hashtable();
410 hash["userID"] = userID.ToString();
411 hash["online"] = online.ToString();
412 int i = 0;
413 foreach (string s in friends)
414 {
415 hash["friend_" + i.ToString()] = s;
416 i++;
417 }
418
419 IList paramList = new ArrayList();
420 paramList.Add(hash);
421
422 XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
423 string reason = string.Empty;
424 GetBoolResponse(request, out reason);
425
426 }
427
428 public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
429 {
430 Hashtable hash = new Hashtable();
431 hash["userID"] = userID.ToString();
432 int i = 0;
433 foreach (string s in friends)
434 {
435 hash["friend_" + i.ToString()] = s;
436 i++;
437 }
438
439 IList paramList = new ArrayList();
440 paramList.Add(hash);
441
442 XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
443 string reason = string.Empty;
444
445 // Send and get reply
446 List<UUID> online = new List<UUID>();
447 XmlRpcResponse response = null;
448 try
449 {
450 response = request.Send(m_ServerURL, 10000);
451 }
452 catch (Exception e)
453 {
454 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
455 reason = "Exception: " + e.Message;
456 return online;
457 }
458
459 if (response.IsFault)
460 {
461 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
462 reason = "XMLRPC Fault";
463 return online;
464 }
465
466 hash = (Hashtable)response.Value;
467 //foreach (Object o in hash)
468 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
469 try
470 {
471 if (hash == null)
472 {
473 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
474 reason = "Internal error 1";
475 return online;
476 }
477
478 // Here is the actual response
479 foreach (object key in hash.Keys)
480 {
481 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
482 {
483 UUID uuid;
484 if (UUID.TryParse(hash[key].ToString(), out uuid))
485 online.Add(uuid);
486 }
487 }
488
489 }
490 catch (Exception e)
491 {
492 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
493 reason = "Exception: " + e.Message;
494 }
495
496 return online;
497 }
407 498
408 private bool GetBoolResponse(XmlRpcRequest request, out string reason) 499 private bool GetBoolResponse(XmlRpcRequest request, out string reason)
409 { 500 {
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 445d45e..0181533 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,34 @@ 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 IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
71 protected static FriendsSimConnector m_FriendsSimConnector; // grid
66 72
67 protected static string m_GridName; 73 protected static string m_GridName;
68 74
69 protected static bool m_BypassClientVerification; 75 protected static bool m_BypassClientVerification;
70 76
71 public UserAgentService(IConfigSource config) 77 public UserAgentService(IConfigSource config) : this(config, null)
72 { 78 {
79 }
80
81 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
82 {
83 // Let's set this always, because we don't know the sequence
84 // of instantiations
85 if (friendsConnector != null)
86 m_FriendsLocalSimConnector = friendsConnector;
87
73 if (!m_Initialized) 88 if (!m_Initialized)
74 { 89 {
75 m_Initialized = true; 90 m_Initialized = true;
76 91
77 m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); 92 m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
78 93
94 m_FriendsSimConnector = new FriendsSimConnector();
95
79 IConfig serverConfig = config.Configs["UserAgentService"]; 96 IConfig serverConfig = config.Configs["UserAgentService"];
80 if (serverConfig == null) 97 if (serverConfig == null)
81 throw new Exception(String.Format("No section UserAgentService in config file")); 98 throw new Exception(String.Format("No section UserAgentService in config file"));
@@ -83,6 +100,8 @@ namespace OpenSim.Services.HypergridService
83 string gridService = serverConfig.GetString("GridService", String.Empty); 100 string gridService = serverConfig.GetString("GridService", String.Empty);
84 string gridUserService = serverConfig.GetString("GridUserService", String.Empty); 101 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
85 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); 102 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty);
103 string friendsService = serverConfig.GetString("FriendsService", String.Empty);
104 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
86 105
87 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); 106 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false);
88 107
@@ -94,6 +113,8 @@ namespace OpenSim.Services.HypergridService
94 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 113 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
95 m_GatekeeperConnector = new GatekeeperServiceConnector(); 114 m_GatekeeperConnector = new GatekeeperServiceConnector();
96 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args); 115 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
116 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
117 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
97 118
98 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 119 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
99 if (m_GridName == string.Empty) 120 if (m_GridName == string.Empty)
@@ -156,11 +177,16 @@ namespace OpenSim.Services.HypergridService
156 string gridName = gatekeeper.ServerURI; 177 string gridName = gatekeeper.ServerURI;
157 178
158 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 179 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
159 180
160 if (m_GridName == gridName) 181 if (m_GridName == gridName)
161 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 182 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
162 else 183 else
184 {
163 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); 185 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason);
186 if (success)
187 // Report them as nowhere
188 m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero);
189 }
164 190
165 if (!success) 191 if (!success)
166 { 192 {
@@ -179,6 +205,7 @@ namespace OpenSim.Services.HypergridService
179 if (clientIP != null) 205 if (clientIP != null)
180 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 206 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
181 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; 207 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
208
182 return true; 209 return true;
183 } 210 }
184 211
@@ -291,6 +318,145 @@ namespace OpenSim.Services.HypergridService
291 return false; 318 return false;
292 } 319 }
293 320
321 public void StatusNotification(List<string> friends, UUID foreignUserID, bool online)
322 {
323 if (m_FriendsService == null || m_PresenceService == null)
324 {
325 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing");
326 return;
327 }
328
329 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count);
330
331 // First, let's double check that the reported friends are, indeed, friends of that user
332 // And let's check that the secret matches
333 List<string> usersToBeNotified = new List<string>();
334 foreach (string uui in friends)
335 {
336 UUID localUserID;
337 string secret = string.Empty, tmp = string.Empty;
338 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
339 {
340 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
341 foreach (FriendInfo finfo in friendInfos)
342 {
343 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret))
344 {
345 // great!
346 usersToBeNotified.Add(localUserID.ToString());
347 }
348 }
349 }
350 }
351
352 // Now, let's send the notifications
353 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count);
354
355 // First, let's send notifications to local users who are online in the home grid
356 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
357 if (friendSessions != null && friendSessions.Length > 0)
358 {
359 PresenceInfo friendSession = null;
360 foreach (PresenceInfo pinfo in friendSessions)
361 if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents
362 {
363 friendSession = pinfo;
364 break;
365 }
366
367 if (friendSession != null)
368 {
369 ForwardStatusNotificationToSim(friendSession.RegionID, friendSession.UserID, foreignUserID, online);
370 usersToBeNotified.Remove(friendSession.UserID.ToString());
371 }
372 }
373
374 // Lastly, let's notify the rest who may be online somewhere else
375 foreach (string user in usersToBeNotified)
376 {
377 UUID id = new UUID(user);
378 if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
379 {
380 string url = m_TravelingAgents[id].GridExternalName;
381 // forward
382 m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
383 }
384 }
385 }
386
387 protected void ForwardStatusNotificationToSim(UUID regionID, string user, UUID foreignUserID, bool online)
388 {
389 UUID userID;
390 if (UUID.TryParse(user, out userID))
391 {
392 if (m_FriendsLocalSimConnector != null)
393 {
394 m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
395 m_FriendsLocalSimConnector.StatusNotify(userID, foreignUserID, online);
396 }
397 else
398 {
399 GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
400 if (region != null)
401 {
402 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, user, foreignUserID, (online ? "online" : "offline"));
403 m_FriendsSimConnector.StatusNotify(region, userID, foreignUserID, online);
404 }
405 }
406 }
407 }
408
409 public List<UUID> GetOnlineFriends(UUID foreignUserID, List<string> friends)
410 {
411 List<UUID> online = new List<UUID>();
412
413 if (m_FriendsService == null || m_PresenceService == null)
414 {
415 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing");
416 return online;
417 }
418
419 m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count);
420
421 // First, let's double check that the reported friends are, indeed, friends of that user
422 // And let's check that the secret matches and the rights
423 List<string> usersToBeNotified = new List<string>();
424 foreach (string uui in friends)
425 {
426 UUID localUserID;
427 string secret = string.Empty, tmp = string.Empty;
428 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
429 {
430 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
431 foreach (FriendInfo finfo in friendInfos)
432 {
433 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) &&
434 (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1))
435 {
436 // great!
437 usersToBeNotified.Add(localUserID.ToString());
438 }
439 }
440 }
441 }
442
443 // Now, let's find out their status
444 m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count);
445
446 // First, let's send notifications to local users who are online in the home grid
447 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
448 if (friendSessions != null && friendSessions.Length > 0)
449 {
450 foreach (PresenceInfo pi in friendSessions)
451 {
452 UUID presenceID;
453 if (UUID.TryParse(pi.UserID, out presenceID))
454 online.Add(presenceID);
455 }
456 }
457
458 return online;
459 }
294 } 460 }
295 461
296 class TravelingAgentInfo 462 class TravelingAgentInfo
diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs
index aac8293..fa1ab1c 100644
--- a/OpenSim/Services/Interfaces/IGatekeeperService.cs
+++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs
@@ -55,6 +55,9 @@ namespace OpenSim.Services.Interfaces
55 void LogoutAgent(UUID userID, UUID sessionID); 55 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); 56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 57
58 void StatusNotification(List<string> friends, UUID userID, bool online);
59 List<UUID> GetOnlineFriends(UUID userID, List<string> friends);
60
58 bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); 61 bool AgentIsComingHome(UUID sessionID, string thisGridExternalName);
59 bool VerifyAgent(UUID sessionID, string token); 62 bool VerifyAgent(UUID sessionID, string token);
60 bool VerifyClient(UUID sessionID, string reportedIP); 63 bool VerifyClient(UUID sessionID, string reportedIP);
diff --git a/OpenSim/Services/Interfaces/ISimulatorSocialService.cs b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs
new file mode 100644
index 0000000..0b7aefc
--- /dev/null
+++ b/OpenSim/Services/Interfaces/ISimulatorSocialService.cs
@@ -0,0 +1,40 @@
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 OpenSim.Framework;
30using OpenMetaverse;
31
32using GridRegion = OpenSim.Services.Interfaces.GridRegion;
33
34namespace OpenSim.Services.Interfaces
35{
36 public interface IFriendsSimConnector
37 {
38 bool StatusNotify(UUID userID, UUID friendID, bool online);
39 }
40}