aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/Connectors
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/Connectors')
-rw-r--r--OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs230
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs373
-rw-r--r--OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs263
-rw-r--r--OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs171
-rw-r--r--OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs123
-rw-r--r--OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs329
-rw-r--r--OpenSim/Services/Connectors/BaseServiceConnector.cs33
-rw-r--r--OpenSim/Services/Connectors/Estate/EstateDataConnector.cs338
-rw-r--r--OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs103
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs269
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs187
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServicesConnector.cs764
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs300
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs332
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs312
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs113
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs625
-rw-r--r--OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs132
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs763
-rw-r--r--OpenSim/Services/Connectors/Land/LandServicesConnector.cs133
-rw-r--r--OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs226
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs205
-rw-r--r--OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs388
-rw-r--r--OpenSim/Services/Connectors/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs100
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs685
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs307
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs344
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs180
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs236
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs147
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs266
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs484
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs941
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs459
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs478
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs337
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs482
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs328
39 files changed, 12519 insertions, 0 deletions
diff --git a/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs b/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs
new file mode 100644
index 0000000..1dbc0c8
--- /dev/null
+++ b/OpenSim/Services/Connectors/AgentPreferences/AgentPreferencesConnector.cs
@@ -0,0 +1,230 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.ServiceAuth;
36using OpenSim.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using IAvatarService = OpenSim.Services.Interfaces.IAvatarService;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class AgentPreferencesServicesConnector : BaseServiceConnector, IAgentPreferencesService
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = String.Empty;
49
50 public AgentPreferencesServicesConnector()
51 {
52 }
53
54 public AgentPreferencesServicesConnector(string serverURI)
55 {
56 m_ServerURI = serverURI.TrimEnd('/');
57 }
58
59 public AgentPreferencesServicesConnector(IConfigSource source)
60 : base(source, "AgentPreferencesService")
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig gridConfig = source.Configs["AgentPreferencesService"];
68 if (gridConfig == null)
69 {
70 m_log.Error("[AGENT PREFERENCES CONNECTOR]: AgentPreferencesService missing from OpenSim.ini");
71 throw new Exception("Agent Preferences connector init error");
72 }
73
74 string serviceURI = gridConfig.GetString("AgentPreferencesServerURI", String.Empty);
75
76 if (serviceURI == String.Empty)
77 {
78 m_log.Error("[AGENT PREFERENCES CONNECTOR]: No Server URI named in section AgentPreferences");
79 throw new Exception("Agent Preferences connector init error");
80 }
81 m_ServerURI = serviceURI;
82
83 base.Initialise(source, "AgentPreferencesService");
84 }
85
86 #region IAgentPreferencesService
87
88 public AgentPrefs GetAgentPreferences(UUID principalID)
89 {
90 Dictionary<string, object> sendData = new Dictionary<string, object>();
91
92 string reply = string.Empty;
93 string uri = String.Concat(m_ServerURI, "/agentprefs");
94
95 sendData["METHOD"] = "getagentprefs";
96 sendData["UserID"] = principalID;
97 string reqString = ServerUtils.BuildQueryString(sendData);
98 // m_log.DebugFormat("[AGENT PREFS CONNECTOR]: queryString = {0}", reqString);
99
100 try
101 {
102 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
103 if (String.IsNullOrEmpty(reply))
104 {
105 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received null or empty reply");
106 return null;
107 }
108 }
109 catch (Exception e)
110 {
111 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message);
112 }
113
114 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
115 if (replyData != null)
116 {
117 if (replyData.ContainsKey("result") &&
118 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
119 {
120 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received Failure response");
121 return null;
122 }
123 }
124 else
125 {
126 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetAgentPreferences received null response");
127 return null;
128 }
129 AgentPrefs prefs = new AgentPrefs(replyData);
130 return prefs;
131 }
132
133 public bool StoreAgentPreferences(AgentPrefs data)
134 {
135 Dictionary<string, object> sendData = new Dictionary<string, object>();
136
137 sendData["METHOD"] = "setagentprefs";
138
139 sendData["PrincipalID"] = data.PrincipalID.ToString();
140 sendData["AccessPrefs"] = data.AccessPrefs;
141 sendData["HoverHeight"] = data.HoverHeight.ToString();
142 sendData["Language"] = data.Language;
143 sendData["LanguageIsPublic"] = data.LanguageIsPublic.ToString();
144 sendData["PermEveryone"] = data.PermEveryone.ToString();
145 sendData["PermGroup"] = data.PermGroup.ToString();
146 sendData["PermNextOwner"] = data.PermNextOwner.ToString();
147
148 string uri = String.Concat(m_ServerURI, "/agentprefs");
149 string reqString = ServerUtils.BuildQueryString(sendData);
150 // m_log.DebugFormat("[AGENT PREFS CONNECTOR]: queryString = {0}", reqString);
151
152 try
153 {
154 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
155 if (reply != string.Empty)
156 {
157 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
158
159 if (replyData.ContainsKey("result"))
160 {
161 if (replyData["result"].ToString().ToLower() == "success")
162 return true;
163 else
164 return false;
165 }
166 else
167 {
168 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: StoreAgentPreferences reply data does not contain result field");
169 }
170
171 }
172 else
173 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: StoreAgentPreferences received empty reply");
174 }
175 catch (Exception e)
176 {
177 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message);
178 }
179
180 return false;
181 }
182
183 public string GetLang(UUID principalID)
184 {
185 Dictionary<string, object> sendData = new Dictionary<string, object>();
186 string reply = string.Empty;
187
188 sendData["METHOD"] = "getagentlang";
189 sendData["UserID"] = principalID.ToString();
190
191 string uri = String.Concat(m_ServerURI, "/agentprefs");
192 string reqString = ServerUtils.BuildQueryString(sendData);
193
194 try
195 {
196 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
197 if (String.IsNullOrEmpty(reply))
198 {
199 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received null or empty reply");
200 return "en-us"; // I guess? Gotta return somethin'!
201 }
202 }
203 catch (Exception e)
204 {
205 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: Exception when contacting agent preferences server at {0}: {1}", uri, e.Message);
206 }
207
208 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
209 if (replyData != null)
210 {
211 if (replyData.ContainsKey("result") &&
212 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
213 {
214 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received Failure response");
215 return "en-us";
216 }
217 if (replyData.ContainsKey("Language"))
218 return replyData["Language"].ToString();
219 }
220 else
221 {
222 m_log.DebugFormat("[AGENT PREFERENCES CONNECTOR]: GetLang received null response");
223
224 }
225 return "en-us";
226 }
227
228 #endregion IAgentPreferencesService
229 }
230}
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
new file mode 100644
index 0000000..badacb7
--- /dev/null
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -0,0 +1,373 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class AssetServicesConnector : BaseServiceConnector, IAssetService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = String.Empty;
49 private IImprovedAssetCache m_Cache = null;
50 private int m_maxAssetRequestConcurrency = 30;
51
52 private delegate void AssetRetrievedEx(AssetBase asset);
53
54 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
55 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded
56 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
57
58 public int MaxAssetRequestConcurrency
59 {
60 get { return m_maxAssetRequestConcurrency; }
61 set { m_maxAssetRequestConcurrency = value; }
62 }
63
64 public AssetServicesConnector()
65 {
66 }
67
68 public AssetServicesConnector(string serverURI)
69 {
70 m_ServerURI = serverURI.TrimEnd('/');
71 }
72
73 public AssetServicesConnector(IConfigSource source)
74 : base(source, "AssetService")
75 {
76 Initialise(source);
77 }
78
79 public virtual void Initialise(IConfigSource source)
80 {
81 IConfig netconfig = source.Configs["Network"];
82 if (netconfig != null)
83 m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency);
84
85 IConfig assetConfig = source.Configs["AssetService"];
86 if (assetConfig == null)
87 {
88 m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini");
89 throw new Exception("Asset connector init error");
90 }
91
92 string serviceURI = assetConfig.GetString("AssetServerURI",
93 String.Empty);
94
95 if (serviceURI == String.Empty)
96 {
97 m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService");
98 throw new Exception("Asset connector init error");
99 }
100
101 m_ServerURI = serviceURI;
102 }
103
104 protected void SetCache(IImprovedAssetCache cache)
105 {
106 m_Cache = cache;
107 }
108
109 public AssetBase Get(string id)
110 {
111// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Synchronous get request for {0}", id);
112
113 string uri = m_ServerURI + "/assets/" + id;
114
115 AssetBase asset = null;
116 if (m_Cache != null)
117 asset = m_Cache.Get(id);
118
119 if (asset == null)
120 {
121 // XXX: Commented out for now since this has either never been properly operational or not for some time
122 // as m_maxAssetRequestConcurrency was being passed as the timeout, not a concurrency limiting option.
123 // Wasn't noticed before because timeout wasn't actually used.
124 // Not attempting concurrency setting for now as this omission was discovered in release candidate
125 // phase for OpenSimulator 0.8. Need to revisit afterwards.
126// asset
127// = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>(
128// "GET", uri, 0, m_maxAssetRequestConcurrency);
129
130 asset = SynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0, m_Auth);
131
132 if (m_Cache != null)
133 m_Cache.Cache(asset);
134 }
135 return asset;
136 }
137
138 public AssetBase GetCached(string id)
139 {
140// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Cache request for {0}", id);
141
142 if (m_Cache != null)
143 return m_Cache.Get(id);
144
145 return null;
146 }
147
148 public AssetMetadata GetMetadata(string id)
149 {
150 if (m_Cache != null)
151 {
152 AssetBase fullAsset = m_Cache.Get(id);
153
154 if (fullAsset != null)
155 return fullAsset.Metadata;
156 }
157
158 string uri = m_ServerURI + "/assets/" + id + "/metadata";
159
160 AssetMetadata asset = SynchronousRestObjectRequester.MakeRequest<int, AssetMetadata>("GET", uri, 0, m_Auth);
161 return asset;
162 }
163
164 public byte[] GetData(string id)
165 {
166 if (m_Cache != null)
167 {
168 AssetBase fullAsset = m_Cache.Get(id);
169
170 if (fullAsset != null)
171 return fullAsset.Data;
172 }
173
174 using (RestClient rc = new RestClient(m_ServerURI))
175 {
176 rc.AddResourcePath("assets");
177 rc.AddResourcePath(id);
178 rc.AddResourcePath("data");
179
180 rc.RequestMethod = "GET";
181
182 Stream s = rc.Request(m_Auth);
183
184 if (s == null)
185 return null;
186
187 if (s.Length > 0)
188 {
189 byte[] ret = new byte[s.Length];
190 s.Read(ret, 0, (int)s.Length);
191
192 return ret;
193 }
194
195 return null;
196 }
197 }
198
199 public bool Get(string id, Object sender, AssetRetrieved handler)
200 {
201// m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Potentially asynchronous get request for {0}", id);
202
203 string uri = m_ServerURI + "/assets/" + id;
204
205 AssetBase asset = null;
206 if (m_Cache != null)
207 asset = m_Cache.Get(id);
208
209 if (asset == null)
210 {
211 lock (m_AssetHandlers)
212 {
213 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
214
215 AssetRetrievedEx handlers;
216 if (m_AssetHandlers.TryGetValue(id, out handlers))
217 {
218 // Someone else is already loading this asset. It will notify our handler when done.
219 handlers += handlerEx;
220 return true;
221 }
222
223 // Load the asset ourselves
224 handlers += handlerEx;
225 m_AssetHandlers.Add(id, handlers);
226 }
227
228 bool success = false;
229 try
230 {
231 AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
232 delegate(AssetBase a)
233 {
234 if (a != null && m_Cache != null)
235 m_Cache.Cache(a);
236
237 AssetRetrievedEx handlers;
238 lock (m_AssetHandlers)
239 {
240 handlers = m_AssetHandlers[id];
241 m_AssetHandlers.Remove(id);
242 }
243 handlers.Invoke(a);
244 }, m_maxAssetRequestConcurrency, m_Auth);
245
246 success = true;
247 }
248 finally
249 {
250 if (!success)
251 {
252 lock (m_AssetHandlers)
253 {
254 m_AssetHandlers.Remove(id);
255 }
256 }
257 }
258 }
259 else
260 {
261 handler(id, sender, asset);
262 }
263
264 return true;
265 }
266
267 public virtual bool[] AssetsExist(string[] ids)
268 {
269 string uri = m_ServerURI + "/get_assets_exist";
270
271 bool[] exist = null;
272 try
273 {
274 exist = SynchronousRestObjectRequester.MakeRequest<string[], bool[]>("POST", uri, ids, m_Auth);
275 }
276 catch (Exception)
277 {
278 // This is most likely to happen because the server doesn't support this function,
279 // so just silently return "doesn't exist" for all the assets.
280 }
281
282 if (exist == null)
283 exist = new bool[ids.Length];
284
285 return exist;
286 }
287
288 public string Store(AssetBase asset)
289 {
290 if (asset.Local)
291 {
292 if (m_Cache != null)
293 m_Cache.Cache(asset);
294
295 return asset.ID;
296 }
297
298 string uri = m_ServerURI + "/assets/";
299
300 string newID;
301 try
302 {
303 newID = SynchronousRestObjectRequester.MakeRequest<AssetBase, string>("POST", uri, asset, m_Auth);
304 }
305 catch (Exception e)
306 {
307 m_log.Warn(string.Format("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1} ", asset.ID, e.Message), e);
308 return string.Empty;
309 }
310
311 // TEMPORARY: SRAS returns 'null' when it's asked to store existing assets
312 if (newID == null)
313 {
314 m_log.DebugFormat("[ASSET CONNECTOR]: Storing of asset {0} returned null; assuming the asset already exists", asset.ID);
315 return asset.ID;
316 }
317
318 if (string.IsNullOrEmpty(newID))
319 return string.Empty;
320
321 asset.ID = newID;
322
323 if (m_Cache != null)
324 m_Cache.Cache(asset);
325
326 return newID;
327 }
328
329 public bool UpdateContent(string id, byte[] data)
330 {
331 AssetBase asset = null;
332
333 if (m_Cache != null)
334 asset = m_Cache.Get(id);
335
336 if (asset == null)
337 {
338 AssetMetadata metadata = GetMetadata(id);
339 if (metadata == null)
340 return false;
341
342 asset = new AssetBase(metadata.FullID, metadata.Name, metadata.Type, UUID.Zero.ToString());
343 asset.Metadata = metadata;
344 }
345 asset.Data = data;
346
347 string uri = m_ServerURI + "/assets/" + id;
348
349 if (SynchronousRestObjectRequester.MakeRequest<AssetBase, bool>("POST", uri, asset, m_Auth))
350 {
351 if (m_Cache != null)
352 m_Cache.Cache(asset);
353
354 return true;
355 }
356 return false;
357 }
358
359 public bool Delete(string id)
360 {
361 string uri = m_ServerURI + "/assets/" + id;
362
363 if (SynchronousRestObjectRequester.MakeRequest<int, bool>("DELETE", uri, 0, m_Auth))
364 {
365 if (m_Cache != null)
366 m_Cache.Expire(id);
367
368 return true;
369 }
370 return false;
371 }
372 }
373}
diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs
new file mode 100644
index 0000000..3710c86
--- /dev/null
+++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs
@@ -0,0 +1,263 @@
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 log4net;
29using Nini.Config;
30using System;
31using System.Collections.Generic;
32using System.Collections.Specialized;
33using System.Reflection;
34using System.Web;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.Hypergrid;
38using OpenSim.Services.Connectors.SimianGrid;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors
42{
43 public class HGAssetServiceConnector : IAssetService
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private Dictionary<IAssetService, object> m_endpointSerializer = new Dictionary<IAssetService, object>();
50 private object EndPointLock(IAssetService connector)
51 {
52 lock (m_endpointSerializer)
53 {
54 object eplock = null;
55
56 if (! m_endpointSerializer.TryGetValue(connector, out eplock))
57 {
58 eplock = new object();
59 m_endpointSerializer.Add(connector, eplock);
60 // m_log.WarnFormat("[WEB UTIL] add a new host to end point serializer {0}",endpoint);
61 }
62
63 return eplock;
64 }
65 }
66
67 private Dictionary<string, IAssetService> m_connectors = new Dictionary<string, IAssetService>();
68
69 public HGAssetServiceConnector(IConfigSource source)
70 {
71 IConfig moduleConfig = source.Configs["Modules"];
72 if (moduleConfig != null)
73 {
74 // string name = moduleConfig.GetString("AssetServices", "");
75
76 IConfig assetConfig = source.Configs["AssetService"];
77 if (assetConfig == null)
78 {
79 m_log.Error("[HG ASSET SERVICE]: AssetService missing from OpenSim.ini");
80 return;
81 }
82
83 m_log.Info("[HG ASSET SERVICE]: HG asset service enabled");
84 }
85 }
86
87 private IAssetService GetConnector(string url)
88 {
89 IAssetService connector = null;
90 lock (m_connectors)
91 {
92 if (m_connectors.ContainsKey(url))
93 {
94 connector = m_connectors[url];
95 }
96 else
97 {
98 // Still not as flexible as I would like this to be,
99 // but good enough for now
100 string connectorType = new HeloServicesConnector(url).Helo();
101 m_log.DebugFormat("[HG ASSET SERVICE]: HELO returned {0}", connectorType);
102 if (connectorType == "opensim-simian")
103 {
104 connector = new SimianAssetServiceConnector(url);
105 }
106 else
107 connector = new AssetServicesConnector(url);
108
109 m_connectors.Add(url, connector);
110 }
111 }
112 return connector;
113 }
114
115 public AssetBase Get(string id)
116 {
117 string url = string.Empty;
118 string assetID = string.Empty;
119
120 if (Util.ParseForeignAssetID(id, out url, out assetID))
121 {
122 IAssetService connector = GetConnector(url);
123 return connector.Get(assetID);
124 }
125
126 return null;
127 }
128
129 public AssetBase GetCached(string id)
130 {
131 string url = string.Empty;
132 string assetID = string.Empty;
133
134 if (Util.ParseForeignAssetID(id, out url, out assetID))
135 {
136 IAssetService connector = GetConnector(url);
137 return connector.GetCached(assetID);
138 }
139
140 return null;
141 }
142
143 public AssetMetadata GetMetadata(string id)
144 {
145 string url = string.Empty;
146 string assetID = string.Empty;
147
148 if (Util.ParseForeignAssetID(id, out url, out assetID))
149 {
150 IAssetService connector = GetConnector(url);
151 return connector.GetMetadata(assetID);
152 }
153
154 return null;
155 }
156
157 public byte[] GetData(string id)
158 {
159 return null;
160 }
161
162 public bool Get(string id, Object sender, AssetRetrieved handler)
163 {
164 string url = string.Empty;
165 string assetID = string.Empty;
166
167 if (Util.ParseForeignAssetID(id, out url, out assetID))
168 {
169 IAssetService connector = GetConnector(url);
170 return connector.Get(assetID, sender, handler);
171 }
172
173 return false;
174 }
175
176
177 private struct AssetAndIndex
178 {
179 public UUID assetID;
180 public int index;
181
182 public AssetAndIndex(UUID assetID, int index)
183 {
184 this.assetID = assetID;
185 this.index = index;
186 }
187 }
188
189 public virtual bool[] AssetsExist(string[] ids)
190 {
191 // This method is a bit complicated because it works even if the assets belong to different
192 // servers; that requires sending separate requests to each server.
193
194 // Group the assets by the server they belong to
195
196 var url2assets = new Dictionary<string, List<AssetAndIndex>>();
197
198 for (int i = 0; i < ids.Length; i++)
199 {
200 string url = string.Empty;
201 string assetID = string.Empty;
202
203 if (Util.ParseForeignAssetID(ids[i], out url, out assetID))
204 {
205 if (!url2assets.ContainsKey(url))
206 url2assets.Add(url, new List<AssetAndIndex>());
207 url2assets[url].Add(new AssetAndIndex(UUID.Parse(assetID), i));
208 }
209 }
210
211 // Query each of the servers in turn
212
213 bool[] exist = new bool[ids.Length];
214
215 foreach (string url in url2assets.Keys)
216 {
217 IAssetService connector = GetConnector(url);
218 lock (EndPointLock(connector))
219 {
220 List<AssetAndIndex> curAssets = url2assets[url];
221 string[] assetIDs = curAssets.ConvertAll(a => a.assetID.ToString()).ToArray();
222 bool[] curExist = connector.AssetsExist(assetIDs);
223
224 int i = 0;
225 foreach (AssetAndIndex ai in curAssets)
226 {
227 exist[ai.index] = curExist[i];
228 ++i;
229 }
230 }
231 }
232
233 return exist;
234 }
235
236 public string Store(AssetBase asset)
237 {
238 string url = string.Empty;
239 string assetID = string.Empty;
240
241 if (Util.ParseForeignAssetID(asset.ID, out url, out assetID))
242 {
243 IAssetService connector = GetConnector(url);
244 // Restore the assetID to a simple UUID
245 asset.ID = assetID;
246 lock (EndPointLock(connector))
247 return connector.Store(asset);
248 }
249
250 return String.Empty;
251 }
252
253 public bool UpdateContent(string id, byte[] data)
254 {
255 return false;
256 }
257
258 public bool Delete(string id)
259 {
260 return false;
261 }
262 }
263}
diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs
new file mode 100644
index 0000000..c8a4912
--- /dev/null
+++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServicesConnector.cs
@@ -0,0 +1,171 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.ServiceAuth;
36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class AuthenticationServicesConnector : BaseServiceConnector, IAuthenticationService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = String.Empty;
49
50 public AuthenticationServicesConnector()
51 {
52 }
53
54 public AuthenticationServicesConnector(string serverURI)
55 {
56 m_ServerURI = serverURI.TrimEnd('/');
57 }
58
59 public AuthenticationServicesConnector(IConfigSource source)
60 : base(source, "AuthenticationService")
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig assetConfig = source.Configs["AuthenticationService"];
68 if (assetConfig == null)
69 {
70 m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini");
71 throw new Exception("Authentication connector init error");
72 }
73
74 string serviceURI = assetConfig.GetString("AuthenticationServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService");
80 throw new Exception("Authentication connector init error");
81 }
82 m_ServerURI = serviceURI;
83
84 base.Initialise(source, "AuthenticationService");
85 }
86
87 public string Authenticate(UUID principalID, string password, int lifetime)
88 {
89 Dictionary<string, object> sendData = new Dictionary<string, object>();
90 sendData["LIFETIME"] = lifetime.ToString();
91 sendData["PRINCIPAL"] = principalID.ToString();
92 sendData["PASSWORD"] = password;
93
94 sendData["METHOD"] = "authenticate";
95
96 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
97 m_ServerURI + "/auth/plain",
98 ServerUtils.BuildQueryString(sendData), m_Auth);
99
100 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
101 reply);
102
103 if (replyData["Result"].ToString() != "Success")
104 return String.Empty;
105
106 return replyData["Token"].ToString();
107 }
108
109 public bool Verify(UUID principalID, string token, int lifetime)
110 {
111// m_log.Error("[XXX]: Verify");
112 Dictionary<string, object> sendData = new Dictionary<string, object>();
113 sendData["LIFETIME"] = lifetime.ToString();
114 sendData["PRINCIPAL"] = principalID.ToString();
115 sendData["TOKEN"] = token;
116
117 sendData["METHOD"] = "verify";
118
119 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
120 m_ServerURI + "/auth/plain",
121 ServerUtils.BuildQueryString(sendData), m_Auth);
122
123 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
124 reply);
125
126 if (replyData["Result"].ToString() != "Success")
127 return false;
128
129 return true;
130 }
131
132 public bool Release(UUID principalID, string token)
133 {
134 Dictionary<string, object> sendData = new Dictionary<string, object>();
135 sendData["PRINCIPAL"] = principalID.ToString();
136 sendData["TOKEN"] = token;
137
138 sendData["METHOD"] = "release";
139
140 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
141 m_ServerURI + "/auth/plain",
142 ServerUtils.BuildQueryString(sendData), m_Auth);
143
144 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
145 reply);
146
147 if (replyData["Result"].ToString() != "Success")
148 return false;
149
150 return true;
151 }
152
153 public bool SetPassword(UUID principalID, string passwd)
154 {
155 // nope, we don't do this
156 return false;
157 }
158
159 public AuthInfo GetAuthInfo(UUID principalID)
160 {
161 // not done from remote simulators
162 return null;
163 }
164
165 public bool SetAuthInfo(AuthInfo info)
166 {
167 // not done from remote simulators
168 return false;
169 }
170 }
171}
diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs
new file mode 100644
index 0000000..63730b3
--- /dev/null
+++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServicesConnector.cs
@@ -0,0 +1,123 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Services.Interfaces;
37using OpenMetaverse;
38
39namespace OpenSim.Services.Connectors
40{
41 public class AuthorizationServicesConnector
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 private string m_ServerURI = String.Empty;
48 private bool m_ResponseOnFailure = true;
49
50 public AuthorizationServicesConnector()
51 {
52 }
53
54 public AuthorizationServicesConnector(string serverURI)
55 {
56 m_ServerURI = serverURI.TrimEnd('/');
57 }
58
59 public AuthorizationServicesConnector(IConfigSource source)
60 {
61 Initialise(source);
62 }
63
64 public virtual void Initialise(IConfigSource source)
65 {
66 IConfig authorizationConfig = source.Configs["AuthorizationService"];
67 if (authorizationConfig == null)
68 {
69 //m_log.Info("[AUTHORIZATION CONNECTOR]: AuthorizationService missing from OpenSim.ini");
70 throw new Exception("Authorization connector init error");
71 }
72
73 string serviceURI = authorizationConfig.GetString("AuthorizationServerURI",
74 String.Empty);
75
76 if (serviceURI == String.Empty)
77 {
78 m_log.Error("[AUTHORIZATION CONNECTOR]: No Server URI named in section AuthorizationService");
79 throw new Exception("Authorization connector init error");
80 }
81 m_ServerURI = serviceURI;
82
83 // this dictates what happens if the remote service fails, if the service fails and the value is true
84 // the user is authorized for the region.
85 bool responseOnFailure = authorizationConfig.GetBoolean("ResponseOnFailure",true);
86
87 m_ResponseOnFailure = responseOnFailure;
88 m_log.Info("[AUTHORIZATION CONNECTOR]: AuthorizationService initialized");
89 }
90
91 public bool IsAuthorizedForRegion(string userID, string firstname, string surname, string email, string regionName, string regionID, out string message)
92 {
93 // do a remote call to the authorization server specified in the AuthorizationServerURI
94 m_log.InfoFormat("[AUTHORIZATION CONNECTOR]: IsAuthorizedForRegion checking {0} at remote server {1}", userID, m_ServerURI);
95
96 string uri = m_ServerURI;
97
98 AuthorizationRequest req = new AuthorizationRequest(userID, firstname, surname, email, regionName, regionID);
99
100 AuthorizationResponse response;
101 try
102 {
103 response = SynchronousRestObjectRequester.MakeRequest<AuthorizationRequest, AuthorizationResponse>("POST", uri, req);
104 }
105 catch (Exception e)
106 {
107 m_log.WarnFormat("[AUTHORIZATION CONNECTOR]: Unable to send authorize {0} for region {1} error thrown during comms with remote server. Reason: {2}", userID, regionID, e.Message);
108 message = e.Message;
109 return m_ResponseOnFailure;
110 }
111 if (response == null)
112 {
113 message = "Null response";
114 return m_ResponseOnFailure;
115 }
116 m_log.DebugFormat("[AUTHORIZATION CONNECTOR] response from remote service was {0}", response.Message);
117 message = response.Message;
118
119 return response.IsAuthorized;
120 }
121
122 }
123}
diff --git a/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs b/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs
new file mode 100644
index 0000000..3f44efa
--- /dev/null
+++ b/OpenSim/Services/Connectors/Avatar/AvatarServicesConnector.cs
@@ -0,0 +1,329 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.ServiceAuth;
36using OpenSim.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using IAvatarService = OpenSim.Services.Interfaces.IAvatarService;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class AvatarServicesConnector : BaseServiceConnector, IAvatarService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public AvatarServicesConnector()
53 {
54 }
55
56 public AvatarServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public AvatarServicesConnector(IConfigSource source)
62 : base(source, "AvatarService")
63 {
64 Initialise(source);
65 }
66
67 public virtual void Initialise(IConfigSource source)
68 {
69 IConfig gridConfig = source.Configs["AvatarService"];
70 if (gridConfig == null)
71 {
72 m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini");
73 throw new Exception("Avatar connector init error");
74 }
75
76 string serviceURI = gridConfig.GetString("AvatarServerURI",
77 String.Empty);
78
79 if (serviceURI == String.Empty)
80 {
81 m_log.Error("[AVATAR CONNECTOR]: No Server URI named in section AvatarService");
82 throw new Exception("Avatar connector init error");
83 }
84 m_ServerURI = serviceURI;
85
86 base.Initialise(source, "AvatarService");
87 }
88
89
90 #region IAvatarService
91
92 public AvatarAppearance GetAppearance(UUID userID)
93 {
94 AvatarData avatar = GetAvatar(userID);
95 return avatar.ToAvatarAppearance();
96 }
97
98 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
99 {
100 AvatarData avatar = new AvatarData(appearance);
101 return SetAvatar(userID,avatar);
102 }
103
104 public AvatarData GetAvatar(UUID userID)
105 {
106 Dictionary<string, object> sendData = new Dictionary<string, object>();
107 //sendData["SCOPEID"] = scopeID.ToString();
108 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
109 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
110 sendData["METHOD"] = "getavatar";
111
112 sendData["UserID"] = userID;
113
114 string reply = string.Empty;
115 string reqString = ServerUtils.BuildQueryString(sendData);
116 string uri = m_ServerURI + "/avatar";
117 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
118 try
119 {
120 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
121 if (reply == null || (reply != null && reply == string.Empty))
122 {
123 m_log.DebugFormat("[AVATAR CONNECTOR]: GetAgent received null or empty reply");
124 return null;
125 }
126 }
127 catch (Exception e)
128 {
129 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
130 }
131
132 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
133 AvatarData avatar = null;
134
135 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
136 {
137 if (replyData["result"] is Dictionary<string, object>)
138 {
139 avatar = new AvatarData((Dictionary<string, object>)replyData["result"]);
140 }
141 }
142
143 return avatar;
144
145 }
146
147 public bool SetAvatar(UUID userID, AvatarData avatar)
148 {
149 Dictionary<string, object> sendData = new Dictionary<string, object>();
150 //sendData["SCOPEID"] = scopeID.ToString();
151 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
152 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
153 sendData["METHOD"] = "setavatar";
154
155 sendData["UserID"] = userID.ToString();
156
157 Dictionary<string, object> structData = avatar.ToKeyValuePairs();
158
159 foreach (KeyValuePair<string, object> kvp in structData)
160 sendData[kvp.Key] = kvp.Value.ToString();
161
162
163 string reqString = ServerUtils.BuildQueryString(sendData);
164 string uri = m_ServerURI + "/avatar";
165 //m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
166 try
167 {
168 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
169 if (reply != string.Empty)
170 {
171 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
172
173 if (replyData.ContainsKey("result"))
174 {
175 if (replyData["result"].ToString().ToLower() == "success")
176 return true;
177 else
178 return false;
179 }
180 else
181 {
182 m_log.DebugFormat("[AVATAR CONNECTOR]: SetAvatar reply data does not contain result field");
183 }
184 }
185 else
186 {
187 m_log.DebugFormat("[AVATAR CONNECTOR]: SetAvatar received empty reply");
188 }
189 }
190 catch (Exception e)
191 {
192 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
193 }
194
195 return false;
196 }
197
198 public bool ResetAvatar(UUID userID)
199 {
200 Dictionary<string, object> sendData = new Dictionary<string, object>();
201 //sendData["SCOPEID"] = scopeID.ToString();
202 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
203 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
204 sendData["METHOD"] = "resetavatar";
205
206 sendData["UserID"] = userID.ToString();
207
208 string reqString = ServerUtils.BuildQueryString(sendData);
209 string uri = m_ServerURI + "/avatar";
210 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
211 try
212 {
213 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
214 if (reply != string.Empty)
215 {
216 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
217
218 if (replyData.ContainsKey("result"))
219 {
220 if (replyData["result"].ToString().ToLower() == "success")
221 return true;
222 else
223 return false;
224 }
225 else
226 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems reply data does not contain result field");
227
228 }
229 else
230 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems received empty reply");
231 }
232 catch (Exception e)
233 {
234 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
235 }
236
237 return false;
238 }
239
240 public bool SetItems(UUID userID, string[] names, string[] values)
241 {
242 Dictionary<string, object> sendData = new Dictionary<string, object>();
243 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
244 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
245 sendData["METHOD"] = "setitems";
246
247 sendData["UserID"] = userID.ToString();
248 sendData["Names"] = new List<string>(names);
249 sendData["Values"] = new List<string>(values);
250
251 string reqString = ServerUtils.BuildQueryString(sendData);
252 string uri = m_ServerURI + "/avatar";
253 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
254 try
255 {
256 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
257 if (reply != string.Empty)
258 {
259 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
260
261 if (replyData.ContainsKey("result"))
262 {
263 if (replyData["result"].ToString().ToLower() == "success")
264 return true;
265 else
266 return false;
267 }
268 else
269 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems reply data does not contain result field");
270
271 }
272 else
273 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems received empty reply");
274 }
275 catch (Exception e)
276 {
277 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
278 }
279
280 return false;
281 }
282
283 public bool RemoveItems(UUID userID, string[] names)
284 {
285 Dictionary<string, object> sendData = new Dictionary<string, object>();
286 //sendData["SCOPEID"] = scopeID.ToString();
287 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
288 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
289 sendData["METHOD"] = "removeitems";
290
291 sendData["UserID"] = userID.ToString();
292 sendData["Names"] = new List<string>(names);
293
294 string reqString = ServerUtils.BuildQueryString(sendData);
295 string uri = m_ServerURI + "/avatar";
296 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
297 try
298 {
299 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
300 if (reply != string.Empty)
301 {
302 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
303
304 if (replyData.ContainsKey("result"))
305 {
306 if (replyData["result"].ToString().ToLower() == "success")
307 return true;
308 else
309 return false;
310 }
311 else
312 m_log.DebugFormat("[AVATAR CONNECTOR]: RemoveItems reply data does not contain result field");
313
314 }
315 else
316 m_log.DebugFormat("[AVATAR CONNECTOR]: RemoveItems received empty reply");
317 }
318 catch (Exception e)
319 {
320 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
321 }
322
323 return false;
324 }
325
326 #endregion
327
328 }
329}
diff --git a/OpenSim/Services/Connectors/BaseServiceConnector.cs b/OpenSim/Services/Connectors/BaseServiceConnector.cs
new file mode 100644
index 0000000..98cd489
--- /dev/null
+++ b/OpenSim/Services/Connectors/BaseServiceConnector.cs
@@ -0,0 +1,33 @@
1using System;
2using OpenSim.Framework;
3using OpenSim.Framework.ServiceAuth;
4
5using Nini.Config;
6
7namespace OpenSim.Services.Connectors
8{
9 public class BaseServiceConnector
10 {
11 protected IServiceAuth m_Auth;
12
13 public BaseServiceConnector() { }
14
15 public BaseServiceConnector(IConfigSource config, string section)
16 {
17 Initialise(config, section);
18 }
19
20 public void Initialise(IConfigSource config, string section)
21 {
22 string authType = Util.GetConfigVarFromSections<string>(config, "AuthType", new string[] { "Network", section }, "None");
23
24 switch (authType)
25 {
26 case "BasicHttpAuthentication":
27 m_Auth = new BasicHttpAuthentication(config, section);
28 break;
29 }
30
31 }
32 }
33}
diff --git a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
new file mode 100644
index 0000000..6412bcd
--- /dev/null
+++ b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
@@ -0,0 +1,338 @@
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 */
27using System;
28using System.Collections.Generic;
29using System.Net;
30using System.Reflection;
31
32using log4net;
33
34using OpenMetaverse;
35using Nini.Config;
36
37using OpenSim.Framework;
38using OpenSim.Framework.ServiceAuth;
39using OpenSim.Services.Connectors;
40using OpenSim.Services.Interfaces;
41using OpenSim.Server.Base;
42
43namespace OpenSim.Services.Connectors
44{
45 public class EstateDataRemoteConnector : BaseServiceConnector, IEstateDataService
46 {
47 private static readonly ILog m_log =
48 LogManager.GetLogger(
49 MethodBase.GetCurrentMethod().DeclaringType);
50
51 private string m_ServerURI = String.Empty;
52 private ExpiringCache<string, List<EstateSettings>> m_EstateCache = new ExpiringCache<string, List<EstateSettings>>();
53 private const int EXPIRATION = 5 * 60; // 5 minutes in secs
54
55 public EstateDataRemoteConnector(IConfigSource source)
56 {
57 Initialise(source);
58 }
59
60 public virtual void Initialise(IConfigSource source)
61 {
62 IConfig gridConfig = source.Configs["EstateService"];
63 if (gridConfig == null)
64 {
65 m_log.Error("[ESTATE CONNECTOR]: EstateService missing from OpenSim.ini");
66 throw new Exception("Estate connector init error");
67 }
68
69 string serviceURI = gridConfig.GetString("EstateServerURI",
70 String.Empty);
71
72 if (serviceURI == String.Empty)
73 {
74 m_log.Error("[ESTATE CONNECTOR]: No Server URI named in section EstateService");
75 throw new Exception("Estate connector init error");
76 }
77 m_ServerURI = serviceURI;
78
79 base.Initialise(source, "EstateService");
80 }
81
82 #region IEstateDataService
83
84 public List<EstateSettings> LoadEstateSettingsAll()
85 {
86 string reply = string.Empty;
87 string uri = m_ServerURI + "/estates";
88
89 reply = MakeRequest("GET", uri, string.Empty);
90 if (String.IsNullOrEmpty(reply))
91 return new List<EstateSettings>();
92
93 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
94
95 List<EstateSettings> estates = new List<EstateSettings>();
96 if (replyData != null && replyData.Count > 0)
97 {
98 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettingsAll returned {0} elements", replyData.Count);
99 Dictionary<string, object>.ValueCollection estateData = replyData.Values;
100 foreach (object r in estateData)
101 {
102 if (r is Dictionary<string, object>)
103 {
104 EstateSettings es = new EstateSettings((Dictionary<string, object>)r);
105 estates.Add(es);
106 }
107 }
108 m_EstateCache.AddOrUpdate("estates", estates, EXPIRATION);
109 }
110 else
111 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettingsAll from {0} received null or zero response", uri);
112
113 return estates;
114
115 }
116
117 public List<int> GetEstatesAll()
118 {
119 List<int> eids = new List<int>();
120 // If we don't have them, load them from the server
121 List<EstateSettings> estates = null;
122 if (!m_EstateCache.TryGetValue("estates", out estates))
123 LoadEstateSettingsAll();
124
125 foreach (EstateSettings es in estates)
126 eids.Add((int)es.EstateID);
127
128 return eids;
129 }
130
131 public List<int> GetEstates(string search)
132 {
133 // If we don't have them, load them from the server
134 List<EstateSettings> estates = null;
135 if (!m_EstateCache.TryGetValue("estates", out estates))
136 LoadEstateSettingsAll();
137
138 List<int> eids = new List<int>();
139 foreach (EstateSettings es in estates)
140 if (es.EstateName == search)
141 eids.Add((int)es.EstateID);
142
143 return eids;
144 }
145
146 public List<int> GetEstatesByOwner(UUID ownerID)
147 {
148 // If we don't have them, load them from the server
149 List<EstateSettings> estates = null;
150 if (!m_EstateCache.TryGetValue("estates", out estates))
151 LoadEstateSettingsAll();
152
153 List<int> eids = new List<int>();
154 foreach (EstateSettings es in estates)
155 if (es.EstateOwner == ownerID)
156 eids.Add((int)es.EstateID);
157
158 return eids;
159 }
160
161 public List<UUID> GetRegions(int estateID)
162 {
163 string reply = string.Empty;
164 // /estates/regions/?eid=int
165 string uri = m_ServerURI + "/estates/regions/?eid=" + estateID.ToString();
166
167 reply = MakeRequest("GET", uri, string.Empty);
168 if (String.IsNullOrEmpty(reply))
169 return new List<UUID>();
170
171 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
172
173 List<UUID> regions = new List<UUID>();
174 if (replyData != null && replyData.Count > 0)
175 {
176 m_log.DebugFormat("[ESTATE CONNECTOR]: GetRegions for estate {0} returned {1} elements", estateID, replyData.Count);
177 Dictionary<string, object>.ValueCollection data = replyData.Values;
178 foreach (object r in data)
179 {
180 UUID uuid = UUID.Zero;
181 if (UUID.TryParse(r.ToString(), out uuid))
182 regions.Add(uuid);
183 }
184 }
185 else
186 m_log.DebugFormat("[ESTATE CONNECTOR]: GetRegions from {0} received null or zero response", uri);
187
188 return regions;
189 }
190
191 public EstateSettings LoadEstateSettings(UUID regionID, bool create)
192 {
193 string reply = string.Empty;
194 // /estates/estate/?region=uuid&create=[t|f]
195 string uri = m_ServerURI + string.Format("/estates/estate/?region={0}&create={1}", regionID, create);
196
197 reply = MakeRequest("GET", uri, string.Empty);
198 if (String.IsNullOrEmpty(reply))
199 return null;
200
201 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
202
203 if (replyData != null && replyData.Count > 0)
204 {
205 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings({0}) returned {1} elements", regionID, replyData.Count);
206 EstateSettings es = new EstateSettings(replyData);
207 return es;
208 }
209 else
210 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings(regionID) from {0} received null or zero response", uri);
211
212 return null;
213 }
214
215 public EstateSettings LoadEstateSettings(int estateID)
216 {
217 string reply = string.Empty;
218 // /estates/estate/?eid=int
219 string uri = m_ServerURI + string.Format("/estates/estate/?eid={0}", estateID);
220
221 reply = MakeRequest("GET", uri, string.Empty);
222 if (String.IsNullOrEmpty(reply))
223 return null;
224
225 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
226
227 if (replyData != null && replyData.Count > 0)
228 {
229 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings({0}) returned {1} elements", estateID, replyData.Count);
230 EstateSettings es = new EstateSettings(replyData);
231 return es;
232 }
233 else
234 m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings(estateID) from {0} received null or zero response", uri);
235
236 return null;
237 }
238
239 /// <summary>
240 /// Forbidden operation
241 /// </summary>
242 /// <returns></returns>
243 public EstateSettings CreateNewEstate()
244 {
245 // No can do
246 return null;
247 }
248
249 public void StoreEstateSettings(EstateSettings es)
250 {
251 // /estates/estate/
252 string uri = m_ServerURI + ("/estates/estate");
253
254 Dictionary<string, object> formdata = es.ToMap();
255 formdata["OP"] = "STORE";
256
257 PostRequest(uri, formdata);
258 }
259
260 public bool LinkRegion(UUID regionID, int estateID)
261 {
262 // /estates/estate/?eid=int&region=uuid
263 string uri = m_ServerURI + String.Format("/estates/estate/?eid={0}&region={1}", estateID, regionID);
264
265 Dictionary<string, object> formdata = new Dictionary<string, object>();
266 formdata["OP"] = "LINK";
267 return PostRequest(uri, formdata);
268 }
269
270 private bool PostRequest(string uri, Dictionary<string, object> sendData)
271 {
272 string reqString = ServerUtils.BuildQueryString(sendData);
273
274 string reply = MakeRequest("POST", uri, reqString);
275 if (String.IsNullOrEmpty(reply))
276 return false;
277
278 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
279
280 bool result = false;
281 if (replyData != null && replyData.Count > 0)
282 {
283 if (replyData.ContainsKey("Result"))
284 {
285 if (Boolean.TryParse(replyData["Result"].ToString(), out result))
286 m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} returned {1}", uri, result);
287 }
288 }
289 else
290 m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} received null or zero response", uri);
291
292 return result;
293 }
294
295 /// <summary>
296 /// Forbidden operation
297 /// </summary>
298 /// <returns></returns>
299 public bool DeleteEstate(int estateID)
300 {
301 return false;
302 }
303
304 #endregion
305
306 private string MakeRequest(string verb, string uri, string formdata)
307 {
308 string reply = string.Empty;
309 try
310 {
311 reply = SynchronousRestFormsRequester.MakeRequest(verb, uri, formdata, m_Auth);
312 }
313 catch (WebException e)
314 {
315 using (HttpWebResponse hwr = (HttpWebResponse)e.Response)
316 {
317 if (hwr != null)
318 {
319 if (hwr.StatusCode == HttpStatusCode.NotFound)
320 m_log.Error(string.Format("[ESTATE CONNECTOR]: Resource {0} not found ", uri));
321 if (hwr.StatusCode == HttpStatusCode.Unauthorized)
322 m_log.Error(string.Format("[ESTATE CONNECTOR]: Web request {0} requires authentication ", uri));
323 }
324 else
325 m_log.Error(string.Format(
326 "[ESTATE CONNECTOR]: WebException for {0} {1} {2} ",
327 verb, uri, formdata, e));
328 }
329 }
330 catch (Exception e)
331 {
332 m_log.DebugFormat("[ESTATE CONNECTOR]: Exception when contacting estate server at {0}: {1}", uri, e.Message);
333 }
334
335 return reply;
336 }
337 }
338}
diff --git a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs
new file mode 100644
index 0000000..d688299
--- /dev/null
+++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs
@@ -0,0 +1,103 @@
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 log4net;
29using System;
30using System.IO;
31using System.Collections;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class RemoteFreeswitchConnector : IFreeswitchService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 private string m_ServerURI = String.Empty;
49
50 public RemoteFreeswitchConnector()
51 {
52 }
53
54 public RemoteFreeswitchConnector(string serverURI)
55 {
56 m_ServerURI = serverURI.TrimEnd('/') + "/region-config";
57 }
58
59 public RemoteFreeswitchConnector(IConfigSource source)
60 {
61 Initialise(source);
62 }
63
64 public virtual void Initialise(IConfigSource source)
65 {
66 IConfig freeswitchConfig = source.Configs["FreeSwitchVoice"];
67 if (freeswitchConfig == null)
68 {
69 m_log.Error("[FREESWITCH CONNECTOR]: FreeSwitchVoice missing from OpenSim.ini");
70 throw new Exception("Freeswitch connector init error");
71 }
72
73 string serviceURI = freeswitchConfig.GetString("FreeswitchServiceURL",
74 String.Empty);
75
76 if (serviceURI == String.Empty)
77 {
78 m_log.Error("[FREESWITCH CONNECTOR]: No FreeswitchServiceURL named in section FreeSwitchVoice");
79 throw new Exception("Freeswitch connector init error");
80 }
81 m_ServerURI = serviceURI.TrimEnd('/') + "/region-config";
82 }
83
84 public Hashtable HandleDirectoryRequest(Hashtable requestBody)
85 {
86 // not used here
87 return new Hashtable();
88 }
89
90 public Hashtable HandleDialplanRequest(Hashtable requestBody)
91 {
92 // not used here
93 return new Hashtable();
94 }
95
96 public string GetJsonConfig()
97 {
98 m_log.DebugFormat("[FREESWITCH CONNECTOR]: Requesting config from {0}", m_ServerURI);
99 return SynchronousRestFormsRequester.MakeRequest("GET",
100 m_ServerURI, String.Empty);
101 }
102 }
103}
diff --git a/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs
new file mode 100644
index 0000000..74851a9
--- /dev/null
+++ b/OpenSim/Services/Connectors/Friends/FriendsServicesConnector.cs
@@ -0,0 +1,269 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.ServiceAuth;
36using OpenSim.Framework.Communications;
37using OpenSim.Services.Interfaces;
38using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors.Friends
43{
44 public class FriendsServicesConnector : BaseServiceConnector, IFriendsService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public FriendsServicesConnector()
53 {
54 }
55
56 public FriendsServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public FriendsServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["FriendsService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[FRIENDS SERVICE CONNECTOR]: FriendsService missing from OpenSim.ini");
72 throw new Exception("Friends connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("FriendsServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[FRIENDS SERVICE CONNECTOR]: No Server URI named in section FriendsService");
81 throw new Exception("Friends connector init error");
82 }
83 m_ServerURI = serviceURI;
84 base.Initialise(source, "FriendsService");
85 }
86
87
88 #region IFriendsService
89
90 public FriendInfo[] GetFriends(UUID PrincipalID)
91 {
92 Dictionary<string, object> sendData = new Dictionary<string, object>();
93
94 sendData["PRINCIPALID"] = PrincipalID.ToString();
95 sendData["METHOD"] = "getfriends";
96
97 return GetFriends(sendData, PrincipalID.ToString());
98 }
99
100 public FriendInfo[] GetFriends(string PrincipalID)
101 {
102 Dictionary<string, object> sendData = new Dictionary<string, object>();
103
104 sendData["PRINCIPALID"] = PrincipalID;
105 sendData["METHOD"] = "getfriends_string";
106
107 return GetFriends(sendData, PrincipalID);
108 }
109
110 protected FriendInfo[] GetFriends(Dictionary<string, object> sendData, string PrincipalID)
111 {
112 string reqString = ServerUtils.BuildQueryString(sendData);
113 string uri = m_ServerURI + "/friends";
114
115 try
116 {
117 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
118 if (reply != string.Empty)
119 {
120 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
121
122 if (replyData != null)
123 {
124 if (replyData.ContainsKey("result") && (replyData["result"].ToString().ToLower() == "null"))
125 {
126 return new FriendInfo[0];
127 }
128
129 List<FriendInfo> finfos = new List<FriendInfo>();
130 Dictionary<string, object>.ValueCollection finfosList = replyData.Values;
131 //m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count);
132 foreach (object f in finfosList)
133 {
134 if (f is Dictionary<string, object>)
135 {
136 FriendInfo finfo = new FriendInfo((Dictionary<string, object>)f);
137 finfos.Add(finfo);
138 }
139 else
140 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: GetFriends {0} received invalid response type {1}",
141 PrincipalID, f.GetType());
142 }
143
144 // Success
145 return finfos.ToArray();
146 }
147 else
148 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: GetFriends {0} received null response",
149 PrincipalID);
150
151 }
152 }
153 catch (Exception e)
154 {
155 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
156 }
157
158 return new FriendInfo[0];
159
160 }
161
162 public bool StoreFriend(string PrincipalID, string Friend, int flags)
163 {
164
165 Dictionary<string, object> sendData = ToKeyValuePairs(PrincipalID, Friend, flags);
166
167 sendData["METHOD"] = "storefriend";
168
169 string reply = string.Empty;
170 string uri = m_ServerURI + "/friends";
171 try
172 {
173 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth);
174 }
175 catch (Exception e)
176 {
177 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
178 return false;
179 }
180
181 if (reply != string.Empty)
182 {
183 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
184
185 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
186 {
187 bool success = false;
188 Boolean.TryParse(replyData["Result"].ToString(), out success);
189 return success;
190 }
191 else
192 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: StoreFriend {0} {1} received null response",
193 PrincipalID, Friend);
194 }
195 else
196 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: StoreFriend received null reply");
197
198 return false;
199
200 }
201
202 public bool Delete(string PrincipalID, string Friend)
203 {
204 Dictionary<string, object> sendData = new Dictionary<string, object>();
205 sendData["PRINCIPALID"] = PrincipalID.ToString();
206 sendData["FRIEND"] = Friend;
207 sendData["METHOD"] = "deletefriend_string";
208
209 return Delete(sendData, PrincipalID, Friend);
210 }
211
212 public bool Delete(UUID PrincipalID, string Friend)
213 {
214 Dictionary<string, object> sendData = new Dictionary<string, object>();
215 sendData["PRINCIPALID"] = PrincipalID.ToString();
216 sendData["FRIEND"] = Friend;
217 sendData["METHOD"] = "deletefriend";
218
219 return Delete(sendData, PrincipalID.ToString(), Friend);
220 }
221
222 public bool Delete(Dictionary<string, object> sendData, string PrincipalID, string Friend)
223 {
224 string reply = string.Empty;
225 string uri = m_ServerURI + "/friends";
226 try
227 {
228 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth);
229 }
230 catch (Exception e)
231 {
232 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
233 return false;
234 }
235
236 if (reply != string.Empty)
237 {
238 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
239
240 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
241 {
242 bool success = false;
243 Boolean.TryParse(replyData["Result"].ToString(), out success);
244 return success;
245 }
246 else
247 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: DeleteFriend {0} {1} received null response",
248 PrincipalID, Friend);
249 }
250 else
251 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: DeleteFriend received null reply");
252
253 return false;
254 }
255
256 #endregion
257
258 public Dictionary<string, object> ToKeyValuePairs(string principalID, string friend, int flags)
259 {
260 Dictionary<string, object> result = new Dictionary<string, object>();
261 result["PrincipalID"] = principalID;
262 result["Friend"] = friend;
263 result["MyFlags"] = flags;
264
265 return result;
266 }
267
268 }
269} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
new file mode 100644
index 0000000..6d5ce4b
--- /dev/null
+++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
@@ -0,0 +1,187 @@
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.Reflection;
31
32using OpenSim.Services.Interfaces;
33using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34using OpenSim.Server.Base;
35using OpenSim.Framework;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Services.Connectors.Friends
41{
42 public class FriendsSimConnector
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 protected virtual string ServicePath()
47 {
48 return "friends";
49 }
50
51 public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message)
52 {
53 return FriendshipOffered(region, userID, friendID, message, String.Empty);
54 }
55
56 public virtual bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message, string userName)
57 {
58 Dictionary<string, object> sendData = new Dictionary<string, object>();
59 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
60 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
61 sendData["METHOD"] = "friendship_offered";
62
63 sendData["FromID"] = userID.ToString();
64 sendData["ToID"] = friendID.ToString();
65 sendData["Message"] = message;
66 if (userName != String.Empty)
67 sendData["FromName"] = userName;
68
69 return Call(region, sendData);
70 }
71
72 public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID)
73 {
74 Dictionary<string, object> sendData = new Dictionary<string, object>();
75 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
76 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
77 sendData["METHOD"] = "friendship_approved";
78
79 sendData["FromID"] = userID.ToString();
80 sendData["FromName"] = userName;
81 sendData["ToID"] = friendID.ToString();
82
83 return Call(region, sendData);
84 }
85
86 public bool FriendshipDenied(GridRegion region, UUID userID, string userName, UUID friendID)
87 {
88 if (region == null)
89 return false;
90
91 Dictionary<string, object> sendData = new Dictionary<string, object>();
92 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
93 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
94 sendData["METHOD"] = "friendship_denied";
95
96 sendData["FromID"] = userID.ToString();
97 sendData["FromName"] = userName;
98 sendData["ToID"] = friendID.ToString();
99
100 return Call(region, sendData);
101 }
102
103 public bool FriendshipTerminated(GridRegion region, UUID userID, UUID friendID)
104 {
105 Dictionary<string, object> sendData = new Dictionary<string, object>();
106 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
107 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
108 sendData["METHOD"] = "friendship_terminated";
109
110 sendData["FromID"] = userID.ToString();
111 sendData["ToID"] = friendID.ToString();
112
113 return Call(region, sendData);
114 }
115
116 public bool GrantRights(GridRegion region, UUID userID, UUID friendID, int userFlags, int rights)
117 {
118 Dictionary<string, object> sendData = new Dictionary<string, object>();
119 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
120 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
121 sendData["METHOD"] = "grant_rights";
122
123 sendData["FromID"] = userID.ToString();
124 sendData["ToID"] = friendID.ToString();
125 sendData["UserFlags"] = userFlags.ToString();
126 sendData["Rights"] = rights.ToString();
127
128 return Call(region, sendData);
129 }
130
131 public bool StatusNotify(GridRegion region, UUID userID, string friendID, bool online)
132 {
133 Dictionary<string, object> sendData = new Dictionary<string, object>();
134 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
135 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
136 sendData["METHOD"] = "status";
137
138 sendData["FromID"] = userID.ToString();
139 sendData["ToID"] = friendID;
140 sendData["Online"] = online.ToString();
141
142 return Call(region, sendData);
143 }
144
145 private bool Call(GridRegion region, Dictionary<string, object> sendData)
146 {
147 string reqString = ServerUtils.BuildQueryString(sendData);
148 //m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: queryString = {0}", reqString);
149 if (region == null)
150 return false;
151
152 string path = ServicePath();
153 if (!region.ServerURI.EndsWith("/"))
154 path = "/" + path;
155 string uri = region.ServerURI + path;
156// m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
157
158 try
159 {
160 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString);
161 if (reply != string.Empty)
162 {
163 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
164
165 if (replyData.ContainsKey("RESULT"))
166 {
167 if (replyData["RESULT"].ToString().ToLower() == "true")
168 return true;
169 else
170 return false;
171 }
172 else
173 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: reply data does not contain result field");
174
175 }
176 else
177 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: received empty reply");
178 }
179 catch (Exception e)
180 {
181 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: Exception when contacting remote sim at {0}: {1}", uri, e.Message);
182 }
183
184 return false;
185 }
186 }
187}
diff --git a/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
new file mode 100644
index 0000000..9e55356
--- /dev/null
+++ b/OpenSim/Services/Connectors/Grid/GridServicesConnector.cs
@@ -0,0 +1,764 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Framework.ServiceAuth;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class GridServicesConnector : BaseServiceConnector, IGridService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public GridServicesConnector()
53 {
54 }
55
56 public GridServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public GridServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["GridService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[GRID CONNECTOR]: GridService missing from OpenSim.ini");
72 throw new Exception("Grid connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("GridServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[GRID CONNECTOR]: No Server URI named in section GridService");
81 throw new Exception("Grid connector init error");
82 }
83 m_ServerURI = serviceURI;
84
85 base.Initialise(source, "GridService");
86 }
87
88
89 #region IGridService
90
91 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
92 {
93 Dictionary<string, object> rinfo = regionInfo.ToKeyValuePairs();
94 Dictionary<string, object> sendData = new Dictionary<string,object>();
95 foreach (KeyValuePair<string, object> kvp in rinfo)
96 sendData[kvp.Key] = (string)kvp.Value;
97
98 sendData["SCOPEID"] = scopeID.ToString();
99 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
100 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
101 sendData["METHOD"] = "register";
102
103 string reqString = ServerUtils.BuildQueryString(sendData);
104 string uri = m_ServerURI + "/grid";
105 // m_log.DebugFormat("[GRID CONNECTOR]: queryString = {0}", reqString);
106 try
107 {
108 string reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
109 if (reply != string.Empty)
110 {
111 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
112
113 if (replyData.ContainsKey("Result")&& (replyData["Result"].ToString().ToLower() == "success"))
114 {
115 return String.Empty;
116 }
117 else if (replyData.ContainsKey("Result")&& (replyData["Result"].ToString().ToLower() == "failure"))
118 {
119 m_log.ErrorFormat(
120 "[GRID CONNECTOR]: Registration failed: {0} when contacting {1}", replyData["Message"], uri);
121
122 return replyData["Message"].ToString();
123 }
124 else if (!replyData.ContainsKey("Result"))
125 {
126 m_log.ErrorFormat(
127 "[GRID CONNECTOR]: reply data does not contain result field when contacting {0}", uri);
128 }
129 else
130 {
131 m_log.ErrorFormat(
132 "[GRID CONNECTOR]: unexpected result {0} when contacting {1}", replyData["Result"], uri);
133
134 return "Unexpected result " + replyData["Result"].ToString();
135 }
136 }
137 else
138 {
139 m_log.ErrorFormat(
140 "[GRID CONNECTOR]: RegisterRegion received null reply when contacting grid server at {0}", uri);
141 }
142 }
143 catch (Exception e)
144 {
145 m_log.ErrorFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
146 }
147
148 return string.Format("Error communicating with the grid service at {0}", uri);
149 }
150
151 public bool DeregisterRegion(UUID regionID)
152 {
153 Dictionary<string, object> sendData = new Dictionary<string, object>();
154
155 sendData["REGIONID"] = regionID.ToString();
156
157 sendData["METHOD"] = "deregister";
158
159 string uri = m_ServerURI + "/grid";
160
161 try
162 {
163 string reply
164 = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth);
165
166 if (reply != string.Empty)
167 {
168 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
169
170 if ((replyData["Result"] != null) && (replyData["Result"].ToString().ToLower() == "success"))
171 return true;
172 }
173 else
174 m_log.DebugFormat("[GRID CONNECTOR]: DeregisterRegion received null reply");
175 }
176 catch (Exception e)
177 {
178 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
179 }
180
181 return false;
182 }
183
184 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
185 {
186 Dictionary<string, object> sendData = new Dictionary<string, object>();
187
188 sendData["SCOPEID"] = scopeID.ToString();
189 sendData["REGIONID"] = regionID.ToString();
190
191 sendData["METHOD"] = "get_neighbours";
192
193 List<GridRegion> rinfos = new List<GridRegion>();
194
195 string reqString = ServerUtils.BuildQueryString(sendData);
196 string reply = string.Empty;
197 string uri = m_ServerURI + "/grid";
198
199 try
200 {
201 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, reqString, m_Auth);
202 }
203 catch (Exception e)
204 {
205 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
206 return rinfos;
207 }
208
209 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
210
211 if (replyData != null)
212 {
213 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
214 //m_log.DebugFormat("[GRID CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count);
215 foreach (object r in rinfosList)
216 {
217 if (r is Dictionary<string, object>)
218 {
219 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
220 rinfos.Add(rinfo);
221 }
222 }
223 }
224 else
225 m_log.DebugFormat("[GRID CONNECTOR]: GetNeighbours {0}, {1} received null response",
226 scopeID, regionID);
227
228 return rinfos;
229 }
230
231 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
232 {
233 Dictionary<string, object> sendData = new Dictionary<string, object>();
234
235 sendData["SCOPEID"] = scopeID.ToString();
236 sendData["REGIONID"] = regionID.ToString();
237
238 sendData["METHOD"] = "get_region_by_uuid";
239
240 string reply = string.Empty;
241 string uri = m_ServerURI + "/grid";
242 try
243 {
244 reply = SynchronousRestFormsRequester.MakeRequest("POST", uri, ServerUtils.BuildQueryString(sendData), m_Auth);
245 }
246 catch (Exception e)
247 {
248 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
249 return null;
250 }
251
252 GridRegion rinfo = null;
253
254 if (reply != string.Empty)
255 {
256 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
257
258 if ((replyData != null) && (replyData["result"] != null))
259 {
260 if (replyData["result"] is Dictionary<string, object>)
261 rinfo = new GridRegion((Dictionary<string, object>)replyData["result"]);
262 //else
263 // m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByUUID {0}, {1} received null response",
264 // scopeID, regionID);
265 }
266 else
267 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByUUID {0}, {1} received null response",
268 scopeID, regionID);
269 }
270 else
271 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByUUID received null reply");
272
273 return rinfo;
274 }
275
276 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
277 {
278 Dictionary<string, object> sendData = new Dictionary<string, object>();
279
280 sendData["SCOPEID"] = scopeID.ToString();
281 sendData["X"] = x.ToString();
282 sendData["Y"] = y.ToString();
283
284 sendData["METHOD"] = "get_region_by_position";
285 string reply = string.Empty;
286 string uri = m_ServerURI + "/grid";
287 try
288 {
289 reply = SynchronousRestFormsRequester.MakeRequest("POST",
290 uri,
291 ServerUtils.BuildQueryString(sendData), m_Auth);
292 }
293 catch (Exception e)
294 {
295 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
296 return null;
297 }
298
299 GridRegion rinfo = null;
300 if (reply != string.Empty)
301 {
302 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
303
304 if ((replyData != null) && (replyData["result"] != null))
305 {
306 if (replyData["result"] is Dictionary<string, object>)
307 rinfo = new GridRegion((Dictionary<string, object>)replyData["result"]);
308 //else
309 // m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received no region",
310 // scopeID, x, y);
311 }
312 else
313 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received null response",
314 scopeID, x, y);
315 }
316 else
317 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition received null reply");
318
319 return rinfo;
320 }
321
322 public GridRegion GetRegionByName(UUID scopeID, string regionName)
323 {
324 Dictionary<string, object> sendData = new Dictionary<string, object>();
325
326 sendData["SCOPEID"] = scopeID.ToString();
327 sendData["NAME"] = regionName;
328
329 sendData["METHOD"] = "get_region_by_name";
330 string reply = string.Empty;
331 string uri = m_ServerURI + "/grid";
332 try
333 {
334 reply = SynchronousRestFormsRequester.MakeRequest("POST",
335 uri,
336 ServerUtils.BuildQueryString(sendData), m_Auth);
337 }
338 catch (Exception e)
339 {
340 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
341 return null;
342 }
343
344 GridRegion rinfo = null;
345 if (reply != string.Empty)
346 {
347 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
348
349 if ((replyData != null) && (replyData["result"] != null))
350 {
351 if (replyData["result"] is Dictionary<string, object>)
352 rinfo = new GridRegion((Dictionary<string, object>)replyData["result"]);
353 }
354 else
355 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1} received null response",
356 scopeID, regionName);
357 }
358 else
359 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByName received null reply");
360
361 return rinfo;
362 }
363
364 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
365 {
366 Dictionary<string, object> sendData = new Dictionary<string, object>();
367
368 sendData["SCOPEID"] = scopeID.ToString();
369 sendData["NAME"] = name;
370 sendData["MAX"] = maxNumber.ToString();
371
372 sendData["METHOD"] = "get_regions_by_name";
373 List<GridRegion> rinfos = new List<GridRegion>();
374 string reply = string.Empty;
375 string uri = m_ServerURI + "/grid";
376 try
377 {
378 reply = SynchronousRestFormsRequester.MakeRequest("POST",
379 uri,
380 ServerUtils.BuildQueryString(sendData), m_Auth);
381 }
382 catch (Exception e)
383 {
384 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
385 return rinfos;
386 }
387
388 if (reply != string.Empty)
389 {
390 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
391
392 if (replyData != null)
393 {
394 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
395 foreach (object r in rinfosList)
396 {
397 if (r is Dictionary<string, object>)
398 {
399 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
400 rinfos.Add(rinfo);
401 }
402 }
403 }
404 else
405 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionsByName {0}, {1}, {2} received null response",
406 scopeID, name, maxNumber);
407 }
408 else
409 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionsByName received null reply");
410
411 return rinfos;
412 }
413
414 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
415 {
416 Dictionary<string, object> sendData = new Dictionary<string, object>();
417
418 sendData["SCOPEID"] = scopeID.ToString();
419 sendData["XMIN"] = xmin.ToString();
420 sendData["XMAX"] = xmax.ToString();
421 sendData["YMIN"] = ymin.ToString();
422 sendData["YMAX"] = ymax.ToString();
423
424 sendData["METHOD"] = "get_region_range";
425
426 List<GridRegion> rinfos = new List<GridRegion>();
427 string reply = string.Empty;
428 string uri = m_ServerURI + "/grid";
429
430 try
431 {
432 reply = SynchronousRestFormsRequester.MakeRequest("POST",
433 uri,
434 ServerUtils.BuildQueryString(sendData), m_Auth);
435
436 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
437 }
438 catch (Exception e)
439 {
440 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
441 return rinfos;
442 }
443
444 if (reply != string.Empty)
445 {
446 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
447
448 if (replyData != null)
449 {
450 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
451 foreach (object r in rinfosList)
452 {
453 if (r is Dictionary<string, object>)
454 {
455 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
456 rinfos.Add(rinfo);
457 }
458 }
459 }
460 else
461 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionRange {0}, {1}-{2} {3}-{4} received null response",
462 scopeID, xmin, xmax, ymin, ymax);
463 }
464 else
465 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionRange received null reply");
466
467 return rinfos;
468 }
469
470 public List<GridRegion> GetDefaultRegions(UUID scopeID)
471 {
472 Dictionary<string, object> sendData = new Dictionary<string, object>();
473
474 sendData["SCOPEID"] = scopeID.ToString();
475
476 sendData["METHOD"] = "get_default_regions";
477
478 List<GridRegion> rinfos = new List<GridRegion>();
479 string reply = string.Empty;
480 string uri = m_ServerURI + "/grid";
481 try
482 {
483 reply = SynchronousRestFormsRequester.MakeRequest("POST",
484 uri,
485 ServerUtils.BuildQueryString(sendData), m_Auth);
486
487 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
488 }
489 catch (Exception e)
490 {
491 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
492 return rinfos;
493 }
494
495 if (reply != string.Empty)
496 {
497 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
498
499 if (replyData != null)
500 {
501 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
502 foreach (object r in rinfosList)
503 {
504 if (r is Dictionary<string, object>)
505 {
506 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
507 rinfos.Add(rinfo);
508 }
509 }
510 }
511 else
512 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultRegions {0} received null response",
513 scopeID);
514 }
515 else
516 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultRegions received null reply");
517
518 return rinfos;
519 }
520
521 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
522 {
523 Dictionary<string, object> sendData = new Dictionary<string, object>();
524
525 sendData["SCOPEID"] = scopeID.ToString();
526
527 sendData["METHOD"] = "get_default_hypergrid_regions";
528
529 List<GridRegion> rinfos = new List<GridRegion>();
530 string reply = string.Empty;
531 string uri = m_ServerURI + "/grid";
532 try
533 {
534 reply = SynchronousRestFormsRequester.MakeRequest("POST",
535 uri,
536 ServerUtils.BuildQueryString(sendData), m_Auth);
537
538 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
539 }
540 catch (Exception e)
541 {
542 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
543 return rinfos;
544 }
545
546 if (reply != string.Empty)
547 {
548 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
549
550 if (replyData != null)
551 {
552 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
553 foreach (object r in rinfosList)
554 {
555 if (r is Dictionary<string, object>)
556 {
557 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
558 rinfos.Add(rinfo);
559 }
560 }
561 }
562 else
563 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions {0} received null response",
564 scopeID);
565 }
566 else
567 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultHypergridRegions received null reply");
568
569 return rinfos;
570 }
571
572 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
573 {
574 Dictionary<string, object> sendData = new Dictionary<string, object>();
575
576 sendData["SCOPEID"] = scopeID.ToString();
577 sendData["X"] = x.ToString();
578 sendData["Y"] = y.ToString();
579
580 sendData["METHOD"] = "get_fallback_regions";
581
582 List<GridRegion> rinfos = new List<GridRegion>();
583 string reply = string.Empty;
584 string uri = m_ServerURI + "/grid";
585 try
586 {
587 reply = SynchronousRestFormsRequester.MakeRequest("POST",
588 uri,
589 ServerUtils.BuildQueryString(sendData), m_Auth);
590
591 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
592 }
593 catch (Exception e)
594 {
595 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
596 return rinfos;
597 }
598
599 if (reply != string.Empty)
600 {
601 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
602
603 if (replyData != null)
604 {
605 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
606 foreach (object r in rinfosList)
607 {
608 if (r is Dictionary<string, object>)
609 {
610 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
611 rinfos.Add(rinfo);
612 }
613 }
614 }
615 else
616 m_log.DebugFormat("[GRID CONNECTOR]: GetFallbackRegions {0}, {1}-{2} received null response",
617 scopeID, x, y);
618 }
619 else
620 m_log.DebugFormat("[GRID CONNECTOR]: GetFallbackRegions received null reply");
621
622 return rinfos;
623 }
624
625 public List<GridRegion> GetHyperlinks(UUID scopeID)
626 {
627 Dictionary<string, object> sendData = new Dictionary<string, object>();
628
629 sendData["SCOPEID"] = scopeID.ToString();
630
631 sendData["METHOD"] = "get_hyperlinks";
632
633 List<GridRegion> rinfos = new List<GridRegion>();
634 string reply = string.Empty;
635 string uri = m_ServerURI + "/grid";
636 try
637 {
638 reply = SynchronousRestFormsRequester.MakeRequest("POST",
639 uri,
640 ServerUtils.BuildQueryString(sendData), m_Auth);
641
642 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
643 }
644 catch (Exception e)
645 {
646 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
647 return rinfos;
648 }
649
650 if (reply != string.Empty)
651 {
652 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
653
654 if (replyData != null)
655 {
656 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
657 foreach (object r in rinfosList)
658 {
659 if (r is Dictionary<string, object>)
660 {
661 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
662 rinfos.Add(rinfo);
663 }
664 }
665 }
666 else
667 m_log.DebugFormat("[GRID CONNECTOR]: GetHyperlinks {0} received null response",
668 scopeID);
669 }
670 else
671 m_log.DebugFormat("[GRID CONNECTOR]: GetHyperlinks received null reply");
672
673 return rinfos;
674 }
675
676 public int GetRegionFlags(UUID scopeID, UUID regionID)
677 {
678 Dictionary<string, object> sendData = new Dictionary<string, object>();
679
680 sendData["SCOPEID"] = scopeID.ToString();
681 sendData["REGIONID"] = regionID.ToString();
682
683 sendData["METHOD"] = "get_region_flags";
684
685 string reply = string.Empty;
686 string uri = m_ServerURI + "/grid";
687 try
688 {
689 reply = SynchronousRestFormsRequester.MakeRequest("POST",
690 uri,
691 ServerUtils.BuildQueryString(sendData), m_Auth);
692 }
693 catch (Exception e)
694 {
695 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server at {0}: {1}", uri, e.Message);
696 return -1;
697 }
698
699 int flags = -1;
700
701 if (reply != string.Empty)
702 {
703 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
704
705 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
706 {
707 Int32.TryParse((string)replyData["result"], out flags);
708 //else
709 // m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags {0}, {1} received wrong type {2}",
710 // scopeID, regionID, replyData["result"].GetType());
711 }
712 else
713 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags {0}, {1} received null response",
714 scopeID, regionID);
715 }
716 else
717 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags received null reply");
718
719 return flags;
720 }
721
722 public Dictionary<string, object> GetExtraFeatures()
723 {
724 Dictionary<string, object> sendData = new Dictionary<string, object>();
725 Dictionary<string, object> extraFeatures = new Dictionary<string, object>();
726
727 sendData["METHOD"] = "get_grid_extra_features";
728
729 string reply = string.Empty;
730 string uri = m_ServerURI + "/grid";
731
732 try
733 {
734 reply = SynchronousRestFormsRequester.MakeRequest("POST",
735 uri,
736 ServerUtils.BuildQueryString(sendData), m_Auth);
737 }
738 catch (Exception e)
739 {
740 m_log.DebugFormat("[GRID CONNECTOR]: GetExtraFeatures - Exception when contacting grid server at {0}: {1}", uri, e.Message);
741 return extraFeatures;
742 }
743
744 if (reply != string.Empty)
745 {
746 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
747
748 if ((replyData != null) && replyData.Count > 0)
749 {
750 foreach (string key in replyData.Keys)
751 {
752 extraFeatures[key] = replyData[key].ToString();
753 }
754 }
755 }
756 else
757 m_log.DebugFormat("[GRID CONNECTOR]: GetExtraServiceURLs received null reply");
758
759 return extraFeatures;
760 }
761 #endregion
762
763 }
764}
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
new file mode 100644
index 0000000..ffdd94a
--- /dev/null
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
@@ -0,0 +1,300 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Framework.ServiceAuth;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class GridUserServicesConnector : BaseServiceConnector, IGridUserService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public GridUserServicesConnector()
53 {
54 }
55
56 public GridUserServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public GridUserServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["GridUserService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[GRID USER CONNECTOR]: GridUserService missing from OpenSim.ini");
72 throw new Exception("GridUser connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("GridUserServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[GRID USER CONNECTOR]: No Server URI named in section GridUserService");
81 throw new Exception("GridUser connector init error");
82 }
83 m_ServerURI = serviceURI;
84 base.Initialise(source, "GridUserService");
85 }
86
87
88 #region IGridUserService
89
90
91 public GridUserInfo LoggedIn(string userID)
92 {
93 Dictionary<string, object> sendData = new Dictionary<string, object>();
94 //sendData["SCOPEID"] = scopeID.ToString();
95 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
96 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
97 sendData["METHOD"] = "loggedin";
98
99 sendData["UserID"] = userID;
100
101 return Get(sendData);
102
103 }
104
105 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
106 {
107 Dictionary<string, object> sendData = new Dictionary<string, object>();
108 //sendData["SCOPEID"] = scopeID.ToString();
109 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
110 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
111 sendData["METHOD"] = "loggedout";
112
113 return Set(sendData, userID, region, position, lookat);
114 }
115
116 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
117 {
118 Dictionary<string, object> sendData = new Dictionary<string, object>();
119 //sendData["SCOPEID"] = scopeID.ToString();
120 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
121 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
122 sendData["METHOD"] = "sethome";
123
124 return Set(sendData, userID, regionID, position, lookAt);
125 }
126
127 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
128 {
129 Dictionary<string, object> sendData = new Dictionary<string, object>();
130 //sendData["SCOPEID"] = scopeID.ToString();
131 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
132 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
133 sendData["METHOD"] = "setposition";
134
135 return Set(sendData, userID, regionID, position, lookAt);
136 }
137
138 public GridUserInfo GetGridUserInfo(string userID)
139 {
140 Dictionary<string, object> sendData = new Dictionary<string, object>();
141 //sendData["SCOPEID"] = scopeID.ToString();
142 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
143 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
144 sendData["METHOD"] = "getgriduserinfo";
145
146 sendData["UserID"] = userID;
147
148 return Get(sendData);
149 }
150
151 #endregion
152
153 protected bool Set(Dictionary<string, object> sendData, string userID, UUID regionID, Vector3 position, Vector3 lookAt)
154 {
155 sendData["UserID"] = userID;
156 sendData["RegionID"] = regionID.ToString();
157 sendData["Position"] = position.ToString();
158 sendData["LookAt"] = lookAt.ToString();
159
160 string reqString = ServerUtils.BuildQueryString(sendData);
161 string uri = m_ServerURI + "/griduser";
162 // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString);
163 try
164 {
165 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
166 uri,
167 reqString,
168 m_Auth);
169 if (reply != string.Empty)
170 {
171 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
172
173 if (replyData.ContainsKey("result"))
174 {
175 if (replyData["result"].ToString().ToLower() == "success")
176 return true;
177 else
178 return false;
179 }
180 else
181 m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition reply data does not contain result field");
182
183 }
184 else
185 m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition received empty reply");
186 }
187 catch (Exception e)
188 {
189 m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server at {0}: {1}", uri, e.Message);
190 }
191
192 return false;
193 }
194
195 protected GridUserInfo Get(Dictionary<string, object> sendData)
196 {
197 string reqString = ServerUtils.BuildQueryString(sendData);
198 string uri = m_ServerURI + "/griduser";
199 // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString);
200 try
201 {
202 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
203 uri,
204 reqString,
205 m_Auth);
206 if (reply != string.Empty)
207 {
208 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
209 GridUserInfo guinfo = null;
210
211 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
212 {
213 if (replyData["result"] is Dictionary<string, object>)
214 guinfo = Create((Dictionary<string, object>)replyData["result"]);
215 }
216
217 return guinfo;
218
219 }
220 else
221 m_log.DebugFormat("[GRID USER CONNECTOR]: Get received empty reply");
222 }
223 catch (Exception e)
224 {
225 m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server at {0}: {1}", uri, e.Message);
226 }
227
228 return null;
229
230 }
231
232 public GridUserInfo[] GetGridUserInfo(string[] userIDs)
233 {
234 Dictionary<string, object> sendData = new Dictionary<string, object>();
235 //sendData["SCOPEID"] = scopeID.ToString();
236 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
237 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
238 sendData["METHOD"] = "getgriduserinfos";
239
240 sendData["AgentIDs"] = new List<string>(userIDs);
241
242 string reply = string.Empty;
243 string reqString = ServerUtils.BuildQueryString(sendData);
244 string uri = m_ServerURI + "/griduser";
245 //m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
246 try
247 {
248 reply = SynchronousRestFormsRequester.MakeRequest("POST",
249 uri,
250 reqString,
251 m_Auth);
252 if (reply == null || (reply != null && reply == string.Empty))
253 {
254 m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received null or empty reply");
255 return null;
256 }
257 }
258 catch (Exception e)
259 {
260 m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server at {0}: {1}", uri, e.Message);
261 }
262
263 List<GridUserInfo> rinfos = new List<GridUserInfo>();
264
265 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
266
267 if (replyData != null)
268 {
269 if (replyData.ContainsKey("result") &&
270 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
271 {
272 return new GridUserInfo[0];
273 }
274
275 Dictionary<string, object>.ValueCollection pinfosList = replyData.Values;
276 //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
277 foreach (object griduser in pinfosList)
278 {
279 if (griduser is Dictionary<string, object>)
280 {
281 GridUserInfo pinfo = Create((Dictionary<string, object>)griduser);
282 rinfos.Add(pinfo);
283 }
284 else
285 m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received invalid response type {0}",
286 griduser.GetType());
287 }
288 }
289 else
290 m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received null response");
291
292 return rinfos.ToArray();
293 }
294
295 protected virtual GridUserInfo Create(Dictionary<string, object> griduser)
296 {
297 return new GridUserInfo(griduser);
298 }
299 }
300}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
new file mode 100644
index 0000000..b1663ee
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -0,0 +1,332 @@
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;
30using System.Collections.Generic;
31using System.Drawing;
32using System.IO;
33using System.Net;
34using System.Reflection;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using OpenMetaverse;
39using OpenMetaverse.Imaging;
40using OpenMetaverse.StructuredData;
41using Nwc.XmlRpc;
42using log4net;
43
44using OpenSim.Services.Connectors.Simulation;
45
46namespace OpenSim.Services.Connectors.Hypergrid
47{
48 public class GatekeeperServiceConnector : SimulationServiceConnector
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private static UUID m_HGMapImage = new UUID("00000000-0000-1111-9999-000000000013");
53
54 private IAssetService m_AssetService;
55
56 public GatekeeperServiceConnector()
57 : base()
58 {
59 }
60
61 public GatekeeperServiceConnector(IAssetService assService)
62 {
63 m_AssetService = assService;
64 }
65
66 protected override string AgentPath()
67 {
68 return "foreignagent/";
69 }
70
71 protected override string ObjectPath()
72 {
73 return "foreignobject/";
74 }
75
76 public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason)
77 {
78 regionID = UUID.Zero;
79 imageURL = string.Empty;
80 realHandle = 0;
81 externalName = string.Empty;
82 reason = string.Empty;
83
84 Hashtable hash = new Hashtable();
85 hash["region_name"] = info.RegionName;
86
87 IList paramList = new ArrayList();
88 paramList.Add(hash);
89
90 XmlRpcRequest request = new XmlRpcRequest("link_region", paramList);
91 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI);
92 XmlRpcResponse response = null;
93 try
94 {
95 response = request.Send(info.ServerURI, 10000);
96 }
97 catch (Exception e)
98 {
99 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message);
100 reason = "Error contacting remote server";
101 return false;
102 }
103
104 if (response.IsFault)
105 {
106 reason = response.FaultString;
107 m_log.ErrorFormat("[GATEKEEPER SERVICE CONNECTOR]: remote call returned an error: {0}", response.FaultString);
108 return false;
109 }
110
111 hash = (Hashtable)response.Value;
112 //foreach (Object o in hash)
113 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
114 try
115 {
116 bool success = false;
117 Boolean.TryParse((string)hash["result"], out success);
118 if (success)
119 {
120 UUID.TryParse((string)hash["uuid"], out regionID);
121 //m_log.Debug(">> HERE, uuid: " + regionID);
122 if ((string)hash["handle"] != null)
123 {
124 realHandle = Convert.ToUInt64((string)hash["handle"]);
125 //m_log.Debug(">> HERE, realHandle: " + realHandle);
126 }
127 if (hash["region_image"] != null)
128 {
129 imageURL = (string)hash["region_image"];
130 //m_log.Debug(">> HERE, imageURL: " + imageURL);
131 }
132 if (hash["external_name"] != null)
133 {
134 externalName = (string)hash["external_name"];
135 //m_log.Debug(">> HERE, externalName: " + externalName);
136 }
137 }
138
139 }
140 catch (Exception e)
141 {
142 reason = "Error parsing return arguments";
143 m_log.Error("[GATEKEEPER SERVICE CONNECTOR]: Got exception while parsing hyperlink response " + e.StackTrace);
144 return false;
145 }
146
147 return true;
148 }
149
150 public UUID GetMapImage(UUID regionID, string imageURL, string storagePath)
151 {
152 if (m_AssetService == null)
153 {
154 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: No AssetService defined. Map tile not retrieved.");
155 return m_HGMapImage;
156 }
157
158 UUID mapTile = m_HGMapImage;
159 string filename = string.Empty;
160
161 try
162 {
163 WebClient c = new WebClient();
164 string name = regionID.ToString();
165 filename = Path.Combine(storagePath, name + ".jpg");
166 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: Map image at {0}, cached at {1}", imageURL, filename);
167 if (!File.Exists(filename))
168 {
169 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: downloading...");
170 c.DownloadFile(imageURL, filename);
171 }
172 else
173 {
174 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: using cached image");
175 }
176
177 byte[] imageData = null;
178
179 using (Bitmap bitmap = new Bitmap(filename))
180 {
181 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
182 imageData = OpenJPEG.EncodeFromImage(bitmap, true);
183 }
184
185 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
186
187 // !!! for now
188 //info.RegionSettings.TerrainImageID = ass.FullID;
189
190 ass.Data = imageData;
191
192 mapTile = ass.FullID;
193
194 // finally
195 m_AssetService.Store(ass);
196
197 }
198 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
199 {
200 m_log.Info("[GATEKEEPER SERVICE CONNECTOR]: Failed getting/storing map image, because it is probably already in the cache");
201 }
202 return mapTile;
203 }
204
205 public GridRegion GetHyperlinkRegion(GridRegion gatekeeper, UUID regionID, UUID agentID, string agentHomeURI, out string message)
206 {
207 Hashtable hash = new Hashtable();
208 hash["region_uuid"] = regionID.ToString();
209 if (agentID != UUID.Zero)
210 {
211 hash["agent_id"] = agentID.ToString();
212 if (agentHomeURI != null)
213 hash["agent_home_uri"] = agentHomeURI;
214 }
215
216 IList paramList = new ArrayList();
217 paramList.Add(hash);
218
219 XmlRpcRequest request = new XmlRpcRequest("get_region", paramList);
220 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI);
221 XmlRpcResponse response = null;
222 try
223 {
224 response = request.Send(gatekeeper.ServerURI, 10000);
225 }
226 catch (Exception e)
227 {
228 message = "Error contacting grid.";
229 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message);
230 return null;
231 }
232
233 if (response.IsFault)
234 {
235 message = "Error contacting grid.";
236 m_log.ErrorFormat("[GATEKEEPER SERVICE CONNECTOR]: remote call returned an error: {0}", response.FaultString);
237 return null;
238 }
239
240 hash = (Hashtable)response.Value;
241 //foreach (Object o in hash)
242 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
243 try
244 {
245 bool success = false;
246 Boolean.TryParse((string)hash["result"], out success);
247
248 if (hash["message"] != null)
249 message = (string)hash["message"];
250 else if (success)
251 message = null;
252 else
253 message = "The teleport destination could not be found."; // probably the dest grid is old and doesn't send 'message', but the most common problem is that the region is unavailable
254
255 if (success)
256 {
257 GridRegion region = new GridRegion();
258
259 UUID.TryParse((string)hash["uuid"], out region.RegionID);
260 //m_log.Debug(">> HERE, uuid: " + region.RegionID);
261 int n = 0;
262 if (hash["x"] != null)
263 {
264 Int32.TryParse((string)hash["x"], out n);
265 region.RegionLocX = n;
266 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
267 }
268 if (hash["y"] != null)
269 {
270 Int32.TryParse((string)hash["y"], out n);
271 region.RegionLocY = n;
272 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
273 }
274 if (hash["size_x"] != null)
275 {
276 Int32.TryParse((string)hash["size_x"], out n);
277 region.RegionSizeX = n;
278 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
279 }
280 if (hash["size_y"] != null)
281 {
282 Int32.TryParse((string)hash["size_y"], out n);
283 region.RegionSizeY = n;
284 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
285 }
286 if (hash["region_name"] != null)
287 {
288 region.RegionName = (string)hash["region_name"];
289 //m_log.Debug(">> HERE, region_name: " + region.RegionName);
290 }
291 if (hash["hostname"] != null)
292 {
293 region.ExternalHostName = (string)hash["hostname"];
294 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
295 }
296 if (hash["http_port"] != null)
297 {
298 uint p = 0;
299 UInt32.TryParse((string)hash["http_port"], out p);
300 region.HttpPort = p;
301 //m_log.Debug(">> HERE, http_port: " + region.HttpPort);
302 }
303 if (hash["internal_port"] != null)
304 {
305 int p = 0;
306 Int32.TryParse((string)hash["internal_port"], out p);
307 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
308 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
309 }
310
311 if (hash["server_uri"] != null)
312 {
313 region.ServerURI = (string)hash["server_uri"];
314 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
315 }
316
317 // Successful return
318 return region;
319 }
320
321 }
322 catch (Exception e)
323 {
324 message = "Error parsing response from grid.";
325 m_log.Error("[GATEKEEPER SERVICE CONNECTOR]: Got exception while parsing hyperlink response " + e.StackTrace);
326 return null;
327 }
328
329 return null;
330 }
331 }
332}
diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs
new file mode 100644
index 0000000..622d4e1
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServicesConnector.cs
@@ -0,0 +1,312 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors.Friends;
37using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors.Hypergrid
42{
43 public class HGFriendsServicesConnector : FriendsSimConnector
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private string m_ServerURI = String.Empty;
50 private string m_ServiceKey = String.Empty;
51 private UUID m_SessionID;
52
53 public HGFriendsServicesConnector()
54 {
55 }
56
57 public HGFriendsServicesConnector(string serverURI)
58 {
59 m_ServerURI = serverURI.TrimEnd('/');
60 }
61
62 public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey)
63 {
64 m_ServerURI = serverURI.TrimEnd('/');
65 m_ServiceKey = serviceKey;
66 m_SessionID = sessionID;
67 }
68
69 protected override string ServicePath()
70 {
71 return "hgfriends";
72 }
73
74 #region IFriendsService
75
76 public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
77 {
78 Dictionary<string, object> sendData = new Dictionary<string, object>();
79
80 sendData["PRINCIPALID"] = PrincipalID.ToString();
81 sendData["FRIENDID"] = friendID.ToString();
82 sendData["METHOD"] = "getfriendperms";
83 sendData["KEY"] = m_ServiceKey;
84 sendData["SESSIONID"] = m_SessionID.ToString();
85
86 string reqString = ServerUtils.BuildQueryString(sendData);
87 string uri = m_ServerURI + "/hgfriends";
88
89 try
90 {
91 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
92 uri,
93 reqString);
94 if (reply != string.Empty)
95 {
96 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
97
98 if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null))
99 {
100 uint perms = 0;
101 uint.TryParse(replyData["Value"].ToString(), out perms);
102 return perms;
103 }
104 else
105 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response",
106 PrincipalID);
107
108 }
109 }
110 catch (Exception e)
111 {
112 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
113 }
114
115 return 0;
116
117 }
118
119 public bool NewFriendship(UUID PrincipalID, string Friend)
120 {
121 FriendInfo finfo = new FriendInfo();
122 finfo.PrincipalID = PrincipalID;
123 finfo.Friend = Friend;
124
125 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
126
127 sendData["METHOD"] = "newfriendship";
128 sendData["KEY"] = m_ServiceKey;
129 sendData["SESSIONID"] = m_SessionID.ToString();
130
131 string reply = string.Empty;
132 string uri = m_ServerURI + "/hgfriends";
133 try
134 {
135 reply = SynchronousRestFormsRequester.MakeRequest("POST",
136 uri,
137 ServerUtils.BuildQueryString(sendData));
138 }
139 catch (Exception e)
140 {
141 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
142 return false;
143 }
144
145 if (reply != string.Empty)
146 {
147 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
148
149 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
150 {
151 bool success = false;
152 Boolean.TryParse(replyData["Result"].ToString(), out success);
153 return success;
154 }
155 else
156 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response",
157 PrincipalID, Friend);
158 }
159 else
160 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply");
161
162 return false;
163
164 }
165
166 public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret)
167 {
168 FriendInfo finfo = new FriendInfo();
169 finfo.PrincipalID = PrincipalID;
170 finfo.Friend = Friend.ToString();
171
172 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
173
174 sendData["METHOD"] = "deletefriendship";
175 sendData["SECRET"] = secret;
176
177 string reply = string.Empty;
178 string uri = m_ServerURI + "/hgfriends";
179 try
180 {
181 reply = SynchronousRestFormsRequester.MakeRequest("POST",
182 uri,
183 ServerUtils.BuildQueryString(sendData));
184 }
185 catch (Exception e)
186 {
187 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
188 return false;
189 }
190
191 if (reply != string.Empty)
192 {
193 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
194
195 if (replyData.ContainsKey("RESULT"))
196 {
197 if (replyData["RESULT"].ToString().ToLower() == "true")
198 return true;
199 else
200 return false;
201 }
202 else
203 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
204
205 }
206 else
207 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
208
209 return false;
210
211 }
212
213 public bool ValidateFriendshipOffered(UUID fromID, UUID toID)
214 {
215 FriendInfo finfo = new FriendInfo();
216 finfo.PrincipalID = fromID;
217 finfo.Friend = toID.ToString();
218
219 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
220
221 sendData["METHOD"] = "validate_friendship_offered";
222
223 string reply = string.Empty;
224 string uri = m_ServerURI + "/hgfriends";
225 try
226 {
227 reply = SynchronousRestFormsRequester.MakeRequest("POST",
228 uri,
229 ServerUtils.BuildQueryString(sendData));
230 }
231 catch (Exception e)
232 {
233 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
234 return false;
235 }
236
237 if (reply != string.Empty)
238 {
239 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
240
241 if (replyData.ContainsKey("RESULT"))
242 {
243 if (replyData["RESULT"].ToString().ToLower() == "true")
244 return true;
245 else
246 return false;
247 }
248 else
249 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: reply data does not contain result field");
250
251 }
252 else
253 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: received empty reply");
254
255 return false;
256
257 }
258
259 public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
260 {
261 Dictionary<string, object> sendData = new Dictionary<string, object>();
262 List<UUID> friendsOnline = new List<UUID>();
263
264 sendData["METHOD"] = "statusnotification";
265 sendData["userID"] = userID.ToString();
266 sendData["online"] = online.ToString();
267 int i = 0;
268 foreach (string s in friends)
269 {
270 sendData["friend_" + i.ToString()] = s;
271 i++;
272 }
273
274 string reply = string.Empty;
275 string uri = m_ServerURI + "/hgfriends";
276 try
277 {
278 reply = SynchronousRestFormsRequester.MakeRequest("POST",
279 uri,
280 ServerUtils.BuildQueryString(sendData), 15);
281 }
282 catch (Exception e)
283 {
284 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server at {0}: {1}", uri, e.Message);
285 return friendsOnline;
286 }
287
288 if (reply != string.Empty)
289 {
290 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
291
292 // Here is the actual response
293 foreach (string key in replyData.Keys)
294 {
295 if (key.StartsWith("friend_") && replyData[key] != null)
296 {
297 UUID uuid;
298 if (UUID.TryParse(replyData[key].ToString(), out uuid))
299 friendsOnline.Add(uuid);
300 }
301 }
302 }
303 else
304 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Received empty reply from remote StatusNotify");
305
306 return friendsOnline;
307
308 }
309
310 #endregion
311 }
312} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs
new file mode 100644
index 0000000..b5e6d69
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/HeloServicesConnector.cs
@@ -0,0 +1,113 @@
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 log4net;
29using System;
30using System.Net;
31using System.Reflection;
32using Nini.Config;
33
34namespace OpenSim.Services.Connectors
35{
36 public class HeloServicesConnector
37 {
38 private static readonly ILog m_log =
39 LogManager.GetLogger(
40 MethodBase.GetCurrentMethod().DeclaringType);
41
42 private string m_ServerURI = String.Empty;
43
44 public HeloServicesConnector()
45 {
46 }
47
48 public HeloServicesConnector(string serverURI)
49 {
50 try
51 {
52 Uri uri;
53
54 if (!serverURI.EndsWith("="))
55 {
56 // Let's check if this is a valid URI, because it may not be
57 uri = new Uri(serverURI);
58 m_ServerURI = serverURI.TrimEnd('/') + "/helo/";
59 }
60 else
61 {
62 // Simian sends malformed urls like this:
63 // http://valley.virtualportland.org/simtest/Grid/?id=
64 //
65 uri = new Uri(serverURI + "xxx");
66 if (uri.Query == string.Empty)
67 m_ServerURI = serverURI.TrimEnd('/') + "/helo/";
68 else
69 {
70 serverURI = serverURI + "xxx";
71 m_ServerURI = serverURI.Replace(uri.Query, "");
72 m_ServerURI = m_ServerURI.TrimEnd('/') + "/helo/";
73 }
74 }
75
76 }
77 catch (UriFormatException)
78 {
79 m_log.WarnFormat("[HELO SERVICE]: Malformed URL {0}", serverURI);
80 }
81 }
82
83 public virtual string Helo()
84 {
85 if (String.IsNullOrEmpty(m_ServerURI))
86 {
87 m_log.WarnFormat("[HELO SERVICE]: Unable to invoke HELO due to empty URL");
88 return String.Empty;
89 }
90
91 try
92 {
93 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
94 // Eventually we need to switch to HEAD
95 /* req.Method = "HEAD"; */
96
97 using (WebResponse response = req.GetResponse())
98 {
99 if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null
100 return string.Empty;
101 return response.Headers.Get("X-Handlers-Provided");
102 }
103 }
104 catch (Exception e)
105 {
106 m_log.DebugFormat("[HELO SERVICE]: Unable to perform HELO request to {0}: {1}", m_ServerURI, e.Message);
107 }
108
109 // fail
110 return string.Empty;
111 }
112 }
113} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
new file mode 100644
index 0000000..8abd046
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -0,0 +1,625 @@
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;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34using System.Text;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.Simulation;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using log4net;
42using Nwc.XmlRpc;
43using Nini.Config;
44
45namespace OpenSim.Services.Connectors.Hypergrid
46{
47 public class UserAgentServiceConnector : SimulationServiceConnector, IUserAgentService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private string m_ServerURLHost;
54 private string m_ServerURL;
55 private GridRegion m_Gatekeeper;
56
57 public UserAgentServiceConnector(string url) : this(url, true)
58 {
59 }
60
61 public UserAgentServiceConnector(string url, bool dnsLookup)
62 {
63 m_ServerURL = m_ServerURLHost = url;
64
65 if (dnsLookup)
66 {
67 // Doing this here, because XML-RPC or mono have some strong ideas about
68 // caching DNS translations.
69 try
70 {
71 Uri m_Uri = new Uri(m_ServerURL);
72 IPAddress ip = Util.GetHostFromDNS(m_Uri.Host);
73 m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString());
74 if (!m_ServerURL.EndsWith("/"))
75 m_ServerURL += "/";
76 }
77 catch (Exception e)
78 {
79 m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", url, e.Message);
80 }
81 }
82
83 //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL);
84 }
85
86 public UserAgentServiceConnector(IConfigSource config)
87 {
88 IConfig serviceConfig = config.Configs["UserAgentService"];
89 if (serviceConfig == null)
90 {
91 m_log.Error("[USER AGENT CONNECTOR]: UserAgentService missing from ini");
92 throw new Exception("UserAgent connector init error");
93 }
94
95 string serviceURI = serviceConfig.GetString("UserAgentServerURI",
96 String.Empty);
97
98 if (serviceURI == String.Empty)
99 {
100 m_log.Error("[USER AGENT CONNECTOR]: No Server URI named in section UserAgentService");
101 throw new Exception("UserAgent connector init error");
102 }
103
104 m_ServerURL = m_ServerURLHost = serviceURI;
105 if (!m_ServerURL.EndsWith("/"))
106 m_ServerURL += "/";
107
108 //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0}", m_ServerURL);
109 }
110
111 protected override string AgentPath()
112 {
113 return "homeagent/";
114 }
115
116 // The Login service calls this interface with fromLogin=true
117 // Sims call it with fromLogin=false
118 // Either way, this is verified by the handler
119 public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
120 {
121 reason = String.Empty;
122
123 if (destination == null)
124 {
125 reason = "Destination is null";
126 m_log.Debug("[USER AGENT CONNECTOR]: Given destination is null");
127 return false;
128 }
129
130 GridRegion home = new GridRegion();
131 home.ServerURI = m_ServerURL;
132 home.RegionID = destination.RegionID;
133 home.RegionLocX = destination.RegionLocX;
134 home.RegionLocY = destination.RegionLocY;
135
136 m_Gatekeeper = gatekeeper;
137
138 Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
139
140 uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
141 return CreateAgent(source, home, aCircuit, flags, out reason);
142 }
143
144
145 // The simulators call this interface
146 public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
147 {
148 return LoginAgentToGrid(source, aCircuit, gatekeeper, destination, false, out reason);
149 }
150
151 protected override void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags)
152 {
153 base.PackData(args, source, aCircuit, destination, flags);
154 args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
155 args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
156 args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
157 args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
158 }
159
160 public void SetClientToken(UUID sessionID, string token)
161 {
162 // no-op
163 }
164
165 private Hashtable CallServer(string methodName, Hashtable hash)
166 {
167 IList paramList = new ArrayList();
168 paramList.Add(hash);
169
170 XmlRpcRequest request = new XmlRpcRequest(methodName, paramList);
171
172 // Send and get reply
173 XmlRpcResponse response = null;
174 try
175 {
176 response = request.Send(m_ServerURL, 10000);
177 }
178 catch (Exception e)
179 {
180 m_log.DebugFormat("[USER AGENT CONNECTOR]: {0} call to {1} failed: {2}", methodName, m_ServerURLHost, e.Message);
181 throw;
182 }
183
184 if (response.IsFault)
185 {
186 throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned an error: {2}", methodName, m_ServerURLHost, response.FaultString));
187 }
188
189 hash = (Hashtable)response.Value;
190
191 if (hash == null)
192 {
193 throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned null", methodName, m_ServerURLHost));
194 }
195
196 return hash;
197 }
198
199 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
200 {
201 position = Vector3.UnitY; lookAt = Vector3.UnitY;
202
203 Hashtable hash = new Hashtable();
204 hash["userID"] = userID.ToString();
205
206 hash = CallServer("get_home_region", hash);
207
208 bool success;
209 if (!Boolean.TryParse((string)hash["result"], out success) || !success)
210 return null;
211
212 GridRegion region = new GridRegion();
213
214 UUID.TryParse((string)hash["uuid"], out region.RegionID);
215 //m_log.Debug(">> HERE, uuid: " + region.RegionID);
216 int n = 0;
217 if (hash["x"] != null)
218 {
219 Int32.TryParse((string)hash["x"], out n);
220 region.RegionLocX = n;
221 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
222 }
223 if (hash["y"] != null)
224 {
225 Int32.TryParse((string)hash["y"], out n);
226 region.RegionLocY = n;
227 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
228 }
229 if (hash["size_x"] != null)
230 {
231 Int32.TryParse((string)hash["size_x"], out n);
232 region.RegionSizeX = n;
233 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
234 }
235 if (hash["size_y"] != null)
236 {
237 Int32.TryParse((string)hash["size_y"], out n);
238 region.RegionSizeY = n;
239 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
240 }
241 if (hash["region_name"] != null)
242 {
243 region.RegionName = (string)hash["region_name"];
244 //m_log.Debug(">> HERE, name: " + region.RegionName);
245 }
246 if (hash["hostname"] != null)
247 region.ExternalHostName = (string)hash["hostname"];
248 if (hash["http_port"] != null)
249 {
250 uint p = 0;
251 UInt32.TryParse((string)hash["http_port"], out p);
252 region.HttpPort = p;
253 }
254 if (hash.ContainsKey("server_uri") && hash["server_uri"] != null)
255 region.ServerURI = (string)hash["server_uri"];
256
257 if (hash["internal_port"] != null)
258 {
259 int p = 0;
260 Int32.TryParse((string)hash["internal_port"], out p);
261 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
262 }
263 if (hash["position"] != null)
264 Vector3.TryParse((string)hash["position"], out position);
265 if (hash["lookAt"] != null)
266 Vector3.TryParse((string)hash["lookAt"], out lookAt);
267
268 // Successful return
269 return region;
270 }
271
272 public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
273 {
274 Hashtable hash = new Hashtable();
275 hash["sessionID"] = sessionID.ToString();
276 hash["externalName"] = thisGridExternalName;
277
278 IList paramList = new ArrayList();
279 paramList.Add(hash);
280
281 XmlRpcRequest request = new XmlRpcRequest("agent_is_coming_home", paramList);
282 string reason = string.Empty;
283 return GetBoolResponse(request, out reason);
284 }
285
286 public bool VerifyAgent(UUID sessionID, string token)
287 {
288 Hashtable hash = new Hashtable();
289 hash["sessionID"] = sessionID.ToString();
290 hash["token"] = token;
291
292 IList paramList = new ArrayList();
293 paramList.Add(hash);
294
295 XmlRpcRequest request = new XmlRpcRequest("verify_agent", paramList);
296 string reason = string.Empty;
297 return GetBoolResponse(request, out reason);
298 }
299
300 public bool VerifyClient(UUID sessionID, string token)
301 {
302 Hashtable hash = new Hashtable();
303 hash["sessionID"] = sessionID.ToString();
304 hash["token"] = token;
305
306 IList paramList = new ArrayList();
307 paramList.Add(hash);
308
309 XmlRpcRequest request = new XmlRpcRequest("verify_client", paramList);
310 string reason = string.Empty;
311 return GetBoolResponse(request, out reason);
312 }
313
314 public void LogoutAgent(UUID userID, UUID sessionID)
315 {
316 Hashtable hash = new Hashtable();
317 hash["sessionID"] = sessionID.ToString();
318 hash["userID"] = userID.ToString();
319
320 IList paramList = new ArrayList();
321 paramList.Add(hash);
322
323 XmlRpcRequest request = new XmlRpcRequest("logout_agent", paramList);
324 string reason = string.Empty;
325 GetBoolResponse(request, out reason);
326 }
327
328 [Obsolete]
329 public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
330 {
331 Hashtable hash = new Hashtable();
332 hash["userID"] = userID.ToString();
333 hash["online"] = online.ToString();
334 int i = 0;
335 foreach (string s in friends)
336 {
337 hash["friend_" + i.ToString()] = s;
338 i++;
339 }
340
341 IList paramList = new ArrayList();
342 paramList.Add(hash);
343
344 XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
345// string reason = string.Empty;
346
347 // Send and get reply
348 List<UUID> friendsOnline = new List<UUID>();
349 XmlRpcResponse response = null;
350 try
351 {
352 response = request.Send(m_ServerURL, 6000);
353 }
354 catch
355 {
356 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURLHost);
357// reason = "Exception: " + e.Message;
358 return friendsOnline;
359 }
360
361 if (response.IsFault)
362 {
363 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURLHost, response.FaultString);
364// reason = "XMLRPC Fault";
365 return friendsOnline;
366 }
367
368 hash = (Hashtable)response.Value;
369 //foreach (Object o in hash)
370 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
371 try
372 {
373 if (hash == null)
374 {
375 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
376// reason = "Internal error 1";
377 return friendsOnline;
378 }
379
380 // Here is the actual response
381 foreach (object key in hash.Keys)
382 {
383 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
384 {
385 UUID uuid;
386 if (UUID.TryParse(hash[key].ToString(), out uuid))
387 friendsOnline.Add(uuid);
388 }
389 }
390
391 }
392 catch
393 {
394 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
395// reason = "Exception: " + e.Message;
396 }
397
398 return friendsOnline;
399 }
400
401 [Obsolete]
402 public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
403 {
404 Hashtable hash = new Hashtable();
405 hash["userID"] = userID.ToString();
406 int i = 0;
407 foreach (string s in friends)
408 {
409 hash["friend_" + i.ToString()] = s;
410 i++;
411 }
412
413 IList paramList = new ArrayList();
414 paramList.Add(hash);
415
416 XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
417// string reason = string.Empty;
418
419 // Send and get reply
420 List<UUID> online = new List<UUID>();
421 XmlRpcResponse response = null;
422 try
423 {
424 response = request.Send(m_ServerURL, 10000);
425 }
426 catch
427 {
428 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURLHost);
429// reason = "Exception: " + e.Message;
430 return online;
431 }
432
433 if (response.IsFault)
434 {
435 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURLHost, response.FaultString);
436// reason = "XMLRPC Fault";
437 return online;
438 }
439
440 hash = (Hashtable)response.Value;
441 //foreach (Object o in hash)
442 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
443 try
444 {
445 if (hash == null)
446 {
447 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
448// reason = "Internal error 1";
449 return online;
450 }
451
452 // Here is the actual response
453 foreach (object key in hash.Keys)
454 {
455 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
456 {
457 UUID uuid;
458 if (UUID.TryParse(hash[key].ToString(), out uuid))
459 online.Add(uuid);
460 }
461 }
462
463 }
464 catch
465 {
466 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
467// reason = "Exception: " + e.Message;
468 }
469
470 return online;
471 }
472
473 public Dictionary<string,object> GetUserInfo (UUID userID)
474 {
475 Hashtable hash = new Hashtable();
476 hash["userID"] = userID.ToString();
477
478 hash = CallServer("get_user_info", hash);
479
480 Dictionary<string, object> info = new Dictionary<string, object>();
481
482 foreach (object key in hash.Keys)
483 {
484 if (hash[key] != null)
485 {
486 info.Add(key.ToString(), hash[key]);
487 }
488 }
489
490 return info;
491 }
492
493 public Dictionary<string, object> GetServerURLs(UUID userID)
494 {
495 Hashtable hash = new Hashtable();
496 hash["userID"] = userID.ToString();
497
498 hash = CallServer("get_server_urls", hash);
499
500 Dictionary<string, object> serverURLs = new Dictionary<string, object>();
501 foreach (object key in hash.Keys)
502 {
503 if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null)
504 {
505 string serverType = key.ToString().Substring(4); // remove "SRV_"
506 serverURLs.Add(serverType, hash[key].ToString());
507 }
508 }
509
510 return serverURLs;
511 }
512
513 public string LocateUser(UUID userID)
514 {
515 Hashtable hash = new Hashtable();
516 hash["userID"] = userID.ToString();
517
518 hash = CallServer("locate_user", hash);
519
520 string url = string.Empty;
521
522 // Here's the actual response
523 if (hash.ContainsKey("URL"))
524 url = hash["URL"].ToString();
525
526 return url;
527 }
528
529 public string GetUUI(UUID userID, UUID targetUserID)
530 {
531 Hashtable hash = new Hashtable();
532 hash["userID"] = userID.ToString();
533 hash["targetUserID"] = targetUserID.ToString();
534
535 hash = CallServer("get_uui", hash);
536
537 string uui = string.Empty;
538
539 // Here's the actual response
540 if (hash.ContainsKey("UUI"))
541 uui = hash["UUI"].ToString();
542
543 return uui;
544 }
545
546 public UUID GetUUID(String first, String last)
547 {
548 Hashtable hash = new Hashtable();
549 hash["first"] = first;
550 hash["last"] = last;
551
552 hash = CallServer("get_uuid", hash);
553
554 if (!hash.ContainsKey("UUID"))
555 {
556 throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} didn't return a UUID", m_ServerURLHost));
557 }
558
559 UUID uuid;
560 if (!UUID.TryParse(hash["UUID"].ToString(), out uuid))
561 {
562 throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} returned an invalid UUID: {1}", m_ServerURLHost, hash["UUID"].ToString()));
563 }
564
565 return uuid;
566 }
567
568 private bool GetBoolResponse(XmlRpcRequest request, out string reason)
569 {
570 //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURLHost);
571 XmlRpcResponse response = null;
572 try
573 {
574 response = request.Send(m_ServerURL, 10000);
575 }
576 catch (Exception e)
577 {
578 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURLHost);
579 reason = "Exception: " + e.Message;
580 return false;
581 }
582
583 if (response.IsFault)
584 {
585 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURLHost, response.FaultString);
586 reason = "XMLRPC Fault";
587 return false;
588 }
589
590 Hashtable hash = (Hashtable)response.Value;
591 //foreach (Object o in hash)
592 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
593 try
594 {
595 if (hash == null)
596 {
597 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
598 reason = "Internal error 1";
599 return false;
600 }
601 bool success = false;
602 reason = string.Empty;
603 if (hash.ContainsKey("result"))
604 Boolean.TryParse((string)hash["result"], out success);
605 else
606 {
607 reason = "Internal error 2";
608 m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURLHost);
609 }
610
611 return success;
612 }
613 catch (Exception e)
614 {
615 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetBoolResponse response.");
616 if (hash.ContainsKey("result") && hash["result"] != null)
617 m_log.ErrorFormat("Reply was ", (string)hash["result"]);
618 reason = "Exception: " + e.Message;
619 return false;
620 }
621
622 }
623
624 }
625}
diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
new file mode 100644
index 0000000..e19c23d
--- /dev/null
+++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
@@ -0,0 +1,132 @@
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 */
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenMetaverse;
34using Nwc.XmlRpc;
35using log4net;
36
37using OpenSim.Framework;
38
39namespace OpenSim.Services.Connectors.InstantMessage
40{
41 public class InstantMessageServiceConnector
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 /// This actually does the XMLRPC Request
49 /// </summary>
50 /// <param name="url">URL we pull the data out of to send the request to</param>
51 /// <param name="im">The Instant Message </param>
52 /// <returns>Bool if the message was successfully delivered at the other side.</returns>
53 public static bool SendInstantMessage(string url, GridInstantMessage im)
54 {
55 Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im);
56 xmlrpcdata["region_handle"] = 0;
57
58 ArrayList SendParams = new ArrayList();
59 SendParams.Add(xmlrpcdata);
60 XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);
61 try
62 {
63
64 XmlRpcResponse GridResp = GridReq.Send(url, 10000);
65
66 Hashtable responseData = (Hashtable)GridResp.Value;
67
68 if (responseData.ContainsKey("success"))
69 {
70 if ((string)responseData["success"] == "TRUE")
71 {
72 //m_log.DebugFormat("[XXX] Success");
73 return true;
74 }
75 else
76 {
77 //m_log.DebugFormat("[XXX] Fail");
78 return false;
79 }
80 }
81 else
82 {
83 m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url);
84 return false;
85 }
86 }
87 catch (WebException e)
88 {
89 m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url);
90 }
91
92 return false;
93 }
94
95 /// <summary>
96 /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC
97 /// </summary>
98 /// <param name="msg">The GridInstantMessage object</param>
99 /// <returns>Hashtable containing the XMLRPC request</returns>
100 protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
101 {
102 Hashtable gim = new Hashtable();
103 gim["from_agent_id"] = msg.fromAgentID.ToString();
104 // Kept for compatibility
105 gim["from_agent_session"] = UUID.Zero.ToString();
106 gim["to_agent_id"] = msg.toAgentID.ToString();
107 gim["im_session_id"] = msg.imSessionID.ToString();
108 gim["timestamp"] = msg.timestamp.ToString();
109 gim["from_agent_name"] = msg.fromAgentName;
110 gim["message"] = msg.message;
111 byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog;
112 gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None);
113
114 if (msg.fromGroup)
115 gim["from_group"] = "TRUE";
116 else
117 gim["from_group"] = "FALSE";
118 byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline;
119 gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None);
120 gim["parent_estate_id"] = msg.ParentEstateID.ToString();
121 gim["position_x"] = msg.Position.X.ToString();
122 gim["position_y"] = msg.Position.Y.ToString();
123 gim["position_z"] = msg.Position.Z.ToString();
124 gim["region_id"] = msg.RegionID.ToString();
125 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None);
126 gim["region_id"] = new UUID(msg.RegionID).ToString();
127
128 return gim;
129 }
130
131 }
132}
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
new file mode 100644
index 0000000..b0615b8
--- /dev/null
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryServicesConnector.cs
@@ -0,0 +1,763 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications;
37using OpenSim.Framework.Monitoring;
38using OpenSim.Services.Interfaces;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 /// <summary>
51 /// Number of requests made to the remote inventory service.
52 /// </summary>
53 public int RequestsMade { get; private set; }
54
55 private string m_ServerURI = String.Empty;
56
57 /// <summary>
58 /// Timeout for remote requests.
59 /// </summary>
60 /// <remarks>
61 /// In this case, -1 is default timeout (100 seconds), not infinite.
62 /// </remarks>
63 private int m_requestTimeoutSecs = -1;
64
65 private const double CACHE_EXPIRATION_SECONDS = 20.0;
66 private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache = new ExpiringCache<UUID,InventoryItemBase>();
67
68 public XInventoryServicesConnector()
69 {
70 }
71
72 public XInventoryServicesConnector(string serverURI)
73 {
74 m_ServerURI = serverURI.TrimEnd('/');
75 }
76
77 public XInventoryServicesConnector(IConfigSource source)
78 : base(source, "InventoryService")
79 {
80 Initialise(source);
81 }
82
83 public virtual void Initialise(IConfigSource source)
84 {
85 IConfig config = source.Configs["InventoryService"];
86 if (config == null)
87 {
88 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
89 throw new Exception("Inventory connector init error");
90 }
91
92 string serviceURI = config.GetString("InventoryServerURI",
93 String.Empty);
94
95 if (serviceURI == String.Empty)
96 {
97 m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService");
98 throw new Exception("Inventory connector init error");
99 }
100 m_ServerURI = serviceURI;
101
102 m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
103
104 StatsManager.RegisterStat(
105 new Stat(
106 "RequestsMade",
107 "Requests made",
108 "Number of requests made to the remove inventory service",
109 "requests",
110 "inventory",
111 serviceURI,
112 StatType.Pull,
113 MeasuresOfInterest.AverageChangeOverTime,
114 s => s.Value = RequestsMade,
115 StatVerbosity.Debug));
116 }
117
118 private bool CheckReturn(Dictionary<string, object> ret)
119 {
120 if (ret == null)
121 return false;
122
123 if (ret.Count == 0)
124 return false;
125
126 if (ret.ContainsKey("RESULT"))
127 {
128 if (ret["RESULT"] is string)
129 {
130 bool result;
131
132 if (bool.TryParse((string)ret["RESULT"], out result))
133 return result;
134
135 return false;
136 }
137 }
138
139 return true;
140 }
141
142 public bool CreateUserInventory(UUID principalID)
143 {
144 Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY",
145 new Dictionary<string,object> {
146 { "PRINCIPAL", principalID.ToString() }
147 });
148
149 return CheckReturn(ret);
150 }
151
152 public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
153 {
154 Dictionary<string,object> ret = MakeRequest("GETINVENTORYSKELETON",
155 new Dictionary<string,object> {
156 { "PRINCIPAL", principalID.ToString() }
157 });
158
159 if (!CheckReturn(ret))
160 return null;
161
162 Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
163
164 List<InventoryFolderBase> fldrs = new List<InventoryFolderBase>();
165
166 try
167 {
168 foreach (Object o in folders.Values)
169 fldrs.Add(BuildFolder((Dictionary<string, object>)o));
170 }
171 catch (Exception e)
172 {
173 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e);
174 }
175
176 return fldrs;
177 }
178
179 public InventoryFolderBase GetRootFolder(UUID principalID)
180 {
181 Dictionary<string,object> ret = MakeRequest("GETROOTFOLDER",
182 new Dictionary<string,object> {
183 { "PRINCIPAL", principalID.ToString() }
184 });
185
186 if (!CheckReturn(ret))
187 return null;
188
189 return BuildFolder((Dictionary<string, object>)ret["folder"]);
190 }
191
192 public InventoryFolderBase GetFolderForType(UUID principalID, FolderType type)
193 {
194 Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE",
195 new Dictionary<string,object> {
196 { "PRINCIPAL", principalID.ToString() },
197 { "TYPE", ((int)type).ToString() }
198 });
199
200 if (!CheckReturn(ret))
201 return null;
202
203 return BuildFolder((Dictionary<string, object>)ret["folder"]);
204 }
205
206 public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
207 {
208 InventoryCollection inventory = new InventoryCollection();
209 inventory.Folders = new List<InventoryFolderBase>();
210 inventory.Items = new List<InventoryItemBase>();
211 inventory.OwnerID = principalID;
212
213 try
214 {
215 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
216 new Dictionary<string,object> {
217 { "PRINCIPAL", principalID.ToString() },
218 { "FOLDER", folderID.ToString() }
219 });
220
221 if (!CheckReturn(ret))
222 return null;
223
224 Dictionary<string,object> folders = ret.ContainsKey("FOLDERS") ?
225 (Dictionary<string,object>)ret["FOLDERS"] : null;
226 Dictionary<string,object> items = ret.ContainsKey("ITEMS") ?
227 (Dictionary<string, object>)ret["ITEMS"] : null;
228
229 if (folders != null)
230 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
231 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
232 if (items != null)
233 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
234 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
235 }
236 catch (Exception e)
237 {
238 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message);
239 }
240
241 return inventory;
242 }
243
244 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
245 {
246 InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
247 // m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", String.Join(",", folderIDs));
248 try
249 {
250 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
251 new Dictionary<string, object> {
252 { "PRINCIPAL", principalID.ToString() },
253 { "FOLDERS", String.Join(",", folderIDs) },
254 { "COUNT", folderIDs.Length.ToString() }
255 });
256
257 if (!CheckReturn(resultSet))
258 return null;
259
260 int i = 0;
261 foreach (KeyValuePair<string, object> kvp in resultSet)
262 {
263 InventoryCollection inventory = new InventoryCollection();
264 if (kvp.Key.StartsWith("F_"))
265 {
266 UUID fid = UUID.Zero;
267 if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
268 {
269 inventory.Folders = new List<InventoryFolderBase>();
270 inventory.Items = new List<InventoryItemBase>();
271
272 Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
273
274 if (ret.ContainsKey("FID"))
275 {
276 if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
277 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
278 }
279 else
280 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
281
282 inventory.Version = -1;
283 if (ret.ContainsKey("VERSION"))
284 Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
285 if (ret.ContainsKey("OWNER"))
286 UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
287
288 //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
289
290 Dictionary<string, object> folders =
291 (Dictionary<string, object>)ret["FOLDERS"];
292 Dictionary<string, object> items =
293 (Dictionary<string, object>)ret["ITEMS"];
294
295 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
296 {
297 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
298 }
299 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
300 {
301 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
302 }
303
304 inventoryArr[i] = inventory;
305 }
306 else
307 {
308 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
309 folderIDs[i], fid);
310 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys));
311 }
312
313 i += 1;
314 }
315 }
316 }
317 catch (Exception e)
318 {
319 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
320 }
321
322 return inventoryArr;
323 }
324
325 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
326 {
327 Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
328 new Dictionary<string,object> {
329 { "PRINCIPAL", principalID.ToString() },
330 { "FOLDER", folderID.ToString() }
331 });
332
333 if (!CheckReturn(ret))
334 return null;
335
336 Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
337 List<InventoryItemBase> fitems = new List<InventoryItemBase>();
338 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
339 fitems.Add(BuildItem((Dictionary<string, object>)o));
340
341 return fitems;
342 }
343
344 public bool AddFolder(InventoryFolderBase folder)
345 {
346 Dictionary<string,object> ret = MakeRequest("ADDFOLDER",
347 new Dictionary<string,object> {
348 { "ParentID", folder.ParentID.ToString() },
349 { "Type", folder.Type.ToString() },
350 { "Version", folder.Version.ToString() },
351 { "Name", folder.Name.ToString() },
352 { "Owner", folder.Owner.ToString() },
353 { "ID", folder.ID.ToString() }
354 });
355
356 return CheckReturn(ret);
357 }
358
359 public bool UpdateFolder(InventoryFolderBase folder)
360 {
361 Dictionary<string,object> ret = MakeRequest("UPDATEFOLDER",
362 new Dictionary<string,object> {
363 { "ParentID", folder.ParentID.ToString() },
364 { "Type", folder.Type.ToString() },
365 { "Version", folder.Version.ToString() },
366 { "Name", folder.Name.ToString() },
367 { "Owner", folder.Owner.ToString() },
368 { "ID", folder.ID.ToString() }
369 });
370
371 return CheckReturn(ret);
372 }
373
374 public bool MoveFolder(InventoryFolderBase folder)
375 {
376 Dictionary<string,object> ret = MakeRequest("MOVEFOLDER",
377 new Dictionary<string,object> {
378 { "ParentID", folder.ParentID.ToString() },
379 { "ID", folder.ID.ToString() },
380 { "PRINCIPAL", folder.Owner.ToString() }
381 });
382
383 return CheckReturn(ret);
384 }
385
386 public bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
387 {
388 List<string> slist = new List<string>();
389
390 foreach (UUID f in folderIDs)
391 slist.Add(f.ToString());
392
393 Dictionary<string,object> ret = MakeRequest("DELETEFOLDERS",
394 new Dictionary<string,object> {
395 { "PRINCIPAL", principalID.ToString() },
396 { "FOLDERS", slist }
397 });
398
399 return CheckReturn(ret);
400 }
401
402 public bool PurgeFolder(InventoryFolderBase folder)
403 {
404 Dictionary<string,object> ret = MakeRequest("PURGEFOLDER",
405 new Dictionary<string,object> {
406 { "ID", folder.ID.ToString() }
407 });
408
409 return CheckReturn(ret);
410 }
411
412 public bool AddItem(InventoryItemBase item)
413 {
414 if (item.Description == null)
415 item.Description = String.Empty;
416 if (item.CreatorData == null)
417 item.CreatorData = String.Empty;
418 if (item.CreatorId == null)
419 item.CreatorId = String.Empty;
420 Dictionary<string, object> ret = MakeRequest("ADDITEM",
421 new Dictionary<string,object> {
422 { "AssetID", item.AssetID.ToString() },
423 { "AssetType", item.AssetType.ToString() },
424 { "Name", item.Name.ToString() },
425 { "Owner", item.Owner.ToString() },
426 { "ID", item.ID.ToString() },
427 { "InvType", item.InvType.ToString() },
428 { "Folder", item.Folder.ToString() },
429 { "CreatorId", item.CreatorId.ToString() },
430 { "CreatorData", item.CreatorData.ToString() },
431 { "Description", item.Description.ToString() },
432 { "NextPermissions", item.NextPermissions.ToString() },
433 { "CurrentPermissions", item.CurrentPermissions.ToString() },
434 { "BasePermissions", item.BasePermissions.ToString() },
435 { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
436 { "GroupPermissions", item.GroupPermissions.ToString() },
437 { "GroupID", item.GroupID.ToString() },
438 { "GroupOwned", item.GroupOwned.ToString() },
439 { "SalePrice", item.SalePrice.ToString() },
440 { "SaleType", item.SaleType.ToString() },
441 { "Flags", item.Flags.ToString() },
442 { "CreationDate", item.CreationDate.ToString() }
443 });
444
445 return CheckReturn(ret);
446 }
447
448 public bool UpdateItem(InventoryItemBase item)
449 {
450 if (item.CreatorData == null)
451 item.CreatorData = String.Empty;
452 Dictionary<string,object> ret = MakeRequest("UPDATEITEM",
453 new Dictionary<string,object> {
454 { "AssetID", item.AssetID.ToString() },
455 { "AssetType", item.AssetType.ToString() },
456 { "Name", item.Name.ToString() },
457 { "Owner", item.Owner.ToString() },
458 { "ID", item.ID.ToString() },
459 { "InvType", item.InvType.ToString() },
460 { "Folder", item.Folder.ToString() },
461 { "CreatorId", item.CreatorId.ToString() },
462 { "CreatorData", item.CreatorData.ToString() },
463 { "Description", item.Description.ToString() },
464 { "NextPermissions", item.NextPermissions.ToString() },
465 { "CurrentPermissions", item.CurrentPermissions.ToString() },
466 { "BasePermissions", item.BasePermissions.ToString() },
467 { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
468 { "GroupPermissions", item.GroupPermissions.ToString() },
469 { "GroupID", item.GroupID.ToString() },
470 { "GroupOwned", item.GroupOwned.ToString() },
471 { "SalePrice", item.SalePrice.ToString() },
472 { "SaleType", item.SaleType.ToString() },
473 { "Flags", item.Flags.ToString() },
474 { "CreationDate", item.CreationDate.ToString() }
475 });
476
477 return CheckReturn(ret);
478 }
479
480 public bool MoveItems(UUID principalID, List<InventoryItemBase> items)
481 {
482 List<string> idlist = new List<string>();
483 List<string> destlist = new List<string>();
484
485 foreach (InventoryItemBase item in items)
486 {
487 idlist.Add(item.ID.ToString());
488 destlist.Add(item.Folder.ToString());
489 }
490
491 Dictionary<string,object> ret = MakeRequest("MOVEITEMS",
492 new Dictionary<string,object> {
493 { "PRINCIPAL", principalID.ToString() },
494 { "IDLIST", idlist },
495 { "DESTLIST", destlist }
496 });
497
498 return CheckReturn(ret);
499 }
500
501 public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
502 {
503 List<string> slist = new List<string>();
504
505 foreach (UUID f in itemIDs)
506 slist.Add(f.ToString());
507
508 Dictionary<string,object> ret = MakeRequest("DELETEITEMS",
509 new Dictionary<string,object> {
510 { "PRINCIPAL", principalID.ToString() },
511 { "ITEMS", slist }
512 });
513
514 return CheckReturn(ret);
515 }
516
517 public InventoryItemBase GetItem(InventoryItemBase item)
518 {
519 InventoryItemBase retrieved = null;
520 if (m_ItemCache.TryGetValue(item.ID, out retrieved))
521 return retrieved;
522
523 try
524 {
525 Dictionary<string, object> ret = MakeRequest("GETITEM",
526 new Dictionary<string, object> {
527 { "ID", item.ID.ToString() }
528 });
529
530 if (!CheckReturn(ret))
531 return null;
532
533 retrieved = BuildItem((Dictionary<string, object>)ret["item"]);
534 }
535 catch (Exception e)
536 {
537 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
538 }
539
540 m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
541
542 return retrieved;
543 }
544
545 public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
546 {
547 //m_log.DebugFormat("[XXX]: In GetMultipleItems {0}", String.Join(",", itemIDs));
548
549 InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
550 // Try to get them from the cache
551 List<UUID> pending = new List<UUID>();
552 InventoryItemBase item = null;
553 int i = 0;
554 foreach (UUID id in itemIDs)
555 {
556 if (m_ItemCache.TryGetValue(id, out item))
557 itemArr[i++] = item;
558 else
559 pending.Add(id);
560 }
561
562 if (pending.Count == 0) // we're done, everything was in the cache
563 return itemArr;
564
565 try
566 {
567 Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
568 new Dictionary<string, object> {
569 { "PRINCIPAL", principalID.ToString() },
570 { "ITEMS", String.Join(",", pending.ToArray()) },
571 { "COUNT", pending.Count.ToString() }
572 });
573
574 if (!CheckReturn(resultSet))
575 {
576 if (i == 0)
577 return null;
578 else
579 return itemArr;
580 }
581
582 // carry over index i where we left above
583 foreach (KeyValuePair<string, object> kvp in resultSet)
584 {
585 InventoryCollection inventory = new InventoryCollection();
586 if (kvp.Key.StartsWith("item_"))
587 {
588 if (kvp.Value is Dictionary<string, object>)
589 {
590 item = BuildItem((Dictionary<string, object>)kvp.Value);
591 m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS);
592 itemArr[i++] = item;
593 }
594 else
595 itemArr[i++] = null;
596 }
597 }
598 }
599 catch (Exception e)
600 {
601 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message);
602 }
603
604 return itemArr;
605 }
606
607 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
608 {
609 try
610 {
611 Dictionary<string, object> ret = MakeRequest("GETFOLDER",
612 new Dictionary<string, object> {
613 { "ID", folder.ID.ToString() }
614 });
615
616 if (!CheckReturn(ret))
617 return null;
618
619 return BuildFolder((Dictionary<string, object>)ret["folder"]);
620 }
621 catch (Exception e)
622 {
623 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e);
624 }
625
626 return null;
627 }
628
629 public List<InventoryItemBase> GetActiveGestures(UUID principalID)
630 {
631 Dictionary<string,object> ret = MakeRequest("GETACTIVEGESTURES",
632 new Dictionary<string,object> {
633 { "PRINCIPAL", principalID.ToString() }
634 });
635
636 if (!CheckReturn(ret))
637 return null;
638
639 List<InventoryItemBase> items = new List<InventoryItemBase>();
640
641 foreach (Object o in ((Dictionary<string,object>)ret["ITEMS"]).Values)
642 items.Add(BuildItem((Dictionary<string, object>)o));
643
644 return items;
645 }
646
647 public int GetAssetPermissions(UUID principalID, UUID assetID)
648 {
649 Dictionary<string,object> ret = MakeRequest("GETASSETPERMISSIONS",
650 new Dictionary<string,object> {
651 { "PRINCIPAL", principalID.ToString() },
652 { "ASSET", assetID.ToString() }
653 });
654
655 // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int
656 if (ret == null)
657 return 0;
658
659 if (ret.ContainsKey("RESULT"))
660 {
661 if (ret["RESULT"] is string)
662 {
663 int intResult;
664
665 if (int.TryParse ((string)ret["RESULT"], out intResult))
666 return intResult;
667 }
668 }
669
670 return 0;
671 }
672
673 public bool HasInventoryForUser(UUID principalID)
674 {
675 return false;
676 }
677
678 // Helpers
679 //
680 private Dictionary<string,object> MakeRequest(string method,
681 Dictionary<string,object> sendData)
682 {
683 // Add "METHOD" as the first key in the dictionary. This ensures that it will be
684 // visible even when using partial logging ("debug http all 5").
685 Dictionary<string, object> temp = sendData;
686 sendData = new Dictionary<string,object>{ { "METHOD", method } };
687 foreach (KeyValuePair<string, object> kvp in temp)
688 sendData.Add(kvp.Key, kvp.Value);
689
690 RequestsMade++;
691
692 string reply
693 = SynchronousRestFormsRequester.MakeRequest(
694 "POST", m_ServerURI + "/xinventory",
695 ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
696
697 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
698 reply);
699
700 return replyData;
701 }
702
703 private InventoryFolderBase BuildFolder(Dictionary<string,object> data)
704 {
705 InventoryFolderBase folder = new InventoryFolderBase();
706
707 try
708 {
709 folder.ParentID = new UUID(data["ParentID"].ToString());
710 folder.Type = short.Parse(data["Type"].ToString());
711 folder.Version = ushort.Parse(data["Version"].ToString());
712 folder.Name = data["Name"].ToString();
713 folder.Owner = new UUID(data["Owner"].ToString());
714 folder.ID = new UUID(data["ID"].ToString());
715 }
716 catch (Exception e)
717 {
718 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e);
719 }
720
721 return folder;
722 }
723
724 private InventoryItemBase BuildItem(Dictionary<string,object> data)
725 {
726 InventoryItemBase item = new InventoryItemBase();
727
728 try
729 {
730 item.AssetID = new UUID(data["AssetID"].ToString());
731 item.AssetType = int.Parse(data["AssetType"].ToString());
732 item.Name = data["Name"].ToString();
733 item.Owner = new UUID(data["Owner"].ToString());
734 item.ID = new UUID(data["ID"].ToString());
735 item.InvType = int.Parse(data["InvType"].ToString());
736 item.Folder = new UUID(data["Folder"].ToString());
737 item.CreatorId = data["CreatorId"].ToString();
738 if (data.ContainsKey("CreatorData"))
739 item.CreatorData = data["CreatorData"].ToString();
740 else
741 item.CreatorData = String.Empty;
742 item.Description = data["Description"].ToString();
743 item.NextPermissions = uint.Parse(data["NextPermissions"].ToString());
744 item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString());
745 item.BasePermissions = uint.Parse(data["BasePermissions"].ToString());
746 item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString());
747 item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString());
748 item.GroupID = new UUID(data["GroupID"].ToString());
749 item.GroupOwned = bool.Parse(data["GroupOwned"].ToString());
750 item.SalePrice = int.Parse(data["SalePrice"].ToString());
751 item.SaleType = byte.Parse(data["SaleType"].ToString());
752 item.Flags = uint.Parse(data["Flags"].ToString());
753 item.CreationDate = int.Parse(data["CreationDate"].ToString());
754 }
755 catch (Exception e)
756 {
757 m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e);
758 }
759
760 return item;
761 }
762 }
763}
diff --git a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs
new file mode 100644
index 0000000..644331a
--- /dev/null
+++ b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs
@@ -0,0 +1,133 @@
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 log4net;
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.IO;
33using System.Reflection;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Framework.Communications;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39using Nwc.XmlRpc;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41
42namespace OpenSim.Services.Connectors
43{
44 public class LandServicesConnector : ILandService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected IGridService m_GridService = null;
51
52 public LandServicesConnector()
53 {
54 }
55
56 public LandServicesConnector(IGridService gridServices)
57 {
58 Initialise(gridServices);
59 }
60
61 public virtual void Initialise(IGridService gridServices)
62 {
63 m_GridService = gridServices;
64 }
65
66 public virtual LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess)
67 {
68 LandData landData = null;
69 Hashtable hash = new Hashtable();
70 hash["region_handle"] = regionHandle.ToString();
71 hash["x"] = x.ToString();
72 hash["y"] = y.ToString();
73
74 IList paramList = new ArrayList();
75 paramList.Add(hash);
76 regionAccess = 42; // Default to adult. Better safe...
77
78 try
79 {
80 uint xpos = 0, ypos = 0;
81 Util.RegionHandleToWorldLoc(regionHandle, out xpos, out ypos);
82 GridRegion info = m_GridService.GetRegionByPosition(scopeID, (int)xpos, (int)ypos);
83 if (info != null) // just to be sure
84 {
85 XmlRpcRequest request = new XmlRpcRequest("land_data", paramList);
86 XmlRpcResponse response = request.Send(info.ServerURI, 10000);
87 if (response.IsFault)
88 {
89 m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString);
90 }
91 else
92 {
93 hash = (Hashtable)response.Value;
94 try
95 {
96 landData = new LandData();
97 landData.AABBMax = Vector3.Parse((string)hash["AABBMax"]);
98 landData.AABBMin = Vector3.Parse((string)hash["AABBMin"]);
99 landData.Area = Convert.ToInt32(hash["Area"]);
100 landData.AuctionID = Convert.ToUInt32(hash["AuctionID"]);
101 landData.Description = (string)hash["Description"];
102 landData.Flags = Convert.ToUInt32(hash["Flags"]);
103 landData.GlobalID = new UUID((string)hash["GlobalID"]);
104 landData.Name = (string)hash["Name"];
105 landData.OwnerID = new UUID((string)hash["OwnerID"]);
106 landData.SalePrice = Convert.ToInt32(hash["SalePrice"]);
107 landData.SnapshotID = new UUID((string)hash["SnapshotID"]);
108 landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]);
109 if (hash["RegionAccess"] != null)
110 regionAccess = (byte)Convert.ToInt32((string)hash["RegionAccess"]);
111 m_log.DebugFormat("[LAND CONNECTOR]: Got land data for parcel {0}", landData.Name);
112 }
113 catch (Exception e)
114 {
115 m_log.ErrorFormat(
116 "[LAND CONNECTOR]: Got exception while parsing land-data: {0} {1}",
117 e.Message, e.StackTrace);
118 }
119 }
120 }
121 else
122 m_log.WarnFormat("[LAND CONNECTOR]: Couldn't find region with handle {0}", regionHandle);
123 }
124 catch (Exception e)
125 {
126 m_log.ErrorFormat(
127 "[LAND CONNECTOR]: Couldn't contact region {0}: {1} {2}", regionHandle, e.Message, e.StackTrace);
128 }
129
130 return landData;
131 }
132 }
133} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
new file mode 100644
index 0000000..677825e
--- /dev/null
+++ b/OpenSim/Services/Connectors/MapImage/MapImageServicesConnector.cs
@@ -0,0 +1,226 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Framework.Communications;
39using OpenSim.Framework.ServiceAuth;
40using OpenSim.Server.Base;
41using OpenSim.Services.Interfaces;
42using OpenMetaverse;
43using OpenMetaverse.StructuredData;
44
45namespace OpenSim.Services.Connectors
46{
47 public class MapImageServicesConnector : BaseServiceConnector, IMapImageService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private string m_ServerURI = String.Empty;
54
55 public MapImageServicesConnector()
56 {
57 }
58
59 public MapImageServicesConnector(string serverURI)
60 {
61 m_ServerURI = serverURI.TrimEnd('/');
62 }
63
64 public MapImageServicesConnector(IConfigSource source)
65 {
66 Initialise(source);
67 }
68
69 public virtual void Initialise(IConfigSource source)
70 {
71 IConfig config = source.Configs["MapImageService"];
72 if (config == null)
73 {
74 m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing");
75 throw new Exception("MapImage connector init error");
76 }
77
78 string serviceURI = config.GetString("MapImageServerURI",
79 String.Empty);
80
81 if (serviceURI == String.Empty)
82 {
83 m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService");
84 throw new Exception("MapImage connector init error");
85 }
86 m_ServerURI = serviceURI;
87 m_ServerURI = serviceURI.TrimEnd('/');
88 base.Initialise(source, "MapImageService");
89 }
90
91 public bool RemoveMapTile(int x, int y, out string reason)
92 {
93 reason = string.Empty;
94 int tickstart = Util.EnvironmentTickCount();
95 Dictionary<string, object> sendData = new Dictionary<string, object>();
96 sendData["X"] = x.ToString();
97 sendData["Y"] = y.ToString();
98
99 string reqString = ServerUtils.BuildQueryString(sendData);
100 string uri = m_ServerURI + "/removemap";
101
102 try
103 {
104 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
105 uri,
106 reqString,
107 m_Auth);
108 if (reply != string.Empty)
109 {
110 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
111
112 if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success"))
113 {
114 return true;
115 }
116 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure"))
117 {
118 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Delete failed: {0}", replyData["Message"].ToString());
119 reason = replyData["Message"].ToString();
120 return false;
121 }
122 else if (!replyData.ContainsKey("Result"))
123 {
124 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field");
125 }
126 else
127 {
128 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString());
129 reason = "Unexpected result " + replyData["Result"].ToString();
130 }
131
132 }
133 else
134 {
135 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Map post received null reply");
136 }
137 }
138 catch (Exception e)
139 {
140 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting map server at {0}: {1}", uri, e.Message);
141 }
142 finally
143 {
144 // This just dumps a warning for any operation that takes more than 100 ms
145 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
146 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile deleted in {0}ms", tickdiff);
147 }
148
149 return false;
150 }
151
152 public bool AddMapTile(int x, int y, byte[] jpgData, out string reason)
153 {
154 reason = string.Empty;
155 int tickstart = Util.EnvironmentTickCount();
156 Dictionary<string, object> sendData = new Dictionary<string, object>();
157 sendData["X"] = x.ToString();
158 sendData["Y"] = y.ToString();
159 sendData["TYPE"] = "image/jpeg";
160 sendData["DATA"] = Convert.ToBase64String(jpgData);
161
162 string reqString = ServerUtils.BuildQueryString(sendData);
163 string uri = m_ServerURI + "/map";
164
165 try
166 {
167 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
168 uri,
169 reqString,
170 m_Auth);
171 if (reply != string.Empty)
172 {
173 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
174
175 if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success"))
176 {
177 return true;
178 }
179 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure"))
180 {
181 reason = string.Format("Map post to {0} failed: {1}", uri, replyData["Message"].ToString());
182 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
183
184 return false;
185 }
186 else if (!replyData.ContainsKey("Result"))
187 {
188 reason = string.Format("Reply data from {0} does not contain result field", uri);
189 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
190 }
191 else
192 {
193 reason = string.Format("Unexpected result {0} from {1}" + replyData["Result"].ToString(), uri);
194 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
195 }
196 }
197 else
198 {
199 reason = string.Format("Map post received null reply from {0}", uri);
200 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
201 }
202 }
203 catch (Exception e)
204 {
205 reason = string.Format("Exception when posting to map server at {0}: {1}", uri, e.Message);
206 m_log.WarnFormat("[MAP IMAGE CONNECTOR]: {0}", reason);
207 }
208 finally
209 {
210 // This just dumps a warning for any operation that takes more than 100 ms
211 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
212 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff);
213 }
214
215 return false;
216
217 }
218
219 public byte[] GetMapTile(string fileName, out string format)
220 {
221 format = string.Empty;
222 new Exception("GetMapTile method not Implemented");
223 return null;
224 }
225 }
226}
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
new file mode 100644
index 0000000..eecf096
--- /dev/null
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs
@@ -0,0 +1,205 @@
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 log4net;
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.IO;
33using System.Net;
34using System.Reflection;
35using System.Text;
36using Nini.Config;
37using OpenSim.Framework;
38using OpenSim.Framework.Communications;
39using OpenSim.Services.Interfaces;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42
43using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44
45namespace OpenSim.Services.Connectors
46{
47 public class NeighbourServicesConnector : INeighbourService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 protected IGridService m_GridService = null;
54
55 public NeighbourServicesConnector()
56 {
57 }
58
59 public NeighbourServicesConnector(IGridService gridServices)
60 {
61 Initialise(gridServices);
62 }
63
64 public virtual void Initialise(IGridService gridServices)
65 {
66 m_GridService = gridServices;
67 }
68
69 public virtual GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion)
70 {
71 uint x = 0, y = 0;
72 Util.RegionHandleToWorldLoc(regionHandle, out x, out y);
73 GridRegion regInfo = m_GridService.GetRegionByPosition(thisRegion.ScopeID, (int)x, (int)y);
74 if ((regInfo != null) &&
75 // Don't remote-call this instance; that's a startup hickup
76 !((regInfo.ExternalHostName == thisRegion.ExternalHostName) && (regInfo.HttpPort == thisRegion.HttpPort)))
77 {
78 if (!DoHelloNeighbourCall(regInfo, thisRegion))
79 return null;
80 }
81 else
82 return null;
83
84 return regInfo;
85 }
86
87 public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion)
88 {
89 string uri = region.ServerURI + "region/" + thisRegion.RegionID + "/";
90// m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
91
92 WebRequest helloNeighbourRequest;
93
94 try
95 {
96 helloNeighbourRequest = WebRequest.Create(uri);
97 }
98 catch (Exception e)
99 {
100 m_log.Warn(string.Format(
101 "[NEIGHBOUR SERVICES CONNECTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3} ",
102 uri, thisRegion.RegionName, region.RegionName, e.Message), e);
103
104 return false;
105 }
106
107 helloNeighbourRequest.Method = "POST";
108 helloNeighbourRequest.ContentType = "application/json";
109 helloNeighbourRequest.Timeout = 10000;
110
111 // Fill it in
112 OSDMap args = null;
113 try
114 {
115 args = thisRegion.PackRegionInfoData();
116 }
117 catch (Exception e)
118 {
119 m_log.Warn(string.Format(
120 "[NEIGHBOUR SERVICES CONNECTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2} ",
121 thisRegion.RegionName, region.RegionName, e.Message), e);
122
123 return false;
124 }
125
126 // Add the regionhandle of the destination region
127 args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString());
128
129 string strBuffer = "";
130 byte[] buffer = new byte[1];
131
132 try
133 {
134 strBuffer = OSDParser.SerializeJsonString(args);
135 buffer = Util.UTF8NoBomEncoding.GetBytes(strBuffer);
136 }
137 catch (Exception e)
138 {
139 m_log.Warn(string.Format(
140 "[NEIGHBOUR SERVICES CONNECTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2} ",
141 thisRegion.RegionName, region.RegionName, e.Message), e);
142
143 return false;
144 }
145
146 Stream os = null;
147 try
148 { // send the Post
149 helloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
150 os = helloNeighbourRequest.GetRequestStream();
151 os.Write(buffer, 0, strBuffer.Length); //Send it
152 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
153 }
154 catch (Exception e)
155 {
156 m_log.Warn(string.Format(
157 "[NEIGHBOUR SERVICES CONNECTOR]: Unable to send HelloNeighbour from {0} to {1} (uri {2}). Exception {3} ",
158 thisRegion.RegionName, region.RegionName, uri, e.Message), e);
159
160 return false;
161 }
162 finally
163 {
164 if (os != null)
165 os.Dispose();
166 }
167
168 // Let's wait for the response
169 //m_log.Info("[REST COMMS]: Waiting for a reply after DoHelloNeighbourCall");
170
171 try
172 {
173 using (WebResponse webResponse = helloNeighbourRequest.GetResponse())
174 {
175 if (webResponse == null)
176 {
177 m_log.DebugFormat(
178 "[NEIGHBOUR SERVICES CONNECTOR]: Null reply on DoHelloNeighbourCall post from {0} to {1}",
179 thisRegion.RegionName, region.RegionName);
180 }
181
182 using (Stream s = webResponse.GetResponseStream())
183 {
184 using (StreamReader sr = new StreamReader(s))
185 {
186 //reply = sr.ReadToEnd().Trim();
187 sr.ReadToEnd().Trim();
188 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
189 }
190 }
191 }
192 }
193 catch (Exception e)
194 {
195 m_log.Warn(string.Format(
196 "[NEIGHBOUR SERVICES CONNECTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2} ",
197 region.RegionName, thisRegion.RegionName, e.Message), e);
198
199 return false;
200 }
201
202 return true;
203 }
204 }
205}
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
new file mode 100644
index 0000000..63f3f37
--- /dev/null
+++ b/OpenSim/Services/Connectors/Presence/PresenceServicesConnector.cs
@@ -0,0 +1,388 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Framework.ServiceAuth;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class PresenceServicesConnector : BaseServiceConnector, IPresenceService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public PresenceServicesConnector()
53 {
54 }
55
56 public PresenceServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public PresenceServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["PresenceService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini");
72 throw new Exception("Presence connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("PresenceServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[PRESENCE CONNECTOR]: No Server URI named in section PresenceService");
81 throw new Exception("Presence connector init error");
82 }
83 m_ServerURI = serviceURI;
84
85 base.Initialise(source, "PresenceService");
86 }
87
88
89 #region IPresenceService
90
91 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
92 {
93 Dictionary<string, object> sendData = new Dictionary<string, object>();
94 //sendData["SCOPEID"] = scopeID.ToString();
95 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
96 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
97 sendData["METHOD"] = "login";
98
99 sendData["UserID"] = userID;
100 sendData["SessionID"] = sessionID.ToString();
101 sendData["SecureSessionID"] = secureSessionID.ToString();
102
103 string reqString = ServerUtils.BuildQueryString(sendData);
104 string uri = m_ServerURI + "/presence";
105 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
106 try
107 {
108 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
109 uri,
110 reqString,
111 m_Auth);
112 if (reply != string.Empty)
113 {
114 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
115
116 if (replyData.ContainsKey("result"))
117 {
118 if (replyData["result"].ToString().ToLower() == "success")
119 return true;
120 else
121 return false;
122 }
123 else
124 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent reply data does not contain result field");
125
126 }
127 else
128 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent received empty reply");
129 }
130 catch (Exception e)
131 {
132 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
133 }
134
135 return false;
136
137 }
138
139 public bool LogoutAgent(UUID sessionID)
140 {
141 Dictionary<string, object> sendData = new Dictionary<string, object>();
142 //sendData["SCOPEID"] = scopeID.ToString();
143 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
144 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
145 sendData["METHOD"] = "logout";
146
147 sendData["SessionID"] = sessionID.ToString();
148
149 string reqString = ServerUtils.BuildQueryString(sendData);
150 string uri = m_ServerURI + "/presence";
151 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
152 try
153 {
154 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
155 uri,
156 reqString,
157 m_Auth);
158 if (reply != string.Empty)
159 {
160 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
161
162 if (replyData.ContainsKey("result"))
163 {
164 if (replyData["result"].ToString().ToLower() == "success")
165 return true;
166 else
167 return false;
168 }
169 else
170 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent reply data does not contain result field");
171
172 }
173 else
174 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent received empty reply");
175 }
176 catch (Exception e)
177 {
178 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
179 }
180
181 return false;
182 }
183
184 public bool LogoutRegionAgents(UUID regionID)
185 {
186 Dictionary<string, object> sendData = new Dictionary<string, object>();
187 //sendData["SCOPEID"] = scopeID.ToString();
188 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
189 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
190 sendData["METHOD"] = "logoutregion";
191
192 sendData["RegionID"] = regionID.ToString();
193
194 string reqString = ServerUtils.BuildQueryString(sendData);
195 string uri = m_ServerURI + "/presence";
196 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
197 try
198 {
199 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
200 uri,
201 reqString,
202 m_Auth);
203 if (reply != string.Empty)
204 {
205 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
206
207 if (replyData.ContainsKey("result"))
208 {
209 if (replyData["result"].ToString().ToLower() == "success")
210 return true;
211 else
212 return false;
213 }
214 else
215 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents reply data does not contain result field");
216
217 }
218 else
219 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents received empty reply");
220 }
221 catch (Exception e)
222 {
223 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
224 }
225
226 return false;
227 }
228
229 public bool ReportAgent(UUID sessionID, UUID regionID)
230 {
231 Dictionary<string, object> sendData = new Dictionary<string, object>();
232 //sendData["SCOPEID"] = scopeID.ToString();
233 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
234 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
235 sendData["METHOD"] = "report";
236
237 sendData["SessionID"] = sessionID.ToString();
238 sendData["RegionID"] = regionID.ToString();
239
240 string reqString = ServerUtils.BuildQueryString(sendData);
241 string uri = m_ServerURI + "/presence";
242 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
243 try
244 {
245 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
246 uri,
247 reqString,
248 m_Auth);
249 if (reply != string.Empty)
250 {
251 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
252
253 if (replyData.ContainsKey("result"))
254 {
255 if (replyData["result"].ToString().ToLower() == "success")
256 return true;
257 else
258 return false;
259 }
260 else
261 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent reply data does not contain result field");
262
263 }
264 else
265 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent received empty reply");
266 }
267 catch (Exception e)
268 {
269 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
270 }
271
272 return false;
273 }
274
275 public PresenceInfo GetAgent(UUID sessionID)
276 {
277 Dictionary<string, object> sendData = new Dictionary<string, object>();
278 //sendData["SCOPEID"] = scopeID.ToString();
279 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
280 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
281 sendData["METHOD"] = "getagent";
282
283 sendData["SessionID"] = sessionID.ToString();
284
285 string reply = string.Empty;
286 string reqString = ServerUtils.BuildQueryString(sendData);
287 string uri = m_ServerURI + "/presence";
288 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
289 try
290 {
291 reply = SynchronousRestFormsRequester.MakeRequest("POST",
292 uri,
293 reqString,
294 m_Auth);
295 if (reply == null || (reply != null && reply == string.Empty))
296 {
297 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply");
298 return null;
299 }
300 }
301 catch (Exception e)
302 {
303 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
304 return null;
305 }
306
307 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
308 PresenceInfo pinfo = null;
309
310 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
311 {
312 if (replyData["result"] is Dictionary<string, object>)
313 {
314 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]);
315 }
316 }
317
318 return pinfo;
319 }
320
321 public PresenceInfo[] GetAgents(string[] userIDs)
322 {
323 Dictionary<string, object> sendData = new Dictionary<string, object>();
324 //sendData["SCOPEID"] = scopeID.ToString();
325 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
326 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
327 sendData["METHOD"] = "getagents";
328
329 sendData["uuids"] = new List<string>(userIDs);
330
331 string reply = string.Empty;
332 string reqString = ServerUtils.BuildQueryString(sendData);
333 string uri = m_ServerURI + "/presence";
334 //m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
335 try
336 {
337 reply = SynchronousRestFormsRequester.MakeRequest("POST",
338 uri,
339 reqString,
340 m_Auth);
341 if (reply == null || (reply != null && reply == string.Empty))
342 {
343 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null or empty reply");
344 return null;
345 }
346 }
347 catch (Exception e)
348 {
349 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server at {0}: {1}", uri, e.Message);
350 }
351
352 List<PresenceInfo> rinfos = new List<PresenceInfo>();
353
354 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
355
356 if (replyData != null)
357 {
358 if (replyData.ContainsKey("result") &&
359 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
360 {
361 return new PresenceInfo[0];
362 }
363
364 Dictionary<string, object>.ValueCollection pinfosList = replyData.Values;
365 //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
366 foreach (object presence in pinfosList)
367 {
368 if (presence is Dictionary<string, object>)
369 {
370 PresenceInfo pinfo = new PresenceInfo((Dictionary<string, object>)presence);
371 rinfos.Add(pinfo);
372 }
373 else
374 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received invalid response type {0}",
375 presence.GetType());
376 }
377 }
378 else
379 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null response");
380
381 return rinfos.ToArray();
382 }
383
384
385 #endregion
386
387 }
388}
diff --git a/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2af2ec1
--- /dev/null
+++ b/OpenSim/Services/Connectors/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.Connectors")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("3ab0a9a1-3f45-4c07-a892-3848df8c0173")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.8.2.*")]
33
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
new file mode 100644
index 0000000..cd4781d
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
@@ -0,0 +1,100 @@
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.Reflection;
30using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Services.Interfaces;
33using OpenMetaverse;
34using log4net;
35
36namespace OpenSim.Services.Connectors.SimianGrid
37{
38 public class SimianActivityDetector
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private IGridUserService m_GridUserService;
43
44 public SimianActivityDetector(IGridUserService guService)
45 {
46 m_GridUserService = guService;
47 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Started");
48 }
49
50 public void AddRegion(Scene scene)
51 {
52 // For now the only events we listen to are these
53 // But we could trigger the position update more often
54 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
55 scene.EventManager.OnNewClient += OnNewClient;
56 scene.EventManager.OnAvatarEnteringNewParcel += OnEnteringNewParcel;
57 }
58
59 public void RemoveRegion(Scene scene)
60 {
61 scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent;
62 scene.EventManager.OnNewClient -= OnNewClient;
63 scene.EventManager.OnAvatarEnteringNewParcel -= OnEnteringNewParcel;
64 }
65
66 public void OnMakeRootAgent(ScenePresence sp)
67 {
68 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
69 Util.FireAndForget(delegate(object o)
70 {
71 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
72 }, null, "SimianActivityDetector.SetLastPositionOnMakeRootAgent");
73 }
74
75 public void OnNewClient(IClientAPI client)
76 {
77 client.OnConnectionClosed += OnConnectionClose;
78 }
79
80 public void OnConnectionClose(IClientAPI client)
81 {
82 if (client.SceneAgent.IsChildAgent)
83 return;
84
85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
86 m_GridUserService.LoggedOut(
87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
89 }
90
91 void OnEnteringNewParcel(ScenePresence sp, int localLandID, UUID regionID)
92 {
93 // Asynchronously update the position stored in the session table for this agent
94 Util.FireAndForget(delegate(object o)
95 {
96 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
97 }, null, "SimianActivityDetector.SetLastPositionOnEnteringNewParcel");
98 }
99 }
100} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
new file mode 100644
index 0000000..9ad4a7a
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -0,0 +1,685 @@
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.IO;
32using System.Net;
33using System.Reflection;
34using log4net;
35using Mono.Addins;
36using Nini.Config;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenMetaverse;
42using OpenMetaverse.StructuredData;
43
44namespace OpenSim.Services.Connectors.SimianGrid
45{
46 /// <summary>
47 /// Connects to the SimianGrid asset service
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAssetServiceConnector")]
50 public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55 private static string ZeroID = UUID.Zero.ToString();
56
57 private string m_serverUrl = String.Empty;
58 private IImprovedAssetCache m_cache;
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 {
66 if (m_cache == null)
67 {
68 IImprovedAssetCache cache = scene.RequestModuleInterface<IImprovedAssetCache>();
69 if (cache is ISharedRegionModule)
70 m_cache = cache;
71 }
72 }
73 public void PostInitialise() { }
74 public void Close() { }
75
76 public SimianAssetServiceConnector() { }
77 public string Name { get { return "SimianAssetServiceConnector"; } }
78 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAssetService>(this); } }
79 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAssetService>(this); } }
80
81 #endregion ISharedRegionModule
82
83 public SimianAssetServiceConnector(IConfigSource source)
84 {
85 CommonInit(source);
86 }
87
88 public SimianAssetServiceConnector(string url)
89 {
90 if (!url.EndsWith("/") && !url.EndsWith("="))
91 url = url + '/';
92 m_serverUrl = url;
93 }
94
95 public void Initialise(IConfigSource source)
96 {
97 IConfig moduleConfig = source.Configs["Modules"];
98 if (moduleConfig != null)
99 {
100 string name = moduleConfig.GetString("AssetServices", "");
101 if (name == Name)
102 CommonInit(source);
103 }
104 }
105
106 private void CommonInit(IConfigSource source)
107 {
108 IConfig gridConfig = source.Configs["AssetService"];
109 if (gridConfig != null)
110 {
111 string serviceUrl = gridConfig.GetString("AssetServerURI");
112 if (!String.IsNullOrEmpty(serviceUrl))
113 {
114 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
115 serviceUrl = serviceUrl + '/';
116 m_serverUrl = serviceUrl;
117 }
118 }
119
120 if (String.IsNullOrEmpty(m_serverUrl))
121 m_log.Info("[SIMIAN ASSET CONNECTOR]: No AssetServerURI specified, disabling connector");
122 else
123 m_Enabled = true;
124 }
125
126#region IAssetService
127
128 public AssetBase Get(string id)
129 {
130 if (String.IsNullOrEmpty(m_serverUrl))
131 {
132 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
133 throw new InvalidOperationException();
134 }
135
136 // Cache fetch
137 if (m_cache != null)
138 {
139 AssetBase asset = m_cache.Get(id);
140 if (asset != null)
141 return asset;
142 }
143
144 return SimianGetOperation(id);
145 }
146
147
148 public AssetBase GetCached(string id)
149 {
150 if (m_cache != null)
151 return m_cache.Get(id);
152
153 return null;
154 }
155
156 /// <summary>
157 /// Get an asset's metadata
158 /// </summary>
159 /// <param name="id"></param>
160 /// <returns></returns>
161 public AssetMetadata GetMetadata(string id)
162 {
163 if (String.IsNullOrEmpty(m_serverUrl))
164 {
165 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
166 throw new InvalidOperationException();
167 }
168
169 // Cache fetch
170 if (m_cache != null)
171 {
172 AssetBase asset = m_cache.Get(id);
173 if (asset != null)
174 return asset.Metadata;
175 }
176
177 // return GetRemoteMetadata(id);
178 return SimianGetMetadataOperation(id);
179 }
180
181 public byte[] GetData(string id)
182 {
183 if (String.IsNullOrEmpty(m_serverUrl))
184 {
185 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
186 throw new InvalidOperationException();
187 }
188
189 AssetBase asset = Get(id);
190
191 if (asset != null)
192 return asset.Data;
193
194 return null;
195 }
196
197 /// <summary>
198 /// Get an asset asynchronously
199 /// </summary>
200 /// <param name="id">The asset id</param>
201 /// <param name="sender">Represents the requester. Passed back via the handler</param>
202 /// <param name="handler">The handler to call back once the asset has been retrieved</param>
203 /// <returns>True if the id was parseable, false otherwise</returns>
204 public bool Get(string id, Object sender, AssetRetrieved handler)
205 {
206 if (String.IsNullOrEmpty(m_serverUrl))
207 {
208 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
209 throw new InvalidOperationException();
210 }
211
212 // Cache fetch
213 if (m_cache != null)
214 {
215 AssetBase asset = m_cache.Get(id);
216 if (asset != null)
217 {
218 handler(id, sender, asset);
219 return true;
220 }
221 }
222
223 Util.FireAndForget(
224 delegate(object o)
225 {
226 AssetBase asset = SimianGetOperation(id);
227 handler(id, sender, asset);
228 }, null, "SimianAssetServiceConnector.GetFromService"
229 );
230
231 return true;
232 }
233
234 public bool[] AssetsExist(string[] ids)
235 {
236 if (String.IsNullOrEmpty(m_serverUrl))
237 {
238 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
239 throw new InvalidOperationException();
240 }
241
242 bool[] exist = new bool[ids.Length];
243
244 for (int i = 0; i < ids.Length; i++)
245 {
246 AssetMetadata metadata = GetMetadata(ids[i]);
247 if (metadata != null)
248 exist[i] = true;
249 }
250
251 return exist;
252 }
253
254 /// <summary>
255 /// Creates a new asset
256 /// </summary>
257 /// Returns a random ID if none is passed into it
258 /// <param name="asset"></param>
259 /// <returns></returns>
260 public string Store(AssetBase asset)
261 {
262 if (String.IsNullOrEmpty(m_serverUrl))
263 {
264 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
265 throw new InvalidOperationException();
266 }
267
268 bool storedInCache = false;
269
270 // AssetID handling
271 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID)
272 {
273 asset.FullID = UUID.Random();
274 asset.ID = asset.FullID.ToString();
275 }
276
277 // Cache handling
278 if (m_cache != null)
279 {
280 m_cache.Cache(asset);
281 storedInCache = true;
282 }
283
284 // Local asset handling
285 if (asset.Local)
286 {
287 if (!storedInCache)
288 {
289 m_log.Error("Cannot store local " + asset.Metadata.ContentType + " asset without an asset cache");
290 asset.ID = null;
291 asset.FullID = UUID.Zero;
292 }
293
294 return asset.ID;
295 }
296
297 return SimianStoreOperation(asset);
298 }
299
300 /// <summary>
301 /// Update an asset's content
302 /// </summary>
303 /// Attachments and bare scripts need this!!
304 /// <param name="id"> </param>
305 /// <param name="data"></param>
306 /// <returns></returns>
307 public bool UpdateContent(string id, byte[] data)
308 {
309 if (String.IsNullOrEmpty(m_serverUrl))
310 {
311 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
312 throw new InvalidOperationException();
313 }
314
315 AssetBase asset = Get(id);
316
317 if (asset == null)
318 {
319 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset {0} for updating", id);
320 return false;
321 }
322
323 asset.Data = data;
324
325 string result = Store(asset);
326 return !String.IsNullOrEmpty(result);
327 }
328
329 /// <summary>
330 /// Delete an asset
331 /// </summary>
332 /// <param name="id"></param>
333 /// <returns></returns>
334 public bool Delete(string id)
335 {
336 if (String.IsNullOrEmpty(m_serverUrl))
337 {
338 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
339 throw new InvalidOperationException();
340 }
341
342 if (m_cache != null)
343 m_cache.Expire(id);
344
345 return SimianDeleteOperation(id);
346 }
347
348#endregion IAssetService
349
350#region SimianOperations
351 /// <summary>
352 /// Invokes the xRemoveAsset operation on the simian server to delete an asset
353 /// </summary>
354 /// <param name="id"></param>
355 /// <returns></returns>
356 private bool SimianDeleteOperation(string id)
357 {
358 try
359 {
360 NameValueCollection requestArgs = new NameValueCollection
361 {
362 { "RequestMethod", "xRemoveAsset" },
363 { "AssetID", id }
364 };
365
366 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
367 if (! response["Success"].AsBoolean())
368 {
369 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset; {0}",response["Message"].AsString());
370 return false;
371 }
372
373 return true;
374
375 }
376 catch (Exception ex)
377 {
378 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset {0}; {1}", id, ex.Message);
379 }
380
381 return false;
382 }
383
384 /// <summary>
385 /// Invokes the xAddAsset operation on the simian server to create or update an asset
386 /// </summary>
387 /// <param name="id"></param>
388 /// <returns></returns>
389 private string SimianStoreOperation(AssetBase asset)
390 {
391 try
392 {
393 NameValueCollection requestArgs = new NameValueCollection
394 {
395 { "RequestMethod", "xAddAsset" },
396 { "ContentType", asset.Metadata.ContentType },
397 { "EncodedData", Convert.ToBase64String(asset.Data) },
398 { "AssetID", asset.FullID.ToString() },
399 { "CreatorID", asset.Metadata.CreatorID },
400 { "Temporary", asset.Temporary ? "1" : "0" },
401 { "Name", asset.Name }
402 };
403
404 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
405 if (! response["Success"].AsBoolean())
406 {
407 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",response["Message"].AsString());
408 return null;
409 }
410
411 // asset.ID is always set before calling this function
412 return asset.ID;
413
414 }
415 catch (Exception ex)
416 {
417 m_log.ErrorFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",ex.Message);
418 }
419
420 return null;
421 }
422
423 /// <summary>
424 /// Invokes the xGetAsset operation on the simian server to get data associated with an asset
425 /// </summary>
426 /// <param name="id"></param>
427 /// <returns></returns>
428 private AssetBase SimianGetOperation(string id)
429 {
430 try
431 {
432 NameValueCollection requestArgs = new NameValueCollection
433 {
434 { "RequestMethod", "xGetAsset" },
435 { "ID", id }
436 };
437
438 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
439 if (! response["Success"].AsBoolean())
440 {
441 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset; {0}",response["Message"].AsString());
442 return null;
443 }
444
445 AssetBase asset = new AssetBase();
446
447 asset.ID = id;
448 asset.Name = String.Empty;
449 asset.Metadata.ContentType = response["ContentType"].AsString(); // this will also set the asset Type property
450 asset.CreatorID = response["CreatorID"].AsString();
451 asset.Data = System.Convert.FromBase64String(response["EncodedData"].AsString());
452 asset.Local = false;
453 asset.Temporary = response["Temporary"];
454
455 return asset;
456 }
457 catch (Exception ex)
458 {
459 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to retrieve asset {0}; {1}", id, ex.Message);
460 }
461
462 return null;
463 }
464
465 /// <summary>
466 /// Invokes the xGetAssetMetadata operation on the simian server to retrieve metadata for an asset
467 /// This operation is generally used to determine if an asset exists in the database
468 /// </summary>
469 /// <param name="id"></param>
470 /// <returns></returns>
471 private AssetMetadata SimianGetMetadataOperation(string id)
472 {
473 try
474 {
475 NameValueCollection requestArgs = new NameValueCollection
476 {
477 { "RequestMethod", "xGetAssetMetadata" },
478 { "ID", id }
479 };
480
481 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
482 if (! response["Success"].AsBoolean())
483 {
484 // this is not really an error, this call is used to test existence
485 // m_log.DebugFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset metadata; {0}",response["Message"].AsString());
486 return null;
487 }
488
489 AssetMetadata metadata = new AssetMetadata();
490 metadata.ID = id;
491 metadata.ContentType = response["ContentType"].AsString();
492 metadata.CreatorID = response["CreatorID"].AsString();
493 metadata.Local = false;
494 metadata.Temporary = response["Temporary"];
495
496 string lastModifiedStr = response["Last-Modified"].AsString();
497 if (! String.IsNullOrEmpty(lastModifiedStr))
498 {
499 DateTime lastModified;
500 if (DateTime.TryParse(lastModifiedStr, out lastModified))
501 metadata.CreationDate = lastModified;
502 }
503
504 return metadata;
505 }
506 catch (Exception ex)
507 {
508 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to get asset metadata; {0}", ex.Message);
509 }
510
511 return null;
512 }
513#endregion
514
515 // private AssetMetadata GetRemoteMetadata(string id)
516 // {
517 // Uri url;
518 // AssetMetadata metadata = null;
519
520 // // Determine if id is an absolute URL or a grid-relative UUID
521 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
522 // url = new Uri(m_serverUrl + id);
523
524 // try
525 // {
526 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
527 // request.Method = "HEAD";
528
529 // using (WebResponse response = request.GetResponse())
530 // {
531 // using (Stream responseStream = response.GetResponseStream())
532 // {
533 // // Create the metadata object
534 // metadata = new AssetMetadata();
535 // metadata.ContentType = response.ContentType;
536 // metadata.ID = id;
537
538 // UUID uuid;
539 // if (UUID.TryParse(id, out uuid))
540 // metadata.FullID = uuid;
541
542 // string lastModifiedStr = response.Headers.Get("Last-Modified");
543 // if (!String.IsNullOrEmpty(lastModifiedStr))
544 // {
545 // DateTime lastModified;
546 // if (DateTime.TryParse(lastModifiedStr, out lastModified))
547 // metadata.CreationDate = lastModified;
548 // }
549 // }
550 // }
551 // }
552 // catch (Exception ex)
553 // {
554 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
555 // }
556
557 // return metadata;
558 // }
559
560 // private AssetBase GetRemote(string id)
561 // {
562 // AssetBase asset = null;
563 // Uri url;
564
565 // // Determine if id is an absolute URL or a grid-relative UUID
566 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
567 // url = new Uri(m_serverUrl + id);
568
569 // try
570 // {
571 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
572
573 // using (WebResponse response = request.GetResponse())
574 // {
575 // using (Stream responseStream = response.GetResponseStream())
576 // {
577 // string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
578
579 // // Create the asset object
580 // asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
581
582 // UUID assetID;
583 // if (UUID.TryParse(id, out assetID))
584 // asset.FullID = assetID;
585
586 // // Grab the asset data from the response stream
587 // using (MemoryStream stream = new MemoryStream())
588 // {
589 // responseStream.CopyStream(stream, Int32.MaxValue);
590 // asset.Data = stream.ToArray();
591 // }
592 // }
593 // }
594
595 // // Cache store
596 // if (m_cache != null && asset != null)
597 // m_cache.Cache(asset);
598
599 // return asset;
600 // }
601 // catch (Exception ex)
602 // {
603 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message);
604 // return null;
605 // }
606 // }
607
608 // private string StoreRemote(AssetBase asset)
609 // {
610 // // Distinguish public and private assets
611 // bool isPublic = true;
612 // switch ((AssetType)asset.Type)
613 // {
614 // case AssetType.CallingCard:
615 // case AssetType.Gesture:
616 // case AssetType.LSLBytecode:
617 // case AssetType.LSLText:
618 // isPublic = false;
619 // break;
620 // }
621
622 // string errorMessage = null;
623
624 // // Build the remote storage request
625 // List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
626 // {
627 // new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
628 // new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
629 // new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
630 // new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
631 // new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
632 // };
633
634 // // Make the remote storage request
635 // try
636 // {
637 // // Simian does not require the asset ID to be in the URL because it's in the post data.
638 // // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
639 // HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
640
641 // using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
642 // {
643 // using (Stream responseStream = response.GetResponseStream())
644 // {
645 // string responseStr = null;
646
647 // try
648 // {
649 // responseStr = responseStream.GetStreamString();
650 // OSD responseOSD = OSDParser.Deserialize(responseStr);
651 // if (responseOSD.Type == OSDType.Map)
652 // {
653 // OSDMap responseMap = (OSDMap)responseOSD;
654 // if (responseMap["Success"].AsBoolean())
655 // return asset.ID;
656 // else
657 // errorMessage = "Upload failed: " + responseMap["Message"].AsString();
658 // }
659 // else
660 // {
661 // errorMessage = "Response format was invalid:\n" + responseStr;
662 // }
663 // }
664 // catch (Exception ex)
665 // {
666 // if (!String.IsNullOrEmpty(responseStr))
667 // errorMessage = "Failed to parse the response:\n" + responseStr;
668 // else
669 // errorMessage = "Failed to retrieve the response: " + ex.Message;
670 // }
671 // }
672 // }
673 // }
674 // catch (WebException ex)
675 // {
676 // errorMessage = ex.Message;
677 // }
678
679 // m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
680 // asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
681
682 // return null;
683 // }
684 }
685}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
new file mode 100644
index 0000000..3bd11d9
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -0,0 +1,307 @@
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.Specialized;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40
41namespace OpenSim.Services.Connectors.SimianGrid
42{
43 /// <summary>
44 /// Connects authentication/authorization to the SimianGrid backend
45 /// </summary>
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAuthenticationServiceConnector")]
47 public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private string m_serverUrl = String.Empty;
54 private bool m_Enabled = false;
55
56 #region ISharedRegionModule
57
58 public Type ReplaceableInterface { get { return null; } }
59 public void RegionLoaded(Scene scene) { }
60 public void PostInitialise() { }
61 public void Close() { }
62
63 public SimianAuthenticationServiceConnector() { }
64 public string Name { get { return "SimianAuthenticationServiceConnector"; } }
65 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAuthenticationService>(this); } }
66 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAuthenticationService>(this); } }
67
68 #endregion ISharedRegionModule
69
70 public SimianAuthenticationServiceConnector(IConfigSource source)
71 {
72 CommonInit(source);
73 }
74
75 public void Initialise(IConfigSource source)
76 {
77 IConfig moduleConfig = source.Configs["Modules"];
78 if (moduleConfig != null)
79 {
80 string name = moduleConfig.GetString("AuthenticationServices", "");
81 if (name == Name)
82 CommonInit(source);
83 }
84 }
85
86 private void CommonInit(IConfigSource source)
87 {
88 IConfig gridConfig = source.Configs["AuthenticationService"];
89 if (gridConfig != null)
90 {
91 string serviceUrl = gridConfig.GetString("AuthenticationServerURI");
92 if (!String.IsNullOrEmpty(serviceUrl))
93 {
94 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
95 serviceUrl = serviceUrl + '/';
96 m_serverUrl = serviceUrl;
97 m_Enabled = true;
98 }
99 }
100
101 if (String.IsNullOrEmpty(m_serverUrl))
102 m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector");
103 }
104
105 public string Authenticate(UUID principalID, string password, int lifetime)
106 {
107 NameValueCollection requestArgs = new NameValueCollection
108 {
109 { "RequestMethod", "GetIdentities" },
110 { "UserID", principalID.ToString() }
111 };
112
113 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
114 if (response["Success"].AsBoolean() && response["Identities"] is OSDArray)
115 {
116 bool md5hashFound = false;
117
118 OSDArray identities = (OSDArray)response["Identities"];
119 for (int i = 0; i < identities.Count; i++)
120 {
121 OSDMap identity = identities[i] as OSDMap;
122 if (identity != null)
123 {
124 if (identity["Type"].AsString() == "md5hash")
125 {
126 string authorizeResult;
127 if (CheckPassword(principalID, password, identity["Credential"].AsString(), out authorizeResult))
128 return authorizeResult;
129
130 md5hashFound = true;
131 break;
132 }
133 }
134 }
135
136 if (!md5hashFound)
137 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + principalID + ", no md5hash identity found");
138 }
139 else
140 {
141 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to retrieve identities for " + principalID + ": " +
142 response["Message"].AsString());
143 }
144
145 return String.Empty;
146 }
147
148 public bool Verify(UUID principalID, string token, int lifetime)
149 {
150 NameValueCollection requestArgs = new NameValueCollection
151 {
152 { "RequestMethod", "GetSession" },
153 { "SessionID", token }
154 };
155
156 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
157 if (response["Success"].AsBoolean())
158 {
159 return true;
160 }
161 else
162 {
163 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Could not verify session for " + principalID + ": " +
164 response["Message"].AsString());
165 }
166
167 return false;
168 }
169
170 public bool Release(UUID principalID, string token)
171 {
172 NameValueCollection requestArgs = new NameValueCollection
173 {
174 { "RequestMethod", "RemoveSession" },
175 { "UserID", principalID.ToString() }
176 };
177
178 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
179 if (response["Success"].AsBoolean())
180 {
181 return true;
182 }
183 else
184 {
185 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to remove session for " + principalID + ": " +
186 response["Message"].AsString());
187 }
188
189 return false;
190 }
191
192 public bool SetPassword(UUID principalID, string passwd)
193 {
194 // Fetch the user name first
195 NameValueCollection requestArgs = new NameValueCollection
196 {
197 { "RequestMethod", "GetUser" },
198 { "UserID", principalID.ToString() }
199 };
200
201 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
202 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
203 {
204 OSDMap userMap = (OSDMap)response["User"];
205 string identifier = userMap["Name"].AsString();
206
207 if (!String.IsNullOrEmpty(identifier))
208 {
209 // Add/update the md5hash identity
210 // TODO: Support salts when AddIdentity does
211 // TODO: Create an a1hash too for WebDAV logins
212 requestArgs = new NameValueCollection
213 {
214 { "RequestMethod", "AddIdentity" },
215 { "Identifier", identifier },
216 { "Credential", "$1$" + Utils.MD5String(passwd) },
217 { "Type", "md5hash" },
218 { "UserID", principalID.ToString() }
219 };
220
221 response = SimianGrid.PostToService(m_serverUrl, requestArgs);
222 bool success = response["Success"].AsBoolean();
223
224 if (!success)
225 m_log.WarnFormat("[SIMIAN AUTH CONNECTOR]: Failed to set password for {0} ({1})", identifier, principalID);
226
227 return success;
228 }
229 }
230 else
231 {
232 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to retrieve identities for " + principalID + ": " +
233 response["Message"].AsString());
234 }
235
236 return false;
237 }
238
239 public AuthInfo GetAuthInfo(UUID principalID)
240 {
241 throw new NotImplementedException();
242 }
243
244 public bool SetAuthInfo(AuthInfo info)
245 {
246 throw new NotImplementedException();
247 }
248
249 private bool CheckPassword(UUID userID, string password, string simianGridCredential, out string authorizeResult)
250 {
251 if (simianGridCredential.Contains(":"))
252 {
253 // Salted version
254 int idx = simianGridCredential.IndexOf(':');
255 string finalhash = simianGridCredential.Substring(0, idx);
256 string salt = simianGridCredential.Substring(idx + 1);
257
258 if (finalhash == Utils.MD5String(password + ":" + salt))
259 {
260 authorizeResult = Authorize(userID);
261 return true;
262 }
263 else
264 {
265 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + userID +
266 " using md5hash " + Utils.MD5String(password) + ":" + salt);
267 }
268 }
269 else
270 {
271 // Unsalted version
272 if (password == simianGridCredential ||
273 "$1$" + password == simianGridCredential ||
274 "$1$" + Utils.MD5String(password) == simianGridCredential ||
275 Utils.MD5String(password) == simianGridCredential ||
276 "$1$" + Utils.MD5String(password + ":") == simianGridCredential)
277 {
278 authorizeResult = Authorize(userID);
279 return true;
280 }
281 else
282 {
283 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + userID +
284 " using md5hash $1$" + Utils.MD5String(password));
285 }
286 }
287
288 authorizeResult = null;
289 return false;
290 }
291
292 private string Authorize(UUID userID)
293 {
294 NameValueCollection requestArgs = new NameValueCollection
295 {
296 { "RequestMethod", "AddSession" },
297 { "UserID", userID.ToString() }
298 };
299
300 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
301 if (response["Success"].AsBoolean())
302 return response["SessionID"].AsUUID().ToString();
303 else
304 return String.Empty;
305 }
306 }
307}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
new file mode 100644
index 0000000..a397740
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -0,0 +1,344 @@
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;
31// DEBUG ON
32using System.Diagnostics;
33// DEBUG OFF
34using System.Reflection;
35using log4net;
36using Mono.Addins;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenMetaverse;
43using OpenMetaverse.StructuredData;
44
45namespace OpenSim.Services.Connectors.SimianGrid
46{
47 /// <summary>
48 /// Connects avatar appearance data to the SimianGrid backend
49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianAvatarServiceConnector")]
51 public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56// private static string ZeroID = UUID.Zero.ToString();
57
58 private string m_serverUrl = String.Empty;
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 SimianAvatarServiceConnector() { }
69 public string Name { get { return "SimianAvatarServiceConnector"; } }
70 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAvatarService>(this); } }
71 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAvatarService>(this); } }
72
73 #endregion ISharedRegionModule
74
75 public SimianAvatarServiceConnector(IConfigSource source)
76 {
77 CommonInit(source);
78 }
79
80 public void Initialise(IConfigSource source)
81 {
82 IConfig moduleConfig = source.Configs["Modules"];
83 if (moduleConfig != null)
84 {
85 string name = moduleConfig.GetString("AvatarServices", "");
86 if (name == Name)
87 CommonInit(source);
88 }
89 }
90
91 private void CommonInit(IConfigSource source)
92 {
93 IConfig gridConfig = source.Configs["AvatarService"];
94 if (gridConfig != null)
95 {
96 string serviceUrl = gridConfig.GetString("AvatarServerURI");
97 if (!String.IsNullOrEmpty(serviceUrl))
98 {
99 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
100 serviceUrl = serviceUrl + '/';
101 m_serverUrl = serviceUrl;
102 m_Enabled = true;
103 }
104 }
105
106 if (String.IsNullOrEmpty(m_serverUrl))
107 m_log.Info("[SIMIAN AVATAR CONNECTOR]: No AvatarServerURI specified, disabling connector");
108 }
109
110 #region IAvatarService
111
112 // <summary>
113 // Retrieves the LLPackedAppearance field from user data and unpacks
114 // it into an AvatarAppearance structure
115 // </summary>
116 // <param name="userID"></param>
117 public AvatarAppearance GetAppearance(UUID userID)
118 {
119 NameValueCollection requestArgs = new NameValueCollection
120 {
121 { "RequestMethod", "GetUser" },
122 { "UserID", userID.ToString() }
123 };
124
125 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
126 if (response["Success"].AsBoolean())
127 {
128 OSDMap map = null;
129 try { map = OSDParser.DeserializeJson(response["LLPackedAppearance"].AsString()) as OSDMap; }
130 catch { }
131
132 if (map != null)
133 {
134 AvatarAppearance appearance = new AvatarAppearance(map);
135// DEBUG ON
136 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR] retrieved appearance for {0}:\n{1}",userID,appearance.ToString());
137// DEBUG OFF
138 return appearance;
139 }
140
141 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to decode appearance for {0}",userID);
142 return null;
143 }
144
145 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to get appearance for {0}: {1}",
146 userID,response["Message"].AsString());
147 return null;
148 }
149
150 // <summary>
151 // </summary>
152 // <param name=""></param>
153 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
154 {
155 OSDMap map = appearance.Pack();
156 if (map == null)
157 {
158 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to encode appearance for {0}",userID);
159 return false;
160 }
161
162 // m_log.DebugFormat("[SIMIAN AVATAR CONNECTOR] save appearance for {0}",userID);
163
164 NameValueCollection requestArgs = new NameValueCollection
165 {
166 { "RequestMethod", "AddUserData" },
167 { "UserID", userID.ToString() },
168 { "LLPackedAppearance", OSDParser.SerializeJsonString(map) }
169 };
170
171 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
172 bool success = response["Success"].AsBoolean();
173
174 if (! success)
175 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to save appearance for {0}: {1}",
176 userID,response["Message"].AsString());
177
178 return success;
179 }
180
181 // <summary>
182 // </summary>
183 // <param name=""></param>
184 public AvatarData GetAvatar(UUID userID)
185 {
186 NameValueCollection requestArgs = new NameValueCollection
187 {
188 { "RequestMethod", "GetUser" },
189 { "UserID", userID.ToString() }
190 };
191
192 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
193 if (response["Success"].AsBoolean())
194 {
195 OSDMap map = null;
196 try { map = OSDParser.DeserializeJson(response["LLAppearance"].AsString()) as OSDMap; }
197 catch { }
198
199 if (map != null)
200 {
201 AvatarWearable[] wearables = new AvatarWearable[13];
202 wearables[0] = new AvatarWearable(map["ShapeItem"].AsUUID(), map["ShapeAsset"].AsUUID());
203 wearables[1] = new AvatarWearable(map["SkinItem"].AsUUID(), map["SkinAsset"].AsUUID());
204 wearables[2] = new AvatarWearable(map["HairItem"].AsUUID(), map["HairAsset"].AsUUID());
205 wearables[3] = new AvatarWearable(map["EyesItem"].AsUUID(), map["EyesAsset"].AsUUID());
206 wearables[4] = new AvatarWearable(map["ShirtItem"].AsUUID(), map["ShirtAsset"].AsUUID());
207 wearables[5] = new AvatarWearable(map["PantsItem"].AsUUID(), map["PantsAsset"].AsUUID());
208 wearables[6] = new AvatarWearable(map["ShoesItem"].AsUUID(), map["ShoesAsset"].AsUUID());
209 wearables[7] = new AvatarWearable(map["SocksItem"].AsUUID(), map["SocksAsset"].AsUUID());
210 wearables[8] = new AvatarWearable(map["JacketItem"].AsUUID(), map["JacketAsset"].AsUUID());
211 wearables[9] = new AvatarWearable(map["GlovesItem"].AsUUID(), map["GlovesAsset"].AsUUID());
212 wearables[10] = new AvatarWearable(map["UndershirtItem"].AsUUID(), map["UndershirtAsset"].AsUUID());
213 wearables[11] = new AvatarWearable(map["UnderpantsItem"].AsUUID(), map["UnderpantsAsset"].AsUUID());
214 wearables[12] = new AvatarWearable(map["SkirtItem"].AsUUID(), map["SkirtAsset"].AsUUID());
215
216 AvatarAppearance appearance = new AvatarAppearance();
217 appearance.Wearables = wearables;
218 appearance.AvatarHeight = (float)map["Height"].AsReal();
219
220 AvatarData avatar = new AvatarData(appearance);
221
222 // Get attachments
223 map = null;
224 try { map = OSDParser.DeserializeJson(response["LLAttachments"].AsString()) as OSDMap; }
225 catch { }
226
227 if (map != null)
228 {
229 foreach (KeyValuePair<string, OSD> kvp in map)
230 avatar.Data[kvp.Key] = kvp.Value.AsString();
231 }
232
233 return avatar;
234 }
235 else
236 {
237 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed to get user appearance for " + userID +
238 ", LLAppearance is missing or invalid");
239 return null;
240 }
241 }
242 else
243 {
244 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed to get user appearance for " + userID + ": " +
245 response["Message"].AsString());
246 }
247
248 return null;
249 }
250
251 // <summary>
252 // </summary>
253 // <param name=""></param>
254 public bool SetAvatar(UUID userID, AvatarData avatar)
255 {
256 m_log.Debug("[SIMIAN AVATAR CONNECTOR]: SetAvatar called for " + userID);
257
258 if (avatar.AvatarType == 1) // LLAvatar
259 {
260 AvatarAppearance appearance = avatar.ToAvatarAppearance();
261
262 OSDMap map = new OSDMap();
263
264 map["Height"] = OSD.FromReal(appearance.AvatarHeight);
265
266 map["BodyItem"] = appearance.Wearables[AvatarWearable.BODY][0].ItemID.ToString();
267 map["EyesItem"] = appearance.Wearables[AvatarWearable.EYES][0].ItemID.ToString();
268 map["GlovesItem"] = appearance.Wearables[AvatarWearable.GLOVES][0].ItemID.ToString();
269 map["HairItem"] = appearance.Wearables[AvatarWearable.HAIR][0].ItemID.ToString();
270 map["JacketItem"] = appearance.Wearables[AvatarWearable.JACKET][0].ItemID.ToString();
271 map["PantsItem"] = appearance.Wearables[AvatarWearable.PANTS][0].ItemID.ToString();
272 map["ShirtItem"] = appearance.Wearables[AvatarWearable.SHIRT][0].ItemID.ToString();
273 map["ShoesItem"] = appearance.Wearables[AvatarWearable.SHOES][0].ItemID.ToString();
274 map["SkinItem"] = appearance.Wearables[AvatarWearable.SKIN][0].ItemID.ToString();
275 map["SkirtItem"] = appearance.Wearables[AvatarWearable.SKIRT][0].ItemID.ToString();
276 map["SocksItem"] = appearance.Wearables[AvatarWearable.SOCKS][0].ItemID.ToString();
277 map["UnderPantsItem"] = appearance.Wearables[AvatarWearable.UNDERPANTS][0].ItemID.ToString();
278 map["UnderShirtItem"] = appearance.Wearables[AvatarWearable.UNDERSHIRT][0].ItemID.ToString();
279 map["BodyAsset"] = appearance.Wearables[AvatarWearable.BODY][0].AssetID.ToString();
280 map["EyesAsset"] = appearance.Wearables[AvatarWearable.EYES][0].AssetID.ToString();
281 map["GlovesAsset"] = appearance.Wearables[AvatarWearable.GLOVES][0].AssetID.ToString();
282 map["HairAsset"] = appearance.Wearables[AvatarWearable.HAIR][0].AssetID.ToString();
283 map["JacketAsset"] = appearance.Wearables[AvatarWearable.JACKET][0].AssetID.ToString();
284 map["PantsAsset"] = appearance.Wearables[AvatarWearable.PANTS][0].AssetID.ToString();
285 map["ShirtAsset"] = appearance.Wearables[AvatarWearable.SHIRT][0].AssetID.ToString();
286 map["ShoesAsset"] = appearance.Wearables[AvatarWearable.SHOES][0].AssetID.ToString();
287 map["SkinAsset"] = appearance.Wearables[AvatarWearable.SKIN][0].AssetID.ToString();
288 map["SkirtAsset"] = appearance.Wearables[AvatarWearable.SKIRT][0].AssetID.ToString();
289 map["SocksAsset"] = appearance.Wearables[AvatarWearable.SOCKS][0].AssetID.ToString();
290 map["UnderPantsAsset"] = appearance.Wearables[AvatarWearable.UNDERPANTS][0].AssetID.ToString();
291 map["UnderShirtAsset"] = appearance.Wearables[AvatarWearable.UNDERSHIRT][0].AssetID.ToString();
292
293
294 OSDMap items = new OSDMap();
295 foreach (KeyValuePair<string, string> kvp in avatar.Data)
296 {
297 if (kvp.Key.StartsWith("_ap_"))
298 items.Add(kvp.Key, OSD.FromString(kvp.Value));
299 }
300
301 NameValueCollection requestArgs = new NameValueCollection
302 {
303 { "RequestMethod", "AddUserData" },
304 { "UserID", userID.ToString() },
305 { "LLAppearance", OSDParser.SerializeJsonString(map) },
306 { "LLAttachments", OSDParser.SerializeJsonString(items) }
307 };
308
309 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
310 bool success = response["Success"].AsBoolean();
311
312 if (!success)
313 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed saving appearance for " + userID + ": " + response["Message"].AsString());
314
315 return success;
316 }
317 else
318 {
319 m_log.Error("[SIMIAN AVATAR CONNECTOR]: Can't save appearance for " + userID + ". Unhandled avatar type " + avatar.AvatarType);
320 return false;
321 }
322 }
323
324 public bool ResetAvatar(UUID userID)
325 {
326 m_log.Error("[SIMIAN AVATAR CONNECTOR]: ResetAvatar called for " + userID + ", implement this");
327 return false;
328 }
329
330 public bool SetItems(UUID userID, string[] names, string[] values)
331 {
332 m_log.Error("[SIMIAN AVATAR CONNECTOR]: SetItems called for " + userID + " with " + names.Length + " names and " + values.Length + " values, implement this");
333 return false;
334 }
335
336 public bool RemoveItems(UUID userID, string[] names)
337 {
338 m_log.Error("[SIMIAN AVATAR CONNECTOR]: RemoveItems called for " + userID + " with " + names.Length + " names, implement this");
339 return false;
340 }
341
342 #endregion IAvatarService
343 }
344}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs
new file mode 100644
index 0000000..764e71f
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianExternalCapsModule.cs
@@ -0,0 +1,180 @@
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;
30using System.Collections.Generic;
31using System.Reflection;
32using System.IO;
33using System.Web;
34
35using log4net;
36using Nini.Config;
37using Mono.Addins;
38
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42using OpenSim.Framework;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.Framework.Scenes;
45using OpenSim.Services.Interfaces;
46using Caps = OpenSim.Framework.Capabilities.Caps;
47
48namespace OpenSim.Services.Connectors.SimianGrid
49{
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")]
51 public class SimianExternalCapsModule : INonSharedRegionModule, IExternalCapsModule
52 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private bool m_enabled = true;
56 private Scene m_scene;
57 private String m_simianURL;
58
59#region IRegionModule Members
60
61 public string Name
62 {
63 get { return this.GetType().Name; }
64 }
65
66 public void Initialise(IConfigSource config)
67 {
68 try
69 {
70 IConfig m_config;
71
72 if ((m_config = config.Configs["SimianExternalCaps"]) != null)
73 {
74 m_enabled = m_config.GetBoolean("Enabled", m_enabled);
75 if ((m_config = config.Configs["SimianGrid"]) != null)
76 {
77 m_simianURL = m_config.GetString("SimianServiceURL");
78 if (String.IsNullOrEmpty(m_simianURL))
79 {
80 //m_log.DebugFormat("[SimianGrid] service URL is not defined");
81 m_enabled = false;
82 return;
83 }
84 }
85 }
86 else
87 m_enabled = false;
88 }
89 catch (Exception e)
90 {
91 m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message);
92 return;
93 }
94 }
95
96 public void PostInitialise() { }
97 public void Close() { }
98
99 public void AddRegion(Scene scene)
100 {
101 if (! m_enabled)
102 return;
103
104 m_scene = scene;
105 m_scene.RegisterModuleInterface<IExternalCapsModule>(this);
106 }
107
108 public void RemoveRegion(Scene scene)
109 {
110 if (! m_enabled)
111 return;
112
113 m_scene.EventManager.OnRegisterCaps -= RegisterCapsEventHandler;
114 m_scene.EventManager.OnDeregisterCaps -= DeregisterCapsEventHandler;
115 }
116
117 public void RegionLoaded(Scene scene)
118 {
119 if (! m_enabled)
120 return;
121
122 m_scene.EventManager.OnRegisterCaps += RegisterCapsEventHandler;
123 m_scene.EventManager.OnDeregisterCaps += DeregisterCapsEventHandler;
124 }
125
126 public Type ReplaceableInterface
127 {
128 get { return null; }
129 }
130
131#endregion
132
133#region IExternalCapsModule
134 // Eg http://grid.sciencesim.com/GridPublic/%CAP%/%OP%/"
135 public bool RegisterExternalUserCapsHandler(UUID agentID, Caps caps, String capName, String urlSkel)
136 {
137 UUID cap = UUID.Random();
138
139 // Call to simian to register the cap we generated
140 // NameValueCollection requestArgs = new NameValueCollection
141 // {
142 // { "RequestMethod", "AddCapability" },
143 // { "Resource", "user" },
144 // { "Expiration", 0 },
145 // { "OwnerID", agentID.ToString() },
146 // { "CapabilityID", cap.ToString() }
147 // };
148
149 // OSDMap response = SimianGrid.PostToService(m_simianURL, requestArgs);
150
151 Dictionary<String,String> subs = new Dictionary<String,String>();
152 subs["%OP%"] = capName;
153 subs["%USR%"] = agentID.ToString();
154 subs["%CAP%"] = cap.ToString();
155 subs["%SIM%"] = m_scene.RegionInfo.RegionID.ToString();
156
157 caps.RegisterHandler(capName,ExpandSkeletonURL(urlSkel,subs));
158 return true;
159 }
160
161#endregion
162
163#region EventHandlers
164 public void RegisterCapsEventHandler(UUID agentID, Caps caps) { }
165 public void DeregisterCapsEventHandler(UUID agentID, Caps caps) { }
166#endregion
167
168 private String ExpandSkeletonURL(String urlSkel, Dictionary<String,String> subs)
169 {
170 String result = urlSkel;
171
172 foreach (KeyValuePair<String,String> kvp in subs)
173 {
174 result = result.Replace(kvp.Key,kvp.Value);
175 }
176
177 return result;
178 }
179 }
180} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
new file mode 100644
index 0000000..9a8164c
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
@@ -0,0 +1,236 @@
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 Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38
39using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
40
41namespace OpenSim.Services.Connectors.SimianGrid
42{
43 /// <summary>
44 /// Stores and retrieves friend lists from the SimianGrid backend
45 /// </summary>
46 public class SimianFriendsServiceConnector : IFriendsService
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 private string m_serverUrl = String.Empty;
53
54 public SimianFriendsServiceConnector(IConfigSource source)
55 {
56 Initialise(source);
57 }
58
59 public void Initialise(IConfigSource source)
60 {
61 IConfig gridConfig = source.Configs["FriendsService"];
62 if (gridConfig != null)
63 {
64 string serviceUrl = gridConfig.GetString("FriendsServerURI");
65 if (!String.IsNullOrEmpty(serviceUrl))
66 {
67 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
68 serviceUrl = serviceUrl + '/';
69 m_serverUrl = serviceUrl;
70 }
71 }
72
73 if (String.IsNullOrEmpty(m_serverUrl))
74 m_log.Info("[SIMIAN FRIENDS CONNECTOR]: No FriendsServerURI specified, disabling connector");
75 }
76
77 #region IFriendsService
78
79 public FriendInfo[] GetFriends(UUID principalID)
80 {
81 return GetFriends(principalID.ToString());
82 }
83
84 public FriendInfo[] GetFriends(string principalID)
85 {
86 if (String.IsNullOrEmpty(m_serverUrl))
87 return new FriendInfo[0];
88
89 Dictionary<UUID, FriendInfo> friends = new Dictionary<UUID, FriendInfo>();
90
91 OSDArray friendsArray = GetFriended(principalID);
92 OSDArray friendedMeArray = GetFriendedBy(principalID);
93
94 // Load the list of friends and their granted permissions
95 for (int i = 0; i < friendsArray.Count; i++)
96 {
97 OSDMap friendEntry = friendsArray[i] as OSDMap;
98 if (friendEntry != null)
99 {
100 UUID friendID = friendEntry["Key"].AsUUID();
101
102 FriendInfo friend = new FriendInfo();
103 if (!UUID.TryParse(principalID, out friend.PrincipalID))
104 {
105 string tmp = string.Empty;
106 if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp))
107 // bad record. ignore this entry
108 continue;
109 }
110
111 friend.Friend = friendID.ToString();
112 friend.MyFlags = friendEntry["Value"].AsInteger();
113 friend.TheirFlags = -1;
114
115 friends[friendID] = friend;
116 }
117 }
118
119 // Load the permissions those friends have granted to this user
120 for (int i = 0; i < friendedMeArray.Count; i++)
121 {
122 OSDMap friendedMeEntry = friendedMeArray[i] as OSDMap;
123 if (friendedMeEntry != null)
124 {
125 UUID friendID = friendedMeEntry["OwnerID"].AsUUID();
126
127 FriendInfo friend;
128 if (friends.TryGetValue(friendID, out friend))
129 friend.TheirFlags = friendedMeEntry["Value"].AsInteger();
130 }
131 }
132
133 // Convert the dictionary of friends to an array and return it
134 FriendInfo[] array = new FriendInfo[friends.Count];
135 int j = 0;
136 foreach (FriendInfo friend in friends.Values)
137 array[j++] = friend;
138
139 return array;
140 }
141
142 public bool StoreFriend(string principalID, string friend, int flags)
143 {
144 if (String.IsNullOrEmpty(m_serverUrl))
145 return true;
146
147 NameValueCollection requestArgs = new NameValueCollection
148 {
149 { "RequestMethod", "AddGeneric" },
150 { "OwnerID", principalID.ToString() },
151 { "Type", "Friend" },
152 { "Key", friend },
153 { "Value", flags.ToString() }
154 };
155
156 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
157 bool success = response["Success"].AsBoolean();
158
159 if (!success)
160 m_log.Error("[SIMIAN FRIENDS CONNECTOR]: Failed to store friend " + friend + " for user " + principalID + ": " + response["Message"].AsString());
161
162 return success;
163 }
164
165 public bool Delete(UUID principalID, string friend)
166 {
167 return Delete(principalID.ToString(), friend);
168 }
169
170 public bool Delete(string principalID, string friend)
171 {
172 if (String.IsNullOrEmpty(m_serverUrl))
173 return true;
174
175 NameValueCollection requestArgs = new NameValueCollection
176 {
177 { "RequestMethod", "RemoveGeneric" },
178 { "OwnerID", principalID.ToString() },
179 { "Type", "Friend" },
180 { "Key", friend }
181 };
182
183 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
184 bool success = response["Success"].AsBoolean();
185
186 if (!success)
187 m_log.Error("[SIMIAN FRIENDS CONNECTOR]: Failed to remove friend " + friend + " for user " + principalID + ": " + response["Message"].AsString());
188
189 return success;
190 }
191
192 #endregion IFriendsService
193
194 private OSDArray GetFriended(string ownerID)
195 {
196 NameValueCollection requestArgs = new NameValueCollection
197 {
198 { "RequestMethod", "GetGenerics" },
199 { "OwnerID", ownerID.ToString() },
200 { "Type", "Friend" }
201 };
202
203 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
204 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
205 {
206 return (OSDArray)response["Entries"];
207 }
208 else
209 {
210 m_log.Warn("[SIMIAN FRIENDS CONNECTOR]: Failed to retrieve friends for user " + ownerID + ": " + response["Message"].AsString());
211 return new OSDArray(0);
212 }
213 }
214
215 private OSDArray GetFriendedBy(string ownerID)
216 {
217 NameValueCollection requestArgs = new NameValueCollection
218 {
219 { "RequestMethod", "GetGenerics" },
220 { "Key", ownerID.ToString() },
221 { "Type", "Friend" }
222 };
223
224 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
225 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
226 {
227 return (OSDArray)response["Entries"];
228 }
229 else
230 {
231 m_log.Warn("[SIMIAN FRIENDS CONNECTOR]: Failed to retrieve reverse friends for user " + ownerID + ": " + response["Message"].AsString());
232 return new OSDArray(0);
233 }
234 }
235 }
236}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
new file mode 100644
index 0000000..a35d749
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
@@ -0,0 +1,147 @@
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
42[assembly: Addin("SimianGrid", OpenSim.VersionInfo.VersionNumber)]
43[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
44
45namespace OpenSim.Services.Connectors.SimianGrid
46{
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianExternalCapsModule")]
48 public class SimianGrid : ISharedRegionModule
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private IConfig m_config = null;
53
54 private String m_simianURL;
55
56#region IRegionModule Members
57
58 public string Name
59 {
60 get { return this.GetType().Name; }
61 }
62
63 public void Initialise(IConfigSource config)
64 {
65 try
66 {
67 m_config = config.Configs["SimianGrid"];
68
69 if (m_config != null)
70 {
71 m_simianURL = m_config.GetString("SimianServiceURL");
72 if (String.IsNullOrEmpty(m_simianURL))
73 {
74 // m_log.DebugFormat("[SimianGrid] service URL is not defined");
75 return;
76 }
77
78 InitialiseSimCap();
79 SimulatorCapability = SimulatorCapability.Trim();
80 m_log.InfoFormat("[SimianExternalCaps] using {0} as simulator capability",SimulatorCapability);
81 }
82 }
83 catch (Exception e)
84 {
85 m_log.ErrorFormat("[SimianExternalCaps] initialization error: {0}",e.Message);
86 return;
87 }
88 }
89
90 public void PostInitialise() { }
91 public void Close() { }
92 public void AddRegion(Scene scene) { }
93 public void RemoveRegion(Scene scene) { }
94 public void RegionLoaded(Scene scene) { }
95
96 public Type ReplaceableInterface
97 {
98 get { return null; }
99 }
100
101 ///<summary>
102 /// Try a variety of methods for finding the simian simulator capability; first check the
103 /// configuration itself, then look for a file that contains the cap, then finally look
104 /// for an environment variable that contains it.
105 ///</summary>
106 private void InitialiseSimCap()
107 {
108 if (m_config.Contains("SimulatorCapability"))
109 {
110 SimulatorCapability = m_config.GetString("SimulatorCapability");
111 return;
112 }
113
114 if (m_config.Contains("SimulatorCapabilityFile"))
115 {
116 String filename = m_config.GetString("SimulatorCapabilityFile");
117 if (System.IO.File.Exists(filename))
118 {
119 SimulatorCapability = System.IO.File.ReadAllText(filename);
120 return;
121 }
122 }
123
124 if (m_config.Contains("SimulatorCapabilityVariable"))
125 {
126 String envname = m_config.GetString("SimulatorCapabilityVariable");
127 String envvalue = System.Environment.GetEnvironmentVariable(envname);
128 if (envvalue != null)
129 {
130 SimulatorCapability = envvalue;
131 return;
132 }
133 }
134
135 m_log.WarnFormat("[SimianExternalCaps] no method specified for simulator capability");
136 }
137
138#endregion
139
140 public static String SimulatorCapability = UUID.Zero.ToString();
141 public static OSDMap PostToService(string url, NameValueCollection data)
142 {
143 data["cap"] = SimulatorCapability;
144 return WebUtil.PostToService(url, data);
145 }
146 }
147} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
new file mode 100644
index 0000000..8375c95
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
@@ -0,0 +1,266 @@
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 System.Net;
33using System.IO;
34using System.Timers;
35using System.Drawing;
36using System.Drawing.Imaging;
37
38using log4net;
39using Mono.Addins;
40using Nini.Config;
41using OpenSim.Framework;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes;
44using OpenMetaverse;
45using OpenMetaverse.StructuredData;
46
47//namespace OpenSim.Region.OptionalModules.Simian
48namespace OpenSim.Services.Connectors.SimianGrid
49{
50 /// <summary>
51 /// </summary>
52 /// <remarks>
53 /// </remarks>
54
55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGridMaptile")]
56 public class SimianGridMaptile : ISharedRegionModule
57 {
58 private static readonly ILog m_log =
59 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
60
61 private bool m_enabled = false;
62 private string m_serverUrl = String.Empty;
63 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
64
65 private int m_refreshtime = 0;
66 private int m_lastrefresh = 0;
67 private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
68
69 #region ISharedRegionModule
70
71 public Type ReplaceableInterface { get { return null; } }
72 public string Name { get { return "SimianGridMaptile"; } }
73 public void RegionLoaded(Scene scene) { }
74 public void Close() { }
75
76 ///<summary>
77 ///
78 ///</summary>
79 public void Initialise(IConfigSource source)
80 {
81 IConfig config = source.Configs["SimianGridMaptiles"];
82 if (config == null)
83 return;
84
85 if (! config.GetBoolean("Enabled", false))
86 return;
87
88 m_serverUrl = config.GetString("MaptileURL");
89 if (String.IsNullOrEmpty(m_serverUrl))
90 return;
91
92 int refreshseconds = Convert.ToInt32(config.GetString("RefreshTime"));
93 if (refreshseconds <= 0)
94 return;
95
96 m_refreshtime = refreshseconds * 1000; // convert from seconds to ms
97 m_log.InfoFormat("[SIMIAN MAPTILE] enabled with refresh timeout {0} and URL {1}",
98 m_refreshtime,m_serverUrl);
99
100 m_enabled = true;
101 }
102
103 ///<summary>
104 ///
105 ///</summary>
106 public void PostInitialise()
107 {
108 if (m_enabled)
109 {
110 m_refreshTimer.Enabled = true;
111 m_refreshTimer.AutoReset = true;
112 m_refreshTimer.Interval = 5 * 60 * 1000; // every 5 minutes
113 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
114 }
115 }
116
117
118 ///<summary>
119 ///
120 ///</summary>
121 public void AddRegion(Scene scene)
122 {
123 if (! m_enabled)
124 return;
125
126 // Every shared region module has to maintain an indepedent list of
127 // currently running regions
128 lock (m_scenes)
129 m_scenes[scene.RegionInfo.RegionID] = scene;
130 }
131
132 ///<summary>
133 ///
134 ///</summary>
135 public void RemoveRegion(Scene scene)
136 {
137 if (! m_enabled)
138 return;
139
140 lock (m_scenes)
141 m_scenes.Remove(scene.RegionInfo.RegionID);
142 }
143
144 #endregion ISharedRegionModule
145
146 ///<summary>
147 ///
148 ///</summary>
149 private void HandleMaptileRefresh(object sender, EventArgs ea)
150 {
151 // this approach is a bit convoluted becase we want to wait for the
152 // first upload to happen on startup but after all the objects are
153 // loaded and initialized
154 if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
155 return;
156
157 m_log.DebugFormat("[SIMIAN MAPTILE] map refresh fired");
158 lock (m_scenes)
159 {
160 foreach (IScene scene in m_scenes.Values)
161 {
162 try
163 {
164 UploadMapTile(scene);
165 }
166 catch (Exception ex)
167 {
168 m_log.WarnFormat("[SIMIAN MAPTILE] something bad happened {0}",ex.Message);
169 }
170 }
171 }
172
173 m_lastrefresh = Util.EnvironmentTickCount();
174 }
175
176 ///<summary>
177 ///
178 ///</summary>
179 private void UploadMapTile(IScene scene)
180 {
181 m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for {0}",scene.RegionInfo.RegionName);
182
183 // Create a PNG map tile and upload it to the AddMapTile API
184 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
185 if (tileGenerator == null)
186 {
187 m_log.Warn("[SIMIAN MAPTILE]: Cannot upload PNG map tile without an ImageGenerator");
188 return;
189 }
190
191 using (Bitmap mapTile = tileGenerator.CreateMapTile())
192 {
193 if (mapTile != null)
194 {
195 // If the region/maptile is legacy sized, just upload the one tile like it has always been done
196 if (mapTile.Width == Constants.RegionSize && mapTile.Height == Constants.RegionSize)
197 {
198 ConvertAndUploadMaptile(mapTile, scene.RegionInfo.RegionLocX, scene.RegionInfo.RegionLocY);
199 }
200 else
201 {
202 // For larger regions (varregion) we must cut the region image into legacy sized
203 // pieces since that is how the maptile system works.
204 // Note the assumption that varregions are always a multiple of legacy size.
205 for (uint xx = 0; xx < mapTile.Width; xx += Constants.RegionSize)
206 {
207 for (uint yy = 0; yy < mapTile.Height; yy += Constants.RegionSize)
208 {
209 // Images are addressed from the upper left corner so have to do funny
210 // math to pick out the sub-tile since regions are numbered from
211 // the lower left.
212 Rectangle rect = new Rectangle(
213 (int)xx,
214 mapTile.Height - (int)yy - (int)Constants.RegionSize,
215 (int)Constants.RegionSize, (int)Constants.RegionSize);
216
217 using (Bitmap subMapTile = mapTile.Clone(rect, mapTile.PixelFormat))
218 {
219 uint locX = scene.RegionInfo.RegionLocX + (xx / Constants.RegionSize);
220 uint locY = scene.RegionInfo.RegionLocY + (yy / Constants.RegionSize);
221
222 ConvertAndUploadMaptile(subMapTile, locX, locY);
223 }
224 }
225 }
226 }
227 }
228 else
229 {
230 m_log.WarnFormat("[SIMIAN MAPTILE] Tile image generation failed");
231 }
232 }
233
234 }
235
236 ///<summary>
237 ///
238 ///</summary>
239 private void ConvertAndUploadMaptile(Image mapTile, uint locX, uint locY)
240 {
241 //m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for location {0}, {1}", locX, locY);
242
243 byte[] pngData = Utils.EmptyBytes;
244 using (MemoryStream stream = new MemoryStream())
245 {
246 mapTile.Save(stream, ImageFormat.Png);
247 pngData = stream.ToArray();
248 }
249
250 NameValueCollection requestArgs = new NameValueCollection
251 {
252 { "RequestMethod", "xAddMapTile" },
253 { "X", locX.ToString() },
254 { "Y", locY.ToString() },
255 { "ContentType", "image/png" },
256 { "EncodedData", System.Convert.ToBase64String(pngData) }
257 };
258
259 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
260 if (! response["Success"].AsBoolean())
261 {
262 m_log.WarnFormat("[SIMIAN MAPTILE] failed to store map tile; {0}",response["Message"].AsString());
263 }
264 }
265 }
266} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
new file mode 100644
index 0000000..b031f21
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -0,0 +1,484 @@
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.IO;
32using System.Net;
33using System.Reflection;
34using log4net;
35using Mono.Addins;
36using Nini.Config;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenMetaverse;
42using OpenMetaverse.StructuredData;
43
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45
46namespace OpenSim.Services.Connectors.SimianGrid
47{
48 /// <summary>
49 /// Connects region registration and neighbor lookups to the SimianGrid
50 /// backend
51 /// </summary>
52 public class SimianGridServiceConnector : IGridService
53 {
54 private static readonly ILog m_log =
55 LogManager.GetLogger(
56 MethodBase.GetCurrentMethod().DeclaringType);
57
58 private string m_ServerURI = String.Empty;
59// private bool m_Enabled = false;
60
61 public SimianGridServiceConnector() { }
62 public SimianGridServiceConnector(string serverURI)
63 {
64 m_ServerURI = serverURI.TrimEnd('/');
65 }
66
67 public SimianGridServiceConnector(IConfigSource source)
68 {
69 CommonInit(source);
70 }
71
72 public void Initialise(IConfigSource source)
73 {
74 CommonInit(source);
75 }
76
77 private void CommonInit(IConfigSource source)
78 {
79 IConfig gridConfig = source.Configs["GridService"];
80 if (gridConfig == null)
81 {
82 m_log.Error("[SIMIAN GRID CONNECTOR]: GridService missing from OpenSim.ini");
83 throw new Exception("Grid connector init error");
84 }
85
86 string serviceUrl = gridConfig.GetString("GridServerURI");
87 if (String.IsNullOrEmpty(serviceUrl))
88 {
89 m_log.Error("[SIMIAN GRID CONNECTOR]: No Server URI named in section GridService");
90 throw new Exception("Grid connector init error");
91 }
92
93 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
94 serviceUrl = serviceUrl + '/';
95 m_ServerURI = serviceUrl;
96// m_Enabled = true;
97 }
98
99 #region IGridService
100
101 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
102 {
103 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
104 Vector3d maxPosition = minPosition + new Vector3d(regionInfo.RegionSizeX, regionInfo.RegionSizeY, Constants.RegionHeight);
105
106 OSDMap extraData = new OSDMap
107 {
108 { "ServerURI", OSD.FromString(regionInfo.ServerURI) },
109 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) },
110 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) },
111 { "ExternalAddress", OSD.FromString(regionInfo.ExternalEndPoint.Address.ToString()) },
112 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) },
113 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) },
114 { "Access", OSD.FromInteger(regionInfo.Access) },
115 { "RegionSecret", OSD.FromString(regionInfo.RegionSecret) },
116 { "EstateOwner", OSD.FromUUID(regionInfo.EstateOwner) },
117 { "Token", OSD.FromString(regionInfo.Token) }
118 };
119
120 NameValueCollection requestArgs = new NameValueCollection
121 {
122 { "RequestMethod", "AddScene" },
123 { "SceneID", regionInfo.RegionID.ToString() },
124 { "Name", regionInfo.RegionName },
125 { "MinPosition", minPosition.ToString() },
126 { "MaxPosition", maxPosition.ToString() },
127 { "Address", regionInfo.ServerURI },
128 { "Enabled", "1" },
129 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
130 };
131
132 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
133 if (response["Success"].AsBoolean())
134 return String.Empty;
135 else
136 return "Region registration for " + regionInfo.RegionName + " failed: " + response["Message"].AsString();
137 }
138
139 public bool DeregisterRegion(UUID regionID)
140 {
141 NameValueCollection requestArgs = new NameValueCollection
142 {
143 { "RequestMethod", "AddScene" },
144 { "SceneID", regionID.ToString() },
145 { "Enabled", "0" }
146 };
147
148 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
149 bool success = response["Success"].AsBoolean();
150
151 if (!success)
152 m_log.Warn("[SIMIAN GRID CONNECTOR]: Region deregistration for " + regionID + " failed: " + response["Message"].AsString());
153
154 return success;
155 }
156
157 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
158 {
159 GridRegion region = GetRegionByUUID(scopeID, regionID);
160
161 int NEIGHBOR_RADIUS = Math.Max(region.RegionSizeX, region.RegionSizeY) / 2;
162
163 if (region != null)
164 {
165 List<GridRegion> regions = GetRegionRange(scopeID,
166 region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + region.RegionSizeX + NEIGHBOR_RADIUS,
167 region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + region.RegionSizeY + NEIGHBOR_RADIUS);
168
169 for (int i = 0; i < regions.Count; i++)
170 {
171 if (regions[i].RegionID == regionID)
172 {
173 regions.RemoveAt(i);
174 break;
175 }
176 }
177
178// m_log.Debug("[SIMIAN GRID CONNECTOR]: Found " + regions.Count + " neighbors for region " + regionID);
179 return regions;
180 }
181
182 return new List<GridRegion>(0);
183 }
184
185 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
186 {
187 NameValueCollection requestArgs = new NameValueCollection
188 {
189 { "RequestMethod", "GetScene" },
190 { "SceneID", regionID.ToString() }
191 };
192
193 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString());
194
195 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
196 if (response["Success"].AsBoolean())
197 {
198 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString());
199 return ResponseToGridRegion(response);
200 }
201 else
202 {
203 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID);
204 return null;
205 }
206 }
207
208 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
209 {
210 // Go one meter in from the requested x/y coords to avoid requesting a position
211 // that falls on the border of two sims
212 Vector3d position = new Vector3d(x + 1, y + 1, 0.0);
213
214 NameValueCollection requestArgs = new NameValueCollection
215 {
216 { "RequestMethod", "GetScene" },
217 { "Position", position.ToString() },
218 { "Enabled", "1" }
219 };
220
221 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString());
222
223 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
224 if (response["Success"].AsBoolean())
225 {
226 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString());
227 return ResponseToGridRegion(response);
228 }
229 else
230 {
231 // m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}",
232 // Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
233 return null;
234 }
235 }
236
237 public GridRegion GetRegionByName(UUID scopeID, string regionName)
238 {
239 List<GridRegion> regions = GetRegionsByName(scopeID, regionName, 1);
240
241 m_log.Debug("[SIMIAN GRID CONNECTOR]: Got " + regions.Count + " matches for region name " + regionName);
242
243 if (regions.Count > 0)
244 return regions[0];
245
246 return null;
247 }
248
249 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
250 {
251 List<GridRegion> foundRegions = new List<GridRegion>();
252
253 NameValueCollection requestArgs = new NameValueCollection
254 {
255 { "RequestMethod", "GetScenes" },
256 { "NameQuery", name },
257 { "Enabled", "1" }
258 };
259 if (maxNumber > 0)
260 requestArgs["MaxNumber"] = maxNumber.ToString();
261
262 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name);
263
264 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
265 if (response["Success"].AsBoolean())
266 {
267 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
268
269 OSDArray array = response["Scenes"] as OSDArray;
270 if (array != null)
271 {
272 for (int i = 0; i < array.Count; i++)
273 {
274 GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
275 if (region != null)
276 foundRegions.Add(region);
277 }
278 }
279 }
280
281 return foundRegions;
282 }
283
284 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
285 {
286 List<GridRegion> foundRegions = new List<GridRegion>();
287
288 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
289 Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
290
291 NameValueCollection requestArgs = new NameValueCollection
292 {
293 { "RequestMethod", "GetScenes" },
294 { "MinPosition", minPosition.ToString() },
295 { "MaxPosition", maxPosition.ToString() },
296 { "Enabled", "1" }
297 };
298
299 //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString());
300
301
302 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
303 if (response["Success"].AsBoolean())
304 {
305 OSDArray array = response["Scenes"] as OSDArray;
306 if (array != null)
307 {
308 for (int i = 0; i < array.Count; i++)
309 {
310 GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
311 if (region != null)
312 foundRegions.Add(region);
313 }
314 }
315 }
316
317 return foundRegions;
318 }
319
320 public List<GridRegion> GetDefaultRegions(UUID scopeID)
321 {
322 // TODO: Allow specifying the default grid location
323 const int DEFAULT_X = 1000 * 256;
324 const int DEFAULT_Y = 1000 * 256;
325
326 GridRegion defRegion = GetNearestRegion(new Vector3d(DEFAULT_X, DEFAULT_Y, 0.0), true);
327 if (defRegion != null)
328 return new List<GridRegion>(1) { defRegion };
329 else
330 return new List<GridRegion>(0);
331 }
332
333 public List<GridRegion> GetDefaultHypergridRegions(UUID scopeID)
334 {
335 // TODO: Allow specifying the default grid location
336 return GetDefaultRegions(scopeID);
337 }
338
339 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
340 {
341 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
342 if (defRegion != null)
343 return new List<GridRegion>(1) { defRegion };
344 else
345 return new List<GridRegion>(0);
346 }
347
348 public List<GridRegion> GetHyperlinks(UUID scopeID)
349 {
350 List<GridRegion> foundRegions = new List<GridRegion>();
351
352 NameValueCollection requestArgs = new NameValueCollection
353 {
354 { "RequestMethod", "GetScenes" },
355 { "HyperGrid", "true" },
356 { "Enabled", "1" }
357 };
358
359 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
360 if (response["Success"].AsBoolean())
361 {
362 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
363
364 OSDArray array = response["Scenes"] as OSDArray;
365 if (array != null)
366 {
367 for (int i = 0; i < array.Count; i++)
368 {
369 GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
370 if (region != null)
371 foundRegions.Add(region);
372 }
373 }
374 }
375
376 return foundRegions;
377 }
378
379 public int GetRegionFlags(UUID scopeID, UUID regionID)
380 {
381 NameValueCollection requestArgs = new NameValueCollection
382 {
383 { "RequestMethod", "GetScene" },
384 { "SceneID", regionID.ToString() }
385 };
386
387 m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString());
388
389 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
390 if (response["Success"].AsBoolean())
391 {
392 OSDMap extraData = response["ExtraData"] as OSDMap;
393 int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0;
394 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0;
395 int flags = enabled | hypergrid;
396 m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
397 return flags;
398 }
399 else
400 {
401 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID + " during region flags check");
402 return -1;
403 }
404 }
405
406 public Dictionary<string, object> GetExtraFeatures()
407 {
408 /// See SimulatorFeaturesModule - Need to get map, search and destination guide
409 Dictionary<string, object> extraFeatures = new Dictionary<string, object>();
410 return extraFeatures;
411 }
412
413 #endregion IGridService
414
415 private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled)
416 {
417 NameValueCollection requestArgs = new NameValueCollection
418 {
419 { "RequestMethod", "GetScene" },
420 { "Position", position.ToString() },
421 { "FindClosest", "1" }
422 };
423 if (onlyEnabled)
424 requestArgs["Enabled"] = "1";
425
426 OSDMap response = SimianGrid.PostToService(m_ServerURI, requestArgs);
427 if (response["Success"].AsBoolean())
428 {
429 return ResponseToGridRegion(response);
430 }
431 else
432 {
433 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at " + position);
434 return null;
435 }
436 }
437
438 private GridRegion ResponseToGridRegion(OSDMap response)
439 {
440 if (response == null)
441 return null;
442
443 OSDMap extraData = response["ExtraData"] as OSDMap;
444 if (extraData == null)
445 return null;
446
447 GridRegion region = new GridRegion();
448
449 region.RegionID = response["SceneID"].AsUUID();
450 region.RegionName = response["Name"].AsString();
451
452 Vector3d minPosition = response["MinPosition"].AsVector3d();
453 Vector3d maxPosition = response["MaxPosition"].AsVector3d();
454 region.RegionLocX = (int)minPosition.X;
455 region.RegionLocY = (int)minPosition.Y;
456
457 region.RegionSizeX = (int)maxPosition.X - (int)minPosition.X;
458 region.RegionSizeY = (int)maxPosition.Y - (int)minPosition.Y;
459
460 if ( ! extraData["HyperGrid"] ) {
461 Uri httpAddress = response["Address"].AsUri();
462 region.ExternalHostName = httpAddress.Host;
463 region.HttpPort = (uint)httpAddress.Port;
464
465 IPAddress internalAddress;
466 IPAddress.TryParse(extraData["InternalAddress"].AsString(), out internalAddress);
467 if (internalAddress == null)
468 internalAddress = IPAddress.Any;
469
470 region.InternalEndPoint = new IPEndPoint(internalAddress, extraData["InternalPort"].AsInteger());
471 region.TerrainImage = extraData["MapTexture"].AsUUID();
472 region.Access = (byte)extraData["Access"].AsInteger();
473 region.RegionSecret = extraData["RegionSecret"].AsString();
474 region.EstateOwner = extraData["EstateOwner"].AsUUID();
475 region.Token = extraData["Token"].AsString();
476 region.ServerURI = extraData["ServerURI"].AsString();
477 } else {
478 region.ServerURI = response["Address"];
479 }
480
481 return region;
482 }
483 }
484}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
new file mode 100644
index 0000000..e793420
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -0,0 +1,941 @@
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 OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using PermissionMask = OpenSim.Framework.PermissionMask;
42
43namespace OpenSim.Services.Connectors.SimianGrid
44{
45 /// <summary>
46 /// Permissions bitflags
47 /// </summary>
48 /*
49 [Flags]
50 public enum PermissionMask : uint
51 {
52 None = 0,
53 Transfer = 1 << 13,
54 Modify = 1 << 14,
55 Copy = 1 << 15,
56 Move = 1 << 19,
57 Damage = 1 << 20,
58 All = 0x7FFFFFFF
59 }
60 */
61
62 /// <summary>
63 /// Connects avatar inventories to the SimianGrid backend
64 /// </summary>
65 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianInventoryServiceConnector")]
66 public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule
67 {
68 private static readonly ILog m_log =
69 LogManager.GetLogger(
70 MethodBase.GetCurrentMethod().DeclaringType);
71
72 private string m_serverUrl = String.Empty;
73 private string m_userServerUrl = String.Empty;
74// private object m_gestureSyncRoot = new object();
75 private bool m_Enabled = false;
76
77 private const double CACHE_EXPIRATION_SECONDS = 20.0;
78 private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache;
79
80 #region ISharedRegionModule
81
82 public Type ReplaceableInterface { get { return null; } }
83 public void RegionLoaded(Scene scene) { }
84 public void PostInitialise() { }
85 public void Close() { }
86
87 public SimianInventoryServiceConnector() { }
88 public string Name { get { return "SimianInventoryServiceConnector"; } }
89 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IInventoryService>(this); } }
90 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IInventoryService>(this); } }
91
92 #endregion ISharedRegionModule
93
94 public SimianInventoryServiceConnector(IConfigSource source)
95 {
96 CommonInit(source);
97 }
98
99 public SimianInventoryServiceConnector(string url)
100 {
101 if (!url.EndsWith("/") && !url.EndsWith("="))
102 url = url + '/';
103 m_serverUrl = url;
104
105 if (m_ItemCache == null)
106 m_ItemCache = new ExpiringCache<UUID, InventoryItemBase>();
107
108 }
109
110 public void Initialise(IConfigSource source)
111 {
112 IConfig moduleConfig = source.Configs["Modules"];
113 if (moduleConfig != null)
114 {
115 string name = moduleConfig.GetString("InventoryServices", "");
116 if (name == Name)
117 CommonInit(source);
118 }
119 }
120
121 private void CommonInit(IConfigSource source)
122 {
123 IConfig gridConfig = source.Configs["InventoryService"];
124 if (gridConfig != null)
125 {
126 string serviceUrl = gridConfig.GetString("InventoryServerURI");
127 if (!String.IsNullOrEmpty(serviceUrl))
128 {
129 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
130 serviceUrl = serviceUrl + '/';
131 m_serverUrl = serviceUrl;
132
133 gridConfig = source.Configs["UserAccountService"];
134 if (gridConfig != null)
135 {
136 serviceUrl = gridConfig.GetString("UserAccountServerURI");
137 if (!String.IsNullOrEmpty(serviceUrl))
138 {
139 m_userServerUrl = serviceUrl;
140 m_Enabled = true;
141 if (m_ItemCache == null)
142 m_ItemCache = new ExpiringCache<UUID, InventoryItemBase>();
143 }
144 }
145 }
146 }
147
148 if (String.IsNullOrEmpty(m_serverUrl))
149 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector");
150 else if (String.IsNullOrEmpty(m_userServerUrl))
151 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector");
152 }
153
154 /// <summary>
155 /// Create the entire inventory for a given user
156 /// </summary>
157 /// <param name="user"></param>
158 /// <returns></returns>
159 public bool CreateUserInventory(UUID userID)
160 {
161 NameValueCollection requestArgs = new NameValueCollection
162 {
163 { "RequestMethod", "AddInventory" },
164 { "OwnerID", userID.ToString() }
165 };
166
167 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
168 bool success = response["Success"].AsBoolean();
169
170 if (!success)
171 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Inventory creation for " + userID + " failed: " + response["Message"].AsString());
172
173 return success;
174 }
175
176 /// <summary>
177 /// Gets the skeleton of the inventory -- folders only
178 /// </summary>
179 /// <param name="userID"></param>
180 /// <returns></returns>
181 public List<InventoryFolderBase> GetInventorySkeleton(UUID userID)
182 {
183 NameValueCollection requestArgs = new NameValueCollection
184 {
185 { "RequestMethod", "GetInventoryNode" },
186 { "ItemID", userID.ToString() },
187 { "OwnerID", userID.ToString() },
188 { "IncludeFolders", "1" },
189 { "IncludeItems", "0" },
190 { "ChildrenOnly", "0" }
191 };
192
193 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
194 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
195 {
196 OSDArray items = (OSDArray)response["Items"];
197 return GetFoldersFromResponse(items, userID, true);
198 }
199 else
200 {
201 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID + ": " +
202 response["Message"].AsString());
203 return new List<InventoryFolderBase>(0);
204 }
205 }
206
207 /// <summary>
208 /// Retrieve the root inventory folder for the given user.
209 /// </summary>
210 /// <param name="userID"></param>
211 /// <returns>null if no root folder was found</returns>
212 public InventoryFolderBase GetRootFolder(UUID userID)
213 {
214 NameValueCollection requestArgs = new NameValueCollection
215 {
216 { "RequestMethod", "GetInventoryNode" },
217 { "ItemID", userID.ToString() },
218 { "OwnerID", userID.ToString() },
219 { "IncludeFolders", "1" },
220 { "IncludeItems", "0" },
221 { "ChildrenOnly", "1" }
222 };
223
224 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
225 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
226 {
227 OSDArray items = (OSDArray)response["Items"];
228 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, userID, true);
229
230 if (folders.Count > 0)
231 return folders[0];
232 }
233
234 return null;
235 }
236
237 /// <summary>
238 /// Gets the user folder for the given folder-type
239 /// </summary>
240 /// <param name="userID"></param>
241 /// <param name="type"></param>
242 /// <returns></returns>
243 public InventoryFolderBase GetFolderForType(UUID userID, FolderType type)
244 {
245 string contentType = SLUtil.SLAssetTypeToContentType((int)type);
246
247 NameValueCollection requestArgs = new NameValueCollection
248 {
249 { "RequestMethod", "GetFolderForType" },
250 { "ContentType", contentType },
251 { "OwnerID", userID.ToString() }
252 };
253
254 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
255 if (response["Success"].AsBoolean() && response["Folder"] is OSDMap)
256 {
257 OSDMap folder = (OSDMap)response["Folder"];
258
259 return new InventoryFolderBase(
260 folder["ID"].AsUUID(),
261 folder["Name"].AsString(),
262 folder["OwnerID"].AsUUID(),
263 (short)SLUtil.ContentTypeToSLAssetType(folder["ContentType"].AsString()),
264 folder["ParentID"].AsUUID(),
265 (ushort)folder["Version"].AsInteger()
266 );
267 }
268 else
269 {
270 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Default folder not found for content type " + contentType + ": " + response["Message"].AsString());
271 return GetRootFolder(userID);
272 }
273 }
274
275 /// <summary>
276 /// Get an item, given by its UUID
277 /// </summary>
278 /// <param name="item"></param>
279 /// <returns></returns>
280 public InventoryItemBase GetItem(InventoryItemBase item)
281 {
282 InventoryItemBase retrieved = null;
283 if (m_ItemCache.TryGetValue(item.ID, out retrieved))
284 return retrieved;
285
286 NameValueCollection requestArgs = new NameValueCollection
287 {
288 { "RequestMethod", "GetInventoryNode" },
289 { "ItemID", item.ID.ToString() },
290 { "OwnerID", item.Owner.ToString() },
291 { "IncludeFolders", "1" },
292 { "IncludeItems", "1" },
293 { "ChildrenOnly", "1" }
294 };
295
296 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
297 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
298 {
299 List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]);
300 if (items.Count > 0)
301 {
302 // The requested item should be the first in this list, but loop through
303 // and sanity check just in case
304 for (int i = 0; i < items.Count; i++)
305 {
306 if (items[i].ID == item.ID)
307 {
308 retrieved = items[i];
309 m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
310 return retrieved;
311 }
312 }
313 }
314 }
315
316 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Item " + item.ID + " owned by " + item.Owner + " not found");
317 return null;
318 }
319
320 public InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
321 {
322 InventoryItemBase[] result = new InventoryItemBase[itemIDs.Length];
323 int i = 0;
324 InventoryItemBase item = new InventoryItemBase();
325 item.Owner = principalID;
326 foreach (UUID id in itemIDs)
327 {
328 item.ID = id;
329 result[i++] = GetItem(item);
330 }
331
332 return result;
333 }
334
335 /// <summary>
336 /// Get a folder, given by its UUID
337 /// </summary>
338 /// <param name="folder"></param>
339 /// <returns></returns>
340 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
341 {
342 NameValueCollection requestArgs = new NameValueCollection
343 {
344 { "RequestMethod", "GetInventoryNode" },
345 { "ItemID", folder.ID.ToString() },
346 { "OwnerID", folder.Owner.ToString() },
347 { "IncludeFolders", "1" },
348 { "IncludeItems", "0" },
349 { "ChildrenOnly", "1" }
350 };
351
352 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
353 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
354 {
355 OSDArray items = (OSDArray)response["Items"];
356 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, folder.ID, true);
357
358 if (folders.Count > 0)
359 return folders[0];
360 }
361
362 return null;
363 }
364
365 /// <summary>
366 /// Gets everything (folders and items) inside a folder
367 /// </summary>
368 /// <param name="userID"></param>
369 /// <param name="folderID"></param>
370 /// <returns></returns>
371 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
372 {
373 InventoryCollection inventory = new InventoryCollection();
374 inventory.OwnerID = userID;
375
376 NameValueCollection requestArgs = new NameValueCollection
377 {
378 { "RequestMethod", "GetInventoryNode" },
379 { "ItemID", folderID.ToString() },
380 { "OwnerID", userID.ToString() },
381 { "IncludeFolders", "1" },
382 { "IncludeItems", "1" },
383 { "ChildrenOnly", "1" }
384 };
385
386 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
387 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
388 {
389 OSDArray items = (OSDArray)response["Items"];
390
391 inventory.Folders = GetFoldersFromResponse(items, folderID, false);
392 inventory.Items = GetItemsFromResponse(items);
393 }
394 else
395 {
396 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " content for " + userID + ": " +
397 response["Message"].AsString());
398 inventory.Folders = new List<InventoryFolderBase>(0);
399 inventory.Items = new List<InventoryItemBase>(0);
400 }
401
402 return inventory;
403 }
404
405 public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
406 {
407 InventoryCollection[] invColl = new InventoryCollection[folderIDs.Length];
408 int i = 0;
409 foreach (UUID fid in folderIDs)
410 {
411 invColl[i++] = GetFolderContent(principalID, fid);
412 }
413
414 return invColl;
415 }
416
417 /// <summary>
418 /// Gets the items inside a folder
419 /// </summary>
420 /// <param name="userID"></param>
421 /// <param name="folderID"></param>
422 /// <returns></returns>
423 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
424 {
425 InventoryCollection inventory = new InventoryCollection();
426 inventory.OwnerID = userID;
427
428 NameValueCollection requestArgs = new NameValueCollection
429 {
430 { "RequestMethod", "GetInventoryNode" },
431 { "ItemID", folderID.ToString() },
432 { "OwnerID", userID.ToString() },
433 { "IncludeFolders", "0" },
434 { "IncludeItems", "1" },
435 { "ChildrenOnly", "1" }
436 };
437
438 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
439 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
440 {
441 OSDArray items = (OSDArray)response["Items"];
442 return GetItemsFromResponse(items);
443 }
444 else
445 {
446 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " for " + userID + ": " +
447 response["Message"].AsString());
448 return new List<InventoryItemBase>(0);
449 }
450 }
451
452 /// <summary>
453 /// Add a new folder to the user's inventory
454 /// </summary>
455 /// <param name="folder"></param>
456 /// <returns>true if the folder was successfully added</returns>
457 public bool AddFolder(InventoryFolderBase folder)
458 {
459 NameValueCollection requestArgs = new NameValueCollection
460 {
461 { "RequestMethod", "AddInventoryFolder" },
462 { "FolderID", folder.ID.ToString() },
463 { "ParentID", folder.ParentID.ToString() },
464 { "OwnerID", folder.Owner.ToString() },
465 { "Name", folder.Name },
466 { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
467 };
468
469 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
470 bool success = response["Success"].AsBoolean();
471
472 if (!success)
473 {
474 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating folder " + folder.Name + " for " + folder.Owner + ": " +
475 response["Message"].AsString());
476 }
477
478 return success;
479 }
480
481 /// <summary>
482 /// Update a folder in the user's inventory
483 /// </summary>
484 /// <param name="folder"></param>
485 /// <returns>true if the folder was successfully updated</returns>
486 public bool UpdateFolder(InventoryFolderBase folder)
487 {
488 return AddFolder(folder);
489 }
490
491 /// <summary>
492 /// Move an inventory folder to a new location
493 /// </summary>
494 /// <param name="folder">A folder containing the details of the new location</param>
495 /// <returns>true if the folder was successfully moved</returns>
496 public bool MoveFolder(InventoryFolderBase folder)
497 {
498 return AddFolder(folder);
499 }
500
501 /// <summary>
502 /// Delete an item from the user's inventory
503 /// </summary>
504 /// <param name="item"></param>
505 /// <returns>true if the item was successfully deleted</returns>
506 //bool DeleteItem(InventoryItemBase item);
507 public bool DeleteFolders(UUID userID, List<UUID> folderIDs)
508 {
509 return DeleteItems(userID, folderIDs);
510 }
511
512 /// <summary>
513 /// Delete an item from the user's inventory
514 /// </summary>
515 /// <param name="item"></param>
516 /// <returns>true if the item was successfully deleted</returns>
517 public bool DeleteItems(UUID userID, List<UUID> itemIDs)
518 {
519 // TODO: RemoveInventoryNode should be replaced with RemoveInventoryNodes
520 bool allSuccess = true;
521
522 for (int i = 0; i < itemIDs.Count; i++)
523 {
524 UUID itemID = itemIDs[i];
525
526 NameValueCollection requestArgs = new NameValueCollection
527 {
528 { "RequestMethod", "RemoveInventoryNode" },
529 { "OwnerID", userID.ToString() },
530 { "ItemID", itemID.ToString() }
531 };
532
533 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
534 bool success = response["Success"].AsBoolean();
535
536 if (!success)
537 {
538 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error removing item " + itemID + " for " + userID + ": " +
539 response["Message"].AsString());
540 allSuccess = false;
541 }
542 }
543
544 return allSuccess;
545 }
546
547 /// <summary>
548 /// Purge an inventory folder of all its items and subfolders.
549 /// </summary>
550 /// <param name="folder"></param>
551 /// <returns>true if the folder was successfully purged</returns>
552 public bool PurgeFolder(InventoryFolderBase folder)
553 {
554 NameValueCollection requestArgs = new NameValueCollection
555 {
556 { "RequestMethod", "PurgeInventoryFolder" },
557 { "OwnerID", folder.Owner.ToString() },
558 { "FolderID", folder.ID.ToString() }
559 };
560
561 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
562 bool success = response["Success"].AsBoolean();
563
564 if (!success)
565 {
566 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error purging folder " + folder.ID + " for " + folder.Owner + ": " +
567 response["Message"].AsString());
568 }
569
570 return success;
571 }
572
573 /// <summary>
574 /// Add a new item to the user's inventory
575 /// </summary>
576 /// <param name="item"></param>
577 /// <returns>true if the item was successfully added</returns>
578 public bool AddItem(InventoryItemBase item)
579 {
580 // A folder of UUID.Zero means we need to find the most appropriate home for this item
581 if (item.Folder == UUID.Zero)
582 {
583 InventoryFolderBase folder = null;
584 if (Enum.IsDefined(typeof(FolderType), (sbyte)item.AssetType))
585 folder = GetFolderForType(item.Owner, (FolderType)item.AssetType);
586 if (folder != null && folder.ID != UUID.Zero)
587 item.Folder = folder.ID;
588 else
589 item.Folder = item.Owner; // Root folder
590 }
591
592 if ((AssetType)item.AssetType == AssetType.Gesture)
593 UpdateGesture(item.Owner, item.ID, item.Flags == 1);
594
595 if (item.BasePermissions == 0)
596 m_log.WarnFormat("[SIMIAN INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID);
597
598 OSDMap permissions = new OSDMap
599 {
600 { "BaseMask", OSD.FromInteger(item.BasePermissions) },
601 { "EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) },
602 { "GroupMask", OSD.FromInteger(item.GroupPermissions) },
603 { "NextOwnerMask", OSD.FromInteger(item.NextPermissions) },
604 { "OwnerMask", OSD.FromInteger(item.CurrentPermissions) }
605 };
606
607 OSDMap extraData = new OSDMap()
608 {
609 { "Flags", OSD.FromInteger(item.Flags) },
610 { "GroupID", OSD.FromUUID(item.GroupID) },
611 { "GroupOwned", OSD.FromBoolean(item.GroupOwned) },
612 { "SalePrice", OSD.FromInteger(item.SalePrice) },
613 { "SaleType", OSD.FromInteger(item.SaleType) },
614 { "Permissions", permissions }
615 };
616
617 // Add different asset type only if it differs from inventory type
618 // (needed for links)
619 string invContentType = SLUtil.SLInvTypeToContentType(item.InvType);
620 string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType);
621
622 if (invContentType != assetContentType)
623 extraData["LinkedItemType"] = OSD.FromString(assetContentType);
624
625 NameValueCollection requestArgs = new NameValueCollection
626 {
627 { "RequestMethod", "AddInventoryItem" },
628 { "ItemID", item.ID.ToString() },
629 { "AssetID", item.AssetID.ToString() },
630 { "ParentID", item.Folder.ToString() },
631 { "OwnerID", item.Owner.ToString() },
632 { "Name", item.Name },
633 { "Description", item.Description },
634 { "CreatorID", item.CreatorId },
635 { "CreatorData", item.CreatorData },
636 { "ContentType", invContentType },
637 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
638 };
639
640 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
641 bool success = response["Success"].AsBoolean();
642
643 if (!success)
644 {
645 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating item " + item.Name + " for " + item.Owner + ": " +
646 response["Message"].AsString());
647 }
648
649 return success;
650 }
651
652 /// <summary>
653 /// Update an item in the user's inventory
654 /// </summary>
655 /// <param name="item"></param>
656 /// <returns>true if the item was successfully updated</returns>
657 public bool UpdateItem(InventoryItemBase item)
658 {
659 if (item.AssetID != UUID.Zero)
660 {
661 return AddItem(item);
662 }
663 else
664 {
665 // This is actually a folder update
666 InventoryFolderBase folder = new InventoryFolderBase(item.ID, item.Name, item.Owner, (short)item.AssetType, item.Folder, 0);
667 return UpdateFolder(folder);
668 }
669 }
670
671 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
672 {
673 bool success = true;
674
675 while (items.Count > 0)
676 {
677 List<InventoryItemBase> currentItems = new List<InventoryItemBase>();
678 UUID destFolderID = items[0].Folder;
679
680 // Find all of the items being moved to the current destination folder
681 for (int i = 0; i < items.Count; i++)
682 {
683 InventoryItemBase item = items[i];
684 if (item.Folder == destFolderID)
685 currentItems.Add(item);
686 }
687
688 // Do the inventory move for the current items
689 success &= MoveItems(ownerID, items, destFolderID);
690
691 // Remove the processed items from the list
692 for (int i = 0; i < currentItems.Count; i++)
693 items.Remove(currentItems[i]);
694 }
695
696 return success;
697 }
698
699 /// <summary>
700 /// Does the given user have an inventory structure?
701 /// </summary>
702 /// <param name="userID"></param>
703 /// <returns></returns>
704 public bool HasInventoryForUser(UUID userID)
705 {
706 return GetRootFolder(userID) != null;
707 }
708
709 /// <summary>
710 /// Get the active gestures of the agent.
711 /// </summary>
712 /// <param name="userID"></param>
713 /// <returns></returns>
714 public List<InventoryItemBase> GetActiveGestures(UUID userID)
715 {
716 OSDArray items = FetchGestures(userID);
717
718 string[] itemIDs = new string[items.Count];
719 for (int i = 0; i < items.Count; i++)
720 itemIDs[i] = items[i].AsUUID().ToString();
721
722// NameValueCollection requestArgs = new NameValueCollection
723// {
724// { "RequestMethod", "GetInventoryNodes" },
725// { "OwnerID", userID.ToString() },
726// { "Items", String.Join(",", itemIDs) }
727// };
728
729 // FIXME: Implement this in SimianGrid
730 return new List<InventoryItemBase>(0);
731 }
732
733 /// <summary>
734 /// Get the union of permissions of all inventory items
735 /// that hold the given assetID.
736 /// </summary>
737 /// <param name="userID"></param>
738 /// <param name="assetID"></param>
739 /// <returns>The permissions or 0 if no such asset is found in
740 /// the user's inventory</returns>
741 public int GetAssetPermissions(UUID userID, UUID assetID)
742 {
743// NameValueCollection requestArgs = new NameValueCollection
744// {
745// { "RequestMethod", "GetInventoryNodes" },
746// { "OwnerID", userID.ToString() },
747// { "AssetID", assetID.ToString() }
748// };
749
750 // FIXME: Implement this in SimianGrid
751 return (int)PermissionMask.All;
752 }
753
754 private List<InventoryFolderBase> GetFoldersFromResponse(OSDArray items, UUID baseFolder, bool includeBaseFolder)
755 {
756 List<InventoryFolderBase> invFolders = new List<InventoryFolderBase>(items.Count);
757
758 for (int i = 0; i < items.Count; i++)
759 {
760 OSDMap item = items[i] as OSDMap;
761
762 if (item != null && item["Type"].AsString() == "Folder")
763 {
764 UUID folderID = item["ID"].AsUUID();
765
766 if (folderID == baseFolder && !includeBaseFolder)
767 continue;
768
769 invFolders.Add(new InventoryFolderBase(
770 folderID,
771 item["Name"].AsString(),
772 item["OwnerID"].AsUUID(),
773 (short)SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()),
774 item["ParentID"].AsUUID(),
775 (ushort)item["Version"].AsInteger()
776 ));
777 }
778 }
779
780// m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invFolders.Count + " folders from SimianGrid response");
781 return invFolders;
782 }
783
784 private List<InventoryItemBase> GetItemsFromResponse(OSDArray items)
785 {
786 List<InventoryItemBase> invItems = new List<InventoryItemBase>(items.Count);
787
788 for (int i = 0; i < items.Count; i++)
789 {
790 OSDMap item = items[i] as OSDMap;
791
792 if (item != null && item["Type"].AsString() == "Item")
793 {
794 InventoryItemBase invItem = new InventoryItemBase();
795
796 invItem.AssetID = item["AssetID"].AsUUID();
797 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString());
798 invItem.CreationDate = item["CreationDate"].AsInteger();
799 invItem.CreatorId = item["CreatorID"].AsString();
800 invItem.CreatorData = item["CreatorData"].AsString();
801 invItem.Description = item["Description"].AsString();
802 invItem.Folder = item["ParentID"].AsUUID();
803 invItem.ID = item["ID"].AsUUID();
804 invItem.InvType = SLUtil.ContentTypeToSLInvType(item["ContentType"].AsString());
805 invItem.Name = item["Name"].AsString();
806 invItem.Owner = item["OwnerID"].AsUUID();
807
808 OSDMap extraData = item["ExtraData"] as OSDMap;
809 if (extraData != null && extraData.Count > 0)
810 {
811 invItem.Flags = extraData["Flags"].AsUInteger();
812 invItem.GroupID = extraData["GroupID"].AsUUID();
813 invItem.GroupOwned = extraData["GroupOwned"].AsBoolean();
814 invItem.SalePrice = extraData["SalePrice"].AsInteger();
815 invItem.SaleType = (byte)extraData["SaleType"].AsInteger();
816
817 OSDMap perms = extraData["Permissions"] as OSDMap;
818 if (perms != null)
819 {
820 invItem.BasePermissions = perms["BaseMask"].AsUInteger();
821 invItem.CurrentPermissions = perms["OwnerMask"].AsUInteger();
822 invItem.EveryOnePermissions = perms["EveryoneMask"].AsUInteger();
823 invItem.GroupPermissions = perms["GroupMask"].AsUInteger();
824 invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger();
825 }
826
827 if (extraData.ContainsKey("LinkedItemType"))
828 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString());
829 }
830
831 if (invItem.BasePermissions == 0)
832 {
833 m_log.InfoFormat("[SIMIAN INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})",
834 invItem.Name, invItem.ID);
835 invItem.BasePermissions = (uint)PermissionMask.All;
836 invItem.CurrentPermissions = (uint)PermissionMask.All;
837 invItem.EveryOnePermissions = (uint)PermissionMask.All;
838 invItem.GroupPermissions = (uint)PermissionMask.All;
839 invItem.NextPermissions = (uint)PermissionMask.All;
840 }
841
842 invItems.Add(invItem);
843 }
844 }
845
846// m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invItems.Count + " items from SimianGrid response");
847 return invItems;
848 }
849
850 private bool MoveItems(UUID ownerID, List<InventoryItemBase> items, UUID destFolderID)
851 {
852 string[] itemIDs = new string[items.Count];
853 for (int i = 0; i < items.Count; i++)
854 itemIDs[i] = items[i].ID.ToString();
855
856 NameValueCollection requestArgs = new NameValueCollection
857 {
858 { "RequestMethod", "MoveInventoryNodes" },
859 { "OwnerID", ownerID.ToString() },
860 { "FolderID", destFolderID.ToString() },
861 { "Items", String.Join(",", itemIDs) }
862 };
863
864 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
865 bool success = response["Success"].AsBoolean();
866
867 if (!success)
868 {
869 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to move " + items.Count + " items to " +
870 destFolderID + ": " + response["Message"].AsString());
871 }
872
873 return success;
874 }
875
876 private void UpdateGesture(UUID userID, UUID itemID, bool enabled)
877 {
878 OSDArray gestures = FetchGestures(userID);
879 OSDArray newGestures = new OSDArray();
880
881 for (int i = 0; i < gestures.Count; i++)
882 {
883 UUID gesture = gestures[i].AsUUID();
884 if (gesture != itemID)
885 newGestures.Add(OSD.FromUUID(gesture));
886 }
887
888 if (enabled)
889 newGestures.Add(OSD.FromUUID(itemID));
890
891 SaveGestures(userID, newGestures);
892 }
893
894 private OSDArray FetchGestures(UUID userID)
895 {
896 NameValueCollection requestArgs = new NameValueCollection
897 {
898 { "RequestMethod", "GetUser" },
899 { "UserID", userID.ToString() }
900 };
901
902 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
903 if (response["Success"].AsBoolean())
904 {
905 OSDMap user = response["User"] as OSDMap;
906 if (user != null && response.ContainsKey("Gestures"))
907 {
908 OSD gestures = OSDParser.DeserializeJson(response["Gestures"].AsString());
909 if (gestures != null && gestures is OSDArray)
910 return (OSDArray)gestures;
911 else
912 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID);
913 }
914 }
915 else
916 {
917 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID + ": " +
918 response["Message"].AsString());
919 }
920
921 return new OSDArray();
922 }
923
924 private void SaveGestures(UUID userID, OSDArray gestures)
925 {
926 NameValueCollection requestArgs = new NameValueCollection
927 {
928 { "RequestMethod", "AddUserData" },
929 { "UserID", userID.ToString() },
930 { "Gestures", OSDParser.SerializeJsonString(gestures) }
931 };
932
933 OSDMap response = SimianGrid.PostToService(m_userServerUrl, requestArgs);
934 if (!response["Success"].AsBoolean())
935 {
936 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " +
937 response["Message"].AsString());
938 }
939 }
940 }
941}
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}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
new file mode 100644
index 0000000..8fc766d
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
@@ -0,0 +1,478 @@
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 OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42
43namespace OpenSim.Services.Connectors.SimianGrid
44{
45 /// <summary>
46 /// Avatar profile flags
47 /// </summary>
48 [Flags]
49 public enum ProfileFlags : uint
50 {
51 AllowPublish = 1,
52 MaturePublish = 2,
53 Identified = 4,
54 Transacted = 8,
55 Online = 16
56 }
57
58 /// <summary>
59 /// Connects avatar profile and classified queries to the SimianGrid
60 /// backend
61 /// </summary>
62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianProfiles")]
63 public class SimianProfiles : INonSharedRegionModule
64 {
65 private static readonly ILog m_log =
66 LogManager.GetLogger(
67 MethodBase.GetCurrentMethod().DeclaringType);
68
69 private string m_serverUrl = String.Empty;
70 private bool m_Enabled = false;
71
72 #region INonSharedRegionModule
73
74 public Type ReplaceableInterface { get { return null; } }
75 public void RegionLoaded(Scene scene) { }
76 public void Close() { }
77
78 public SimianProfiles() { }
79 public string Name { get { return "SimianProfiles"; } }
80
81 public void AddRegion(Scene scene)
82 {
83 if (m_Enabled)
84 {
85 CheckEstateManager(scene);
86 scene.EventManager.OnClientConnect += ClientConnectHandler;
87 }
88 }
89
90 public void RemoveRegion(Scene scene)
91 {
92 if (m_Enabled)
93 {
94 scene.EventManager.OnClientConnect -= ClientConnectHandler;
95 }
96 }
97
98 #endregion INonSharedRegionModule
99
100 public SimianProfiles(IConfigSource source)
101 {
102 Initialise(source);
103 }
104
105 public void Initialise(IConfigSource source)
106 {
107 IConfig profileConfig = source.Configs["Profiles"];
108 if (profileConfig == null)
109 return;
110
111 if (profileConfig.GetString("Module", String.Empty) != Name)
112 return;
113
114 m_log.DebugFormat("[SIMIAN PROFILES] module enabled");
115 m_Enabled = true;
116
117 IConfig gridConfig = source.Configs["UserAccountService"];
118 if (gridConfig != null)
119 {
120 string serviceUrl = gridConfig.GetString("UserAccountServerURI");
121 if (!String.IsNullOrEmpty(serviceUrl))
122 {
123 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
124 serviceUrl = serviceUrl + '/';
125 m_serverUrl = serviceUrl;
126 }
127 }
128
129 if (String.IsNullOrEmpty(m_serverUrl))
130 m_log.Info("[SIMIAN PROFILES]: No UserAccountServerURI specified, disabling connector");
131 }
132
133 private void ClientConnectHandler(IClientCore clientCore)
134 {
135 if (clientCore is IClientAPI)
136 {
137 IClientAPI client = (IClientAPI)clientCore;
138
139 // Classifieds
140 client.AddGenericPacketHandler("avatarclassifiedsrequest", AvatarClassifiedsRequestHandler);
141 client.OnClassifiedInfoRequest += ClassifiedInfoRequestHandler;
142 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdateHandler;
143 client.OnClassifiedDelete += ClassifiedDeleteHandler;
144
145 // Picks
146 client.AddGenericPacketHandler("avatarpicksrequest", HandleAvatarPicksRequest);
147 client.AddGenericPacketHandler("pickinforequest", HandlePickInfoRequest);
148 client.OnPickInfoUpdate += PickInfoUpdateHandler;
149 client.OnPickDelete += PickDeleteHandler;
150
151 // Notes
152 client.AddGenericPacketHandler("avatarnotesrequest", HandleAvatarNotesRequest);
153 client.OnAvatarNotesUpdate += AvatarNotesUpdateHandler;
154
155 // Profiles
156 client.OnRequestAvatarProperties += RequestAvatarPropertiesHandler;
157
158 client.OnUpdateAvatarProperties += UpdateAvatarPropertiesHandler;
159 client.OnAvatarInterestUpdate += AvatarInterestUpdateHandler;
160 client.OnUserInfoRequest += UserInfoRequestHandler;
161 client.OnUpdateUserInfo += UpdateUserInfoHandler;
162 }
163 }
164
165 #region Classifieds
166
167 private void AvatarClassifiedsRequestHandler(Object sender, string method, List<String> args)
168 {
169 if (!(sender is IClientAPI))
170 return;
171 IClientAPI client = (IClientAPI)sender;
172
173 UUID targetAvatarID;
174 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
175 {
176 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
177 return;
178 }
179
180 // FIXME: Query the generic key/value store for classifieds
181 client.SendAvatarClassifiedReply(targetAvatarID, new Dictionary<UUID, string>(0));
182 }
183
184 private void ClassifiedInfoRequestHandler(UUID classifiedID, IClientAPI client)
185 {
186 // FIXME: Fetch this info
187 client.SendClassifiedInfoReply(classifiedID, UUID.Zero, 0, Utils.DateTimeToUnixTime(DateTime.UtcNow + TimeSpan.FromDays(1)),
188 0, String.Empty, String.Empty, UUID.Zero, 0, UUID.Zero, String.Empty, Vector3.Zero, String.Empty, 0, 0);
189 }
190
191 private void ClassifiedInfoUpdateHandler(UUID classifiedID, uint category, string name, string description,
192 UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price,
193 IClientAPI client)
194 {
195 // FIXME: Save this info
196 }
197
198 private void ClassifiedDeleteHandler(UUID classifiedID, IClientAPI client)
199 {
200 // FIXME: Delete the specified classified ad
201 }
202
203 #endregion Classifieds
204
205 #region Picks
206
207 private void HandleAvatarPicksRequest(Object sender, string method, List<String> args)
208 {
209 if (!(sender is IClientAPI))
210 return;
211 IClientAPI client = (IClientAPI)sender;
212
213 UUID targetAvatarID;
214 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
215 {
216 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
217 return;
218 }
219
220 // FIXME: Fetch these
221 client.SendAvatarPicksReply(targetAvatarID, new Dictionary<UUID, string>(0));
222 }
223
224 private void HandlePickInfoRequest(Object sender, string method, List<String> args)
225 {
226 if (!(sender is IClientAPI))
227 return;
228 IClientAPI client = (IClientAPI)sender;
229
230 UUID avatarID;
231 UUID pickID;
232 if (args.Count < 2 || !UUID.TryParse(args[0], out avatarID) || !UUID.TryParse(args[1], out pickID))
233 {
234 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
235 return;
236 }
237
238 // FIXME: Fetch this
239 client.SendPickInfoReply(pickID, avatarID, false, UUID.Zero, String.Empty, String.Empty, UUID.Zero, String.Empty,
240 String.Empty, String.Empty, Vector3.Zero, 0, false);
241 }
242
243 private void PickInfoUpdateHandler(IClientAPI client, UUID pickID, UUID creatorID, bool topPick, string name,
244 string desc, UUID snapshotID, int sortOrder, bool enabled)
245 {
246 // FIXME: Save this
247 }
248
249 private void PickDeleteHandler(IClientAPI client, UUID pickID)
250 {
251 // FIXME: Delete
252 }
253
254 #endregion Picks
255
256 #region Notes
257
258 private void HandleAvatarNotesRequest(Object sender, string method, List<String> args)
259 {
260 if (!(sender is IClientAPI))
261 return;
262 IClientAPI client = (IClientAPI)sender;
263
264 UUID targetAvatarID;
265 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
266 {
267 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
268 return;
269 }
270
271 // FIXME: Fetch this
272 client.SendAvatarNotesReply(targetAvatarID, String.Empty);
273 }
274
275 private void AvatarNotesUpdateHandler(IClientAPI client, UUID targetID, string notes)
276 {
277 // FIXME: Save this
278 }
279
280 #endregion Notes
281
282 #region Profiles
283
284 private void RequestAvatarPropertiesHandler(IClientAPI client, UUID avatarID)
285 {
286 m_log.DebugFormat("[SIMIAN PROFILES]: Request avatar properties for {0}",avatarID);
287
288 OSDMap user = FetchUserData(avatarID);
289
290 ProfileFlags flags = ProfileFlags.AllowPublish | ProfileFlags.MaturePublish;
291
292 if (user != null)
293 {
294 OSDMap about = null;
295 if (user.ContainsKey("LLAbout"))
296 {
297 try
298 {
299 about = OSDParser.DeserializeJson(user["LLAbout"].AsString()) as OSDMap;
300 }
301 catch
302 {
303 m_log.WarnFormat("[SIMIAN PROFILES]: Unable to decode LLAbout");
304 }
305 }
306
307 if (about == null)
308 about = new OSDMap(0);
309
310 // Check if this user is a grid operator
311 byte[] charterMember;
312 if (user["AccessLevel"].AsInteger() >= 200)
313 charterMember = Utils.StringToBytes("Operator");
314 else
315 charterMember = Utils.EmptyBytes;
316
317 // Check if the user is online
318 if (client.Scene is Scene)
319 {
320 OpenSim.Services.Interfaces.PresenceInfo[] presences = ((Scene)client.Scene).PresenceService.GetAgents(new string[] { avatarID.ToString() });
321 if (presences != null && presences.Length > 0)
322 flags |= ProfileFlags.Online;
323 }
324
325 // Check if the user is identified
326 if (user["Identified"].AsBoolean())
327 flags |= ProfileFlags.Identified;
328
329 client.SendAvatarProperties(avatarID, about["About"].AsString(), user["CreationDate"].AsDate().ToString("M/d/yyyy",
330 System.Globalization.CultureInfo.InvariantCulture), charterMember, about["FLAbout"].AsString(), (uint)flags,
331 about["FLImage"].AsUUID(), about["Image"].AsUUID(), about["URL"].AsString(), user["Partner"].AsUUID());
332
333 OSDMap interests = null;
334 if (user.ContainsKey("LLInterests"))
335 {
336 try
337 {
338 interests = OSDParser.DeserializeJson(user["LLInterests"].AsString()) as OSDMap;
339 client.SendAvatarInterestsReply(avatarID, interests["WantMask"].AsUInteger(), interests["WantText"].AsString(), interests["SkillsMask"].AsUInteger(), interests["SkillsText"].AsString(), interests["Languages"].AsString());
340 }
341 catch { }
342 }
343
344 if (about == null)
345 about = new OSDMap(0);
346 }
347 else
348 {
349 m_log.Warn("[SIMIAN PROFILES]: Failed to fetch profile information for " + client.Name + ", returning default values");
350 client.SendAvatarProperties(avatarID, String.Empty, "1/1/1970", Utils.EmptyBytes,
351 String.Empty, (uint)flags, UUID.Zero, UUID.Zero, String.Empty, UUID.Zero);
352 }
353 }
354
355 private void UpdateAvatarPropertiesHandler(IClientAPI client, UserProfileData profileData)
356 {
357 OSDMap map = new OSDMap
358 {
359 { "About", OSD.FromString(profileData.AboutText) },
360 { "Image", OSD.FromUUID(profileData.Image) },
361 { "FLAbout", OSD.FromString(profileData.FirstLifeAboutText) },
362 { "FLImage", OSD.FromUUID(profileData.FirstLifeImage) },
363 { "URL", OSD.FromString(profileData.ProfileUrl) }
364 };
365
366 AddUserData(client.AgentId, "LLAbout", map);
367 }
368
369 private void AvatarInterestUpdateHandler(IClientAPI client, uint wantmask, string wanttext, uint skillsmask,
370 string skillstext, string languages)
371 {
372 OSDMap map = new OSDMap
373 {
374 { "WantMask", OSD.FromInteger(wantmask) },
375 { "WantText", OSD.FromString(wanttext) },
376 { "SkillsMask", OSD.FromInteger(skillsmask) },
377 { "SkillsText", OSD.FromString(skillstext) },
378 { "Languages", OSD.FromString(languages) }
379 };
380
381 AddUserData(client.AgentId, "LLInterests", map);
382 }
383
384 private void UserInfoRequestHandler(IClientAPI client)
385 {
386 m_log.Error("[SIMIAN PROFILES]: UserInfoRequestHandler");
387
388 // Fetch this user's e-mail address
389 NameValueCollection requestArgs = new NameValueCollection
390 {
391 { "RequestMethod", "GetUser" },
392 { "UserID", client.AgentId.ToString() }
393 };
394
395 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
396 string email = response["Email"].AsString();
397
398 if (!response["Success"].AsBoolean())
399 m_log.Warn("[SIMIAN PROFILES]: GetUser failed during a user info request for " + client.Name);
400
401 client.SendUserInfoReply(false, true, email);
402 }
403
404 private void UpdateUserInfoHandler(bool imViaEmail, bool visible, IClientAPI client)
405 {
406 m_log.Info("[SIMIAN PROFILES]: Ignoring user info update from " + client.Name);
407 }
408
409 #endregion Profiles
410
411 /// <summary>
412 /// Sanity checks regions for a valid estate owner at startup
413 /// </summary>
414 private void CheckEstateManager(Scene scene)
415 {
416 EstateSettings estate = scene.RegionInfo.EstateSettings;
417
418 if (estate.EstateOwner == UUID.Zero)
419 {
420 // Attempt to lookup the grid admin
421 UserAccount admin = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, UUID.Zero);
422 if (admin != null)
423 {
424 m_log.InfoFormat("[SIMIAN PROFILES]: Setting estate {0} (ID: {1}) owner to {2}", estate.EstateName,
425 estate.EstateID, admin.Name);
426
427 estate.EstateOwner = admin.PrincipalID;
428 scene.EstateDataService.StoreEstateSettings(estate);
429 }
430 else
431 {
432 m_log.WarnFormat("[SIMIAN PROFILES]: Estate {0} (ID: {1}) does not have an owner", estate.EstateName, estate.EstateID);
433 }
434 }
435 }
436
437 private bool AddUserData(UUID userID, string key, OSDMap value)
438 {
439 NameValueCollection requestArgs = new NameValueCollection
440 {
441 { "RequestMethod", "AddUserData" },
442 { "UserID", userID.ToString() },
443 { key, OSDParser.SerializeJsonString(value) }
444 };
445
446 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
447 bool success = response["Success"].AsBoolean();
448
449 if (!success)
450 m_log.WarnFormat("[SIMIAN PROFILES]: Failed to add user data with key {0} for {1}: {2}", key, userID, response["Message"].AsString());
451
452 return success;
453 }
454
455 private OSDMap FetchUserData(UUID userID)
456 {
457 m_log.DebugFormat("[SIMIAN PROFILES]: Fetch information about {0}",userID);
458
459 NameValueCollection requestArgs = new NameValueCollection
460 {
461 { "RequestMethod", "GetUser" },
462 { "UserID", userID.ToString() }
463 };
464
465 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
466 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
467 {
468 return (OSDMap)response["User"];
469 }
470 else
471 {
472 m_log.Error("[SIMIAN PROFILES]: Failed to fetch user data for " + userID + ": " + response["Message"].AsString());
473 }
474
475 return null;
476 }
477 }
478}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
new file mode 100644
index 0000000..698c4c0
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -0,0 +1,337 @@
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 OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces;
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42namespace OpenSim.Services.Connectors.SimianGrid
43{
44 /// <summary>
45 /// Connects user account data (creating new users, looking up existing
46 /// users) to the SimianGrid backend
47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianUserAccountServiceConnector")]
49 public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule
50 {
51 private const double CACHE_EXPIRATION_SECONDS = 120.0;
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 ExpiringCache<UUID, UserAccount> m_accountCache = new ExpiringCache<UUID,UserAccount>();
59 private bool m_Enabled;
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 SimianUserAccountServiceConnector() { }
69 public string Name { get { return "SimianUserAccountServiceConnector"; } }
70 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IUserAccountService>(this); } }
71 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IUserAccountService>(this); } }
72
73 #endregion ISharedRegionModule
74
75 public SimianUserAccountServiceConnector(IConfigSource source)
76 {
77 CommonInit(source);
78 }
79
80 public void Initialise(IConfigSource source)
81 {
82 IConfig moduleConfig = source.Configs["Modules"];
83 if (moduleConfig != null)
84 {
85 string name = moduleConfig.GetString("UserAccountServices", "");
86 if (name == Name)
87 CommonInit(source);
88 }
89 }
90
91 private void CommonInit(IConfigSource source)
92 {
93 IConfig gridConfig = source.Configs["UserAccountService"];
94 if (gridConfig != null)
95 {
96 string serviceUrl = gridConfig.GetString("UserAccountServerURI");
97 if (!String.IsNullOrEmpty(serviceUrl))
98 {
99 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
100 serviceUrl = serviceUrl + '/';
101 m_serverUrl = serviceUrl;
102 m_Enabled = true;
103 }
104 }
105
106 if (String.IsNullOrEmpty(m_serverUrl))
107 m_log.Info("[SIMIAN ACCOUNT CONNECTOR]: No UserAccountServerURI specified, disabling connector");
108 }
109
110 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
111 {
112 NameValueCollection requestArgs = new NameValueCollection
113 {
114 { "RequestMethod", "GetUser" },
115 { "Name", firstName + ' ' + lastName }
116 };
117
118 return GetUser(requestArgs);
119 }
120
121 public UserAccount GetUserAccount(UUID scopeID, string email)
122 {
123 NameValueCollection requestArgs = new NameValueCollection
124 {
125 { "RequestMethod", "GetUser" },
126 { "Email", email }
127 };
128
129 return GetUser(requestArgs);
130 }
131
132 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
133 {
134 // Cache check
135 UserAccount account;
136 if (m_accountCache.TryGetValue(userID, out account))
137 return account;
138
139 NameValueCollection requestArgs = new NameValueCollection
140 {
141 { "RequestMethod", "GetUser" },
142 { "UserID", userID.ToString() }
143 };
144
145 account = GetUser(requestArgs);
146
147 if (account == null)
148 {
149 // Store null responses too, to avoid repeated lookups for missing accounts
150 m_accountCache.AddOrUpdate(userID, null, CACHE_EXPIRATION_SECONDS);
151 }
152
153 return account;
154 }
155
156 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
157 {
158 List<UserAccount> accounts = new List<UserAccount>();
159
160// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Searching for user accounts with name query " + query);
161
162 NameValueCollection requestArgs = new NameValueCollection
163 {
164 { "RequestMethod", "GetUsers" },
165 { "NameQuery", query }
166 };
167
168 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
169 if (response["Success"].AsBoolean())
170 {
171 OSDArray array = response["Users"] as OSDArray;
172 if (array != null && array.Count > 0)
173 {
174 for (int i = 0; i < array.Count; i++)
175 {
176 UserAccount account = ResponseToUserAccount(array[i] as OSDMap);
177 if (account != null)
178 accounts.Add(account);
179 }
180 }
181 else
182 {
183 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format");
184 }
185 }
186 else
187 {
188 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to search for account data by name " + query);
189 }
190
191 return accounts;
192 }
193
194 public void InvalidateCache(UUID userID)
195 {
196 m_accountCache.Remove(userID);
197 }
198
199 public bool StoreUserAccount(UserAccount data)
200 {
201// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name);
202
203 NameValueCollection requestArgs = new NameValueCollection
204 {
205 { "RequestMethod", "AddUser" },
206 { "UserID", data.PrincipalID.ToString() },
207 { "Name", data.Name },
208 { "Email", data.Email },
209 { "AccessLevel", data.UserLevel.ToString() }
210 };
211
212 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
213
214 if (response["Success"].AsBoolean())
215 {
216 m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account data for " + data.Name);
217
218 requestArgs = new NameValueCollection
219 {
220 { "RequestMethod", "AddUserData" },
221 { "UserID", data.PrincipalID.ToString() },
222 { "CreationDate", data.Created.ToString() },
223 { "UserFlags", data.UserFlags.ToString() },
224 { "UserTitle", data.UserTitle }
225 };
226
227 response = SimianGrid.PostToService(m_serverUrl, requestArgs);
228 bool success = response["Success"].AsBoolean();
229
230 if (success)
231 {
232 // Cache the user account info
233 m_accountCache.AddOrUpdate(data.PrincipalID, data, CACHE_EXPIRATION_SECONDS);
234 }
235 else
236 {
237 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to store user account data for " + data.Name + ": " + response["Message"].AsString());
238 }
239
240 return success;
241 }
242 else
243 {
244 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to store user account for " + data.Name + ": " + response["Message"].AsString());
245 }
246
247 return false;
248 }
249
250 /// <summary>
251 /// Helper method for the various ways of retrieving a user account
252 /// </summary>
253 /// <param name="requestArgs">Service query parameters</param>
254 /// <returns>A UserAccount object on success, null on failure</returns>
255 private UserAccount GetUser(NameValueCollection requestArgs)
256 {
257 string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)";
258// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue);
259
260 OSDMap response = SimianGrid.PostToService(m_serverUrl, requestArgs);
261 if (response["Success"].AsBoolean())
262 {
263 OSDMap user = response["User"] as OSDMap;
264 if (user != null)
265 return ResponseToUserAccount(user);
266 else
267 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format");
268 }
269 else
270 {
271 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to lookup user account with query: " + lookupValue);
272 }
273
274 return null;
275 }
276
277 /// <summary>
278 /// Convert a User object in LLSD format to a UserAccount
279 /// </summary>
280 /// <param name="response">LLSD containing user account data</param>
281 /// <returns>A UserAccount object on success, null on failure</returns>
282 private UserAccount ResponseToUserAccount(OSDMap response)
283 {
284 if (response == null)
285 return null;
286
287 UserAccount account = new UserAccount();
288 account.PrincipalID = response["UserID"].AsUUID();
289 account.Created = response["CreationDate"].AsInteger();
290 account.Email = response["Email"].AsString();
291 account.ServiceURLs = new Dictionary<string, object>(0);
292 account.UserFlags = response["UserFlags"].AsInteger();
293 account.UserLevel = response["AccessLevel"].AsInteger();
294 account.UserTitle = response["UserTitle"].AsString();
295 account.LocalToGrid = true;
296 if (response.ContainsKey("LocalToGrid"))
297 account.LocalToGrid = (response["LocalToGrid"].AsString() == "true" ? true : false);
298
299 GetFirstLastName(response["Name"].AsString(), out account.FirstName, out account.LastName);
300
301 // Cache the user account info
302 m_accountCache.AddOrUpdate(account.PrincipalID, account, CACHE_EXPIRATION_SECONDS);
303
304 return account;
305 }
306
307 /// <summary>
308 /// Convert a name with a single space in it to a first and last name
309 /// </summary>
310 /// <param name="name">A full name such as "John Doe"</param>
311 /// <param name="firstName">First name</param>
312 /// <param name="lastName">Last name (surname)</param>
313 private static void GetFirstLastName(string name, out string firstName, out string lastName)
314 {
315 if (String.IsNullOrEmpty(name))
316 {
317 firstName = String.Empty;
318 lastName = String.Empty;
319 }
320 else
321 {
322 string[] names = name.Split(' ');
323
324 if (names.Length == 2)
325 {
326 firstName = names[0];
327 lastName = names[1];
328 }
329 else
330 {
331 firstName = String.Empty;
332 lastName = name;
333 }
334 }
335 }
336 }
337} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
new file mode 100644
index 0000000..1eedbef
--- /dev/null
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -0,0 +1,482 @@
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.IO;
31using System.Net;
32using System.Reflection;
33using System.Text;
34using System.Collections;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Services.Connectors.Simulation
46{
47 public class SimulationServiceConnector : ISimulationService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 // we use this dictionary to track the pending updateagent requests, maps URI --> position update
52 private Dictionary<string,AgentPosition> m_updateAgentQueue = new Dictionary<string,AgentPosition>();
53
54 //private GridRegion m_Region;
55
56 public SimulationServiceConnector()
57 {
58 }
59
60 public SimulationServiceConnector(IConfigSource config)
61 {
62 //m_Region = region;
63 }
64
65 public IScene GetScene(UUID regionId)
66 {
67 return null;
68 }
69
70 public ISimulationService GetInnerService()
71 {
72 return null;
73 }
74
75 #region Agents
76
77 protected virtual string AgentPath()
78 {
79 return "agent/";
80 }
81
82 protected virtual void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags)
83 {
84 if (source != null)
85 {
86 args["source_x"] = OSD.FromString(source.RegionLocX.ToString());
87 args["source_y"] = OSD.FromString(source.RegionLocY.ToString());
88 args["source_name"] = OSD.FromString(source.RegionName);
89 args["source_uuid"] = OSD.FromString(source.RegionID.ToString());
90 if (!String.IsNullOrEmpty(source.RawServerURI))
91 args["source_server_uri"] = OSD.FromString(source.RawServerURI);
92 }
93
94 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
95 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
96 args["destination_name"] = OSD.FromString(destination.RegionName);
97 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
98 args["teleport_flags"] = OSD.FromString(flags.ToString());
99 }
100
101 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
102 {
103 string tmp = String.Empty;
104 return CreateAgent(source, destination, aCircuit, flags, out tmp, out reason);
105 }
106
107 public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
108 {
109 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: Creating agent at {0}", destination.ServerURI);
110 reason = String.Empty;
111 myipaddress = String.Empty;
112
113 if (destination == null)
114 {
115 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null");
116 return false;
117 }
118
119 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
120
121 try
122 {
123 OSDMap args = aCircuit.PackAgentCircuitData();
124 PackData(args, source, aCircuit, destination, flags);
125
126 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
127 bool success = result["success"].AsBoolean();
128 if (success && result.ContainsKey("_Result"))
129 {
130 OSDMap data = (OSDMap)result["_Result"];
131
132 reason = data["reason"].AsString();
133 success = data["success"].AsBoolean();
134 myipaddress = data["your_ip"].AsString();
135 return success;
136 }
137
138 // Try the old version, uncompressed
139 result = WebUtil.PostToService(uri, args, 30000, false);
140
141 if (result["Success"].AsBoolean())
142 {
143 if (result.ContainsKey("_Result"))
144 {
145 OSDMap data = (OSDMap)result["_Result"];
146
147 reason = data["reason"].AsString();
148 success = data["success"].AsBoolean();
149 myipaddress = data["your_ip"].AsString();
150 m_log.WarnFormat(
151 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
152 return success;
153 }
154 }
155
156 m_log.WarnFormat(
157 "[REMOTE SIMULATION CONNECTOR]: Failed to create agent {0} {1} at remote simulator {2}",
158 aCircuit.firstname, aCircuit.lastname, destination.RegionName);
159 reason = result["Message"] != null ? result["Message"].AsString() : "error";
160 return false;
161 }
162 catch (Exception e)
163 {
164 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
165 reason = e.Message;
166 }
167
168 return false;
169 }
170
171 /// <summary>
172 /// Send complete data about an agent in this region to a neighbor
173 /// </summary>
174 public bool UpdateAgent(GridRegion destination, AgentData data)
175 {
176 return UpdateAgent(destination, (IAgentData)data, 200000); // yes, 200 seconds
177 }
178
179 private ExpiringCache<string, bool> _failedSims = new ExpiringCache<string, bool>();
180 /// <summary>
181 /// Send updated position information about an agent in this region to a neighbor
182 /// This operation may be called very frequently if an avatar is moving about in
183 /// the region.
184 /// </summary>
185 public bool UpdateAgent(GridRegion destination, AgentPosition data)
186 {
187 bool v = true;
188 if (_failedSims.TryGetValue(destination.ServerURI, out v))
189 return false;
190
191 // The basic idea of this code is that the first thread that needs to
192 // send an update for a specific avatar becomes the worker for any subsequent
193 // requests until there are no more outstanding requests. Further, only send the most
194 // recent update; this *should* never be needed but some requests get
195 // slowed down and once that happens the problem with service end point
196 // limits kicks in and nothing proceeds
197 string uri = destination.ServerURI + AgentPath() + data.AgentID + "/";
198 lock (m_updateAgentQueue)
199 {
200 if (m_updateAgentQueue.ContainsKey(uri))
201 {
202 // Another thread is already handling
203 // updates for this simulator, just update
204 // the position and return, overwrites are
205 // not a problem since we only care about the
206 // last update anyway
207 m_updateAgentQueue[uri] = data;
208 return true;
209 }
210
211 // Otherwise update the reference and start processing
212 m_updateAgentQueue[uri] = data;
213 }
214
215 AgentPosition pos = null;
216 bool success = true;
217 while (success)
218 {
219 lock (m_updateAgentQueue)
220 {
221 // save the position
222 AgentPosition lastpos = pos;
223
224 pos = m_updateAgentQueue[uri];
225
226 // this is true if no one put a new
227 // update in the map since the last
228 // one we processed, if thats the
229 // case then we are done
230 if (pos == lastpos)
231 {
232 m_updateAgentQueue.Remove(uri);
233 return true;
234 }
235 }
236
237 success = UpdateAgent(destination, (IAgentData)pos, 10000);
238 }
239 // we get here iff success == false
240 // blacklist sim for 2 minutes
241 lock (m_updateAgentQueue)
242 {
243 _failedSims.AddOrUpdate(destination.ServerURI, true, 120);
244 m_updateAgentQueue.Remove(uri);
245 }
246 return false;
247 }
248
249 /// <summary>
250 /// This is the worker function to send AgentData to a neighbor region
251 /// </summary>
252 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
253 {
254 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent in {0}", destination.ServerURI);
255
256 // Eventually, we want to use a caps url instead of the agentID
257 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
258
259 try
260 {
261 OSDMap args = cAgentData.Pack();
262
263 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
264 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
265 args["destination_name"] = OSD.FromString(destination.RegionName);
266 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
267
268 OSDMap result = WebUtil.PutToServiceCompressed(uri, args, timeout);
269 if (result["Success"].AsBoolean())
270 return true;
271
272 result = WebUtil.PutToService(uri, args, timeout);
273
274 return result["Success"].AsBoolean();
275 }
276 catch (Exception e)
277 {
278 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: UpdateAgent failed with exception: " + e.ToString());
279 }
280
281 return false;
282 }
283
284
285 public bool QueryAccess(GridRegion destination, UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, string myversion, List<UUID> featuresAvailable, out string version, out string reason)
286 {
287 reason = "Failed to contact destination";
288 version = "Unknown";
289
290 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position);
291
292 IPEndPoint ext = destination.ExternalEndPoint;
293 if (ext == null) return false;
294
295 // Eventually, we want to use a caps url instead of the agentID
296 string uri = destination.ServerURI + AgentPath() + agentID + "/" + destination.RegionID.ToString() + "/";
297
298 OSDMap request = new OSDMap();
299 request.Add("viaTeleport", OSD.FromBoolean(viaTeleport));
300 request.Add("position", OSD.FromString(position.ToString()));
301 request.Add("my_version", OSD.FromString(myversion));
302
303 OSDArray features = new OSDArray();
304 foreach (UUID feature in featuresAvailable)
305 features.Add(OSD.FromString(feature.ToString()));
306
307 request.Add("features", features);
308
309 if (agentHomeURI != null)
310 request.Add("agent_home_uri", OSD.FromString(agentHomeURI));
311
312 try
313 {
314 OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 30000, false, false);
315 bool success = result["success"].AsBoolean();
316 if (result.ContainsKey("_Result"))
317 {
318 OSDMap data = (OSDMap)result["_Result"];
319
320 // FIXME: If there is a _Result map then it's the success key here that indicates the true success
321 // or failure, not the sibling result node.
322 success = data["success"];
323
324 reason = data["reason"].AsString();
325 if (data["version"] != null && data["version"].AsString() != string.Empty)
326 version = data["version"].AsString();
327
328 m_log.DebugFormat(
329 "[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1}, reason {2}, version {3} ({4})",
330 uri, success, reason, version, data["version"].AsString());
331 }
332
333 if (!success)
334 {
335 // If we don't check this then OpenSimulator 0.7.3.1 and some period before will never see the
336 // actual failure message
337 if (!result.ContainsKey("_Result"))
338 {
339 if (result.ContainsKey("Message"))
340 {
341 string message = result["Message"].AsString();
342 if (message == "Service request failed: [MethodNotAllowed] MethodNotAllowed") // Old style region
343 {
344 m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored");
345 return true;
346 }
347
348 reason = result["Message"];
349 }
350 else
351 {
352 reason = "Communications failure";
353 }
354 }
355
356 return false;
357 }
358
359
360 featuresAvailable.Clear();
361
362 if (result.ContainsKey("features"))
363 {
364 OSDArray array = (OSDArray)result["features"];
365
366 foreach (OSD o in array)
367 featuresAvailable.Add(new UUID(o.AsString()));
368 }
369
370 return success;
371 }
372 catch (Exception e)
373 {
374 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] QueryAcesss failed with exception; {0}",e.ToString());
375 }
376
377 return false;
378 }
379
380 /// <summary>
381 /// </summary>
382 public bool ReleaseAgent(UUID origin, UUID id, string uri)
383 {
384 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: ReleaseAgent start");
385
386 try
387 {
388 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false, false);
389 }
390 catch (Exception e)
391 {
392 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] ReleaseAgent failed with exception; {0}",e.ToString());
393 }
394
395 return true;
396 }
397
398 /// <summary>
399 /// </summary>
400 public bool CloseAgent(GridRegion destination, UUID id, string auth_code)
401 {
402 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/?auth=" + auth_code;
403 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent {0}", uri);
404
405 try
406 {
407 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false, false);
408 }
409 catch (Exception e)
410 {
411 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CloseAgent failed with exception; {0}",e.ToString());
412 }
413
414 return true;
415 }
416
417 #endregion Agents
418
419 #region Objects
420
421 protected virtual string ObjectPath()
422 {
423 return "object/";
424 }
425
426 /// <summary>
427 ///
428 /// </summary>
429 public bool CreateObject(GridRegion destination, Vector3 newPosition, ISceneObject sog, bool isLocalCall)
430 {
431 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateObject start");
432
433 string uri = destination.ServerURI + ObjectPath() + sog.UUID + "/";
434
435 try
436 {
437 OSDMap args = new OSDMap(2);
438
439 args["sog"] = OSD.FromString(sog.ToXml2());
440 args["extra"] = OSD.FromString(sog.ExtraToXmlString());
441 args["modified"] = OSD.FromBoolean(sog.HasGroupChanged);
442 args["new_position"] = newPosition.ToString();
443
444 string state = sog.GetStateSnapshot();
445 if (state.Length > 0)
446 args["state"] = OSD.FromString(state);
447
448 // Add the input general arguments
449 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
450 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
451 args["destination_name"] = OSD.FromString(destination.RegionName);
452 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
453
454 OSDMap result = WebUtil.PostToService(uri, args, 40000, false);
455
456 if (result == null)
457 return false;
458 bool success = result["success"].AsBoolean();
459 if (!success)
460 return false;
461 }
462 catch (Exception e)
463 {
464 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CreateObject failed with exception; {0}",e.ToString());
465 return false;
466 }
467
468 return true;
469 }
470
471 /// <summary>
472 ///
473 /// </summary>
474 public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
475 {
476 // TODO, not that urgent
477 return false;
478 }
479
480 #endregion Objects
481 }
482}
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
new file mode 100644
index 0000000..560e6c4
--- /dev/null
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServicesConnector.cs
@@ -0,0 +1,328 @@
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 log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Framework.ServiceAuth;
37using OpenSim.Server.Base;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors
42{
43 public class UserAccountServicesConnector : BaseServiceConnector, IUserAccountService
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private string m_ServerURI = String.Empty;
50
51 public UserAccountServicesConnector()
52 {
53 }
54
55 public UserAccountServicesConnector(string serverURI)
56 {
57 m_ServerURI = serverURI.TrimEnd('/');
58 }
59
60 public UserAccountServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig assetConfig = source.Configs["UserAccountService"];
68 if (assetConfig == null)
69 {
70 m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini");
71 throw new Exception("User account connector init error");
72 }
73
74 string serviceURI = assetConfig.GetString("UserAccountServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[ACCOUNT CONNECTOR]: No Server URI named in section UserAccountService");
80 throw new Exception("User account connector init error");
81 }
82 m_ServerURI = serviceURI;
83
84 base.Initialise(source, "UserAccountService");
85 }
86
87 public virtual UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
88 {
89 Dictionary<string, object> sendData = new Dictionary<string, object>();
90 //sendData["SCOPEID"] = scopeID.ToString();
91 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
92 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
93 sendData["METHOD"] = "getaccount";
94
95 sendData["ScopeID"] = scopeID;
96 sendData["FirstName"] = firstName.ToString();
97 sendData["LastName"] = lastName.ToString();
98
99 return SendAndGetReply(sendData);
100 }
101
102 public virtual UserAccount GetUserAccount(UUID scopeID, string email)
103 {
104 Dictionary<string, object> sendData = new Dictionary<string, object>();
105 //sendData["SCOPEID"] = scopeID.ToString();
106 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
107 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
108 sendData["METHOD"] = "getaccount";
109
110 sendData["ScopeID"] = scopeID;
111 sendData["Email"] = email;
112
113 return SendAndGetReply(sendData);
114 }
115
116 public virtual UserAccount GetUserAccount(UUID scopeID, UUID userID)
117 {
118 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccount {0}", userID);
119 Dictionary<string, object> sendData = new Dictionary<string, object>();
120 //sendData["SCOPEID"] = scopeID.ToString();
121 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
122 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
123 sendData["METHOD"] = "getaccount";
124
125 sendData["ScopeID"] = scopeID;
126 sendData["UserID"] = userID.ToString();
127
128 return SendAndGetReply(sendData);
129 }
130
131 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
132 {
133 Dictionary<string, object> sendData = new Dictionary<string, object>();
134 //sendData["SCOPEID"] = scopeID.ToString();
135 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
136 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
137 sendData["METHOD"] = "getaccounts";
138
139 sendData["ScopeID"] = scopeID.ToString();
140 sendData["query"] = query;
141
142 string reply = string.Empty;
143 string reqString = ServerUtils.BuildQueryString(sendData);
144 string uri = m_ServerURI + "/accounts";
145 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
146 try
147 {
148 reply = SynchronousRestFormsRequester.MakeRequest("POST",
149 uri,
150 reqString,
151 m_Auth);
152 if (reply == null || (reply != null && reply == string.Empty))
153 {
154 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccounts received null or empty reply");
155 return null;
156 }
157 }
158 catch (Exception e)
159 {
160 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user accounts server at {0}: {1}", uri, e.Message);
161 }
162
163 List<UserAccount> accounts = new List<UserAccount>();
164
165 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
166
167 if (replyData != null)
168 {
169 if (replyData.ContainsKey("result") && replyData["result"].ToString() == "null")
170 {
171 return accounts;
172 }
173
174 Dictionary<string, object>.ValueCollection accountList = replyData.Values;
175 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
176 foreach (object acc in accountList)
177 {
178 if (acc is Dictionary<string, object>)
179 {
180 UserAccount pinfo = new UserAccount((Dictionary<string, object>)acc);
181 accounts.Add(pinfo);
182 }
183 else
184 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccounts received invalid response type {0}",
185 acc.GetType());
186 }
187 }
188 else
189 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccounts received null response");
190
191 return accounts;
192 }
193
194 public void InvalidateCache(UUID userID)
195 {
196 }
197
198 public virtual bool StoreUserAccount(UserAccount data)
199 {
200 Dictionary<string, object> sendData = new Dictionary<string, object>();
201 //sendData["SCOPEID"] = scopeID.ToString();
202 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
203 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
204 sendData["METHOD"] = "setaccount";
205
206 Dictionary<string, object> structData = data.ToKeyValuePairs();
207
208 foreach (KeyValuePair<string, object> kvp in structData)
209 {
210 if (kvp.Value == null)
211 {
212 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Null value for {0}", kvp.Key);
213 continue;
214 }
215 sendData[kvp.Key] = kvp.Value.ToString();
216 }
217
218 if (SendAndGetReply(sendData) != null)
219 return true;
220 else
221 return false;
222 }
223
224 /// <summary>
225 /// Create user remotely. Note this this is not part of the IUserAccountsService
226 /// </summary>
227 /// <param name="first"></param>
228 /// <param name="last"></param>
229 /// <param name="password"></param>
230 /// <param name="email"></param>
231 /// <param name="scopeID"></param>
232 /// <returns></returns>
233 public virtual UserAccount CreateUser(string first, string last, string password, string email, UUID scopeID)
234 {
235 Dictionary<string, object> sendData = new Dictionary<string, object>();
236 //sendData["SCOPEID"] = scopeID.ToString();
237 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
238 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
239 sendData["METHOD"] = "createuser";
240
241 sendData["FirstName"] = first;
242 sendData["LastName"] = last;
243 sendData["Password"] = password;
244 if (!string.IsNullOrEmpty(email))
245 sendData["Email"] = first;
246 sendData["ScopeID"] = scopeID.ToString();
247
248 return SendAndGetReply(sendData);
249 }
250
251 private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
252 {
253 string reply = string.Empty;
254 string reqString = ServerUtils.BuildQueryString(sendData);
255 string uri = m_ServerURI + "/accounts";
256 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
257 try
258 {
259 reply = SynchronousRestFormsRequester.MakeRequest("POST",
260 uri,
261 reqString,
262 m_Auth);
263 if (reply == null || (reply != null && reply == string.Empty))
264 {
265 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccount received null or empty reply");
266 return null;
267 }
268 }
269 catch (Exception e)
270 {
271 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user accounts server at {0}: {1}", uri, e.Message);
272 }
273
274 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
275 UserAccount account = null;
276
277 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
278 {
279 if (replyData["result"] is Dictionary<string, object>)
280 {
281 account = new UserAccount((Dictionary<string, object>)replyData["result"]);
282 }
283 }
284
285 return account;
286
287 }
288
289 private bool SendAndGetBoolReply(Dictionary<string, object> sendData)
290 {
291 string reqString = ServerUtils.BuildQueryString(sendData);
292 string uri = m_ServerURI + "/accounts";
293 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
294 try
295 {
296 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
297 uri,
298 reqString,
299 m_Auth);
300 if (reply != string.Empty)
301 {
302 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: reply = {0}", reply);
303 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
304
305 if (replyData.ContainsKey("result"))
306 {
307 if (replyData["result"].ToString().ToLower() == "success")
308 return true;
309 else
310 return false;
311 }
312 else
313 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount reply data does not contain result field");
314
315 }
316 else
317 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount received empty reply");
318 }
319 catch (Exception e)
320 {
321 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user accounts server at {0}: {1}", uri, e.Message);
322 }
323
324 return false;
325 }
326
327 }
328}