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