OpenSimBase.cs 45 KB

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