diff options
Refactored the GridServer into a GridDBService and a set of "modules".
Currently they aren't plugin modules as the support for dynamically loading them isn't complete.
Diffstat (limited to 'OpenSim/Grid/GridServer/GridManager.cs')
-rw-r--r-- | OpenSim/Grid/GridServer/GridManager.cs | 1282 |
1 files changed, 0 insertions, 1282 deletions
diff --git a/OpenSim/Grid/GridServer/GridManager.cs b/OpenSim/Grid/GridServer/GridManager.cs deleted file mode 100644 index 5dc186c..0000000 --- a/OpenSim/Grid/GridServer/GridManager.cs +++ /dev/null | |||
@@ -1,1282 +0,0 @@ | |||
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 OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Reflection; | ||
33 | using System.Xml; | ||
34 | using log4net; | ||
35 | using Nwc.XmlRpc; | ||
36 | using OpenMetaverse; | ||
37 | using OpenSim.Data; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Communications; | ||
40 | using OpenSim.Framework.Servers; | ||
41 | |||
42 | namespace OpenSim.Grid.GridServer | ||
43 | { | ||
44 | public class GridManager | ||
45 | { | ||
46 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
47 | |||
48 | private List<IGridDataPlugin> _plugins = new List<IGridDataPlugin>(); | ||
49 | private List<ILogDataPlugin> _logplugins = new List<ILogDataPlugin>(); | ||
50 | |||
51 | // This is here so that the grid server can hand out MessageServer settings to regions on registration | ||
52 | private List<MessageServerInfo> _MessageServers = new List<MessageServerInfo>(); | ||
53 | |||
54 | public GridConfig Config; | ||
55 | |||
56 | /// <value> | ||
57 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
58 | /// </value> | ||
59 | private string m_opensimVersion; | ||
60 | |||
61 | /// <summary> | ||
62 | /// Constructor | ||
63 | /// </summary> | ||
64 | /// <param name="opensimVersion"> | ||
65 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
66 | /// </param> | ||
67 | public GridManager(string opensimVersion) | ||
68 | { | ||
69 | m_opensimVersion = opensimVersion; | ||
70 | } | ||
71 | |||
72 | /// <summary> | ||
73 | /// Adds a list of grid and log data plugins, as described by | ||
74 | /// `provider' and `connect', to `_plugins' and `_logplugins', | ||
75 | /// respectively. | ||
76 | /// </summary> | ||
77 | /// <param name="provider"> | ||
78 | /// The filename of the inventory server plugin DLL. | ||
79 | /// </param> | ||
80 | /// <param name="connect"> | ||
81 | /// The connection string for the storage backend. | ||
82 | /// </param> | ||
83 | public void AddPlugin(string provider, string connect) | ||
84 | { | ||
85 | _plugins = DataPluginFactory.LoadDataPlugins<IGridDataPlugin>(provider, connect); | ||
86 | _logplugins = DataPluginFactory.LoadDataPlugins<ILogDataPlugin>(provider, connect); | ||
87 | } | ||
88 | |||
89 | /// <summary> | ||
90 | /// Logs a piece of information to the database | ||
91 | /// </summary> | ||
92 | /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param> | ||
93 | /// <param name="method">Which method is being called?</param> | ||
94 | /// <param name="args">What arguments are being passed?</param> | ||
95 | /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param> | ||
96 | /// <param name="message">The message to log</param> | ||
97 | private void logToDB(string target, string method, string args, int priority, string message) | ||
98 | { | ||
99 | foreach (ILogDataPlugin plugin in _logplugins) | ||
100 | { | ||
101 | try | ||
102 | { | ||
103 | plugin.saveLog("Gridserver", target, method, args, priority, message); | ||
104 | } | ||
105 | catch (Exception) | ||
106 | { | ||
107 | m_log.Warn("[storage]: Unable to write log via " + plugin.Name); | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | /// <summary> | ||
113 | /// Returns a region by argument | ||
114 | /// </summary> | ||
115 | /// <param name="uuid">A UUID key of the region to return</param> | ||
116 | /// <returns>A SimProfileData for the region</returns> | ||
117 | public RegionProfileData GetRegion(UUID uuid) | ||
118 | { | ||
119 | foreach (IGridDataPlugin plugin in _plugins) | ||
120 | { | ||
121 | try | ||
122 | { | ||
123 | return plugin.GetProfileByUUID(uuid); | ||
124 | } | ||
125 | catch (Exception e) | ||
126 | { | ||
127 | m_log.Warn("[storage]: GetRegion - " + e.Message); | ||
128 | } | ||
129 | } | ||
130 | return null; | ||
131 | } | ||
132 | |||
133 | /// <summary> | ||
134 | /// Returns a region by argument | ||
135 | /// </summary> | ||
136 | /// <param name="uuid">A regionHandle of the region to return</param> | ||
137 | /// <returns>A SimProfileData for the region</returns> | ||
138 | public RegionProfileData GetRegion(ulong handle) | ||
139 | { | ||
140 | foreach (IGridDataPlugin plugin in _plugins) | ||
141 | { | ||
142 | try | ||
143 | { | ||
144 | return plugin.GetProfileByHandle(handle); | ||
145 | } | ||
146 | catch (Exception ex) | ||
147 | { | ||
148 | m_log.Debug("[storage]: " + ex.Message); | ||
149 | m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + plugin.Name); | ||
150 | } | ||
151 | } | ||
152 | return null; | ||
153 | } | ||
154 | |||
155 | /// <summary> | ||
156 | /// Returns a region by argument | ||
157 | /// </summary> | ||
158 | /// <param name="regionName">A partial regionName of the region to return</param> | ||
159 | /// <returns>A SimProfileData for the region</returns> | ||
160 | public RegionProfileData GetRegion(string regionName) | ||
161 | { | ||
162 | foreach (IGridDataPlugin plugin in _plugins) | ||
163 | { | ||
164 | try | ||
165 | { | ||
166 | return plugin.GetProfileByString(regionName); | ||
167 | } | ||
168 | catch | ||
169 | { | ||
170 | m_log.Warn("[storage]: Unable to find region " + regionName + " via " + plugin.Name); | ||
171 | } | ||
172 | } | ||
173 | return null; | ||
174 | } | ||
175 | |||
176 | public List<RegionProfileData> GetRegions(uint xmin, uint ymin, uint xmax, uint ymax) | ||
177 | { | ||
178 | List<RegionProfileData> regions = new List<RegionProfileData>(); | ||
179 | |||
180 | foreach (IGridDataPlugin plugin in _plugins) | ||
181 | { | ||
182 | try | ||
183 | { | ||
184 | regions.AddRange(plugin.GetProfilesInRange(xmin, ymin, xmax, ymax)); | ||
185 | } | ||
186 | catch | ||
187 | { | ||
188 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | ||
189 | } | ||
190 | } | ||
191 | |||
192 | return regions; | ||
193 | } | ||
194 | |||
195 | public List<RegionProfileData> GetRegions(string name, int maxNum) | ||
196 | { | ||
197 | List<RegionProfileData> regions = new List<RegionProfileData>(); | ||
198 | foreach (IGridDataPlugin plugin in _plugins) | ||
199 | { | ||
200 | try | ||
201 | { | ||
202 | int num = maxNum - regions.Count; | ||
203 | List <RegionProfileData> profiles = plugin.GetRegionsByName(name, (uint)num); | ||
204 | if (profiles != null) regions.AddRange(profiles); | ||
205 | } | ||
206 | catch | ||
207 | { | ||
208 | m_log.Warn("[storage]: Unable to query regionblock via " + plugin.Name); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | return regions; | ||
213 | } | ||
214 | |||
215 | /// <summary> | ||
216 | /// Returns a XML String containing a list of the neighbouring regions | ||
217 | /// </summary> | ||
218 | /// <param name="reqhandle">The regionhandle for the center sim</param> | ||
219 | /// <returns>An XML string containing neighbour entities</returns> | ||
220 | public string GetXMLNeighbours(ulong reqhandle) | ||
221 | { | ||
222 | string response = String.Empty; | ||
223 | RegionProfileData central_region = GetRegion(reqhandle); | ||
224 | RegionProfileData neighbour; | ||
225 | for (int x = -1; x < 2; x++) | ||
226 | { | ||
227 | for (int y = -1; y < 2; y++) | ||
228 | { | ||
229 | if ( | ||
230 | GetRegion( | ||
231 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | ||
232 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) | ||
233 | { | ||
234 | neighbour = | ||
235 | GetRegion( | ||
236 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | ||
237 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)); | ||
238 | |||
239 | response += "<neighbour>"; | ||
240 | response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>"; | ||
241 | response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>"; | ||
242 | response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>"; | ||
243 | response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>"; | ||
244 | response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>"; | ||
245 | response += "</neighbour>"; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | return response; | ||
250 | } | ||
251 | |||
252 | /// <summary> | ||
253 | /// Checks that it's valid to replace the existing region data with new data | ||
254 | /// | ||
255 | /// Currently, this means ensure that the keys passed in by the new region | ||
256 | /// match those in the original region. (XXX Is this correct? Shouldn't we simply check | ||
257 | /// against the keys in the current configuration?) | ||
258 | /// </summary> | ||
259 | /// <param name="sim"></param> | ||
260 | /// <returns></returns> | ||
261 | protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) | ||
262 | { | ||
263 | if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) | ||
264 | { | ||
265 | throw new LoginException( | ||
266 | String.Format( | ||
267 | "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" | ||
268 | + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", | ||
269 | sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, | ||
270 | sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), | ||
271 | "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | /// <summary> | ||
276 | /// Checks that the new region data is valid. | ||
277 | /// | ||
278 | /// Currently, this means checking that the keys passed in by the new region | ||
279 | /// match those in the grid server's configuration. | ||
280 | /// </summary> | ||
281 | /// | ||
282 | /// <param name="sim"></param> | ||
283 | /// <exception cref="LoginException">Thrown if region login failed</exception> | ||
284 | protected virtual void ValidateNewRegionKeys(RegionProfileData sim) | ||
285 | { | ||
286 | if (!(sim.regionRecvKey == Config.SimSendKey && sim.regionSendKey == Config.SimRecvKey)) | ||
287 | { | ||
288 | throw new LoginException( | ||
289 | String.Format( | ||
290 | "Authentication failed when trying to login new region {0} at location {1} {2}" | ||
291 | + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", | ||
292 | sim.regionName, sim.regionLocX, sim.regionLocY, | ||
293 | sim.regionSendKey, Config.SimRecvKey, sim.regionRecvKey, Config.SimSendKey), | ||
294 | "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /// <summary> | ||
299 | /// Check that a region's http uri is externally contactable. | ||
300 | /// </summary> | ||
301 | /// <param name="sim"></param> | ||
302 | /// <exception cref="LoginException">Thrown if the region is not contactable</exception> | ||
303 | protected virtual void ValidateRegionContactable(RegionProfileData sim) | ||
304 | { | ||
305 | string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); | ||
306 | string regionStatusResponse; | ||
307 | |||
308 | RestClient rc = new RestClient(regionStatusUrl); | ||
309 | rc.RequestMethod = "GET"; | ||
310 | |||
311 | m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); | ||
312 | |||
313 | try | ||
314 | { | ||
315 | Stream rs = rc.Request(); | ||
316 | StreamReader sr = new StreamReader(rs); | ||
317 | regionStatusResponse = sr.ReadToEnd(); | ||
318 | sr.Close(); | ||
319 | } | ||
320 | catch (Exception e) | ||
321 | { | ||
322 | throw new LoginException( | ||
323 | String.Format("Region status request to {0} failed", regionStatusUrl), | ||
324 | String.Format( | ||
325 | "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", | ||
326 | regionStatusUrl), | ||
327 | e); | ||
328 | } | ||
329 | |||
330 | if (!regionStatusResponse.Equals("OK")) | ||
331 | { | ||
332 | throw new LoginException( | ||
333 | String.Format( | ||
334 | "Region {0} at {1} returned status response {2} rather than {3}", | ||
335 | sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), | ||
336 | String.Format( | ||
337 | "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", | ||
338 | regionStatusResponse, "OK")); | ||
339 | } | ||
340 | } | ||
341 | |||
342 | /// <summary> | ||
343 | /// Construct an XMLRPC error response | ||
344 | /// </summary> | ||
345 | /// <param name="error"></param> | ||
346 | /// <returns></returns> | ||
347 | public static XmlRpcResponse ErrorResponse(string error) | ||
348 | { | ||
349 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | ||
350 | Hashtable errorResponseData = new Hashtable(); | ||
351 | errorResponse.Value = errorResponseData; | ||
352 | errorResponseData["error"] = error; | ||
353 | return errorResponse; | ||
354 | } | ||
355 | |||
356 | /// <summary> | ||
357 | /// Performed when a region connects to the grid server initially. | ||
358 | /// </summary> | ||
359 | /// <param name="request">The XML RPC Request</param> | ||
360 | /// <returns>Startup parameters</returns> | ||
361 | public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request) | ||
362 | { | ||
363 | RegionProfileData sim; | ||
364 | RegionProfileData existingSim; | ||
365 | |||
366 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
367 | UUID uuid; | ||
368 | |||
369 | if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) | ||
370 | { | ||
371 | m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); | ||
372 | return ErrorResponse("No UUID passed to grid server - unable to connect you"); | ||
373 | } | ||
374 | |||
375 | try | ||
376 | { | ||
377 | sim = RegionFromRequest(requestData); | ||
378 | } | ||
379 | catch (FormatException e) | ||
380 | { | ||
381 | m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); | ||
382 | return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); | ||
383 | } | ||
384 | |||
385 | m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); | ||
386 | |||
387 | if (!Config.AllowRegionRegistration) | ||
388 | { | ||
389 | m_log.DebugFormat( | ||
390 | "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", | ||
391 | sim.regionName); | ||
392 | |||
393 | return ErrorResponse("This grid is currently not accepting region registrations."); | ||
394 | } | ||
395 | |||
396 | int majorInterfaceVersion = 0; | ||
397 | if (requestData.ContainsKey("major_interface_version")) | ||
398 | int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); | ||
399 | |||
400 | if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) | ||
401 | { | ||
402 | return ErrorResponse( | ||
403 | String.Format( | ||
404 | "Your region service implements OGS1 interface version {0}" | ||
405 | + " but this grid requires that the region implement OGS1 interface version {1} to connect." | ||
406 | + " Try changing to OpenSimulator {2}", | ||
407 | majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); | ||
408 | } | ||
409 | |||
410 | existingSim = GetRegion(sim.regionHandle); | ||
411 | |||
412 | if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) | ||
413 | { | ||
414 | try | ||
415 | { | ||
416 | if (existingSim == null) | ||
417 | { | ||
418 | ValidateNewRegionKeys(sim); | ||
419 | } | ||
420 | else | ||
421 | { | ||
422 | ValidateOverwriteKeys(sim, existingSim); | ||
423 | } | ||
424 | |||
425 | ValidateRegionContactable(sim); | ||
426 | } | ||
427 | catch (LoginException e) | ||
428 | { | ||
429 | string logMsg = e.Message; | ||
430 | if (e.InnerException != null) | ||
431 | logMsg += ", " + e.InnerException.Message; | ||
432 | |||
433 | m_log.WarnFormat("[LOGIN END]: {0}", logMsg); | ||
434 | |||
435 | return e.XmlRpcErrorResponse; | ||
436 | } | ||
437 | |||
438 | foreach (IGridDataPlugin plugin in _plugins) | ||
439 | { | ||
440 | try | ||
441 | { | ||
442 | DataResponse insertResponse; | ||
443 | |||
444 | if (existingSim == null) | ||
445 | { | ||
446 | insertResponse = plugin.AddProfile(sim); | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | insertResponse = plugin.UpdateProfile(sim); | ||
451 | } | ||
452 | |||
453 | switch (insertResponse) | ||
454 | { | ||
455 | case DataResponse.RESPONSE_OK: | ||
456 | m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); | ||
457 | break; | ||
458 | case DataResponse.RESPONSE_ERROR: | ||
459 | m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); | ||
460 | break; | ||
461 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | ||
462 | m_log.Warn("[LOGIN END]: " + | ||
463 | "Sim login failed (Invalid Credentials): " + sim.regionName); | ||
464 | break; | ||
465 | case DataResponse.RESPONSE_AUTHREQUIRED: | ||
466 | m_log.Warn("[LOGIN END]: " + | ||
467 | "Sim login failed (Authentication Required): " + | ||
468 | sim.regionName); | ||
469 | break; | ||
470 | } | ||
471 | } | ||
472 | catch (Exception e) | ||
473 | { | ||
474 | m_log.Warn("[LOGIN END]: " + | ||
475 | "Unable to login region " + sim.ToString() + " via " + plugin.Name); | ||
476 | m_log.Warn("[LOGIN END]: " + e.ToString()); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | XmlRpcResponse response = CreateLoginResponse(sim); | ||
481 | |||
482 | return response; | ||
483 | } | ||
484 | else | ||
485 | { | ||
486 | m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); | ||
487 | return ErrorResponse("Another region already exists at that location. Please try another."); | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /// <summary> | ||
492 | /// Construct a successful response to a simulator's login attempt. | ||
493 | /// </summary> | ||
494 | /// <param name="sim"></param> | ||
495 | /// <returns></returns> | ||
496 | private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) | ||
497 | { | ||
498 | XmlRpcResponse response = new XmlRpcResponse(); | ||
499 | Hashtable responseData = new Hashtable(); | ||
500 | response.Value = responseData; | ||
501 | |||
502 | ArrayList SimNeighboursData = GetSimNeighboursData(sim); | ||
503 | |||
504 | responseData["UUID"] = sim.UUID.ToString(); | ||
505 | responseData["region_locx"] = sim.regionLocX.ToString(); | ||
506 | responseData["region_locy"] = sim.regionLocY.ToString(); | ||
507 | responseData["regionname"] = sim.regionName; | ||
508 | responseData["estate_id"] = "1"; | ||
509 | responseData["neighbours"] = SimNeighboursData; | ||
510 | |||
511 | responseData["sim_ip"] = sim.serverIP; | ||
512 | responseData["sim_port"] = sim.serverPort.ToString(); | ||
513 | responseData["asset_url"] = sim.regionAssetURI; | ||
514 | responseData["asset_sendkey"] = sim.regionAssetSendKey; | ||
515 | responseData["asset_recvkey"] = sim.regionAssetRecvKey; | ||
516 | responseData["user_url"] = sim.regionUserURI; | ||
517 | responseData["user_sendkey"] = sim.regionUserSendKey; | ||
518 | responseData["user_recvkey"] = sim.regionUserRecvKey; | ||
519 | responseData["authkey"] = sim.regionSecret; | ||
520 | |||
521 | // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) | ||
522 | responseData["data_uri"] = sim.regionDataURI; | ||
523 | |||
524 | responseData["allow_forceful_banlines"] = Config.AllowForcefulBanlines; | ||
525 | |||
526 | // Instead of sending a multitude of message servers to the registering sim | ||
527 | // we should probably be sending a single one and parhaps it's backup | ||
528 | // that has responsibility over routing it's messages. | ||
529 | |||
530 | // The Sim won't be contacting us again about any of the message server stuff during it's time up. | ||
531 | |||
532 | responseData["messageserver_count"] = _MessageServers.Count; | ||
533 | |||
534 | for (int i = 0; i < _MessageServers.Count; i++) | ||
535 | { | ||
536 | responseData["messageserver_uri" + i] = _MessageServers[i].URI; | ||
537 | responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey; | ||
538 | responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey; | ||
539 | } | ||
540 | return response; | ||
541 | } | ||
542 | |||
543 | private ArrayList GetSimNeighboursData(RegionProfileData sim) | ||
544 | { | ||
545 | ArrayList SimNeighboursData = new ArrayList(); | ||
546 | |||
547 | RegionProfileData neighbour; | ||
548 | Hashtable NeighbourBlock; | ||
549 | |||
550 | //First use the fast method. (not implemented in SQLLite) | ||
551 | List<RegionProfileData> neighbours = GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); | ||
552 | |||
553 | if (neighbours.Count > 0) | ||
554 | { | ||
555 | foreach (RegionProfileData aSim in neighbours) | ||
556 | { | ||
557 | NeighbourBlock = new Hashtable(); | ||
558 | NeighbourBlock["sim_ip"] = aSim.serverIP; | ||
559 | NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); | ||
560 | NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); | ||
561 | NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); | ||
562 | NeighbourBlock["UUID"] = aSim.ToString(); | ||
563 | NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); | ||
564 | |||
565 | if (aSim.UUID != sim.UUID) | ||
566 | { | ||
567 | SimNeighboursData.Add(NeighbourBlock); | ||
568 | } | ||
569 | } | ||
570 | } | ||
571 | else | ||
572 | { | ||
573 | for (int x = -1; x < 2; x++) | ||
574 | { | ||
575 | for (int y = -1; y < 2; y++) | ||
576 | { | ||
577 | if ( | ||
578 | GetRegion( | ||
579 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | ||
580 | (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) | ||
581 | { | ||
582 | neighbour = | ||
583 | GetRegion( | ||
584 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | ||
585 | (uint)(sim.regionLocY + y) * Constants.RegionSize)); | ||
586 | |||
587 | NeighbourBlock = new Hashtable(); | ||
588 | NeighbourBlock["sim_ip"] = neighbour.serverIP; | ||
589 | NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); | ||
590 | NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); | ||
591 | NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); | ||
592 | NeighbourBlock["UUID"] = neighbour.UUID.ToString(); | ||
593 | NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); | ||
594 | |||
595 | if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); | ||
596 | } | ||
597 | } | ||
598 | } | ||
599 | } | ||
600 | return SimNeighboursData; | ||
601 | } | ||
602 | |||
603 | /// <summary> | ||
604 | /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region | ||
605 | /// </summary> | ||
606 | /// <param name="requestData"></param> | ||
607 | /// <returns></returns> | ||
608 | private RegionProfileData RegionFromRequest(Hashtable requestData) | ||
609 | { | ||
610 | RegionProfileData sim; | ||
611 | sim = new RegionProfileData(); | ||
612 | |||
613 | sim.UUID = new UUID((string)requestData["UUID"]); | ||
614 | sim.originUUID = new UUID((string)requestData["originUUID"]); | ||
615 | |||
616 | sim.regionRecvKey = String.Empty; | ||
617 | sim.regionSendKey = String.Empty; | ||
618 | |||
619 | if (requestData.ContainsKey("region_secret")) | ||
620 | { | ||
621 | string regionsecret = (string)requestData["region_secret"]; | ||
622 | if (regionsecret.Length > 0) | ||
623 | sim.regionSecret = regionsecret; | ||
624 | else | ||
625 | sim.regionSecret = Config.SimRecvKey; | ||
626 | |||
627 | } | ||
628 | else | ||
629 | { | ||
630 | sim.regionSecret = Config.SimRecvKey; | ||
631 | } | ||
632 | |||
633 | sim.regionDataURI = String.Empty; | ||
634 | sim.regionAssetURI = Config.DefaultAssetServer; | ||
635 | sim.regionAssetRecvKey = Config.AssetRecvKey; | ||
636 | sim.regionAssetSendKey = Config.AssetSendKey; | ||
637 | sim.regionUserURI = Config.DefaultUserServer; | ||
638 | sim.regionUserSendKey = Config.UserSendKey; | ||
639 | sim.regionUserRecvKey = Config.UserRecvKey; | ||
640 | |||
641 | sim.serverIP = (string)requestData["sim_ip"]; | ||
642 | sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); | ||
643 | sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); | ||
644 | sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); | ||
645 | sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); | ||
646 | sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); | ||
647 | sim.regionLocZ = 0; | ||
648 | |||
649 | UUID textureID; | ||
650 | if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) | ||
651 | { | ||
652 | sim.regionMapTextureID = textureID; | ||
653 | } | ||
654 | |||
655 | // part of an initial brutish effort to provide accurate information (as per the xml region spec) | ||
656 | // wrt the ownership of a given region | ||
657 | // the (very bad) assumption is that this value is being read and handled inconsistently or | ||
658 | // not at all. Current strategy is to put the code in place to support the validity of this information | ||
659 | // and to roll forward debugging any issues from that point | ||
660 | // | ||
661 | // this particular section of the mod attempts to receive a value from the region's xml file by way of | ||
662 | // OSG1GridServices for the region's owner | ||
663 | sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; | ||
664 | |||
665 | try | ||
666 | { | ||
667 | sim.regionRecvKey = (string)requestData["recvkey"]; | ||
668 | sim.regionSendKey = (string)requestData["authkey"]; | ||
669 | } | ||
670 | catch (KeyNotFoundException) { } | ||
671 | |||
672 | sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); | ||
673 | sim.serverURI = (string)requestData["server_uri"]; | ||
674 | |||
675 | sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; | ||
676 | |||
677 | sim.regionName = (string)requestData["sim_name"]; | ||
678 | return sim; | ||
679 | } | ||
680 | |||
681 | /// <summary> | ||
682 | /// Returns an XML RPC response to a simulator profile request | ||
683 | /// Performed after moving a region. | ||
684 | /// </summary> | ||
685 | /// <param name="request"></param> | ||
686 | /// <returns></returns> | ||
687 | /// <param name="request">The XMLRPC Request</param> | ||
688 | /// <returns>Processing parameters</returns> | ||
689 | public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request) | ||
690 | { | ||
691 | XmlRpcResponse response = new XmlRpcResponse(); | ||
692 | Hashtable responseData = new Hashtable(); | ||
693 | response.Value = responseData; | ||
694 | |||
695 | //RegionProfileData TheSim = null; | ||
696 | string uuid; | ||
697 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
698 | |||
699 | if (requestData.ContainsKey("UUID")) | ||
700 | { | ||
701 | //TheSim = GetRegion(new UUID((string) requestData["UUID"])); | ||
702 | uuid = requestData["UUID"].ToString(); | ||
703 | m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); | ||
704 | // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); | ||
705 | } | ||
706 | else | ||
707 | { | ||
708 | responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; | ||
709 | return response; | ||
710 | } | ||
711 | |||
712 | foreach (IGridDataPlugin plugin in _plugins) | ||
713 | { | ||
714 | //OpenSim.Data.MySQL.MySQLGridData dbengine = new OpenSim.Data.MySQL.MySQLGridData(); | ||
715 | try | ||
716 | { | ||
717 | //Nice are we not using multiple databases? | ||
718 | //MySQLGridData mysqldata = (MySQLGridData)(plugin); | ||
719 | |||
720 | //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim); | ||
721 | DataResponse insertResponse = plugin.DeleteProfile(uuid); | ||
722 | |||
723 | switch (insertResponse) | ||
724 | { | ||
725 | case DataResponse.RESPONSE_OK: | ||
726 | //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); | ||
727 | responseData["status"] = "Deleting region successful: " + uuid; | ||
728 | break; | ||
729 | case DataResponse.RESPONSE_ERROR: | ||
730 | //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); | ||
731 | responseData["status"] = "Deleting region failed (Error): " + uuid; | ||
732 | break; | ||
733 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | ||
734 | //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); | ||
735 | responseData["status"] = "Deleting region (Invalid Credentials): " + uuid; | ||
736 | break; | ||
737 | case DataResponse.RESPONSE_AUTHREQUIRED: | ||
738 | //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); | ||
739 | responseData["status"] = "Deleting region (Authentication Required): " + uuid; | ||
740 | break; | ||
741 | } | ||
742 | } | ||
743 | catch (Exception) | ||
744 | { | ||
745 | m_log.Error("storage Unable to delete region " + uuid + " via " + plugin.Name); | ||
746 | //MainLog.Instance.Warn("storage", e.ToString()); | ||
747 | } | ||
748 | } | ||
749 | |||
750 | return response; | ||
751 | } | ||
752 | |||
753 | /// <summary> | ||
754 | /// Returns an XML RPC response to a simulator profile request | ||
755 | /// </summary> | ||
756 | /// <param name="request"></param> | ||
757 | /// <returns></returns> | ||
758 | public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request) | ||
759 | { | ||
760 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
761 | Hashtable responseData = new Hashtable(); | ||
762 | RegionProfileData simData = null; | ||
763 | if (requestData.ContainsKey("region_UUID")) | ||
764 | { | ||
765 | UUID regionID = new UUID((string)requestData["region_UUID"]); | ||
766 | simData = GetRegion(regionID); | ||
767 | if (simData == null) | ||
768 | { | ||
769 | m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", | ||
770 | regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
771 | } | ||
772 | } | ||
773 | else if (requestData.ContainsKey("region_handle")) | ||
774 | { | ||
775 | //CFK: The if/else below this makes this message redundant. | ||
776 | //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]); | ||
777 | ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); | ||
778 | simData = GetRegion(regionHandle); | ||
779 | if (simData == null) | ||
780 | { | ||
781 | m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", | ||
782 | regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
783 | } | ||
784 | } | ||
785 | else if (requestData.ContainsKey("region_name_search")) | ||
786 | { | ||
787 | string regionName = (string)requestData["region_name_search"]; | ||
788 | simData = GetRegion(regionName); | ||
789 | if (simData == null) | ||
790 | { | ||
791 | m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", | ||
792 | regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
793 | } | ||
794 | } | ||
795 | else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); | ||
796 | |||
797 | if (simData == null) | ||
798 | { | ||
799 | //Sim does not exist | ||
800 | responseData["error"] = "Sim does not exist"; | ||
801 | } | ||
802 | else | ||
803 | { | ||
804 | m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + | ||
805 | (string)requestData["region_handle"]); | ||
806 | responseData["sim_ip"] = simData.serverIP; | ||
807 | responseData["sim_port"] = simData.serverPort.ToString(); | ||
808 | responseData["server_uri"] = simData.serverURI; | ||
809 | responseData["http_port"] = simData.httpPort.ToString(); | ||
810 | responseData["remoting_port"] = simData.remotingPort.ToString(); | ||
811 | responseData["region_locx"] = simData.regionLocX.ToString(); | ||
812 | responseData["region_locy"] = simData.regionLocY.ToString(); | ||
813 | responseData["region_UUID"] = simData.UUID.Guid.ToString(); | ||
814 | responseData["region_name"] = simData.regionName; | ||
815 | responseData["regionHandle"] = simData.regionHandle.ToString(); | ||
816 | } | ||
817 | |||
818 | XmlRpcResponse response = new XmlRpcResponse(); | ||
819 | response.Value = responseData; | ||
820 | return response; | ||
821 | } | ||
822 | |||
823 | public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request) | ||
824 | { | ||
825 | int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; | ||
826 | |||
827 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
828 | if (requestData.ContainsKey("xmin")) | ||
829 | { | ||
830 | xmin = (Int32)requestData["xmin"]; | ||
831 | } | ||
832 | if (requestData.ContainsKey("ymin")) | ||
833 | { | ||
834 | ymin = (Int32)requestData["ymin"]; | ||
835 | } | ||
836 | if (requestData.ContainsKey("xmax")) | ||
837 | { | ||
838 | xmax = (Int32)requestData["xmax"]; | ||
839 | } | ||
840 | if (requestData.ContainsKey("ymax")) | ||
841 | { | ||
842 | ymax = (Int32)requestData["ymax"]; | ||
843 | } | ||
844 | //CFK: The second log is more meaningful and either standard or fast generally occurs. | ||
845 | //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
846 | |||
847 | XmlRpcResponse response = new XmlRpcResponse(); | ||
848 | Hashtable responseData = new Hashtable(); | ||
849 | response.Value = responseData; | ||
850 | IList simProfileList = new ArrayList(); | ||
851 | |||
852 | bool fastMode = (Config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || Config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); | ||
853 | |||
854 | if (fastMode) | ||
855 | { | ||
856 | List<RegionProfileData> neighbours = GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); | ||
857 | |||
858 | foreach (RegionProfileData aSim in neighbours) | ||
859 | { | ||
860 | Hashtable simProfileBlock = new Hashtable(); | ||
861 | simProfileBlock["x"] = aSim.regionLocX.ToString(); | ||
862 | simProfileBlock["y"] = aSim.regionLocY.ToString(); | ||
863 | //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); | ||
864 | simProfileBlock["name"] = aSim.regionName; | ||
865 | simProfileBlock["access"] = 21; | ||
866 | simProfileBlock["region-flags"] = 512; | ||
867 | simProfileBlock["water-height"] = 0; | ||
868 | simProfileBlock["agents"] = 1; | ||
869 | simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); | ||
870 | |||
871 | // For Sugilite compatibility | ||
872 | simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); | ||
873 | simProfileBlock["sim_ip"] = aSim.serverIP; | ||
874 | simProfileBlock["sim_port"] = aSim.serverPort.ToString(); | ||
875 | simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); | ||
876 | simProfileBlock["uuid"] = aSim.UUID.ToString(); | ||
877 | simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); | ||
878 | simProfileBlock["http_port"] = aSim.httpPort.ToString(); | ||
879 | |||
880 | simProfileList.Add(simProfileBlock); | ||
881 | } | ||
882 | m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + | ||
883 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
884 | } | ||
885 | else | ||
886 | { | ||
887 | RegionProfileData simProfile; | ||
888 | for (int x = xmin; x < xmax + 1; x++) | ||
889 | { | ||
890 | for (int y = ymin; y < ymax + 1; y++) | ||
891 | { | ||
892 | ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); | ||
893 | simProfile = GetRegion(regHandle); | ||
894 | if (simProfile != null) | ||
895 | { | ||
896 | Hashtable simProfileBlock = new Hashtable(); | ||
897 | simProfileBlock["x"] = x; | ||
898 | simProfileBlock["y"] = y; | ||
899 | simProfileBlock["name"] = simProfile.regionName; | ||
900 | simProfileBlock["access"] = 0; | ||
901 | simProfileBlock["region-flags"] = 0; | ||
902 | simProfileBlock["water-height"] = 20; | ||
903 | simProfileBlock["agents"] = 1; | ||
904 | simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); | ||
905 | |||
906 | // For Sugilite compatibility | ||
907 | simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); | ||
908 | simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); | ||
909 | simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); | ||
910 | simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); | ||
911 | simProfileBlock["uuid"] = simProfile.UUID.ToString(); | ||
912 | simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); | ||
913 | simProfileBlock["http_port"] = simProfile.httpPort; | ||
914 | |||
915 | simProfileList.Add(simProfileBlock); | ||
916 | } | ||
917 | } | ||
918 | } | ||
919 | m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + | ||
920 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
921 | } | ||
922 | |||
923 | responseData["sim-profiles"] = simProfileList; | ||
924 | |||
925 | return response; | ||
926 | } | ||
927 | |||
928 | /// <summary> | ||
929 | /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code> | ||
930 | /// </summary> | ||
931 | /// <param name="request"></param> | ||
932 | /// <returns></returns> | ||
933 | public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request) | ||
934 | { | ||
935 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
936 | |||
937 | if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) | ||
938 | { | ||
939 | m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); | ||
940 | return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); | ||
941 | } | ||
942 | |||
943 | Hashtable responseData = new Hashtable(); | ||
944 | |||
945 | string name = (string)requestData["name"]; | ||
946 | int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); | ||
947 | if (maxNumber == 0 || name.Length < 3) | ||
948 | { | ||
949 | // either we didn't want any, or we were too unspecific | ||
950 | responseData["numFound"] = 0; | ||
951 | } | ||
952 | else | ||
953 | { | ||
954 | List<RegionProfileData> sims = GetRegions(name, maxNumber); | ||
955 | |||
956 | responseData["numFound"] = sims.Count; | ||
957 | for (int i = 0; i < sims.Count; ++i) | ||
958 | { | ||
959 | RegionProfileData sim = sims[i]; | ||
960 | string prefix = "region" + i + "."; | ||
961 | responseData[prefix + "region_name"] = sim.regionName; | ||
962 | responseData[prefix + "region_UUID"] = sim.UUID.ToString(); | ||
963 | responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); | ||
964 | responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); | ||
965 | responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); | ||
966 | responseData[prefix + "sim_port"] = sim.serverPort.ToString(); | ||
967 | responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); | ||
968 | responseData[prefix + "http_port"] = sim.httpPort.ToString(); | ||
969 | responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | XmlRpcResponse response = new XmlRpcResponse(); | ||
974 | response.Value = responseData; | ||
975 | return response; | ||
976 | } | ||
977 | |||
978 | /// <summary> | ||
979 | /// Performs a REST Get Operation | ||
980 | /// </summary> | ||
981 | /// <param name="request"></param> | ||
982 | /// <param name="path"></param> | ||
983 | /// <param name="param"></param> | ||
984 | /// <param name="httpRequest">HTTP request header object</param> | ||
985 | /// <param name="httpResponse">HTTP response header object</param> | ||
986 | /// <returns></returns> | ||
987 | public string RestGetRegionMethod(string request, string path, string param, | ||
988 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
989 | { | ||
990 | return RestGetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
991 | } | ||
992 | |||
993 | /// <summary> | ||
994 | /// Performs a REST Set Operation | ||
995 | /// </summary> | ||
996 | /// <param name="request"></param> | ||
997 | /// <param name="path"></param> | ||
998 | /// <param name="param"></param> | ||
999 | /// <param name="httpRequest">HTTP request header object</param> | ||
1000 | /// <param name="httpResponse">HTTP response header object</param> | ||
1001 | /// <returns></returns> | ||
1002 | public string RestSetRegionMethod(string request, string path, string param, | ||
1003 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1004 | { | ||
1005 | return RestSetSimMethod(String.Empty, "/sims/", param, httpRequest, httpResponse); | ||
1006 | } | ||
1007 | |||
1008 | /// <summary> | ||
1009 | /// Returns information about a sim via a REST Request | ||
1010 | /// </summary> | ||
1011 | /// <param name="request"></param> | ||
1012 | /// <param name="path"></param> | ||
1013 | /// <param name="param">A string representing the sim's UUID</param> | ||
1014 | /// <param name="httpRequest">HTTP request header object</param> | ||
1015 | /// <param name="httpResponse">HTTP response header object</param> | ||
1016 | /// <returns>Information about the sim in XML</returns> | ||
1017 | public string RestGetSimMethod(string request, string path, string param, | ||
1018 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1019 | { | ||
1020 | string respstring = String.Empty; | ||
1021 | |||
1022 | RegionProfileData TheSim; | ||
1023 | |||
1024 | UUID UUID; | ||
1025 | if (UUID.TryParse(param, out UUID)) | ||
1026 | { | ||
1027 | TheSim = GetRegion(UUID); | ||
1028 | |||
1029 | if (!(TheSim == null)) | ||
1030 | { | ||
1031 | respstring = "<Root>"; | ||
1032 | respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>"; | ||
1033 | respstring += "<sim>"; | ||
1034 | respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>"; | ||
1035 | respstring += "<regionname>" + TheSim.regionName + "</regionname>"; | ||
1036 | respstring += "<sim_ip>" + TheSim.serverIP + "</sim_ip>"; | ||
1037 | respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>"; | ||
1038 | respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>"; | ||
1039 | respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>"; | ||
1040 | respstring += "<estate_id>1</estate_id>"; | ||
1041 | respstring += "</sim>"; | ||
1042 | respstring += "</Root>"; | ||
1043 | } | ||
1044 | } | ||
1045 | else | ||
1046 | { | ||
1047 | respstring = "<Root>"; | ||
1048 | respstring += "<error>Param must be a UUID</error>"; | ||
1049 | respstring += "</Root>"; | ||
1050 | } | ||
1051 | |||
1052 | return respstring; | ||
1053 | } | ||
1054 | |||
1055 | /// <summary> | ||
1056 | /// Creates or updates a sim via a REST Method Request | ||
1057 | /// BROKEN with SQL Update | ||
1058 | /// </summary> | ||
1059 | /// <param name="request"></param> | ||
1060 | /// <param name="path"></param> | ||
1061 | /// <param name="param"></param> | ||
1062 | /// <param name="httpRequest">HTTP request header object</param> | ||
1063 | /// <param name="httpResponse">HTTP response header object</param> | ||
1064 | /// <returns>"OK" or an error</returns> | ||
1065 | public string RestSetSimMethod(string request, string path, string param, | ||
1066 | OSHttpRequest httpRequest, OSHttpResponse httpResponse) | ||
1067 | { | ||
1068 | Console.WriteLine("Processing region update via REST method"); | ||
1069 | RegionProfileData theSim; | ||
1070 | theSim = GetRegion(new UUID(param)); | ||
1071 | if (theSim == null) | ||
1072 | { | ||
1073 | theSim = new RegionProfileData(); | ||
1074 | UUID UUID = new UUID(param); | ||
1075 | theSim.UUID = UUID; | ||
1076 | theSim.regionRecvKey = Config.SimRecvKey; | ||
1077 | } | ||
1078 | |||
1079 | XmlDocument doc = new XmlDocument(); | ||
1080 | doc.LoadXml(request); | ||
1081 | XmlNode rootnode = doc.FirstChild; | ||
1082 | XmlNode authkeynode = rootnode.ChildNodes[0]; | ||
1083 | if (authkeynode.Name != "authkey") | ||
1084 | { | ||
1085 | return "ERROR! bad XML - expected authkey tag"; | ||
1086 | } | ||
1087 | |||
1088 | XmlNode simnode = rootnode.ChildNodes[1]; | ||
1089 | if (simnode.Name != "sim") | ||
1090 | { | ||
1091 | return "ERROR! bad XML - expected sim tag"; | ||
1092 | } | ||
1093 | |||
1094 | //theSim.regionSendKey = Cfg; | ||
1095 | theSim.regionRecvKey = Config.SimRecvKey; | ||
1096 | theSim.regionSendKey = Config.SimSendKey; | ||
1097 | theSim.regionSecret = Config.SimRecvKey; | ||
1098 | theSim.regionDataURI = String.Empty; | ||
1099 | theSim.regionAssetURI = Config.DefaultAssetServer; | ||
1100 | theSim.regionAssetRecvKey = Config.AssetRecvKey; | ||
1101 | theSim.regionAssetSendKey = Config.AssetSendKey; | ||
1102 | theSim.regionUserURI = Config.DefaultUserServer; | ||
1103 | theSim.regionUserSendKey = Config.UserSendKey; | ||
1104 | theSim.regionUserRecvKey = Config.UserRecvKey; | ||
1105 | |||
1106 | for (int i = 0; i < simnode.ChildNodes.Count; i++) | ||
1107 | { | ||
1108 | switch (simnode.ChildNodes[i].Name) | ||
1109 | { | ||
1110 | case "regionname": | ||
1111 | theSim.regionName = simnode.ChildNodes[i].InnerText; | ||
1112 | break; | ||
1113 | |||
1114 | case "sim_ip": | ||
1115 | theSim.serverIP = simnode.ChildNodes[i].InnerText; | ||
1116 | break; | ||
1117 | |||
1118 | case "sim_port": | ||
1119 | theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText); | ||
1120 | break; | ||
1121 | |||
1122 | case "region_locx": | ||
1123 | theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
1124 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
1125 | break; | ||
1126 | |||
1127 | case "region_locy": | ||
1128 | theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText); | ||
1129 | theSim.regionHandle = Utils.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize)); | ||
1130 | break; | ||
1131 | } | ||
1132 | } | ||
1133 | |||
1134 | theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/"; | ||
1135 | bool requirePublic = false; | ||
1136 | bool requireValid = true; | ||
1137 | |||
1138 | if (requirePublic && | ||
1139 | (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") || | ||
1140 | theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") || | ||
1141 | theSim.serverIP.StartsWith("255."))) | ||
1142 | { | ||
1143 | return "ERROR! Servers must register with public addresses."; | ||
1144 | } | ||
1145 | |||
1146 | if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255."))) | ||
1147 | { | ||
1148 | return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again"; | ||
1149 | } | ||
1150 | |||
1151 | try | ||
1152 | { | ||
1153 | m_log.Info("[DATA]: " + | ||
1154 | "Updating / adding via " + _plugins.Count + " storage provider(s) registered."); | ||
1155 | |||
1156 | foreach (IGridDataPlugin plugin in _plugins) | ||
1157 | { | ||
1158 | try | ||
1159 | { | ||
1160 | //Check reservations | ||
1161 | ReservationData reserveData = | ||
1162 | plugin.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY); | ||
1163 | if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) || | ||
1164 | (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey)) | ||
1165 | { | ||
1166 | plugin.AddProfile(theSim); | ||
1167 | m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")"); | ||
1168 | logToDB(theSim.ToString(), "RestSetSimMethod", String.Empty, 5, | ||
1169 | "Region successfully updated and connected to grid."); | ||
1170 | } | ||
1171 | else | ||
1172 | { | ||
1173 | m_log.Warn("[grid]: " + | ||
1174 | "Unable to update region (RestSetSimMethod): Incorrect reservation auth key."); | ||
1175 | // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + "."); | ||
1176 | return "Unable to update region (RestSetSimMethod): Incorrect auth key."; | ||
1177 | } | ||
1178 | } | ||
1179 | catch (Exception e) | ||
1180 | { | ||
1181 | m_log.Warn("[GRID]: GetRegionPlugin Handle " + plugin.Name + " unable to add new sim: " + | ||
1182 | e.ToString()); | ||
1183 | } | ||
1184 | } | ||
1185 | return "OK"; | ||
1186 | } | ||
1187 | catch (Exception e) | ||
1188 | { | ||
1189 | return "ERROR! Could not save to database! (" + e.ToString() + ")"; | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request) | ||
1194 | { | ||
1195 | XmlRpcResponse response = new XmlRpcResponse(); | ||
1196 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1197 | Hashtable responseData = new Hashtable(); | ||
1198 | |||
1199 | if (requestData.Contains("uri")) | ||
1200 | { | ||
1201 | string URI = (string)requestData["URI"]; | ||
1202 | string sendkey = (string)requestData["sendkey"]; | ||
1203 | string recvkey = (string)requestData["recvkey"]; | ||
1204 | MessageServerInfo m = new MessageServerInfo(); | ||
1205 | m.URI = URI; | ||
1206 | m.sendkey = sendkey; | ||
1207 | m.recvkey = recvkey; | ||
1208 | if (!_MessageServers.Contains(m)) | ||
1209 | _MessageServers.Add(m); | ||
1210 | responseData["responsestring"] = "TRUE"; | ||
1211 | response.Value = responseData; | ||
1212 | } | ||
1213 | return response; | ||
1214 | } | ||
1215 | |||
1216 | public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request) | ||
1217 | { | ||
1218 | XmlRpcResponse response = new XmlRpcResponse(); | ||
1219 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
1220 | Hashtable responseData = new Hashtable(); | ||
1221 | |||
1222 | if (requestData.Contains("uri")) | ||
1223 | { | ||
1224 | string URI = (string)requestData["uri"]; | ||
1225 | string sendkey = (string)requestData["sendkey"]; | ||
1226 | string recvkey = (string)requestData["recvkey"]; | ||
1227 | MessageServerInfo m = new MessageServerInfo(); | ||
1228 | m.URI = URI; | ||
1229 | m.sendkey = sendkey; | ||
1230 | m.recvkey = recvkey; | ||
1231 | if (_MessageServers.Contains(m)) | ||
1232 | _MessageServers.Remove(m); | ||
1233 | responseData["responsestring"] = "TRUE"; | ||
1234 | response.Value = responseData; | ||
1235 | } | ||
1236 | return response; | ||
1237 | } | ||
1238 | |||
1239 | /// <summary> | ||
1240 | /// Construct an XMLRPC registration disabled response | ||
1241 | /// </summary> | ||
1242 | /// <param name="error"></param> | ||
1243 | /// <returns></returns> | ||
1244 | public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) | ||
1245 | { | ||
1246 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | ||
1247 | Hashtable errorResponseData = new Hashtable(); | ||
1248 | errorResponse.Value = errorResponseData; | ||
1249 | errorResponseData["restricted"] = error; | ||
1250 | return errorResponse; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | /// <summary> | ||
1255 | /// Exception generated when a simulator fails to login to the grid | ||
1256 | /// </summary> | ||
1257 | public class LoginException : Exception | ||
1258 | { | ||
1259 | /// <summary> | ||
1260 | /// Return an XmlRpcResponse version of the exception message suitable for sending to a client | ||
1261 | /// </summary> | ||
1262 | /// <param name="message"></param> | ||
1263 | /// <param name="xmlRpcMessage"></param> | ||
1264 | public XmlRpcResponse XmlRpcErrorResponse | ||
1265 | { | ||
1266 | get { return m_xmlRpcErrorResponse; } | ||
1267 | } | ||
1268 | private XmlRpcResponse m_xmlRpcErrorResponse; | ||
1269 | |||
1270 | public LoginException(string message, string xmlRpcMessage) : base(message) | ||
1271 | { | ||
1272 | // FIXME: Might be neater to refactor and put the method inside here | ||
1273 | m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); | ||
1274 | } | ||
1275 | |||
1276 | public LoginException(string message, string xmlRpcMessage, Exception e) : base(message, e) | ||
1277 | { | ||
1278 | // FIXME: Might be neater to refactor and put the method inside here | ||
1279 | m_xmlRpcErrorResponse = GridManager.ErrorResponse(xmlRpcMessage); | ||
1280 | } | ||
1281 | } | ||
1282 | } | ||