HGGridServices.cs 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  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;
  29. using System.Collections.Generic;
  30. using System.Drawing;
  31. using System.Net;
  32. using System.Net.Sockets;
  33. using System.Reflection;
  34. using System.Runtime.Remoting;
  35. using System.Security.Authentication;
  36. using log4net;
  37. using Nwc.XmlRpc;
  38. using OpenMetaverse;
  39. using OpenMetaverse.Imaging;
  40. using OpenSim.Framework;
  41. using OpenSim.Framework.Communications;
  42. using OpenSim.Framework.Communications.Cache;
  43. using OpenSim.Framework.Servers;
  44. using OpenSim.Framework.Servers.HttpServer;
  45. using OpenSim.Region.Communications.OGS1;
  46. using OpenSim.Region.Framework.Scenes;
  47. using OpenSim.Services.Interfaces;
  48. // using OpenSim.Region.Environment.Modules.Framework;
  49. namespace OpenSim.Region.Communications.Hypergrid
  50. {
  51. /// <summary>
  52. /// This class encapsulates the main hypergrid functions related to creating and managing
  53. /// hyperlinks, as well as processing all the inter-region comms between a region and
  54. /// an hyperlinked region.
  55. /// </summary>
  56. public class HGGridServices : IGridServices, IHyperlink
  57. {
  58. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  59. public BaseHttpServer httpListener;
  60. public NetworkServersInfo serversInfo;
  61. protected List<RegionInfo> m_regionsOnInstance = new List<RegionInfo>();
  62. // Hyperlink regions are hyperlinks on the map
  63. protected List<RegionInfo> m_hyperlinkRegions = new List<RegionInfo>();
  64. // Known regions are home regions of visiting foreign users.
  65. // They are not on the map as static hyperlinks. They are dynamic hyperlinks, they go away when
  66. // the visitor goes away. They are mapped to X=0 on the map.
  67. // This is key-ed on agent ID
  68. protected Dictionary<UUID, RegionInfo> m_knownRegions = new Dictionary<UUID, RegionInfo>();
  69. protected UserProfileCacheService m_userProfileCache;
  70. protected SceneManager m_sceneman;
  71. private Dictionary<string, string> m_queuedGridSettings = new Dictionary<string, string>();
  72. public virtual string gdebugRegionName
  73. {
  74. get { return "Override me"; }
  75. set { ; }
  76. }
  77. public string rdebugRegionName
  78. {
  79. get { return _rdebugRegionName; }
  80. set { _rdebugRegionName = value; }
  81. }
  82. private string _rdebugRegionName = String.Empty;
  83. public virtual bool RegionLoginsEnabled
  84. {
  85. get { return true; }
  86. set { ; }
  87. }
  88. public UserProfileCacheService UserProfileCache
  89. {
  90. set { m_userProfileCache = value; }
  91. }
  92. private Random random;
  93. /// <summary>
  94. /// Contructor. Adds "expect_hg_user" and "check" xmlrpc method handlers
  95. /// </summary>
  96. /// <param name="servers_info"></param>
  97. public HGGridServices(NetworkServersInfo servers_info, SceneManager sman)
  98. {
  99. serversInfo = servers_info;
  100. m_sceneman = sman;
  101. random = new Random();
  102. MainServer.Instance.AddXmlRPCHandler("link_region", LinkRegionRequest);
  103. MainServer.Instance.AddXmlRPCHandler("expect_hg_user", ExpectHGUser);
  104. HGNetworkServersInfo.Init(servers_info.AssetURL, servers_info.InventoryURL, servers_info.UserURL);
  105. }
  106. // see IGridServices
  107. public virtual RegionCommsListener RegisterRegion(RegionInfo regionInfo)
  108. {
  109. // Region doesn't exist here. Trying to link remote region
  110. m_log.Info("[HGrid]: Linking remote region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort);
  111. regionInfo.RegionID = LinkRegion(regionInfo); // UUID.Random();
  112. if (!regionInfo.RegionID.Equals(UUID.Zero))
  113. {
  114. m_hyperlinkRegions.Add(regionInfo);
  115. m_log.Info("[HGrid]: Successfully linked to region_uuid " + regionInfo.RegionID);
  116. //Try get the map image
  117. GetMapImage(regionInfo);
  118. }
  119. else
  120. {
  121. m_log.Info("[HGrid]: No such region " + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + "(" + regionInfo.InternalEndPoint.Port + ")");
  122. }
  123. // Note that these remote regions aren't registered in localBackend, so return null, no local listeners
  124. return null;
  125. }
  126. // see IGridServices
  127. public virtual bool DeregisterRegion(RegionInfo regionInfo)
  128. {
  129. if (m_hyperlinkRegions.Contains(regionInfo))
  130. {
  131. m_hyperlinkRegions.Remove(regionInfo);
  132. return true;
  133. }
  134. foreach (KeyValuePair<UUID, RegionInfo> kvp in m_knownRegions)
  135. {
  136. if (kvp.Value == regionInfo)
  137. {
  138. m_knownRegions.Remove(kvp.Key);
  139. return true;
  140. }
  141. }
  142. return false;
  143. }
  144. public virtual Dictionary<string, string> GetGridSettings()
  145. {
  146. Dictionary<string, string> returnGridSettings = new Dictionary<string, string>();
  147. lock (m_queuedGridSettings)
  148. {
  149. foreach (string Dictkey in m_queuedGridSettings.Keys)
  150. {
  151. returnGridSettings.Add(Dictkey, m_queuedGridSettings[Dictkey]);
  152. }
  153. m_queuedGridSettings.Clear();
  154. }
  155. return returnGridSettings;
  156. }
  157. // see IGridServices
  158. public virtual List<SimpleRegionInfo> RequestNeighbours(uint x, uint y)
  159. {
  160. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  161. foreach (RegionInfo reg in m_hyperlinkRegions)
  162. {
  163. if (reg.RegionLocX != x || reg.RegionLocY != y)
  164. {
  165. //m_log.Debug("CommsManager- RequestNeighbours() - found a different region in list, checking location");
  166. if ((reg.RegionLocX > (x - 2)) && (reg.RegionLocX < (x + 2)))
  167. {
  168. if ((reg.RegionLocY > (y - 2)) && (reg.RegionLocY < (y + 2)))
  169. {
  170. neighbours.Add(reg);
  171. }
  172. }
  173. }
  174. }
  175. return neighbours;
  176. }
  177. /// <summary>
  178. /// Request information about a region.
  179. /// </summary>
  180. /// <param name="regionHandle"></param>
  181. /// <returns>
  182. /// null on a failure to contact or get a response from the grid server
  183. /// FIXME: Might be nicer to return a proper exception here since we could inform the client more about the
  184. /// nature of the faiulre.
  185. /// </returns>
  186. public virtual RegionInfo RequestNeighbourInfo(UUID Region_UUID)
  187. {
  188. foreach (RegionInfo info in m_hyperlinkRegions)
  189. {
  190. if (info.RegionID == Region_UUID) return info;
  191. }
  192. // I don't trust region uuids to be unique...
  193. //foreach (RegionInfo info in m_knownRegions.Values)
  194. //{
  195. // if (info.RegionID == Region_UUID) return info;
  196. //}
  197. return null;
  198. }
  199. /// <summary>
  200. /// Request information about a region.
  201. /// </summary>
  202. /// <param name="regionHandle"></param>
  203. /// <returns></returns>
  204. public virtual RegionInfo RequestNeighbourInfo(ulong regionHandle)
  205. {
  206. //m_log.Debug(" >> RequestNeighbourInfo for " + regionHandle);
  207. foreach (RegionInfo info in m_hyperlinkRegions)
  208. {
  209. //m_log.Debug(" .. " + info.RegionHandle);
  210. if (info.RegionHandle == regionHandle) return info;
  211. }
  212. foreach (RegionInfo info in m_knownRegions.Values)
  213. {
  214. if (info.RegionHandle == regionHandle)
  215. {
  216. //m_log.Debug("XXX------ known region " + info.RegionHandle);
  217. return info;
  218. }
  219. }
  220. return null;
  221. }
  222. public virtual RegionInfo RequestNeighbourInfo(string name)
  223. {
  224. foreach (RegionInfo info in m_hyperlinkRegions)
  225. {
  226. //m_log.Debug(" .. " + info.RegionHandle);
  227. if (info.RegionName == name) return info;
  228. }
  229. foreach (RegionInfo info in m_knownRegions.Values)
  230. {
  231. if (info.RegionName == name)
  232. {
  233. //m_log.Debug("XXX------ known region " + info.RegionHandle);
  234. return info;
  235. }
  236. }
  237. return null;
  238. }
  239. public virtual RegionInfo RequestNeighbourInfo(string hostName, uint port)
  240. {
  241. foreach (RegionInfo info in m_hyperlinkRegions)
  242. {
  243. //m_log.Debug(" .. " + info.RegionHandle);
  244. if ((info.ExternalHostName == hostName) && (info.HttpPort == port))
  245. return info;
  246. }
  247. foreach (RegionInfo info in m_knownRegions.Values)
  248. {
  249. if ((info.ExternalHostName == hostName) && (info.HttpPort == port))
  250. {
  251. //m_log.Debug("XXX------ known region " + info.RegionHandle);
  252. return info;
  253. }
  254. }
  255. return null;
  256. }
  257. public virtual RegionInfo RequestClosestRegion(string regionName)
  258. {
  259. foreach (RegionInfo info in m_hyperlinkRegions)
  260. {
  261. if (info.RegionName == regionName) return info;
  262. }
  263. return null;
  264. }
  265. /// <summary>
  266. ///
  267. /// </summary>
  268. /// <param name="minX"></param>
  269. /// <param name="minY"></param>
  270. /// <param name="maxX"></param>
  271. /// <param name="maxY"></param>
  272. /// <returns></returns>
  273. public virtual List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  274. {
  275. List<MapBlockData> neighbours = new List<MapBlockData>();
  276. foreach (RegionInfo regInfo in m_hyperlinkRegions)
  277. {
  278. if (((regInfo.RegionLocX >= minX) && (regInfo.RegionLocX <= maxX)) &&
  279. ((regInfo.RegionLocY >= minY) && (regInfo.RegionLocY <= maxY)))
  280. {
  281. MapBlockData map = new MapBlockData();
  282. map.Name = regInfo.RegionName;
  283. map.X = (ushort)regInfo.RegionLocX;
  284. map.Y = (ushort)regInfo.RegionLocY;
  285. map.WaterHeight = (byte)regInfo.RegionSettings.WaterHeight;
  286. map.MapImageId = regInfo.RegionSettings.TerrainImageID;
  287. // m_log.Debug("ImgID: " + map.MapImageId);
  288. map.Agents = 1;
  289. map.RegionFlags = 72458694;
  290. map.Access = regInfo.AccessLevel;
  291. neighbours.Add(map);
  292. }
  293. }
  294. return neighbours;
  295. }
  296. protected virtual void GetMapImage(RegionInfo info)
  297. {
  298. try
  299. {
  300. string regionimage = "regionImage" + info.RegionID.ToString();
  301. regionimage = regionimage.Replace("-", "");
  302. WebClient c = new WebClient();
  303. string uri = "http://" + info.ExternalHostName + ":" + info.HttpPort + "/index.php?method=" + regionimage;
  304. //m_log.Debug("JPEG: " + uri);
  305. c.DownloadFile(uri, info.RegionID.ToString() + ".jpg");
  306. Bitmap m = new Bitmap(info.RegionID.ToString() + ".jpg");
  307. //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
  308. byte[] imageData = OpenJPEG.EncodeFromImage(m, true);
  309. AssetBase ass = new AssetBase(UUID.Random(), "region " + info.RegionID.ToString());
  310. info.RegionSettings.TerrainImageID = ass.FullID;
  311. ass.Type = (int)AssetType.Texture;
  312. ass.Temporary = false;
  313. ass.Local = true;
  314. ass.Data = imageData;
  315. m_sceneman.CurrentOrFirstScene.AssetService.Store(ass);
  316. }
  317. catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
  318. {
  319. m_log.Warn("[HGrid]: Failed getting/storing map image, because it is probably already in the cache");
  320. }
  321. }
  322. // A little ugly, since this code is exactly the same as OSG1's, and we're already
  323. // calling that for when the region in in grid mode... (for the grid regions)
  324. //
  325. public virtual LandData RequestLandData (ulong regionHandle, uint x, uint y)
  326. {
  327. m_log.DebugFormat("[HGrid]: requests land data in {0}, at {1}, {2}",
  328. regionHandle, x, y);
  329. // Remote region
  330. Hashtable hash = new Hashtable();
  331. hash["region_handle"] = regionHandle.ToString();
  332. hash["x"] = x.ToString();
  333. hash["y"] = y.ToString();
  334. IList paramList = new ArrayList();
  335. paramList.Add(hash);
  336. LandData landData = null;
  337. try
  338. {
  339. RegionInfo info = RequestNeighbourInfo(regionHandle);
  340. if (info != null) // just to be sure
  341. {
  342. XmlRpcRequest request = new XmlRpcRequest("land_data", paramList);
  343. string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/";
  344. XmlRpcResponse response = request.Send(uri, 10000);
  345. if (response.IsFault)
  346. {
  347. m_log.ErrorFormat("[HGrid]: remote call returned an error: {0}", response.FaultString);
  348. }
  349. else
  350. {
  351. hash = (Hashtable)response.Value;
  352. try
  353. {
  354. landData = new LandData();
  355. landData.AABBMax = Vector3.Parse((string)hash["AABBMax"]);
  356. landData.AABBMin = Vector3.Parse((string)hash["AABBMin"]);
  357. landData.Area = Convert.ToInt32(hash["Area"]);
  358. landData.AuctionID = Convert.ToUInt32(hash["AuctionID"]);
  359. landData.Description = (string)hash["Description"];
  360. landData.Flags = Convert.ToUInt32(hash["Flags"]);
  361. landData.GlobalID = new UUID((string)hash["GlobalID"]);
  362. landData.Name = (string)hash["Name"];
  363. landData.OwnerID = new UUID((string)hash["OwnerID"]);
  364. landData.SalePrice = Convert.ToInt32(hash["SalePrice"]);
  365. landData.SnapshotID = new UUID((string)hash["SnapshotID"]);
  366. landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]);
  367. m_log.DebugFormat("[HGrid]: Got land data for parcel {0}", landData.Name);
  368. }
  369. catch (Exception e)
  370. {
  371. m_log.Error("[HGrid]: Got exception while parsing land-data:", e);
  372. }
  373. }
  374. }
  375. else m_log.WarnFormat("[HGrid]: Couldn't find region with handle {0}", regionHandle);
  376. }
  377. catch (Exception e)
  378. {
  379. m_log.ErrorFormat("[HGrid]: Couldn't contact region {0}: {1}", regionHandle, e);
  380. }
  381. return landData;
  382. }
  383. // Grid Request Processing
  384. public virtual List<RegionInfo> RequestNamedRegions (string name, int maxNumber)
  385. {
  386. List<RegionInfo> infos = new List<RegionInfo>();
  387. foreach (RegionInfo info in m_hyperlinkRegions)
  388. {
  389. if (info.RegionName.ToLower().Contains(name))
  390. {
  391. infos.Add(info);
  392. }
  393. }
  394. return infos;
  395. }
  396. private UUID LinkRegion(RegionInfo info)
  397. {
  398. UUID uuid = UUID.Zero;
  399. Hashtable hash = new Hashtable();
  400. hash["region_name"] = info.RegionName;
  401. IList paramList = new ArrayList();
  402. paramList.Add(hash);
  403. XmlRpcRequest request = new XmlRpcRequest("link_region", paramList);
  404. string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/";
  405. m_log.Debug("[HGrid]: Linking to " + uri);
  406. XmlRpcResponse response = request.Send(uri, 10000);
  407. if (response.IsFault)
  408. {
  409. m_log.ErrorFormat("[HGrid]: remote call returned an error: {0}", response.FaultString);
  410. }
  411. else
  412. {
  413. hash = (Hashtable)response.Value;
  414. //foreach (Object o in hash)
  415. // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
  416. try
  417. {
  418. UUID.TryParse((string)hash["uuid"], out uuid);
  419. info.RegionID = uuid;
  420. if ((string)hash["handle"] != null)
  421. {
  422. info.regionSecret = (string)hash["handle"];
  423. //m_log.Debug(">> HERE: " + info.regionSecret);
  424. }
  425. if (hash["region_image"] != null)
  426. {
  427. UUID img = UUID.Zero;
  428. UUID.TryParse((string)hash["region_image"], out img);
  429. info.RegionSettings.TerrainImageID = img;
  430. }
  431. if (hash["region_name"] != null)
  432. {
  433. info.RegionName = (string)hash["region_name"];
  434. //m_log.Debug(">> " + info.RegionName);
  435. }
  436. if (hash["internal_port"] != null)
  437. {
  438. int port = Convert.ToInt32((string)hash["internal_port"]);
  439. info.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port);
  440. //m_log.Debug(">> " + info.InternalEndPoint.ToString());
  441. }
  442. if (hash["remoting_port"] != null)
  443. {
  444. info.RemotingPort = Convert.ToUInt32(hash["remoting_port"]);
  445. //m_log.Debug(">> " + info.RemotingPort);
  446. }
  447. }
  448. catch (Exception e)
  449. {
  450. m_log.Error("[HGrid]: Got exception while parsing hyperlink response " + e.StackTrace);
  451. }
  452. }
  453. return uuid;
  454. }
  455. /// <summary>
  456. /// Someone wants to link to us
  457. /// </summary>
  458. /// <param name="request"></param>
  459. /// <returns></returns>
  460. public XmlRpcResponse LinkRegionRequest(XmlRpcRequest request, IPEndPoint remoteClient)
  461. {
  462. Hashtable requestData = (Hashtable)request.Params[0];
  463. //string host = (string)requestData["host"];
  464. //string portstr = (string)requestData["port"];
  465. string name = (string)requestData["region_name"];
  466. m_log.DebugFormat("[HGrid]: Hyperlink request");
  467. RegionInfo regInfo = null;
  468. foreach (RegionInfo r in m_regionsOnInstance)
  469. {
  470. if ((r.RegionName != null) && (name != null) && (r.RegionName.ToLower() == name.ToLower()))
  471. {
  472. regInfo = r;
  473. break;
  474. }
  475. }
  476. if (regInfo == null)
  477. regInfo = m_regionsOnInstance[0]; // Send out the first region
  478. Hashtable hash = new Hashtable();
  479. hash["uuid"] = regInfo.RegionID.ToString();
  480. hash["handle"] = regInfo.RegionHandle.ToString();
  481. //m_log.Debug(">> Here " + regInfo.RegionHandle);
  482. hash["region_image"] = regInfo.RegionSettings.TerrainImageID.ToString();
  483. hash["region_name"] = regInfo.RegionName;
  484. hash["internal_port"] = regInfo.InternalEndPoint.Port.ToString();
  485. hash["remoting_port"] = ConfigSettings.DefaultRegionRemotingPort.ToString();
  486. //m_log.Debug(">> Here: " + regInfo.InternalEndPoint.Port);
  487. XmlRpcResponse response = new XmlRpcResponse();
  488. response.Value = hash;
  489. return response;
  490. }
  491. public bool InformRegionOfUser(RegionInfo regInfo, AgentCircuitData agentData)
  492. {
  493. //ulong regionHandle = regInfo.RegionHandle;
  494. try
  495. {
  496. //regionHandle = Convert.ToUInt64(regInfo.regionSecret);
  497. m_log.Info("[HGrid]: InformRegionOfUser: Remote hyperlinked region " + regInfo.regionSecret);
  498. }
  499. catch
  500. {
  501. m_log.Info("[HGrid]: InformRegionOfUser: Local grid region " + regInfo.regionSecret);
  502. }
  503. string capsPath = agentData.CapsPath;
  504. Hashtable loginParams = new Hashtable();
  505. loginParams["session_id"] = agentData.SessionID.ToString();
  506. loginParams["secure_session_id"] = agentData.SecureSessionID.ToString();
  507. loginParams["firstname"] = agentData.firstname;
  508. loginParams["lastname"] = agentData.lastname;
  509. loginParams["agent_id"] = agentData.AgentID.ToString();
  510. loginParams["circuit_code"] = agentData.circuitcode.ToString();
  511. loginParams["startpos_x"] = agentData.startpos.X.ToString();
  512. loginParams["startpos_y"] = agentData.startpos.Y.ToString();
  513. loginParams["startpos_z"] = agentData.startpos.Z.ToString();
  514. loginParams["caps_path"] = capsPath;
  515. CachedUserInfo u = m_userProfileCache.GetUserDetails(agentData.AgentID);
  516. if (u != null && u.UserProfile != null)
  517. {
  518. loginParams["region_uuid"] = u.UserProfile.HomeRegionID.ToString(); // This seems to be always Zero
  519. //m_log.Debug(" --------- Home Region UUID -------");
  520. //m_log.Debug(" >> " + loginParams["region_uuid"] + " <<");
  521. //m_log.Debug(" --------- ---------------- -------");
  522. string serverURI = "";
  523. if (u.UserProfile is ForeignUserProfileData)
  524. serverURI = HGNetworkServersInfo.ServerURI(((ForeignUserProfileData)u.UserProfile).UserServerURI);
  525. loginParams["userserver_id"] = (serverURI == "") || (serverURI == null) ? HGNetworkServersInfo.Singleton.LocalUserServerURI : serverURI;
  526. serverURI = HGNetworkServersInfo.ServerURI(u.UserProfile.UserAssetURI);
  527. loginParams["assetserver_id"] = (serverURI == "") || (serverURI == null) ? HGNetworkServersInfo.Singleton.LocalAssetServerURI : serverURI;
  528. serverURI = HGNetworkServersInfo.ServerURI(u.UserProfile.UserInventoryURI);
  529. loginParams["inventoryserver_id"] = (serverURI == "") || (serverURI == null) ? HGNetworkServersInfo.Singleton.LocalInventoryServerURI : serverURI;
  530. loginParams["root_folder_id"] = u.UserProfile.RootInventoryFolderID;
  531. RegionInfo rinfo = RequestNeighbourInfo(u.UserProfile.HomeRegion);
  532. if (rinfo != null)
  533. {
  534. loginParams["internal_port"] = rinfo.InternalEndPoint.Port.ToString();
  535. if (!IsLocalUser(u))
  536. {
  537. loginParams["regionhandle"] = rinfo.regionSecret; // user.CurrentAgent.Handle.ToString();
  538. //m_log.Debug("XXX--- informregionofuser (foreign user) here handle: " + rinfo.regionSecret);
  539. loginParams["home_address"] = ((ForeignUserProfileData)(u.UserProfile)).UserHomeAddress;
  540. loginParams["home_port"] = ((ForeignUserProfileData)(u.UserProfile)).UserHomePort;
  541. loginParams["home_remoting"] = ((ForeignUserProfileData)(u.UserProfile)).UserHomeRemotingPort;
  542. }
  543. else
  544. {
  545. //m_log.Debug("XXX--- informregionofuser (local user) here handle: " + rinfo.regionSecret);
  546. //// local user about to jump out, let's process the name
  547. // On second thoughts, let's not do this for the *user*; let's only do it for the *agent*
  548. //loginParams["firstname"] = agentData.firstname + "." + agentData.lastname;
  549. //loginParams["lastname"] = serversInfo.UserURL;
  550. // local user, first time out. let's ask the grid about this user's home region
  551. loginParams["regionhandle"] = u.UserProfile.HomeRegion.ToString(); // user.CurrentAgent.Handle.ToString();
  552. loginParams["home_address"] = rinfo.ExternalHostName;
  553. m_log.Debug(" --------- Home Address -------");
  554. m_log.Debug(" >> " + loginParams["home_address"] + " <<");
  555. m_log.Debug(" --------- ------------ -------");
  556. loginParams["home_port"] = rinfo.HttpPort.ToString();
  557. loginParams["home_remoting"] = ConfigSettings.DefaultRegionRemotingPort.ToString(); ;
  558. }
  559. }
  560. else
  561. {
  562. m_log.Warn("[HGrid]: User's home region info not found: " + u.UserProfile.HomeRegionX + ", " + u.UserProfile.HomeRegionY);
  563. }
  564. }
  565. ArrayList SendParams = new ArrayList();
  566. SendParams.Add(loginParams);
  567. // Send
  568. string uri = "http://" + regInfo.ExternalHostName + ":" + regInfo.HttpPort + "/";
  569. //m_log.Debug("XXX uri: " + uri);
  570. XmlRpcRequest request = new XmlRpcRequest("expect_hg_user", SendParams);
  571. XmlRpcResponse reply;
  572. try
  573. {
  574. reply = request.Send(uri, 6000);
  575. }
  576. catch (Exception e)
  577. {
  578. m_log.Warn("[HGrid]: Failed to notify region about user. Reason: " + e.Message);
  579. return false;
  580. }
  581. if (!reply.IsFault)
  582. {
  583. bool responseSuccess = true;
  584. if (reply.Value != null)
  585. {
  586. Hashtable resp = (Hashtable)reply.Value;
  587. if (resp.ContainsKey("success"))
  588. {
  589. if ((string)resp["success"] == "FALSE")
  590. {
  591. responseSuccess = false;
  592. }
  593. }
  594. }
  595. if (responseSuccess)
  596. {
  597. m_log.Info("[HGrid]: Successfully informed remote region about user " + agentData.AgentID);
  598. return true;
  599. }
  600. else
  601. {
  602. m_log.ErrorFormat("[HGrid]: Region responded that it is not available to receive clients");
  603. return false;
  604. }
  605. }
  606. else
  607. {
  608. m_log.ErrorFormat("[HGrid]: XmlRpc request to region failed with message {0}, code {1} ", reply.FaultString, reply.FaultCode);
  609. return false;
  610. }
  611. }
  612. /// <summary>
  613. /// Received from other HGrid nodes when a user wants to teleport here. This call allows
  614. /// the region to prepare for direct communication from the client. Sends back an empty
  615. /// xmlrpc response on completion.
  616. /// This is somewhat similar to OGS1's ExpectUser, but with the additional task of
  617. /// registering the user in the local user cache.
  618. /// </summary>
  619. /// <param name="request"></param>
  620. /// <returns></returns>
  621. public XmlRpcResponse ExpectHGUser(XmlRpcRequest request, IPEndPoint remoteClient)
  622. {
  623. Hashtable requestData = (Hashtable)request.Params[0];
  624. ForeignUserProfileData userData = new ForeignUserProfileData();
  625. userData.FirstName = (string)requestData["firstname"];
  626. userData.SurName = (string)requestData["lastname"];
  627. userData.ID = new UUID((string)requestData["agent_id"]);
  628. userData.HomeLocation = new Vector3((float)Convert.ToDecimal((string)requestData["startpos_x"]),
  629. (float)Convert.ToDecimal((string)requestData["startpos_y"]),
  630. (float)Convert.ToDecimal((string)requestData["startpos_z"]));
  631. userData.UserServerURI = (string)requestData["userserver_id"];
  632. userData.UserAssetURI = (string)requestData["assetserver_id"];
  633. userData.UserInventoryURI = (string)requestData["inventoryserver_id"];
  634. UUID rootID = UUID.Zero;
  635. UUID.TryParse((string)requestData["root_folder_id"], out rootID);
  636. userData.RootInventoryFolderID = rootID;
  637. UUID uuid = UUID.Zero;
  638. UUID.TryParse((string)requestData["region_uuid"], out uuid);
  639. userData.HomeRegionID = uuid; // not quite comfortable about this...
  640. ulong userRegionHandle = Convert.ToUInt64((string)requestData["regionhandle"]);
  641. //userData.HomeRegion = userRegionHandle;
  642. userData.UserHomeAddress = (string)requestData["home_address"];
  643. userData.UserHomePort = (string)requestData["home_port"];
  644. int userhomeinternalport = Convert.ToInt32((string)requestData["internal_port"]);
  645. userData.UserHomeRemotingPort = (string)requestData["home_remoting"];
  646. m_log.DebugFormat("[HGrid]: Prepare for connection from {0} {1} (@{2}) UUID={3}",
  647. userData.FirstName, userData.SurName, userData.UserServerURI, userData.ID);
  648. m_log.Debug("[HGrid]: home_address: " + userData.UserHomeAddress +
  649. "; home_port: " + userData.UserHomePort + "; remoting: " + userData.UserHomeRemotingPort);
  650. XmlRpcResponse resp = new XmlRpcResponse();
  651. // Let's check if someone is trying to get in with a stolen local identity.
  652. // The need for this test is a consequence of not having truly global names :-/
  653. CachedUserInfo uinfo = m_userProfileCache.GetUserDetails(userData.ID);
  654. if ((uinfo != null) && !(uinfo.UserProfile is ForeignUserProfileData))
  655. {
  656. m_log.WarnFormat("[HGrid]: Foreign user trying to get in with local identity. Access denied.");
  657. Hashtable respdata = new Hashtable();
  658. respdata["success"] = "FALSE";
  659. respdata["reason"] = "Foreign user has the same ID as a local user.";
  660. resp.Value = respdata;
  661. return resp;
  662. }
  663. if (!RegionLoginsEnabled)
  664. {
  665. m_log.InfoFormat(
  666. "[HGrid]: Denying access for user {0} {1} because region login is currently disabled",
  667. userData.FirstName, userData.SurName);
  668. Hashtable respdata = new Hashtable();
  669. respdata["success"] = "FALSE";
  670. respdata["reason"] = "region login currently disabled";
  671. resp.Value = respdata;
  672. }
  673. else
  674. {
  675. // Finally, everything looks ok
  676. //m_log.Debug("XXX---- EVERYTHING OK ---XXX");
  677. // 1 - Preload the user data
  678. m_userProfileCache.PreloadUserCache(userData);
  679. if (m_knownRegions.ContainsKey(userData.ID))
  680. {
  681. // This was left here when the user departed
  682. m_knownRegions.Remove(userData.ID);
  683. }
  684. // 2 - Load the region info into list of known regions
  685. RegionInfo rinfo = new RegionInfo();
  686. rinfo.RegionID = userData.HomeRegionID;
  687. rinfo.ExternalHostName = userData.UserHomeAddress;
  688. rinfo.HttpPort = Convert.ToUInt32(userData.UserHomePort);
  689. rinfo.RemotingPort = Convert.ToUInt32(userData.UserHomeRemotingPort);
  690. rinfo.RegionID = userData.HomeRegionID;
  691. // X=0 on the map
  692. rinfo.RegionLocX = 0;
  693. rinfo.RegionLocY = (uint)(random.Next(0, Int32.MaxValue)); //(uint)m_knownRegions.Count;
  694. rinfo.regionSecret = userRegionHandle.ToString();
  695. //m_log.Debug("XXX--- Here: handle = " + rinfo.regionSecret);
  696. try
  697. {
  698. rinfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)userhomeinternalport);
  699. }
  700. catch (Exception e)
  701. {
  702. m_log.Warn("[HGrid]: Exception while constructing internal endpoint: " + e);
  703. }
  704. rinfo.RemotingAddress = rinfo.ExternalEndPoint.Address.ToString(); //userData.UserHomeAddress;
  705. if (!IsComingHome(userData))
  706. {
  707. // Change the user's home region here!!!
  708. userData.HomeRegion = rinfo.RegionHandle;
  709. }
  710. if (!m_knownRegions.ContainsKey(userData.ID))
  711. m_knownRegions.Add(userData.ID, rinfo);
  712. // 3 - Send the reply
  713. Hashtable respdata = new Hashtable();
  714. respdata["success"] = "TRUE";
  715. resp.Value = respdata;
  716. DumpUserData(userData);
  717. DumpRegionData(rinfo);
  718. }
  719. return resp;
  720. }
  721. public bool SendUserInformation(RegionInfo regInfo, AgentCircuitData agentData)
  722. {
  723. CachedUserInfo uinfo = m_userProfileCache.GetUserDetails(agentData.AgentID);
  724. if ((IsLocalUser(uinfo) && IsHyperlinkRegion(regInfo.RegionHandle)) ||
  725. (!IsLocalUser(uinfo) && !IsGoingHome(uinfo, regInfo)))
  726. {
  727. m_log.Info("[HGrid]: Local user is going to foreign region or foreign user is going elsewhere");
  728. if (!InformRegionOfUser(regInfo, agentData))
  729. {
  730. m_log.Warn("[HGrid]: Could not inform remote region of transferring user.");
  731. return false;
  732. }
  733. }
  734. //if ((uinfo == null) || !IsGoingHome(uinfo, regInfo))
  735. //{
  736. // m_log.Info("[HGrid]: User seems to be going to foreign region.");
  737. // if (!InformRegionOfUser(regInfo, agentData))
  738. // {
  739. // m_log.Warn("[HGrid]: Could not inform remote region of transferring user.");
  740. // return false;
  741. // }
  742. //}
  743. //else
  744. // m_log.Info("[HGrid]: User seems to be going home " + uinfo.UserProfile.FirstName + " " + uinfo.UserProfile.SurName);
  745. // May need to change agent's name
  746. if (IsLocalUser(uinfo) && IsHyperlinkRegion(regInfo.RegionHandle))
  747. {
  748. agentData.firstname = agentData.firstname + "." + agentData.lastname;
  749. agentData.lastname = "@" + serversInfo.UserURL.Replace("http://", ""); ; //HGNetworkServersInfo.Singleton.LocalUserServerURI;
  750. }
  751. return true;
  752. }
  753. #region Methods triggered by calls from external instances
  754. /// <summary>
  755. ///
  756. /// </summary>
  757. /// <param name="regionHandle"></param>
  758. /// <param name="agentData"></param>
  759. /// <returns></returns>
  760. public void AdjustUserInformation(AgentCircuitData agentData)
  761. {
  762. CachedUserInfo uinfo = m_userProfileCache.GetUserDetails(agentData.AgentID);
  763. if ((uinfo != null) && (uinfo.UserProfile != null) &&
  764. (IsLocalUser(uinfo) || !(uinfo.UserProfile is ForeignUserProfileData)))
  765. {
  766. //m_log.Debug("---------------> Local User!");
  767. string[] parts = agentData.firstname.Split(new char[] { '.' });
  768. if (parts.Length == 2)
  769. {
  770. agentData.firstname = parts[0];
  771. agentData.lastname = parts[1];
  772. }
  773. }
  774. //else
  775. // m_log.Debug("---------------> Foreign User!");
  776. }
  777. #endregion
  778. #region IHyperGrid interface
  779. public virtual bool IsHyperlinkRegion(ulong ihandle)
  780. {
  781. if (GetHyperlinkRegion(ihandle) == null)
  782. return false;
  783. else
  784. return true;
  785. }
  786. public virtual RegionInfo GetHyperlinkRegion(ulong ihandle)
  787. {
  788. foreach (RegionInfo info in m_hyperlinkRegions)
  789. {
  790. if (info.RegionHandle == ihandle)
  791. return info;
  792. }
  793. foreach (RegionInfo info in m_knownRegions.Values)
  794. {
  795. if (info.RegionHandle == ihandle)
  796. return info;
  797. }
  798. return null;
  799. }
  800. public virtual ulong FindRegionHandle(ulong ihandle)
  801. {
  802. long ohandle = -1;
  803. List<RegionInfo> rlist = new List<RegionInfo>(m_hyperlinkRegions);
  804. rlist.AddRange(m_knownRegions.Values);
  805. foreach (RegionInfo info in rlist)
  806. {
  807. if (info.RegionHandle == ihandle)
  808. {
  809. try
  810. {
  811. ohandle = Convert.ToInt64(info.regionSecret);
  812. m_log.Info("[HGrid] remote region " + ohandle);
  813. }
  814. catch
  815. {
  816. m_log.Error("[HGrid] Could not convert secret for " + ihandle + " (" + info.regionSecret + ")");
  817. }
  818. break;
  819. }
  820. }
  821. return ohandle < 0 ? ihandle : (ulong)ohandle;
  822. }
  823. #endregion
  824. #region Misc
  825. protected bool IsComingHome(ForeignUserProfileData userData)
  826. {
  827. return (userData.UserServerURI == HGNetworkServersInfo.Singleton.LocalUserServerURI);
  828. }
  829. protected bool IsGoingHome(CachedUserInfo uinfo, RegionInfo rinfo)
  830. {
  831. if (uinfo.UserProfile == null)
  832. return false;
  833. string userUserServerURI = String.Empty;
  834. if (uinfo.UserProfile is ForeignUserProfileData)
  835. {
  836. userUserServerURI = HGNetworkServersInfo.ServerURI(((ForeignUserProfileData)uinfo.UserProfile).UserServerURI);
  837. }
  838. return ((uinfo.UserProfile.HomeRegionID == rinfo.RegionID) &&
  839. (userUserServerURI != HGNetworkServersInfo.Singleton.LocalUserServerURI));
  840. }
  841. protected bool IsLocalUser(CachedUserInfo uinfo)
  842. {
  843. if (uinfo == null)
  844. return true;
  845. if (uinfo.UserProfile is ForeignUserProfileData)
  846. return HGNetworkServersInfo.Singleton.IsLocalUser(((ForeignUserProfileData)uinfo.UserProfile).UserServerURI);
  847. else
  848. return true;
  849. }
  850. protected bool IsLocalRegion(ulong handle)
  851. {
  852. foreach (RegionInfo reg in m_regionsOnInstance)
  853. if (reg.RegionHandle == handle)
  854. return true;
  855. return false;
  856. }
  857. private void DumpUserData(ForeignUserProfileData userData)
  858. {
  859. m_log.Info(" ------------ User Data Dump ----------");
  860. m_log.Info(" >> Name: " + userData.FirstName + " " + userData.SurName);
  861. m_log.Info(" >> HomeID: " + userData.HomeRegionID);
  862. m_log.Info(" >> HomeHandle: " + userData.HomeRegion);
  863. m_log.Info(" >> HomeX: " + userData.HomeRegionX);
  864. m_log.Info(" >> HomeY: " + userData.HomeRegionY);
  865. m_log.Info(" >> UserServer: " + userData.UserServerURI);
  866. m_log.Info(" >> InvServer: " + userData.UserInventoryURI);
  867. m_log.Info(" >> AssetServer: " + userData.UserAssetURI);
  868. m_log.Info(" ------------ -------------- ----------");
  869. }
  870. private void DumpRegionData(RegionInfo rinfo)
  871. {
  872. m_log.Info(" ------------ Region Data Dump ----------");
  873. m_log.Info(" >> handle: " + rinfo.RegionHandle);
  874. m_log.Info(" >> coords: " + rinfo.RegionLocX + ", " + rinfo.RegionLocY);
  875. m_log.Info(" >> secret: " + rinfo.regionSecret);
  876. m_log.Info(" >> remoting address: " + rinfo.RemotingAddress);
  877. m_log.Info(" >> remoting port: " + rinfo.RemotingPort);
  878. m_log.Info(" >> external host name: " + rinfo.ExternalHostName);
  879. m_log.Info(" >> http port: " + rinfo.HttpPort);
  880. m_log.Info(" >> external EP address: " + rinfo.ExternalEndPoint.Address);
  881. m_log.Info(" >> external EP port: " + rinfo.ExternalEndPoint.Port);
  882. m_log.Info(" ------------ -------------- ----------");
  883. }
  884. #endregion
  885. }
  886. }