OpenSimBase.cs 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  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. //##
  880. // Target Estate Specified in Region.ini
  881. string targetEstateName = regInfo.GetSetting("TargetEstate");
  882. if (targetEstateName != null && targetEstateName != string.Empty)
  883. {
  884. bool targetEstateJoined = false;
  885. if (Int32.TryParse(targetEstateName, out int targetEstateID) && targetEstateID > 99)
  886. {
  887. // Attempt to join the target estate given in Config by ID
  888. foreach (EstateSettings estate in estates)
  889. {
  890. if (estate.EstateID == targetEstateID)
  891. {
  892. if (EstateDataService.LinkRegion(regInfo.RegionID, targetEstateID))
  893. targetEstateJoined = true;
  894. break;
  895. }
  896. }
  897. }
  898. else
  899. {
  900. // Attempt to join the target estate given in Config by name
  901. EstateSettings targetEstate;
  902. if (estatesByName.ContainsKey(targetEstateName))
  903. {
  904. targetEstate = estatesByName[targetEstateName];
  905. if (EstateDataService.LinkRegion(regInfo.RegionID, (int)targetEstate.EstateID))
  906. targetEstateJoined = true;
  907. }
  908. }
  909. if (targetEstateJoined)
  910. return true; // need to update the database
  911. else
  912. m_log.ErrorFormat(
  913. "[OPENSIM BASE]: Joining target estate specified in region config {0} failed", targetEstateName);
  914. }
  915. //##
  916. // Default Estate
  917. if (Config.Configs[ESTATE_SECTION_NAME] != null)
  918. {
  919. string defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
  920. if (defaultEstateName != null)
  921. {
  922. EstateSettings defaultEstate;
  923. bool defaultEstateJoined = false;
  924. if (estatesByName.ContainsKey(defaultEstateName))
  925. {
  926. defaultEstate = estatesByName[defaultEstateName];
  927. if (EstateDataService.LinkRegion(regInfo.RegionID, (int)defaultEstate.EstateID))
  928. defaultEstateJoined = true;
  929. }
  930. else
  931. {
  932. if (CreateEstate(regInfo, estatesByName, defaultEstateName))
  933. defaultEstateJoined = true;
  934. }
  935. if (defaultEstateJoined)
  936. return true; // need to update the database
  937. else
  938. m_log.ErrorFormat(
  939. "[OPENSIM BASE]: Joining default estate {0} failed", defaultEstateName);
  940. }
  941. }
  942. // If we have no default estate or creation of the default estate failed then ask the user.
  943. while (true)
  944. {
  945. if (estates.Count == 0)
  946. {
  947. m_log.Info("[ESTATE]: No existing estates found. You must create a new one.");
  948. if (CreateEstate(regInfo, estatesByName, null))
  949. break;
  950. else
  951. continue;
  952. }
  953. else
  954. {
  955. string response
  956. = MainConsole.Instance.Prompt(
  957. string.Format(
  958. "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
  959. "yes",
  960. new List<string>() { "yes", "no" });
  961. if (response == "no")
  962. {
  963. if (CreateEstate(regInfo, estatesByName, null))
  964. break;
  965. else
  966. continue;
  967. }
  968. else
  969. {
  970. string[] estateNames = estatesByName.Keys.ToArray();
  971. response
  972. = MainConsole.Instance.Prompt(
  973. string.Format(
  974. "Name of estate to join. Existing estate names are ({0})",
  975. string.Join(", ", estateNames)),
  976. estateNames[0]);
  977. List<int> estateIDs = EstateDataService.GetEstates(response);
  978. if (estateIDs.Count < 1)
  979. {
  980. MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
  981. continue;
  982. }
  983. int estateID = estateIDs[0];
  984. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID);
  985. if (EstateDataService.LinkRegion(regInfo.RegionID, estateID))
  986. break;
  987. MainConsole.Instance.Output("Joining the estate failed. Please try again.");
  988. }
  989. }
  990. }
  991. return true; // need to update the database
  992. }
  993. }
  994. public class OpenSimConfigSource
  995. {
  996. public IConfigSource Source;
  997. }
  998. }