1
0

HGGridServices.cs 40 KB

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