/Aurora/Modules/Communications/InterWorldComms/InterWorldCommunications.cs

http://github.com/aurora-sim/Aurora-Sim · C# · 441 lines · 18 code · 2 blank · 421 comment · 0 complexity · 6eede378d85f38bae284892a025b36b2 MD5 · raw file

  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.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 Aurora-Sim 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.IO;
  30. using System.Linq;
  31. using System.Reflection;
  32. using System.Text;
  33. using Aurora.Framework;
  34. using Aurora.Simulation.Base;
  35. using Nini.Config;
  36. using OpenMetaverse;
  37. using OpenMetaverse.StructuredData;
  38. using Aurora.Framework.Servers.HttpServer;
  39. using OpenSim.Services.Interfaces;
  40. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  41. using RegionFlags = Aurora.Framework.RegionFlags;
  42. namespace Aurora.Modules
  43. {
  44. /*public class InterWorldCommunications : IService, ICommunicationService
  45. {
  46. #region Declares
  47. /// <summary>
  48. /// All connections that we have to other hosts
  49. /// (Before sending the initial connection requests,
  50. /// this MAY contain connections that we do not currently have)
  51. /// </summary>
  52. protected List<string> Connections = new List<string>();
  53. public bool IsGettingUrlsForIWCConnection;
  54. /// <summary>
  55. /// The class that sends requests to other hosts
  56. /// </summary>
  57. public IWCOutgoingConnections OutgoingPublicComms;
  58. /// <summary>
  59. /// Whether we are enabled or not
  60. /// </summary>
  61. protected bool m_Enabled;
  62. /// <summary>
  63. /// Should connections that come to us that are not authenticated be allowed to connect?
  64. /// </summary>
  65. public bool m_allowUntrustedConnections;
  66. /// <summary>
  67. /// The 'AuroraInterWorldConnectors' config
  68. /// </summary>
  69. protected IConfig m_config;
  70. /// <summary>
  71. /// The registry where we can get services
  72. /// </summary>
  73. protected IRegistryCore m_registry;
  74. /// <summary>
  75. /// The config source
  76. /// </summary>
  77. protected IConfigSource m_source;
  78. /// <summary>
  79. /// Untrusted connections automatically get this trust level
  80. /// </summary>
  81. public ThreatLevel m_untrustedConnectionsDefaultTrust = ThreatLevel.Low;
  82. public IRegistryCore Registry
  83. {
  84. get { return m_registry; }
  85. }
  86. #endregion
  87. #region Console Commands
  88. private void AddConsoleCommands()
  89. {
  90. if (MainConsole.Instance == null)
  91. return;
  92. MainConsole.Instance.Commands.AddCommand("iwc add connection", "iwc add connection",
  93. "Add an IWC connection to another host.", AddIWCConnection);
  94. MainConsole.Instance.Commands.AddCommand("iwc remove connection", "iwc remove connection",
  95. "Remove an IWC connection from another host.", RemoveIWCConnection);
  96. MainConsole.Instance.Commands.AddCommand("iwc show connections", "iwc show connections",
  97. "Shows all active IWC connections.", ShowIWCConnections);
  98. }
  99. #region Commands
  100. /// <summary>
  101. /// Add a certificate for the given connection
  102. /// </summary>
  103. /// <param name = "module"></param>
  104. /// <param name = "cmds"></param>
  105. private void AddIWCConnection(string[] cmds)
  106. {
  107. string Url = MainConsole.Instance.Prompt("Url to the connection");
  108. //Be user friendly, add the http:// if needed as well as the final /
  109. Url = (Url.StartsWith("http://") || Url.StartsWith("https://")) ? Url : "http://" + Url;
  110. Url = Url.EndsWith("/") ? Url + "iwcconnection" : Url + "/iwcconnection";
  111. bool success = this.OutgoingPublicComms.AttemptConnection(Url);
  112. if (success)
  113. Connections.Add(Url);
  114. }
  115. private void RemoveIWCConnection(string[] cmds)
  116. {
  117. string Url = MainConsole.Instance.Prompt("Url to the connection");
  118. }
  119. private void ShowIWCConnections(string[] cmds)
  120. {
  121. MainConsole.Instance.InfoFormat("Showing {0} active IWC connections.", Connections.Count);
  122. foreach (string t in Connections)
  123. {
  124. MainConsole.Instance.Info("Url: " + t);
  125. }
  126. }
  127. #endregion
  128. #endregion
  129. #region ICommunicationService Members
  130. public GridRegion GetRegionForGrid(string regionName, string url)
  131. {
  132. bool found = Connections.Contains(url);
  133. if (found)
  134. {
  135. //If we are already connected, the grid services are together, so we already know of the region if it exists, therefore, it does not exist
  136. return null;
  137. }
  138. else
  139. {
  140. //Be user friendly, add the http:// if needed as well as the final /
  141. url = (url.StartsWith("http://") || url.StartsWith("https://")) ? url : "http://" + url;
  142. url = url.EndsWith("/") ? url + "iwcconnection" : url + "/iwcconnection";
  143. bool success = this.OutgoingPublicComms.AttemptConnection(url);
  144. if (success)
  145. {
  146. IGridService service = m_registry.RequestModuleInterface<IGridService>();
  147. if (service != null)
  148. {
  149. List<GridRegion> regions = service.GetRegionsByName(UUID.Zero, regionName, 0, 3);
  150. #if (!ISWIN)
  151. foreach (GridRegion t in regions)
  152. {
  153. if (t.RegionName == regionName)
  154. {
  155. return t;
  156. }
  157. }
  158. #else
  159. foreach (GridRegion t in regions.Where(t => t.RegionName == regionName))
  160. {
  161. return t;
  162. }
  163. #endif
  164. if (regions.Count > 0)
  165. return regions[0];
  166. }
  167. }
  168. }
  169. return null;
  170. }
  171. public OSDMap GetUrlsForUser(GridRegion region, UUID userID)
  172. {
  173. if ((((RegionFlags) region.Flags) & RegionFlags.Foreign) != RegionFlags.Foreign)
  174. {
  175. MainConsole.Instance.Debug("[IWC]: Not a foreign region");
  176. return null;
  177. }
  178. string host = userID.ToString();
  179. IGridRegistrationService module = Registry.RequestModuleInterface<IGridRegistrationService>();
  180. if (module != null)
  181. {
  182. module.RemoveUrlsForClient(host);
  183. module.RemoveUrlsForClient(host + "|" + region.RegionHandle);
  184. IsGettingUrlsForIWCConnection = true;
  185. OSDMap map = module.GetUrlForRegisteringClient(host + "|" + region.RegionHandle);
  186. IsGettingUrlsForIWCConnection = false;
  187. string url = region.GenericMap["URL"];
  188. if (url == "")
  189. {
  190. MainConsole.Instance.Warn("[IWC]: Foreign region with no URL");
  191. return null; //What the hell? Its a foreign region, it better have a URL!
  192. }
  193. //Remove the /Grid.... stuff
  194. url = url.Remove(url.Length - 5 - 36);
  195. OutgoingPublicComms.InformOfURLs(url + "/iwcconnection", map, userID, region.RegionHandle);
  196. return map;
  197. }
  198. return null;
  199. }
  200. #endregion
  201. #region IService Members
  202. public void Initialize(IConfigSource source, IRegistryCore registry)
  203. {
  204. m_source = source;
  205. m_config = source.Configs["AuroraInterWorldConnectors"];
  206. if (m_config != null)
  207. {
  208. m_Enabled = m_config.GetBoolean("Enabled", false);
  209. m_allowUntrustedConnections = m_config.GetBoolean("AllowUntrustedConnections",
  210. m_allowUntrustedConnections);
  211. m_untrustedConnectionsDefaultTrust =
  212. (ThreatLevel)
  213. Enum.Parse(typeof (ThreatLevel),
  214. m_config.GetString("UntrustedConnectionsDefaultTrust",
  215. m_untrustedConnectionsDefaultTrust.ToString()));
  216. registry.RegisterModuleInterface(this);
  217. registry.StackModuleInterface<ICommunicationService>(this);
  218. m_registry = registry;
  219. }
  220. }
  221. public void Start(IConfigSource source, IRegistryCore registry)
  222. {
  223. }
  224. public void FinishedStartup()
  225. {
  226. if (m_Enabled)
  227. {
  228. //Set up the public connection
  229. MainServer.Instance.AddStreamHandler(new IWCIncomingConnections(this));
  230. //Startup outgoing
  231. OutgoingPublicComms = new IWCOutgoingConnections(this);
  232. //Make our connection strings.
  233. //Connections = BuildConnections();
  234. try
  235. {
  236. ContactOtherServers();
  237. }
  238. catch
  239. {
  240. }
  241. AddConsoleCommands();
  242. }
  243. }
  244. #endregion
  245. private void ContactOtherServers()
  246. {
  247. }
  248. internal void AddNewConnectionFromRequest(string identifer, OSDMap args)
  249. {
  250. //Add the other servers IP to our connections=
  251. IConfigurationService configService = Registry.RequestModuleInterface<IConfigurationService>();
  252. if (configService != null)
  253. {
  254. //Add the URLs they sent us
  255. configService.RemoveUrls(identifer);
  256. configService.AddNewUrls(identifer, args);
  257. }
  258. }
  259. }
  260. /// <summary>
  261. /// This class deals with sending requests to other hosts
  262. /// </summary>
  263. public class IWCOutgoingConnections
  264. {
  265. private readonly InterWorldCommunications IWC;
  266. public IWCOutgoingConnections(InterWorldCommunications iwc)
  267. {
  268. IWC = iwc;
  269. }
  270. /// <summary>
  271. /// Query the given host (by connection) and verify that we can connect to it.
  272. /// </summary>
  273. /// <param name = "connector">The host to connect to</param>
  274. /// <returns>The connection that has been recieved from the host</returns>
  275. public bool AttemptConnection(string host)
  276. {
  277. IGridRegistrationService module = IWC.Registry.RequestModuleInterface<IGridRegistrationService>();
  278. if (module != null)
  279. {
  280. module.RemoveUrlsForClient(host);
  281. IWC.IsGettingUrlsForIWCConnection = true;
  282. OSDMap callThem = module.GetUrlForRegisteringClient(host);
  283. IWC.IsGettingUrlsForIWCConnection = false;
  284. callThem["OurIdentifier"] = Utilities.GetAddress();
  285. callThem["Method"] = "ConnectionRequest";
  286. string resultStr = WebUtils.PostToService(host, callThem);
  287. if (resultStr != "")
  288. {
  289. OSDMap result = OSDParser.DeserializeJson(resultStr) as OSDMap;
  290. //Add their URLs back again
  291. MainConsole.Instance.Warn("Successfully Connected to " + host);
  292. IWC.AddNewConnectionFromRequest(result["OurIdentifier"], result);
  293. return true;
  294. }
  295. }
  296. return false;
  297. }
  298. public bool InformOfURLs(string url, OSDMap urls, UUID userID, ulong regionHandle)
  299. {
  300. urls["OurIdentifier"] = Utilities.GetAddress();
  301. urls["UserID"] = userID;
  302. urls["RegionHandle"] = regionHandle;
  303. urls["Method"] = "NewURLs";
  304. return WebUtils.PostToService(url, urls) != "";
  305. }
  306. }
  307. /// <summary>
  308. /// This class deals with incoming requests (secure and insecure) from other hosts
  309. /// </summary>
  310. public class IWCIncomingConnections : BaseRequestHandler
  311. {
  312. private readonly InterWorldCommunications IWC;
  313. public IWCIncomingConnections(InterWorldCommunications iwc) :
  314. base("POST", "/iwcconnection")
  315. {
  316. IWC = iwc;
  317. }
  318. public override byte[] Handle(string path, Stream requestData,
  319. OSHttpRequest httpRequest, OSHttpResponse httpResponse)
  320. {
  321. StreamReader sr = new StreamReader(requestData);
  322. string body = sr.ReadToEnd();
  323. sr.Close();
  324. body = body.Trim();
  325. OSDMap args = WebUtils.GetOSDMap(body);
  326. if (args == null)
  327. {
  328. //No data or not an json OSDMap
  329. return new byte[0];
  330. }
  331. else
  332. {
  333. if (args.ContainsKey("Method"))
  334. {
  335. string Method = args["Method"].AsString();
  336. if (Method == "ConnectionRequest")
  337. return ConnectionRequest(args);
  338. if (Method == "NewURLs")
  339. return NewURLs(args);
  340. }
  341. }
  342. return new byte[0];
  343. }
  344. private byte[] NewURLs(OSDMap args)
  345. {
  346. UUID userID = args["UserID"];
  347. ulong regionhandle = args["RegionHandle"];
  348. string ident = userID + "|" + regionhandle;
  349. IWC.AddNewConnectionFromRequest(userID.ToString(), args);
  350. OSDMap result = new OSDMap();
  351. result["success"] = true;
  352. string json = OSDParser.SerializeJsonString(result);
  353. UTF8Encoding enc = new UTF8Encoding();
  354. return enc.GetBytes(json);
  355. }
  356. private byte[] ConnectionRequest(OSDMap args)
  357. {
  358. IGridRegistrationService module = IWC.Registry.RequestModuleInterface<IGridRegistrationService>();
  359. OSDMap result = new OSDMap();
  360. if (module != null)
  361. {
  362. //Add our URLs for them so that they can connect too
  363. string theirIdent = args["OurIdentifier"];
  364. ulong handle;
  365. if (ulong.TryParse(theirIdent, out handle))
  366. {
  367. //Fu**in hackers
  368. //No making region handle sessionIDs!
  369. result["success"] = false;
  370. }
  371. else
  372. {
  373. module.RemoveUrlsForClient(theirIdent);
  374. IWC.IsGettingUrlsForIWCConnection = true;
  375. result = module.GetUrlForRegisteringClient(theirIdent);
  376. IWC.IsGettingUrlsForIWCConnection = false;
  377. result["OurIdentifier"] = Utilities.GetAddress();
  378. MainConsole.Instance.Warn(theirIdent + " successfully connected to us");
  379. IWC.AddNewConnectionFromRequest(theirIdent, args);
  380. result["success"] = true;
  381. }
  382. }
  383. string json = OSDParser.SerializeJsonString(result);
  384. UTF8Encoding enc = new UTF8Encoding();
  385. return enc.GetBytes(json);
  386. }
  387. }*/
  388. }