OpenSimBase.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  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.IO;
  30. using System.Linq;
  31. using System.Net;
  32. using System.Reflection;
  33. using System.Text;
  34. using log4net;
  35. using Nini.Config;
  36. using OpenMetaverse;
  37. using OpenSim.Framework;
  38. using OpenSim.Framework.Communications;
  39. using OpenSim.Framework.Console;
  40. using OpenSim.Framework.Servers;
  41. using OpenSim.Framework.Servers.HttpServer;
  42. using OpenSim.Framework.Monitoring;
  43. using OpenSim.Region.ClientStack;
  44. using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
  45. using OpenSim.Region.Framework;
  46. using OpenSim.Region.Framework.Interfaces;
  47. using OpenSim.Region.Framework.Scenes;
  48. using OpenSim.Region.Physics.Manager;
  49. using OpenSim.Server.Base;
  50. using OpenSim.Services.Base;
  51. using OpenSim.Services.Interfaces;
  52. using OpenSim.Services.UserAccountService;
  53. namespace OpenSim
  54. {
  55. /// <summary>
  56. /// Common OpenSimulator simulator code
  57. /// </summary>
  58. public class OpenSimBase : RegionApplicationBase
  59. {
  60. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  61. // These are the names of the plugin-points extended by this
  62. // class during system startup.
  63. //
  64. private const string PLUGIN_ASSET_CACHE = "/OpenSim/AssetCache";
  65. private const string PLUGIN_ASSET_SERVER_CLIENT = "/OpenSim/AssetClient";
  66. // OpenSim.ini Section name for ESTATES Settings
  67. public const string ESTATE_SECTION_NAME = "Estates";
  68. protected string proxyUrl;
  69. protected int proxyOffset = 0;
  70. public string userStatsURI = String.Empty;
  71. protected bool m_autoCreateClientStack = true;
  72. /// <value>
  73. /// The file used to load and save prim backup xml if no filename has been specified
  74. /// </value>
  75. protected const string DEFAULT_PRIM_BACKUP_FILENAME = "prim-backup.xml";
  76. public ConfigSettings ConfigurationSettings
  77. {
  78. get { return m_configSettings; }
  79. set { m_configSettings = value; }
  80. }
  81. protected ConfigSettings m_configSettings;
  82. protected ConfigurationLoader m_configLoader;
  83. public ConsoleCommand CreateAccount = null;
  84. protected List<IApplicationPlugin> m_plugins = new List<IApplicationPlugin>();
  85. /// <value>
  86. /// The config information passed into the OpenSimulator region server.
  87. /// </value>
  88. public OpenSimConfigSource ConfigSource
  89. {
  90. get { return m_config; }
  91. set { m_config = value; }
  92. }
  93. protected OpenSimConfigSource m_config;
  94. public List<IClientNetworkServer> ClientServers
  95. {
  96. get { return m_clientServers; }
  97. }
  98. protected EnvConfigSource m_EnvConfigSource = new EnvConfigSource();
  99. public EnvConfigSource envConfigSource
  100. {
  101. get { return m_EnvConfigSource; }
  102. }
  103. protected List<IClientNetworkServer> m_clientServers = new List<IClientNetworkServer>();
  104. public uint HttpServerPort
  105. {
  106. get { return m_httpServerPort; }
  107. }
  108. public ModuleLoader ModuleLoader
  109. {
  110. get { return m_moduleLoader; }
  111. set { m_moduleLoader = value; }
  112. }
  113. protected ModuleLoader m_moduleLoader;
  114. protected IRegistryCore m_applicationRegistry = new RegistryCore();
  115. public IRegistryCore ApplicationRegistry
  116. {
  117. get { return m_applicationRegistry; }
  118. }
  119. /// <summary>
  120. /// Constructor.
  121. /// </summary>
  122. /// <param name="configSource"></param>
  123. public OpenSimBase(IConfigSource configSource) : base()
  124. {
  125. LoadConfigSettings(configSource);
  126. }
  127. protected virtual void LoadConfigSettings(IConfigSource configSource)
  128. {
  129. m_configLoader = new ConfigurationLoader();
  130. m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
  131. ReadExtraConfigSettings();
  132. }
  133. protected virtual void ReadExtraConfigSettings()
  134. {
  135. IConfig networkConfig = m_config.Source.Configs["Network"];
  136. if (networkConfig != null)
  137. {
  138. proxyUrl = networkConfig.GetString("proxy_url", "");
  139. proxyOffset = Int32.Parse(networkConfig.GetString("proxy_offset", "0"));
  140. }
  141. }
  142. protected virtual void LoadPlugins()
  143. {
  144. using (PluginLoader<IApplicationPlugin> loader = new PluginLoader<IApplicationPlugin>(new ApplicationPluginInitialiser(this)))
  145. {
  146. loader.Load("/OpenSim/Startup");
  147. m_plugins = loader.Plugins;
  148. }
  149. }
  150. protected override List<string> GetHelpTopics()
  151. {
  152. List<string> topics = base.GetHelpTopics();
  153. Scene s = SceneManager.CurrentOrFirstScene;
  154. if (s != null && s.GetCommanders() != null)
  155. topics.AddRange(s.GetCommanders().Keys);
  156. return topics;
  157. }
  158. /// <summary>
  159. /// Performs startup specific to the region server, including initialization of the scene
  160. /// such as loading configuration from disk.
  161. /// </summary>
  162. protected override void StartupSpecific()
  163. {
  164. IConfig startupConfig = m_config.Source.Configs["Startup"];
  165. if (startupConfig != null)
  166. {
  167. string pidFile = startupConfig.GetString("PIDFile", String.Empty);
  168. if (pidFile != String.Empty)
  169. CreatePIDFile(pidFile);
  170. userStatsURI = startupConfig.GetString("Stats_URI", String.Empty);
  171. }
  172. // Load the simulation data service
  173. IConfig simDataConfig = m_config.Source.Configs["SimulationDataStore"];
  174. if (simDataConfig == null)
  175. throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
  176. string module = simDataConfig.GetString("LocalServiceModule", String.Empty);
  177. if (String.IsNullOrEmpty(module))
  178. throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section.");
  179. m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { m_config.Source });
  180. // Load the estate data service
  181. IConfig estateDataConfig = m_config.Source.Configs["EstateDataStore"];
  182. if (estateDataConfig == null)
  183. throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
  184. module = estateDataConfig.GetString("LocalServiceModule", String.Empty);
  185. if (String.IsNullOrEmpty(module))
  186. throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section");
  187. m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { m_config.Source });
  188. base.StartupSpecific();
  189. // Create a ModuleLoader instance
  190. m_moduleLoader = new ModuleLoader(m_config.Source);
  191. LoadPlugins();
  192. foreach (IApplicationPlugin plugin in m_plugins)
  193. {
  194. plugin.PostInitialise();
  195. }
  196. if (m_console != null)
  197. {
  198. StatsManager.RegisterConsoleCommands(m_console);
  199. AddPluginCommands(m_console);
  200. }
  201. }
  202. protected virtual void AddPluginCommands(CommandConsole console)
  203. {
  204. List<string> topics = GetHelpTopics();
  205. foreach (string topic in topics)
  206. {
  207. string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
  208. // This is a hack to allow the user to enter the help command in upper or lowercase. This will go
  209. // away at some point.
  210. console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
  211. "help " + capitalizedTopic,
  212. "Get help on plugin command '" + topic + "'",
  213. HandleCommanderHelp);
  214. console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
  215. "help " + capitalizedTopic,
  216. "Get help on plugin command '" + topic + "'",
  217. HandleCommanderHelp);
  218. ICommander commander = null;
  219. Scene s = SceneManager.CurrentOrFirstScene;
  220. if (s != null && s.GetCommanders() != null)
  221. {
  222. if (s.GetCommanders().ContainsKey(topic))
  223. commander = s.GetCommanders()[topic];
  224. }
  225. if (commander == null)
  226. continue;
  227. foreach (string command in commander.Commands.Keys)
  228. {
  229. console.Commands.AddCommand(capitalizedTopic, false,
  230. topic + " " + command,
  231. topic + " " + commander.Commands[command].ShortHelp(),
  232. String.Empty, HandleCommanderCommand);
  233. }
  234. }
  235. }
  236. private void HandleCommanderCommand(string module, string[] cmd)
  237. {
  238. SceneManager.SendCommandToPluginModules(cmd);
  239. }
  240. private void HandleCommanderHelp(string module, string[] cmd)
  241. {
  242. // Only safe for the interactive console, since it won't
  243. // let us come here unless both scene and commander exist
  244. //
  245. ICommander moduleCommander = SceneManager.CurrentOrFirstScene.GetCommander(cmd[1].ToLower());
  246. if (moduleCommander != null)
  247. m_console.Output(moduleCommander.Help);
  248. }
  249. protected override void Initialize()
  250. {
  251. // Called from base.StartUp()
  252. m_httpServerPort = m_networkServersInfo.HttpListenerPort;
  253. SceneManager.OnRestartSim += handleRestartRegion;
  254. // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
  255. // heavily used during initial startup.
  256. //
  257. // FIXME: It's also possible that region ready status should be flipped during an OAR load since this
  258. // also makes heavy use of the CPU.
  259. SceneManager.OnRegionsReadyStatusChange
  260. += sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
  261. }
  262. /// <summary>
  263. /// Execute the region creation process. This includes setting up scene infrastructure.
  264. /// </summary>
  265. /// <param name="regionInfo"></param>
  266. /// <param name="portadd_flag"></param>
  267. /// <returns></returns>
  268. public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene)
  269. {
  270. return CreateRegion(regionInfo, portadd_flag, false, out scene);
  271. }
  272. /// <summary>
  273. /// Execute the region creation process. This includes setting up scene infrastructure.
  274. /// </summary>
  275. /// <param name="regionInfo"></param>
  276. /// <returns></returns>
  277. public IClientNetworkServer CreateRegion(RegionInfo regionInfo, out IScene scene)
  278. {
  279. return CreateRegion(regionInfo, false, true, out scene);
  280. }
  281. /// <summary>
  282. /// Execute the region creation process. This includes setting up scene infrastructure.
  283. /// </summary>
  284. /// <param name="regionInfo"></param>
  285. /// <param name="portadd_flag"></param>
  286. /// <param name="do_post_init"></param>
  287. /// <returns></returns>
  288. public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene)
  289. {
  290. int port = regionInfo.InternalEndPoint.Port;
  291. // set initial RegionID to originRegionID in RegionInfo. (it needs for loding prims)
  292. // Commented this out because otherwise regions can't register with
  293. // the grid as there is already another region with the same UUID
  294. // at those coordinates. This is required for the load balancer to work.
  295. // --Mike, 2009.02.25
  296. //regionInfo.originRegionID = regionInfo.RegionID;
  297. // set initial ServerURI
  298. regionInfo.HttpPort = m_httpServerPort;
  299. regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort.ToString() + "/";
  300. regionInfo.osSecret = m_osSecret;
  301. if ((proxyUrl.Length > 0) && (portadd_flag))
  302. {
  303. // set proxy url to RegionInfo
  304. regionInfo.proxyUrl = proxyUrl;
  305. regionInfo.ProxyOffset = proxyOffset;
  306. Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName);
  307. }
  308. IClientNetworkServer clientServer;
  309. Scene scene = SetupScene(regionInfo, proxyOffset, m_config.Source, out clientServer);
  310. m_log.Info("[MODULES]: Loading Region's modules (old style)");
  311. List<IRegionModule> modules = m_moduleLoader.PickupModules(scene, ".");
  312. // This needs to be ahead of the script engine load, so the
  313. // script module can pick up events exposed by a module
  314. m_moduleLoader.InitialiseSharedModules(scene);
  315. // Use this in the future, the line above will be deprecated soon
  316. m_log.Info("[REGIONMODULES]: Loading Region's modules (new style)");
  317. IRegionModulesController controller;
  318. if (ApplicationRegistry.TryGet(out controller))
  319. {
  320. controller.AddRegionToModules(scene);
  321. }
  322. else m_log.Error("[REGIONMODULES]: The new RegionModulesController is missing...");
  323. scene.SetModuleInterfaces();
  324. while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
  325. SetUpEstateOwner(scene);
  326. // Prims have to be loaded after module configuration since some modules may be invoked during the load
  327. scene.LoadPrimsFromStorage(regionInfo.originRegionID);
  328. // TODO : Try setting resource for region xstats here on scene
  329. MainServer.Instance.AddStreamHandler(new RegionStatsHandler(regionInfo));
  330. scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
  331. scene.EventManager.TriggerParcelPrimCountUpdate();
  332. try
  333. {
  334. scene.RegisterRegionWithGrid();
  335. }
  336. catch (Exception e)
  337. {
  338. m_log.ErrorFormat(
  339. "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}",
  340. e.Message, e.StackTrace);
  341. // Carrying on now causes a lot of confusion down the
  342. // line - we need to get the user's attention
  343. Environment.Exit(1);
  344. }
  345. // We need to do this after we've initialized the
  346. // scripting engines.
  347. scene.CreateScriptInstances();
  348. SceneManager.Add(scene);
  349. if (m_autoCreateClientStack)
  350. {
  351. m_clientServers.Add(clientServer);
  352. clientServer.Start();
  353. }
  354. if (do_post_init)
  355. {
  356. foreach (IRegionModule module in modules)
  357. {
  358. module.PostInitialise();
  359. }
  360. }
  361. scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); };
  362. mscene = scene;
  363. scene.Start();
  364. scene.StartScripts();
  365. return clientServer;
  366. }
  367. /// <summary>
  368. /// Try to set up the estate owner for the given scene.
  369. /// </summary>
  370. /// <remarks>
  371. /// The involves asking the user for information about the user on the console. If the user does not already
  372. /// exist then it is created.
  373. /// </remarks>
  374. /// <param name="scene"></param>
  375. private void SetUpEstateOwner(Scene scene)
  376. {
  377. RegionInfo regionInfo = scene.RegionInfo;
  378. string estateOwnerFirstName = null;
  379. string estateOwnerLastName = null;
  380. string estateOwnerEMail = null;
  381. string estateOwnerPassword = null;
  382. string rawEstateOwnerUuid = null;
  383. if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null)
  384. {
  385. string defaultEstateOwnerName
  386. = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim();
  387. string[] ownerNames = defaultEstateOwnerName.Split(' ');
  388. if (ownerNames.Length >= 2)
  389. {
  390. estateOwnerFirstName = ownerNames[0];
  391. estateOwnerLastName = ownerNames[1];
  392. }
  393. // Info to be used only on Standalone Mode
  394. rawEstateOwnerUuid = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null);
  395. estateOwnerEMail = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null);
  396. estateOwnerPassword = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null);
  397. }
  398. MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
  399. List<char> excluded = new List<char>(new char[1]{' '});
  400. if (estateOwnerFirstName == null || estateOwnerLastName == null)
  401. {
  402. estateOwnerFirstName = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded);
  403. estateOwnerLastName = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded);
  404. }
  405. UserAccount account
  406. = scene.UserAccountService.GetUserAccount(regionInfo.ScopeID, estateOwnerFirstName, estateOwnerLastName);
  407. if (account == null)
  408. {
  409. // XXX: The LocalUserAccountServicesConnector is currently registering its inner service rather than
  410. // itself!
  411. // if (scene.UserAccountService is LocalUserAccountServicesConnector)
  412. // {
  413. // IUserAccountService innerUas
  414. // = ((LocalUserAccountServicesConnector)scene.UserAccountService).UserAccountService;
  415. //
  416. // m_log.DebugFormat("B {0}", innerUas.GetType());
  417. //
  418. // if (innerUas is UserAccountService)
  419. // {
  420. if (scene.UserAccountService is UserAccountService)
  421. {
  422. if (estateOwnerPassword == null)
  423. estateOwnerPassword = MainConsole.Instance.PasswdPrompt("Password");
  424. if (estateOwnerEMail == null)
  425. estateOwnerEMail = MainConsole.Instance.CmdPrompt("Email");
  426. if (rawEstateOwnerUuid == null)
  427. rawEstateOwnerUuid = MainConsole.Instance.CmdPrompt("User ID", UUID.Random().ToString());
  428. UUID estateOwnerUuid = UUID.Zero;
  429. if (!UUID.TryParse(rawEstateOwnerUuid, out estateOwnerUuid))
  430. {
  431. m_log.ErrorFormat("[OPENSIM]: ID {0} is not a valid UUID", rawEstateOwnerUuid);
  432. return;
  433. }
  434. // If we've been given a zero uuid then this signals that we should use a random user id
  435. if (estateOwnerUuid == UUID.Zero)
  436. estateOwnerUuid = UUID.Random();
  437. account
  438. = ((UserAccountService)scene.UserAccountService).CreateUser(
  439. regionInfo.ScopeID,
  440. estateOwnerUuid,
  441. estateOwnerFirstName,
  442. estateOwnerLastName,
  443. estateOwnerPassword,
  444. estateOwnerEMail);
  445. }
  446. }
  447. if (account == null)
  448. {
  449. m_log.ErrorFormat(
  450. "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level.");
  451. }
  452. else
  453. {
  454. regionInfo.EstateSettings.EstateOwner = account.PrincipalID;
  455. regionInfo.EstateSettings.Save();
  456. }
  457. }
  458. private void ShutdownRegion(Scene scene)
  459. {
  460. m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
  461. IRegionModulesController controller;
  462. if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
  463. {
  464. controller.RemoveRegionFromModules(scene);
  465. }
  466. }
  467. public void RemoveRegion(Scene scene, bool cleanup)
  468. {
  469. // only need to check this if we are not at the
  470. // root level
  471. if ((SceneManager.CurrentScene != null) &&
  472. (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
  473. {
  474. SceneManager.TrySetCurrentScene("..");
  475. }
  476. scene.DeleteAllSceneObjects();
  477. SceneManager.CloseScene(scene);
  478. ShutdownClientServer(scene.RegionInfo);
  479. if (!cleanup)
  480. return;
  481. if (!String.IsNullOrEmpty(scene.RegionInfo.RegionFile))
  482. {
  483. if (scene.RegionInfo.RegionFile.ToLower().EndsWith(".xml"))
  484. {
  485. File.Delete(scene.RegionInfo.RegionFile);
  486. m_log.InfoFormat("[OPENSIM]: deleting region file \"{0}\"", scene.RegionInfo.RegionFile);
  487. }
  488. if (scene.RegionInfo.RegionFile.ToLower().EndsWith(".ini"))
  489. {
  490. try
  491. {
  492. IniConfigSource source = new IniConfigSource(scene.RegionInfo.RegionFile);
  493. if (source.Configs[scene.RegionInfo.RegionName] != null)
  494. {
  495. source.Configs.Remove(scene.RegionInfo.RegionName);
  496. if (source.Configs.Count == 0)
  497. {
  498. File.Delete(scene.RegionInfo.RegionFile);
  499. }
  500. else
  501. {
  502. source.Save(scene.RegionInfo.RegionFile);
  503. }
  504. }
  505. }
  506. catch (Exception)
  507. {
  508. }
  509. }
  510. }
  511. }
  512. public void RemoveRegion(string name, bool cleanUp)
  513. {
  514. Scene target;
  515. if (SceneManager.TryGetScene(name, out target))
  516. RemoveRegion(target, cleanUp);
  517. }
  518. /// <summary>
  519. /// Remove a region from the simulator without deleting it permanently.
  520. /// </summary>
  521. /// <param name="scene"></param>
  522. /// <returns></returns>
  523. public void CloseRegion(Scene scene)
  524. {
  525. // only need to check this if we are not at the
  526. // root level
  527. if ((SceneManager.CurrentScene != null) &&
  528. (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
  529. {
  530. SceneManager.TrySetCurrentScene("..");
  531. }
  532. SceneManager.CloseScene(scene);
  533. ShutdownClientServer(scene.RegionInfo);
  534. }
  535. /// <summary>
  536. /// Remove a region from the simulator without deleting it permanently.
  537. /// </summary>
  538. /// <param name="name"></param>
  539. /// <returns></returns>
  540. public void CloseRegion(string name)
  541. {
  542. Scene target;
  543. if (SceneManager.TryGetScene(name, out target))
  544. CloseRegion(target);
  545. }
  546. /// <summary>
  547. /// Create a scene and its initial base structures.
  548. /// </summary>
  549. /// <param name="regionInfo"></param>
  550. /// <param name="clientServer"> </param>
  551. /// <returns></returns>
  552. protected Scene SetupScene(RegionInfo regionInfo, out IClientNetworkServer clientServer)
  553. {
  554. return SetupScene(regionInfo, 0, null, out clientServer);
  555. }
  556. /// <summary>
  557. /// Create a scene and its initial base structures.
  558. /// </summary>
  559. /// <param name="regionInfo"></param>
  560. /// <param name="proxyOffset"></param>
  561. /// <param name="configSource"></param>
  562. /// <param name="clientServer"> </param>
  563. /// <returns></returns>
  564. protected Scene SetupScene(
  565. RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out IClientNetworkServer clientServer)
  566. {
  567. AgentCircuitManager circuitManager = new AgentCircuitManager();
  568. IPAddress listenIP = regionInfo.InternalEndPoint.Address;
  569. //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP))
  570. // listenIP = IPAddress.Parse("0.0.0.0");
  571. uint port = (uint) regionInfo.InternalEndPoint.Port;
  572. if (m_autoCreateClientStack)
  573. {
  574. clientServer
  575. = m_clientStackManager.CreateServer(
  576. listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, configSource,
  577. circuitManager);
  578. }
  579. else
  580. {
  581. clientServer = null;
  582. }
  583. regionInfo.InternalEndPoint.Port = (int) port;
  584. Scene scene = CreateScene(regionInfo, m_simulationDataService, m_estateDataService, circuitManager);
  585. if (m_autoCreateClientStack)
  586. {
  587. clientServer.AddScene(scene);
  588. }
  589. scene.LoadWorldMap();
  590. scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
  591. scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset;
  592. scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
  593. scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight);
  594. return scene;
  595. }
  596. protected override ClientStackManager CreateClientStackManager()
  597. {
  598. return new ClientStackManager(m_configSettings.ClientstackDll);
  599. }
  600. protected override Scene CreateScene(RegionInfo regionInfo, ISimulationDataService simDataService,
  601. IEstateDataService estateDataService, AgentCircuitManager circuitManager)
  602. {
  603. SceneCommunicationService sceneGridService = new SceneCommunicationService();
  604. return new Scene(
  605. regionInfo, circuitManager, sceneGridService,
  606. simDataService, estateDataService, m_moduleLoader, false,
  607. m_config.Source, m_version);
  608. }
  609. protected void ShutdownClientServer(RegionInfo whichRegion)
  610. {
  611. // Close and remove the clientserver for a region
  612. bool foundClientServer = false;
  613. int clientServerElement = 0;
  614. Location location = new Location(whichRegion.RegionHandle);
  615. for (int i = 0; i < m_clientServers.Count; i++)
  616. {
  617. if (m_clientServers[i].HandlesRegion(location))
  618. {
  619. clientServerElement = i;
  620. foundClientServer = true;
  621. break;
  622. }
  623. }
  624. if (foundClientServer)
  625. {
  626. m_clientServers[clientServerElement].NetworkStop();
  627. m_clientServers.RemoveAt(clientServerElement);
  628. }
  629. }
  630. public void handleRestartRegion(RegionInfo whichRegion)
  631. {
  632. m_log.Info("[OPENSIM]: Got restart signal from SceneManager");
  633. ShutdownClientServer(whichRegion);
  634. IScene scene;
  635. CreateRegion(whichRegion, true, out scene);
  636. }
  637. # region Setup methods
  638. protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier)
  639. {
  640. return GetPhysicsScene(
  641. m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, m_config.Source, osSceneIdentifier);
  642. }
  643. /// <summary>
  644. /// Handler to supply the current status of this sim
  645. /// </summary>
  646. /// Currently this is always OK if the simulator is still listening for connections on its HTTP service
  647. public class SimStatusHandler : IStreamedRequestHandler
  648. {
  649. public byte[] Handle(string path, Stream request,
  650. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  651. {
  652. return Util.UTF8.GetBytes("OK");
  653. }
  654. public string Name { get { return "SimStatus"; } }
  655. public string Description { get { return "Simulator Status"; } }
  656. public string ContentType
  657. {
  658. get { return "text/plain"; }
  659. }
  660. public string HttpMethod
  661. {
  662. get { return "GET"; }
  663. }
  664. public string Path
  665. {
  666. get { return "/simstatus"; }
  667. }
  668. }
  669. /// <summary>
  670. /// Handler to supply the current extended status of this sim
  671. /// Sends the statistical data in a json serialization
  672. /// </summary>
  673. public class XSimStatusHandler : IStreamedRequestHandler
  674. {
  675. OpenSimBase m_opensim;
  676. string osXStatsURI = String.Empty;
  677. public string Name { get { return "XSimStatus"; } }
  678. public string Description { get { return "Simulator XStatus"; } }
  679. public XSimStatusHandler(OpenSimBase sim)
  680. {
  681. m_opensim = sim;
  682. osXStatsURI = Util.SHA1Hash(sim.osSecret);
  683. }
  684. public byte[] Handle(string path, Stream request,
  685. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  686. {
  687. return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
  688. }
  689. public string ContentType
  690. {
  691. get { return "text/plain"; }
  692. }
  693. public string HttpMethod
  694. {
  695. get { return "GET"; }
  696. }
  697. public string Path
  698. {
  699. // This is for the OpenSimulator instance and is the osSecret hashed
  700. get { return "/" + osXStatsURI; }
  701. }
  702. }
  703. /// <summary>
  704. /// Handler to supply the current extended status of this sim to a user configured URI
  705. /// Sends the statistical data in a json serialization
  706. /// If the request contains a key, "callback" the response will be wrappend in the
  707. /// associated value for jsonp used with ajax/javascript
  708. /// </summary>
  709. public class UXSimStatusHandler : IStreamedRequestHandler
  710. {
  711. OpenSimBase m_opensim;
  712. string osUXStatsURI = String.Empty;
  713. public string Name { get { return "UXSimStatus"; } }
  714. public string Description { get { return "Simulator UXStatus"; } }
  715. public UXSimStatusHandler(OpenSimBase sim)
  716. {
  717. m_opensim = sim;
  718. osUXStatsURI = sim.userStatsURI;
  719. }
  720. public byte[] Handle(string path, Stream request,
  721. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  722. {
  723. return Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
  724. }
  725. public string ContentType
  726. {
  727. get { return "text/plain"; }
  728. }
  729. public string HttpMethod
  730. {
  731. get { return "GET"; }
  732. }
  733. public string Path
  734. {
  735. // This is for the OpenSimulator instance and is the user provided URI
  736. get { return "/" + osUXStatsURI; }
  737. }
  738. }
  739. #endregion
  740. /// <summary>
  741. /// Performs any last-minute sanity checking and shuts down the region server
  742. /// </summary>
  743. public override void ShutdownSpecific()
  744. {
  745. if (proxyUrl.Length > 0)
  746. {
  747. Util.XmlRpcCommand(proxyUrl, "Stop");
  748. }
  749. m_log.Info("[SHUTDOWN]: Closing all threads");
  750. m_log.Info("[SHUTDOWN]: Killing listener thread");
  751. m_log.Info("[SHUTDOWN]: Killing clients");
  752. // TODO: implement this
  753. m_log.Info("[SHUTDOWN]: Closing console and terminating");
  754. try
  755. {
  756. SceneManager.Close();
  757. }
  758. catch (Exception e)
  759. {
  760. m_log.ErrorFormat("[SHUTDOWN]: Ignoring failure during shutdown - {0}", e);
  761. }
  762. }
  763. /// <summary>
  764. /// Get the start time and up time of Region server
  765. /// </summary>
  766. /// <param name="starttime">The first out parameter describing when the Region server started</param>
  767. /// <param name="uptime">The second out parameter describing how long the Region server has run</param>
  768. public void GetRunTime(out string starttime, out string uptime)
  769. {
  770. starttime = m_startuptime.ToString();
  771. uptime = (DateTime.Now - m_startuptime).ToString();
  772. }
  773. /// <summary>
  774. /// Get the number of the avatars in the Region server
  775. /// </summary>
  776. /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
  777. public void GetAvatarNumber(out int usernum)
  778. {
  779. usernum = SceneManager.GetCurrentSceneAvatars().Count;
  780. }
  781. /// <summary>
  782. /// Get the number of regions
  783. /// </summary>
  784. /// <param name="regionnum">The first out parameter describing the number of regions</param>
  785. public void GetRegionNumber(out int regionnum)
  786. {
  787. regionnum = SceneManager.Scenes.Count;
  788. }
  789. /// <summary>
  790. /// Create an estate with an initial region.
  791. /// </summary>
  792. /// <remarks>
  793. /// This method doesn't allow an estate to be created with the same name as existing estates.
  794. /// </remarks>
  795. /// <param name="regInfo"></param>
  796. /// <param name="estatesByName">A list of estate names that already exist.</param>
  797. /// <param name="estateName">Estate name to create if already known</param>
  798. /// <returns>true if the estate was created, false otherwise</returns>
  799. public bool CreateEstate(RegionInfo regInfo, Dictionary<string, EstateSettings> estatesByName, string estateName)
  800. {
  801. // Create a new estate
  802. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
  803. string newName;
  804. if (estateName != null && estateName != "")
  805. newName = estateName;
  806. else
  807. newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
  808. if (estatesByName.ContainsKey(newName))
  809. {
  810. MainConsole.Instance.OutputFormat("An estate named {0} already exists. Please try again.", newName);
  811. return false;
  812. }
  813. regInfo.EstateSettings.EstateName = newName;
  814. // FIXME: Later on, the scene constructor will reload the estate settings no matter what.
  815. // Therefore, we need to do an initial save here otherwise the new estate name will be reset
  816. // back to the default. The reloading of estate settings by scene could be eliminated if it
  817. // knows that the passed in settings in RegionInfo are already valid. Also, it might be
  818. // possible to eliminate some additional later saves made by callers of this method.
  819. regInfo.EstateSettings.Save();
  820. return true;
  821. }
  822. /// <summary>
  823. /// Load the estate information for the provided RegionInfo object.
  824. /// </summary>
  825. /// <param name="regInfo"></param>
  826. public bool PopulateRegionEstateInfo(RegionInfo regInfo)
  827. {
  828. if (EstateDataService != null)
  829. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false);
  830. if (regInfo.EstateSettings.EstateID != 0)
  831. return false; // estate info in the database did not change
  832. m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName);
  833. List<EstateSettings> estates = EstateDataService.LoadEstateSettingsAll();
  834. Dictionary<string, EstateSettings> estatesByName = new Dictionary<string, EstateSettings>();
  835. foreach (EstateSettings estate in estates)
  836. estatesByName[estate.EstateName] = estate;
  837. string defaultEstateName = null;
  838. if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null)
  839. {
  840. defaultEstateName = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
  841. if (defaultEstateName != null)
  842. {
  843. EstateSettings defaultEstate;
  844. bool defaultEstateJoined = false;
  845. if (estatesByName.ContainsKey(defaultEstateName))
  846. {
  847. defaultEstate = estatesByName[defaultEstateName];
  848. if (EstateDataService.LinkRegion(regInfo.RegionID, (int)defaultEstate.EstateID))
  849. defaultEstateJoined = true;
  850. }
  851. else
  852. {
  853. if (CreateEstate(regInfo, estatesByName, defaultEstateName))
  854. defaultEstateJoined = true;
  855. }
  856. if (defaultEstateJoined)
  857. return true; // need to update the database
  858. else
  859. m_log.ErrorFormat(
  860. "[OPENSIM BASE]: Joining default estate {0} failed", defaultEstateName);
  861. }
  862. }
  863. // If we have no default estate or creation of the default estate failed then ask the user.
  864. while (true)
  865. {
  866. if (estates.Count == 0)
  867. {
  868. m_log.Info("[ESTATE]: No existing estates found. You must create a new one.");
  869. if (CreateEstate(regInfo, estatesByName, null))
  870. break;
  871. else
  872. continue;
  873. }
  874. else
  875. {
  876. string response
  877. = MainConsole.Instance.CmdPrompt(
  878. string.Format(
  879. "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
  880. "yes",
  881. new List<string>() { "yes", "no" });
  882. if (response == "no")
  883. {
  884. if (CreateEstate(regInfo, estatesByName, null))
  885. break;
  886. else
  887. continue;
  888. }
  889. else
  890. {
  891. string[] estateNames = estatesByName.Keys.ToArray();
  892. response
  893. = MainConsole.Instance.CmdPrompt(
  894. string.Format(
  895. "Name of estate to join. Existing estate names are ({0})",
  896. string.Join(", ", estateNames)),
  897. estateNames[0]);
  898. List<int> estateIDs = EstateDataService.GetEstates(response);
  899. if (estateIDs.Count < 1)
  900. {
  901. MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
  902. continue;
  903. }
  904. int estateID = estateIDs[0];
  905. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID);
  906. if (EstateDataService.LinkRegion(regInfo.RegionID, estateID))
  907. break;
  908. MainConsole.Instance.Output("Joining the estate failed. Please try again.");
  909. }
  910. }
  911. }
  912. return true; // need to update the database
  913. }
  914. }
  915. public class OpenSimConfigSource
  916. {
  917. public IConfigSource Source;
  918. public void Save(string path)
  919. {
  920. if (Source is IniConfigSource)
  921. {
  922. IniConfigSource iniCon = (IniConfigSource) Source;
  923. iniCon.Save(path);
  924. }
  925. else if (Source is XmlConfigSource)
  926. {
  927. XmlConfigSource xmlCon = (XmlConfigSource) Source;
  928. xmlCon.Save(path);
  929. }
  930. }
  931. }
  932. }