MessageServersConnector.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  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.Collections;
  28. using System.Collections.Generic;
  29. using System.Net;
  30. using System.Reflection;
  31. using System.Threading;
  32. using log4net;
  33. using Nwc.XmlRpc;
  34. using OpenMetaverse;
  35. using OpenSim.Framework;
  36. using OpenSim.Framework.Servers;
  37. using OpenSim.Framework.Servers.HttpServer;
  38. using OpenSim.Grid.Framework;
  39. namespace OpenSim.Grid.UserServer.Modules
  40. {
  41. public enum NotificationRequest : int
  42. {
  43. Login = 0,
  44. Logout = 1,
  45. Shutdown = 2
  46. }
  47. public struct PresenceNotification
  48. {
  49. public NotificationRequest request;
  50. public UUID agentID;
  51. public UUID sessionID;
  52. public UUID RegionID;
  53. public ulong regionhandle;
  54. public float positionX;
  55. public float positionY;
  56. public float positionZ;
  57. public string firstname;
  58. public string lastname;
  59. }
  60. public delegate void AgentLocationDelegate(UUID agentID, UUID regionID, ulong regionHandle);
  61. public delegate void AgentLeavingDelegate(UUID agentID, UUID regionID, ulong regionHandle);
  62. public delegate void RegionStartupDelegate(UUID regionID);
  63. public delegate void RegionShutdownDelegate(UUID regionID);
  64. public class MessageServersConnector
  65. {
  66. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  67. public Dictionary<string, MessageServerInfo> MessageServers;
  68. private BaseHttpServer m_httpServer;
  69. private OpenSim.Framework.BlockingQueue<PresenceNotification> m_NotifyQueue =
  70. new OpenSim.Framework.BlockingQueue<PresenceNotification>();
  71. Thread m_NotifyThread;
  72. private IGridServiceCore m_core;
  73. public event AgentLocationDelegate OnAgentLocation;
  74. public event AgentLeavingDelegate OnAgentLeaving;
  75. public event RegionStartupDelegate OnRegionStartup;
  76. public event RegionShutdownDelegate OnRegionShutdown;
  77. public MessageServersConnector()
  78. {
  79. MessageServers = new Dictionary<string, MessageServerInfo>();
  80. }
  81. public void Initialise(IGridServiceCore core)
  82. {
  83. m_core = core;
  84. m_core.RegisterInterface<MessageServersConnector>(this);
  85. m_NotifyThread = new Thread(new ThreadStart(NotifyQueueRunner));
  86. m_NotifyThread.Start();
  87. }
  88. public void PostInitialise()
  89. {
  90. }
  91. public void RegisterHandlers(BaseHttpServer httpServer)
  92. {
  93. m_httpServer = httpServer;
  94. m_httpServer.AddXmlRPCHandler("region_startup", RegionStartup);
  95. m_httpServer.AddXmlRPCHandler("region_shutdown", RegionShutdown);
  96. m_httpServer.AddXmlRPCHandler("agent_location", AgentLocation);
  97. m_httpServer.AddXmlRPCHandler("agent_leaving", AgentLeaving);
  98. // Message Server ---> User Server
  99. m_httpServer.AddXmlRPCHandler("register_messageserver", XmlRPCRegisterMessageServer);
  100. m_httpServer.AddXmlRPCHandler("agent_change_region", XmlRPCUserMovedtoRegion);
  101. m_httpServer.AddXmlRPCHandler("deregister_messageserver", XmlRPCDeRegisterMessageServer);
  102. }
  103. public void RegisterMessageServer(string URI, MessageServerInfo serverData)
  104. {
  105. lock (MessageServers)
  106. {
  107. if (!MessageServers.ContainsKey(URI))
  108. MessageServers.Add(URI, serverData);
  109. }
  110. }
  111. public void DeRegisterMessageServer(string URI)
  112. {
  113. lock (MessageServers)
  114. {
  115. if (MessageServers.ContainsKey(URI))
  116. MessageServers.Remove(URI);
  117. }
  118. }
  119. public void AddResponsibleRegion(string URI, ulong regionhandle)
  120. {
  121. if (!MessageServers.ContainsKey(URI))
  122. {
  123. m_log.Warn("[MSGSERVER]: Got addResponsibleRegion Request for a MessageServer that isn't registered");
  124. }
  125. else
  126. {
  127. MessageServerInfo msginfo = MessageServers["URI"];
  128. msginfo.responsibleForRegions.Add(regionhandle);
  129. MessageServers["URI"] = msginfo;
  130. }
  131. }
  132. public void RemoveResponsibleRegion(string URI, ulong regionhandle)
  133. {
  134. if (!MessageServers.ContainsKey(URI))
  135. {
  136. m_log.Warn("[MSGSERVER]: Got RemoveResponsibleRegion Request for a MessageServer that isn't registered");
  137. }
  138. else
  139. {
  140. MessageServerInfo msginfo = MessageServers["URI"];
  141. if (msginfo.responsibleForRegions.Contains(regionhandle))
  142. {
  143. msginfo.responsibleForRegions.Remove(regionhandle);
  144. MessageServers["URI"] = msginfo;
  145. }
  146. }
  147. }
  148. public XmlRpcResponse XmlRPCRegisterMessageServer(XmlRpcRequest request, IPEndPoint remoteClient)
  149. {
  150. XmlRpcResponse response = new XmlRpcResponse();
  151. Hashtable requestData = (Hashtable)request.Params[0];
  152. Hashtable responseData = new Hashtable();
  153. if (requestData.Contains("uri"))
  154. {
  155. string URI = (string)requestData["uri"];
  156. string sendkey=(string)requestData["sendkey"];
  157. string recvkey=(string)requestData["recvkey"];
  158. MessageServerInfo m = new MessageServerInfo();
  159. m.URI = URI;
  160. m.sendkey = sendkey;
  161. m.recvkey = recvkey;
  162. RegisterMessageServer(URI, m);
  163. responseData["responsestring"] = "TRUE";
  164. response.Value = responseData;
  165. }
  166. return response;
  167. }
  168. public XmlRpcResponse XmlRPCDeRegisterMessageServer(XmlRpcRequest request, IPEndPoint remoteClient)
  169. {
  170. XmlRpcResponse response = new XmlRpcResponse();
  171. Hashtable requestData = (Hashtable)request.Params[0];
  172. Hashtable responseData = new Hashtable();
  173. if (requestData.Contains("uri"))
  174. {
  175. string URI = (string)requestData["uri"];
  176. DeRegisterMessageServer(URI);
  177. responseData["responsestring"] = "TRUE";
  178. response.Value = responseData;
  179. }
  180. return response;
  181. }
  182. public XmlRpcResponse XmlRPCUserMovedtoRegion(XmlRpcRequest request, IPEndPoint remoteClient)
  183. {
  184. XmlRpcResponse response = new XmlRpcResponse();
  185. Hashtable requestData = (Hashtable)request.Params[0];
  186. Hashtable responseData = new Hashtable();
  187. if (requestData.Contains("fromuri"))
  188. {
  189. // string sURI = (string)requestData["fromuri"];
  190. // string sagentID = (string)requestData["agentid"];
  191. // string ssessionID = (string)requestData["sessionid"];
  192. // string scurrentRegionID = (string)requestData["regionid"];
  193. // string sregionhandle = (string)requestData["regionhandle"];
  194. // string scurrentpos = (string)requestData["currentpos"];
  195. //Vector3.TryParse((string)reader["currentPos"], out retval.currentPos);
  196. // TODO: Okay now raise event so the user server can pass this data to the Usermanager
  197. responseData["responsestring"] = "TRUE";
  198. response.Value = responseData;
  199. }
  200. return response;
  201. }
  202. public void TellMessageServersAboutUser(UUID agentID, UUID sessionID, UUID RegionID,
  203. ulong regionhandle, float positionX, float positionY,
  204. float positionZ, string firstname, string lastname)
  205. {
  206. PresenceNotification notification = new PresenceNotification();
  207. notification.request = NotificationRequest.Login;
  208. notification.agentID = agentID;
  209. notification.sessionID = sessionID;
  210. notification.RegionID = RegionID;
  211. notification.regionhandle = regionhandle;
  212. notification.positionX = positionX;
  213. notification.positionY = positionY;
  214. notification.positionZ = positionZ;
  215. notification.firstname = firstname;
  216. notification.lastname = lastname;
  217. m_NotifyQueue.Enqueue(notification);
  218. }
  219. private void TellMessageServersAboutUserInternal(UUID agentID, UUID sessionID, UUID RegionID,
  220. ulong regionhandle, float positionX, float positionY,
  221. float positionZ, string firstname, string lastname)
  222. {
  223. // Loop over registered Message Servers (AND THERE WILL BE MORE THEN ONE :D)
  224. lock (MessageServers)
  225. {
  226. if (MessageServers.Count > 0)
  227. {
  228. m_log.Info("[MSGCONNECTOR]: Sending login notice to registered message servers");
  229. }
  230. // else
  231. // {
  232. // m_log.Debug("[MSGCONNECTOR]: No Message Servers registered, ignoring");
  233. // }
  234. foreach (MessageServerInfo serv in MessageServers.Values)
  235. {
  236. NotifyMessageServerAboutUser(serv, agentID, sessionID, RegionID,
  237. regionhandle, positionX, positionY, positionZ,
  238. firstname, lastname);
  239. }
  240. }
  241. }
  242. private void TellMessageServersAboutUserLogoffInternal(UUID agentID)
  243. {
  244. lock (MessageServers)
  245. {
  246. if (MessageServers.Count > 0)
  247. {
  248. m_log.Info("[MSGCONNECTOR]: Sending logoff notice to registered message servers");
  249. }
  250. else
  251. {
  252. // m_log.Debug("[MSGCONNECTOR]: No Message Servers registered, ignoring");
  253. }
  254. foreach (MessageServerInfo serv in MessageServers.Values)
  255. {
  256. NotifyMessageServerAboutUserLogoff(serv,agentID);
  257. }
  258. }
  259. }
  260. private void TellMessageServersAboutRegionShutdownInternal(UUID regionID)
  261. {
  262. lock (MessageServers)
  263. {
  264. if (MessageServers.Count > 0)
  265. {
  266. m_log.Info("[MSGCONNECTOR]: Sending region down notice to registered message servers");
  267. }
  268. else
  269. {
  270. // m_log.Debug("[MSGCONNECTOR]: No Message Servers registered, ignoring");
  271. }
  272. foreach (MessageServerInfo serv in MessageServers.Values)
  273. {
  274. NotifyMessageServerAboutRegionShutdown(serv,regionID);
  275. }
  276. }
  277. }
  278. public void TellMessageServersAboutUserLogoff(UUID agentID)
  279. {
  280. PresenceNotification notification = new PresenceNotification();
  281. notification.request = NotificationRequest.Logout;
  282. notification.agentID = agentID;
  283. m_NotifyQueue.Enqueue(notification);
  284. }
  285. public void TellMessageServersAboutRegionShutdown(UUID regionID)
  286. {
  287. PresenceNotification notification = new PresenceNotification();
  288. notification.request = NotificationRequest.Shutdown;
  289. notification.RegionID = regionID;
  290. m_NotifyQueue.Enqueue(notification);
  291. }
  292. private void NotifyMessageServerAboutUserLogoff(MessageServerInfo serv, UUID agentID)
  293. {
  294. Hashtable reqparams = new Hashtable();
  295. reqparams["sendkey"] = serv.sendkey;
  296. reqparams["agentid"] = agentID.ToString();
  297. ArrayList SendParams = new ArrayList();
  298. SendParams.Add(reqparams);
  299. XmlRpcRequest GridReq = new XmlRpcRequest("logout_of_simulator", SendParams);
  300. try
  301. {
  302. GridReq.Send(serv.URI, 6000);
  303. }
  304. catch (WebException)
  305. {
  306. m_log.Warn("[MSGCONNECTOR]: Unable to notify Message Server about log out. Other users might still think this user is online");
  307. }
  308. m_log.Info("[LOGOUT]: Notified : " + serv.URI + " about user logout");
  309. }
  310. private void NotifyMessageServerAboutRegionShutdown(MessageServerInfo serv, UUID regionID)
  311. {
  312. Hashtable reqparams = new Hashtable();
  313. reqparams["sendkey"] = serv.sendkey;
  314. reqparams["regionid"] = regionID.ToString();
  315. ArrayList SendParams = new ArrayList();
  316. SendParams.Add(reqparams);
  317. XmlRpcRequest GridReq = new XmlRpcRequest("process_region_shutdown", SendParams);
  318. try
  319. {
  320. GridReq.Send(serv.URI, 6000);
  321. }
  322. catch (WebException)
  323. {
  324. m_log.Warn("[MSGCONNECTOR]: Unable to notify Message Server about region shutdown.");
  325. }
  326. m_log.Info("[REGION UPDOWN]: Notified : " + serv.URI + " about region state change");
  327. }
  328. private void NotifyMessageServerAboutUser(MessageServerInfo serv,
  329. UUID agentID, UUID sessionID, UUID RegionID,
  330. ulong regionhandle, float positionX, float positionY, float positionZ,
  331. string firstname, string lastname)
  332. {
  333. Hashtable reqparams = new Hashtable();
  334. reqparams["sendkey"] = serv.sendkey;
  335. reqparams["agentid"] = agentID.ToString();
  336. reqparams["sessionid"] = sessionID.ToString();
  337. reqparams["regionid"] = RegionID.ToString();
  338. reqparams["regionhandle"] = regionhandle.ToString();
  339. reqparams["positionx"] = positionX.ToString();
  340. reqparams["positiony"] = positionY.ToString();
  341. reqparams["positionz"] = positionZ.ToString();
  342. reqparams["firstname"] = firstname;
  343. reqparams["lastname"] = lastname;
  344. //reqparams["position"] = Position.ToString();
  345. ArrayList SendParams = new ArrayList();
  346. SendParams.Add(reqparams);
  347. XmlRpcRequest GridReq = new XmlRpcRequest("login_to_simulator", SendParams);
  348. try
  349. {
  350. GridReq.Send(serv.URI, 6000);
  351. m_log.Info("[LOGIN]: Notified : " + serv.URI + " about user login");
  352. }
  353. catch (WebException)
  354. {
  355. m_log.Warn("[MSGCONNECTOR]: Unable to notify Message Server about login. Presence might be borked for this user");
  356. }
  357. }
  358. private void NotifyQueueRunner()
  359. {
  360. while (true)
  361. {
  362. PresenceNotification presence = m_NotifyQueue.Dequeue();
  363. if (presence.request == NotificationRequest.Shutdown)
  364. {
  365. TellMessageServersAboutRegionShutdownInternal(presence.RegionID);
  366. }
  367. if (presence.request == NotificationRequest.Login)
  368. {
  369. TellMessageServersAboutUserInternal(presence.agentID,
  370. presence.sessionID, presence.RegionID,
  371. presence.regionhandle, presence.positionX,
  372. presence.positionY, presence.positionZ,
  373. presence.firstname, presence.lastname);
  374. }
  375. if (presence.request == NotificationRequest.Logout)
  376. {
  377. TellMessageServersAboutUserLogoffInternal(presence.agentID);
  378. }
  379. }
  380. }
  381. public XmlRpcResponse RegionStartup(XmlRpcRequest request, IPEndPoint remoteClient)
  382. {
  383. Hashtable requestData = (Hashtable)request.Params[0];
  384. Hashtable result = new Hashtable();
  385. UUID regionID;
  386. if (UUID.TryParse((string)requestData["RegionUUID"], out regionID))
  387. {
  388. if (OnRegionStartup != null)
  389. OnRegionStartup(regionID);
  390. result["responsestring"] = "TRUE";
  391. }
  392. XmlRpcResponse response = new XmlRpcResponse();
  393. response.Value = result;
  394. return response;
  395. }
  396. public XmlRpcResponse RegionShutdown(XmlRpcRequest request, IPEndPoint remoteClient)
  397. {
  398. Hashtable requestData = (Hashtable)request.Params[0];
  399. Hashtable result = new Hashtable();
  400. UUID regionID;
  401. if (UUID.TryParse((string)requestData["RegionUUID"], out regionID))
  402. {
  403. if (OnRegionShutdown != null)
  404. OnRegionShutdown(regionID);
  405. result["responsestring"] = "TRUE";
  406. }
  407. XmlRpcResponse response = new XmlRpcResponse();
  408. response.Value = result;
  409. return response;
  410. }
  411. public XmlRpcResponse AgentLocation(XmlRpcRequest request, IPEndPoint remoteClient)
  412. {
  413. Hashtable requestData = (Hashtable)request.Params[0];
  414. Hashtable result = new Hashtable();
  415. UUID agentID;
  416. UUID regionID;
  417. ulong regionHandle;
  418. if (UUID.TryParse((string)requestData["AgentID"], out agentID) && UUID.TryParse((string)requestData["RegionUUID"], out regionID) && ulong.TryParse((string)requestData["RegionHandle"], out regionHandle))
  419. {
  420. if (OnAgentLocation != null)
  421. OnAgentLocation(agentID, regionID, regionHandle);
  422. result["responsestring"] = "TRUE";
  423. }
  424. XmlRpcResponse response = new XmlRpcResponse();
  425. response.Value = result;
  426. return response;
  427. }
  428. public XmlRpcResponse AgentLeaving(XmlRpcRequest request, IPEndPoint remoteClient)
  429. {
  430. Hashtable requestData = (Hashtable)request.Params[0];
  431. Hashtable result = new Hashtable();
  432. UUID agentID;
  433. UUID regionID;
  434. ulong regionHandle;
  435. if (UUID.TryParse((string)requestData["AgentID"], out agentID) && UUID.TryParse((string)requestData["RegionUUID"], out regionID) && ulong.TryParse((string)requestData["RegionHandle"], out regionHandle))
  436. {
  437. if (OnAgentLeaving != null)
  438. OnAgentLeaving(agentID, regionID, regionHandle);
  439. result["responsestring"] = "TRUE";
  440. }
  441. XmlRpcResponse response = new XmlRpcResponse();
  442. response.Value = result;
  443. return response;
  444. }
  445. }
  446. }