PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Aurora/Services/SQLServices/GridService/GridService.cs

https://bitbucket.org/VirtualReality/async-sim-testing
C# | 1166 lines | 891 code | 150 blank | 125 comment | 226 complexity | 0a9f780ebc26511ebe2a5c0f45f9c922 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/, 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 Aurora-Sim 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 Aurora.Framework;
  28. using Aurora.Framework.ClientInterfaces;
  29. using Aurora.Framework.ConsoleFramework;
  30. using Aurora.Framework.Modules;
  31. using Aurora.Framework.Services;
  32. using Aurora.Framework.Services.ClassHelpers.Other;
  33. using Aurora.Framework.Utilities;
  34. using Nini.Config;
  35. using OpenMetaverse;
  36. using System;
  37. using System.Collections.Generic;
  38. using System.Linq;
  39. using GridRegion = Aurora.Framework.Services.GridRegion;
  40. using RegionFlags = Aurora.Framework.Services.RegionFlags;
  41. namespace Aurora.Services.SQLServices.GridService
  42. {
  43. public class GridService : ConnectorBase, IGridService, IService
  44. {
  45. #region Declares
  46. protected bool m_AllowDuplicateNames;
  47. protected bool m_AllowNewRegistrations = true;
  48. protected bool m_AllowNewRegistrationsWithPass = false;
  49. protected string m_RegisterRegionPassword = "";
  50. protected IRegionData m_Database;
  51. protected bool m_DisableRegistrations;
  52. protected bool m_UseSessionID = true;
  53. protected IConfigSource m_config;
  54. protected int m_maxRegionSize = 8192;
  55. protected int m_cachedMaxRegionSize = 0;
  56. protected int m_cachedRegionViewSize = 0;
  57. protected IRegistryCore m_registryCore;
  58. protected IAgentInfoService m_agentInfoService;
  59. private readonly Dictionary<UUID, List<GridRegion>> m_KnownNeighbors = new Dictionary<UUID, List<GridRegion>>();
  60. #endregion
  61. #region IService Members
  62. public virtual void Initialize(IConfigSource config, IRegistryCore registry)
  63. {
  64. IConfig handlerConfig = config.Configs["Handlers"];
  65. if (handlerConfig.GetString("GridHandler", "") != Name)
  66. return;
  67. //MainConsole.Instance.DebugFormat("[GRID SERVICE]: Starting...");
  68. Configure(config, registry);
  69. }
  70. public virtual void Configure(IConfigSource config, IRegistryCore registry)
  71. {
  72. m_config = config;
  73. IConfig gridConfig = config.Configs["GridService"];
  74. if (gridConfig != null)
  75. {
  76. m_DisableRegistrations = gridConfig.GetBoolean("DisableRegistrations", m_DisableRegistrations);
  77. m_AllowNewRegistrations = gridConfig.GetBoolean("AllowNewRegistrations", m_AllowNewRegistrations);
  78. m_AllowNewRegistrationsWithPass = gridConfig.GetBoolean("AllowNewRegistrationsWithPass",
  79. m_AllowNewRegistrationsWithPass);
  80. m_RegisterRegionPassword =
  81. Util.Md5Hash(gridConfig.GetString("RegisterRegionPassword", m_RegisterRegionPassword));
  82. m_maxRegionSize = gridConfig.GetInt("MaxRegionSize", m_maxRegionSize);
  83. m_cachedRegionViewSize = gridConfig.GetInt("RegionSightSize", m_cachedRegionViewSize);
  84. m_UseSessionID = !gridConfig.GetBoolean("DisableSessionID", !m_UseSessionID);
  85. m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames);
  86. }
  87. if (MainConsole.Instance != null)
  88. {
  89. MainConsole.Instance.Commands.AddCommand("show region",
  90. "show region [Region name]",
  91. "Show details on a region",
  92. HandleShowRegion);
  93. MainConsole.Instance.Commands.AddCommand("set region flags",
  94. "set region flags [Region name] [flags]",
  95. "Set database flags for region",
  96. HandleSetFlags);
  97. MainConsole.Instance.Commands.AddCommand("set region scope",
  98. "set region scope [Region name] [UUID]",
  99. "Set database scope for region",
  100. HandleSetScope);
  101. MainConsole.Instance.Commands.AddCommand("grid clear all regions",
  102. "grid clear all regions",
  103. "Clears all regions from the database",
  104. HandleClearAllRegions);
  105. MainConsole.Instance.Commands.AddCommand("grid clear down regions",
  106. "grid clear down regions",
  107. "Clears all regions that are offline from the database",
  108. HandleClearAllDownRegions);
  109. MainConsole.Instance.Commands.AddCommand("grid clear region",
  110. "grid clear region [RegionName]",
  111. "Clears the regions with the given name from the database",
  112. HandleClearRegion);
  113. MainConsole.Instance.Commands.AddCommand("grid enable region registration",
  114. "grid enable region registration",
  115. "Allows new regions to be registered with the grid",
  116. HandleRegionRegistration);
  117. MainConsole.Instance.Commands.AddCommand("grid disable region registration",
  118. "grid disable region registration",
  119. "Disallows new regions to be registered with the grid",
  120. HandleRegionRegistration);
  121. }
  122. registry.RegisterModuleInterface<IGridService>(this);
  123. Init(registry, Name, serverPath: "/grid/");
  124. }
  125. public virtual void Start(IConfigSource config, IRegistryCore registry)
  126. {
  127. m_registryCore = registry;
  128. m_Database = Framework.Utilities.DataManager.RequestPlugin<IRegionData>();
  129. m_agentInfoService = m_registryCore.RequestModuleInterface<IAgentInfoService>();
  130. }
  131. public virtual void FinishedStartup()
  132. {
  133. }
  134. public virtual string Name
  135. {
  136. get { return GetType().Name; }
  137. }
  138. #endregion
  139. #region IGridService Members
  140. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  141. public virtual int GetMaxRegionSize()
  142. {
  143. if (m_cachedMaxRegionSize != 0)
  144. return m_cachedMaxRegionSize;
  145. object remoteValue = DoRemoteByURL("GridServerURI");
  146. if (remoteValue != null || m_doRemoteOnly)
  147. {
  148. m_cachedMaxRegionSize = (int) remoteValue == 0 ? 8192 : (int) remoteValue;
  149. if ((int) remoteValue == 0) return 8192;
  150. return (int) remoteValue;
  151. }
  152. if (m_maxRegionSize == 0) return 8192;
  153. return m_maxRegionSize;
  154. }
  155. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  156. public virtual int GetRegionViewSize()
  157. {
  158. if (m_cachedRegionViewSize != 0)
  159. return m_cachedRegionViewSize;
  160. object remoteValue = DoRemoteByURL("GridServerURI");
  161. if (remoteValue != null && m_doRemoteOnly)
  162. {
  163. m_cachedRegionViewSize = (int) remoteValue;
  164. }
  165. else m_cachedRegionViewSize = 1;
  166. return m_cachedRegionViewSize;
  167. }
  168. public virtual IGridService InnerService
  169. {
  170. get { return this; }
  171. }
  172. /// <summary>
  173. /// Gets the default regions that people land in if they have no other region to enter
  174. /// </summary>
  175. /// <param name="scopeIDs"></param>
  176. /// <returns></returns>
  177. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  178. public virtual List<GridRegion> GetDefaultRegions(List<UUID> scopeIDs)
  179. {
  180. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs);
  181. if (remoteValue != null || m_doRemoteOnly)
  182. return (List<GridRegion>) remoteValue;
  183. List<GridRegion> regions = m_Database.GetDefaultRegions(scopeIDs);
  184. List<GridRegion> ret = regions.Where(r => (r.Flags & (int) RegionFlags.RegionOnline) != 0).ToList();
  185. MainConsole.Instance.DebugFormat("[GRID SERVICE]: GetDefaultRegions returning {0} regions", ret.Count);
  186. return ret;
  187. }
  188. /// <summary>
  189. /// Attempts to find regions that are good for the agent to login to if the default and fallback regions are down.
  190. /// </summary>
  191. /// <param name="scopeIDs"></param>
  192. /// <param name="x"></param>
  193. /// <param name="y"></param>
  194. /// <returns></returns>
  195. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  196. public virtual List<GridRegion> GetSafeRegions(List<UUID> scopeIDs, int x, int y)
  197. {
  198. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, x, y);
  199. if (remoteValue != null || m_doRemoteOnly)
  200. return (List<GridRegion>) remoteValue;
  201. return m_Database.GetSafeRegions(scopeIDs, x, y);
  202. }
  203. /// <summary>
  204. /// Tells the grid server that this region is not able to be connected to.
  205. /// This updates the down flag in the map and blocks it from becoming a 'safe' region fallback
  206. /// Only called by LLLoginService
  207. /// </summary>
  208. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  209. public virtual void SetRegionUnsafe(UUID id)
  210. {
  211. /*object remoteValue = DoRemoteByURL("GridServerURI", id);
  212. if (remoteValue != null || m_doRemoteOnly)
  213. return;*/
  214. GridRegion data = m_Database.Get(id, null);
  215. if (data == null)
  216. return;
  217. if ((data.Flags & (int) RegionFlags.Safe) == (int) RegionFlags.Safe)
  218. data.Flags &= ~(int) RegionFlags.Safe; //Remove only the safe var the first time
  219. else if ((data.Flags & (int) RegionFlags.RegionOnline) == (int) RegionFlags.RegionOnline)
  220. data.Flags &= ~(int) RegionFlags.RegionOnline; //Remove online the second time it fails
  221. m_Database.Store(data);
  222. }
  223. /// <summary>
  224. /// Tells the grid server that this region is able to be connected to.
  225. /// This updates the down flag in the map and allows it to become a 'safe' region fallback
  226. /// Only called by LLLoginService
  227. /// </summary>
  228. //[CanBeReflected(ThreatLevel = ThreatLevel.Full)]
  229. public virtual void SetRegionSafe(UUID id)
  230. {
  231. /*object remoteValue = DoRemoteByURL("GridServerURI", id);
  232. if (remoteValue != null || m_doRemoteOnly)
  233. return;*/
  234. GridRegion data = m_Database.Get(id, null);
  235. if (data == null)
  236. return;
  237. if ((data.Flags & (int) RegionFlags.Safe) == 0)
  238. data.Flags |= (int) RegionFlags.Safe;
  239. else if ((data.Flags & (int) RegionFlags.RegionOnline) == 0)
  240. data.Flags |= (int) RegionFlags.RegionOnline;
  241. m_Database.Store(data);
  242. }
  243. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  244. public virtual List<GridRegion> GetFallbackRegions(List<UUID> scopeIDs, int x, int y)
  245. {
  246. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, x, y);
  247. if (remoteValue != null || m_doRemoteOnly)
  248. return (List<GridRegion>) remoteValue;
  249. List<GridRegion> regions = m_Database.GetFallbackRegions(scopeIDs, x, y);
  250. List<GridRegion> ret = regions.Where(r => (r.Flags & (int) RegionFlags.RegionOnline) != 0).ToList();
  251. MainConsole.Instance.DebugFormat("[GRID SERVICE]: Fallback returned {0} regions", ret.Count);
  252. return ret;
  253. }
  254. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  255. public virtual int GetRegionFlags(List<UUID> scopeIDs, UUID regionID)
  256. {
  257. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, regionID);
  258. if (remoteValue != null || m_doRemoteOnly)
  259. return (int) remoteValue;
  260. GridRegion region = m_Database.Get(regionID, scopeIDs);
  261. if (region != null)
  262. {
  263. //MainConsole.Instance.DebugFormat("[GRID SERVICE]: Request for flags of {0}: {1}", regionID, flags);
  264. return region.Flags;
  265. }
  266. return -1;
  267. }
  268. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  269. public virtual multipleMapItemReply GetMapItems(List<UUID> scopeIDs, ulong regionHandle,
  270. GridItemType gridItemType)
  271. {
  272. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, regionHandle, gridItemType);
  273. if (remoteValue != null || m_doRemoteOnly)
  274. return (multipleMapItemReply) remoteValue;
  275. multipleMapItemReply allItems = new multipleMapItemReply();
  276. if (gridItemType == GridItemType.AgentLocations) //Grid server only cares about agent locations
  277. {
  278. int X, Y;
  279. Util.UlongToInts(regionHandle, out X, out Y);
  280. //Get the items and send them back
  281. allItems.items[regionHandle] = GetItems(scopeIDs, X, Y, regionHandle);
  282. }
  283. return allItems;
  284. }
  285. [CanBeReflected(ThreatLevel = ThreatLevel.None)]
  286. public virtual RegisterRegion RegisterRegion(GridRegion regionInfos, UUID oldSessionID, string password,
  287. int majorProtocolVersion, int minorProtocolVersion)
  288. {
  289. RegisterRegion rr = new RegisterRegion();
  290. object remoteValue = DoRemoteByURL("GridServerURI", regionInfos, oldSessionID, password,
  291. majorProtocolVersion, minorProtocolVersion);
  292. if (remoteValue != null || m_doRemoteOnly)
  293. {
  294. rr = (RegisterRegion) remoteValue;
  295. if (rr == null)
  296. rr = new RegisterRegion {Error = "Could not reach grid service."};
  297. return rr;
  298. }
  299. if (majorProtocolVersion < ProtocolVersion.MINIMUM_MAJOR_PROTOCOL_VERSION ||
  300. minorProtocolVersion < ProtocolVersion.MINIMUM_MINOR_PROTOCOL_VERSION)
  301. {
  302. return new RegisterRegion
  303. {
  304. Error =
  305. "You need to update your version of Aurora, the protocol version is too low to connect to this server."
  306. };
  307. }
  308. if (m_DisableRegistrations)
  309. return new RegisterRegion {Error = "Registrations are disabled."};
  310. UUID NeedToDeletePreviousRegion = UUID.Zero;
  311. //Get the range of this so that we get the full count and make sure that we are not overlapping smaller regions
  312. List<GridRegion> regions = m_Database.Get(regionInfos.RegionLocX - GetMaxRegionSize(),
  313. regionInfos.RegionLocY - GetMaxRegionSize(),
  314. regionInfos.RegionLocX + regionInfos.RegionSizeX - 1,
  315. regionInfos.RegionLocY + regionInfos.RegionSizeY - 1,
  316. null);
  317. if (regions.Any(r => (r.RegionLocX >= regionInfos.RegionLocX &&
  318. r.RegionLocX < regionInfos.RegionLocX + regionInfos.RegionSizeX) &&
  319. (r.RegionLocY >= regionInfos.RegionLocY &&
  320. r.RegionLocY < regionInfos.RegionLocY + regionInfos.RegionSizeY) &&
  321. r.RegionID != regionInfos.RegionID))
  322. {
  323. MainConsole.Instance.WarnFormat(
  324. "[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
  325. regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, regionInfos.ScopeID);
  326. return new RegisterRegion {Error = "Region overlaps another region"};
  327. }
  328. GridRegion region = m_Database.Get(regionInfos.RegionID, null);
  329. if (region != null)
  330. {
  331. //If we already have a session, we need to check it
  332. if (!VerifyRegionSessionID(region, oldSessionID))
  333. {
  334. MainConsole.Instance.WarnFormat(
  335. "[GRID SERVICE]: Region {0} called register, but the sessionID they provided is wrong!",
  336. region.RegionName);
  337. return new RegisterRegion {Error = "Wrong Session ID"};
  338. }
  339. }
  340. if ((!m_AllowNewRegistrations && region == null) && (!m_AllowNewRegistrationsWithPass))
  341. {
  342. MainConsole.Instance.WarnFormat(
  343. "[GRID SERVICE]: Region {0} tried to register but registrations are disabled.",
  344. regionInfos.RegionName);
  345. return new RegisterRegion {Error = "Registrations are disabled."};
  346. }
  347. if (region == null && m_AllowNewRegistrationsWithPass && password != m_RegisterRegionPassword)
  348. {
  349. MainConsole.Instance.WarnFormat(
  350. "[GRID SERVICE]: Region {0} tried to register but passwords didn't match.", regionInfos.RegionName);
  351. // don't want to leak info so just tell them its disabled
  352. return new RegisterRegion {Error = "Registrations are disabled."};
  353. }
  354. if (m_maxRegionSize != 0 &&
  355. (regionInfos.RegionSizeX > m_maxRegionSize || regionInfos.RegionSizeY > m_maxRegionSize))
  356. {
  357. //Too big... kick it out
  358. MainConsole.Instance.WarnFormat(
  359. "[GRID SERVICE]: Region {0} tried to register with too large of a size {1},{2}.",
  360. regionInfos.RegionName, regionInfos.RegionSizeX, regionInfos.RegionSizeY);
  361. return new RegisterRegion {Error = "Region is too large, reduce its size."};
  362. }
  363. if ((region != null) && (region.RegionID != regionInfos.RegionID))
  364. {
  365. MainConsole.Instance.WarnFormat(
  366. "[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
  367. regionInfos.RegionName, regionInfos.RegionLocX, regionInfos.RegionLocY, regionInfos.ScopeID);
  368. return new RegisterRegion {Error = "Region overlaps another region"};
  369. }
  370. if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
  371. ((region.RegionLocX != regionInfos.RegionLocX) || (region.RegionLocY != regionInfos.RegionLocY)))
  372. {
  373. if ((region.Flags & (int) RegionFlags.NoMove) != 0)
  374. return new RegisterRegion
  375. {
  376. Error =
  377. "Can't move this region," + region.RegionLocX + "," +
  378. region.RegionLocY
  379. };
  380. // Region reregistering in other coordinates. Delete the old entry
  381. MainConsole.Instance.DebugFormat(
  382. "[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
  383. regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
  384. NeedToDeletePreviousRegion = regionInfos.RegionID;
  385. }
  386. if (region != null)
  387. {
  388. // There is a preexisting record
  389. //
  390. // Get it's flags
  391. //
  392. RegionFlags rflags = (RegionFlags) region.Flags;
  393. // Is this a reservation?
  394. //
  395. if ((rflags & RegionFlags.Reservation) != 0)
  396. {
  397. // Regions reserved for the null key cannot be taken.
  398. if (region.SessionID == UUID.Zero)
  399. return new RegisterRegion {Error = "Region location is reserved"};
  400. // Treat it as an auth request
  401. //
  402. // NOTE: Fudging the flags value here, so these flags
  403. // should not be used elsewhere. Don't optimize
  404. // this with the later retrieval of the same flags!
  405. rflags |= RegionFlags.Authenticate;
  406. }
  407. }
  408. if (!m_AllowDuplicateNames)
  409. {
  410. List<GridRegion> dupe = m_Database.Get(regionInfos.RegionName, null, null, null);
  411. if (dupe != null && dupe.Count > 0)
  412. {
  413. if (dupe.Any(d => d.RegionID != regionInfos.RegionID))
  414. {
  415. MainConsole.Instance.WarnFormat(
  416. "[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
  417. regionInfos.RegionName, regionInfos.RegionID);
  418. return new RegisterRegion {Error = "Duplicate region name"};
  419. }
  420. }
  421. }
  422. if (region != null)
  423. {
  424. //If we are locked out, we can't come in
  425. if ((region.Flags & (int) RegionFlags.LockedOut) != 0)
  426. return new RegisterRegion {Error = "Region locked out"};
  427. //Remove the reservation if we are there now
  428. region.Flags &= ~(int) RegionFlags.Reservation;
  429. regionInfos.Flags = region.Flags; // Preserve flags
  430. //Preserve scopeIDs
  431. regionInfos.AllScopeIDs = region.AllScopeIDs;
  432. regionInfos.ScopeID = region.ScopeID;
  433. }
  434. else
  435. {
  436. //Regions do not get to set flags, so wipe them
  437. regionInfos.Flags = 0;
  438. //See if we are in the configs anywhere and have flags set
  439. IConfig gridConfig = m_config.Configs["GridService"];
  440. if ((gridConfig != null) && regionInfos.RegionName != string.Empty)
  441. {
  442. int newFlags = 0;
  443. string regionName = regionInfos.RegionName.Trim().Replace(' ', '_');
  444. newFlags = ParseFlags(newFlags, gridConfig.GetString("DefaultRegionFlags", String.Empty));
  445. newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + regionName, String.Empty));
  446. newFlags = ParseFlags(newFlags,
  447. gridConfig.GetString("Region_" + regionInfos.RegionHandle.ToString(),
  448. String.Empty));
  449. regionInfos.Flags = newFlags;
  450. }
  451. }
  452. //Set these so that we can make sure the region is online later
  453. regionInfos.Flags |= (int) RegionFlags.RegionOnline;
  454. regionInfos.Flags |= (int) RegionFlags.Safe;
  455. regionInfos.LastSeen = Util.UnixTimeSinceEpoch();
  456. //Update the sessionID, use the old so that we don't generate a bunch of these
  457. UUID SessionID = oldSessionID == UUID.Zero ? UUID.Random() : oldSessionID;
  458. regionInfos.SessionID = SessionID;
  459. // Everything is ok, let's register
  460. try
  461. {
  462. if (NeedToDeletePreviousRegion != UUID.Zero)
  463. m_Database.Delete(NeedToDeletePreviousRegion);
  464. if (m_Database.Store(regionInfos))
  465. {
  466. //Get the neighbors for them
  467. List<GridRegion> neighbors = GetNeighbors(null, regionInfos);
  468. FixNeighbors(regionInfos, neighbors, false);
  469. MainConsole.Instance.DebugFormat("[GRID SERVICE]: Region {0} registered successfully at {1}-{2}",
  470. regionInfos.RegionName, regionInfos.RegionLocX,
  471. regionInfos.RegionLocY);
  472. return new RegisterRegion
  473. {
  474. Error = "",
  475. Neighbors = neighbors,
  476. RegionFlags = regionInfos.Flags,
  477. SessionID = SessionID,
  478. Region = regionInfos
  479. };
  480. }
  481. }
  482. catch (Exception e)
  483. {
  484. MainConsole.Instance.WarnFormat("[GRID SERVICE]: Database exception: {0}", e);
  485. }
  486. return new RegisterRegion {Error = "Failed to save region into the database."};
  487. }
  488. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  489. public virtual string UpdateMap(GridRegion gregion, bool online)
  490. {
  491. object remoteValue = DoRemoteByURL("GridServerURI", gregion, online);
  492. if (remoteValue != null || m_doRemoteOnly)
  493. return (string) remoteValue;
  494. GridRegion region = m_Database.Get(gregion.RegionID, null);
  495. if (region != null)
  496. {
  497. if (!VerifyRegionSessionID(region, gregion.SessionID))
  498. {
  499. MainConsole.Instance.Warn(
  500. "[GRID SERVICE]: Region called UpdateMap, but provided incorrect SessionID! Possible attempt to disable a region!!");
  501. return "Wrong Session ID";
  502. }
  503. MainConsole.Instance.DebugFormat("[GRID SERVICE]: Region {0} updated its map", gregion.RegionID);
  504. m_Database.Delete(gregion.RegionID);
  505. if (online)
  506. {
  507. region.Flags |= (int) RegionFlags.RegionOnline;
  508. region.Flags |= (int) RegionFlags.Safe;
  509. }
  510. else
  511. {
  512. region.Flags &= ~(int) RegionFlags.RegionOnline;
  513. region.Flags &= ~(int) RegionFlags.Safe;
  514. }
  515. region.TerrainImage = gregion.TerrainImage;
  516. region.TerrainMapImage = gregion.TerrainMapImage;
  517. region.SessionID = gregion.SessionID;
  518. region.AllScopeIDs = gregion.AllScopeIDs;
  519. region.ScopeID = gregion.ScopeID;
  520. //Update all of these as well, as they are able to be set by the region owner
  521. region.EstateOwner = gregion.EstateOwner;
  522. region.Access = gregion.Access;
  523. region.ExternalHostName = gregion.ExternalHostName;
  524. region.HttpPort = gregion.HttpPort;
  525. region.RegionName = gregion.RegionName;
  526. region.RegionType = gregion.RegionType;
  527. region.ServerURI = gregion.ServerURI;
  528. try
  529. {
  530. region.LastSeen = Util.UnixTimeSinceEpoch();
  531. m_Database.Store(region);
  532. FixNeighbors(region, GetNeighbors(null, region), false);
  533. }
  534. catch (Exception e)
  535. {
  536. MainConsole.Instance.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
  537. }
  538. }
  539. return "";
  540. }
  541. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  542. public virtual bool DeregisterRegion(GridRegion gregion)
  543. {
  544. object remoteValue = DoRemoteByURL("GridServerURI", gregion);
  545. if (remoteValue != null || m_doRemoteOnly)
  546. return remoteValue != null && (bool) remoteValue;
  547. GridRegion region = m_Database.Get(gregion.RegionID, null);
  548. if (region == null)
  549. return false;
  550. if (!VerifyRegionSessionID(region, gregion.SessionID))
  551. {
  552. MainConsole.Instance.Warn(
  553. "[GRID SERVICE]: Region called deregister, but provided incorrect SessionID! Possible attempt to disable a region!!");
  554. return false;
  555. }
  556. MainConsole.Instance.DebugFormat("[GRID SERVICE]: Region {0} deregistered", region.RegionID);
  557. FixNeighbors(region, GetNeighbors(null, region), true);
  558. return m_Database.Delete(region.RegionID);
  559. }
  560. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  561. public virtual GridRegion GetRegionByUUID(List<UUID> scopeIDs, UUID regionID)
  562. {
  563. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, regionID);
  564. if (remoteValue != null || m_doRemoteOnly)
  565. return (GridRegion) remoteValue;
  566. return m_Database.Get(regionID, scopeIDs);
  567. }
  568. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  569. public virtual GridRegion GetRegionByPosition(List<UUID> scopeIDs, int x, int y)
  570. {
  571. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, x, y);
  572. if (remoteValue != null || m_doRemoteOnly)
  573. return (GridRegion) remoteValue;
  574. return m_Database.GetZero(x, y, scopeIDs);
  575. }
  576. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  577. public virtual GridRegion GetRegionByName(List<UUID> scopeIDs, string regionName)
  578. {
  579. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, regionName);
  580. if (remoteValue != null || m_doRemoteOnly)
  581. return (GridRegion) remoteValue;
  582. List<GridRegion> rdatas = m_Database.Get(regionName + "%", scopeIDs, 0, 1);
  583. if ((rdatas != null) && (rdatas.Count > 0))
  584. {
  585. //Sort to find the region with the exact name that was given
  586. rdatas.Sort(new RegionDataComparison(regionName));
  587. //Results are backwards... so it needs reversed
  588. rdatas.Reverse();
  589. return rdatas[0];
  590. }
  591. return null;
  592. }
  593. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  594. public virtual List<GridRegion> GetRegionsByName(List<UUID> scopeIDs, string name, uint? start, uint? count)
  595. {
  596. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, name, start, count);
  597. if (remoteValue != null || m_doRemoteOnly)
  598. return (List<GridRegion>) remoteValue;
  599. List<GridRegion> rdatas = m_Database.Get(name + "%", scopeIDs, start, count);
  600. if (rdatas != null)
  601. {
  602. //Sort to find the region with the exact name that was given
  603. rdatas.Sort(new RegionDataComparison(name));
  604. //Results are backwards... so it needs reversed
  605. rdatas.Reverse();
  606. }
  607. return rdatas;
  608. }
  609. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  610. public virtual uint GetRegionsByNameCount(List<UUID> scopeIDs, string name)
  611. {
  612. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, name);
  613. if (remoteValue != null || m_doRemoteOnly)
  614. return (uint) remoteValue;
  615. return m_Database.GetCount(name + "%", scopeIDs);
  616. }
  617. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  618. public virtual List<GridRegion> GetRegionRange(List<UUID> scopeIDs, int xmin, int xmax, int ymin, int ymax)
  619. {
  620. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, xmin, xmax, ymin, ymax);
  621. if (remoteValue != null || m_doRemoteOnly)
  622. return (List<GridRegion>) remoteValue;
  623. return m_Database.Get(xmin, ymin, xmax, ymax, scopeIDs);
  624. }
  625. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  626. public virtual List<GridRegion> GetRegionRange(List<UUID> scopeIDs, float centerX, float centerY,
  627. uint squareRangeFromCenterInMeters)
  628. {
  629. object remoteValue = DoRemoteByURL("GridServerURI", scopeIDs, centerX, centerY,
  630. squareRangeFromCenterInMeters);
  631. return (remoteValue != null || m_doRemoteOnly)
  632. ? (List<GridRegion>) remoteValue
  633. : m_Database.Get(scopeIDs, UUID.Zero, centerX, centerY, squareRangeFromCenterInMeters);
  634. }
  635. /// <summary>
  636. /// Get the cached list of neighbors or a new list
  637. /// </summary>
  638. /// <param name="scopeIDs"></param>
  639. /// <param name="region"></param>
  640. /// <returns></returns>
  641. [CanBeReflected(ThreatLevel = ThreatLevel.Low)]
  642. public virtual List<GridRegion> GetNeighbors(List<UUID> scopeIDs, GridRegion region)
  643. {
  644. object remoteValue = DoRemoteByURL("GridServerURI", region);
  645. if (remoteValue != null || m_doRemoteOnly)
  646. return (List<GridRegion>) remoteValue;
  647. List<GridRegion> neighbors = new List<GridRegion>();
  648. if (!m_KnownNeighbors.TryGetValue(region.RegionID, out neighbors))
  649. {
  650. neighbors = FindNewNeighbors(region);
  651. m_KnownNeighbors[region.RegionID] = neighbors;
  652. }
  653. GridRegion[] regions = new GridRegion[neighbors.Count];
  654. neighbors.CopyTo(regions);
  655. return AllScopeIDImpl.CheckScopeIDs(scopeIDs, new List<GridRegion>(regions));
  656. }
  657. #endregion
  658. #region Console Members
  659. private void HandleClearAllRegions(string[] cmd)
  660. {
  661. //Delete everything... give no criteria to just do 'delete from gridregions'
  662. m_Database.DeleteAll(new[] {"1"}, new object[] {1});
  663. MainConsole.Instance.Warn("[GridService]: Cleared all regions");
  664. }
  665. private void HandleClearRegion(string[] cmd)
  666. {
  667. if (cmd.Length <= 3)
  668. {
  669. MainConsole.Instance.Warn("Wrong syntax, please check the help function and try again");
  670. return;
  671. }
  672. string regionName = Util.CombineParams(cmd, 3);
  673. GridRegion r = GetRegionByName(null, regionName);
  674. if (r == null)
  675. {
  676. MainConsole.Instance.Warn("[GridService]: Region was not found");
  677. return;
  678. }
  679. m_Database.Delete(r.RegionID);
  680. MainConsole.Instance.Warn("[GridService]: Region was removed");
  681. }
  682. private void HandleRegionRegistration(string[] cmd)
  683. {
  684. bool enabled = cmd[1] == "enable";
  685. m_AllowNewRegistrations = enabled;
  686. IConfig gridConfig = m_config.Configs["GridService"];
  687. if (gridConfig != null)
  688. gridConfig.Set("AllowNewRegistrations", enabled);
  689. MainConsole.Instance.Info("[GridService]: Registrations have been " + (enabled ? "enabled" : "disabled") +
  690. " for new regions");
  691. }
  692. private void HandleClearAllDownRegions(string[] cmd)
  693. {
  694. //Delete any flags with (Flags & 254) == 254
  695. m_Database.DeleteAll(new[] {"Flags", "Flags", "Flags", "Flags"},
  696. new object[] {254, 267, 275, 296});
  697. MainConsole.Instance.Warn("[GridService]: Cleared all down regions");
  698. }
  699. private void HandleShowRegion(string[] cmd)
  700. {
  701. if (cmd.Length < 3)
  702. {
  703. MainConsole.Instance.Info("Syntax: show region <region name>");
  704. return;
  705. }
  706. string regionname = cmd[2];
  707. if (cmd.Length > 3)
  708. {
  709. for (int ii = 3; ii < cmd.Length; ii++)
  710. {
  711. regionname += " " + cmd[ii];
  712. }
  713. }
  714. List<GridRegion> regions = m_Database.Get(regionname, null, null, null);
  715. if (regions == null || regions.Count < 1)
  716. {
  717. MainConsole.Instance.Info("Region not found");
  718. return;
  719. }
  720. foreach (GridRegion r in regions)
  721. {
  722. MainConsole.Instance.Info(
  723. "-------------------------------------------------------------------------------");
  724. RegionFlags flags = (RegionFlags) Convert.ToInt32(r.Flags);
  725. MainConsole.Instance.Info("Region Name: " + r.RegionName);
  726. MainConsole.Instance.Info("Region UUID: " + r.RegionID);
  727. MainConsole.Instance.Info("Region ScopeID: " + r.ScopeID);
  728. MainConsole.Instance.Info("Region Location: " + String.Format("{0},{1}", r.RegionLocX, r.RegionLocY));
  729. MainConsole.Instance.Info("Region URI: " + r.ServerURI);
  730. MainConsole.Instance.Info("Region Owner: " + r.EstateOwner);
  731. MainConsole.Instance.Info("Region Flags: " + flags);
  732. MainConsole.Instance.Info(
  733. "-------------------------------------------------------------------------------");
  734. }
  735. }
  736. private int ParseFlags(int prev, string flags)
  737. {
  738. RegionFlags f = (RegionFlags) prev;
  739. string[] parts = flags.Split(new[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
  740. foreach (string p in parts)
  741. {
  742. try
  743. {
  744. int val;
  745. if (p.StartsWith("+"))
  746. {
  747. val = (int) Enum.Parse(typeof (RegionFlags), p.Substring(1));
  748. f |= (RegionFlags) val;
  749. }
  750. else if (p.StartsWith("-"))
  751. {
  752. val = (int) Enum.Parse(typeof (RegionFlags), p.Substring(1));
  753. f &= ~(RegionFlags) val;
  754. }
  755. else
  756. {
  757. val = (int) Enum.Parse(typeof (RegionFlags), p);
  758. f |= (RegionFlags) val;
  759. }
  760. }
  761. catch (Exception)
  762. {
  763. MainConsole.Instance.Info("Error in flag specification: " + p);
  764. }
  765. }
  766. return (int) f;
  767. }
  768. private void HandleSetFlags(string[] cmd)
  769. {
  770. if (cmd.Length < 5)
  771. {
  772. MainConsole.Instance.Info("Syntax: set region flags <region name> <flags>");
  773. return;
  774. }
  775. string regionname = cmd[3];
  776. if (cmd.Length > 5)
  777. {
  778. for (int ii = 4; ii < cmd.Length - 1; ii++)
  779. {
  780. regionname += " " + cmd[ii];
  781. }
  782. }
  783. List<GridRegion> regions = m_Database.Get(regionname, null, null, null);
  784. if (regions == null || regions.Count < 1)
  785. {
  786. MainConsole.Instance.Info("Region not found");
  787. return;
  788. }
  789. foreach (GridRegion r in regions)
  790. {
  791. int flags = r.Flags;
  792. flags = ParseFlags(flags, cmd[cmd.Length - 1]);
  793. r.Flags = flags;
  794. RegionFlags f = (RegionFlags) flags;
  795. MainConsole.Instance.Info(String.Format("Set region {0} to {1}", r.RegionName, f));
  796. m_Database.Store(r);
  797. }
  798. }
  799. private void HandleSetScope(string[] cmd)
  800. {
  801. if (cmd.Length < 5)
  802. {
  803. MainConsole.Instance.Info("Syntax: set region scope <region name> <UUID>");
  804. return;
  805. }
  806. string regionname = cmd[3];
  807. if (cmd.Length > 5)
  808. {
  809. for (int ii = 4; ii < cmd.Length - 1; ii++)
  810. {
  811. regionname += " " + cmd[ii];
  812. }
  813. }
  814. List<GridRegion> regions = m_Database.Get(regionname, null, null, null);
  815. if (regions == null || regions.Count < 1)
  816. {
  817. MainConsole.Instance.Info("Region not found");
  818. return;
  819. }
  820. foreach (GridRegion r in regions)
  821. {
  822. r.ScopeID = UUID.Parse(cmd[cmd.Length - 1]);
  823. MainConsole.Instance.Info(String.Format("Set region {0} to {1}", r.RegionName, r.ScopeID));
  824. m_Database.Store(r);
  825. }
  826. }
  827. #endregion
  828. #region Helpers
  829. /// <summary>
  830. /// Normalize the current float to the nearest block of 5 meters
  831. /// </summary>
  832. /// <param name="number"></param>
  833. /// <returns></returns>
  834. private float NormalizePosition(float number)
  835. {
  836. try
  837. {
  838. if (float.IsNaN(number))
  839. return 0;
  840. if (float.IsInfinity(number))
  841. return 0;
  842. if (number < 0)
  843. number = 0;
  844. double n = Math.Round(number, 0); //Remove the decimal
  845. string Number = n.ToString(); //Round the last
  846. string first = Number.Remove(Number.Length - 1);
  847. if (first == "")
  848. return 0;
  849. int FirstNumber = 0;
  850. FirstNumber = first.StartsWith(".") ? 0 : int.Parse(first);
  851. string endNumber = Number.Remove(0, Number.Length - 1);
  852. if (endNumber == "")
  853. return 0;
  854. float EndNumber = float.Parse(endNumber);
  855. if (EndNumber < 2.5f)
  856. EndNumber = 0;
  857. else if (EndNumber > 7.5)
  858. {
  859. EndNumber = 0;
  860. FirstNumber++;
  861. }
  862. else
  863. EndNumber = 5;
  864. return float.Parse(FirstNumber + EndNumber.ToString());
  865. }
  866. catch (Exception ex)
  867. {
  868. MainConsole.Instance.Error("[GridService]: Error in NormalizePosition " + ex);
  869. }
  870. return 0;
  871. }
  872. /// <summary>
  873. /// Get all agent locations for the given region
  874. /// </summary>
  875. /// <param name="scopeIDs"></param>
  876. /// <param name="X"></param>
  877. /// <param name="Y"></param>
  878. /// <param name="regionHandle"></param>
  879. /// <returns></returns>
  880. private List<mapItemReply> GetItems(List<UUID> scopeIDs, int X, int Y, ulong regionHandle)
  881. {
  882. List<mapItemReply> mapItems = new List<mapItemReply>();
  883. GridRegion region = GetRegionByPosition(scopeIDs, X, Y);
  884. //if the region is down or doesn't exist, don't check it
  885. if (region == null)
  886. return new List<mapItemReply>();
  887. Dictionary<Vector3, int> Positions = new Dictionary<Vector3, int>();
  888. //Get a list of all the clients in the region and add them
  889. List<UserInfo> userInfos = m_agentInfoService.GetUserInfos(region.RegionID);
  890. foreach (UserInfo userInfo in userInfos)
  891. {
  892. //Normalize the positions to 5 meter blocks so that agents stack instead of cover up each other
  893. Vector3 position = new Vector3(NormalizePosition(userInfo.CurrentPosition.X),
  894. NormalizePosition(userInfo.CurrentPosition.Y), 0);
  895. int Number = 0;
  896. //Find the number of agents currently at this position
  897. if (!Positions.TryGetValue(position, out Number))
  898. Number = 0;
  899. Number++;
  900. Positions[position] = Number;
  901. }
  902. //Build the mapItemReply blocks
  903. mapItems = Positions.Select(position => new mapItemReply
  904. {
  905. x =
  906. (uint)
  907. (region.RegionLocX + position.Key.X),
  908. y =
  909. (uint)
  910. (region.RegionLocY + position.Key.Y),
  911. id = UUID.Zero,
  912. name =
  913. Util.Md5Hash(region.RegionName +
  914. Environment.TickCount.
  915. ToString()),
  916. Extra = position.Value,
  917. Extra2 = 0
  918. }).ToList();
  919. //If there are no agents, we send one blank one to the client
  920. if (mapItems.Count == 0)
  921. {
  922. mapItemReply mapitem = new mapItemReply
  923. {
  924. x = (uint) (region.RegionLocX + 1),
  925. y = (uint) (region.RegionLocY + 1),
  926. id = UUID.Zero,
  927. name = Util.Md5Hash(region.RegionName + Environment.TickCount.ToString()),
  928. Extra = 0,
  929. Extra2 = 0
  930. };
  931. mapItems.Add(mapitem);
  932. }
  933. return mapItems;
  934. }
  935. private void FixNeighbors(GridRegion regionInfos, List<GridRegion> neighbors, bool down)
  936. {
  937. ISyncMessagePosterService postService = m_registryCore.RequestModuleInterface<ISyncMessagePosterService>();
  938. foreach (GridRegion r in neighbors)
  939. {
  940. if (m_KnownNeighbors.ContainsKey(r.RegionID))
  941. {
  942. //Add/Remove them to/from the list
  943. if (down)
  944. m_KnownNeighbors[r.RegionID].Remove(regionInfos);

Large files files are truncated, but you can click here to view the full file