aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
diff options
context:
space:
mode:
authorDiva Canto2015-01-06 21:24:44 -0800
committerDiva Canto2015-01-06 21:24:44 -0800
commit8e562f04d1576bd51138ac656f796ba18965fdcf (patch)
treec06dce809cb04c971ac545e9793d885ea555e611 /OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC-8e562f04d1576bd51138ac656f796ba18965fdcf.zip
opensim-SC-8e562f04d1576bd51138ac656f796ba18965fdcf.tar.gz
opensim-SC-8e562f04d1576bd51138ac656f796ba18965fdcf.tar.bz2
opensim-SC-8e562f04d1576bd51138ac656f796ba18965fdcf.tar.xz
Donation of robust network connectors for estate service, as promised. This allows to have one central database for estates without having to open the MySql port. This is off by default, so not to disturb everyone's existing installations. To use it, see GridCommon.ini.example [EstateDataStore] section and Robust*.ini.example's new additions.
Note that I also made things consistent by removing both the EstateDataService and the SimulationService into their own dlls, just like all other services. They really didn't belong in Services.Connectors, since everything in that component is about network connectors to robust backends. We may have too many dlls, and at some point it might not be a bad idea to merge all services into one single dll, since they all have more or less the same dependencies.
Diffstat (limited to '')
-rw-r--r--OpenSim/Services/Connectors/Estate/EstateDataConnector.cs340
1 files changed, 340 insertions, 0 deletions
diff --git a/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
new file mode 100644
index 0000000..9d01b47
--- /dev/null
+++ b/OpenSim/Services/Connectors/Estate/EstateDataConnector.cs
@@ -0,0 +1,340 @@
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.Service.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 string reply = string.Empty;
252 // /estates/estate/
253 string uri = m_ServerURI + ("/estates/estate");
254
255 Dictionary<string, object> formdata = es.ToMap();
256 formdata["OP"] = "STORE";
257
258 PostRequest(uri, formdata);
259 }
260
261 public bool LinkRegion(UUID regionID, int estateID)
262 {
263 string reply = string.Empty;
264 // /estates/estate/?eid=int&region=uuid
265 string uri = m_ServerURI + String.Format("/estates/estate/?eid={0}&region={1}", estateID, regionID);
266
267 Dictionary<string, object> formdata = new Dictionary<string, object>();
268 formdata["OP"] = "LINK";
269 return PostRequest(uri, formdata);
270 }
271
272 private bool PostRequest(string uri, Dictionary<string, object> sendData)
273 {
274 string reqString = ServerUtils.BuildQueryString(sendData);
275
276 string reply = MakeRequest("POST", uri, reqString);
277 if (String.IsNullOrEmpty(reply))
278 return false;
279
280 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
281
282 bool result = false;
283 if (replyData != null && replyData.Count > 0)
284 {
285 if (replyData.ContainsKey("Result"))
286 {
287 if (Boolean.TryParse(replyData["Result"].ToString(), out result))
288 m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} returned {1}", uri, result);
289 }
290 }
291 else
292 m_log.DebugFormat("[ESTATE CONNECTOR]: PostRequest {0} received null or zero response", uri);
293
294 return result;
295 }
296
297 /// <summary>
298 /// Forbidden operation
299 /// </summary>
300 /// <returns></returns>
301 public bool DeleteEstate(int estateID)
302 {
303 return false;
304 }
305
306 #endregion
307
308 private string MakeRequest(string verb, string uri, string formdata)
309 {
310 string reply = string.Empty;
311 try
312 {
313 reply = SynchronousRestFormsRequester.MakeRequest(verb, uri, formdata, m_Auth);
314 }
315 catch (WebException e)
316 {
317 using (HttpWebResponse hwr = (HttpWebResponse)e.Response)
318 {
319 if (hwr != null)
320 {
321 if (hwr.StatusCode == HttpStatusCode.NotFound)
322 m_log.Error(string.Format("[ESTATE CONNECTOR]: Resource {0} not found ", uri));
323 if (hwr.StatusCode == HttpStatusCode.Unauthorized)
324 m_log.Error(string.Format("[ESTATE CONNECTOR]: Web request {0} requires authentication ", uri));
325 }
326 else
327 m_log.Error(string.Format(
328 "[ESTATE CONNECTOR]: WebException for {0} {1} {2} ",
329 verb, uri, formdata, e));
330 }
331 }
332 catch (Exception e)
333 {
334 m_log.DebugFormat("[ESTATE CONNECTOR]: Exception when contacting estate server at {0}: {1}", uri, e.Message);
335 }
336
337 return reply;
338 }
339 }
340}