Main.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  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 OpenSim 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.Net;
  31. using System.Reflection;
  32. using OpenMetaverse;
  33. using log4net;
  34. using log4net.Config;
  35. using OpenSim.Framework;
  36. using OpenSim.Framework.Communications;
  37. using OpenSim.Framework.Communications.Cache;
  38. using OpenSim.Framework.Console;
  39. using OpenSim.Framework.Servers;
  40. using OpenSim.Framework.Statistics;
  41. using OpenSim.Grid.Communications.OGS1;
  42. namespace OpenSim.Grid.UserServer
  43. {
  44. /// <summary>
  45. /// Grid user server main class
  46. /// </summary>
  47. public class OpenUser_Main : BaseOpenSimServer, conscmd_callback
  48. {
  49. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  50. protected UserConfig Cfg;
  51. public UserManager m_userManager;
  52. public UserLoginService m_loginService;
  53. public GridInfoService m_gridInfoService;
  54. public MessageServersConnector m_messagesService;
  55. private UUID m_lastCreatedUser = UUID.Random();
  56. public static void Main(string[] args)
  57. {
  58. XmlConfigurator.Configure();
  59. m_log.Info("Launching UserServer...");
  60. OpenUser_Main userserver = new OpenUser_Main();
  61. userserver.Startup();
  62. userserver.Work();
  63. }
  64. protected OpenUser_Main()
  65. {
  66. m_console = new ConsoleBase("User", this);
  67. MainConsole.Instance = m_console;
  68. }
  69. public void Work()
  70. {
  71. m_console.Notice("Enter help for a list of commands\n");
  72. while (true)
  73. {
  74. m_console.Prompt();
  75. }
  76. }
  77. protected override void StartupSpecific()
  78. {
  79. Cfg = new UserConfig("USER SERVER", (Path.Combine(Util.configDir(), "UserServer_Config.xml")));
  80. m_stats = StatsManager.StartCollectingUserStats();
  81. m_log.Info("[STARTUP]: Establishing data connection");
  82. IInterServiceInventoryServices inventoryService = new OGS1InterServiceInventoryService(Cfg.InventoryUrl);
  83. StartupUserManager(inventoryService);
  84. m_userManager.AddPlugin(Cfg.DatabaseProvider, Cfg.DatabaseConnect);
  85. m_gridInfoService = new GridInfoService();
  86. StartupLoginService(inventoryService);
  87. m_messagesService = new MessageServersConnector();
  88. m_loginService.OnUserLoggedInAtLocation += NotifyMessageServersUserLoggedInToLocation;
  89. m_userManager.OnLogOffUser += NotifyMessageServersUserLoggOff;
  90. m_messagesService.OnAgentLocation += HandleAgentLocation;
  91. m_messagesService.OnAgentLeaving += HandleAgentLeaving;
  92. m_messagesService.OnRegionStartup += HandleRegionStartup;
  93. m_messagesService.OnRegionShutdown += HandleRegionShutdown;
  94. m_log.Info("[STARTUP]: Starting HTTP process");
  95. m_httpServer = new BaseHttpServer(Cfg.HttpPort);
  96. AddHttpHandlers();
  97. m_httpServer.Start();
  98. }
  99. /// <summary>
  100. /// Start up the user manager
  101. /// </summary>
  102. /// <param name="inventoryService"></param>
  103. protected virtual void StartupUserManager(IInterServiceInventoryServices inventoryService)
  104. {
  105. m_userManager = new UserManager(new OGS1InterServiceInventoryService(Cfg.InventoryUrl));
  106. }
  107. /// <summary>
  108. /// Start up the login service
  109. /// </summary>
  110. /// <param name="inventoryService"></param>
  111. protected virtual void StartupLoginService(IInterServiceInventoryServices inventoryService)
  112. {
  113. m_loginService = new UserLoginService(
  114. m_userManager, inventoryService, new LibraryRootFolder(Cfg.LibraryXmlfile), Cfg, Cfg.DefaultStartupMsg);
  115. }
  116. protected virtual void AddHttpHandlers()
  117. {
  118. m_httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod);
  119. m_httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin);
  120. //
  121. // Get the minimum defaultLevel to access to the grid
  122. //
  123. m_loginService.setloginlevel((int)Cfg.DefaultUserLevel);
  124. if (Cfg.EnableLLSDLogin)
  125. {
  126. m_httpServer.SetDefaultLLSDHandler(m_loginService.LLSDLoginMethod);
  127. }
  128. m_httpServer.AddXmlRPCHandler("get_user_by_name", m_userManager.XmlRPCGetUserMethodName);
  129. m_httpServer.AddXmlRPCHandler("get_user_by_uuid", m_userManager.XmlRPCGetUserMethodUUID);
  130. m_httpServer.AddXmlRPCHandler("get_avatar_picker_avatar", m_userManager.XmlRPCGetAvatarPickerAvatar);
  131. m_httpServer.AddXmlRPCHandler("add_new_user_friend", m_userManager.XmlRpcResponseXmlRPCAddUserFriend);
  132. m_httpServer.AddXmlRPCHandler("remove_user_friend", m_userManager.XmlRpcResponseXmlRPCRemoveUserFriend);
  133. m_httpServer.AddXmlRPCHandler("update_user_friend_perms",
  134. m_userManager.XmlRpcResponseXmlRPCUpdateUserFriendPerms);
  135. m_httpServer.AddXmlRPCHandler("get_user_friend_list", m_userManager.XmlRpcResponseXmlRPCGetUserFriendList);
  136. m_httpServer.AddXmlRPCHandler("get_avatar_appearance", m_userManager.XmlRPCGetAvatarAppearance);
  137. m_httpServer.AddXmlRPCHandler("update_avatar_appearance", m_userManager.XmlRPCUpdateAvatarAppearance);
  138. m_httpServer.AddXmlRPCHandler("update_user_current_region", m_userManager.XmlRPCAtRegion);
  139. m_httpServer.AddXmlRPCHandler("logout_of_simulator", m_userManager.XmlRPCLogOffUserMethodUUID);
  140. m_httpServer.AddXmlRPCHandler("get_agent_by_uuid", m_userManager.XmlRPCGetAgentMethodUUID);
  141. m_httpServer.AddXmlRPCHandler("check_auth_session", m_userManager.XmlRPCCheckAuthSession);
  142. m_httpServer.AddXmlRPCHandler("set_login_params", m_loginService.XmlRPCSetLoginParams);
  143. m_httpServer.AddXmlRPCHandler("region_startup", m_messagesService.RegionStartup);
  144. m_httpServer.AddXmlRPCHandler("region_shutdown", m_messagesService.RegionShutdown);
  145. m_httpServer.AddXmlRPCHandler("agent_location", m_messagesService.AgentLocation);
  146. m_httpServer.AddXmlRPCHandler("agent_leaving", m_messagesService.AgentLeaving);
  147. // Message Server ---> User Server
  148. m_httpServer.AddXmlRPCHandler("register_messageserver", m_messagesService.XmlRPCRegisterMessageServer);
  149. m_httpServer.AddXmlRPCHandler("agent_change_region", m_messagesService.XmlRPCUserMovedtoRegion);
  150. m_httpServer.AddXmlRPCHandler("deregister_messageserver", m_messagesService.XmlRPCDeRegisterMessageServer);
  151. m_httpServer.AddStreamHandler(new RestStreamHandler("GET", "/get_grid_info",
  152. m_gridInfoService.RestGetGridInfoMethod));
  153. m_httpServer.AddXmlRPCHandler("get_grid_info", m_gridInfoService.XmlRpcGridInfoMethod);
  154. m_httpServer.AddStreamHandler(
  155. new RestStreamHandler("DELETE", "/usersessions/", m_userManager.RestDeleteUserSessionMethod));
  156. m_httpServer.AddXmlRPCHandler("update_user_profile", m_userManager.XmlRpcResponseXmlRPCUpdateUserProfile);
  157. // Handler for OpenID avatar identity pages
  158. m_httpServer.AddStreamHandler(new OpenIdStreamHandler("GET", "/users/", m_loginService));
  159. // Handlers for the OpenID endpoint server
  160. m_httpServer.AddStreamHandler(new OpenIdStreamHandler("POST", "/openid/server/", m_loginService));
  161. m_httpServer.AddStreamHandler(new OpenIdStreamHandler("GET", "/openid/server/", m_loginService));
  162. }
  163. public void do_create(string[] args)
  164. {
  165. switch (args[0])
  166. {
  167. case "user":
  168. CreateUser(args);
  169. break;
  170. }
  171. }
  172. /// <summary>
  173. /// Execute switch for some of the reset commands
  174. /// </summary>
  175. /// <param name="args"></param>
  176. protected void Reset(string[] args)
  177. {
  178. if (args.Length == 0)
  179. return;
  180. switch (args[0])
  181. {
  182. case "user":
  183. switch (args[1])
  184. {
  185. case "password":
  186. ResetUserPassword(args);
  187. break;
  188. }
  189. break;
  190. }
  191. }
  192. /// <summary>
  193. /// Create a new user
  194. /// </summary>
  195. /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email</param>
  196. protected void CreateUser(string[] cmdparams)
  197. {
  198. string firstName;
  199. string lastName;
  200. string password;
  201. string email;
  202. uint regX = 1000;
  203. uint regY = 1000;
  204. if (cmdparams.Length < 2)
  205. firstName = MainConsole.Instance.CmdPrompt("First name", "Default");
  206. else firstName = cmdparams[1];
  207. if (cmdparams.Length < 3)
  208. lastName = MainConsole.Instance.CmdPrompt("Last name", "User");
  209. else lastName = cmdparams[2];
  210. if (cmdparams.Length < 4)
  211. password = MainConsole.Instance.PasswdPrompt("Password");
  212. else password = cmdparams[3];
  213. if (cmdparams.Length < 5)
  214. regX = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region X", regX.ToString()));
  215. else regX = Convert.ToUInt32(cmdparams[4]);
  216. if (cmdparams.Length < 6)
  217. regY = Convert.ToUInt32(MainConsole.Instance.CmdPrompt("Start Region Y", regY.ToString()));
  218. else regY = Convert.ToUInt32(cmdparams[5]);
  219. if (cmdparams.Length < 7)
  220. email = MainConsole.Instance.CmdPrompt("Email", "");
  221. else email = cmdparams[6];
  222. if (null == m_userManager.GetUserProfile(firstName, lastName))
  223. {
  224. m_lastCreatedUser = m_userManager.AddUser(firstName, lastName, password, email, regX, regY);
  225. }
  226. else
  227. {
  228. m_log.ErrorFormat("[USERS]: A user with the name {0} {1} already exists!", firstName, lastName);
  229. }
  230. }
  231. /// <summary>
  232. /// Reset a user password.
  233. /// </summary>
  234. /// <param name="cmdparams"></param>
  235. private void ResetUserPassword(string[] cmdparams)
  236. {
  237. string firstName;
  238. string lastName;
  239. string newPassword;
  240. if (cmdparams.Length < 3)
  241. firstName = MainConsole.Instance.CmdPrompt("First name");
  242. else firstName = cmdparams[2];
  243. if ( cmdparams.Length < 4 )
  244. lastName = MainConsole.Instance.CmdPrompt("Last name");
  245. else lastName = cmdparams[3];
  246. if ( cmdparams.Length < 5 )
  247. newPassword = MainConsole.Instance.PasswdPrompt("New password");
  248. else newPassword = cmdparams[4];
  249. m_userManager.ResetUserPassword(firstName, lastName, newPassword);
  250. }
  251. public override void RunCmd(string cmd, string[] cmdparams)
  252. {
  253. base.RunCmd(cmd, cmdparams);
  254. switch (cmd)
  255. {
  256. case "create":
  257. do_create(cmdparams);
  258. break;
  259. case "reset":
  260. Reset(cmdparams);
  261. break;
  262. case "login-level":
  263. // Set the minimal level to allow login
  264. // Usefull to allow grid update without worrying about users.
  265. // or fixing critical issue
  266. if (cmdparams.Length == 1)
  267. {
  268. int level = Convert.ToInt32(cmdparams[0]);
  269. m_loginService.setloginlevel(level);
  270. }
  271. break;
  272. case "login-reset":
  273. m_loginService.setloginlevel(0);
  274. break;
  275. case "login-text":
  276. if (cmdparams.Length == 1)
  277. {
  278. m_loginService.setwelcometext(cmdparams[0]);
  279. }
  280. break;
  281. case "test-inventory":
  282. // RestObjectPosterResponse<List<InventoryFolderBase>> requester = new RestObjectPosterResponse<List<InventoryFolderBase>>();
  283. // requester.ReturnResponseVal = TestResponse;
  284. // requester.BeginPostObject<UUID>(m_userManager._config.InventoryUrl + "RootFolders/", m_lastCreatedUser);
  285. SynchronousRestObjectPoster.BeginPostObject<UUID, List<InventoryFolderBase>>(
  286. "POST", Cfg.InventoryUrl + "RootFolders/", m_lastCreatedUser);
  287. break;
  288. case "logoff-user":
  289. if (cmdparams.Length >= 3)
  290. {
  291. string firstname = cmdparams[0];
  292. string lastname = cmdparams[1];
  293. string message = "";
  294. for (int i = 2; i < cmdparams.Length; i++)
  295. message += " " + cmdparams[i];
  296. UserProfileData theUser = null;
  297. try
  298. {
  299. theUser = m_loginService.GetTheUser(firstname, lastname);
  300. }
  301. catch (Exception)
  302. {
  303. m_log.Error("[LOGOFF]: Error getting user data from the database.");
  304. }
  305. if (theUser != null)
  306. {
  307. if (theUser.CurrentAgent != null)
  308. {
  309. if (theUser.CurrentAgent.AgentOnline)
  310. {
  311. m_log.Info("[LOGOFF]: Logging off requested user!");
  312. m_loginService.LogOffUser(theUser, message);
  313. theUser.CurrentAgent.AgentOnline = false;
  314. m_loginService.CommitAgent(ref theUser);
  315. }
  316. else
  317. {
  318. m_log.Info(
  319. "[LOGOFF]: User Doesn't appear to be online, sending the logoff message anyway.");
  320. m_loginService.LogOffUser(theUser, message);
  321. theUser.CurrentAgent.AgentOnline = false;
  322. m_loginService.CommitAgent(ref theUser);
  323. }
  324. }
  325. else
  326. {
  327. m_log.Error(
  328. "[LOGOFF]: Unable to logoff-user. User doesn't have an agent record so I can't find the simulator to notify");
  329. }
  330. }
  331. else
  332. {
  333. m_log.Info("[LOGOFF]: User doesn't exist in the database");
  334. }
  335. }
  336. else
  337. {
  338. m_log.Error(
  339. "[LOGOFF]: Invalid amount of parameters. logoff-user takes at least three. Firstname, Lastname, and message");
  340. }
  341. break;
  342. }
  343. }
  344. protected override void ShowHelp(string[] helpArgs)
  345. {
  346. base.ShowHelp(helpArgs);
  347. m_console.Notice("create user - create a new user");
  348. m_console.Notice("logoff-user <firstname> <lastname> <message> - logs off the specified user from the grid");
  349. m_console.Notice("reset user password - reset a user's password.");
  350. m_console.Notice("login-level <value> - Set the miminim userlevel allowed To login.");
  351. m_console.Notice("login-reset - reset the login level to its default value.");
  352. m_console.Notice("login-text <text to print during the login>");
  353. }
  354. public override void ShutdownSpecific()
  355. {
  356. m_loginService.OnUserLoggedInAtLocation -= NotifyMessageServersUserLoggedInToLocation;
  357. }
  358. public void TestResponse(List<InventoryFolderBase> resp)
  359. {
  360. m_console.Notice("response got");
  361. }
  362. public void NotifyMessageServersUserLoggOff(UUID agentID)
  363. {
  364. m_messagesService.TellMessageServersAboutUserLogoff(agentID);
  365. }
  366. public void NotifyMessageServersUserLoggedInToLocation(UUID agentID, UUID sessionID, UUID RegionID,
  367. ulong regionhandle, float positionX, float positionY,
  368. float positionZ, string firstname, string lastname)
  369. {
  370. m_messagesService.TellMessageServersAboutUser(agentID, sessionID, RegionID, regionhandle, positionX,
  371. positionY, positionZ, firstname, lastname);
  372. }
  373. public void HandleAgentLocation(UUID agentID, UUID regionID, ulong regionHandle)
  374. {
  375. m_userManager.HandleAgentLocation(agentID, regionID, regionHandle);
  376. }
  377. public void HandleAgentLeaving(UUID agentID, UUID regionID, ulong regionHandle)
  378. {
  379. m_userManager.HandleAgentLeaving(agentID, regionID, regionHandle);
  380. }
  381. public void HandleRegionStartup(UUID regionID)
  382. {
  383. // This might seem strange, that we send this back to the
  384. // server it came from. But there is method to the madness.
  385. // There can be multiple user servers on the same database,
  386. // and each can have multiple messaging servers. So, we send
  387. // it to all known user servers, who send it to all known
  388. // message servers. That way, we should be able to finally
  389. // update presence to all regions and thereby all friends
  390. //
  391. m_userManager.HandleRegionStartup(regionID);
  392. m_messagesService.TellMessageServersAboutRegionShutdown(regionID);
  393. }
  394. public void HandleRegionShutdown(UUID regionID)
  395. {
  396. // This might seem strange, that we send this back to the
  397. // server it came from. But there is method to the madness.
  398. // There can be multiple user servers on the same database,
  399. // and each can have multiple messaging servers. So, we send
  400. // it to all known user servers, who send it to all known
  401. // message servers. That way, we should be able to finally
  402. // update presence to all regions and thereby all friends
  403. //
  404. m_userManager.HandleRegionShutdown(regionID);
  405. m_messagesService.TellMessageServersAboutRegionShutdown(regionID);
  406. }
  407. }
  408. }