diff options
Diffstat (limited to 'OpenSim/Grid/GridServer.Modules/GridXmlRpcModule.cs')
-rw-r--r-- | OpenSim/Grid/GridServer.Modules/GridXmlRpcModule.cs | 900 |
1 files changed, 0 insertions, 900 deletions
diff --git a/OpenSim/Grid/GridServer.Modules/GridXmlRpcModule.cs b/OpenSim/Grid/GridServer.Modules/GridXmlRpcModule.cs deleted file mode 100644 index 854e66a..0000000 --- a/OpenSim/Grid/GridServer.Modules/GridXmlRpcModule.cs +++ /dev/null | |||
@@ -1,900 +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 OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.IO; | ||
32 | using System.Net; | ||
33 | using System.Reflection; | ||
34 | using System.Xml; | ||
35 | using log4net; | ||
36 | using Nwc.XmlRpc; | ||
37 | using OpenMetaverse; | ||
38 | using OpenSim.Data; | ||
39 | using OpenSim.Framework; | ||
40 | using OpenSim.Framework.Communications; | ||
41 | using OpenSim.Framework.Servers; | ||
42 | using OpenSim.Framework.Servers.HttpServer; | ||
43 | using OpenSim.Grid.Framework; | ||
44 | |||
45 | namespace OpenSim.Grid.GridServer.Modules | ||
46 | { | ||
47 | public class GridXmlRpcModule | ||
48 | { | ||
49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
50 | |||
51 | private IRegionProfileService m_gridDBService; | ||
52 | private IGridServiceCore m_gridCore; | ||
53 | |||
54 | protected GridConfig m_config; | ||
55 | |||
56 | protected IMessagingServerDiscovery m_messagingServerMapper; | ||
57 | /// <value> | ||
58 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
59 | /// </value> | ||
60 | private string m_opensimVersion; | ||
61 | |||
62 | protected BaseHttpServer m_httpServer; | ||
63 | |||
64 | /// <summary> | ||
65 | /// Constructor | ||
66 | /// </summary> | ||
67 | /// <param name="opensimVersion"> | ||
68 | /// Used to notify old regions as to which OpenSim version to upgrade to | ||
69 | /// </param> | ||
70 | public GridXmlRpcModule() | ||
71 | { | ||
72 | } | ||
73 | |||
74 | public void Initialise(string opensimVersion, IRegionProfileService gridDBService, IGridServiceCore gridCore, GridConfig config) | ||
75 | { | ||
76 | m_opensimVersion = opensimVersion; | ||
77 | m_gridDBService = gridDBService; | ||
78 | m_gridCore = gridCore; | ||
79 | m_config = config; | ||
80 | RegisterHandlers(); | ||
81 | } | ||
82 | |||
83 | public void PostInitialise() | ||
84 | { | ||
85 | IMessagingServerDiscovery messagingModule; | ||
86 | if (m_gridCore.TryGet<IMessagingServerDiscovery>(out messagingModule)) | ||
87 | { | ||
88 | m_messagingServerMapper = messagingModule; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | public void RegisterHandlers() | ||
93 | { | ||
94 | //have these in separate method as some servers restart the http server and reregister all the handlers. | ||
95 | m_httpServer = m_gridCore.GetHttpServer(); | ||
96 | |||
97 | m_httpServer.AddXmlRPCHandler("simulator_login", XmlRpcSimulatorLoginMethod); | ||
98 | m_httpServer.AddXmlRPCHandler("simulator_data_request", XmlRpcSimulatorDataRequestMethod); | ||
99 | m_httpServer.AddXmlRPCHandler("simulator_after_region_moved", XmlRpcDeleteRegionMethod); | ||
100 | m_httpServer.AddXmlRPCHandler("map_block", XmlRpcMapBlockMethod); | ||
101 | m_httpServer.AddXmlRPCHandler("search_for_region_by_name", XmlRpcSearchForRegionMethod); | ||
102 | } | ||
103 | |||
104 | /// <summary> | ||
105 | /// Returns a XML String containing a list of the neighbouring regions | ||
106 | /// </summary> | ||
107 | /// <param name="reqhandle">The regionhandle for the center sim</param> | ||
108 | /// <returns>An XML string containing neighbour entities</returns> | ||
109 | public string GetXMLNeighbours(ulong reqhandle) | ||
110 | { | ||
111 | string response = String.Empty; | ||
112 | RegionProfileData central_region = m_gridDBService.GetRegion(reqhandle); | ||
113 | RegionProfileData neighbour; | ||
114 | for (int x = -1; x < 2; x++) | ||
115 | { | ||
116 | for (int y = -1; y < 2; y++) | ||
117 | { | ||
118 | if ( | ||
119 | m_gridDBService.GetRegion( | ||
120 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | ||
121 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null) | ||
122 | { | ||
123 | neighbour = | ||
124 | m_gridDBService.GetRegion( | ||
125 | Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize), | ||
126 | (uint)(central_region.regionLocY + y) * Constants.RegionSize)); | ||
127 | |||
128 | response += "<neighbour>"; | ||
129 | response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>"; | ||
130 | response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>"; | ||
131 | response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>"; | ||
132 | response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>"; | ||
133 | response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>"; | ||
134 | response += "</neighbour>"; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | return response; | ||
139 | } | ||
140 | |||
141 | /// <summary> | ||
142 | /// Checks that it's valid to replace the existing region data with new data | ||
143 | /// | ||
144 | /// Currently, this means ensure that the keys passed in by the new region | ||
145 | /// match those in the original region. (XXX Is this correct? Shouldn't we simply check | ||
146 | /// against the keys in the current configuration?) | ||
147 | /// </summary> | ||
148 | /// <param name="sim"></param> | ||
149 | /// <returns></returns> | ||
150 | protected virtual void ValidateOverwriteKeys(RegionProfileData sim, RegionProfileData existingSim) | ||
151 | { | ||
152 | if (!(existingSim.regionRecvKey == sim.regionRecvKey && existingSim.regionSendKey == sim.regionSendKey)) | ||
153 | { | ||
154 | throw new LoginException( | ||
155 | String.Format( | ||
156 | "Authentication failed when trying to login existing region {0} at location {1} {2} currently occupied by {3}" | ||
157 | + " with the region's send key {4} (expected {5}) and the region's receive key {6} (expected {7})", | ||
158 | sim.regionName, sim.regionLocX, sim.regionLocY, existingSim.regionName, | ||
159 | sim.regionSendKey, existingSim.regionSendKey, sim.regionRecvKey, existingSim.regionRecvKey), | ||
160 | "The keys required to login your region did not match the grid server keys. Please check your grid send and receive keys."); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /// <summary> | ||
165 | /// Checks that the new region data is valid. | ||
166 | /// | ||
167 | /// Currently, this means checking that the keys passed in by the new region | ||
168 | /// match those in the grid server's configuration. | ||
169 | /// </summary> | ||
170 | /// | ||
171 | /// <param name="sim"></param> | ||
172 | /// <exception cref="LoginException">Thrown if region login failed</exception> | ||
173 | protected virtual void ValidateNewRegionKeys(RegionProfileData sim) | ||
174 | { | ||
175 | if (!(sim.regionRecvKey == m_config.SimSendKey && sim.regionSendKey == m_config.SimRecvKey)) | ||
176 | { | ||
177 | throw new LoginException( | ||
178 | String.Format( | ||
179 | "Authentication failed when trying to login new region {0} at location {1} {2}" | ||
180 | + " with the region's send key {3} (expected {4}) and the region's receive key {5} (expected {6})", | ||
181 | sim.regionName, sim.regionLocX, sim.regionLocY, | ||
182 | sim.regionSendKey, m_config.SimRecvKey, sim.regionRecvKey, m_config.SimSendKey), | ||
183 | "The keys required to login your region did not match your existing region keys. Please check your grid send and receive keys."); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /// <summary> | ||
188 | /// Check that a region's http uri is externally contactable. | ||
189 | /// </summary> | ||
190 | /// <param name="sim"></param> | ||
191 | /// <exception cref="LoginException">Thrown if the region is not contactable</exception> | ||
192 | protected virtual void ValidateRegionContactable(RegionProfileData sim) | ||
193 | { | ||
194 | string regionStatusUrl = String.Format("{0}{1}", sim.httpServerURI, "simstatus/"); | ||
195 | string regionStatusResponse; | ||
196 | |||
197 | RestClient rc = new RestClient(regionStatusUrl); | ||
198 | rc.RequestMethod = "GET"; | ||
199 | |||
200 | m_log.DebugFormat("[LOGIN]: Contacting {0} for status of region {1}", regionStatusUrl, sim.regionName); | ||
201 | |||
202 | try | ||
203 | { | ||
204 | Stream rs = rc.Request(); | ||
205 | StreamReader sr = new StreamReader(rs); | ||
206 | regionStatusResponse = sr.ReadToEnd(); | ||
207 | sr.Close(); | ||
208 | } | ||
209 | catch (Exception e) | ||
210 | { | ||
211 | throw new LoginException( | ||
212 | String.Format("Region status request to {0} failed", regionStatusUrl), | ||
213 | String.Format( | ||
214 | "The grid service could not contact the http url {0} at your region. Please make sure this url is reachable by the grid service", | ||
215 | regionStatusUrl), | ||
216 | e); | ||
217 | } | ||
218 | |||
219 | if (!regionStatusResponse.Equals("OK")) | ||
220 | { | ||
221 | throw new LoginException( | ||
222 | String.Format( | ||
223 | "Region {0} at {1} returned status response {2} rather than {3}", | ||
224 | sim.regionName, regionStatusUrl, regionStatusResponse, "OK"), | ||
225 | String.Format( | ||
226 | "When the grid service asked for the status of your region, it received the response {0} rather than {1}. Please check your status", | ||
227 | regionStatusResponse, "OK")); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /// <summary> | ||
232 | /// Construct an XMLRPC error response | ||
233 | /// </summary> | ||
234 | /// <param name="error"></param> | ||
235 | /// <returns></returns> | ||
236 | public static XmlRpcResponse ErrorResponse(string error) | ||
237 | { | ||
238 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | ||
239 | Hashtable errorResponseData = new Hashtable(); | ||
240 | errorResponse.Value = errorResponseData; | ||
241 | errorResponseData["error"] = error; | ||
242 | return errorResponse; | ||
243 | } | ||
244 | |||
245 | /// <summary> | ||
246 | /// Performed when a region connects to the grid server initially. | ||
247 | /// </summary> | ||
248 | /// <param name="request">The XML RPC Request</param> | ||
249 | /// <returns>Startup parameters</returns> | ||
250 | public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient) | ||
251 | { | ||
252 | RegionProfileData sim; | ||
253 | RegionProfileData existingSim; | ||
254 | |||
255 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
256 | UUID uuid; | ||
257 | |||
258 | if (!requestData.ContainsKey("UUID") || !UUID.TryParse((string)requestData["UUID"], out uuid)) | ||
259 | { | ||
260 | m_log.Debug("[LOGIN PRELUDE]: Region connected without a UUID, sending back error response."); | ||
261 | return ErrorResponse("No UUID passed to grid server - unable to connect you"); | ||
262 | } | ||
263 | |||
264 | try | ||
265 | { | ||
266 | sim = RegionFromRequest(requestData); | ||
267 | } | ||
268 | catch (FormatException e) | ||
269 | { | ||
270 | m_log.Debug("[LOGIN PRELUDE]: Invalid login parameters, sending back error response."); | ||
271 | return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString()); | ||
272 | } | ||
273 | |||
274 | m_log.InfoFormat("[LOGIN BEGIN]: Received login request from simulator: {0}", sim.regionName); | ||
275 | |||
276 | if (!m_config.AllowRegionRegistration) | ||
277 | { | ||
278 | m_log.DebugFormat( | ||
279 | "[LOGIN END]: Disabled region registration blocked login request from simulator: {0}", | ||
280 | sim.regionName); | ||
281 | |||
282 | return ErrorResponse("This grid is currently not accepting region registrations."); | ||
283 | } | ||
284 | |||
285 | int majorInterfaceVersion = 0; | ||
286 | if (requestData.ContainsKey("major_interface_version")) | ||
287 | int.TryParse((string)requestData["major_interface_version"], out majorInterfaceVersion); | ||
288 | |||
289 | if (majorInterfaceVersion != VersionInfo.MajorInterfaceVersion) | ||
290 | { | ||
291 | return ErrorResponse( | ||
292 | String.Format( | ||
293 | "Your region service implements OGS1 interface version {0}" | ||
294 | + " but this grid requires that the region implement OGS1 interface version {1} to connect." | ||
295 | + " Try changing to OpenSimulator {2}", | ||
296 | majorInterfaceVersion, VersionInfo.MajorInterfaceVersion, m_opensimVersion)); | ||
297 | } | ||
298 | |||
299 | existingSim = m_gridDBService.GetRegion(sim.regionHandle); | ||
300 | |||
301 | if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID) | ||
302 | { | ||
303 | try | ||
304 | { | ||
305 | if (existingSim == null) | ||
306 | { | ||
307 | ValidateNewRegionKeys(sim); | ||
308 | } | ||
309 | else | ||
310 | { | ||
311 | ValidateOverwriteKeys(sim, existingSim); | ||
312 | } | ||
313 | |||
314 | ValidateRegionContactable(sim); | ||
315 | } | ||
316 | catch (LoginException e) | ||
317 | { | ||
318 | string logMsg = e.Message; | ||
319 | if (e.InnerException != null) | ||
320 | logMsg += ", " + e.InnerException.Message; | ||
321 | |||
322 | m_log.WarnFormat("[LOGIN END]: {0}", logMsg); | ||
323 | |||
324 | return e.XmlRpcErrorResponse; | ||
325 | } | ||
326 | |||
327 | DataResponse insertResponse = m_gridDBService.AddUpdateRegion(sim, existingSim); | ||
328 | |||
329 | switch (insertResponse) | ||
330 | { | ||
331 | case DataResponse.RESPONSE_OK: | ||
332 | m_log.Info("[LOGIN END]: " + (existingSim == null ? "New" : "Existing") + " sim login successful: " + sim.regionName); | ||
333 | break; | ||
334 | case DataResponse.RESPONSE_ERROR: | ||
335 | m_log.Warn("[LOGIN END]: Sim login failed (Error): " + sim.regionName); | ||
336 | break; | ||
337 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | ||
338 | m_log.Warn("[LOGIN END]: " + | ||
339 | "Sim login failed (Invalid Credentials): " + sim.regionName); | ||
340 | break; | ||
341 | case DataResponse.RESPONSE_AUTHREQUIRED: | ||
342 | m_log.Warn("[LOGIN END]: " + | ||
343 | "Sim login failed (Authentication Required): " + | ||
344 | sim.regionName); | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | XmlRpcResponse response = CreateLoginResponse(sim); | ||
349 | |||
350 | return response; | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | m_log.Warn("[LOGIN END]: Failed to login region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName); | ||
355 | return ErrorResponse("Another region already exists at that location. Please try another."); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | /// <summary> | ||
360 | /// Construct a successful response to a simulator's login attempt. | ||
361 | /// </summary> | ||
362 | /// <param name="sim"></param> | ||
363 | /// <returns></returns> | ||
364 | private XmlRpcResponse CreateLoginResponse(RegionProfileData sim) | ||
365 | { | ||
366 | XmlRpcResponse response = new XmlRpcResponse(); | ||
367 | Hashtable responseData = new Hashtable(); | ||
368 | response.Value = responseData; | ||
369 | |||
370 | ArrayList SimNeighboursData = GetSimNeighboursData(sim); | ||
371 | |||
372 | responseData["UUID"] = sim.UUID.ToString(); | ||
373 | responseData["region_locx"] = sim.regionLocX.ToString(); | ||
374 | responseData["region_locy"] = sim.regionLocY.ToString(); | ||
375 | responseData["regionname"] = sim.regionName; | ||
376 | responseData["estate_id"] = "1"; | ||
377 | responseData["neighbours"] = SimNeighboursData; | ||
378 | |||
379 | responseData["sim_ip"] = sim.serverIP; | ||
380 | responseData["sim_port"] = sim.serverPort.ToString(); | ||
381 | responseData["asset_url"] = sim.regionAssetURI; | ||
382 | responseData["asset_sendkey"] = sim.regionAssetSendKey; | ||
383 | responseData["asset_recvkey"] = sim.regionAssetRecvKey; | ||
384 | responseData["user_url"] = sim.regionUserURI; | ||
385 | responseData["user_sendkey"] = sim.regionUserSendKey; | ||
386 | responseData["user_recvkey"] = sim.regionUserRecvKey; | ||
387 | responseData["authkey"] = sim.regionSecret; | ||
388 | |||
389 | // New! If set, use as URL to local sim storage (ie http://remotehost/region.Yap) | ||
390 | responseData["data_uri"] = sim.regionDataURI; | ||
391 | |||
392 | responseData["allow_forceful_banlines"] = m_config.AllowForcefulBanlines; | ||
393 | |||
394 | // Instead of sending a multitude of message servers to the registering sim | ||
395 | // we should probably be sending a single one and parhaps it's backup | ||
396 | // that has responsibility over routing it's messages. | ||
397 | |||
398 | // The Sim won't be contacting us again about any of the message server stuff during it's time up. | ||
399 | |||
400 | responseData["messageserver_count"] = 0; | ||
401 | |||
402 | // IGridMessagingModule messagingModule; | ||
403 | // if (m_gridCore.TryGet<IGridMessagingModule>(out messagingModule)) | ||
404 | //{ | ||
405 | if (m_messagingServerMapper != null) | ||
406 | { | ||
407 | List<MessageServerInfo> messageServers = m_messagingServerMapper.GetMessageServersList(); | ||
408 | responseData["messageserver_count"] = messageServers.Count; | ||
409 | |||
410 | for (int i = 0; i < messageServers.Count; i++) | ||
411 | { | ||
412 | responseData["messageserver_uri" + i] = messageServers[i].URI; | ||
413 | responseData["messageserver_sendkey" + i] = messageServers[i].sendkey; | ||
414 | responseData["messageserver_recvkey" + i] = messageServers[i].recvkey; | ||
415 | } | ||
416 | } | ||
417 | return response; | ||
418 | } | ||
419 | |||
420 | private ArrayList GetSimNeighboursData(RegionProfileData sim) | ||
421 | { | ||
422 | ArrayList SimNeighboursData = new ArrayList(); | ||
423 | |||
424 | RegionProfileData neighbour; | ||
425 | Hashtable NeighbourBlock; | ||
426 | |||
427 | //First use the fast method. (not implemented in SQLLite) | ||
428 | List<RegionProfileData> neighbours = m_gridDBService.GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1, sim.regionLocY + 1); | ||
429 | |||
430 | if (neighbours.Count > 0) | ||
431 | { | ||
432 | foreach (RegionProfileData aSim in neighbours) | ||
433 | { | ||
434 | NeighbourBlock = new Hashtable(); | ||
435 | NeighbourBlock["sim_ip"] = aSim.serverIP; | ||
436 | NeighbourBlock["sim_port"] = aSim.serverPort.ToString(); | ||
437 | NeighbourBlock["region_locx"] = aSim.regionLocX.ToString(); | ||
438 | NeighbourBlock["region_locy"] = aSim.regionLocY.ToString(); | ||
439 | NeighbourBlock["UUID"] = aSim.ToString(); | ||
440 | NeighbourBlock["regionHandle"] = aSim.regionHandle.ToString(); | ||
441 | |||
442 | if (aSim.UUID != sim.UUID) | ||
443 | { | ||
444 | SimNeighboursData.Add(NeighbourBlock); | ||
445 | } | ||
446 | } | ||
447 | } | ||
448 | else | ||
449 | { | ||
450 | for (int x = -1; x < 2; x++) | ||
451 | { | ||
452 | for (int y = -1; y < 2; y++) | ||
453 | { | ||
454 | if ( | ||
455 | m_gridDBService.GetRegion( | ||
456 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | ||
457 | (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null) | ||
458 | { | ||
459 | neighbour = | ||
460 | m_gridDBService.GetRegion( | ||
461 | Utils.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize), | ||
462 | (uint)(sim.regionLocY + y) * Constants.RegionSize)); | ||
463 | |||
464 | NeighbourBlock = new Hashtable(); | ||
465 | NeighbourBlock["sim_ip"] = neighbour.serverIP; | ||
466 | NeighbourBlock["sim_port"] = neighbour.serverPort.ToString(); | ||
467 | NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString(); | ||
468 | NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString(); | ||
469 | NeighbourBlock["UUID"] = neighbour.UUID.ToString(); | ||
470 | NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString(); | ||
471 | |||
472 | if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | } | ||
477 | return SimNeighboursData; | ||
478 | } | ||
479 | |||
480 | /// <summary> | ||
481 | /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region | ||
482 | /// </summary> | ||
483 | /// <param name="requestData"></param> | ||
484 | /// <returns></returns> | ||
485 | private RegionProfileData RegionFromRequest(Hashtable requestData) | ||
486 | { | ||
487 | RegionProfileData sim; | ||
488 | sim = new RegionProfileData(); | ||
489 | |||
490 | sim.UUID = new UUID((string)requestData["UUID"]); | ||
491 | sim.originUUID = new UUID((string)requestData["originUUID"]); | ||
492 | |||
493 | sim.regionRecvKey = String.Empty; | ||
494 | sim.regionSendKey = String.Empty; | ||
495 | |||
496 | if (requestData.ContainsKey("region_secret")) | ||
497 | { | ||
498 | string regionsecret = (string)requestData["region_secret"]; | ||
499 | if (regionsecret.Length > 0) | ||
500 | sim.regionSecret = regionsecret; | ||
501 | else | ||
502 | sim.regionSecret = m_config.SimRecvKey; | ||
503 | |||
504 | } | ||
505 | else | ||
506 | { | ||
507 | sim.regionSecret = m_config.SimRecvKey; | ||
508 | } | ||
509 | |||
510 | sim.regionDataURI = String.Empty; | ||
511 | sim.regionAssetURI = m_config.DefaultAssetServer; | ||
512 | sim.regionAssetRecvKey = m_config.AssetRecvKey; | ||
513 | sim.regionAssetSendKey = m_config.AssetSendKey; | ||
514 | sim.regionUserURI = m_config.DefaultUserServer; | ||
515 | sim.regionUserSendKey = m_config.UserSendKey; | ||
516 | sim.regionUserRecvKey = m_config.UserRecvKey; | ||
517 | |||
518 | sim.serverIP = (string)requestData["sim_ip"]; | ||
519 | sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]); | ||
520 | sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]); | ||
521 | sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]); | ||
522 | sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]); | ||
523 | sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]); | ||
524 | sim.regionLocZ = 0; | ||
525 | |||
526 | UUID textureID; | ||
527 | if (UUID.TryParse((string)requestData["map-image-id"], out textureID)) | ||
528 | { | ||
529 | sim.regionMapTextureID = textureID; | ||
530 | } | ||
531 | |||
532 | // part of an initial brutish effort to provide accurate information (as per the xml region spec) | ||
533 | // wrt the ownership of a given region | ||
534 | // the (very bad) assumption is that this value is being read and handled inconsistently or | ||
535 | // not at all. Current strategy is to put the code in place to support the validity of this information | ||
536 | // and to roll forward debugging any issues from that point | ||
537 | // | ||
538 | // this particular section of the mod attempts to receive a value from the region's xml file by way of | ||
539 | // OSG1GridServices for the region's owner | ||
540 | sim.owner_uuid = (UUID)(string)requestData["master_avatar_uuid"]; | ||
541 | |||
542 | try | ||
543 | { | ||
544 | sim.regionRecvKey = (string)requestData["recvkey"]; | ||
545 | sim.regionSendKey = (string)requestData["authkey"]; | ||
546 | } | ||
547 | catch (KeyNotFoundException) { } | ||
548 | |||
549 | sim.regionHandle = Utils.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize)); | ||
550 | sim.serverURI = (string)requestData["server_uri"]; | ||
551 | |||
552 | sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/"; | ||
553 | |||
554 | sim.regionName = (string)requestData["sim_name"]; | ||
555 | |||
556 | |||
557 | try | ||
558 | { | ||
559 | |||
560 | sim.maturity = Convert.ToUInt32((string)requestData["maturity"]); | ||
561 | } | ||
562 | catch (KeyNotFoundException) | ||
563 | { | ||
564 | //older region not providing this key - so default to Mature | ||
565 | sim.maturity = 1; | ||
566 | } | ||
567 | |||
568 | return sim; | ||
569 | } | ||
570 | |||
571 | /// <summary> | ||
572 | /// Returns an XML RPC response to a simulator profile request | ||
573 | /// Performed after moving a region. | ||
574 | /// </summary> | ||
575 | /// <param name="request"></param> | ||
576 | /// <returns></returns> | ||
577 | /// <param name="request">The XMLRPC Request</param> | ||
578 | /// <returns>Processing parameters</returns> | ||
579 | public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) | ||
580 | { | ||
581 | XmlRpcResponse response = new XmlRpcResponse(); | ||
582 | Hashtable responseData = new Hashtable(); | ||
583 | response.Value = responseData; | ||
584 | |||
585 | //RegionProfileData TheSim = null; | ||
586 | string uuid; | ||
587 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
588 | |||
589 | if (requestData.ContainsKey("UUID")) | ||
590 | { | ||
591 | //TheSim = GetRegion(new UUID((string) requestData["UUID"])); | ||
592 | uuid = requestData["UUID"].ToString(); | ||
593 | m_log.InfoFormat("[LOGOUT]: Logging out region: {0}", uuid); | ||
594 | // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID."); | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete"; | ||
599 | return response; | ||
600 | } | ||
601 | |||
602 | DataResponse insertResponse = m_gridDBService.DeleteRegion(uuid); | ||
603 | |||
604 | string insertResp = ""; | ||
605 | switch (insertResponse) | ||
606 | { | ||
607 | case DataResponse.RESPONSE_OK: | ||
608 | //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid); | ||
609 | insertResp = "Deleting region successful: " + uuid; | ||
610 | break; | ||
611 | case DataResponse.RESPONSE_ERROR: | ||
612 | //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid); | ||
613 | insertResp = "Deleting region failed (Error): " + uuid; | ||
614 | break; | ||
615 | case DataResponse.RESPONSE_INVALIDCREDENTIALS: | ||
616 | //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid); | ||
617 | insertResp = "Deleting region (Invalid Credentials): " + uuid; | ||
618 | break; | ||
619 | case DataResponse.RESPONSE_AUTHREQUIRED: | ||
620 | //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid); | ||
621 | insertResp = "Deleting region (Authentication Required): " + uuid; | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | responseData["status"] = insertResp; | ||
626 | |||
627 | return response; | ||
628 | } | ||
629 | |||
630 | /// <summary> | ||
631 | /// Returns an XML RPC response to a simulator profile request | ||
632 | /// </summary> | ||
633 | /// <param name="request"></param> | ||
634 | /// <returns></returns> | ||
635 | public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request, IPEndPoint remoteClient) | ||
636 | { | ||
637 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
638 | Hashtable responseData = new Hashtable(); | ||
639 | RegionProfileData simData = null; | ||
640 | if (requestData.ContainsKey("region_UUID")) | ||
641 | { | ||
642 | UUID regionID = new UUID((string)requestData["region_UUID"]); | ||
643 | simData = m_gridDBService.GetRegion(regionID); | ||
644 | if (simData == null) | ||
645 | { | ||
646 | m_log.WarnFormat("[DATA] didn't find region for regionID {0} from {1}", | ||
647 | regionID, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
648 | } | ||
649 | } | ||
650 | else if (requestData.ContainsKey("region_handle")) | ||
651 | { | ||
652 | //CFK: The if/else below this makes this message redundant. | ||
653 | //CFK: m_log.Info("requesting data for region " + (string) requestData["region_handle"]); | ||
654 | ulong regionHandle = Convert.ToUInt64((string)requestData["region_handle"]); | ||
655 | simData = m_gridDBService.GetRegion(regionHandle); | ||
656 | if (simData == null) | ||
657 | { | ||
658 | m_log.WarnFormat("[DATA] didn't find region for regionHandle {0} from {1}", | ||
659 | regionHandle, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
660 | } | ||
661 | } | ||
662 | else if (requestData.ContainsKey("region_name_search")) | ||
663 | { | ||
664 | string regionName = (string)requestData["region_name_search"]; | ||
665 | simData = m_gridDBService.GetRegion(regionName); | ||
666 | if (simData == null) | ||
667 | { | ||
668 | m_log.WarnFormat("[DATA] didn't find region for regionName {0} from {1}", | ||
669 | regionName, request.Params.Count > 1 ? request.Params[1] : "unknwon source"); | ||
670 | } | ||
671 | } | ||
672 | else m_log.Warn("[DATA] regionlookup without regionID, regionHandle or regionHame"); | ||
673 | |||
674 | if (simData == null) | ||
675 | { | ||
676 | //Sim does not exist | ||
677 | responseData["error"] = "Sim does not exist"; | ||
678 | } | ||
679 | else | ||
680 | { | ||
681 | m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " + | ||
682 | (string)requestData["region_handle"]); | ||
683 | responseData["sim_ip"] = simData.serverIP; | ||
684 | responseData["sim_port"] = simData.serverPort.ToString(); | ||
685 | responseData["server_uri"] = simData.serverURI; | ||
686 | responseData["http_port"] = simData.httpPort.ToString(); | ||
687 | responseData["remoting_port"] = simData.remotingPort.ToString(); | ||
688 | responseData["region_locx"] = simData.regionLocX.ToString(); | ||
689 | responseData["region_locy"] = simData.regionLocY.ToString(); | ||
690 | responseData["region_UUID"] = simData.UUID.Guid.ToString(); | ||
691 | responseData["region_name"] = simData.regionName; | ||
692 | responseData["regionHandle"] = simData.regionHandle.ToString(); | ||
693 | } | ||
694 | |||
695 | XmlRpcResponse response = new XmlRpcResponse(); | ||
696 | response.Value = responseData; | ||
697 | return response; | ||
698 | } | ||
699 | |||
700 | public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request, IPEndPoint remoteClient) | ||
701 | { | ||
702 | int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020; | ||
703 | |||
704 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
705 | if (requestData.ContainsKey("xmin")) | ||
706 | { | ||
707 | xmin = (Int32)requestData["xmin"]; | ||
708 | } | ||
709 | if (requestData.ContainsKey("ymin")) | ||
710 | { | ||
711 | ymin = (Int32)requestData["ymin"]; | ||
712 | } | ||
713 | if (requestData.ContainsKey("xmax")) | ||
714 | { | ||
715 | xmax = (Int32)requestData["xmax"]; | ||
716 | } | ||
717 | if (requestData.ContainsKey("ymax")) | ||
718 | { | ||
719 | ymax = (Int32)requestData["ymax"]; | ||
720 | } | ||
721 | //CFK: The second log is more meaningful and either standard or fast generally occurs. | ||
722 | //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
723 | |||
724 | XmlRpcResponse response = new XmlRpcResponse(); | ||
725 | Hashtable responseData = new Hashtable(); | ||
726 | response.Value = responseData; | ||
727 | IList simProfileList = new ArrayList(); | ||
728 | |||
729 | bool fastMode = (m_config.DatabaseProvider == "OpenSim.Data.MySQL.dll" || m_config.DatabaseProvider == "OpenSim.Data.MSSQL.dll"); | ||
730 | |||
731 | if (fastMode) | ||
732 | { | ||
733 | List<RegionProfileData> neighbours = m_gridDBService.GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax); | ||
734 | |||
735 | foreach (RegionProfileData aSim in neighbours) | ||
736 | { | ||
737 | Hashtable simProfileBlock = new Hashtable(); | ||
738 | simProfileBlock["x"] = aSim.regionLocX.ToString(); | ||
739 | simProfileBlock["y"] = aSim.regionLocY.ToString(); | ||
740 | //m_log.DebugFormat("[MAP]: Sending neighbour info for {0},{1}", aSim.regionLocX, aSim.regionLocY); | ||
741 | simProfileBlock["name"] = aSim.regionName; | ||
742 | simProfileBlock["access"] = aSim.AccessLevel.ToString(); | ||
743 | simProfileBlock["region-flags"] = 512; | ||
744 | simProfileBlock["water-height"] = 0; | ||
745 | simProfileBlock["agents"] = 1; | ||
746 | simProfileBlock["map-image-id"] = aSim.regionMapTextureID.ToString(); | ||
747 | |||
748 | // For Sugilite compatibility | ||
749 | simProfileBlock["regionhandle"] = aSim.regionHandle.ToString(); | ||
750 | simProfileBlock["sim_ip"] = aSim.serverIP; | ||
751 | simProfileBlock["sim_port"] = aSim.serverPort.ToString(); | ||
752 | simProfileBlock["sim_uri"] = aSim.serverURI.ToString(); | ||
753 | simProfileBlock["uuid"] = aSim.UUID.ToString(); | ||
754 | simProfileBlock["remoting_port"] = aSim.remotingPort.ToString(); | ||
755 | simProfileBlock["http_port"] = aSim.httpPort.ToString(); | ||
756 | |||
757 | simProfileList.Add(simProfileBlock); | ||
758 | } | ||
759 | m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() + | ||
760 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
761 | } | ||
762 | else | ||
763 | { | ||
764 | RegionProfileData simProfile; | ||
765 | for (int x = xmin; x < xmax + 1; x++) | ||
766 | { | ||
767 | for (int y = ymin; y < ymax + 1; y++) | ||
768 | { | ||
769 | ulong regHandle = Utils.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize)); | ||
770 | simProfile = m_gridDBService.GetRegion(regHandle); | ||
771 | if (simProfile != null) | ||
772 | { | ||
773 | Hashtable simProfileBlock = new Hashtable(); | ||
774 | simProfileBlock["x"] = x; | ||
775 | simProfileBlock["y"] = y; | ||
776 | simProfileBlock["name"] = simProfile.regionName; | ||
777 | simProfileBlock["access"] = simProfile.AccessLevel.ToString(); | ||
778 | simProfileBlock["region-flags"] = 0; | ||
779 | simProfileBlock["water-height"] = 20; | ||
780 | simProfileBlock["agents"] = 1; | ||
781 | simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString(); | ||
782 | |||
783 | // For Sugilite compatibility | ||
784 | simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString(); | ||
785 | simProfileBlock["sim_ip"] = simProfile.serverIP.ToString(); | ||
786 | simProfileBlock["sim_port"] = simProfile.serverPort.ToString(); | ||
787 | simProfileBlock["sim_uri"] = simProfile.serverURI.ToString(); | ||
788 | simProfileBlock["uuid"] = simProfile.UUID.ToString(); | ||
789 | simProfileBlock["remoting_port"] = simProfile.remotingPort.ToString(); | ||
790 | simProfileBlock["http_port"] = simProfile.httpPort; | ||
791 | |||
792 | simProfileList.Add(simProfileBlock); | ||
793 | } | ||
794 | } | ||
795 | } | ||
796 | m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() + | ||
797 | " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")"); | ||
798 | } | ||
799 | |||
800 | responseData["sim-profiles"] = simProfileList; | ||
801 | |||
802 | return response; | ||
803 | } | ||
804 | |||
805 | /// <summary> | ||
806 | /// Returns up to <code>maxNumber</code> profiles of regions that have a name starting with <code>name</code> | ||
807 | /// </summary> | ||
808 | /// <param name="request"></param> | ||
809 | /// <returns></returns> | ||
810 | public XmlRpcResponse XmlRpcSearchForRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) | ||
811 | { | ||
812 | Hashtable requestData = (Hashtable)request.Params[0]; | ||
813 | |||
814 | if (!requestData.ContainsKey("name") || !requestData.Contains("maxNumber")) | ||
815 | { | ||
816 | m_log.Warn("[DATA] Invalid region-search request; missing name or maxNumber"); | ||
817 | return new XmlRpcResponse(500, "Missing name or maxNumber in region search request"); | ||
818 | } | ||
819 | |||
820 | Hashtable responseData = new Hashtable(); | ||
821 | |||
822 | string name = (string)requestData["name"]; | ||
823 | int maxNumber = Convert.ToInt32((string)requestData["maxNumber"]); | ||
824 | if (maxNumber == 0 || name.Length < 3) | ||
825 | { | ||
826 | // either we didn't want any, or we were too unspecific | ||
827 | responseData["numFound"] = 0; | ||
828 | } | ||
829 | else | ||
830 | { | ||
831 | List<RegionProfileData> sims = m_gridDBService.GetRegions(name, maxNumber); | ||
832 | |||
833 | responseData["numFound"] = sims.Count; | ||
834 | for (int i = 0; i < sims.Count; ++i) | ||
835 | { | ||
836 | RegionProfileData sim = sims[i]; | ||
837 | string prefix = "region" + i + "."; | ||
838 | responseData[prefix + "region_name"] = sim.regionName; | ||
839 | responseData[prefix + "region_UUID"] = sim.UUID.ToString(); | ||
840 | responseData[prefix + "region_locx"] = sim.regionLocX.ToString(); | ||
841 | responseData[prefix + "region_locy"] = sim.regionLocY.ToString(); | ||
842 | responseData[prefix + "sim_ip"] = sim.serverIP.ToString(); | ||
843 | responseData[prefix + "sim_port"] = sim.serverPort.ToString(); | ||
844 | responseData[prefix + "remoting_port"] = sim.remotingPort.ToString(); | ||
845 | responseData[prefix + "http_port"] = sim.httpPort.ToString(); | ||
846 | responseData[prefix + "map_UUID"] = sim.regionMapTextureID.ToString(); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | XmlRpcResponse response = new XmlRpcResponse(); | ||
851 | response.Value = responseData; | ||
852 | return response; | ||
853 | } | ||
854 | |||
855 | /// <summary> | ||
856 | /// Construct an XMLRPC registration disabled response | ||
857 | /// </summary> | ||
858 | /// <param name="error"></param> | ||
859 | /// <returns></returns> | ||
860 | public static XmlRpcResponse XmlRPCRegionRegistrationDisabledResponse(string error) | ||
861 | { | ||
862 | XmlRpcResponse errorResponse = new XmlRpcResponse(); | ||
863 | Hashtable errorResponseData = new Hashtable(); | ||
864 | errorResponse.Value = errorResponseData; | ||
865 | errorResponseData["restricted"] = error; | ||
866 | return errorResponse; | ||
867 | } | ||
868 | } | ||
869 | |||
870 | /// <summary> | ||
871 | /// Exception generated when a simulator fails to login to the grid | ||
872 | /// </summary> | ||
873 | public class LoginException : Exception | ||
874 | { | ||
875 | /// <summary> | ||
876 | /// Return an XmlRpcResponse version of the exception message suitable for sending to a client | ||
877 | /// </summary> | ||
878 | /// <param name="message"></param> | ||
879 | /// <param name="xmlRpcMessage"></param> | ||
880 | public XmlRpcResponse XmlRpcErrorResponse | ||
881 | { | ||
882 | get { return m_xmlRpcErrorResponse; } | ||
883 | } | ||
884 | private XmlRpcResponse m_xmlRpcErrorResponse; | ||
885 | |||
886 | public LoginException(string message, string xmlRpcMessage) | ||
887 | : base(message) | ||
888 | { | ||
889 | // FIXME: Might be neater to refactor and put the method inside here | ||
890 | m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); | ||
891 | } | ||
892 | |||
893 | public LoginException(string message, string xmlRpcMessage, Exception e) | ||
894 | : base(message, e) | ||
895 | { | ||
896 | // FIXME: Might be neater to refactor and put the method inside here | ||
897 | m_xmlRpcErrorResponse = GridXmlRpcModule.ErrorResponse(xmlRpcMessage); | ||
898 | } | ||
899 | } | ||
900 | } | ||