HGGridConnector.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.Net;
  30. using System.Reflection;
  31. using System.Xml;
  32. using OpenSim.Framework.Communications.Cache;
  33. using OpenSim.Framework;
  34. using OpenSim.Region.Framework.Interfaces;
  35. using OpenSim.Region.Framework.Scenes;
  36. using OpenSim.Region.Framework.Scenes.Hypergrid;
  37. using OpenSim.Services.Interfaces;
  38. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  39. using OpenSim.Server.Base;
  40. using OpenSim.Services.Connectors.Grid;
  41. using OpenSim.Framework.Console;
  42. using OpenMetaverse;
  43. using log4net;
  44. using Nini.Config;
  45. namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid
  46. {
  47. public class HGGridConnector : ISharedRegionModule, IGridService, IHyperlinkService
  48. {
  49. private static readonly ILog m_log =
  50. LogManager.GetLogger(
  51. MethodBase.GetCurrentMethod().DeclaringType);
  52. private static string LocalAssetServerURI, LocalInventoryServerURI, LocalUserServerURI;
  53. private bool m_Enabled = false;
  54. private bool m_Initialized = false;
  55. private Scene m_aScene;
  56. private Dictionary<ulong, Scene> m_LocalScenes = new Dictionary<ulong, Scene>();
  57. private IGridService m_GridServiceConnector;
  58. private HypergridServiceConnector m_HypergridServiceConnector;
  59. // Hyperlink regions are hyperlinks on the map
  60. protected Dictionary<UUID, GridRegion> m_HyperlinkRegions = new Dictionary<UUID, GridRegion>();
  61. // Known regions are home regions of visiting foreign users.
  62. // They are not on the map as static hyperlinks. They are dynamic hyperlinks, they go away when
  63. // the visitor goes away. They are mapped to X=0 on the map.
  64. // This is key-ed on agent ID
  65. protected Dictionary<UUID, GridRegion> m_knownRegions = new Dictionary<UUID, GridRegion>();
  66. protected Dictionary<UUID, ulong> m_HyperlinkHandles = new Dictionary<UUID, ulong>();
  67. #region ISharedRegionModule
  68. public Type ReplaceableInterface
  69. {
  70. get { return null; }
  71. }
  72. public string Name
  73. {
  74. get { return "HGGridServicesConnector"; }
  75. }
  76. public void Initialise(IConfigSource source)
  77. {
  78. IConfig moduleConfig = source.Configs["Modules"];
  79. if (moduleConfig != null)
  80. {
  81. string name = moduleConfig.GetString("GridServices", "");
  82. if (name == Name)
  83. {
  84. IConfig gridConfig = source.Configs["GridService"];
  85. if (gridConfig == null)
  86. {
  87. m_log.Error("[HGGRID CONNECTOR]: GridService missing from OpenSim.ini");
  88. return;
  89. }
  90. InitialiseConnectorModule(source);
  91. m_Enabled = true;
  92. m_log.Info("[HGGRID CONNECTOR]: HG grid enabled");
  93. }
  94. }
  95. }
  96. private void InitialiseConnectorModule(IConfigSource source)
  97. {
  98. IConfig gridConfig = source.Configs["GridService"];
  99. if (gridConfig == null)
  100. {
  101. m_log.Error("[HGGRID CONNECTOR]: GridService missing from OpenSim.ini");
  102. throw new Exception("Grid connector init error");
  103. }
  104. string module = gridConfig.GetString("GridServiceConnectorModule", String.Empty);
  105. if (module == String.Empty)
  106. {
  107. m_log.Error("[HGGRID CONNECTOR]: No GridServiceConnectorModule named in section GridService");
  108. //return;
  109. throw new Exception("Unable to proceed. Please make sure your ini files in config-include are updated according to .example's");
  110. }
  111. Object[] args = new Object[] { source };
  112. m_GridServiceConnector = ServerUtils.LoadPlugin<IGridService>(module, args);
  113. }
  114. public void PostInitialise()
  115. {
  116. if (m_Enabled)
  117. ((ISharedRegionModule)m_GridServiceConnector).PostInitialise();
  118. }
  119. public void Close()
  120. {
  121. }
  122. public void AddRegion(Scene scene)
  123. {
  124. if (!m_Enabled)
  125. return;
  126. m_LocalScenes[scene.RegionInfo.RegionHandle] = scene;
  127. scene.RegisterModuleInterface<IGridService>(this);
  128. scene.RegisterModuleInterface<IHyperlinkService>(this);
  129. ((ISharedRegionModule)m_GridServiceConnector).AddRegion(scene);
  130. // Yikes!! Remove this as soon as user services get refactored
  131. LocalAssetServerURI = scene.CommsManager.NetworkServersInfo.AssetURL;
  132. LocalInventoryServerURI = scene.CommsManager.NetworkServersInfo.InventoryURL;
  133. LocalUserServerURI = scene.CommsManager.NetworkServersInfo.UserURL;
  134. HGNetworkServersInfo.Init(LocalAssetServerURI, LocalInventoryServerURI, LocalUserServerURI);
  135. }
  136. public void RemoveRegion(Scene scene)
  137. {
  138. if (m_Enabled)
  139. {
  140. m_LocalScenes.Remove(scene.RegionInfo.RegionHandle);
  141. ((ISharedRegionModule)m_GridServiceConnector).RemoveRegion(scene);
  142. }
  143. }
  144. public void RegionLoaded(Scene scene)
  145. {
  146. if (!m_Enabled)
  147. return;
  148. if (!m_Initialized)
  149. {
  150. m_aScene = scene;
  151. m_HypergridServiceConnector = new HypergridServiceConnector(scene.AssetService);
  152. HGCommands hgCommands = new HGCommands(this, scene);
  153. MainConsole.Instance.Commands.AddCommand("HGGridServicesConnector", false, "link-region",
  154. "link-region <Xloc> <Yloc> <HostName>:<HttpPort>[:<RemoteRegionName>] <cr>",
  155. "Link a hypergrid region", hgCommands.RunCommand);
  156. MainConsole.Instance.Commands.AddCommand("HGGridServicesConnector", false, "unlink-region",
  157. "unlink-region <local name> or <HostName>:<HttpPort> <cr>",
  158. "Unlink a hypergrid region", hgCommands.RunCommand);
  159. MainConsole.Instance.Commands.AddCommand("HGGridServicesConnector", false, "link-mapping", "link-mapping [<x> <y>] <cr>",
  160. "Set local coordinate to map HG regions to", hgCommands.RunCommand);
  161. m_Initialized = true;
  162. }
  163. }
  164. #endregion
  165. #region IGridService
  166. public bool RegisterRegion(UUID scopeID, GridRegion regionInfo)
  167. {
  168. // Region doesn't exist here. Trying to link remote region
  169. if (regionInfo.RegionID.Equals(UUID.Zero))
  170. {
  171. m_log.Info("[HGrid]: Linking remote region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort);
  172. ulong regionHandle = 0;
  173. regionInfo.RegionID = m_HypergridServiceConnector.LinkRegion(regionInfo, out regionHandle);
  174. if (!regionInfo.RegionID.Equals(UUID.Zero))
  175. {
  176. AddHyperlinkRegion(regionInfo, regionHandle);
  177. m_log.Info("[HGrid]: Successfully linked to region_uuid " + regionInfo.RegionID);
  178. // Try get the map image
  179. m_HypergridServiceConnector.GetMapImage(regionInfo);
  180. return true;
  181. }
  182. else
  183. {
  184. m_log.Info("[HGrid]: No such region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "(" + regionInfo.InternalEndPoint.Port + ")");
  185. return false;
  186. }
  187. // Note that these remote regions aren't registered in localBackend, so return null, no local listeners
  188. }
  189. else // normal grid
  190. return m_GridServiceConnector.RegisterRegion(scopeID, regionInfo);
  191. }
  192. public bool DeregisterRegion(UUID regionID)
  193. {
  194. // Try the hyperlink collection
  195. if (m_HyperlinkRegions.ContainsKey(regionID))
  196. {
  197. RemoveHyperlinkRegion(regionID);
  198. return true;
  199. }
  200. // Try the foreign users home collection
  201. foreach (GridRegion r in m_knownRegions.Values)
  202. if (r.RegionID == regionID)
  203. {
  204. RemoveHyperlinkHomeRegion(regionID);
  205. return true;
  206. }
  207. // Finally, try the normal route
  208. return m_GridServiceConnector.DeregisterRegion(regionID);
  209. }
  210. public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
  211. {
  212. // No serving neighbours on hyperliked regions.
  213. // Just the regular regions.
  214. return m_GridServiceConnector.GetNeighbours(scopeID, regionID);
  215. }
  216. public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
  217. {
  218. // Try the hyperlink collection
  219. if (m_HyperlinkRegions.ContainsKey(regionID))
  220. return m_HyperlinkRegions[regionID];
  221. // Try the foreign users home collection
  222. foreach (GridRegion r in m_knownRegions.Values)
  223. if (r.RegionID == regionID)
  224. return r;
  225. // Finally, try the normal route
  226. return m_GridServiceConnector.GetRegionByUUID(scopeID, regionID);
  227. }
  228. public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
  229. {
  230. int snapX = (int) (x / Constants.RegionSize) * (int)Constants.RegionSize;
  231. int snapY = (int) (y / Constants.RegionSize) * (int)Constants.RegionSize;
  232. // Try the hyperlink collection
  233. foreach (GridRegion r in m_HyperlinkRegions.Values)
  234. {
  235. if ((r.RegionLocX == snapX) && (r.RegionLocY == snapY))
  236. return r;
  237. }
  238. // Try the foreign users home collection
  239. foreach (GridRegion r in m_knownRegions.Values)
  240. {
  241. if ((r.RegionLocX == snapX) && (r.RegionLocY == snapY))
  242. {
  243. return r;
  244. }
  245. }
  246. // Finally, try the normal route
  247. return m_GridServiceConnector.GetRegionByPosition(scopeID, x, y);
  248. }
  249. public GridRegion GetRegionByName(UUID scopeID, string regionName)
  250. {
  251. // Try normal grid first
  252. GridRegion region = m_GridServiceConnector.GetRegionByName(scopeID, regionName);
  253. if (region != null)
  254. return region;
  255. // Try the hyperlink collection
  256. foreach (GridRegion r in m_HyperlinkRegions.Values)
  257. {
  258. if (r.RegionName == regionName)
  259. return r;
  260. }
  261. // Try the foreign users home collection
  262. foreach (GridRegion r in m_knownRegions.Values)
  263. {
  264. if (r.RegionName == regionName)
  265. return r;
  266. }
  267. return null;
  268. }
  269. public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
  270. {
  271. List<GridRegion> rinfos = new List<GridRegion>();
  272. if (name == string.Empty)
  273. return rinfos;
  274. foreach (GridRegion r in m_HyperlinkRegions.Values)
  275. if ((r.RegionName != null) && r.RegionName.ToLower().StartsWith(name.ToLower()))
  276. rinfos.Add(r);
  277. rinfos.AddRange(m_GridServiceConnector.GetRegionsByName(scopeID, name, maxNumber));
  278. return rinfos;
  279. }
  280. public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
  281. {
  282. int snapXmin = (int)(xmin / Constants.RegionSize) * (int)Constants.RegionSize;
  283. // int snapXmax = (int)(xmax / Constants.RegionSize) * (int)Constants.RegionSize;
  284. int snapYmin = (int)(ymin / Constants.RegionSize) * (int)Constants.RegionSize;
  285. int snapYmax = (int)(ymax / Constants.RegionSize) * (int)Constants.RegionSize;
  286. List<GridRegion> rinfos = new List<GridRegion>();
  287. foreach (GridRegion r in m_HyperlinkRegions.Values)
  288. if ((r.RegionLocX > snapXmin) && (r.RegionLocX < snapYmax) &&
  289. (r.RegionLocY > snapYmin) && (r.RegionLocY < snapYmax))
  290. rinfos.Add(r);
  291. rinfos.AddRange(m_GridServiceConnector.GetRegionRange(scopeID, xmin, xmax, ymin, ymax));
  292. return rinfos;
  293. }
  294. #endregion
  295. #region Auxiliary
  296. private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
  297. {
  298. m_HyperlinkRegions[regionInfo.RegionID] = regionInfo;
  299. m_HyperlinkHandles[regionInfo.RegionID] = regionHandle;
  300. }
  301. private void RemoveHyperlinkRegion(UUID regionID)
  302. {
  303. m_HyperlinkRegions.Remove(regionID);
  304. m_HyperlinkHandles.Remove(regionID);
  305. }
  306. private void AddHyperlinkHomeRegion(UUID userID, GridRegion regionInfo, ulong regionHandle)
  307. {
  308. m_knownRegions[userID] = regionInfo;
  309. m_HyperlinkHandles[regionInfo.RegionID] = regionHandle;
  310. }
  311. private void RemoveHyperlinkHomeRegion(UUID regionID)
  312. {
  313. foreach (KeyValuePair<UUID, GridRegion> kvp in m_knownRegions)
  314. {
  315. if (kvp.Value.RegionID == regionID)
  316. {
  317. m_knownRegions.Remove(kvp.Key);
  318. }
  319. }
  320. m_HyperlinkHandles.Remove(regionID);
  321. }
  322. #endregion
  323. #region IHyperlinkService
  324. private static Random random = new Random();
  325. public GridRegion TryLinkRegionToCoords(Scene m_scene, IClientAPI client, string mapName, int xloc, int yloc)
  326. {
  327. string host = "127.0.0.1";
  328. string portstr;
  329. string regionName = "";
  330. uint port = 9000;
  331. string[] parts = mapName.Split(new char[] { ':' });
  332. if (parts.Length >= 1)
  333. {
  334. host = parts[0];
  335. }
  336. if (parts.Length >= 2)
  337. {
  338. portstr = parts[1];
  339. //m_log.Debug("-- port = " + portstr);
  340. if (!UInt32.TryParse(portstr, out port))
  341. regionName = parts[1];
  342. }
  343. // always take the last one
  344. if (parts.Length >= 3)
  345. {
  346. regionName = parts[2];
  347. }
  348. // Sanity check. Don't ever link to this sim.
  349. IPAddress ipaddr = null;
  350. try
  351. {
  352. ipaddr = Util.GetHostFromDNS(host);
  353. }
  354. catch { }
  355. if ((ipaddr != null) &&
  356. !((m_scene.RegionInfo.ExternalEndPoint.Address.Equals(ipaddr)) && (m_scene.RegionInfo.HttpPort == port)))
  357. {
  358. GridRegion regInfo;
  359. bool success = TryCreateLink(m_scene, client, xloc, yloc, regionName, port, host, out regInfo);
  360. if (success)
  361. {
  362. regInfo.RegionName = mapName;
  363. return regInfo;
  364. }
  365. }
  366. return null;
  367. }
  368. // From the map search and secondlife://blah
  369. public GridRegion TryLinkRegion(Scene m_scene, IClientAPI client, string mapName)
  370. {
  371. int xloc = random.Next(0, Int16.MaxValue) * (int) Constants.RegionSize;
  372. return TryLinkRegionToCoords(m_scene, client, mapName, xloc, 0);
  373. }
  374. public bool TryCreateLink(Scene m_scene, IClientAPI client, int xloc, int yloc,
  375. string externalRegionName, uint externalPort, string externalHostName, out GridRegion regInfo)
  376. {
  377. m_log.DebugFormat("[HGrid]: Link to {0}:{1}, in {2}-{3}", externalHostName, externalPort, xloc, yloc);
  378. regInfo = new GridRegion();
  379. regInfo.RegionName = externalRegionName;
  380. regInfo.HttpPort = externalPort;
  381. regInfo.ExternalHostName = externalHostName;
  382. regInfo.RegionLocX = xloc;
  383. regInfo.RegionLocY = yloc;
  384. try
  385. {
  386. regInfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)0);
  387. }
  388. catch (Exception e)
  389. {
  390. m_log.Warn("[HGrid]: Wrong format for link-region: " + e.Message);
  391. return false;
  392. }
  393. // Finally, link it
  394. if (!RegisterRegion(UUID.Zero, regInfo))
  395. {
  396. m_log.Warn("[HGrid]: Unable to link region");
  397. return false;
  398. }
  399. int x, y;
  400. if (!Check4096(m_scene, regInfo, out x, out y))
  401. {
  402. DeregisterRegion(regInfo.RegionID);
  403. if (client != null)
  404. client.SendAlertMessage("Region is too far (" + x + ", " + y + ")");
  405. m_log.Info("[HGrid]: Unable to link, region is too far (" + x + ", " + y + ")");
  406. return false;
  407. }
  408. if (!CheckCoords(m_scene.RegionInfo.RegionLocX, m_scene.RegionInfo.RegionLocY, x, y))
  409. {
  410. DeregisterRegion(regInfo.RegionID);
  411. if (client != null)
  412. client.SendAlertMessage("Region has incompatible coordinates (" + x + ", " + y + ")");
  413. m_log.Info("[HGrid]: Unable to link, region has incompatible coordinates (" + x + ", " + y + ")");
  414. return false;
  415. }
  416. m_log.Debug("[HGrid]: link region succeeded");
  417. return true;
  418. }
  419. public bool TryUnlinkRegion(Scene m_scene, string mapName)
  420. {
  421. GridRegion regInfo = null;
  422. if (mapName.Contains(":"))
  423. {
  424. string host = "127.0.0.1";
  425. //string portstr;
  426. //string regionName = "";
  427. uint port = 9000;
  428. string[] parts = mapName.Split(new char[] { ':' });
  429. if (parts.Length >= 1)
  430. {
  431. host = parts[0];
  432. }
  433. // if (parts.Length >= 2)
  434. // {
  435. // portstr = parts[1];
  436. // if (!UInt32.TryParse(portstr, out port))
  437. // regionName = parts[1];
  438. // }
  439. // always take the last one
  440. // if (parts.Length >= 3)
  441. // {
  442. // regionName = parts[2];
  443. // }
  444. foreach (GridRegion r in m_HyperlinkRegions.Values)
  445. if (host.Equals(r.ExternalHostName) && (port == r.HttpPort))
  446. regInfo = r;
  447. }
  448. else
  449. {
  450. foreach (GridRegion r in m_HyperlinkRegions.Values)
  451. if (r.RegionName.Equals(mapName))
  452. regInfo = r;
  453. }
  454. if (regInfo != null)
  455. {
  456. return DeregisterRegion(regInfo.RegionID);
  457. }
  458. else
  459. {
  460. m_log.InfoFormat("[HGrid]: Region {0} not found", mapName);
  461. return false;
  462. }
  463. }
  464. /// <summary>
  465. /// Cope with this viewer limitation.
  466. /// </summary>
  467. /// <param name="regInfo"></param>
  468. /// <returns></returns>
  469. public bool Check4096(Scene m_scene, GridRegion regInfo, out int x, out int y)
  470. {
  471. ulong realHandle = m_HyperlinkHandles[regInfo.RegionID];
  472. uint ux = 0, uy = 0;
  473. Utils.LongToUInts(realHandle, out ux, out uy);
  474. x = (int)(ux / Constants.RegionSize);
  475. y = (int)(uy / Constants.RegionSize);
  476. if ((Math.Abs((int)m_scene.RegionInfo.RegionLocX - x) >= 4096) ||
  477. (Math.Abs((int)m_scene.RegionInfo.RegionLocY - y) >= 4096))
  478. {
  479. return false;
  480. }
  481. return true;
  482. }
  483. public bool CheckCoords(uint thisx, uint thisy, int x, int y)
  484. {
  485. if ((thisx == x) && (thisy == y))
  486. return false;
  487. return true;
  488. }
  489. public GridRegion TryLinkRegion(IClientAPI client, string regionDescriptor)
  490. {
  491. return TryLinkRegion((Scene)client.Scene, client, regionDescriptor);
  492. }
  493. public GridRegion GetHyperlinkRegion(ulong handle)
  494. {
  495. foreach (GridRegion r in m_HyperlinkRegions.Values)
  496. if (r.RegionHandle == handle)
  497. return r;
  498. foreach (GridRegion r in m_knownRegions.Values)
  499. if (r.RegionHandle == handle)
  500. return r;
  501. return null;
  502. }
  503. public ulong FindRegionHandle(ulong handle)
  504. {
  505. foreach (GridRegion r in m_HyperlinkRegions.Values)
  506. if ((r.RegionHandle == handle) && (m_HyperlinkHandles.ContainsKey(r.RegionID)))
  507. return m_HyperlinkHandles[r.RegionID];
  508. foreach (GridRegion r in m_knownRegions.Values)
  509. if ((r.RegionHandle == handle) && (m_HyperlinkHandles.ContainsKey(r.RegionID)))
  510. return m_HyperlinkHandles[r.RegionID];
  511. return handle;
  512. }
  513. public bool SendUserInformation(GridRegion regInfo, AgentCircuitData agentData)
  514. {
  515. CachedUserInfo uinfo = m_aScene.CommsManager.UserProfileCacheService.GetUserDetails(agentData.AgentID);
  516. if (uinfo == null)
  517. return false;
  518. if ((IsLocalUser(uinfo) && (GetHyperlinkRegion(regInfo.RegionHandle) != null)) ||
  519. (!IsLocalUser(uinfo) && !IsGoingHome(uinfo, regInfo)))
  520. {
  521. m_log.Info("[HGrid]: Local user is going to foreign region or foreign user is going elsewhere");
  522. // Set the position of the region on the remote grid
  523. // ulong realHandle = FindRegionHandle(regInfo.RegionHandle);
  524. uint x = 0, y = 0;
  525. Utils.LongToUInts(regInfo.RegionHandle, out x, out y);
  526. GridRegion clonedRegion = new GridRegion(regInfo);
  527. clonedRegion.RegionLocX = (int)x;
  528. clonedRegion.RegionLocY = (int)y;
  529. // Get the user's home region information and adapt the region handle
  530. GridRegion home = GetRegionByUUID(m_aScene.RegionInfo.ScopeID, uinfo.UserProfile.HomeRegionID);
  531. if (m_HyperlinkHandles.ContainsKey(uinfo.UserProfile.HomeRegionID))
  532. {
  533. ulong realHandle = m_HyperlinkHandles[uinfo.UserProfile.HomeRegionID];
  534. Utils.LongToUInts(realHandle, out x, out y);
  535. m_log.DebugFormat("[HGrid]: Foreign user is going elsewhere. Adjusting home handle from {0}-{1} to {2}-{3}", home.RegionLocX, home.RegionLocY, x, y);
  536. home.RegionLocX = (int)x;
  537. home.RegionLocY = (int)y;
  538. }
  539. // Get the user's service URLs
  540. string serverURI = "";
  541. if (uinfo.UserProfile is ForeignUserProfileData)
  542. serverURI = Util.ServerURI(((ForeignUserProfileData)uinfo.UserProfile).UserServerURI);
  543. string userServer = (serverURI == "") || (serverURI == null) ? LocalUserServerURI : serverURI;
  544. string assetServer = Util.ServerURI(uinfo.UserProfile.UserAssetURI);
  545. if ((assetServer == null) || (assetServer == ""))
  546. assetServer = LocalAssetServerURI;
  547. string inventoryServer = Util.ServerURI(uinfo.UserProfile.UserInventoryURI);
  548. if ((inventoryServer == null) || (inventoryServer == ""))
  549. inventoryServer = LocalInventoryServerURI;
  550. if (!m_HypergridServiceConnector.InformRegionOfUser(clonedRegion, agentData, home, userServer, assetServer, inventoryServer))
  551. {
  552. m_log.Warn("[HGrid]: Could not inform remote region of transferring user.");
  553. return false;
  554. }
  555. }
  556. //if ((uinfo == null) || !IsGoingHome(uinfo, regInfo))
  557. //{
  558. // m_log.Info("[HGrid]: User seems to be going to foreign region.");
  559. // if (!InformRegionOfUser(regInfo, agentData))
  560. // {
  561. // m_log.Warn("[HGrid]: Could not inform remote region of transferring user.");
  562. // return false;
  563. // }
  564. //}
  565. //else
  566. // m_log.Info("[HGrid]: User seems to be going home " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
  567. // May need to change agent's name
  568. if (IsLocalUser(uinfo) && (GetHyperlinkRegion(regInfo.RegionHandle) != null))
  569. {
  570. agentData.firstname = agentData.firstname + "." + agentData.lastname;
  571. agentData.lastname = "@" + LocalUserServerURI.Replace("http://", ""); ; //HGNetworkServersInfo.Singleton.LocalUserServerURI;
  572. }
  573. return true;
  574. }
  575. public void AdjustUserInformation(AgentCircuitData agentData)
  576. {
  577. CachedUserInfo uinfo = m_aScene.CommsManager.UserProfileCacheService.GetUserDetails(agentData.AgentID);
  578. if ((uinfo != null) && (uinfo.UserProfile != null) &&
  579. (IsLocalUser(uinfo) || !(uinfo.UserProfile is ForeignUserProfileData)))
  580. {
  581. //m_log.Debug("---------------> Local User!");
  582. string[] parts = agentData.firstname.Split(new char[] { '.' });
  583. if (parts.Length == 2)
  584. {
  585. agentData.firstname = parts[0];
  586. agentData.lastname = parts[1];
  587. }
  588. }
  589. //else
  590. // m_log.Debug("---------------> Foreign User!");
  591. }
  592. // Check if a local user exists with the same UUID as the incoming foreign user
  593. public bool CheckUserAtEntry(UUID userID, UUID sessionID, out bool comingHome)
  594. {
  595. comingHome = false;
  596. CachedUserInfo uinfo = m_aScene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
  597. if (uinfo != null)
  598. {
  599. // uh-oh we have a potential intruder
  600. if (uinfo.SessionID != sessionID)
  601. // can't have a foreigner with a local UUID
  602. return false;
  603. else
  604. // oh, so it's you! welcome back
  605. comingHome = true;
  606. }
  607. // OK, user can come in
  608. return true;
  609. }
  610. public void AcceptUser(ForeignUserProfileData user, GridRegion home)
  611. {
  612. m_aScene.CommsManager.UserProfileCacheService.PreloadUserCache(user);
  613. ulong realHandle = home.RegionHandle;
  614. // Change the local coordinates
  615. // X=0 on the map
  616. home.RegionLocX = 0;
  617. home.RegionLocY = random.Next(0, 10000) * (int)Constants.RegionSize;
  618. AddHyperlinkHomeRegion(user.ID, home, realHandle);
  619. DumpUserData(user);
  620. DumpRegionData(home);
  621. }
  622. public bool IsLocalUser(UUID userID)
  623. {
  624. CachedUserInfo uinfo = m_aScene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
  625. return IsLocalUser(uinfo);
  626. }
  627. #endregion
  628. #region IHyperlink Misc
  629. protected bool IsComingHome(ForeignUserProfileData userData)
  630. {
  631. return (userData.UserServerURI == LocalUserServerURI);
  632. }
  633. // Is the user going back to the home region or the home grid?
  634. protected bool IsGoingHome(CachedUserInfo uinfo, GridRegion rinfo)
  635. {
  636. if (uinfo == null)
  637. return false;
  638. if (uinfo.UserProfile == null)
  639. return false;
  640. if (!(uinfo.UserProfile is ForeignUserProfileData))
  641. // it's a home user, can't be outside to return home
  642. return false;
  643. // OK, it's a foreign user with a ForeignUserProfileData
  644. // and is going back to exactly the home region.
  645. // We can't check if it's going back to a non-home region
  646. // of the home grid. That will be dealt with in the
  647. // receiving end
  648. return (uinfo.UserProfile.HomeRegionID == rinfo.RegionID);
  649. }
  650. protected bool IsLocalUser(CachedUserInfo uinfo)
  651. {
  652. if (uinfo == null)
  653. return false;
  654. return !(uinfo.UserProfile is ForeignUserProfileData);
  655. }
  656. protected bool IsLocalRegion(ulong handle)
  657. {
  658. return m_LocalScenes.ContainsKey(handle);
  659. }
  660. private void DumpUserData(ForeignUserProfileData userData)
  661. {
  662. m_log.Info(" ------------ User Data Dump ----------");
  663. m_log.Info(" >> Name: " + userData.FirstName + " " + userData.SurName);
  664. m_log.Info(" >> HomeID: " + userData.HomeRegionID);
  665. m_log.Info(" >> UserServer: " + userData.UserServerURI);
  666. m_log.Info(" >> InvServer: " + userData.UserInventoryURI);
  667. m_log.Info(" >> AssetServer: " + userData.UserAssetURI);
  668. m_log.Info(" ------------ -------------- ----------");
  669. }
  670. private void DumpRegionData(GridRegion rinfo)
  671. {
  672. m_log.Info(" ------------ Region Data Dump ----------");
  673. m_log.Info(" >> handle: " + rinfo.RegionHandle);
  674. m_log.Info(" >> coords: " + rinfo.RegionLocX + ", " + rinfo.RegionLocY);
  675. m_log.Info(" >> external host name: " + rinfo.ExternalHostName);
  676. m_log.Info(" >> http port: " + rinfo.HttpPort);
  677. m_log.Info(" >> external EP address: " + rinfo.ExternalEndPoint.Address);
  678. m_log.Info(" >> external EP port: " + rinfo.ExternalEndPoint.Port);
  679. m_log.Info(" ------------ -------------- ----------");
  680. }
  681. #endregion
  682. }
  683. }