clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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  
28 using System;
29 using System.Collections.Generic;
30 using System.Collections.Specialized;
31 using System.Reflection;
32 using log4net;
33 using Mono.Addins;
34 using Nini.Config;
35 using OpenSim.Framework;
36 using OpenSim.Region.Framework.Interfaces;
37 using OpenSim.Region.Framework.Scenes;
38 using OpenSim.Services.Interfaces;
39 using OpenMetaverse;
40 using OpenMetaverse.StructuredData;
41  
42 using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
43  
44 namespace 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 }