OpenSimBase.cs 41 KB

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