OpenSimBase.cs 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  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.Length == 0)
  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. // Sure is not the right place for this but do the job...
  296. // Must always be called before (all) / the HTTP servers starting for the Certs creation or renewals.
  297. if(startupConfig.GetBoolean("EnableSelfsignedCertSupport", false))
  298. {
  299. if(!File.Exists("SSL\\ssl\\"+ startupConfig.GetString("CertFileName") +".p12") || startupConfig.GetBoolean("CertRenewOnStartup"))
  300. {
  301. Util.CreateOrUpdateSelfsignedCert(
  302. string.IsNullOrEmpty(startupConfig.GetString("CertFileName")) ? "OpenSim" : startupConfig.GetString("CertFileName"),
  303. string.IsNullOrEmpty(startupConfig.GetString("CertHostName")) ? "localhost" : startupConfig.GetString("CertHostName"),
  304. string.IsNullOrEmpty(startupConfig.GetString("CertHostIp")) ? "127.0.0.1" : startupConfig.GetString("CertHostIp"),
  305. string.IsNullOrEmpty(startupConfig.GetString("CertPassword")) ? string.Empty : startupConfig.GetString("CertPassword")
  306. );
  307. }
  308. }
  309. if(startupConfig.GetBoolean("EnableCertConverter", false))
  310. {
  311. Util.ConvertPemToPKCS12(
  312. string.IsNullOrEmpty(startupConfig.GetString("outputCertName")) ? "letsencrypt" : startupConfig.GetString("outputCertName"),
  313. string.IsNullOrEmpty(startupConfig.GetString("PemCertPublicKey")) ? string.Empty : startupConfig.GetString("PemCertPublicKey"),
  314. string.IsNullOrEmpty(startupConfig.GetString("PemCertPrivateKey")) ? string.Empty : startupConfig.GetString("PemCertPrivateKey"),
  315. string.IsNullOrEmpty(startupConfig.GetString("outputCertPassword")) ? string.Empty : startupConfig.GetString("outputCertPassword")
  316. );
  317. }
  318. if(m_networkServersInfo.HttpUsesSSL)
  319. {
  320. m_httpServerSSL = true;
  321. m_httpServerPort = m_networkServersInfo.httpSSLPort;
  322. }
  323. else
  324. {
  325. m_httpServerSSL = false;
  326. m_httpServerPort = m_networkServersInfo.HttpListenerPort;
  327. }
  328. SceneManager.OnRestartSim += HandleRestartRegion;
  329. // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
  330. // heavily used during initial startup.
  331. //
  332. // FIXME: It's also possible that region ready status should be flipped during an OAR load since this
  333. // also makes heavy use of the CPU.
  334. SceneManager.OnRegionsReadyStatusChange
  335. += sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
  336. }
  337. /// <summary>
  338. /// Execute the region creation process. This includes setting up scene infrastructure.
  339. /// </summary>
  340. /// <param name="regionInfo"></param>
  341. /// <param name="portadd_flag"></param>
  342. /// <returns></returns>
  343. public void CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene)
  344. {
  345. CreateRegion(regionInfo, portadd_flag, false, out scene);
  346. }
  347. /// <summary>
  348. /// Execute the region creation process. This includes setting up scene infrastructure.
  349. /// </summary>
  350. /// <param name="regionInfo"></param>
  351. /// <returns></returns>
  352. public void CreateRegion(RegionInfo regionInfo, out IScene scene)
  353. {
  354. CreateRegion(regionInfo, false, true, out scene);
  355. }
  356. /// <summary>
  357. /// Execute the region creation process. This includes setting up scene infrastructure.
  358. /// </summary>
  359. /// <param name="regionInfo"></param>
  360. /// <param name="portadd_flag"></param>
  361. /// <param name="do_post_init"></param>
  362. /// <returns></returns>
  363. public void CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene)
  364. {
  365. IRegionModulesController controller;
  366. if (!ApplicationRegistry.TryGet(out controller))
  367. {
  368. m_log.Fatal("REGIONMODULES]: The new RegionModulesController is missing...");
  369. Environment.Exit(0);
  370. }
  371. int port = regionInfo.InternalEndPoint.Port;
  372. // set initial RegionID to originRegionID in RegionInfo. (it needs for loding prims)
  373. // Commented this out because otherwise regions can't register with
  374. // the grid as there is already another region with the same UUID
  375. // at those coordinates. This is required for the load balancer to work.
  376. // --Mike, 2009.02.25
  377. //regionInfo.originRegionID = regionInfo.RegionID;
  378. // set initial ServerURI
  379. regionInfo.HttpPort = m_httpServerPort;
  380. if(m_httpServerSSL)
  381. {
  382. if(!m_httpServer.CheckSSLCertHost(regionInfo.ExternalHostName))
  383. throw new Exception("main http cert CN doesn't match region External IP");
  384. regionInfo.ServerURI = "https://" + regionInfo.ExternalHostName +
  385. ":" + regionInfo.HttpPort.ToString() + "/";
  386. }
  387. else
  388. regionInfo.ServerURI = "http://" + regionInfo.ExternalHostName +
  389. ":" + regionInfo.HttpPort.ToString() + "/";
  390. regionInfo.osSecret = m_osSecret;
  391. if ((proxyUrl.Length > 0) && (portadd_flag))
  392. {
  393. // set proxy url to RegionInfo
  394. regionInfo.proxyUrl = proxyUrl;
  395. regionInfo.ProxyOffset = proxyOffset;
  396. Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName);
  397. }
  398. Scene scene = SetupScene(regionInfo, proxyOffset, Config);
  399. m_log.Info("[REGIONMODULES]: Loading Region's modules");
  400. if (controller != null)
  401. controller.AddRegionToModules(scene);
  402. if (m_securePermissionsLoading)
  403. {
  404. foreach (string s in m_permsModules)
  405. {
  406. if (!scene.RegionModules.ContainsKey(s))
  407. {
  408. m_log.Fatal("[MODULES]: Required module " + s + " not found.");
  409. Environment.Exit(0);
  410. }
  411. }
  412. m_log.InfoFormat("[SCENE]: Secure permissions loading enabled, modules loaded: {0}", String.Join(" ", m_permsModules.ToArray()));
  413. }
  414. scene.SetModuleInterfaces();
  415. // First Step of bootreport sequence
  416. if (scene.SnmpService != null)
  417. {
  418. scene.SnmpService.ColdStart(1,scene);
  419. scene.SnmpService.LinkDown(scene);
  420. }
  421. if (scene.SnmpService != null)
  422. {
  423. scene.SnmpService.BootInfo("Loading prims", scene);
  424. }
  425. while (regionInfo.EstateSettings.EstateOwner.IsZero() && MainConsole.Instance != null)
  426. SetUpEstateOwner(scene);
  427. scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID);
  428. // Prims have to be loaded after module configuration since some modules may be invoked during the load
  429. scene.LoadPrimsFromStorage(regionInfo.originRegionID);
  430. // TODO : Try setting resource for region xstats here on scene
  431. MainServer.Instance.AddSimpleStreamHandler(new RegionStatsSimpleHandler(regionInfo));
  432. if (scene.SnmpService != null)
  433. {
  434. scene.SnmpService.BootInfo("Grid Registration in progress", scene);
  435. }
  436. try
  437. {
  438. scene.RegisterRegionWithGrid();
  439. }
  440. catch (Exception e)
  441. {
  442. m_log.ErrorFormat(
  443. "[STARTUP]: Registration of region with grid failed, aborting startup due to {0} {1}",
  444. e.Message, e.StackTrace);
  445. if (scene.SnmpService != null)
  446. {
  447. scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene);
  448. }
  449. // Carrying on now causes a lot of confusion down the
  450. // line - we need to get the user's attention
  451. Environment.Exit(1);
  452. }
  453. if (scene.SnmpService != null)
  454. {
  455. scene.SnmpService.BootInfo("Grid Registration done", scene);
  456. }
  457. // We need to do this after we've initialized the scripting engines.
  458. scene.CreateScriptInstances();
  459. if (scene.SnmpService != null)
  460. {
  461. scene.SnmpService.BootInfo("ScriptEngine started", scene);
  462. }
  463. SceneManager.Add(scene);
  464. //if (m_autoCreateClientStack)
  465. //{
  466. // foreach (IClientNetworkServer clientserver in clientServers)
  467. // {
  468. // m_clientServers.Add(clientserver);
  469. // clientserver.Start();
  470. // }
  471. //}
  472. if (scene.SnmpService != null)
  473. {
  474. scene.SnmpService.BootInfo("Initializing region modules", scene);
  475. }
  476. scene.EventManager.OnShutdown += delegate() { ShutdownRegion(scene); };
  477. mscene = scene;
  478. if (scene.SnmpService != null)
  479. {
  480. scene.SnmpService.BootInfo("The region is operational", scene);
  481. scene.SnmpService.LinkUp(scene);
  482. }
  483. //return clientServers;
  484. }
  485. /// <summary>
  486. /// Try to set up the estate owner for the given scene.
  487. /// </summary>
  488. /// <remarks>
  489. /// The involves asking the user for information about the user on the console. If the user does not already
  490. /// exist then it is created.
  491. /// </remarks>
  492. /// <param name="scene"></param>
  493. private void SetUpEstateOwner(Scene scene)
  494. {
  495. RegionInfo regionInfo = scene.RegionInfo;
  496. string estateOwnerFirstName = null;
  497. string estateOwnerLastName = null;
  498. string estateOwnerEMail = null;
  499. string estateOwnerPassword = null;
  500. string rawEstateOwnerUuid = null;
  501. if (Config.Configs[ESTATE_SECTION_NAME] != null)
  502. {
  503. string defaultEstateOwnerName
  504. = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim();
  505. string[] ownerNames = defaultEstateOwnerName.Split(' ');
  506. if (ownerNames.Length >= 2)
  507. {
  508. estateOwnerFirstName = ownerNames[0];
  509. estateOwnerLastName = ownerNames[1];
  510. }
  511. // Info to be used only on Standalone Mode
  512. rawEstateOwnerUuid = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null);
  513. estateOwnerEMail = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null);
  514. estateOwnerPassword = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null);
  515. }
  516. MainConsole.Instance.Output("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
  517. List<char> excluded = new List<char>(new char[1]{' '});
  518. if (estateOwnerFirstName == null || estateOwnerLastName == null)
  519. {
  520. estateOwnerFirstName = MainConsole.Instance.Prompt("Estate owner first name", "Test", excluded);
  521. estateOwnerLastName = MainConsole.Instance.Prompt("Estate owner last name", "User", excluded);
  522. }
  523. UserAccount account
  524. = scene.UserAccountService.GetUserAccount(regionInfo.ScopeID, estateOwnerFirstName, estateOwnerLastName);
  525. if (account == null)
  526. {
  527. // XXX: The LocalUserAccountServicesConnector is currently registering its inner service rather than
  528. // itself!
  529. // if (scene.UserAccountService is LocalUserAccountServicesConnector)
  530. // {
  531. // IUserAccountService innerUas
  532. // = ((LocalUserAccountServicesConnector)scene.UserAccountService).UserAccountService;
  533. //
  534. // m_log.DebugFormat("B {0}", innerUas.GetType());
  535. //
  536. // if (innerUas is UserAccountService)
  537. // {
  538. if (scene.UserAccountService is UserAccountService)
  539. {
  540. if (estateOwnerPassword == null)
  541. estateOwnerPassword = MainConsole.Instance.Prompt("Password", null, null, false);
  542. if (estateOwnerEMail == null)
  543. estateOwnerEMail = MainConsole.Instance.Prompt("Email");
  544. if (rawEstateOwnerUuid == null)
  545. rawEstateOwnerUuid = MainConsole.Instance.Prompt("User ID", UUID.Random().ToString());
  546. UUID estateOwnerUuid = UUID.Zero;
  547. if (!UUID.TryParse(rawEstateOwnerUuid, out estateOwnerUuid))
  548. {
  549. m_log.ErrorFormat("[OPENSIM]: ID {0} is not a valid UUID", rawEstateOwnerUuid);
  550. return;
  551. }
  552. // If we've been given a zero uuid then this signals that we should use a random user id
  553. if (estateOwnerUuid.IsZero())
  554. estateOwnerUuid = UUID.Random();
  555. account
  556. = ((UserAccountService)scene.UserAccountService).CreateUser(
  557. regionInfo.ScopeID,
  558. estateOwnerUuid,
  559. estateOwnerFirstName,
  560. estateOwnerLastName,
  561. estateOwnerPassword,
  562. estateOwnerEMail);
  563. }
  564. }
  565. if (account == null)
  566. {
  567. m_log.ErrorFormat(
  568. "[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.");
  569. }
  570. else
  571. {
  572. regionInfo.EstateSettings.EstateOwner = account.PrincipalID;
  573. m_estateDataService.StoreEstateSettings(regionInfo.EstateSettings);
  574. }
  575. }
  576. private void ShutdownRegion(Scene scene)
  577. {
  578. m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName);
  579. if (scene.SnmpService != null)
  580. {
  581. scene.SnmpService.BootInfo("The region is shutting down", scene);
  582. scene.SnmpService.LinkDown(scene);
  583. }
  584. IRegionModulesController controller;
  585. if (ApplicationRegistry.TryGet<IRegionModulesController>(out controller))
  586. {
  587. controller.RemoveRegionFromModules(scene);
  588. }
  589. }
  590. public void RemoveRegion(Scene scene, bool cleanup)
  591. {
  592. // only need to check this if we are not at the
  593. // root level
  594. if ((SceneManager.CurrentScene != null) &&
  595. (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
  596. {
  597. SceneManager.TrySetCurrentScene("..");
  598. }
  599. scene.DeleteAllSceneObjects();
  600. SceneManager.CloseScene(scene);
  601. //ShutdownClientServer(scene.RegionInfo);
  602. if (!cleanup)
  603. return;
  604. if (!String.IsNullOrEmpty(scene.RegionInfo.RegionFile))
  605. {
  606. if (scene.RegionInfo.RegionFile.ToLower().EndsWith(".xml"))
  607. {
  608. File.Delete(scene.RegionInfo.RegionFile);
  609. m_log.InfoFormat("[OPENSIM]: deleting region file \"{0}\"", scene.RegionInfo.RegionFile);
  610. }
  611. if (scene.RegionInfo.RegionFile.ToLower().EndsWith(".ini"))
  612. {
  613. try
  614. {
  615. IniConfigSource source = new IniConfigSource(scene.RegionInfo.RegionFile);
  616. if (source.Configs[scene.RegionInfo.RegionName] != null)
  617. {
  618. source.Configs.Remove(scene.RegionInfo.RegionName);
  619. if (source.Configs.Count == 0)
  620. {
  621. File.Delete(scene.RegionInfo.RegionFile);
  622. }
  623. else
  624. {
  625. source.Save(scene.RegionInfo.RegionFile);
  626. }
  627. }
  628. }
  629. catch (Exception)
  630. {
  631. }
  632. }
  633. }
  634. }
  635. public void RemoveRegion(string name, bool cleanUp)
  636. {
  637. Scene target;
  638. if (SceneManager.TryGetScene(name, out target))
  639. RemoveRegion(target, cleanUp);
  640. }
  641. /// <summary>
  642. /// Remove a region from the simulator without deleting it permanently.
  643. /// </summary>
  644. /// <param name="scene"></param>
  645. /// <returns></returns>
  646. public void CloseRegion(Scene scene)
  647. {
  648. // only need to check this if we are not at the
  649. // root level
  650. if ((SceneManager.CurrentScene != null) &&
  651. (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
  652. {
  653. SceneManager.TrySetCurrentScene("..");
  654. }
  655. SceneManager.CloseScene(scene);
  656. //ShutdownClientServer(scene.RegionInfo);
  657. }
  658. /// <summary>
  659. /// Remove a region from the simulator without deleting it permanently.
  660. /// </summary>
  661. /// <param name="name"></param>
  662. /// <returns></returns>
  663. public void CloseRegion(string name)
  664. {
  665. Scene target;
  666. if (SceneManager.TryGetScene(name, out target))
  667. CloseRegion(target);
  668. }
  669. /// <summary>
  670. /// Create a scene and its initial base structures.
  671. /// </summary>
  672. /// <param name="regionInfo"></param>
  673. /// <param name="clientServer"> </param>
  674. /// <returns></returns>
  675. protected Scene SetupScene(RegionInfo regionInfo)
  676. {
  677. return SetupScene(regionInfo, 0, null);
  678. }
  679. /// <summary>
  680. /// Create a scene and its initial base structures.
  681. /// </summary>
  682. /// <param name="regionInfo"></param>
  683. /// <param name="proxyOffset"></param>
  684. /// <param name="configSource"></param>
  685. /// <param name="clientServer"> </param>
  686. /// <returns></returns>
  687. protected Scene SetupScene(RegionInfo regionInfo, int proxyOffset, IConfigSource configSource)
  688. {
  689. //List<IClientNetworkServer> clientNetworkServers = null;
  690. AgentCircuitManager circuitManager = new AgentCircuitManager();
  691. Scene scene = CreateScene(regionInfo, m_simulationDataService, m_estateDataService, circuitManager);
  692. scene.LoadWorldMap();
  693. return scene;
  694. }
  695. protected override Scene CreateScene(RegionInfo regionInfo, ISimulationDataService simDataService,
  696. IEstateDataService estateDataService, AgentCircuitManager circuitManager)
  697. {
  698. return new Scene(
  699. regionInfo, circuitManager,
  700. simDataService, estateDataService,
  701. Config, m_version);
  702. }
  703. protected virtual void HandleRestartRegion(RegionInfo whichRegion)
  704. {
  705. m_log.InfoFormat(
  706. "[OPENSIM]: Got restart signal from SceneManager for region {0} ({1},{2})",
  707. whichRegion.RegionName, whichRegion.RegionLocX, whichRegion.RegionLocY);
  708. //ShutdownClientServer(whichRegion);
  709. IScene scene;
  710. CreateRegion(whichRegion, true, out scene);
  711. scene.Start();
  712. }
  713. # region Setup methods
  714. /// <summary>
  715. /// Handler to supply the current status of this sim
  716. /// </summary>
  717. /// <remarks>
  718. /// Currently this is always OK if the simulator is still listening for connections on its HTTP service
  719. /// </remarks>
  720. public class SimStatusHandler : SimpleStreamHandler
  721. {
  722. public SimStatusHandler() : base("/simstatus", "SimStatus") {}
  723. protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  724. {
  725. httpResponse.KeepAlive = false;
  726. httpResponse.RawBuffer = Util.UTF8.GetBytes("OK");
  727. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  728. }
  729. }
  730. /// <summary>
  731. /// Handler to supply the current extended status of this sim
  732. /// Sends the statistical data in a json serialization
  733. /// </summary>
  734. public class XSimStatusHandler : SimpleStreamHandler
  735. {
  736. OpenSimBase m_opensim;
  737. public XSimStatusHandler(OpenSimBase sim)
  738. : base("/" + Util.SHA1Hash(sim.osSecret), "XSimStatus")
  739. {
  740. m_opensim = sim;
  741. }
  742. protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  743. {
  744. httpResponse.KeepAlive = false;
  745. try
  746. {
  747. httpResponse.RawBuffer = Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
  748. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  749. }
  750. catch
  751. {
  752. httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
  753. }
  754. }
  755. }
  756. /// <summary>
  757. /// Handler to supply the current extended status of this sim to a user configured URI
  758. /// Sends the statistical data in a json serialization
  759. /// If the request contains a key, "callback" the response will be wrappend in the
  760. /// associated value for jsonp used with ajax/javascript
  761. /// </summary>
  762. protected class UXSimStatusHandler : SimpleStreamHandler
  763. {
  764. OpenSimBase m_opensim;
  765. public UXSimStatusHandler(OpenSimBase sim)
  766. : base("/" + sim.userStatsURI, "UXSimStatus")
  767. {
  768. m_opensim = sim;
  769. }
  770. protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  771. {
  772. httpResponse.KeepAlive = false;
  773. try
  774. {
  775. httpResponse.RawBuffer = Util.UTF8.GetBytes(m_opensim.StatReport(httpRequest));
  776. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  777. }
  778. catch
  779. {
  780. httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
  781. }
  782. }
  783. }
  784. /// <summary>
  785. /// handler to supply serving http://domainname:port/robots.txt
  786. /// </summary>
  787. public class SimRobotsHandler : SimpleStreamHandler
  788. {
  789. private readonly byte[] binmsg;
  790. public SimRobotsHandler() : base("/robots.txt", "SimRobots")
  791. {
  792. binmsg = Util.UTF8.GetBytes("# go away\nUser-agent: *\nDisallow: /\n");
  793. }
  794. protected override void ProcessRequest(IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  795. {
  796. httpResponse.KeepAlive = false;
  797. httpResponse.RawBuffer = binmsg;
  798. httpResponse.StatusCode = (int)HttpStatusCode.OK;
  799. }
  800. }
  801. #endregion
  802. /// <summary>
  803. /// Performs any last-minute sanity checking and shuts down the region server
  804. /// </summary>
  805. protected override void ShutdownSpecific()
  806. {
  807. if (proxyUrl.Length > 0)
  808. {
  809. Util.XmlRpcCommand(proxyUrl, "Stop");
  810. }
  811. m_log.Info("[SHUTDOWN]: Closing all threads");
  812. m_log.Info("[SHUTDOWN]: Killing listener thread");
  813. m_log.Info("[SHUTDOWN]: Killing clients");
  814. m_log.Info("[SHUTDOWN]: Closing console and terminating");
  815. try
  816. {
  817. SceneManager.Close();
  818. foreach (IApplicationPlugin plugin in m_plugins)
  819. plugin.Dispose();
  820. }
  821. catch (Exception e)
  822. {
  823. m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
  824. }
  825. base.ShutdownSpecific();
  826. }
  827. /// <summary>
  828. /// Get the start time and up time of Region server
  829. /// </summary>
  830. /// <param name="starttime">The first out parameter describing when the Region server started</param>
  831. /// <param name="uptime">The second out parameter describing how long the Region server has run</param>
  832. public void GetRunTime(out string starttime, out string uptime)
  833. {
  834. starttime = m_startuptime.ToString();
  835. uptime = (DateTime.Now - m_startuptime).ToString();
  836. }
  837. /// <summary>
  838. /// Get the number of the avatars in the Region server
  839. /// </summary>
  840. /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
  841. public void GetAvatarNumber(out int usernum)
  842. {
  843. usernum = SceneManager.GetCurrentSceneAvatars().Count;
  844. }
  845. /// <summary>
  846. /// Get the number of regions
  847. /// </summary>
  848. /// <param name="regionnum">The first out parameter describing the number of regions</param>
  849. public void GetRegionNumber(out int regionnum)
  850. {
  851. regionnum = SceneManager.Scenes.Count;
  852. }
  853. /// <summary>
  854. /// Create an estate with an initial region.
  855. /// </summary>
  856. /// <remarks>
  857. /// This method doesn't allow an estate to be created with the same name as existing estates.
  858. /// </remarks>
  859. /// <param name="regInfo"></param>
  860. /// <param name="estatesByName">A list of estate names that already exist.</param>
  861. /// <param name="estateName">Estate name to create if already known</param>
  862. /// <returns>true if the estate was created, false otherwise</returns>
  863. public bool CreateEstate(RegionInfo regInfo, Dictionary<string, EstateSettings> estatesByName, string estateName)
  864. {
  865. // Create a new estate
  866. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
  867. string newName;
  868. if (!string.IsNullOrEmpty(estateName))
  869. newName = estateName;
  870. else
  871. newName = MainConsole.Instance.Prompt("New estate name", regInfo.EstateSettings.EstateName);
  872. if (estatesByName.ContainsKey(newName))
  873. {
  874. MainConsole.Instance.Output("An estate named {0} already exists. Please try again.", newName);
  875. return false;
  876. }
  877. regInfo.EstateSettings.EstateName = newName;
  878. // FIXME: Later on, the scene constructor will reload the estate settings no matter what.
  879. // Therefore, we need to do an initial save here otherwise the new estate name will be reset
  880. // back to the default. The reloading of estate settings by scene could be eliminated if it
  881. // knows that the passed in settings in RegionInfo are already valid. Also, it might be
  882. // possible to eliminate some additional later saves made by callers of this method.
  883. EstateDataService.StoreEstateSettings(regInfo.EstateSettings);
  884. return true;
  885. }
  886. /// <summary>
  887. /// Load the estate information for the provided RegionInfo object.
  888. /// </summary>
  889. /// <param name="regInfo"></param>
  890. public bool PopulateRegionEstateInfo(RegionInfo regInfo)
  891. {
  892. if (EstateDataService != null)
  893. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false);
  894. if (regInfo.EstateSettings.EstateID != 0)
  895. return false; // estate info in the database did not change
  896. m_log.WarnFormat("[ESTATE] Region {0} is not part of an estate.", regInfo.RegionName);
  897. List<EstateSettings> estates = EstateDataService.LoadEstateSettingsAll();
  898. Dictionary<string, EstateSettings> estatesByName = new Dictionary<string, EstateSettings>();
  899. foreach (EstateSettings estate in estates)
  900. estatesByName[estate.EstateName] = estate;
  901. //##
  902. // Target Estate Specified in Region.ini
  903. string targetEstateIDstr = regInfo.GetSetting("TargetEstate");
  904. if (!string.IsNullOrWhiteSpace(targetEstateIDstr))
  905. {
  906. bool targetEstateJoined = false;
  907. if (Int32.TryParse(targetEstateIDstr, out int targetEstateID) && targetEstateID > 99)
  908. {
  909. // Attempt to join the target estate given in Config by ID
  910. foreach (EstateSettings estate in estates)
  911. {
  912. if (estate.EstateID == targetEstateID)
  913. {
  914. if (EstateDataService.LinkRegion(regInfo.RegionID, targetEstateID))
  915. targetEstateJoined = true;
  916. break;
  917. }
  918. }
  919. }
  920. else
  921. {
  922. // Attempt to join the target estate given in Config by name
  923. if (estatesByName.TryGetValue(targetEstateIDstr, out EstateSettings targetEstate))
  924. {
  925. if (EstateDataService.LinkRegion(regInfo.RegionID, (int)targetEstate.EstateID))
  926. targetEstateJoined = true;
  927. }
  928. }
  929. if (targetEstateJoined)
  930. return true; // need to update the database
  931. else
  932. m_log.ErrorFormat(
  933. "[OPENSIM BASE]: Joining target estate specified in region config {0} failed", targetEstateIDstr);
  934. }
  935. //##
  936. // Default Estate
  937. if (Config.Configs[ESTATE_SECTION_NAME] != null)
  938. {
  939. string defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
  940. if (defaultEstateName != null)
  941. {
  942. bool defaultEstateJoined = false;
  943. if (estatesByName.TryGetValue(defaultEstateName, out EstateSettings defaultEstate))
  944. {
  945. if (EstateDataService.LinkRegion(regInfo.RegionID, (int)defaultEstate.EstateID))
  946. defaultEstateJoined = true;
  947. }
  948. else
  949. {
  950. if (CreateEstate(regInfo, estatesByName, defaultEstateName))
  951. defaultEstateJoined = true;
  952. }
  953. if (defaultEstateJoined)
  954. return true; // need to update the database
  955. else
  956. m_log.ErrorFormat(
  957. "[OPENSIM BASE]: Joining default estate {0} failed", defaultEstateName);
  958. }
  959. }
  960. // If we have no default estate or creation of the default estate failed then ask the user.
  961. while (true)
  962. {
  963. if (estates.Count == 0)
  964. {
  965. m_log.Info("[ESTATE]: No existing estates found. You must create a new one.");
  966. if (CreateEstate(regInfo, estatesByName, null))
  967. break;
  968. else
  969. continue;
  970. }
  971. else
  972. {
  973. string response = MainConsole.Instance.Prompt(
  974. string.Format(
  975. "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
  976. "yes",
  977. new List<string>() { "yes", "no" });
  978. if (response == "no")
  979. {
  980. if (CreateEstate(regInfo, estatesByName, null))
  981. break;
  982. else
  983. continue;
  984. }
  985. else
  986. {
  987. string[] estateNames = estatesByName.Keys.ToArray();
  988. response
  989. = MainConsole.Instance.Prompt(
  990. string.Format(
  991. "Name of estate to join. Existing estate names are ({0})",
  992. string.Join(", ", estateNames)),
  993. estateNames[0]);
  994. List<int> estateIDs = EstateDataService.GetEstates(response);
  995. if (estateIDs.Count < 1)
  996. {
  997. MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
  998. continue;
  999. }
  1000. int estateID = estateIDs[0];
  1001. regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID);
  1002. if (EstateDataService.LinkRegion(regInfo.RegionID, estateID))
  1003. break;
  1004. MainConsole.Instance.Output("Joining the estate failed. Please try again.");
  1005. }
  1006. }
  1007. }
  1008. return true; // need to update the database
  1009. }
  1010. }
  1011. public class OpenSimConfigSource
  1012. {
  1013. public IConfigSource Source;
  1014. }
  1015. }