OpenSimBase.cs 43 KB

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