GridManager.cs 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  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. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Reflection;
  31. using System.Xml;
  32. using libsecondlife;
  33. using Nwc.XmlRpc;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Console;
  36. using OpenSim.Framework.Data;
  37. using OpenSim.Framework.Servers;
  38. using OpenSim.Framework.Data.MySQL;
  39. namespace OpenSim.Grid.GridServer
  40. {
  41. public class GridManager
  42. {
  43. private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  44. private Dictionary<string, IGridData> _plugins = new Dictionary<string, IGridData>();
  45. private Dictionary<string, ILogData> _logplugins = new Dictionary<string, ILogData>();
  46. // This is here so that the grid server can hand out MessageServer settings to regions on registration
  47. private List<MessageServerInfo> _MessageServers = new List<MessageServerInfo>();
  48. public GridConfig Config;
  49. /// <summary>
  50. /// Adds a new grid server plugin - grid servers will be requested in the order they were loaded.
  51. /// </summary>
  52. /// <param name="FileName">The filename to the grid server plugin DLL</param>
  53. public void AddPlugin(string FileName)
  54. {
  55. m_log.Info("[DATA]: Attempting to load " + FileName);
  56. Assembly pluginAssembly = Assembly.LoadFrom(FileName);
  57. m_log.Info("[DATA]: Found " + pluginAssembly.GetTypes().Length + " interfaces.");
  58. foreach (Type pluginType in pluginAssembly.GetTypes())
  59. {
  60. if (!pluginType.IsAbstract)
  61. {
  62. // Regions go here
  63. Type typeInterface = pluginType.GetInterface("IGridData", true);
  64. if (typeInterface != null)
  65. {
  66. IGridData plug =
  67. (IGridData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
  68. plug.Initialise();
  69. _plugins.Add(plug.getName(), plug);
  70. m_log.Info("[DATA]: Added IGridData Interface");
  71. }
  72. typeInterface = null;
  73. // Logs go here
  74. typeInterface = pluginType.GetInterface("ILogData", true);
  75. if (typeInterface != null)
  76. {
  77. ILogData plug =
  78. (ILogData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
  79. plug.Initialise();
  80. _logplugins.Add(plug.getName(), plug);
  81. m_log.Info("[DATA]: Added ILogData Interface");
  82. }
  83. typeInterface = null;
  84. }
  85. }
  86. pluginAssembly = null;
  87. }
  88. /// <summary>
  89. /// Logs a piece of information to the database
  90. /// </summary>
  91. /// <param name="target">What you were operating on (in grid server, this will likely be the region UUIDs)</param>
  92. /// <param name="method">Which method is being called?</param>
  93. /// <param name="args">What arguments are being passed?</param>
  94. /// <param name="priority">How high priority is this? 1 = Max, 6 = Verbose</param>
  95. /// <param name="message">The message to log</param>
  96. private void logToDB(string target, string method, string args, int priority, string message)
  97. {
  98. foreach (KeyValuePair<string, ILogData> kvp in _logplugins)
  99. {
  100. try
  101. {
  102. kvp.Value.saveLog("Gridserver", target, method, args, priority, message);
  103. }
  104. catch (Exception)
  105. {
  106. m_log.Warn("[storage]: Unable to write log via " + kvp.Key);
  107. }
  108. }
  109. }
  110. /// <summary>
  111. /// Returns a region by argument
  112. /// </summary>
  113. /// <param name="uuid">A UUID key of the region to return</param>
  114. /// <returns>A SimProfileData for the region</returns>
  115. public RegionProfileData GetRegion(LLUUID uuid)
  116. {
  117. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  118. {
  119. try
  120. {
  121. return kvp.Value.GetProfileByLLUUID(uuid);
  122. }
  123. catch (Exception e)
  124. {
  125. m_log.Warn("[storage]: GetRegion - " + e.Message);
  126. }
  127. }
  128. return null;
  129. }
  130. /// <summary>
  131. /// Returns a region by argument
  132. /// </summary>
  133. /// <param name="uuid">A regionHandle of the region to return</param>
  134. /// <returns>A SimProfileData for the region</returns>
  135. public RegionProfileData GetRegion(ulong handle)
  136. {
  137. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  138. {
  139. try
  140. {
  141. return kvp.Value.GetProfileByHandle(handle);
  142. }
  143. catch
  144. {
  145. m_log.Warn("[storage]: Unable to find region " + handle.ToString() + " via " + kvp.Key);
  146. }
  147. }
  148. return null;
  149. }
  150. /// <summary>
  151. /// Returns a region by argument
  152. /// </summary>
  153. /// <param name="regionName">A partial regionName of the region to return</param>
  154. /// <returns>A SimProfileData for the region</returns>
  155. public RegionProfileData GetRegion(string regionName)
  156. {
  157. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  158. {
  159. try
  160. {
  161. return kvp.Value.GetProfileByString(regionName);
  162. }
  163. catch
  164. {
  165. m_log.Warn("[storage]: Unable to find region " + regionName + " via " + kvp.Key);
  166. }
  167. }
  168. return null;
  169. }
  170. public Dictionary<ulong, RegionProfileData> GetRegions(uint xmin, uint ymin, uint xmax, uint ymax)
  171. {
  172. Dictionary<ulong, RegionProfileData> regions = new Dictionary<ulong, RegionProfileData>();
  173. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  174. {
  175. try
  176. {
  177. RegionProfileData[] neighbours = kvp.Value.GetProfilesInRange(xmin, ymin, xmax, ymax);
  178. foreach (RegionProfileData neighbour in neighbours)
  179. {
  180. regions[neighbour.regionHandle] = neighbour;
  181. }
  182. }
  183. catch
  184. {
  185. m_log.Warn("[storage]: Unable to query regionblock via " + kvp.Key);
  186. }
  187. }
  188. return regions;
  189. }
  190. /// <summary>
  191. /// Returns a XML String containing a list of the neighbouring regions
  192. /// </summary>
  193. /// <param name="reqhandle">The regionhandle for the center sim</param>
  194. /// <returns>An XML string containing neighbour entities</returns>
  195. public string GetXMLNeighbours(ulong reqhandle)
  196. {
  197. string response = String.Empty;
  198. RegionProfileData central_region = GetRegion(reqhandle);
  199. RegionProfileData neighbour;
  200. for (int x = -1; x < 2; x++)
  201. {
  202. for (int y = -1; y < 2; y++)
  203. {
  204. if (
  205. GetRegion(
  206. Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize),
  207. (uint)(central_region.regionLocY + y) * Constants.RegionSize)) != null)
  208. {
  209. neighbour =
  210. GetRegion(
  211. Util.UIntsToLong((uint)((central_region.regionLocX + x) * Constants.RegionSize),
  212. (uint)(central_region.regionLocY + y) * Constants.RegionSize));
  213. response += "<neighbour>";
  214. response += "<sim_ip>" + neighbour.serverIP + "</sim_ip>";
  215. response += "<sim_port>" + neighbour.serverPort.ToString() + "</sim_port>";
  216. response += "<locx>" + neighbour.regionLocX.ToString() + "</locx>";
  217. response += "<locy>" + neighbour.regionLocY.ToString() + "</locy>";
  218. response += "<regionhandle>" + neighbour.regionHandle.ToString() + "</regionhandle>";
  219. response += "</neighbour>";
  220. }
  221. }
  222. }
  223. return response;
  224. }
  225. /// <summary>
  226. /// Checks that it's valid to replace the existing region data with new data
  227. ///
  228. /// Currently, this means ensure that the keys passed in by the new region
  229. /// match those in the original region. (XXX Is this correct? Shouldn't we simply check
  230. /// against the keys in the current configuration?)
  231. /// </summary>
  232. /// <param name="sim"></param>
  233. /// <returns></returns>
  234. protected virtual bool ValidateOverwrite(RegionProfileData sim, RegionProfileData existingSim)
  235. {
  236. return (existingSim.regionRecvKey == sim.regionRecvKey &&
  237. existingSim.regionSendKey == sim.regionSendKey);
  238. }
  239. /// <summary>
  240. /// Checks that the new region data is valid.
  241. ///
  242. /// Currently, this means checking that the keys passed in by the new region
  243. /// match those in the grid server's configuration.
  244. /// </summary>
  245. /// <param name="sim"></param>
  246. /// <returns></returns>
  247. protected virtual bool ValidateNewRegion(RegionProfileData sim)
  248. {
  249. return (sim.regionRecvKey == Config.SimSendKey &&
  250. sim.regionSendKey == Config.SimRecvKey);
  251. }
  252. private XmlRpcResponse ErrorResponse(string error)
  253. {
  254. XmlRpcResponse errorResponse = new XmlRpcResponse();
  255. Hashtable errorResponseData = new Hashtable();
  256. errorResponse.Value = errorResponseData;
  257. errorResponseData["error"] = error;
  258. return errorResponse;
  259. }
  260. /// <summary>
  261. /// Performed when a region connects to the grid server initially.
  262. /// </summary>
  263. /// <param name="request">The XMLRPC Request</param>
  264. /// <returns>Startup parameters</returns>
  265. public XmlRpcResponse XmlRpcSimulatorLoginMethod(XmlRpcRequest request)
  266. {
  267. RegionProfileData sim;
  268. RegionProfileData existingSim;
  269. Hashtable requestData = (Hashtable)request.Params[0];
  270. LLUUID uuid;
  271. if (!requestData.ContainsKey("UUID") || !LLUUID.TryParse((string)requestData["UUID"], out uuid))
  272. {
  273. m_log.Info("[GRID]: Region connected without a UUID, ignoring.");
  274. return ErrorResponse("No UUID passed to grid server - unable to connect you");
  275. }
  276. try
  277. {
  278. sim = RegionFromRequest(requestData);
  279. }
  280. catch (FormatException e)
  281. {
  282. m_log.Info("[GRID]: Invalid login parameters, ignoring.");
  283. return ErrorResponse("Wrong format in login parameters. Please verify parameters." + e.ToString() );
  284. }
  285. existingSim = GetRegion(sim.regionHandle);
  286. if (existingSim == null || existingSim.UUID == sim.UUID || sim.UUID != sim.originUUID)
  287. {
  288. bool validated;
  289. if (existingSim == null)
  290. {
  291. validated = ValidateNewRegion(sim);
  292. }
  293. else
  294. {
  295. validated = ValidateOverwrite(sim, existingSim);
  296. }
  297. if (validated)
  298. {
  299. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  300. {
  301. try
  302. {
  303. DataResponse insertResponse = kvp.Value.AddProfile(sim);
  304. switch (insertResponse)
  305. {
  306. case DataResponse.RESPONSE_OK:
  307. m_log.Info("[grid]: New sim " + (existingSim == null ? "creation" : "connection") + " successful: " + sim.regionName);
  308. break;
  309. case DataResponse.RESPONSE_ERROR:
  310. m_log.Warn("[storage]: New sim creation failed (Error): " + sim.regionName);
  311. break;
  312. case DataResponse.RESPONSE_INVALIDCREDENTIALS:
  313. m_log.Warn("[storage]: " +
  314. "New sim creation failed (Invalid Credentials): " + sim.regionName);
  315. break;
  316. case DataResponse.RESPONSE_AUTHREQUIRED:
  317. m_log.Warn("[storage]: " +
  318. "New sim creation failed (Authentication Required): " +
  319. sim.regionName);
  320. break;
  321. }
  322. }
  323. catch (Exception e)
  324. {
  325. m_log.Warn("[storage]: " +
  326. "Unable to add region " + sim.UUID.ToString() + " via " + kvp.Key);
  327. m_log.Warn("[storage]: " + e.ToString());
  328. }
  329. }
  330. XmlRpcResponse response = CreateLoginResponse(sim);
  331. return response;
  332. }
  333. else
  334. {
  335. if (existingSim == null)
  336. {
  337. m_log.Warn("[grid]: Authentication failed when trying to add new region " + sim.regionName +
  338. " at location " + sim.regionLocX +
  339. " " + sim.regionLocY + " with TheSim.regionRecvKey " + sim.regionRecvKey + "(" + Config.SimSendKey + ") and TheSim.regionRecvKey " + sim.regionSendKey + "(" + Config.SimRecvKey + ") ");
  340. }
  341. else
  342. {
  343. m_log.Warn("[grid]: Authentication failed when trying to add new region " + sim.regionName +
  344. " at location " + sim.regionLocX +
  345. " " + sim.regionLocY + " currently occupied by " + existingSim.regionName);
  346. }
  347. return ErrorResponse("The key required to connect to your region did not match. Please check your send and recieve keys.");
  348. }
  349. }
  350. else
  351. {
  352. m_log.Warn("[grid]: Failed to add new region " + sim.regionName + " at location " + sim.regionLocX + " " + sim.regionLocY + " currently occupied by " + existingSim.regionName);
  353. return ErrorResponse("Another region already exists at that location. Try another");
  354. }
  355. }
  356. /// <summary>
  357. /// Construct a successful response to a simulator's login attempt.
  358. /// </summary>
  359. /// <param name="sim"></param>
  360. /// <returns></returns>
  361. private XmlRpcResponse CreateLoginResponse(RegionProfileData sim)
  362. {
  363. XmlRpcResponse response = new XmlRpcResponse();
  364. Hashtable responseData = new Hashtable();
  365. response.Value = responseData;
  366. ArrayList SimNeighboursData = GetSimNeighboursData(sim);
  367. responseData["UUID"] = sim.UUID.ToString();
  368. responseData["region_locx"] = sim.regionLocX.ToString();
  369. responseData["region_locy"] = sim.regionLocY.ToString();
  370. responseData["regionname"] = sim.regionName;
  371. responseData["estate_id"] = "1";
  372. responseData["neighbours"] = SimNeighboursData;
  373. responseData["sim_ip"] = sim.serverIP;
  374. responseData["sim_port"] = sim.serverPort.ToString();
  375. responseData["asset_url"] = sim.regionAssetURI;
  376. responseData["asset_sendkey"] = sim.regionAssetSendKey;
  377. responseData["asset_recvkey"] = sim.regionAssetRecvKey;
  378. responseData["user_url"] = sim.regionUserURI;
  379. responseData["user_sendkey"] = sim.regionUserSendKey;
  380. responseData["user_recvkey"] = sim.regionUserRecvKey;
  381. responseData["authkey"] = sim.regionSecret;
  382. // New! If set, use as URL to local sim storage (ie http://remotehost/region.yap)
  383. responseData["data_uri"] = sim.regionDataURI;
  384. responseData["allow_forceful_banlines"] = Config.AllowForcefulBanlines;
  385. // Instead of sending a multitude of message servers to the registering sim
  386. // we should probably be sending a single one and parhaps it's backup
  387. // that has responsibility over routing it's messages.
  388. // The Sim won't be contacting us again about any of the message server stuff during it's time up.
  389. responseData["messageserver_count"] = _MessageServers.Count;
  390. for (int i = 0; i < _MessageServers.Count; i++)
  391. {
  392. responseData["messageserver_uri" + i] = _MessageServers[i].URI;
  393. responseData["messageserver_sendkey" + i] = _MessageServers[i].sendkey;
  394. responseData["messageserver_recvkey" + i] = _MessageServers[i].recvkey;
  395. }
  396. return response;
  397. }
  398. private ArrayList GetSimNeighboursData(RegionProfileData sim)
  399. {
  400. ArrayList SimNeighboursData = new ArrayList();
  401. RegionProfileData neighbour;
  402. Hashtable NeighbourBlock;
  403. bool fastMode = false; // Only compatible with MySQL right now
  404. if (fastMode)
  405. {
  406. Dictionary<ulong, RegionProfileData> neighbours =
  407. GetRegions(sim.regionLocX - 1, sim.regionLocY - 1, sim.regionLocX + 1,
  408. sim.regionLocY + 1);
  409. foreach (KeyValuePair<ulong, RegionProfileData> aSim in neighbours)
  410. {
  411. NeighbourBlock = new Hashtable();
  412. NeighbourBlock["sim_ip"] = Util.GetHostFromDNS(aSim.Value.serverIP.ToString()).ToString();
  413. NeighbourBlock["sim_port"] = aSim.Value.serverPort.ToString();
  414. NeighbourBlock["region_locx"] = aSim.Value.regionLocX.ToString();
  415. NeighbourBlock["region_locy"] = aSim.Value.regionLocY.ToString();
  416. NeighbourBlock["UUID"] = aSim.Value.UUID.ToString();
  417. NeighbourBlock["regionHandle"] = aSim.Value.regionHandle.ToString();
  418. if (aSim.Value.UUID != sim.UUID)
  419. {
  420. SimNeighboursData.Add(NeighbourBlock);
  421. }
  422. }
  423. }
  424. else
  425. {
  426. for (int x = -1; x < 2; x++)
  427. {
  428. for (int y = -1; y < 2; y++)
  429. {
  430. if (
  431. GetRegion(
  432. Helpers.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize),
  433. (uint)(sim.regionLocY + y) * Constants.RegionSize)) != null)
  434. {
  435. neighbour =
  436. GetRegion(
  437. Helpers.UIntsToLong((uint)((sim.regionLocX + x) * Constants.RegionSize),
  438. (uint)(sim.regionLocY + y) * Constants.RegionSize));
  439. NeighbourBlock = new Hashtable();
  440. NeighbourBlock["sim_ip"] = Util.GetHostFromDNS(neighbour.serverIP).ToString();
  441. NeighbourBlock["sim_port"] = neighbour.serverPort.ToString();
  442. NeighbourBlock["region_locx"] = neighbour.regionLocX.ToString();
  443. NeighbourBlock["region_locy"] = neighbour.regionLocY.ToString();
  444. NeighbourBlock["UUID"] = neighbour.UUID.ToString();
  445. NeighbourBlock["regionHandle"] = neighbour.regionHandle.ToString();
  446. if (neighbour.UUID != sim.UUID) SimNeighboursData.Add(NeighbourBlock);
  447. }
  448. }
  449. }
  450. }
  451. return SimNeighboursData;
  452. }
  453. /// <summary>
  454. /// Loads the grid's own RegionProfileData object with data from the XMLRPC simulator_login request from a region
  455. /// </summary>
  456. /// <param name="requestData"></param>
  457. /// <returns></returns>
  458. private RegionProfileData RegionFromRequest(Hashtable requestData)
  459. {
  460. RegionProfileData sim;
  461. sim = new RegionProfileData();
  462. sim.UUID = new LLUUID((string)requestData["UUID"]);
  463. sim.originUUID = new LLUUID((string)requestData["originUUID"]);
  464. sim.regionRecvKey = String.Empty;
  465. sim.regionSendKey = String.Empty;
  466. sim.regionSecret = Config.SimRecvKey;
  467. sim.regionDataURI = String.Empty;
  468. sim.regionAssetURI = Config.DefaultAssetServer;
  469. sim.regionAssetRecvKey = Config.AssetRecvKey;
  470. sim.regionAssetSendKey = Config.AssetSendKey;
  471. sim.regionUserURI = Config.DefaultUserServer;
  472. sim.regionUserSendKey = Config.UserSendKey;
  473. sim.regionUserRecvKey = Config.UserRecvKey;
  474. sim.serverIP = (string)requestData["sim_ip"];
  475. sim.serverPort = Convert.ToUInt32((string)requestData["sim_port"]);
  476. sim.httpPort = Convert.ToUInt32((string)requestData["http_port"]);
  477. sim.remotingPort = Convert.ToUInt32((string)requestData["remoting_port"]);
  478. sim.regionLocX = Convert.ToUInt32((string)requestData["region_locx"]);
  479. sim.regionLocY = Convert.ToUInt32((string)requestData["region_locy"]);
  480. sim.regionLocZ = 0;
  481. LLUUID textureID;
  482. if (LLUUID.TryParse((string)requestData["map-image-id"], out textureID))
  483. {
  484. sim.regionMapTextureID = textureID;
  485. }
  486. // part of an initial brutish effort to provide accurate information (as per the xml region spec)
  487. // wrt the ownership of a given region
  488. // the (very bad) assumption is that this value is being read and handled inconsistently or
  489. // not at all. Current strategy is to put the code in place to support the validity of this information
  490. // and to roll forward debugging any issues from that point
  491. //
  492. // this particular section of the mod attempts to receive a value from the region's xml file by way of
  493. // OSG1GridServices for the region's owner
  494. sim.owner_uuid = (string)requestData["master_avatar_uuid"];
  495. try
  496. {
  497. sim.regionRecvKey = (string)requestData["recvkey"];
  498. sim.regionSendKey = (string)requestData["authkey"];
  499. }
  500. catch (KeyNotFoundException) { }
  501. sim.regionHandle = Helpers.UIntsToLong((sim.regionLocX * Constants.RegionSize), (sim.regionLocY * Constants.RegionSize));
  502. sim.serverURI = (string)requestData["server_uri"];
  503. sim.httpServerURI = "http://" + sim.serverIP + ":" + sim.httpPort + "/";
  504. sim.regionName = (string)requestData["sim_name"];
  505. return sim;
  506. }
  507. /// <summary>
  508. /// Returns an XML RPC response to a simulator profile request
  509. /// Performed after moving a region.
  510. /// </summary>
  511. /// <param name="request"></param>
  512. /// <returns></returns>
  513. /// <param name="request">The XMLRPC Request</param>
  514. /// <returns>Processing parameters</returns>
  515. public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request)
  516. {
  517. XmlRpcResponse response = new XmlRpcResponse();
  518. Hashtable responseData = new Hashtable();
  519. response.Value = responseData;
  520. //RegionProfileData TheSim = null;
  521. string uuid = String.Empty; ;
  522. Hashtable requestData = (Hashtable)request.Params[0];
  523. if (requestData.ContainsKey("UUID"))
  524. {
  525. //TheSim = GetRegion(new LLUUID((string) requestData["UUID"]));
  526. uuid = requestData["UUID"].ToString();
  527. Console.WriteLine("deleting region " + uuid);
  528. // logToDB((new LLUUID((string)requestData["UUID"])).ToString(),"XmlRpcDeleteRegionMethod","", 5,"Attempting delete with UUID.");
  529. }
  530. else
  531. {
  532. responseData["error"] = "No UUID or region_handle passed to grid server - unable to delete";
  533. return response;
  534. }
  535. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  536. {
  537. //OpenSim.Framework.Data.MySQL.MySQLGridData dbengine = new OpenSim.Framework.Data.MySQL.MySQLGridData();
  538. try
  539. {
  540. OpenSim.Framework.Data.MySQL.MySQLGridData mysqldata = (OpenSim.Framework.Data.MySQL.MySQLGridData)(kvp.Value);
  541. //DataResponse insertResponse = mysqldata.DeleteProfile(TheSim);
  542. DataResponse insertResponse = mysqldata.DeleteProfile(uuid);
  543. switch (insertResponse)
  544. {
  545. case DataResponse.RESPONSE_OK:
  546. //MainLog.Instance.Verbose("grid", "Deleting region successful: " + uuid);
  547. responseData["status"] = "Deleting region successful: " + uuid;
  548. break;
  549. case DataResponse.RESPONSE_ERROR:
  550. //MainLog.Instance.Warn("storage", "Deleting region failed (Error): " + uuid);
  551. responseData["status"] = "Deleting region failed (Error): " + uuid;
  552. break;
  553. case DataResponse.RESPONSE_INVALIDCREDENTIALS:
  554. //MainLog.Instance.Warn("storage", "Deleting region failed (Invalid Credentials): " + uuid);
  555. responseData["status"] = "Deleting region (Invalid Credentials): " + uuid;
  556. break;
  557. case DataResponse.RESPONSE_AUTHREQUIRED:
  558. //MainLog.Instance.Warn("storage", "Deleting region failed (Authentication Required): " + uuid);
  559. responseData["status"] = "Deleting region (Authentication Required): " + uuid;
  560. break;
  561. }
  562. }
  563. catch (Exception)
  564. {
  565. m_log.Error("storage Unable to delete region " + uuid + " via MySQL");
  566. //MainLog.Instance.Warn("storage", e.ToString());
  567. }
  568. }
  569. return response;
  570. }
  571. /// <summary>
  572. /// Returns an XML RPC response to a simulator profile request
  573. /// </summary>
  574. /// <param name="request"></param>
  575. /// <returns></returns>
  576. public XmlRpcResponse XmlRpcSimulatorDataRequestMethod(XmlRpcRequest request)
  577. {
  578. Hashtable requestData = (Hashtable)request.Params[0];
  579. Hashtable responseData = new Hashtable();
  580. RegionProfileData simData = null;
  581. if (requestData.ContainsKey("region_UUID"))
  582. {
  583. simData = GetRegion(new LLUUID((string)requestData["region_UUID"]));
  584. }
  585. else if (requestData.ContainsKey("region_handle"))
  586. {
  587. //CFK: The if/else below this makes this message redundant.
  588. //CFK: Console.WriteLine("requesting data for region " + (string) requestData["region_handle"]);
  589. simData = GetRegion(Convert.ToUInt64((string)requestData["region_handle"]));
  590. }
  591. else if (requestData.ContainsKey("region_name_search"))
  592. {
  593. simData = GetRegion((string)requestData["region_name_search"]);
  594. }
  595. if (simData == null)
  596. {
  597. //Sim does not exist
  598. Console.WriteLine("region not found");
  599. responseData["error"] = "Sim does not exist";
  600. }
  601. else
  602. {
  603. m_log.Info("[DATA]: found " + (string)simData.regionName + " regionHandle = " +
  604. (string)requestData["region_handle"]);
  605. responseData["sim_ip"] = Util.GetHostFromDNS(simData.serverIP).ToString();
  606. responseData["sim_port"] = simData.serverPort.ToString();
  607. responseData["server_uri"] = simData.serverURI;
  608. responseData["http_port"] = simData.httpPort.ToString();
  609. responseData["remoting_port"] = simData.remotingPort.ToString();
  610. responseData["region_locx"] = simData.regionLocX.ToString();
  611. responseData["region_locy"] = simData.regionLocY.ToString();
  612. responseData["region_UUID"] = simData.UUID.UUID.ToString();
  613. responseData["region_name"] = simData.regionName;
  614. responseData["regionHandle"] = simData.regionHandle.ToString();
  615. }
  616. XmlRpcResponse response = new XmlRpcResponse();
  617. response.Value = responseData;
  618. return response;
  619. }
  620. public XmlRpcResponse XmlRpcMapBlockMethod(XmlRpcRequest request)
  621. {
  622. int xmin = 980, ymin = 980, xmax = 1020, ymax = 1020;
  623. Hashtable requestData = (Hashtable)request.Params[0];
  624. if (requestData.ContainsKey("xmin"))
  625. {
  626. xmin = (Int32)requestData["xmin"];
  627. }
  628. if (requestData.ContainsKey("ymin"))
  629. {
  630. ymin = (Int32)requestData["ymin"];
  631. }
  632. if (requestData.ContainsKey("xmax"))
  633. {
  634. xmax = (Int32)requestData["xmax"];
  635. }
  636. if (requestData.ContainsKey("ymax"))
  637. {
  638. ymax = (Int32)requestData["ymax"];
  639. }
  640. //CFK: The second log is more meaningful and either standard or fast generally occurs.
  641. //CFK: m_log.Info("[MAP]: World map request for range (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
  642. XmlRpcResponse response = new XmlRpcResponse();
  643. Hashtable responseData = new Hashtable();
  644. response.Value = responseData;
  645. IList simProfileList = new ArrayList();
  646. bool fastMode = false; // MySQL Only
  647. fastMode = (Config.DatabaseProvider == "OpenSim.Framework.Data.MySQL.dll");
  648. if (fastMode)
  649. {
  650. Dictionary<ulong, RegionProfileData> neighbours =
  651. GetRegions((uint)xmin, (uint)ymin, (uint)xmax, (uint)ymax);
  652. foreach (KeyValuePair<ulong, RegionProfileData> aSim in neighbours)
  653. {
  654. Hashtable simProfileBlock = new Hashtable();
  655. simProfileBlock["x"] = aSim.Value.regionLocX.ToString();
  656. simProfileBlock["y"] = aSim.Value.regionLocY.ToString();
  657. Console.WriteLine("send neighbour info for " + aSim.Value.regionLocX.ToString() + " , " +
  658. aSim.Value.regionLocY.ToString());
  659. simProfileBlock["name"] = aSim.Value.regionName;
  660. simProfileBlock["access"] = 21;
  661. simProfileBlock["region-flags"] = 512;
  662. simProfileBlock["water-height"] = 0;
  663. simProfileBlock["agents"] = 1;
  664. simProfileBlock["map-image-id"] = aSim.Value.regionMapTextureID.ToString();
  665. // For Sugilite compatibility
  666. simProfileBlock["regionhandle"] = aSim.Value.regionHandle.ToString();
  667. simProfileBlock["sim_ip"] = aSim.Value.serverIP.ToString();
  668. simProfileBlock["sim_port"] = aSim.Value.serverPort.ToString();
  669. simProfileBlock["sim_uri"] = aSim.Value.serverURI.ToString();
  670. simProfileBlock["uuid"] = aSim.Value.UUID.ToString();
  671. simProfileBlock["remoting_port"] = aSim.Value.remotingPort;
  672. simProfileList.Add(simProfileBlock);
  673. }
  674. m_log.Info("[MAP]: Fast map " + simProfileList.Count.ToString() +
  675. " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
  676. }
  677. else
  678. {
  679. RegionProfileData simProfile;
  680. for (int x = xmin; x < xmax + 1; x++)
  681. {
  682. for (int y = ymin; y < ymax + 1; y++)
  683. {
  684. ulong regHandle = Helpers.UIntsToLong((uint)(x * Constants.RegionSize), (uint)(y * Constants.RegionSize));
  685. simProfile = GetRegion(regHandle);
  686. if (simProfile != null)
  687. {
  688. Hashtable simProfileBlock = new Hashtable();
  689. simProfileBlock["x"] = x;
  690. simProfileBlock["y"] = y;
  691. simProfileBlock["name"] = simProfile.regionName;
  692. simProfileBlock["access"] = 0;
  693. simProfileBlock["region-flags"] = 0;
  694. simProfileBlock["water-height"] = 20;
  695. simProfileBlock["agents"] = 1;
  696. simProfileBlock["map-image-id"] = simProfile.regionMapTextureID.ToString();
  697. // For Sugilite compatibility
  698. simProfileBlock["regionhandle"] = simProfile.regionHandle.ToString();
  699. simProfileBlock["sim_ip"] = simProfile.serverIP.ToString();
  700. simProfileBlock["sim_port"] = simProfile.serverPort.ToString();
  701. simProfileBlock["sim_uri"] = simProfile.serverURI.ToString();
  702. simProfileBlock["uuid"] = simProfile.UUID.ToString();
  703. simProfileList.Add(simProfileBlock);
  704. }
  705. }
  706. }
  707. m_log.Info("[MAP]: Std map " + simProfileList.Count.ToString() +
  708. " regions @ (" + xmin + "," + ymin + ")..(" + xmax + "," + ymax + ")");
  709. }
  710. responseData["sim-profiles"] = simProfileList;
  711. return response;
  712. }
  713. /// <summary>
  714. /// Performs a REST Get Operation
  715. /// </summary>
  716. /// <param name="request"></param>
  717. /// <param name="path"></param>
  718. /// <param name="param"></param>
  719. /// <returns></returns>
  720. public string RestGetRegionMethod(string request, string path, string param)
  721. {
  722. return RestGetSimMethod(String.Empty, "/sims/", param);
  723. }
  724. /// <summary>
  725. /// Performs a REST Set Operation
  726. /// </summary>
  727. /// <param name="request"></param>
  728. /// <param name="path"></param>
  729. /// <param name="param"></param>
  730. /// <returns></returns>
  731. public string RestSetRegionMethod(string request, string path, string param)
  732. {
  733. return RestSetSimMethod(String.Empty, "/sims/", param);
  734. }
  735. /// <summary>
  736. /// Returns information about a sim via a REST Request
  737. /// </summary>
  738. /// <param name="request"></param>
  739. /// <param name="path"></param>
  740. /// <param name="param">A string representing the sim's UUID</param>
  741. /// <returns>Information about the sim in XML</returns>
  742. public string RestGetSimMethod(string request, string path, string param)
  743. {
  744. string respstring = String.Empty;
  745. RegionProfileData TheSim;
  746. LLUUID UUID;
  747. if (LLUUID.TryParse(param, out UUID))
  748. {
  749. TheSim = GetRegion(UUID);
  750. if (!(TheSim == null))
  751. {
  752. respstring = "<Root>";
  753. respstring += "<authkey>" + TheSim.regionSendKey + "</authkey>";
  754. respstring += "<sim>";
  755. respstring += "<uuid>" + TheSim.UUID.ToString() + "</uuid>";
  756. respstring += "<regionname>" + TheSim.regionName + "</regionname>";
  757. respstring += "<sim_ip>" + Util.GetHostFromDNS(TheSim.serverIP).ToString() + "</sim_ip>";
  758. respstring += "<sim_port>" + TheSim.serverPort.ToString() + "</sim_port>";
  759. respstring += "<region_locx>" + TheSim.regionLocX.ToString() + "</region_locx>";
  760. respstring += "<region_locy>" + TheSim.regionLocY.ToString() + "</region_locy>";
  761. respstring += "<estate_id>1</estate_id>";
  762. respstring += "</sim>";
  763. respstring += "</Root>";
  764. }
  765. }
  766. else
  767. {
  768. respstring = "<Root>";
  769. respstring += "<error>Param must be a UUID</error>";
  770. respstring += "</Root>";
  771. }
  772. return respstring;
  773. }
  774. /// <summary>
  775. /// Creates or updates a sim via a REST Method Request
  776. /// BROKEN with SQL Update
  777. /// </summary>
  778. /// <param name="request"></param>
  779. /// <param name="path"></param>
  780. /// <param name="param"></param>
  781. /// <returns>"OK" or an error</returns>
  782. public string RestSetSimMethod(string request, string path, string param)
  783. {
  784. Console.WriteLine("Processing region update via REST method");
  785. RegionProfileData theSim;
  786. theSim = GetRegion(new LLUUID(param));
  787. if (theSim == null)
  788. {
  789. theSim = new RegionProfileData();
  790. LLUUID UUID = new LLUUID(param);
  791. theSim.UUID = UUID;
  792. theSim.regionRecvKey = Config.SimRecvKey;
  793. }
  794. XmlDocument doc = new XmlDocument();
  795. doc.LoadXml(request);
  796. XmlNode rootnode = doc.FirstChild;
  797. XmlNode authkeynode = rootnode.ChildNodes[0];
  798. if (authkeynode.Name != "authkey")
  799. {
  800. return "ERROR! bad XML - expected authkey tag";
  801. }
  802. XmlNode simnode = rootnode.ChildNodes[1];
  803. if (simnode.Name != "sim")
  804. {
  805. return "ERROR! bad XML - expected sim tag";
  806. }
  807. //theSim.regionSendKey = Cfg;
  808. theSim.regionRecvKey = Config.SimRecvKey;
  809. theSim.regionSendKey = Config.SimSendKey;
  810. theSim.regionSecret = Config.SimRecvKey;
  811. theSim.regionDataURI = String.Empty;
  812. theSim.regionAssetURI = Config.DefaultAssetServer;
  813. theSim.regionAssetRecvKey = Config.AssetRecvKey;
  814. theSim.regionAssetSendKey = Config.AssetSendKey;
  815. theSim.regionUserURI = Config.DefaultUserServer;
  816. theSim.regionUserSendKey = Config.UserSendKey;
  817. theSim.regionUserRecvKey = Config.UserRecvKey;
  818. for (int i = 0; i < simnode.ChildNodes.Count; i++)
  819. {
  820. switch (simnode.ChildNodes[i].Name)
  821. {
  822. case "regionname":
  823. theSim.regionName = simnode.ChildNodes[i].InnerText;
  824. break;
  825. case "sim_ip":
  826. theSim.serverIP = simnode.ChildNodes[i].InnerText;
  827. break;
  828. case "sim_port":
  829. theSim.serverPort = Convert.ToUInt32(simnode.ChildNodes[i].InnerText);
  830. break;
  831. case "region_locx":
  832. theSim.regionLocX = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
  833. theSim.regionHandle = Helpers.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize));
  834. break;
  835. case "region_locy":
  836. theSim.regionLocY = Convert.ToUInt32((string)simnode.ChildNodes[i].InnerText);
  837. theSim.regionHandle = Helpers.UIntsToLong((theSim.regionLocX * Constants.RegionSize), (theSim.regionLocY * Constants.RegionSize));
  838. break;
  839. }
  840. }
  841. theSim.serverURI = "http://" + theSim.serverIP + ":" + theSim.serverPort + "/";
  842. bool requirePublic = false;
  843. bool requireValid = true;
  844. if (requirePublic &&
  845. (theSim.serverIP.StartsWith("172.16") || theSim.serverIP.StartsWith("192.168") ||
  846. theSim.serverIP.StartsWith("10.") || theSim.serverIP.StartsWith("0.") ||
  847. theSim.serverIP.StartsWith("255.")))
  848. {
  849. return "ERROR! Servers must register with public addresses.";
  850. }
  851. if (requireValid && (theSim.serverIP.StartsWith("0.") || theSim.serverIP.StartsWith("255.")))
  852. {
  853. return "ERROR! 0.*.*.* / 255.*.*.* Addresses are invalid, please check your server config and try again";
  854. }
  855. try
  856. {
  857. m_log.Info("[DATA]: " +
  858. "Updating / adding via " + _plugins.Count + " storage provider(s) registered.");
  859. foreach (KeyValuePair<string, IGridData> kvp in _plugins)
  860. {
  861. try
  862. {
  863. //Check reservations
  864. ReservationData reserveData =
  865. kvp.Value.GetReservationAtPoint(theSim.regionLocX, theSim.regionLocY);
  866. if ((reserveData != null && reserveData.gridRecvKey == theSim.regionRecvKey) ||
  867. (reserveData == null && authkeynode.InnerText != theSim.regionRecvKey))
  868. {
  869. kvp.Value.AddProfile(theSim);
  870. m_log.Info("[grid]: New sim added to grid (" + theSim.regionName + ")");
  871. logToDB(theSim.UUID.ToString(), "RestSetSimMethod", String.Empty, 5,
  872. "Region successfully updated and connected to grid.");
  873. }
  874. else
  875. {
  876. m_log.Warn("[grid]: " +
  877. "Unable to update region (RestSetSimMethod): Incorrect reservation auth key.");
  878. // Wanted: " + reserveData.gridRecvKey + ", Got: " + theSim.regionRecvKey + ".");
  879. return "Unable to update region (RestSetSimMethod): Incorrect auth key.";
  880. }
  881. }
  882. catch (Exception e)
  883. {
  884. m_log.Warn("[GRID]: GetRegionPlugin Handle " + kvp.Key + " unable to add new sim: " +
  885. e.ToString());
  886. }
  887. }
  888. return "OK";
  889. }
  890. catch (Exception e)
  891. {
  892. return "ERROR! Could not save to database! (" + e.ToString() + ")";
  893. }
  894. }
  895. public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request)
  896. {
  897. XmlRpcResponse response = new XmlRpcResponse();
  898. Hashtable requestData = (Hashtable)request.Params[0];
  899. Hashtable responseData = new Hashtable();
  900. if (requestData.Contains("uri"))
  901. {
  902. string URI = (string)requestData["URI"];
  903. string sendkey = (string)requestData["sendkey"];
  904. string recvkey = (string)requestData["recvkey"];
  905. MessageServerInfo m = new MessageServerInfo();
  906. m.URI = URI;
  907. m.sendkey = sendkey;
  908. m.recvkey = recvkey;
  909. if (!_MessageServers.Contains(m))
  910. _MessageServers.Add(m);
  911. responseData["responsestring"] = "TRUE";
  912. response.Value = responseData;
  913. }
  914. return response;
  915. }
  916. public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request)
  917. {
  918. XmlRpcResponse response = new XmlRpcResponse();
  919. Hashtable requestData = (Hashtable)request.Params[0];
  920. Hashtable responseData = new Hashtable();
  921. if (requestData.Contains("uri"))
  922. {
  923. string URI = (string)requestData["uri"];
  924. string sendkey = (string)requestData["sendkey"];
  925. string recvkey = (string)requestData["recvkey"];
  926. MessageServerInfo m = new MessageServerInfo();
  927. m.URI = URI;
  928. m.sendkey = sendkey;
  929. m.recvkey = recvkey;
  930. if (_MessageServers.Contains(m))
  931. _MessageServers.Remove(m);
  932. responseData["responsestring"] = "TRUE";
  933. response.Value = responseData;
  934. }
  935. return response;
  936. }
  937. }
  938. }