1
0

SceneCommunicationService.cs 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  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 OpenSim 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.Communications;
  37. using OpenSim.Region.Interfaces;
  38. using OSD = OpenMetaverse.StructuredData.OSD;
  39. namespace OpenSim.Region.Environment.Scenes
  40. {
  41. public delegate void KiPrimitiveDelegate(uint localID);
  42. public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
  43. public class SceneCommunicationService //one instance per region
  44. {
  45. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  46. protected CommunicationsManager m_commsProvider;
  47. protected RegionInfo m_regionInfo;
  48. protected RegionCommsListener regionCommsHost;
  49. public event AgentCrossing OnAvatarCrossingIntoRegion;
  50. public event ExpectUserDelegate OnExpectUser;
  51. public event ExpectPrimDelegate OnExpectPrim;
  52. public event CloseAgentConnection OnCloseAgentConnection;
  53. public event PrimCrossing OnPrimCrossingIntoRegion;
  54. public event RegionUp OnRegionUp;
  55. public event ChildAgentUpdate OnChildAgentUpdate;
  56. //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
  57. public event LogOffUser OnLogOffUser;
  58. public event GetLandData OnGetLandData;
  59. private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion;
  60. private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser;
  61. private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim;
  62. private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection;
  63. private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion;
  64. private RegionUp handlerRegionUp = null; // OnRegionUp;
  65. private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate;
  66. //private RemoveKnownRegionsFromAvatarList handlerRemoveKnownRegionFromAvatar = null; // OnRemoveKnownRegionFromAvatar;
  67. private LogOffUser handlerLogOffUser = null;
  68. private GetLandData handlerGetLandData = null; // OnGetLandData
  69. public KiPrimitiveDelegate KiPrimitive;
  70. public SceneCommunicationService(CommunicationsManager commsMan)
  71. {
  72. m_commsProvider = commsMan;
  73. }
  74. /// <summary>
  75. /// Register a region with the grid
  76. /// </summary>
  77. /// <param name="regionInfos"></param>
  78. /// <exception cref="System.Exception">Thrown if region registration fails.</exception>
  79. public void RegisterRegion(RegionInfo regionInfos)
  80. {
  81. m_regionInfo = regionInfos;
  82. m_commsProvider.GridService.gdebugRegionName = regionInfos.RegionName;
  83. m_commsProvider.InterRegion.rdebugRegionName = regionInfos.RegionName;
  84. regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo);
  85. if (regionCommsHost != null)
  86. {
  87. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString());
  88. regionCommsHost.debugRegionName = regionInfos.RegionName;
  89. regionCommsHost.OnExpectPrim += IncomingPrimCrossing;
  90. regionCommsHost.OnExpectUser += NewUserConnection;
  91. regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing;
  92. regionCommsHost.OnCloseAgentConnection += CloseConnection;
  93. regionCommsHost.OnRegionUp += newRegionUp;
  94. regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate;
  95. regionCommsHost.OnLogOffUser += GridLogOffUser;
  96. regionCommsHost.OnGetLandData += FetchLandData;
  97. }
  98. else
  99. {
  100. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null");
  101. }
  102. }
  103. public RegionInfo RequestClosestRegion(string name)
  104. {
  105. return m_commsProvider.GridService.RequestClosestRegion(name);
  106. }
  107. public void Close()
  108. {
  109. if (regionCommsHost != null)
  110. {
  111. regionCommsHost.OnLogOffUser -= GridLogOffUser;
  112. regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate;
  113. regionCommsHost.OnRegionUp -= newRegionUp;
  114. regionCommsHost.OnExpectUser -= NewUserConnection;
  115. regionCommsHost.OnExpectPrim -= IncomingPrimCrossing;
  116. regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing;
  117. regionCommsHost.OnCloseAgentConnection -= CloseConnection;
  118. regionCommsHost.OnGetLandData -= FetchLandData;
  119. try
  120. {
  121. m_commsProvider.GridService.DeregisterRegion(m_regionInfo);
  122. }
  123. catch (Exception e)
  124. {
  125. m_log.ErrorFormat(
  126. "[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing",
  127. m_regionInfo.RegionName, e);
  128. }
  129. regionCommsHost = null;
  130. }
  131. }
  132. #region CommsManager Event handlers
  133. /// <summary>
  134. ///
  135. /// </summary>
  136. /// <param name="regionHandle"></param>
  137. /// <param name="agent"></param>
  138. ///
  139. protected void NewUserConnection(AgentCircuitData agent)
  140. {
  141. handlerExpectUser = OnExpectUser;
  142. if (handlerExpectUser != null)
  143. {
  144. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: OnExpectUser Fired for User:" + agent.firstname + " " + agent.lastname);
  145. handlerExpectUser(agent);
  146. }
  147. }
  148. protected void GridLogOffUser(UUID AgentID, UUID RegionSecret, string message)
  149. {
  150. handlerLogOffUser = OnLogOffUser;
  151. if (handlerLogOffUser != null)
  152. {
  153. handlerLogOffUser(AgentID, RegionSecret, message);
  154. }
  155. }
  156. protected bool newRegionUp(RegionInfo region)
  157. {
  158. handlerRegionUp = OnRegionUp;
  159. if (handlerRegionUp != null)
  160. {
  161. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: newRegionUp Fired for User:" + region.RegionName);
  162. handlerRegionUp(region);
  163. }
  164. return true;
  165. }
  166. protected bool ChildAgentUpdate(ChildAgentDataUpdate cAgentData)
  167. {
  168. handlerChildAgentUpdate = OnChildAgentUpdate;
  169. if (handlerChildAgentUpdate != null)
  170. handlerChildAgentUpdate(cAgentData);
  171. return true;
  172. }
  173. protected void AgentCrossing(UUID agentID, Vector3 position, bool isFlying)
  174. {
  175. handlerAvatarCrossingIntoRegion = OnAvatarCrossingIntoRegion;
  176. if (handlerAvatarCrossingIntoRegion != null)
  177. {
  178. handlerAvatarCrossingIntoRegion(agentID, position, isFlying);
  179. }
  180. }
  181. protected bool IncomingPrimCrossing(UUID primID, String objXMLData, int XMLMethod)
  182. {
  183. handlerExpectPrim = OnExpectPrim;
  184. if (handlerExpectPrim != null)
  185. {
  186. return handlerExpectPrim(primID, objXMLData, XMLMethod);
  187. }
  188. else
  189. {
  190. return false;
  191. }
  192. }
  193. protected void PrimCrossing(UUID primID, Vector3 position, bool isPhysical)
  194. {
  195. handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion;
  196. if (handlerPrimCrossingIntoRegion != null)
  197. {
  198. handlerPrimCrossingIntoRegion(primID, position, isPhysical);
  199. }
  200. }
  201. protected bool CloseConnection(UUID agentID)
  202. {
  203. m_log.Debug("[INTERREGION]: Incoming Agent Close Request for agent: " + agentID);
  204. handlerCloseAgentConnection = OnCloseAgentConnection;
  205. if (handlerCloseAgentConnection != null)
  206. {
  207. return handlerCloseAgentConnection(agentID);
  208. }
  209. return false;
  210. }
  211. protected LandData FetchLandData(uint x, uint y)
  212. {
  213. handlerGetLandData = OnGetLandData;
  214. if (handlerGetLandData != null)
  215. {
  216. return handlerGetLandData(x, y);
  217. }
  218. return null;
  219. }
  220. #endregion
  221. #region Inform Client of Neighbours
  222. private delegate void InformClientOfNeighbourDelegate(
  223. ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg, IPEndPoint endPoint, bool newAgent);
  224. private void InformClientOfNeighbourCompleted(IAsyncResult iar)
  225. {
  226. InformClientOfNeighbourDelegate icon = (InformClientOfNeighbourDelegate) iar.AsyncState;
  227. icon.EndInvoke(iar);
  228. }
  229. /// <summary>
  230. /// Async component for informing client of which neighbours exist
  231. /// </summary>
  232. /// <remarks>
  233. /// This needs to run asynchronesously, as a network timeout may block the thread for a long while
  234. /// </remarks>
  235. /// <param name="remoteClient"></param>
  236. /// <param name="a"></param>
  237. /// <param name="regionHandle"></param>
  238. /// <param name="endPoint"></param>
  239. private void InformClientOfNeighbourAsync(ScenePresence avatar, AgentCircuitData a, SimpleRegionInfo reg,
  240. IPEndPoint endPoint, bool newAgent)
  241. {
  242. // Let's wait just a little to give time to originating regions to catch up with closing child agents
  243. // after a cross here
  244. Thread.Sleep(500);
  245. uint x, y;
  246. Utils.LongToUInts(reg.RegionHandle, out x, out y);
  247. x = x / Constants.RegionSize;
  248. y = y / Constants.RegionSize;
  249. m_log.Info("[INTERGRID]: Starting to inform client about neighbour " + x + ", " + y + "(" + endPoint.ToString() + ")");
  250. string capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  251. + "/CAPS/" + a.CapsPath + "0000/";
  252. bool regionAccepted = m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, a);
  253. if (regionAccepted && newAgent)
  254. {
  255. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  256. if (eq != null)
  257. {
  258. OSD Item = EventQueueHelper.EnableSimulator(reg.RegionHandle, endPoint);
  259. eq.Enqueue(Item, avatar.UUID);
  260. Item = EventQueueHelper.EstablishAgentCommunication(avatar.UUID, endPoint.ToString(), capsPath);
  261. eq.Enqueue(Item, avatar.UUID);
  262. m_log.DebugFormat("[CAPS]: Sending new CAPS seed url {0} to client {1} in region {2}", capsPath, avatar.UUID, avatar.Scene.RegionInfo.RegionName);
  263. }
  264. else
  265. {
  266. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  267. // TODO: make Event Queue disablable!
  268. }
  269. m_log.Info("[INTERGRID]: Completed inform client about neighbour " + endPoint.ToString());
  270. }
  271. }
  272. public void RequestNeighbors(RegionInfo region)
  273. {
  274. // List<SimpleRegionInfo> neighbours =
  275. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  276. //IPEndPoint blah = new IPEndPoint();
  277. //blah.Address = region.RemotingAddress;
  278. //blah.Port = region.RemotingPort;
  279. }
  280. /// <summary>
  281. /// This informs all neighboring regions about agent "avatar".
  282. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  283. /// </summary>
  284. public void EnableNeighbourChildAgents(ScenePresence avatar, List<RegionInfo> lstneighbours)
  285. {
  286. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  287. //m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  288. for (int i = 0; i < lstneighbours.Count; i++)
  289. {
  290. // We don't want to keep sending to regions that consistently fail on comms.
  291. if (!(lstneighbours[i].commFailTF))
  292. {
  293. neighbours.Add(new SimpleRegionInfo(lstneighbours[i]));
  294. }
  295. }
  296. // we're going to be using the above code once neighbour cache is correct. Currently it doesn't appear to be
  297. // So we're temporarily going back to the old method of grabbing it from the Grid Server Every time :/
  298. neighbours =
  299. m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  300. m_log.Debug("[SCM]: EnableChildAgents from " + avatar.Scene.RegionInfo.RegionName);
  301. /// We need to find the difference between the new regions where there are no child agents
  302. /// and the regions where there are already child agents. We only send notification to the former.
  303. List<ulong> neighbourHandles = NeighbourHandles(neighbours); // on this region
  304. neighbourHandles.Add(avatar.Scene.RegionInfo.RegionHandle); // add this region too
  305. List<ulong> previousRegionNeighbourHandles = new List<ulong>(avatar.Scene.GetChildrenSeeds(avatar.UUID).Keys);
  306. List<ulong> newRegions = NewNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  307. List<ulong> oldRegions = OldNeighbours(neighbourHandles, previousRegionNeighbourHandles);
  308. //Dump("Current Neighbors", neighbourHandles);
  309. //Dump("Previous Neighbours", previousRegionNeighbourHandles);
  310. //Dump("New Neighbours", newRegions);
  311. //Dump("Old Neighbours", oldRegions);
  312. /// Update the scene presence's known regions here on this region
  313. avatar.DropOldNeighbours(oldRegions);
  314. /// Collect as many seeds as possible
  315. Dictionary<ulong, string> seeds = new Dictionary<ulong, string>(avatar.Scene.GetChildrenSeeds(avatar.UUID));
  316. //Console.WriteLine(" !!! No. of seeds: " + seeds.Count);
  317. if (!seeds.ContainsKey(avatar.Scene.RegionInfo.RegionHandle))
  318. seeds.Add(avatar.Scene.RegionInfo.RegionHandle, avatar.ControllingClient.RequestClientInfo().CapsPath);
  319. /// Create the necessary child agents
  320. List<AgentCircuitData> cagents = new List<AgentCircuitData>();
  321. foreach (SimpleRegionInfo neighbour in neighbours)
  322. {
  323. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  324. {
  325. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  326. agent.BaseFolder = UUID.Zero;
  327. agent.InventoryFolder = UUID.Zero;
  328. agent.startpos = new Vector3(128, 128, 70);
  329. agent.child = true;
  330. if (newRegions.Contains(neighbour.RegionHandle))
  331. {
  332. agent.CapsPath = Util.GetRandomCapsPath();
  333. avatar.AddNeighbourRegion(neighbour.RegionHandle, agent.CapsPath);
  334. seeds.Add(neighbour.RegionHandle, agent.CapsPath);
  335. }
  336. else
  337. agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, neighbour.RegionHandle);
  338. cagents.Add(agent);
  339. }
  340. }
  341. /// Update all child agent with everyone's seeds
  342. foreach (AgentCircuitData a in cagents)
  343. {
  344. a.ChildrenCapSeeds = new Dictionary<ulong, string>(seeds);
  345. }
  346. // These two are the same thing!
  347. avatar.Scene.SetChildrenSeed(avatar.UUID, seeds);
  348. avatar.KnownRegions = seeds;
  349. //avatar.Scene.DumpChildrenSeeds(avatar.UUID);
  350. //avatar.DumpKnownRegions();
  351. bool newAgent = false;
  352. int count = 0;
  353. foreach (SimpleRegionInfo neighbour in neighbours)
  354. {
  355. // Don't do it if there's already an agent in that region
  356. if (newRegions.Contains(neighbour.RegionHandle))
  357. newAgent = true;
  358. else
  359. newAgent = false;
  360. if (neighbour.RegionHandle != avatar.Scene.RegionInfo.RegionHandle)
  361. {
  362. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  363. try
  364. {
  365. d.BeginInvoke(avatar, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent,
  366. InformClientOfNeighbourCompleted,
  367. d);
  368. }
  369. catch (Exception e)
  370. {
  371. m_log.ErrorFormat(
  372. "[REGIONINFO]: Could not resolve external hostname {0} for region {1} ({2}, {3}). {4}",
  373. neighbour.ExternalHostName,
  374. neighbour.RegionHandle,
  375. neighbour.RegionLocX,
  376. neighbour.RegionLocY,
  377. e);
  378. // FIXME: Okay, even though we've failed, we're still going to throw the exception on,
  379. // since I don't know what will happen if we just let the client continue
  380. // XXX: Well, decided to swallow the exception instead for now. Let us see how that goes.
  381. // throw e;
  382. }
  383. }
  384. count++;
  385. }
  386. }
  387. /// <summary>
  388. /// This informs a single neighboring region about agent "avatar".
  389. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  390. /// </summary>
  391. public void InformNeighborChildAgent(ScenePresence avatar, SimpleRegionInfo region, List<RegionInfo> neighbours)
  392. {
  393. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  394. agent.BaseFolder = UUID.Zero;
  395. agent.InventoryFolder = UUID.Zero;
  396. agent.startpos = new Vector3(128, 128, 70);
  397. agent.child = true;
  398. InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync;
  399. d.BeginInvoke(avatar, agent, region, region.ExternalEndPoint, true,
  400. InformClientOfNeighbourCompleted,
  401. d);
  402. }
  403. #endregion
  404. public delegate void InformNeighbourThatRegionUpDelegate(RegionInfo region, ulong regionhandle);
  405. private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
  406. {
  407. InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState;
  408. icon.EndInvoke(iar);
  409. }
  410. /// <summary>
  411. /// Asynchronous call to information neighbouring regions that this region is up
  412. /// </summary>
  413. /// <param name="region"></param>
  414. /// <param name="regionhandle"></param>
  415. private void InformNeighboursThatRegionIsUpAsync(RegionInfo region, ulong regionhandle)
  416. {
  417. m_log.Info("[INTERGRID]: Starting to inform neighbors that I'm here");
  418. //RegionUpData regiondata = new RegionUpData(region.RegionLocX, region.RegionLocY, region.ExternalHostName, region.InternalEndPoint.Port);
  419. bool regionAccepted =
  420. m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region), regionhandle);
  421. if (regionAccepted)
  422. {
  423. m_log.Info("[INTERGRID]: Completed informing neighbors that I'm here");
  424. handlerRegionUp = OnRegionUp;
  425. // yes, we're notifying ourselves.
  426. if (handlerRegionUp != null)
  427. handlerRegionUp(region);
  428. }
  429. else
  430. {
  431. m_log.Warn("[INTERGRID]: Failed to inform neighbors that I'm here.");
  432. }
  433. }
  434. /// <summary>
  435. /// Called by scene when region is initialized (not always when it's listening for agents)
  436. /// This is an inter-region message that informs the surrounding neighbors that the sim is up.
  437. /// </summary>
  438. public void InformNeighborsThatRegionisUp(RegionInfo region)
  439. {
  440. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
  441. List<SimpleRegionInfo> neighbours = new List<SimpleRegionInfo>();
  442. // This stays uncached because we don't already know about our neighbors at this point.
  443. neighbours = m_commsProvider.GridService.RequestNeighbours(m_regionInfo.RegionLocX, m_regionInfo.RegionLocY);
  444. if (neighbours != null)
  445. {
  446. for (int i = 0; i < neighbours.Count; i++)
  447. {
  448. InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
  449. d.BeginInvoke(region, neighbours[i].RegionHandle,
  450. InformNeighborsThatRegionisUpCompleted,
  451. d);
  452. }
  453. }
  454. //bool val = m_commsProvider.InterRegion.RegionUp(new SerializableRegionInfo(region));
  455. }
  456. public delegate void SendChildAgentDataUpdateDelegate(ChildAgentDataUpdate cAgentData, ScenePresence presence);
  457. /// <summary>
  458. /// This informs all neighboring regions about the settings of it's child agent.
  459. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  460. ///
  461. /// This contains information, such as, Draw Distance, Camera location, Current Position, Current throttle settings, etc.
  462. ///
  463. /// </summary>
  464. private void SendChildAgentDataUpdateAsync(ChildAgentDataUpdate cAgentData, ScenePresence presence)
  465. {
  466. //m_log.Info("[INTERGRID]: Informing neighbors about my agent in " + presence.Scene.RegionInfo.RegionName);
  467. try
  468. {
  469. foreach (ulong regionHandle in presence.KnownChildRegionHandles)
  470. {
  471. bool regionAccepted = m_commsProvider.InterRegion.ChildAgentUpdate(regionHandle, cAgentData);
  472. if (regionAccepted)
  473. {
  474. //m_log.Info("[INTERGRID]: Completed sending a neighbor an update about my agent");
  475. }
  476. else
  477. {
  478. //m_log.Info("[INTERGRID]: Failed sending a neighbor an update about my agent");
  479. }
  480. }
  481. }
  482. catch (InvalidOperationException)
  483. {
  484. // We're ignoring a collection was modified error because this data gets old and outdated fast.
  485. }
  486. }
  487. private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
  488. {
  489. SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState;
  490. icon.EndInvoke(iar);
  491. }
  492. public void SendChildAgentDataUpdate(ChildAgentDataUpdate cAgentData, ScenePresence presence)
  493. {
  494. // This assumes that we know what our neighbors are.
  495. SendChildAgentDataUpdateDelegate d = SendChildAgentDataUpdateAsync;
  496. d.BeginInvoke(cAgentData,presence,
  497. SendChildAgentDataUpdateCompleted,
  498. d);
  499. }
  500. public delegate void SendCloseChildAgentDelegate(UUID agentID, List<ulong> regionlst);
  501. /// <summary>
  502. /// This Closes child agents on neighboring regions
  503. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
  504. /// </summary>
  505. protected void SendCloseChildAgentAsync(UUID agentID, List<ulong> regionlst)
  506. {
  507. foreach (ulong regionHandle in regionlst)
  508. {
  509. m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
  510. //bool regionAccepted = m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
  511. // let's do our best, but there's not much we can do if the neighbour doesn't accept.
  512. m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
  513. //if (regionAccepted)
  514. //{
  515. // m_log.Info("[INTERGRID]: Completed sending agent Close agent Request to neighbor");
  516. //}
  517. //else
  518. //{
  519. // m_log.Info("[INTERGRID]: Failed sending agent Close agent Request to neighbor");
  520. //}
  521. }
  522. //// We remove the list of known regions from the agent's known region list through an event
  523. //// to scene, because, if an agent logged of, it's likely that there will be no scene presence
  524. //// by the time we get to this part of the method.
  525. //handlerRemoveKnownRegionFromAvatar = OnRemoveKnownRegionFromAvatar;
  526. //if (handlerRemoveKnownRegionFromAvatar != null)
  527. //{
  528. // handlerRemoveKnownRegionFromAvatar(agentID, regionlst);
  529. //}
  530. }
  531. private void SendCloseChildAgentCompleted(IAsyncResult iar)
  532. {
  533. SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
  534. icon.EndInvoke(iar);
  535. }
  536. public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
  537. {
  538. // This assumes that we know what our neighbors are.
  539. SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
  540. d.BeginInvoke(agentID, regionslst,
  541. SendCloseChildAgentCompleted,
  542. d);
  543. }
  544. /// <summary>
  545. /// Helper function to request neighbors from grid-comms
  546. /// </summary>
  547. /// <param name="regionHandle"></param>
  548. /// <returns></returns>
  549. public virtual RegionInfo RequestNeighbouringRegionInfo(ulong regionHandle)
  550. {
  551. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionHandle.ToString());
  552. return m_commsProvider.GridService.RequestNeighbourInfo(regionHandle);
  553. }
  554. /// <summary>
  555. /// Helper function to request neighbors from grid-comms
  556. /// </summary>
  557. /// <param name="regionID"></param>
  558. /// <returns></returns>
  559. public virtual RegionInfo RequestNeighbouringRegionInfo(UUID regionID)
  560. {
  561. //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending Grid Services Request about neighbor " + regionID);
  562. return m_commsProvider.GridService.RequestNeighbourInfo(regionID);
  563. }
  564. /// <summary>
  565. /// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
  566. /// </summary>
  567. /// <param name="minX"></param>
  568. /// <param name="minY"></param>
  569. /// <param name="maxX"></param>
  570. /// <param name="maxY"></param>
  571. public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY)
  572. {
  573. List<MapBlockData> mapBlocks;
  574. mapBlocks = m_commsProvider.GridService.RequestNeighbourMapBlocks(minX - 4, minY - 4, minX + 4, minY + 4);
  575. remoteClient.SendMapBlock(mapBlocks, 0);
  576. }
  577. /// <summary>
  578. /// Try to teleport an agent to a new region.
  579. /// </summary>
  580. /// <param name="remoteClient"></param>
  581. /// <param name="RegionHandle"></param>
  582. /// <param name="position"></param>
  583. /// <param name="lookAt"></param>
  584. /// <param name="flags"></param>
  585. public virtual void RequestTeleportToLocation(ScenePresence avatar, ulong regionHandle, Vector3 position,
  586. Vector3 lookAt, uint teleportFlags)
  587. {
  588. if (!avatar.Scene.Permissions.CanTeleport(avatar.UUID))
  589. return;
  590. bool destRegionUp = false;
  591. IEventQueue eq = avatar.Scene.RequestModuleInterface<IEventQueue>();
  592. if (regionHandle == m_regionInfo.RegionHandle)
  593. {
  594. // Teleport within the same region
  595. if (position.X < 0 || position.X > Constants.RegionSize || position.Y < 0 || position.Y > Constants.RegionSize || position.Z < 0)
  596. {
  597. Vector3 emergencyPos = new Vector3(128, 128, 128);
  598. m_log.WarnFormat(
  599. "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}",
  600. position, avatar.Name, avatar.UUID, emergencyPos);
  601. position = emergencyPos;
  602. }
  603. // TODO: Get proper AVG Height
  604. float localAVHeight = 1.56f;
  605. float posZLimit = (float)avatar.Scene.GetLandHeight((int)position.X, (int)position.Y);
  606. float newPosZ = posZLimit + localAVHeight;
  607. if (posZLimit >= (position.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
  608. {
  609. position.Z = newPosZ;
  610. }
  611. // Only send this if the event queue is null
  612. if (eq == null)
  613. avatar.ControllingClient.SendTeleportLocationStart();
  614. avatar.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags);
  615. avatar.Teleport(position);
  616. }
  617. else
  618. {
  619. RegionInfo reg = RequestNeighbouringRegionInfo(regionHandle);
  620. if (reg != null)
  621. {
  622. if (eq == null)
  623. avatar.ControllingClient.SendTeleportLocationStart();
  624. if (reg.RemotingAddress != "" && reg.RemotingPort != 0)
  625. {
  626. // region is remote. see if it is up
  627. destRegionUp = m_commsProvider.InterRegion.CheckRegion(reg.RemotingAddress, reg.RemotingPort);
  628. }
  629. else
  630. {
  631. // assume local regions are always up
  632. destRegionUp = true;
  633. }
  634. // Let's do DNS resolution only once in this process, please!
  635. // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field,
  636. // it's actually doing a lot of work.
  637. IPEndPoint endPoint = reg.ExternalEndPoint;
  638. if (endPoint.Address == null)
  639. {
  640. // Couldn't resolve the name. Can't TP, because the viewer wants IP addresses.
  641. destRegionUp = false;
  642. }
  643. if (destRegionUp)
  644. {
  645. uint newRegionX = (uint)(reg.RegionHandle >> 40);
  646. uint newRegionY = (((uint)(reg.RegionHandle)) >> 8);
  647. uint oldRegionX = (uint)(m_regionInfo.RegionHandle >> 40);
  648. uint oldRegionY = (((uint)(m_regionInfo.RegionHandle)) >> 8);
  649. // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
  650. // both regions
  651. if (avatar.ParentID != (uint)0)
  652. avatar.StandUp();
  653. if (!avatar.ValidateAttachments())
  654. {
  655. avatar.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
  656. return;
  657. }
  658. // the avatar.Close below will clear the child region list. We need this below for (possibly)
  659. // closing the child agents, so save it here (we need a copy as it is Clear()-ed).
  660. //List<ulong> childRegions = new List<ulong>(avatar.GetKnownRegionList());
  661. // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport
  662. // failure at this point (unlike a border crossing failure). So perhaps this can never fail
  663. // once we reach here...
  664. //avatar.Scene.RemoveCapsHandler(avatar.UUID);
  665. // Let's close some agents
  666. avatar.CloseChildAgents(newRegionX, newRegionY);
  667. string capsPath = String.Empty;
  668. AgentCircuitData agent = avatar.ControllingClient.RequestClientInfo();
  669. agent.BaseFolder = UUID.Zero;
  670. agent.InventoryFolder = UUID.Zero;
  671. agent.startpos = position;
  672. agent.child = true;
  673. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  674. {
  675. Thread.Sleep(1000);
  676. // brand new agent
  677. agent.CapsPath = Util.GetRandomCapsPath();
  678. if (!m_commsProvider.InterRegion.InformRegionOfChildAgent(reg.RegionHandle, agent))
  679. {
  680. avatar.ControllingClient.SendTeleportFailed("Destination is not accepting teleports.");
  681. return;
  682. }
  683. Thread.Sleep(2000);
  684. // TODO Should construct this behind a method
  685. capsPath =
  686. "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  687. + "/CAPS/" + agent.CapsPath + "0000/";
  688. if (eq != null)
  689. {
  690. OSD Item = EventQueueHelper.EnableSimulator(reg.RegionHandle, endPoint);
  691. eq.Enqueue(Item, avatar.UUID);
  692. Item = EventQueueHelper.EstablishAgentCommunication(avatar.UUID, endPoint.ToString(), capsPath);
  693. eq.Enqueue(Item, avatar.UUID);
  694. }
  695. else
  696. {
  697. avatar.ControllingClient.InformClientOfNeighbour(reg.RegionHandle, endPoint);
  698. }
  699. }
  700. else
  701. {
  702. agent.CapsPath = avatar.Scene.GetChildSeed(avatar.UUID, reg.RegionHandle);
  703. capsPath = "http://" + reg.ExternalHostName + ":" + reg.HttpPort
  704. + "/CAPS/" + agent.CapsPath + "0000/";
  705. }
  706. m_commsProvider.InterRegion.ExpectAvatarCrossing(reg.RegionHandle, avatar.ControllingClient.AgentId,
  707. position, false);
  708. //{
  709. // avatar.ControllingClient.SendTeleportFailed("Problem with destination.");
  710. // // We should close that agent we just created over at destination...
  711. // List<ulong> lst = new List<ulong>();
  712. // lst.Add(reg.RegionHandle);
  713. // SendCloseChildAgentAsync(avatar.UUID, lst);
  714. // return;
  715. //}
  716. Thread.Sleep(2000);
  717. m_log.DebugFormat(
  718. "[CAPS]: Sending new CAPS seed url {0} to client {1}", capsPath, avatar.UUID);
  719. if (eq != null)
  720. {
  721. OSD Item = EventQueueHelper.TeleportFinishEvent(reg.RegionHandle, 13, endPoint,
  722. 4, teleportFlags, capsPath, avatar.UUID);
  723. eq.Enqueue(Item, avatar.UUID);
  724. }
  725. else
  726. {
  727. avatar.ControllingClient.SendRegionTeleport(reg.RegionHandle, 13, endPoint, 4,
  728. teleportFlags, capsPath);
  729. }
  730. avatar.MakeChildAgent();
  731. Thread.Sleep(3000);
  732. avatar.CrossAttachmentsIntoNewRegion(reg.RegionHandle, true);
  733. if (KiPrimitive != null)
  734. {
  735. KiPrimitive(avatar.LocalId);
  736. }
  737. // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
  738. if (Util.IsOutsideView(oldRegionX, newRegionX, oldRegionY, newRegionY))
  739. {
  740. CloseConnection(avatar.UUID);
  741. }
  742. // if (teleport success) // seems to be always success here
  743. // the user may change their profile information in other region,
  744. // so the userinfo in UserProfileCache is not reliable any more, delete it
  745. if (avatar.Scene.NeedSceneCacheClear(avatar.UUID))
  746. {
  747. m_commsProvider.UserProfileCacheService.RemoveUser(avatar.UUID);
  748. m_log.InfoFormat("User {0} is going to another region, profile cache removed", avatar.UUID);
  749. }
  750. // Close this ScenePresence too
  751. //avatar.Close();
  752. }
  753. else
  754. {
  755. avatar.ControllingClient.SendTeleportFailed("Remote Region appears to be down");
  756. }
  757. }
  758. else
  759. {
  760. // TP to a place that doesn't exist (anymore)
  761. // Inform the viewer about that
  762. avatar.ControllingClient.SendTeleportFailed("The region you tried to teleport to doesn't exist anymore");
  763. // and set the map-tile to '(Offline)'
  764. uint regX, regY;
  765. Utils.LongToUInts(regionHandle, out regX, out regY);
  766. MapBlockData block = new MapBlockData();
  767. block.X = (ushort)(regX / Constants.RegionSize);
  768. block.Y = (ushort)(regY / Constants.RegionSize);
  769. block.Access = 254; // == not there
  770. List<MapBlockData> blocks = new List<MapBlockData>();
  771. blocks.Add(block);
  772. avatar.ControllingClient.SendMapBlock(blocks, 0);
  773. }
  774. }
  775. }
  776. private List<ulong> NeighbourHandles(List<SimpleRegionInfo> neighbours)
  777. {
  778. List<ulong> handles = new List<ulong>();
  779. foreach (SimpleRegionInfo reg in neighbours)
  780. {
  781. handles.Add(reg.RegionHandle);
  782. }
  783. return handles;
  784. }
  785. private List<ulong> NewNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  786. {
  787. return currentNeighbours.FindAll(delegate(ulong handle) { return !previousNeighbours.Contains(handle); });
  788. }
  789. // private List<ulong> CommonNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  790. // {
  791. // return currentNeighbours.FindAll(delegate(ulong handle) { return previousNeighbours.Contains(handle); });
  792. // }
  793. private List<ulong> OldNeighbours(List<ulong> currentNeighbours, List<ulong> previousNeighbours)
  794. {
  795. return previousNeighbours.FindAll(delegate(ulong handle) { return !currentNeighbours.Contains(handle); });
  796. }
  797. /// <summary>
  798. /// Inform a neighbouring region that an avatar is about to cross into it.
  799. /// </summary>
  800. /// <param name="regionhandle"></param>
  801. /// <param name="agentID"></param>
  802. /// <param name="position"></param>
  803. public bool CrossToNeighbouringRegion(ulong regionhandle, UUID agentID, Vector3 position, bool isFlying)
  804. {
  805. return m_commsProvider.InterRegion.ExpectAvatarCrossing(regionhandle, agentID, position, isFlying);
  806. }
  807. public bool PrimCrossToNeighboringRegion(ulong regionhandle, UUID primID, string objData, int XMLMethod)
  808. {
  809. return m_commsProvider.InterRegion.InformRegionOfPrimCrossing(regionhandle, primID, objData, XMLMethod);
  810. }
  811. public Dictionary<string, string> GetGridSettings()
  812. {
  813. return m_commsProvider.GridService.GetGridSettings();
  814. }
  815. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
  816. {
  817. m_commsProvider.LogOffUser(userid, regionid, regionhandle, position, lookat);
  818. }
  819. // deprecated as of 2008-08-27
  820. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
  821. {
  822. m_commsProvider.LogOffUser(userid, regionid, regionhandle, posx, posy, posz);
  823. }
  824. public void ClearUserAgent(UUID avatarID)
  825. {
  826. m_commsProvider.UserService.ClearUserAgent(avatarID);
  827. }
  828. public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
  829. {
  830. m_commsProvider.AddNewUserFriend(friendlistowner, friend, perms);
  831. }
  832. public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
  833. {
  834. m_commsProvider.UpdateUserFriendPerms(friendlistowner, friend, perms);
  835. }
  836. public void RemoveUserFriend(UUID friendlistowner, UUID friend)
  837. {
  838. m_commsProvider.RemoveUserFriend(friendlistowner, friend);
  839. }
  840. public List<FriendListItem> GetUserFriendList(UUID friendlistowner)
  841. {
  842. return m_commsProvider.GetUserFriendList(friendlistowner);
  843. }
  844. public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  845. {
  846. return m_commsProvider.GridService.RequestNeighbourMapBlocks(minX, minY, maxX, maxY);
  847. }
  848. public List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
  849. {
  850. return m_commsProvider.GenerateAgentPickerRequestResponse(queryID, query);
  851. }
  852. public List<RegionInfo> RequestNamedRegions(string name, int maxNumber)
  853. {
  854. return m_commsProvider.GridService.RequestNamedRegions(name, maxNumber);
  855. }
  856. // private void Dump(string msg, List<ulong> handles)
  857. // {
  858. // Console.WriteLine("-------------- HANDLE DUMP ({0}) ---------", msg);
  859. // foreach (ulong handle in handles)
  860. // {
  861. // uint x, y;
  862. // Utils.LongToUInts(handle, out x, out y);
  863. // x = x / Constants.RegionSize;
  864. // y = y / Constants.RegionSize;
  865. // Console.WriteLine("({0}, {1})", x, y);
  866. // }
  867. // }
  868. }
  869. }