SceneCommunicationService.cs 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  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.Threading;
  32. using OpenMetaverse;
  33. using OpenMetaverse.StructuredData;
  34. using log4net;
  35. using OpenSim.Framework;
  36. using OpenSim.Framework.Client;
  37. using OpenSim.Framework.Communications;
  38. using OpenSim.Framework.Communications.Cache;
  39. using OpenSim.Framework.Capabilities;
  40. using OpenSim.Region.Framework.Interfaces;
  41. using OpenSim.Services.Interfaces;
  42. using OSD = OpenMetaverse.StructuredData.OSD;
  43. namespace OpenSim.Region.Framework.Scenes
  44. {
  45. public delegate void KiPrimitiveDelegate(uint localID);
  46. public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
  47. /// <summary>
  48. /// Class that Region communications runs through
  49. /// </summary>
  50. public class SceneCommunicationService //one instance per region
  51. {
  52. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  53. protected CommunicationsManager m_commsProvider;
  54. protected IInterregionCommsOut m_interregionCommsOut;
  55. protected RegionInfo m_regionInfo;
  56. protected RegionCommsListener regionCommsHost;
  57. protected List<UUID> m_agentsInTransit;
  58. /// <summary>
  59. /// An agent is crossing into this region
  60. /// </summary>
  61. public event AgentCrossing OnAvatarCrossingIntoRegion;
  62. /// <summary>
  63. /// A user will arrive shortly, set up appropriate credentials so it can connect
  64. /// </summary>
  65. public event ExpectUserDelegate OnExpectUser;
  66. /// <summary>
  67. /// A Prim will arrive shortly
  68. /// </summary>
  69. public event ExpectPrimDelegate OnExpectPrim;
  70. public event CloseAgentConnection OnCloseAgentConnection;
  71. /// <summary>
  72. /// A new prim has arrived
  73. /// </summary>
  74. public event PrimCrossing OnPrimCrossingIntoRegion;
  75. /// <summary>
  76. /// A New Region is up and available
  77. /// </summary>
  78. public event RegionUp OnRegionUp;
  79. /// <summary>
  80. /// We have a child agent for this avatar and we're getting a status update about it
  81. /// </summary>
  82. public event ChildAgentUpdate OnChildAgentUpdate;
  83. //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
  84. /// <summary>
  85. /// Time to log one of our users off. Grid Service sends this mostly
  86. /// </summary>
  87. public event LogOffUser OnLogOffUser;
  88. /// <summary>
  89. /// A region wants land data from us!
  90. /// </summary>
  91. public event GetLandData OnGetLandData;
  92. private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
  93. private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
  94. private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
  95. private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
  96. private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
  97. private RegionUp handlerRegionUp = null; // OnRegionUp;
  98. private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
  99. //private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
  100. private LogOffUser handlerLogOffUser = null;
  101. private GetLandData handlerGetLandData = null; // OnGetLandData
  102. public KiPrimitiveDelegate KiPrimitive;
  103. public SceneCommunicationService(CommunicationsManager commsMan)
  104. {
  105. m_commsProvider = commsMan;
  106. m_agentsInTransit = new List<UUID>();
  107. }
  108. /// <summary>
  109. /// Register a region with the grid
  110. /// </summary>
  111. /// <param name="regionInfos"></param>
  112. /// <exception cref="System.Exception">Thrown if region registration fails.</exception>
  113. public void RegisterRegion(IInterregionCommsOut comms_out, RegionInfo regionInfos)
  114. {
  115. m_interregionCommsOut = comms_out;
  116. m_regionInfo = regionInfos;
  117. m_commsProvider.GridService.gdebugRegionName = regionInfos.RegionName;
  118. regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo);
  119. if (regionCommsHost != null)
  120. {
  121. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
  122. regionCommsHost.debugRegionName = regionInfos.RegionName;
  123. regionCommsHost.OnExpectPrim += IncomingPrimCrossing;
  124. regionCommsHost.OnExpectUser += NewUserConnection;
  125. regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing;
  126. regionCommsHost.OnCloseAgentConnection += CloseConnection;
  127. regionCommsHost.OnRegionUp += newRegionUp;
  128. regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
  129. regionCommsHost.OnLogOffUser += GridLogOffUser;
  130. regionCommsHost.OnGetLandData += FetchLandData;
  131. }
  132. else
  133. {
  134. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
  135. }
  136. }
  137. /// <summary>
  138. /// Returns a region with the name closest to string provided
  139. /// </summary>
  140. /// <param name="name">Partial Region Name for matching</param>
  141. /// <returns>Region Information for the region</returns>
  142. public RegionInfo RequestClosestRegion(string name)
  143. {
  144. return m_commsProvider.GridService.RequestClosestRegion(name);
  145. }
  146. /// <summary>
  147. /// This region is shutting down, de-register all events!
  148. /// De-Register region from Grid!
  149. /// </summary>
  150. public void Close()
  151. {
  152. if (regionCommsHost != null)
  153. {
  154. regionCommsHost.OnLogOffUser -= GridLogOffUser;
  155. regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
  156. regionCommsHost.OnRegionUp -= newRegionUp;
  157. regionCommsHost.OnExpectUser -= NewUserConnection;
  158. regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
  159. regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
  160. regionCommsHost.OnCloseAgentConnection -= CloseConnection;
  161. regionCommsHost.OnGetLandData -= FetchLandData;
  162. try
  163. {
  164. m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
  165. }
  166. catch (Exception e)
  167. {
  168. m_log.ErrorFormat(
  169. "[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing",
  170. m_regionInfo.RegionName, e);
  171. }
  172. regionCommsHost = null;
  173. }
  174. }
  175. #region CommsManager Event handlers
  176. /// <summary>
  177. /// A New User will arrive shortly, Informs the scene that there's a new user on the way
  178. /// </summary>
  179. /// <param name="agent">Data we need to ensure that the agent can connect</param>
  180. ///
  181. protected void NewUserConnection(AgentCircuitData agent)
  182. {
  183. handlerExpectUser = OnExpectUser;
  184. if (handlerExpectUser != null)
  185. {
  186. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
  187. handlerExpectUser(agent);
  188. }
  189. }
  190. /// <summary>
  191. /// The Grid has requested us to log-off the user
  192. /// </summary>
  193. /// <param name="AgentID">Unique ID of agent to log-off</param>
  194. /// <param name="RegionSecret">The secret string that the region establishes with the grid when registering</param>
  195. /// <param name="message">The message to send to the user that tells them why they were logged off</param>
  196. protected void GridLogOffUser(UUID AgentID, UUID RegionSecret, string message)
  197. {
  198. handlerLogOffUser = OnLogOffUser;
  199. if (handlerLogOffUser != null)
  200. {
  201. handlerLogOffUser(AgentID, RegionSecret, message);
  202. }
  203. }
  204. /// <summary>
  205. /// A New Region is now available. Inform the scene that there is a new region available.
  206. /// </summary>
  207. /// <param name="region">Information about the new region that is available</param>
  208. /// <returns>True if the event was handled</returns>
  209. protected bool newRegionUp(RegionInfo region)
  210. {
  211. handlerRegionUp = OnRegionUp;
  212. if (handlerRegionUp != null)
  213. {
  214. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
  215. handlerRegionUp(region);
  216. }
  217. return true;
  218. }
  219. /// <summary>
  220. /// Inform the scene that we've got an update about a child agent that we have
  221. /// </summary>
  222. /// <param name="cAgentData"></param>
  223. /// <returns></returns>
  224. protected bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData)
  225. {
  226. handlerChildAgentUpdate = OnChildAgentUpdate;
  227. if (handlerChildAgentUpdate != null)
  228. handlerChildAgentUpdate(cAgentData);
  229. return true;
  230. }
  231. protected void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
  232. {
  233. handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
  234. if (handlerAvatarCrossingIntoRegion != null)
  235. {
  236. handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
  237. }
  238. }
  239. /// <summary>
  240. /// We have a new prim from a neighbor
  241. /// </summary>
  242. /// <param name="primID">unique ID for the primative</param>
  243. /// <param name="objXMLData">XML2 encoded data of the primative</param>
  244. /// <param name="XMLMethod">An Int that represents the version of the XMLMethod</param>
  245. /// <returns>True if the prim was accepted, false if it was not</returns>
  246. protected bool IncomingPrimCrossing(UUID primID, String objXMLData, int XMLMethod)
  247. {
  248. handlerExpectPrim = OnExpectPrim;
  249. if (handlerExpectPrim != null)
  250. {
  251. return handlerExpectPrim(primID, objXMLData, XMLMethod);
  252. }
  253. else
  254. {
  255. return false;
  256. }
  257. }
  258. protected void PrimCrossing(UUID primID, Vector3 position, bool isPhysical)
  259. {
  260. handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion;
  261. if (handlerPrimCrossingIntoRegion != null)
  262. {
  263. handlerPrimCrossingIntoRegion(primID, position, isPhysical);
  264. }
  265. }
  266. protected bool CloseConnection(UUID agentID)
  267. {
  268. m_log.Debug("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID);
  269. handlerCloseAgentConnection = OnCloseAgentConnection;
  270. if (handlerCloseAgentConnection != null)
  271. {
  272. return handlerCloseAgentConnection(agentID);
  273. }
  274. return false;
  275. }
  276. protected LandData FetchLandData(uint x, uint y)
  277. {
  278. handlerGetLandData = OnGetLandData;
  279. if (handlerGetLandData != null)
  280. {
  281. return handlerGetLandData(x, y);
  282. }
  283. return null;
  284. }
  285. #endregion
  286. #region Inform Client of Neighbours
  287. private delegate void InformClientOfNeighbourDelegate(
  288. ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint, bool newAgent);
  289. private void InformClientOfNeighbourCompleted(IAsyncResult iar)
  290. {
  291. InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState;
  292. icon.EndInvoke(iar);
  293. }
  294. /// <summary>
  295. /// Async component for informing client of which neighbours exist
  296. /// </summary>
  297. /// <remarks>
  298. /// This needs to run asynchronously, as a network timeout may block the thread for a long while
  299. /// </remarks>
  300. /// <param name="remoteClient"></param>
  301. /// <param name="a"></param>
  302. /// <param name="regionHandle"></param>
  303. /// <param name="endPoint"></param>
  304. private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg,
  305. IPEndPoint endPoint, bool newAgent)
  306. {
  307. // Let's wait just a little to give time to originating regions to catch up with closing child agents
  308. // after a cross here
  309. Thread.Sleep(500);
  310. uint x, y;
  311. Utils.LongToUInts(reg.RegionHandle, out x, out y);
  312. x = x / Constants.RegionSize;
  313. y = y / Constants.RegionSize;
  314. m_log.Info("[INTERGRID]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
  315. string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  316. + "/CAPS/" + a.CapsPath + "0000/";
  317. string reason = String.Empty;
  318. //bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
  319. bool regionAccepted = m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, out reason);
  320. if (regionAccepted && newAgent)
  321. {
  322. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  323. if (eq != null)
  324. {
  325. #region IP Translation for NAT
  326. IClientIPEndpoint ipepClient;
  327. if (avatar.ClientView.TryGet(out ipepClient))
  328. {
  329. endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
  330. }
  331. #endregion
  332. eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);
  333. eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
  334. m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}",
  335. capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName);
  336. }
  337. else
  338. {
  339. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  340. // TODO: make Event Queue disablable!
  341. }
  342. m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString());
  343. }
  344. }
  345. public void RequestNeighbors(RegionInfo region)
  346. {
  347. // List<SimpleRegionInfo> neighbours =
  348. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  349. //IPEndPoint blah = new IPEndPoint();
  350. //blah.Address = region.RemotingAddress;
  351. //blah.Port = region.RemotingPort;
  352. }
  353. /// <summary>
  354. /// This informs all neighboring regions about agent "avatar".
  355. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  356. /// </summary>
  357. public void EnableNeighbourChildAgents(ScenePresence avatar, List<RegionInfo> lstneighbours)
  358. {
  359. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  360. //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  361. for (int i = 0; i < lstneighbours.Count; i++)
  362. {
  363. // We don't want to keep sending to regions that consistently fail on comms.
  364. if (!(lstneighbours[i].commFailTF))
  365. {
  366. neighbours.Add(new SimpleRegionInfo(lstneighbours[i]));
  367. }
  368. }
  369. // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
  370. // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
  371. if (m_regionInfo != null)
  372. {
  373. neighbours =
  374. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  375. }
  376. else
  377. {
  378. m_log.Debug("[ENABLENEIGHBOURCHILDAGENTS]: m_regionInfo was null in EnableNeighbourChildAgents, is this a NPC?");
  379. }
  380. /// We need to find the difference between the new regions where there are no child agents
  381. /// and the regions where there are already child agents. We only send notification to the former.
  382. List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
  383. neighbourHandles.Add(avatar.Scene.RegionInfo.RegionHandle); // add this region too
  384. List<ulong> previousRegionNeighbourHandles ;
  385. if (avatar.Scene.CapsModule != null)
  386. {
  387. previousRegionNeighbourHandles =
  388. new List<ulong>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID).Keys);
  389. }
  390. else
  391. {
  392. previousRegionNeighbourHandles = new List<ulong>();
  393. }
  394. List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  395. List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  396. //Dump("Current Neighbors", neighbourHandles);
  397. //Dump("Previous Neighbours", previousRegionNeighbourHandles);
  398. //Dump("New Neighbours", newRegions);
  399. //Dump("Old Neighbours", oldRegions);
  400. /// Update the scene presence's known regions here on this region
  401. avatar.DropOldNeighbours(oldRegions);
  402. /// Collect as many seeds as possible
  403. Dictionary<ulong, string> seeds;
  404. if (avatar.Scene.CapsModule != null)
  405. seeds
  406. = new Dictionary<ulong, string>(avatar.Scene.CapsModule.GetChildrenSeeds(avatar.UUID));
  407. else
  408. seeds = new Dictionary<ulong, string>();
  409. //m_log.Debug(" !!! No. of seeds: " + seeds.Count);
  410. if (!seeds.ContainsKey(avatar.Scene.RegionInfo.RegionHandle))
  411. seeds.Add(avatar.Scene.RegionInfo.RegionHandle, avatar.ControllingClient.RequestClientInfo().CapsPath);
  412. /// Create the necessary child agents
  413. List<AgentCircuitData> cagents = new List<AgentCircuitData>();
  414. foreach (SimpleRegionInfo neighbour in neighbours)
  415. {
  416. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  417. {
  418. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  419. agent.BaseFolder = UUID.Zero;
  420. agent.InventoryFolder = UUID.Zero;
  421. agent.startpos = new Vector3(128, 128, 70);
  422. agent.child = true;
  423. if (newRegions.Contains(neighbour.RegionHandle))
  424. {
  425. agent.CapsPath = CapsUtil.GetRandomCapsObjectPath();
  426. avatar.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
  427. seeds.Add(neighbour.RegionHandle, agent.CapsPath);
  428. }
  429. else
  430. agent.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, neighbour.RegionHandle);
  431. cagents.Add(agent);
  432. }
  433. }
  434. /// Update all child agent with everyone's seeds
  435. foreach (AgentCircuitData a in cagents)
  436. {
  437. a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
  438. }
  439. if (avatar.Scene.CapsModule != null)
  440. {
  441. // These two are the same thing!
  442. avatar.Scene.CapsModule.SetChildrenSeed(avatar.UUID, seeds);
  443. }
  444. avatar.KnownRegions = seeds;
  445. //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
  446. //avatar.DumpKnownRegions();
  447. bool newAgent = false;
  448. int count = 0;
  449. foreach (SimpleRegionInfo neighbour in neighbours)
  450. {
  451. // Don't do it if there's already an agent in that region
  452. if (newRegions.Contains(neighbour.RegionHandle))
  453. newAgent = true;
  454. else
  455. newAgent = false;
  456. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  457. {
  458. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  459. try
  460. {
  461. d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
  462. InformClientOfNeighbourCompleted,
  463. d);
  464. }
  465. catch (Exception e)
  466. {
  467. m_log.ErrorFormat(
  468. "[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
  469. neighbour.ExternalHostName,
  470. neighbour.RegionHandle,
  471. neighbour.RegionLocX,
  472. neighbour.RegionLocY,
  473. e);
  474. // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
  475. // since I don't know what will happen if we just let the client continue
  476. // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
  477. // throw e;
  478. }
  479. }
  480. count++;
  481. }
  482. }
  483. /// <summary>
  484. /// This informs a single neighboring region about agent "avatar".
  485. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  486. /// </summary>
  487. public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region)
  488. {
  489. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  490. agent.BaseFolder = UUID.Zero;
  491. agent.InventoryFolder = UUID.Zero;
  492. agent.startpos = new Vector3(128, 128, 70);
  493. agent.child = true;
  494. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  495. d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint, true,
  496. InformClientOfNeighbourCompleted,
  497. d);
  498. }
  499. #endregion
  500. public delegate void InformNeighbourThatRegionUpDelegate(INeighbourService nService, RegionInfo region, ulong regionhandle);
  501. private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
  502. {
  503. InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
  504. icon.EndInvoke(iar);
  505. }
  506. /// <summary>
  507. /// Asynchronous call to information neighbouring regions that this region is up
  508. /// </summary>
  509. /// <param name="region"></param>
  510. /// <param name="regionhandle"></param>
  511. private void InformNeighboursThatRegionIsUpAsync(INeighbourService neighbourService, RegionInfo region, ulong regionhandle)
  512. {
  513. m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here");
  514. //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
  515. //bool regionAccepted =
  516. // m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle);
  517. //bool regionAccepted = m_interregionCommsOut.SendHelloNeighbour(regionhandle, region);
  518. bool regionAccepted = false;
  519. if (neighbourService != null)
  520. regionAccepted = neighbourService.HelloNeighbour(regionhandle, region);
  521. else
  522. m_log.DebugFormat("[SCS]: No neighbour service provided for informing neigbhours of this region");
  523. if (regionAccepted)
  524. {
  525. m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here");
  526. handlerRegionUp = OnRegionUp;
  527. // yes, we're notifying ourselves.
  528. if (handlerRegionUp != null)
  529. handlerRegionUp(region);
  530. }
  531. else
  532. {
  533. m_log.Warn("[INTERGRID]: Failed to inform neighbors that I'm here.");
  534. }
  535. }
  536. /// <summary>
  537. /// Called by scene when region is initialized (not always when it's listening for agents)
  538. /// This is an inter-region message that informs the surrounding neighbors that the sim is up.
  539. /// </summary>
  540. public void InformNeighborsThatRegionisUp(INeighbourService neighbourService, RegionInfo region)
  541. {
  542. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
  543. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  544. // This stays uncached because we don't already know about our neighbors at this point.
  545. neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  546. if (neighbours != null)
  547. {
  548. for (int i = 0; i < neighbours.Count; i++)
  549. {
  550. InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
  551. d.BeginInvoke(neighbourService, region, neighbours[i].RegionHandle,
  552. InformNeighborsThatRegionisUpCompleted,
  553. d);
  554. }
  555. }
  556. //bool val = m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region));
  557. }
  558. public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, ulong regionHandle);
  559. /// <summary>
  560. /// This informs all neighboring regions about the settings of it's child agent.
  561. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  562. ///
  563. /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
  564. ///
  565. /// </summary>
  566. private void SendChildAgentDataUpdateAsync(AgentPosition cAgentData, ulong regionHandle)
  567. {
  568. //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + m_regionInfo.RegionName);
  569. try
  570. {
  571. //m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
  572. m_interregionCommsOut.SendChildAgentUpdate(regionHandle, cAgentData);
  573. }
  574. catch
  575. {
  576. // Ignore; we did our best
  577. }
  578. //if (regionAccepted)
  579. //{
  580. // //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
  581. //}
  582. //else
  583. //{
  584. // //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
  585. //}
  586. }
  587. private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
  588. {
  589. SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
  590. icon.EndInvoke(iar);
  591. }
  592. public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
  593. {
  594. // This assumes that we know what our neighbors are.
  595. try
  596. {
  597. foreach (ulong regionHandle in presence.KnownChildRegionHandles)
  598. {
  599. if (regionHandle != m_regionInfo.RegionHandle)
  600. {
  601. SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
  602. d.BeginInvoke(cAgentData, regionHandle,
  603. SendChildAgentDataUpdateCompleted,
  604. d);
  605. }
  606. }
  607. }
  608. catch (InvalidOperationException)
  609. {
  610. // We're ignoring a collection was modified error because this data gets old and outdated fast.
  611. }
  612. }
  613. public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
  614. /// <summary>
  615. /// This Closes child agents on neighboring regions
  616. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  617. /// </summary>
  618. protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
  619. {
  620. m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
  621. // let's do our best, but there's not much we can do if the neighbour doesn't accept.
  622. //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
  623. m_interregionCommsOut.SendCloseAgent(regionHandle, agentID);
  624. }
  625. private void SendCloseChildAgentCompleted(IAsyncResult iar)
  626. {
  627. SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
  628. icon.EndInvoke(iar);
  629. }
  630. public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
  631. {
  632. foreach (ulong handle in regionslst)
  633. {
  634. SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
  635. d.BeginInvoke(agentID, handle,
  636. SendCloseChildAgentCompleted,
  637. d);
  638. }
  639. }
  640. /// <summary>
  641. /// Helper function to request neighbors from grid-comms
  642. /// </summary>
  643. /// <param name="regionHandle"></param>
  644. /// <returns></returns>
  645. public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
  646. {
  647. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
  648. return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle);
  649. }
  650. /// <summary>
  651. /// Helper function to request neighbors from grid-comms
  652. /// </summary>
  653. /// <param name="regionID"></param>
  654. /// <returns></returns>
  655. public virtual RegionInfo RequestNeighbouringRegionInfo(UUID regionID)
  656. {
  657. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionID);
  658. return m_commsProvider.GridService.RequestNeighbourInfo(regionID);
  659. }
  660. /// <summary>
  661. /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
  662. /// </summary>
  663. /// <param name="minX"></param>
  664. /// <param name="minY"></param>
  665. /// <param name="maxX"></param>
  666. /// <param name="maxY"></param>
  667. public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
  668. {
  669. List<MapBlockData> mapBlocks;
  670. mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4);
  671. remoteClient.SendMapBlock(mapBlocks, 0);
  672. }
  673. /// <summary>
  674. /// Try to teleport an agent to a new region.
  675. /// </summary>
  676. /// <param name="remoteClient"></param>
  677. /// <param name="RegionHandle"></param>
  678. /// <param name="position"></param>
  679. /// <param name="lookAt"></param>
  680. /// <param name="flags"></param>
  681. public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
  682. Vector3 lookAt, uint teleportFlags)
  683. {
  684. if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
  685. return;
  686. bool destRegionUp = true;
  687. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  688. // Reset animations; the viewer does that in teleports.
  689. avatar.ResetAnimations();
  690. if (regionHandle == m_regionInfo.RegionHandle)
  691. {
  692. m_log.DebugFormat(
  693. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}",
  694. position, m_regionInfo.RegionName);
  695. // Teleport within the same region
  696. if (position.X < 0 || position.X > Constants.RegionSize || position.Y < 0 || position.Y > Constants.RegionSize || position.Z < 0)
  697. {
  698. Vector3 emergencyPos = new Vector3(128, 128, 128);
  699. m_log.WarnFormat(
  700. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
  701. position, avatar.Name, avatar.UUID, emergencyPos);
  702. position = emergencyPos;
  703. }
  704. // TODO: Get proper AVG Height
  705. float localAVHeight = 1.56f;
  706. float posZLimit = (float)avatar.Scene.Heightmap[(int)position.X, (int)position.Y];
  707. float newPosZ = posZLimit + localAVHeight;
  708. if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
  709. {
  710. position.Z = newPosZ;
  711. }
  712. // Only send this if the event queue is null
  713. if (eq == null)
  714. avatar.ControllingClient.SendTeleportLocationStart();
  715. avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
  716. avatar.Teleport(position);
  717. }
  718. else
  719. {
  720. RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
  721. if (reg != null)
  722. {
  723. m_log.DebugFormat(
  724. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation to {0} in {1}",
  725. position, reg.RegionName);
  726. if (eq == null)
  727. avatar.ControllingClient.SendTeleportLocationStart();
  728. // Let's do DNS resolution only once in this process, please!
  729. // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
  730. // it's actually doing a lot of work.
  731. IPEndPoint endPoint = reg.ExternalEndPoint;
  732. if (endPoint.Address == null)
  733. {
  734. // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
  735. destRegionUp = false;
  736. }
  737. if (destRegionUp)
  738. {
  739. uint newRegionX = (uint)(reg.RegionHandle >> 40);
  740. uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
  741. uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
  742. uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
  743. // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
  744. // both regions
  745. if (avatar.ParentID != (uint)0)
  746. avatar.StandUp();
  747. if (!avatar.ValidateAttachments())
  748. {
  749. avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
  750. return;
  751. }
  752. // the avatar.Close below will clear the child region list. We need this below for (possibly)
  753. // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
  754. //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
  755. // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
  756. // failure at this point (unlike a border crossing failure). So perhaps this can never fail
  757. // once we reach here...
  758. //avatar.Scene.RemoveCapsHandler(avatar.UUID);
  759. string capsPath = String.Empty;
  760. AgentCircuitData agentCircuit = avatar.ControllingClient.RequestClientInfo();
  761. agentCircuit.BaseFolder = UUID.Zero;
  762. agentCircuit.InventoryFolder = UUID.Zero;
  763. agentCircuit.startpos = position;
  764. agentCircuit.child = true;
  765. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  766. {
  767. // brand new agent, let's create a new caps seed
  768. agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
  769. }
  770. string reason = String.Empty;
  771. // Let's create an agent there if one doesn't exist yet.
  772. //if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agentCircuit))
  773. if (!m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, agentCircuit, out reason))
  774. {
  775. avatar.ControllingClient.SendTeleportFailed(String.Format("Destination is not accepting teleports: {0}",
  776. reason));
  777. return;
  778. }
  779. // OK, it got this agent. Let's close some child agents
  780. avatar.CloseChildAgents(newRegionX, newRegionY);
  781. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  782. {
  783. #region IP Translation for NAT
  784. IClientIPEndpoint ipepClient;
  785. if (avatar.ClientView.TryGet(out ipepClient))
  786. {
  787. capsPath
  788. = "http://"
  789. + NetworkUtil.GetHostFor(ipepClient.EndPoint, reg.ExternalHostName)
  790. + ":"
  791. + reg.HttpPort
  792. + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
  793. }
  794. else
  795. {
  796. capsPath
  797. = "http://"
  798. + reg.ExternalHostName
  799. + ":"
  800. + reg.HttpPort
  801. + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
  802. }
  803. #endregion
  804. if (eq != null)
  805. {
  806. #region IP Translation for NAT
  807. // Uses ipepClient above
  808. if (avatar.ClientView.TryGet(out ipepClient))
  809. {
  810. endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address);
  811. }
  812. #endregion
  813. eq.EnableSimulator(reg.RegionHandle, endPoint, avatar.UUID);
  814. // ES makes the client send a UseCircuitCode message to the destination,
  815. // which triggers a bunch of things there.
  816. // So let's wait
  817. Thread.Sleep(2000);
  818. eq.EstablishAgentCommunication(avatar.UUID, endPoint, capsPath);
  819. }
  820. else
  821. {
  822. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  823. }
  824. }
  825. else
  826. {
  827. agentCircuit.CapsPath = avatar.Scene.CapsModule.GetChildSeed(avatar.UUID, reg.RegionHandle);
  828. capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  829. + "/CAPS/" + agentCircuit.CapsPath + "0000/";
  830. }
  831. // Expect avatar crossing is a heavy-duty function at the destination.
  832. // That is where MakeRoot is called, which fetches appearance and inventory.
  833. // Plus triggers OnMakeRoot, which spawns a series of asynchronous updates.
  834. //m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
  835. // position, false);
  836. //{
  837. // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
  838. // // We should close that agent we just created over at destination...
  839. // List<ulong> lst = new List<ulong>();
  840. // lst.Add(reg.RegionHandle);
  841. // SendCloseChildAgentAsync(avatar.UUID, lst);
  842. // return;
  843. //}
  844. SetInTransit(avatar.UUID);
  845. // Let's send a full update of the agent. This is a synchronous call.
  846. AgentData agent = new AgentData();
  847. avatar.CopyTo(agent);
  848. agent.Position = position;
  849. agent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
  850. "/agent/" + avatar.UUID.ToString() + "/" + avatar.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
  851. m_interregionCommsOut.SendChildAgentUpdate(reg.RegionHandle, agent);
  852. m_log.DebugFormat(
  853. "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);
  854. if (eq != null)
  855. {
  856. eq.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
  857. 4, teleportFlags, capsPath, avatar.UUID);
  858. }
  859. else
  860. {
  861. avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
  862. teleportFlags, capsPath);
  863. }
  864. // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
  865. // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
  866. // that the client contacted the destination before we send the attachments and close things here.
  867. if (!WaitForCallback(avatar.UUID))
  868. {
  869. // Client never contacted destination. Let's restore everything back
  870. avatar.ControllingClient.SendTeleportFailed("Problems connecting to destination.");
  871. ResetFromTransit(avatar.UUID);
  872. // Yikes! We should just have a ref to scene here.
  873. avatar.Scene.InformClientOfNeighbours(avatar);
  874. // Finally, kill the agent we just created at the destination.
  875. m_interregionCommsOut.SendCloseAgent(reg.RegionHandle, avatar.UUID);
  876. return;
  877. }
  878. // Can't go back from here
  879. if (KiPrimitive != null)
  880. {
  881. KiPrimitive(avatar.LocalId);
  882. }
  883. avatar.MakeChildAgent();
  884. // CrossAttachmentsIntoNewRegion is a synchronous call. We shouldn't need to wait after it
  885. avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);
  886. // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
  887. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  888. {
  889. Thread.Sleep(5000);
  890. avatar.Close();
  891. CloseConnection(avatar.UUID);
  892. }
  893. else
  894. // now we have a child agent in this region.
  895. avatar.Reset();
  896. // if (teleport success) // seems to be always success here
  897. // the user may change their profile information in other region,
  898. // so the userinfo in UserProfileCache is not reliable any more, delete it
  899. if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
  900. {
  901. m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
  902. m_log.DebugFormat(
  903. "[SCENE COMMUNICATION SERVICE]: User {0} is going to another region, profile cache removed",
  904. avatar.UUID);
  905. }
  906. }
  907. else
  908. {
  909. avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
  910. }
  911. }
  912. else
  913. {
  914. // TP to a place that doesn't exist (anymore)
  915. // Inform the viewer about that
  916. avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
  917. // and set the map-tile to '(Offline)'
  918. uint regX, regY;
  919. Utils.LongToUInts(regionHandle, out regX, out regY);
  920. MapBlockData block = new MapBlockData();
  921. block.X = (ushort)(regX / Constants.RegionSize);
  922. block.Y = (ushort)(regY / Constants.RegionSize);
  923. block.Access = 254; // == not there
  924. List<MapBlockData> blocks = new List<MapBlockData>();
  925. blocks.Add(block);
  926. avatar.ControllingClient.SendMapBlock(blocks, 0);
  927. }
  928. }
  929. }
  930. public bool WaitForCallback(UUID id)
  931. {
  932. int count = 20;
  933. while (m_agentsInTransit.Contains(id) && count-- > 0)
  934. {
  935. //m_log.Debug(" >>> Waiting... " + count);
  936. Thread.Sleep(1000);
  937. }
  938. if (count > 0)
  939. return true;
  940. else
  941. return false;
  942. }
  943. public bool ReleaseAgent(UUID id)
  944. {
  945. //m_log.Debug(" >>> ReleaseAgent called <<< ");
  946. return ResetFromTransit(id);
  947. }
  948. public void SetInTransit(UUID id)
  949. {
  950. lock (m_agentsInTransit)
  951. {
  952. if (!m_agentsInTransit.Contains(id))
  953. m_agentsInTransit.Add(id);
  954. }
  955. }
  956. protected bool ResetFromTransit(UUID id)
  957. {
  958. lock (m_agentsInTransit)
  959. {
  960. if (m_agentsInTransit.Contains(id))
  961. {
  962. m_agentsInTransit.Remove(id);
  963. return true;
  964. }
  965. }
  966. return false;
  967. }
  968. private List<ulong> NeighbourHandles(List<SimpleRegionInfo> neighbours)
  969. {
  970. List<ulong> handles = new List<ulong>();
  971. foreach (SimpleRegionInfo reg in neighbours)
  972. {
  973. handles.Add(reg.RegionHandle);
  974. }
  975. return handles;
  976. }
  977. private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  978. {
  979. return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
  980. }
  981. // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  982. // {
  983. // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
  984. // }
  985. private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  986. {
  987. return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
  988. }
  989. public void CrossAgentToNewRegion(Scene scene, ScenePresence agent, bool isFlying)
  990. {
  991. Vector3 pos = agent.AbsolutePosition;
  992. Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z);
  993. uint neighbourx = m_regionInfo.RegionLocX;
  994. uint neighboury = m_regionInfo.RegionLocY;
  995. // distance to edge that will trigger crossing
  996. const float boundaryDistance = 1.7f;
  997. // distance into new region to place avatar
  998. const float enterDistance = 0.1f;
  999. if (pos.X < boundaryDistance)
  1000. {
  1001. neighbourx--;
  1002. newpos.X = Constants.RegionSize - enterDistance;
  1003. }
  1004. else if (pos.X > Constants.RegionSize - boundaryDistance)
  1005. {
  1006. neighbourx++;
  1007. newpos.X = enterDistance;
  1008. }
  1009. if (pos.Y < boundaryDistance)
  1010. {
  1011. neighboury--;
  1012. newpos.Y = Constants.RegionSize - enterDistance;
  1013. }
  1014. else if (pos.Y > Constants.RegionSize - boundaryDistance)
  1015. {
  1016. neighboury++;
  1017. newpos.Y = enterDistance;
  1018. }
  1019. CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync;
  1020. d.BeginInvoke(agent, newpos, neighbourx, neighboury, isFlying, CrossAgentToNewRegionCompleted, d);
  1021. }
  1022. public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying);
  1023. /// <summary>
  1024. /// This Closes child agents on neighboring regions
  1025. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  1026. /// </summary>
  1027. protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, bool isFlying)
  1028. {
  1029. m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} to {2}-{3}", agent.Firstname, agent.Lastname, neighbourx, neighboury);
  1030. ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
  1031. SimpleRegionInfo neighbourRegion = RequestNeighbouringRegionInfo(neighbourHandle);
  1032. if (neighbourRegion != null && agent.ValidateAttachments())
  1033. {
  1034. pos = pos + (agent.Velocity);
  1035. CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
  1036. if (userInfo != null)
  1037. {
  1038. userInfo.DropInventory();
  1039. }
  1040. else
  1041. {
  1042. m_log.WarnFormat("[SCENE COMM]: No cached user info found for {0} {1} on leaving region {2}",
  1043. agent.Name, agent.UUID, agent.Scene.RegionInfo.RegionName);
  1044. }
  1045. //bool crossingSuccessful =
  1046. // CrossToNeighbouringRegion(neighbourHandle, agent.ControllingClient.AgentId, pos,
  1047. //isFlying);
  1048. SetInTransit(agent.UUID);
  1049. AgentData cAgent = new AgentData();
  1050. agent.CopyTo(cAgent);
  1051. cAgent.Position = pos;
  1052. if (isFlying)
  1053. cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY;
  1054. cAgent.CallbackURI = "http://" + m_regionInfo.ExternalHostName + ":" + m_regionInfo.HttpPort +
  1055. "/agent/" + agent.UUID.ToString() + "/" + agent.Scene.RegionInfo.RegionHandle.ToString() + "/release/";
  1056. m_interregionCommsOut.SendChildAgentUpdate(neighbourHandle, cAgent);
  1057. // Next, let's close the child agent connections that are too far away.
  1058. agent.CloseChildAgents(neighbourx, neighboury);
  1059. //AgentCircuitData circuitdata = m_controllingClient.RequestClientInfo();
  1060. agent.ControllingClient.RequestClientInfo();
  1061. //m_log.Debug("BEFORE CROSS");
  1062. //Scene.DumpChildrenSeeds(UUID);
  1063. //DumpKnownRegions();
  1064. string agentcaps;
  1065. if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps))
  1066. {
  1067. m_log.ErrorFormat("[SCENE COMM]: No CAPS information for region handle {0}, exiting CrossToNewRegion.",
  1068. neighbourRegion.RegionHandle);
  1069. return agent;
  1070. }
  1071. // TODO Should construct this behind a method
  1072. string capsPath =
  1073. "http://" + neighbourRegion.ExternalHostName + ":" + neighbourRegion.HttpPort
  1074. + "/CAPS/" + agentcaps /*circuitdata.CapsPath*/ + "0000/";
  1075. m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID);
  1076. IEventQueue eq = agent.Scene.RequestModuleInterface<IEventQueue>();
  1077. if (eq != null)
  1078. {
  1079. eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
  1080. capsPath, agent.UUID, agent.ControllingClient.SessionId);
  1081. }
  1082. else
  1083. {
  1084. agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint,
  1085. capsPath);
  1086. }
  1087. if (!WaitForCallback(agent.UUID))
  1088. {
  1089. ResetFromTransit(agent.UUID);
  1090. // Yikes! We should just have a ref to scene here.
  1091. agent.Scene.InformClientOfNeighbours(agent);
  1092. return agent;
  1093. }
  1094. agent.MakeChildAgent();
  1095. // now we have a child agent in this region. Request all interesting data about other (root) agents
  1096. agent.SendInitialFullUpdateToAllClients();
  1097. agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true);
  1098. // m_scene.SendKillObject(m_localId);
  1099. agent.Scene.NotifyMyCoarseLocationChange();
  1100. // the user may change their profile information in other region,
  1101. // so the userinfo in UserProfileCache is not reliable any more, delete it
  1102. if (agent.Scene.NeedSceneCacheClear(agent.UUID))
  1103. {
  1104. agent.Scene.CommsManager.UserProfileCacheService.RemoveUser(agent.UUID);
  1105. m_log.DebugFormat(
  1106. "[SCENE COMM]: User {0} is going to another region, profile cache removed", agent.UUID);
  1107. }
  1108. }
  1109. //m_log.Debug("AFTER CROSS");
  1110. //Scene.DumpChildrenSeeds(UUID);
  1111. //DumpKnownRegions();
  1112. return agent;
  1113. }
  1114. private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
  1115. {
  1116. CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
  1117. ScenePresence agent = icon.EndInvoke(iar);
  1118. // If the cross was successful, this agent is a child agent
  1119. if (agent.IsChildAgent)
  1120. {
  1121. agent.Reset();
  1122. }
  1123. else // Not successful
  1124. {
  1125. CachedUserInfo userInfo = m_commsProvider.UserProfileCacheService.GetUserDetails(agent.UUID);
  1126. if (userInfo != null)
  1127. {
  1128. userInfo.FetchInventory();
  1129. }
  1130. agent.RestoreInCurrentScene();
  1131. }
  1132. // In any case
  1133. agent.NotInTransit();
  1134. //m_log.DebugFormat("[SCENE COMM]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
  1135. }
  1136. public Dictionary<string, string> GetGridSettings()
  1137. {
  1138. return m_commsProvider.GridService.GetGridSettings();
  1139. }
  1140. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
  1141. {
  1142. m_commsProvider.LogOffUser(userid, regionid, regionhandle, position, lookat);
  1143. }
  1144. // deprecated as of 2008-08-27
  1145. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
  1146. {
  1147. m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
  1148. }
  1149. public void ClearUserAgent(UUID avatarID)
  1150. {
  1151. m_commsProvider.UserService.ClearUserAgent(avatarID);
  1152. }
  1153. public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
  1154. {
  1155. m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms);
  1156. }
  1157. public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
  1158. {
  1159. m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms);
  1160. }
  1161. public void RemoveUserFriend(UUID friendlistowner, UUID friend)
  1162. {
  1163. m_commsProvider.RemoveUserFriend(friendlistowner, friend);
  1164. }
  1165. public List<FriendListItem> GetUserFriendList(UUID friendlistowner)
  1166. {
  1167. return m_commsProvider.GetUserFriendList(friendlistowner);
  1168. }
  1169. public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  1170. {
  1171. return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
  1172. }
  1173. public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
  1174. {
  1175. return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query);
  1176. }
  1177. public List<RegionInfo> RequestNamedRegions(string name, int maxNumber)
  1178. {
  1179. return m_commsProvider.GridService.RequestNamedRegions(name, maxNumber);
  1180. }
  1181. //private void Dump(string msg, List<ulong> handles)
  1182. //{
  1183. // m_log.InfoFormat("-------------- HANDLE DUMP ({0}) ---------", msg);
  1184. // foreach (ulong handle in handles)
  1185. // {
  1186. // uint x, y;
  1187. // Utils.LongToUInts(handle, out x, out y);
  1188. // x = x / Constants.RegionSize;
  1189. // y = y / Constants.RegionSize;
  1190. // m_log.InfoFormat("({0}, {1})", x, y);
  1191. // }
  1192. //}
  1193. }
  1194. }