OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
UserAgentServiceConnector.cs
Go to the documentation of this file.
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 
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Net;
33 using System.Reflection;
34 using System.Text;
35 using OpenSim.Framework;
36 using OpenSim.Services.Interfaces;
37 using OpenSim.Services.Connectors.Simulation;
39 using OpenMetaverse;
40 using OpenMetaverse.StructuredData;
41 using log4net;
42 using Nwc.XmlRpc;
43 using Nini.Config;
44 
45 namespace OpenSim.Services.Connectors.Hypergrid
46 {
48  {
49  private static readonly ILog m_log =
50  LogManager.GetLogger(
51  MethodBase.GetCurrentMethod().DeclaringType);
52 
53  private string m_ServerURLHost;
54  private string m_ServerURL;
55  private GridRegion m_Gatekeeper;
56 
57  public UserAgentServiceConnector(string url) : this(url, true)
58  {
59  }
60 
61  public UserAgentServiceConnector(string url, bool dnsLookup)
62  {
63  m_ServerURL = m_ServerURLHost = url;
64 
65  if (dnsLookup)
66  {
67  // Doing this here, because XML-RPC or mono have some strong ideas about
68  // caching DNS translations.
69  try
70  {
71  Uri m_Uri = new Uri(m_ServerURL);
72  IPAddress ip = Util.GetHostFromDNS(m_Uri.Host);
73  m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString());
74  if (!m_ServerURL.EndsWith("/"))
75  m_ServerURL += "/";
76  }
77  catch (Exception e)
78  {
79  m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", url, e.Message);
80  }
81  }
82 
83  //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL);
84  }
85 
86  public UserAgentServiceConnector(IConfigSource config)
87  {
88  IConfig serviceConfig = config.Configs["UserAgentService"];
89  if (serviceConfig == null)
90  {
91  m_log.Error("[USER AGENT CONNECTOR]: UserAgentService missing from ini");
92  throw new Exception("UserAgent connector init error");
93  }
94 
95  string serviceURI = serviceConfig.GetString("UserAgentServerURI",
96  String.Empty);
97 
98  if (serviceURI == String.Empty)
99  {
100  m_log.Error("[USER AGENT CONNECTOR]: No Server URI named in section UserAgentService");
101  throw new Exception("UserAgent connector init error");
102  }
103 
104  m_ServerURL = m_ServerURLHost = serviceURI;
105  if (!m_ServerURL.EndsWith("/"))
106  m_ServerURL += "/";
107 
108  //m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0}", m_ServerURL);
109  }
110 
111  protected override string AgentPath()
112  {
113  return "homeagent/";
114  }
115 
116  // The Login service calls this interface with fromLogin=true
117  // Sims call it with fromLogin=false
118  // Either way, this is verified by the handler
119  public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)
120  {
121  reason = String.Empty;
122 
123  if (destination == null)
124  {
125  reason = "Destination is null";
126  m_log.Debug("[USER AGENT CONNECTOR]: Given destination is null");
127  return false;
128  }
129 
130  GridRegion home = new GridRegion();
131  home.ServerURI = m_ServerURL;
132  home.RegionID = destination.RegionID;
133  home.RegionLocX = destination.RegionLocX;
134  home.RegionLocY = destination.RegionLocY;
135 
136  m_Gatekeeper = gatekeeper;
137 
138  Console.WriteLine(" >>> LoginAgentToGrid <<< " + home.ServerURI);
139 
140  uint flags = fromLogin ? (uint)TeleportFlags.ViaLogin : (uint)TeleportFlags.ViaHome;
142  return CreateAgent(source, home, aCircuit, flags, ctx, out reason);
143  }
144 
145 
146  // The simulators call this interface
147  public bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
148  {
149  return LoginAgentToGrid(source, aCircuit, gatekeeper, destination, false, out reason);
150  }
151 
152  protected override void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags)
153  {
154  base.PackData(args, source, aCircuit, destination, flags);
155  args["gatekeeper_serveruri"] = OSD.FromString(m_Gatekeeper.ServerURI);
156  args["gatekeeper_host"] = OSD.FromString(m_Gatekeeper.ExternalHostName);
157  args["gatekeeper_port"] = OSD.FromString(m_Gatekeeper.HttpPort.ToString());
158  args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
159  }
160 
161  public void SetClientToken(UUID sessionID, string token)
162  {
163  // no-op
164  }
165 
166  private Hashtable CallServer(string methodName, Hashtable hash)
167  {
168  IList paramList = new ArrayList();
169  paramList.Add(hash);
170 
171  XmlRpcRequest request = new XmlRpcRequest(methodName, paramList);
172 
173  // Send and get reply
174  XmlRpcResponse response = null;
175  try
176  {
177  response = request.Send(m_ServerURL, 10000);
178  }
179  catch (Exception e)
180  {
181  m_log.DebugFormat("[USER AGENT CONNECTOR]: {0} call to {1} failed: {2}", methodName, m_ServerURLHost, e.Message);
182  throw;
183  }
184 
185  if (response.IsFault)
186  {
187  throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned an error: {2}", methodName, m_ServerURLHost, response.FaultString));
188  }
189 
190  hash = (Hashtable)response.Value;
191 
192  if (hash == null)
193  {
194  throw new Exception(string.Format("[USER AGENT CONNECTOR]: {0} call to {1} returned null", methodName, m_ServerURLHost));
195  }
196 
197  return hash;
198  }
199 
200  public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
201  {
202  position = Vector3.UnitY; lookAt = Vector3.UnitY;
203 
204  Hashtable hash = new Hashtable();
205  hash["userID"] = userID.ToString();
206 
207  hash = CallServer("get_home_region", hash);
208 
209  bool success;
210  if (!Boolean.TryParse((string)hash["result"], out success) || !success)
211  return null;
212 
213  GridRegion region = new GridRegion();
214 
215  UUID.TryParse((string)hash["uuid"], out region.RegionID);
216  //m_log.Debug(">> HERE, uuid: " + region.RegionID);
217  int n = 0;
218  if (hash["x"] != null)
219  {
220  Int32.TryParse((string)hash["x"], out n);
221  region.RegionLocX = n;
222  //m_log.Debug(">> HERE, x: " + region.RegionLocX);
223  }
224  if (hash["y"] != null)
225  {
226  Int32.TryParse((string)hash["y"], out n);
227  region.RegionLocY = n;
228  //m_log.Debug(">> HERE, y: " + region.RegionLocY);
229  }
230  if (hash["size_x"] != null)
231  {
232  Int32.TryParse((string)hash["size_x"], out n);
233  region.RegionSizeX = n;
234  //m_log.Debug(">> HERE, x: " + region.RegionLocX);
235  }
236  if (hash["size_y"] != null)
237  {
238  Int32.TryParse((string)hash["size_y"], out n);
239  region.RegionSizeY = n;
240  //m_log.Debug(">> HERE, y: " + region.RegionLocY);
241  }
242  if (hash["region_name"] != null)
243  {
244  region.RegionName = (string)hash["region_name"];
245  //m_log.Debug(">> HERE, name: " + region.RegionName);
246  }
247  if (hash["hostname"] != null)
248  region.ExternalHostName = (string)hash["hostname"];
249  if (hash["http_port"] != null)
250  {
251  uint p = 0;
252  UInt32.TryParse((string)hash["http_port"], out p);
253  region.HttpPort = p;
254  }
255  if (hash.ContainsKey("server_uri") && hash["server_uri"] != null)
256  region.ServerURI = (string)hash["server_uri"];
257 
258  if (hash["internal_port"] != null)
259  {
260  int p = 0;
261  Int32.TryParse((string)hash["internal_port"], out p);
262  region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
263  }
264  if (hash["position"] != null)
265  Vector3.TryParse((string)hash["position"], out position);
266  if (hash["lookAt"] != null)
267  Vector3.TryParse((string)hash["lookAt"], out lookAt);
268 
269  // Successful return
270  return region;
271  }
272 
273  public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
274  {
275  Hashtable hash = new Hashtable();
276  hash["sessionID"] = sessionID.ToString();
277  hash["externalName"] = thisGridExternalName;
278 
279  IList paramList = new ArrayList();
280  paramList.Add(hash);
281 
282  XmlRpcRequest request = new XmlRpcRequest("agent_is_coming_home", paramList);
283  string reason = string.Empty;
284  return GetBoolResponse(request, out reason);
285  }
286 
287  public bool VerifyAgent(UUID sessionID, string token)
288  {
289  Hashtable hash = new Hashtable();
290  hash["sessionID"] = sessionID.ToString();
291  hash["token"] = token;
292 
293  IList paramList = new ArrayList();
294  paramList.Add(hash);
295 
296  XmlRpcRequest request = new XmlRpcRequest("verify_agent", paramList);
297  string reason = string.Empty;
298  return GetBoolResponse(request, out reason);
299  }
300 
301  public bool VerifyClient(UUID sessionID, string token)
302  {
303  Hashtable hash = new Hashtable();
304  hash["sessionID"] = sessionID.ToString();
305  hash["token"] = token;
306 
307  IList paramList = new ArrayList();
308  paramList.Add(hash);
309 
310  XmlRpcRequest request = new XmlRpcRequest("verify_client", paramList);
311  string reason = string.Empty;
312  return GetBoolResponse(request, out reason);
313  }
314 
315  public void LogoutAgent(UUID userID, UUID sessionID)
316  {
317  Hashtable hash = new Hashtable();
318  hash["sessionID"] = sessionID.ToString();
319  hash["userID"] = userID.ToString();
320 
321  IList paramList = new ArrayList();
322  paramList.Add(hash);
323 
324  XmlRpcRequest request = new XmlRpcRequest("logout_agent", paramList);
325  string reason = string.Empty;
326  GetBoolResponse(request, out reason);
327  }
328 
329  [Obsolete]
330  public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
331  {
332  Hashtable hash = new Hashtable();
333  hash["userID"] = userID.ToString();
334  hash["online"] = online.ToString();
335  int i = 0;
336  foreach (string s in friends)
337  {
338  hash["friend_" + i.ToString()] = s;
339  i++;
340  }
341 
342  IList paramList = new ArrayList();
343  paramList.Add(hash);
344 
345  XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
346 // string reason = string.Empty;
347 
348  // Send and get reply
349  List<UUID> friendsOnline = new List<UUID>();
350  XmlRpcResponse response = null;
351  try
352  {
353  response = request.Send(m_ServerURL, 6000);
354  }
355  catch
356  {
357  m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURLHost);
358 // reason = "Exception: " + e.Message;
359  return friendsOnline;
360  }
361 
362  if (response.IsFault)
363  {
364  m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURLHost, response.FaultString);
365 // reason = "XMLRPC Fault";
366  return friendsOnline;
367  }
368 
369  hash = (Hashtable)response.Value;
370  //foreach (Object o in hash)
371  // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
372  try
373  {
374  if (hash == null)
375  {
376  m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
377 // reason = "Internal error 1";
378  return friendsOnline;
379  }
380 
381  // Here is the actual response
382  foreach (object key in hash.Keys)
383  {
384  if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
385  {
386  UUID uuid;
387  if (UUID.TryParse(hash[key].ToString(), out uuid))
388  friendsOnline.Add(uuid);
389  }
390  }
391 
392  }
393  catch
394  {
395  m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
396 // reason = "Exception: " + e.Message;
397  }
398 
399  return friendsOnline;
400  }
401 
402  [Obsolete]
403  public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
404  {
405  Hashtable hash = new Hashtable();
406  hash["userID"] = userID.ToString();
407  int i = 0;
408  foreach (string s in friends)
409  {
410  hash["friend_" + i.ToString()] = s;
411  i++;
412  }
413 
414  IList paramList = new ArrayList();
415  paramList.Add(hash);
416 
417  XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
418 // string reason = string.Empty;
419 
420  // Send and get reply
421  List<UUID> online = new List<UUID>();
422  XmlRpcResponse response = null;
423  try
424  {
425  response = request.Send(m_ServerURL, 10000);
426  }
427  catch
428  {
429  m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURLHost);
430 // reason = "Exception: " + e.Message;
431  return online;
432  }
433 
434  if (response.IsFault)
435  {
436  m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURLHost, response.FaultString);
437 // reason = "XMLRPC Fault";
438  return online;
439  }
440 
441  hash = (Hashtable)response.Value;
442  //foreach (Object o in hash)
443  // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
444  try
445  {
446  if (hash == null)
447  {
448  m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
449 // reason = "Internal error 1";
450  return online;
451  }
452 
453  // Here is the actual response
454  foreach (object key in hash.Keys)
455  {
456  if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
457  {
458  UUID uuid;
459  if (UUID.TryParse(hash[key].ToString(), out uuid))
460  online.Add(uuid);
461  }
462  }
463 
464  }
465  catch
466  {
467  m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
468 // reason = "Exception: " + e.Message;
469  }
470 
471  return online;
472  }
473 
474  public Dictionary<string,object> GetUserInfo (UUID userID)
475  {
476  Hashtable hash = new Hashtable();
477  hash["userID"] = userID.ToString();
478 
479  hash = CallServer("get_user_info", hash);
480 
481  Dictionary<string, object> info = new Dictionary<string, object>();
482 
483  foreach (object key in hash.Keys)
484  {
485  if (hash[key] != null)
486  {
487  info.Add(key.ToString(), hash[key]);
488  }
489  }
490 
491  return info;
492  }
493 
494  public Dictionary<string, object> GetServerURLs(UUID userID)
495  {
496  Hashtable hash = new Hashtable();
497  hash["userID"] = userID.ToString();
498 
499  hash = CallServer("get_server_urls", hash);
500 
501  Dictionary<string, object> serverURLs = new Dictionary<string, object>();
502  foreach (object key in hash.Keys)
503  {
504  if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null)
505  {
506  string serverType = key.ToString().Substring(4); // remove "SRV_"
507  serverURLs.Add(serverType, hash[key].ToString());
508  }
509  }
510 
511  return serverURLs;
512  }
513 
514  public string LocateUser(UUID userID)
515  {
516  Hashtable hash = new Hashtable();
517  hash["userID"] = userID.ToString();
518 
519  hash = CallServer("locate_user", hash);
520 
521  string url = string.Empty;
522 
523  // Here's the actual response
524  if (hash.ContainsKey("URL"))
525  url = hash["URL"].ToString();
526 
527  return url;
528  }
529 
530  public string GetUUI(UUID userID, UUID targetUserID)
531  {
532  Hashtable hash = new Hashtable();
533  hash["userID"] = userID.ToString();
534  hash["targetUserID"] = targetUserID.ToString();
535 
536  hash = CallServer("get_uui", hash);
537 
538  string uui = string.Empty;
539 
540  // Here's the actual response
541  if (hash.ContainsKey("UUI"))
542  uui = hash["UUI"].ToString();
543 
544  return uui;
545  }
546 
547  public UUID GetUUID(String first, String last)
548  {
549  Hashtable hash = new Hashtable();
550  hash["first"] = first;
551  hash["last"] = last;
552 
553  hash = CallServer("get_uuid", hash);
554 
555  if (!hash.ContainsKey("UUID"))
556  {
557  throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} didn't return a UUID", m_ServerURLHost));
558  }
559 
560  UUID uuid;
561  if (!UUID.TryParse(hash["UUID"].ToString(), out uuid))
562  {
563  throw new Exception(string.Format("[USER AGENT CONNECTOR]: get_uuid call to {0} returned an invalid UUID: {1}", m_ServerURLHost, hash["UUID"].ToString()));
564  }
565 
566  return uuid;
567  }
568 
569  private bool GetBoolResponse(XmlRpcRequest request, out string reason)
570  {
571  //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURLHost);
572  XmlRpcResponse response = null;
573  try
574  {
575  response = request.Send(m_ServerURL, 10000);
576  }
577  catch (Exception e)
578  {
579  m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURLHost);
580  reason = "Exception: " + e.Message;
581  return false;
582  }
583 
584  if (response.IsFault)
585  {
586  m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURLHost, response.FaultString);
587  reason = "XMLRPC Fault";
588  return false;
589  }
590 
591  Hashtable hash = (Hashtable)response.Value;
592  //foreach (Object o in hash)
593  // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
594  try
595  {
596  if (hash == null)
597  {
598  m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURLHost);
599  reason = "Internal error 1";
600  return false;
601  }
602  bool success = false;
603  reason = string.Empty;
604  if (hash.ContainsKey("result"))
605  Boolean.TryParse((string)hash["result"], out success);
606  else
607  {
608  reason = "Internal error 2";
609  m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURLHost);
610  }
611 
612  return success;
613  }
614  catch (Exception e)
615  {
616  m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetBoolResponse response.");
617  if (hash.ContainsKey("result") && hash["result"] != null)
618  m_log.ErrorFormat("Reply was ", (string)hash["result"]);
619  reason = "Exception: " + e.Message;
620  return false;
621  }
622 
623  }
624 
625  }
626 }
OpenSim.Framework.Constants.TeleportFlags TeleportFlags
List< UUID > GetOnlineFriends(UUID userID, List< string > friends)
string LocateUser(UUID userID)
Returns the current location of a remote user.
List< UUID > StatusNotification(List< string > friends, UUID userID, bool online)
OpenMetaverse.StructuredData.OSDMap OSDMap
Dictionary< string, object > GetUserInfo(UUID userID)
Returns the UserInfo of a remote user.
UUID GetUUID(String first, String last)
Returns the remote user that has the given name.
OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString key
Definition: ICM_Api.cs:31
OpenSim.Services.Interfaces.GridRegion GridRegion
bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
override void PackData(OSDMap args, GridRegion source, AgentCircuitData aCircuit, GridRegion destination, uint flags)
Circuit data for an agent. Connection information shared between regions that accept UDP connections ...
GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
Returns the home region of a remote user.
Dictionary< string, object > GetServerURLs(UUID userID)
Returns the Server URLs of a remote user.
string GetUUI(UUID userID, UUID targetUserID)
Returns the Universal User Identifier for 'targetUserID' on behalf of 'userID'.
string ServerURI
A well-formed URI for the host region server (namely "http://" + ExternalHostName) ...
bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
bool LoginAgentToGrid(GridRegion source, AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, bool fromLogin, out string reason)