PageRenderTime 59ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

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

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

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