OGS1GridServices.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Net;
  5. using System.Runtime.Remoting;
  6. using System.Runtime.Remoting.Channels;
  7. using System.Runtime.Remoting.Channels.Tcp;
  8. using libsecondlife;
  9. using Nwc.XmlRpc;
  10. using OpenSim.Framework;
  11. using OpenSim.Framework.Communications;
  12. using OpenSim.Framework.Console;
  13. using OpenSim.Framework.Servers;
  14. using OpenSim.Framework.Types;
  15. namespace OpenSim.Region.Communications.OGS1
  16. {
  17. public class OGS1GridServices : IGridServices, IInterRegionCommunications
  18. {
  19. public Dictionary<ulong, RegionCommsListener> listeners = new Dictionary<ulong, RegionCommsListener>();
  20. protected Dictionary<ulong, RegionInfo> regions = new Dictionary<ulong, RegionInfo>();
  21. public BaseHttpServer httpListener;
  22. public NetworkServersInfo serversInfo;
  23. public BaseHttpServer httpServer;
  24. /// <summary>
  25. ///
  26. /// </summary>
  27. /// <param name="servers_info"></param>
  28. /// <param name="httpServe"></param>
  29. public OGS1GridServices(NetworkServersInfo servers_info, BaseHttpServer httpServe)
  30. {
  31. serversInfo = servers_info;
  32. httpServer = httpServe;
  33. httpServer.AddXmlRPCHandler("expect_user", this.ExpectUser);
  34. this.StartRemoting();
  35. }
  36. /// <summary>
  37. ///
  38. /// </summary>
  39. /// <param name="regionInfo"></param>
  40. /// <returns></returns>
  41. public RegionCommsListener RegisterRegion(RegionInfo regionInfo)
  42. {
  43. if (!this.regions.ContainsKey((uint)regionInfo.RegionHandle))
  44. {
  45. this.regions.Add(regionInfo.RegionHandle, regionInfo);
  46. }
  47. Hashtable GridParams = new Hashtable();
  48. // Login / Authentication
  49. GridParams["authkey"] = serversInfo.GridSendKey;
  50. GridParams["UUID"] = regionInfo.SimUUID.ToStringHyphenated();
  51. GridParams["sim_ip"] = regionInfo.ExternalHostName;
  52. GridParams["sim_port"] = regionInfo.InternalEndPoint.Port.ToString();
  53. GridParams["region_locx"] = regionInfo.RegionLocX.ToString();
  54. GridParams["region_locy"] = regionInfo.RegionLocY.ToString();
  55. GridParams["sim_name"] = regionInfo.RegionName;
  56. GridParams["http_port"] = serversInfo.HttpListenerPort.ToString();
  57. GridParams["remoting_port"] = serversInfo.RemotingListenerPort.ToString();
  58. GridParams["map-image-id"] = regionInfo.estateSettings.terrainImageID.ToStringHyphenated();
  59. // Package into an XMLRPC Request
  60. ArrayList SendParams = new ArrayList();
  61. SendParams.Add(GridParams);
  62. // Send Request
  63. XmlRpcRequest GridReq = new XmlRpcRequest("simulator_login", SendParams);
  64. XmlRpcResponse GridResp = GridReq.Send(serversInfo.GridURL, 3000);
  65. Hashtable GridRespData = (Hashtable)GridResp.Value;
  66. Hashtable griddatahash = GridRespData;
  67. // Process Response
  68. if (GridRespData.ContainsKey("error"))
  69. {
  70. string errorstring = (string)GridRespData["error"];
  71. MainLog.Instance.Error("Unable to connect to grid: " + errorstring);
  72. return null;
  73. }
  74. // Initialise the background listeners
  75. RegionCommsListener regListener = new RegionCommsListener();
  76. if (!this.listeners.ContainsKey(regionInfo.RegionHandle))
  77. {
  78. this.listeners.Add(regionInfo.RegionHandle, regListener);
  79. }
  80. else
  81. {
  82. listeners[regionInfo.RegionHandle] = regListener;
  83. }
  84. return regListener;
  85. }
  86. /// <summary>
  87. ///
  88. /// </summary>
  89. /// <param name="regionInfo"></param>
  90. /// <returns></returns>
  91. public List<RegionInfo> RequestNeighbours(RegionInfo regionInfo)
  92. {
  93. Hashtable respData = MapBlockQuery((int)regionInfo.RegionLocX - 1, (int)regionInfo.RegionLocY - 1, (int)regionInfo.RegionLocX + 1, (int)regionInfo.RegionLocY + 1);
  94. List<RegionInfo> neighbours = new List<RegionInfo>();
  95. foreach (ArrayList a in respData.Values)
  96. {
  97. foreach (Hashtable n in a)
  98. {
  99. uint regX = Convert.ToUInt32(n["x"]);
  100. uint regY = Convert.ToUInt32(n["y"]);
  101. if ((regionInfo.RegionLocX != regX) || (regionInfo.RegionLocY != regY))
  102. {
  103. string externalIpStr = (string)n["sim_ip"];
  104. uint port = Convert.ToUInt32(n["sim_port"]);
  105. string externalUri = (string)n["sim_uri"];
  106. IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(externalIpStr), (int)port);
  107. string neighbourExternalUri = externalUri;
  108. RegionInfo neighbour = new RegionInfo(regX, regY, neighbourInternalEndPoint, externalIpStr);
  109. //OGS1
  110. //neighbour.RegionHandle = (ulong)n["regionhandle"]; is now calculated locally
  111. neighbour.RegionName = (string)n["name"];
  112. //OGS1+
  113. neighbour.SimUUID = (string)n["uuid"];
  114. neighbours.Add(neighbour);
  115. }
  116. }
  117. }
  118. return neighbours;
  119. }
  120. /// <summary>
  121. ///
  122. /// </summary>
  123. /// <param name="regionHandle"></param>
  124. /// <returns></returns>
  125. public RegionInfo RequestNeighbourInfo(ulong regionHandle)
  126. {
  127. if (this.regions.ContainsKey(regionHandle))
  128. {
  129. return this.regions[regionHandle];
  130. }
  131. //TODO not a region in this instance so ask remote grid server
  132. Hashtable requestData = new Hashtable();
  133. requestData["region_handle"] = regionHandle.ToString();
  134. requestData["authkey"] = this.serversInfo.GridSendKey;
  135. ArrayList SendParams = new ArrayList();
  136. SendParams.Add(requestData);
  137. XmlRpcRequest GridReq = new XmlRpcRequest("simulator_data_request", SendParams);
  138. XmlRpcResponse GridResp = GridReq.Send(this.serversInfo.GridURL, 3000);
  139. Hashtable responseData = (Hashtable)GridResp.Value;
  140. if (responseData.ContainsKey("error"))
  141. {
  142. Console.WriteLine("error received from grid server" + responseData["error"]);
  143. return null;
  144. }
  145. uint regX = Convert.ToUInt32((string)responseData["region_locx"]);
  146. uint regY = Convert.ToUInt32((string)responseData["region_locy"]);
  147. string internalIpStr = (string)responseData["sim_ip"];
  148. uint port = Convert.ToUInt32(responseData["sim_port"]);
  149. string externalUri = (string)responseData["sim_uri"];
  150. IPEndPoint neighbourInternalEndPoint = new IPEndPoint(IPAddress.Parse(internalIpStr), (int)port);
  151. string neighbourExternalUri = externalUri;
  152. RegionInfo regionInfo = new RegionInfo(regX, regY, neighbourInternalEndPoint, internalIpStr);
  153. regionInfo.RemotingPort = Convert.ToUInt32((string)responseData["remoting_port"]);
  154. regionInfo.RemotingAddress = internalIpStr;
  155. regionInfo.SimUUID = new LLUUID((string)responseData["region_UUID"]);
  156. regionInfo.RegionName = (string)responseData["region_name"];
  157. return regionInfo;
  158. }
  159. /// <summary>
  160. ///
  161. /// </summary>
  162. /// <param name="minX"></param>
  163. /// <param name="minY"></param>
  164. /// <param name="maxX"></param>
  165. /// <param name="maxY"></param>
  166. /// <returns></returns>
  167. public List<MapBlockData> RequestNeighbourMapBlocks(int minX, int minY, int maxX, int maxY)
  168. {
  169. Hashtable respData = MapBlockQuery(minX, minY, maxX, maxY);
  170. List<MapBlockData> neighbours = new List<MapBlockData>();
  171. foreach (ArrayList a in respData.Values)
  172. {
  173. foreach (Hashtable n in a)
  174. {
  175. MapBlockData neighbour = new MapBlockData();
  176. neighbour.X = Convert.ToUInt16(n["x"]);
  177. neighbour.Y = Convert.ToUInt16(n["y"]);
  178. neighbour.Name = (string)n["name"];
  179. neighbour.Access = Convert.ToByte(n["access"]);
  180. neighbour.RegionFlags = Convert.ToUInt32(n["region-flags"]);
  181. neighbour.WaterHeight = Convert.ToByte(n["water-height"]);
  182. neighbour.MapImageId = new LLUUID((string)n["map-image-id"]);
  183. neighbours.Add(neighbour);
  184. }
  185. }
  186. return neighbours;
  187. }
  188. /// <summary>
  189. /// Performs a XML-RPC query against the grid server returning mapblock information in the specified coordinates
  190. /// </summary>
  191. /// <remarks>REDUNDANT - OGS1 is to be phased out in favour of OGS2</remarks>
  192. /// <param name="minX">Minimum X value</param>
  193. /// <param name="minY">Minimum Y value</param>
  194. /// <param name="maxX">Maximum X value</param>
  195. /// <param name="maxY">Maximum Y value</param>
  196. /// <returns>Hashtable of hashtables containing map data elements</returns>
  197. private Hashtable MapBlockQuery(int minX, int minY, int maxX, int maxY)
  198. {
  199. Hashtable param = new Hashtable();
  200. param["xmin"] = minX;
  201. param["ymin"] = minY;
  202. param["xmax"] = maxX;
  203. param["ymax"] = maxY;
  204. IList parameters = new ArrayList();
  205. parameters.Add(param);
  206. XmlRpcRequest req = new XmlRpcRequest("map_block", parameters);
  207. XmlRpcResponse resp = req.Send(serversInfo.GridURL, 3000);
  208. Hashtable respData = (Hashtable)resp.Value;
  209. return respData;
  210. }
  211. // Grid Request Processing
  212. /// <summary>
  213. ///
  214. /// </summary>
  215. /// <param name="request"></param>
  216. /// <returns></returns>
  217. public XmlRpcResponse ExpectUser(XmlRpcRequest request)
  218. {
  219. Console.WriteLine("Expecting User...");
  220. Hashtable requestData = (Hashtable)request.Params[0];
  221. AgentCircuitData agentData = new AgentCircuitData();
  222. agentData.SessionID = new LLUUID((string)requestData["session_id"]);
  223. agentData.SecureSessionID = new LLUUID((string)requestData["secure_session_id"]);
  224. agentData.firstname = (string)requestData["firstname"];
  225. agentData.lastname = (string)requestData["lastname"];
  226. agentData.AgentID = new LLUUID((string)requestData["agent_id"]);
  227. agentData.circuitcode = Convert.ToUInt32(requestData["circuit_code"]);
  228. agentData.CapsPath = (string)requestData["caps_path"];
  229. if (requestData.ContainsKey("child_agent") && requestData["child_agent"].Equals("1"))
  230. {
  231. agentData.child = true;
  232. }
  233. else
  234. {
  235. agentData.startpos = new LLVector3(Convert.ToUInt32(requestData["startpos_x"]), Convert.ToUInt32(requestData["startpos_y"]), Convert.ToUInt32(requestData["startpos_z"]));
  236. agentData.child = false;
  237. }
  238. if (listeners.ContainsKey(Convert.ToUInt64((string)requestData["regionhandle"])))
  239. {
  240. this.listeners[Convert.ToUInt64((string)requestData["regionhandle"])].TriggerExpectUser(Convert.ToUInt64((string)requestData["regionhandle"]), agentData);
  241. }
  242. else
  243. {
  244. MainLog.Instance.Error("ExpectUser() - Unknown region " + ((ulong)requestData["regionhandle"]).ToString());
  245. }
  246. MainLog.Instance.Verbose("ExpectUser() - Welcoming new user...");
  247. return new XmlRpcResponse();
  248. }
  249. #region InterRegion Comms
  250. /// <summary>
  251. ///
  252. /// </summary>
  253. private void StartRemoting()
  254. {
  255. TcpChannel ch = new TcpChannel(this.serversInfo.RemotingListenerPort);
  256. ChannelServices.RegisterChannel(ch, true);
  257. WellKnownServiceTypeEntry wellType = new WellKnownServiceTypeEntry(typeof(OGS1InterRegionRemoting), "InterRegions", WellKnownObjectMode.Singleton);
  258. RemotingConfiguration.RegisterWellKnownServiceType(wellType);
  259. InterRegionSingleton.Instance.OnArrival += this.IncomingArrival;
  260. InterRegionSingleton.Instance.OnChildAgent += this.IncomingChildAgent;
  261. }
  262. #region Methods called by regions in this instance
  263. /// <summary>
  264. ///
  265. /// </summary>
  266. /// <param name="regionHandle"></param>
  267. /// <param name="agentData"></param>
  268. /// <returns></returns>
  269. public bool InformRegionOfChildAgent(ulong regionHandle, AgentCircuitData agentData)
  270. {
  271. if (this.listeners.ContainsKey(regionHandle))
  272. {
  273. this.listeners[regionHandle].TriggerExpectUser(regionHandle, agentData);
  274. return true;
  275. }
  276. RegionInfo regInfo = this.RequestNeighbourInfo(regionHandle);
  277. if (regInfo != null)
  278. {
  279. //don't want to be creating a new link to the remote instance every time like we are here
  280. bool retValue = false;
  281. OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject(
  282. typeof(OGS1InterRegionRemoting),
  283. "tcp://"+ regInfo.RemotingAddress+":"+regInfo.RemotingPort+"/InterRegions");
  284. if (remObject != null)
  285. {
  286. retValue = remObject.InformRegionOfChildAgent(regionHandle, agentData);
  287. }
  288. else
  289. {
  290. Console.WriteLine("remoting object not found");
  291. }
  292. remObject = null;
  293. return retValue;
  294. }
  295. return false;
  296. }
  297. /// <summary>
  298. ///
  299. /// </summary>
  300. /// <param name="regionHandle"></param>
  301. /// <param name="agentID"></param>
  302. /// <param name="position"></param>
  303. /// <returns></returns>
  304. public bool ExpectAvatarCrossing(ulong regionHandle, LLUUID agentID, LLVector3 position)
  305. {
  306. if (this.listeners.ContainsKey(regionHandle))
  307. {
  308. this.listeners[regionHandle].TriggerExpectAvatarCrossing(regionHandle, agentID, position);
  309. return true;
  310. }
  311. RegionInfo regInfo = this.RequestNeighbourInfo(regionHandle);
  312. if (regInfo != null)
  313. {
  314. bool retValue = false;
  315. OGS1InterRegionRemoting remObject = (OGS1InterRegionRemoting)Activator.GetObject(
  316. typeof(OGS1InterRegionRemoting),
  317. "tcp://" + regInfo.RemotingAddress + ":" + regInfo.RemotingPort + "/InterRegions");
  318. if (remObject != null)
  319. {
  320. retValue = remObject.ExpectAvatarCrossing(regionHandle, agentID, position);
  321. }
  322. else
  323. {
  324. Console.WriteLine("remoting object not found");
  325. }
  326. remObject = null;
  327. return retValue;
  328. }
  329. //TODO need to see if we know about where this region is and use .net remoting
  330. // to inform it.
  331. return false;
  332. }
  333. #endregion
  334. #region Methods triggered by calls from external instances
  335. /// <summary>
  336. ///
  337. /// </summary>
  338. /// <param name="regionHandle"></param>
  339. /// <param name="agentData"></param>
  340. /// <returns></returns>
  341. public bool IncomingChildAgent(ulong regionHandle, AgentCircuitData agentData)
  342. {
  343. if (this.listeners.ContainsKey(regionHandle))
  344. {
  345. this.listeners[regionHandle].TriggerExpectUser(regionHandle, agentData);
  346. return true;
  347. }
  348. return false;
  349. }
  350. /// <summary>
  351. ///
  352. /// </summary>
  353. /// <param name="regionHandle"></param>
  354. /// <param name="agentID"></param>
  355. /// <param name="position"></param>
  356. /// <returns></returns>
  357. public bool IncomingArrival(ulong regionHandle, LLUUID agentID, LLVector3 position)
  358. {
  359. if (this.listeners.ContainsKey(regionHandle))
  360. {
  361. this.listeners[regionHandle].TriggerExpectAvatarCrossing(regionHandle, agentID, position);
  362. return true;
  363. }
  364. return false;
  365. }
  366. #endregion
  367. #endregion
  368. }
  369. }