aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs')
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs459
1 files changed, 459 insertions, 0 deletions
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
new file mode 100644
index 0000000..211b775
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -0,0 +1,459 @@
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.Collections.Specialized;
31using System.Reflection;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
43
44namespace OpenSim.Services.Connectors.SimianGrid
45{
46 /// <summary>
47 /// Connects avatar presence information (for tracking current location and
48 /// message routing) to the SimianGrid backend
49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianPresenceServiceConnector")]
51 public class SimianPresenceServiceConnector : IPresenceService, IGridUserService, ISharedRegionModule
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private string m_serverUrl = String.Empty;
58 private SimianActivityDetector m_activityDetector;
59 private bool m_Enabled = false;
60
61 #region ISharedRegionModule
62
63 public Type ReplaceableInterface { get { return null; } }
64 public void RegionLoaded(Scene scene) { }
65 public void PostInitialise() { }
66 public void Close() { }
67
68 public SimianPresenceServiceConnector() { }
69 public string Name { get { return "SimianPresenceServiceConnector"; } }
70 public void AddRegion(Scene scene)
71 {
72 if (m_Enabled)
73 {
74 scene.RegisterModuleInterface<IPresenceService>(this);
75 scene.RegisterModuleInterface<IGridUserService>(this);
76
77 m_activityDetector.AddRegion(scene);
78
79 LogoutRegionAgents(scene.RegionInfo.RegionID);
80 }
81 }
82 public void RemoveRegion(Scene scene)
83 {
84 if (m_Enabled)
85 {
86 scene.UnregisterModuleInterface<IPresenceService>(this);
87 scene.UnregisterModuleInterface<IGridUserService>(this);
88
89 m_activityDetector.RemoveRegion(scene);
90
91 LogoutRegionAgents(scene.RegionInfo.RegionID);
92 }
93 }
94
95 #endregion ISharedRegionModule
96
97 public SimianPresenceServiceConnector(IConfigSource source)
98 {
99 CommonInit(source);
100 }
101
102 public void Initialise(IConfigSource source)
103 {
104 IConfig moduleConfig = source.Configs["Modules"];
105 if (moduleConfig != null)
106 {
107 string name = moduleConfig.GetString("PresenceServices", "");
108 if (name == Name)
109 CommonInit(source);
110 }
111 }
112
113 private void CommonInit(IConfigSource source)
114 {
115 IConfig gridConfig = source.Configs["PresenceService"];
116 if (gridConfig != null)
117 {
118 string serviceUrl = gridConfig.GetString("PresenceServerURI");
119 if (!String.IsNullOrEmpty(serviceUrl))
120 {
121 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
122 serviceUrl = serviceUrl + '/';
123 m_serverUrl = serviceUrl;
124 m_activityDetector = new SimianActivityDetector(this);
125 m_Enabled = true;
126 }
127 }
128
129 if (String.IsNullOrEmpty(m_serverUrl))
130 m_log.Info("[SIMIAN PRESENCE CONNECTOR]: No PresenceServerURI specified, disabling connector");
131 }
132
133 #region IPresenceService
134
135 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
136 {
137 m_log.ErrorFormat("[SIMIAN PRESENCE CONNECTOR]: Login requested, UserID={0}, SessionID={1}, SecureSessionID={2}",
138 userID, sessionID, secureSessionID);
139
140 NameValueCollection requestArgs = new NameValueCollection
141 {
142 { "RequestMethod", "AddSession" },
143 { "UserID", userID.ToString() }
144 };
145
146 if (sessionID != UUID.Zero)
147 {
148 requestArgs["SessionID"] = sessionID.ToString();
149 requestArgs["SecureSessionID"] = secureSessionID.ToString();
150 }
151
152 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
153 bool success = response["Success"].AsBoolean();
154
155 if (!success)
156 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to login agent " + userID + ": " + response["Message"].AsString());
157
158 return success;
159 }
160
161 public bool LogoutAgent(UUID sessionID)
162 {
163 // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID);
164
165 NameValueCollection requestArgs = new NameValueCollection
166 {
167 { "RequestMethod", "RemoveSession" },
168 { "SessionID", sessionID.ToString() }
169 };
170
171 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
172 bool success = response["Success"].AsBoolean();
173
174 if (!success)
175 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to logout agent with sessionID " + sessionID + ": " + response["Message"].AsString());
176
177 return success;
178 }
179
180 public bool LogoutRegionAgents(UUID regionID)
181 {
182 // m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID);
183
184 NameValueCollection requestArgs = new NameValueCollection
185 {
186 { "RequestMethod", "RemoveSessions" },
187 { "SceneID", regionID.ToString() }
188 };
189
190 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
191 bool success = response["Success"].AsBoolean();
192
193 if (!success)
194 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to logout agents from region " + regionID + ": " + response["Message"].AsString());
195
196 return success;
197 }
198
199 public bool ReportAgent(UUID sessionID, UUID regionID)
200 {
201 // Not needed for SimianGrid
202 return true;
203 }
204
205 public PresenceInfo GetAgent(UUID sessionID)
206 {
207 OSDMap sessionResponse = GetSessionDataFromSessionID(sessionID);
208 if (sessionResponse == null)
209 {
210 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session {0}: {1}",sessionID.ToString(),sessionResponse["Message"].AsString());
211 return null;
212 }
213
214 UUID userID = sessionResponse["UserID"].AsUUID();
215 OSDMap userResponse = GetUserData(userID);
216 if (userResponse == null)
217 {
218 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}: {1}",userID.ToString(),userResponse["Message"].AsString());
219 return null;
220 }
221
222 return ResponseToPresenceInfo(sessionResponse);
223 }
224
225 public PresenceInfo[] GetAgents(string[] userIDs)
226 {
227 List<PresenceInfo> presences = new List<PresenceInfo>();
228
229 NameValueCollection requestArgs = new NameValueCollection
230 {
231 { "RequestMethod", "GetSessions" },
232 { "UserIDList", String.Join(",",userIDs) }
233 };
234
235 OSDMap sessionListResponse = SimianGrid.PostToService(m_serverUrl, requestArgs);
236 if (! sessionListResponse["Success"].AsBoolean())
237 {
238 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve sessions: {0}",sessionListResponse["Message"].AsString());
239 return null;
240 }
241
242 OSDArray sessionList = sessionListResponse["Sessions"] as OSDArray;
243 for (int i = 0; i < sessionList.Count; i++)
244 {
245 OSDMap sessionInfo = sessionList[i] as OSDMap;
246 presences.Add(ResponseToPresenceInfo(sessionInfo));
247 }
248
249 return presences.ToArray();
250 }
251
252 #endregion IPresenceService
253
254 #region IGridUserService
255
256 public GridUserInfo LoggedIn(string userID)
257 {
258 // Never implemented at the sim
259 return null;
260 }
261
262 public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
263 {
264 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID);
265
266 // Remove the session to mark this user offline
267 if (!LogoutAgent(sessionID))
268 return false;
269
270 // Save our last position as user data
271 NameValueCollection requestArgs = new NameValueCollection
272 {
273 { "RequestMethod", "AddUserData" },
274 { "UserID", userID.ToString() },
275 { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
276 };
277
278 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
279 bool success = response["Success"].AsBoolean();
280
281 if (!success)
282 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set last location for " + userID + ": " + response["Message"].AsString());
283
284 return success;
285 }
286
287 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
288 {
289 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID);
290
291 NameValueCollection requestArgs = new NameValueCollection
292 {
293 { "RequestMethod", "AddUserData" },
294 { "UserID", userID.ToString() },
295 { "HomeLocation", SerializeLocation(regionID, position, lookAt) }
296 };
297
298 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
299 bool success = response["Success"].AsBoolean();
300
301 if (!success)
302 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set home location for " + userID + ": " + response["Message"].AsString());
303
304 return success;
305 }
306
307 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
308 {
309 return UpdateSession(sessionID, regionID, lastPosition, lastLookAt);
310 }
311
312 public GridUserInfo GetGridUserInfo(string user)
313 {
314 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user);
315
316 UUID userID = new UUID(user);
317 OSDMap userResponse = GetUserData(userID);
318
319 if (userResponse == null)
320 {
321 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}", userID);
322 }
323
324 // Note that ResponseToGridUserInfo properly checks for and returns a null if passed a null.
325 return ResponseToGridUserInfo(userResponse);
326
327 }
328
329 #endregion
330
331 #region Helpers
332
333 private OSDMap GetUserData(UUID userID)
334 {
335 // m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
336
337 NameValueCollection requestArgs = new NameValueCollection
338 {
339 { "RequestMethod", "GetUser" },
340 { "UserID", userID.ToString() }
341 };
342
343 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
344 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
345 return response;
346
347 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for {0}; {1}",userID.ToString(),response["Message"].AsString());
348 return null;
349 }
350
351 private OSDMap GetSessionDataFromSessionID(UUID sessionID)
352 {
353 NameValueCollection requestArgs = new NameValueCollection
354 {
355 { "RequestMethod", "GetSession" },
356 { "SessionID", sessionID.ToString() }
357 };
358
359 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
360 if (response["Success"].AsBoolean())
361 return response;
362
363 m_log.WarnFormat("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session data for {0}; {1}",sessionID.ToString(),response["Message"].AsString());
364 return null;
365 }
366
367 private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
368 {
369 // Save our current location as session data
370 NameValueCollection requestArgs = new NameValueCollection
371 {
372 { "RequestMethod", "UpdateSession" },
373 { "SessionID", sessionID.ToString() },
374 { "SceneID", regionID.ToString() },
375 { "ScenePosition", lastPosition.ToString() },
376 { "SceneLookAt", lastLookAt.ToString() }
377 };
378
379 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
380 bool success = response["Success"].AsBoolean();
381
382 if (!success)
383 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to update agent session " + sessionID + ": " + response["Message"].AsString());
384
385 return success;
386 }
387
388 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse)
389 {
390 if (sessionResponse == null)
391 return null;
392
393 PresenceInfo info = new PresenceInfo();
394
395 info.UserID = sessionResponse["UserID"].AsUUID().ToString();
396 info.RegionID = sessionResponse["SceneID"].AsUUID();
397
398 return info;
399 }
400
401 private GridUserInfo ResponseToGridUserInfo(OSDMap userResponse)
402 {
403 if (userResponse != null && userResponse["User"] is OSDMap)
404 {
405 GridUserInfo info = new GridUserInfo();
406
407 info.Online = true;
408 info.UserID = userResponse["UserID"].AsUUID().ToString();
409 info.LastRegionID = userResponse["SceneID"].AsUUID();
410 info.LastPosition = userResponse["ScenePosition"].AsVector3();
411 info.LastLookAt = userResponse["SceneLookAt"].AsVector3();
412
413 OSDMap user = (OSDMap)userResponse["User"];
414
415 info.Login = user["LastLoginDate"].AsDate();
416 info.Logout = user["LastLogoutDate"].AsDate();
417 DeserializeLocation(user["HomeLocation"].AsString(), out info.HomeRegionID, out info.HomePosition, out info.HomeLookAt);
418
419 return info;
420 }
421
422 return null;
423 }
424
425 private string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt)
426 {
427 return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}";
428 }
429
430 private bool DeserializeLocation(string location, out UUID regionID, out Vector3 position, out Vector3 lookAt)
431 {
432 OSDMap map = null;
433
434 try { map = OSDParser.DeserializeJson(location) as OSDMap; }
435 catch { }
436
437 if (map != null)
438 {
439 regionID = map["SceneID"].AsUUID();
440 if (Vector3.TryParse(map["Position"].AsString(), out position) &&
441 Vector3.TryParse(map["LookAt"].AsString(), out lookAt))
442 {
443 return true;
444 }
445 }
446
447 regionID = UUID.Zero;
448 position = Vector3.Zero;
449 lookAt = Vector3.Zero;
450 return false;
451 }
452
453 public GridUserInfo[] GetGridUserInfo(string[] userIDs)
454 {
455 return new GridUserInfo[0];
456 }
457 #endregion Helpers
458 }
459}