aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services')
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs45
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs206
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs274
-rw-r--r--OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs130
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs25
-rw-r--r--OpenSim/Services/Friends/FriendsService.cs38
-rw-r--r--OpenSim/Services/HypergridService/HGInstantMessageService.cs317
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs224
-rw-r--r--OpenSim/Services/Interfaces/IFriendsService.cs4
-rw-r--r--OpenSim/Services/Interfaces/IHypergridServices.cs (renamed from OpenSim/Services/Interfaces/IGatekeeperService.cs)24
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginResponse.cs14
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs30
12 files changed, 1304 insertions, 27 deletions
diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs
index 861c475..08f1dc3 100644
--- a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs
@@ -38,7 +38,7 @@ using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38using OpenSim.Server.Base; 38using OpenSim.Server.Base;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41namespace OpenSim.Services.Connectors 41namespace OpenSim.Services.Connectors.Friends
42{ 42{
43 public class FriendsServicesConnector : IFriendsService 43 public class FriendsServicesConnector : IFriendsService
44 { 44 {
@@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors
84 84
85 85
86 #region IFriendsService 86 #region IFriendsService
87 87
88 public FriendInfo[] GetFriends(UUID PrincipalID) 88 public FriendInfo[] GetFriends(UUID PrincipalID)
89 { 89 {
90 Dictionary<string, object> sendData = new Dictionary<string, object>(); 90 Dictionary<string, object> sendData = new Dictionary<string, object>();
@@ -92,6 +92,21 @@ namespace OpenSim.Services.Connectors
92 sendData["PRINCIPALID"] = PrincipalID.ToString(); 92 sendData["PRINCIPALID"] = PrincipalID.ToString();
93 sendData["METHOD"] = "getfriends"; 93 sendData["METHOD"] = "getfriends";
94 94
95 return GetFriends(sendData, PrincipalID.ToString());
96 }
97
98 public FriendInfo[] GetFriends(string PrincipalID)
99 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>();
101
102 sendData["PRINCIPALID"] = PrincipalID;
103 sendData["METHOD"] = "getfriends_string";
104
105 return GetFriends(sendData, PrincipalID);
106 }
107
108 protected FriendInfo[] GetFriends(Dictionary<string, object> sendData, string PrincipalID)
109 {
95 string reqString = ServerUtils.BuildQueryString(sendData); 110 string reqString = ServerUtils.BuildQueryString(sendData);
96 111
97 try 112 try
@@ -144,10 +159,17 @@ namespace OpenSim.Services.Connectors
144 159
145 } 160 }
146 161
147 public bool StoreFriend(UUID PrincipalID, string Friend, int flags) 162 public bool StoreFriend(string PrincipalID, string Friend, int flags)
148 { 163 {
149 FriendInfo finfo = new FriendInfo(); 164 FriendInfo finfo = new FriendInfo();
150 finfo.PrincipalID = PrincipalID; 165 try
166 {
167 finfo.PrincipalID = new UUID(PrincipalID);
168 }
169 catch
170 {
171 return false;
172 }
151 finfo.Friend = Friend; 173 finfo.Friend = Friend;
152 finfo.MyFlags = flags; 174 finfo.MyFlags = flags;
153 175
@@ -189,6 +211,16 @@ namespace OpenSim.Services.Connectors
189 211
190 } 212 }
191 213
214 public bool Delete(string PrincipalID, string Friend)
215 {
216 Dictionary<string, object> sendData = new Dictionary<string, object>();
217 sendData["PRINCIPALID"] = PrincipalID.ToString();
218 sendData["FRIEND"] = Friend;
219 sendData["METHOD"] = "deletefriend_string";
220
221 return Delete(sendData, PrincipalID, Friend);
222 }
223
192 public bool Delete(UUID PrincipalID, string Friend) 224 public bool Delete(UUID PrincipalID, string Friend)
193 { 225 {
194 Dictionary<string, object> sendData = new Dictionary<string, object>(); 226 Dictionary<string, object> sendData = new Dictionary<string, object>();
@@ -196,6 +228,11 @@ namespace OpenSim.Services.Connectors
196 sendData["FRIEND"] = Friend; 228 sendData["FRIEND"] = Friend;
197 sendData["METHOD"] = "deletefriend"; 229 sendData["METHOD"] = "deletefriend";
198 230
231 return Delete(sendData, PrincipalID.ToString(), Friend);
232 }
233
234 public bool Delete(Dictionary<string, object> sendData, string PrincipalID, string Friend)
235 {
199 string reply = string.Empty; 236 string reply = string.Empty;
200 try 237 try
201 { 238 {
diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs
new file mode 100644
index 0000000..d699f59
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs
@@ -0,0 +1,206 @@
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
28using log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors.Friends;
37using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors.Hypergrid
42{
43 public class HGFriendsServicesConnector
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private string m_ServerURI = String.Empty;
50 private string m_ServiceKey = String.Empty;
51 private UUID m_SessionID;
52
53 public HGFriendsServicesConnector()
54 {
55 }
56
57 public HGFriendsServicesConnector(string serverURI)
58 {
59 m_ServerURI = serverURI.TrimEnd('/');
60 }
61
62 public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey)
63 {
64 m_ServerURI = serverURI.TrimEnd('/');
65 m_ServiceKey = serviceKey;
66 m_SessionID = sessionID;
67 }
68
69 #region IFriendsService
70
71 public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
72 {
73 Dictionary<string, object> sendData = new Dictionary<string, object>();
74
75 sendData["PRINCIPALID"] = PrincipalID.ToString();
76 sendData["FRIENDID"] = friendID.ToString();
77 sendData["METHOD"] = "getfriendperms";
78 sendData["KEY"] = m_ServiceKey;
79 sendData["SESSIONID"] = m_SessionID.ToString();
80
81 string reqString = ServerUtils.BuildQueryString(sendData);
82
83 try
84 {
85 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
86 m_ServerURI + "/hgfriends",
87 reqString);
88 if (reply != string.Empty)
89 {
90 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
91
92 if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null))
93 {
94 uint perms = 0;
95 uint.TryParse(replyData["Value"].ToString(), out perms);
96 return perms;
97 }
98 else
99 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response",
100 PrincipalID);
101
102 }
103 }
104 catch (Exception e)
105 {
106 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
107 }
108
109 return 0;
110
111 }
112
113 public bool NewFriendship(UUID PrincipalID, string Friend)
114 {
115 FriendInfo finfo = new FriendInfo();
116 finfo.PrincipalID = PrincipalID;
117 finfo.Friend = Friend;
118
119 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
120
121 sendData["METHOD"] = "newfriendship";
122 sendData["KEY"] = m_ServiceKey;
123 sendData["SESSIONID"] = m_SessionID.ToString();
124
125 string reply = string.Empty;
126 try
127 {
128 reply = SynchronousRestFormsRequester.MakeRequest("POST",
129 m_ServerURI + "/hgfriends",
130 ServerUtils.BuildQueryString(sendData));
131 }
132 catch (Exception e)
133 {
134 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
135 return false;
136 }
137
138 if (reply != string.Empty)
139 {
140 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
141
142 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
143 {
144 bool success = false;
145 Boolean.TryParse(replyData["Result"].ToString(), out success);
146 return success;
147 }
148 else
149 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response",
150 PrincipalID, Friend);
151 }
152 else
153 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply");
154
155 return false;
156
157 }
158
159 public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret)
160 {
161 FriendInfo finfo = new FriendInfo();
162 finfo.PrincipalID = PrincipalID;
163 finfo.Friend = Friend.ToString();
164
165 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
166
167 sendData["METHOD"] = "deletefriendship";
168 sendData["SECRET"] = secret;
169
170 string reply = string.Empty;
171 try
172 {
173 reply = SynchronousRestFormsRequester.MakeRequest("POST",
174 m_ServerURI + "/hgfriends",
175 ServerUtils.BuildQueryString(sendData));
176 }
177 catch (Exception e)
178 {
179 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
180 return false;
181 }
182
183 if (reply != string.Empty)
184 {
185 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
186
187 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
188 {
189 bool success = false;
190 Boolean.TryParse(replyData["Result"].ToString(), out success);
191 return success;
192 }
193 else
194 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response",
195 PrincipalID, Friend);
196 }
197 else
198 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply");
199
200 return false;
201
202 }
203
204 #endregion
205 }
206} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
index c40a347..1c01563 100644
--- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -404,6 +404,280 @@ namespace OpenSim.Services.Connectors.Hypergrid
404 GetBoolResponse(request, out reason); 404 GetBoolResponse(request, out reason);
405 } 405 }
406 406
407 public void StatusNotification(List<string> friends, UUID userID, bool online)
408 {
409 Hashtable hash = new Hashtable();
410 hash["userID"] = userID.ToString();
411 hash["online"] = online.ToString();
412 int i = 0;
413 foreach (string s in friends)
414 {
415 hash["friend_" + i.ToString()] = s;
416 i++;
417 }
418
419 IList paramList = new ArrayList();
420 paramList.Add(hash);
421
422 XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
423 string reason = string.Empty;
424 GetBoolResponse(request, out reason);
425
426 }
427
428 public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
429 {
430 Hashtable hash = new Hashtable();
431 hash["userID"] = userID.ToString();
432 int i = 0;
433 foreach (string s in friends)
434 {
435 hash["friend_" + i.ToString()] = s;
436 i++;
437 }
438
439 IList paramList = new ArrayList();
440 paramList.Add(hash);
441
442 XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
443 string reason = string.Empty;
444
445 // Send and get reply
446 List<UUID> online = new List<UUID>();
447 XmlRpcResponse response = null;
448 try
449 {
450 response = request.Send(m_ServerURL, 10000);
451 }
452 catch (Exception e)
453 {
454 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
455 reason = "Exception: " + e.Message;
456 return online;
457 }
458
459 if (response.IsFault)
460 {
461 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
462 reason = "XMLRPC Fault";
463 return online;
464 }
465
466 hash = (Hashtable)response.Value;
467 //foreach (Object o in hash)
468 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
469 try
470 {
471 if (hash == null)
472 {
473 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
474 reason = "Internal error 1";
475 return online;
476 }
477
478 // Here is the actual response
479 foreach (object key in hash.Keys)
480 {
481 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
482 {
483 UUID uuid;
484 if (UUID.TryParse(hash[key].ToString(), out uuid))
485 online.Add(uuid);
486 }
487 }
488
489 }
490 catch (Exception e)
491 {
492 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
493 reason = "Exception: " + e.Message;
494 }
495
496 return online;
497 }
498
499 public Dictionary<string, object> GetServerURLs(UUID userID)
500 {
501 Hashtable hash = new Hashtable();
502 hash["userID"] = userID.ToString();
503
504 IList paramList = new ArrayList();
505 paramList.Add(hash);
506
507 XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList);
508 string reason = string.Empty;
509
510 // Send and get reply
511 Dictionary<string, object> serverURLs = new Dictionary<string,object>();
512 XmlRpcResponse response = null;
513 try
514 {
515 response = request.Send(m_ServerURL, 10000);
516 }
517 catch (Exception e)
518 {
519 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
520 reason = "Exception: " + e.Message;
521 return serverURLs;
522 }
523
524 if (response.IsFault)
525 {
526 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
527 reason = "XMLRPC Fault";
528 return serverURLs;
529 }
530
531 hash = (Hashtable)response.Value;
532 //foreach (Object o in hash)
533 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
534 try
535 {
536 if (hash == null)
537 {
538 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
539 reason = "Internal error 1";
540 return serverURLs;
541 }
542
543 // Here is the actual response
544 foreach (object key in hash.Keys)
545 {
546 if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null)
547 {
548 string serverType = key.ToString().Substring(4); // remove "SRV_"
549 serverURLs.Add(serverType, hash[key].ToString());
550 }
551 }
552
553 }
554 catch (Exception e)
555 {
556 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
557 reason = "Exception: " + e.Message;
558 }
559
560 return serverURLs;
561 }
562
563 public string LocateUser(UUID userID)
564 {
565 Hashtable hash = new Hashtable();
566 hash["userID"] = userID.ToString();
567
568 IList paramList = new ArrayList();
569 paramList.Add(hash);
570
571 XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList);
572 string reason = string.Empty;
573
574 // Send and get reply
575 string url = string.Empty;
576 XmlRpcResponse response = null;
577 try
578 {
579 m_log.DebugFormat("[XXX]: Calling locate_user on {0}", m_ServerURL);
580 response = request.Send(m_ServerURL, 10000);
581 }
582 catch (Exception e)
583 {
584 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
585 reason = "Exception: " + e.Message;
586 return url;
587 }
588
589 if (response.IsFault)
590 {
591 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
592 reason = "XMLRPC Fault";
593 return url;
594 }
595
596 hash = (Hashtable)response.Value;
597 //foreach (Object o in hash)
598 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
599 try
600 {
601 if (hash == null)
602 {
603 m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
604 reason = "Internal error 1";
605 return url;
606 }
607
608 // Here's the actual response
609 if (hash.ContainsKey("URL"))
610 url = hash["URL"].ToString();
611
612 }
613 catch (Exception e)
614 {
615 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response.");
616 reason = "Exception: " + e.Message;
617 }
618
619 return url;
620 }
621
622 public string GetUUI(UUID userID, UUID targetUserID)
623 {
624 Hashtable hash = new Hashtable();
625 hash["userID"] = userID.ToString();
626 hash["targetUserID"] = targetUserID.ToString();
627
628 IList paramList = new ArrayList();
629 paramList.Add(hash);
630
631 XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList);
632 string reason = string.Empty;
633
634 // Send and get reply
635 string uui = string.Empty;
636 XmlRpcResponse response = null;
637 try
638 {
639 m_log.DebugFormat("[XXX]: Calling get_uuid on {0}", m_ServerURL);
640 response = request.Send(m_ServerURL, 10000);
641 }
642 catch (Exception e)
643 {
644 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
645 reason = "Exception: " + e.Message;
646 return uui;
647 }
648
649 if (response.IsFault)
650 {
651 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
652 reason = "XMLRPC Fault";
653 return uui;
654 }
655
656 hash = (Hashtable)response.Value;
657 //foreach (Object o in hash)
658 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
659 try
660 {
661 if (hash == null)
662 {
663 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
664 reason = "Internal error 1";
665 return uui;
666 }
667
668 // Here's the actual response
669 if (hash.ContainsKey("UUI"))
670 uui = hash["UUI"].ToString();
671
672 }
673 catch (Exception e)
674 {
675 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response.");
676 reason = "Exception: " + e.Message;
677 }
678
679 return uui;
680 }
407 681
408 private bool GetBoolResponse(XmlRpcRequest request, out string reason) 682 private bool GetBoolResponse(XmlRpcRequest request, out string reason)
409 { 683 {
diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
new file mode 100644
index 0000000..2a922de
--- /dev/null
+++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
@@ -0,0 +1,130 @@
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 */
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenMetaverse;
34using Nwc.XmlRpc;
35using log4net;
36
37using OpenSim.Framework;
38
39namespace OpenSim.Services.Connectors.InstantMessage
40{
41 public class InstantMessageServiceConnector
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 /// This actually does the XMLRPC Request
49 /// </summary>
50 /// <param name="url">URL we pull the data out of to send the request to</param>
51 /// <param name="im">The Instant Message </param>
52 /// <returns>Bool if the message was successfully delivered at the other side.</returns>
53 public static bool SendInstantMessage(string url, GridInstantMessage im)
54 {
55 Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im);
56 xmlrpcdata["region_handle"] = 0;
57
58 ArrayList SendParams = new ArrayList();
59 SendParams.Add(xmlrpcdata);
60 XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);
61 try
62 {
63
64 XmlRpcResponse GridResp = GridReq.Send(url, 3000);
65
66 Hashtable responseData = (Hashtable)GridResp.Value;
67
68 if (responseData.ContainsKey("success"))
69 {
70 if ((string)responseData["success"] == "TRUE")
71 {
72 m_log.DebugFormat("[XXX] Success");
73 return true;
74 }
75 else
76 {
77 m_log.DebugFormat("[XXX] Fail");
78 return false;
79 }
80 }
81 else
82 {
83 m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url);
84 return false;
85 }
86 }
87 catch (WebException e)
88 {
89 m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url);
90 }
91
92 return false;
93 }
94
95 /// <summary>
96 /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC
97 /// </summary>
98 /// <param name="msg">The GridInstantMessage object</param>
99 /// <returns>Hashtable containing the XMLRPC request</returns>
100 protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
101 {
102 Hashtable gim = new Hashtable();
103 gim["from_agent_id"] = msg.fromAgentID.ToString();
104 // Kept for compatibility
105 gim["from_agent_session"] = UUID.Zero.ToString();
106 gim["to_agent_id"] = msg.toAgentID.ToString();
107 gim["im_session_id"] = msg.imSessionID.ToString();
108 gim["timestamp"] = msg.timestamp.ToString();
109 gim["from_agent_name"] = msg.fromAgentName;
110 gim["message"] = msg.message;
111 byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog;
112 gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None);
113
114 if (msg.fromGroup)
115 gim["from_group"] = "TRUE";
116 else
117 gim["from_group"] = "FALSE";
118 byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline;
119 gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None);
120 gim["parent_estate_id"] = msg.ParentEstateID.ToString();
121 gim["position_x"] = msg.Position.X.ToString();
122 gim["position_y"] = msg.Position.Y.ToString();
123 gim["position_z"] = msg.Position.Z.ToString();
124 gim["region_id"] = msg.RegionID.ToString();
125 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None);
126 return gim;
127 }
128
129 }
130}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
index 6f2d735..7422d94 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
@@ -78,6 +78,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
78 78
79 public FriendInfo[] GetFriends(UUID principalID) 79 public FriendInfo[] GetFriends(UUID principalID)
80 { 80 {
81 return GetFriends(principalID.ToString());
82 }
83
84 public FriendInfo[] GetFriends(string principalID)
85 {
81 if (String.IsNullOrEmpty(m_serverUrl)) 86 if (String.IsNullOrEmpty(m_serverUrl))
82 return new FriendInfo[0]; 87 return new FriendInfo[0];
83 88
@@ -95,7 +100,14 @@ namespace OpenSim.Services.Connectors.SimianGrid
95 UUID friendID = friendEntry["Key"].AsUUID(); 100 UUID friendID = friendEntry["Key"].AsUUID();
96 101
97 FriendInfo friend = new FriendInfo(); 102 FriendInfo friend = new FriendInfo();
98 friend.PrincipalID = principalID; 103 if (!UUID.TryParse(principalID, out friend.PrincipalID))
104 {
105 string tmp = string.Empty;
106 if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp))
107 // bad record. ignore this entry
108 continue;
109 }
110
99 friend.Friend = friendID.ToString(); 111 friend.Friend = friendID.ToString();
100 friend.MyFlags = friendEntry["Value"].AsInteger(); 112 friend.MyFlags = friendEntry["Value"].AsInteger();
101 friend.TheirFlags = -1; 113 friend.TheirFlags = -1;
@@ -127,7 +139,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
127 return array; 139 return array;
128 } 140 }
129 141
130 public bool StoreFriend(UUID principalID, string friend, int flags) 142 public bool StoreFriend(string principalID, string friend, int flags)
131 { 143 {
132 if (String.IsNullOrEmpty(m_serverUrl)) 144 if (String.IsNullOrEmpty(m_serverUrl))
133 return true; 145 return true;
@@ -152,6 +164,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
152 164
153 public bool Delete(UUID principalID, string friend) 165 public bool Delete(UUID principalID, string friend)
154 { 166 {
167 return Delete(principalID.ToString(), friend);
168 }
169
170 public bool Delete(string principalID, string friend)
171 {
155 if (String.IsNullOrEmpty(m_serverUrl)) 172 if (String.IsNullOrEmpty(m_serverUrl))
156 return true; 173 return true;
157 174
@@ -174,7 +191,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
174 191
175 #endregion IFriendsService 192 #endregion IFriendsService
176 193
177 private OSDArray GetFriended(UUID ownerID) 194 private OSDArray GetFriended(string ownerID)
178 { 195 {
179 NameValueCollection requestArgs = new NameValueCollection 196 NameValueCollection requestArgs = new NameValueCollection
180 { 197 {
@@ -195,7 +212,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
195 } 212 }
196 } 213 }
197 214
198 private OSDArray GetFriendedBy(UUID ownerID) 215 private OSDArray GetFriendedBy(string ownerID)
199 { 216 {
200 NameValueCollection requestArgs = new NameValueCollection 217 NameValueCollection requestArgs = new NameValueCollection
201 { 218 {
diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs
index 3c64ecc..e2033ac 100644
--- a/OpenSim/Services/Friends/FriendsService.cs
+++ b/OpenSim/Services/Friends/FriendsService.cs
@@ -43,17 +43,42 @@ namespace OpenSim.Services.Friends
43 { 43 {
44 } 44 }
45 45
46 public FriendInfo[] GetFriends(UUID PrincipalID) 46 public virtual FriendInfo[] GetFriends(UUID PrincipalID)
47 { 47 {
48 FriendsData[] data = m_Database.GetFriends(PrincipalID); 48 FriendsData[] data = m_Database.GetFriends(PrincipalID);
49 List<FriendInfo> info = new List<FriendInfo>();
50
51 foreach (FriendsData d in data)
52 {
53 FriendInfo i = new FriendInfo();
54
55 i.PrincipalID = new UUID(d.PrincipalID);
56 i.Friend = d.Friend;
57 i.MyFlags = Convert.ToInt32(d.Data["Flags"]);
58 i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]);
59
60 info.Add(i);
61 }
62
63 return info.ToArray();
64 }
49 65
66 public virtual FriendInfo[] GetFriends(string PrincipalID)
67 {
68 FriendsData[] data = m_Database.GetFriends(PrincipalID);
50 List<FriendInfo> info = new List<FriendInfo>(); 69 List<FriendInfo> info = new List<FriendInfo>();
51 70
52 foreach (FriendsData d in data) 71 foreach (FriendsData d in data)
53 { 72 {
54 FriendInfo i = new FriendInfo(); 73 FriendInfo i = new FriendInfo();
55 74
56 i.PrincipalID = d.PrincipalID; 75 if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID))
76 {
77 string tmp = string.Empty;
78 if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp, out tmp))
79 // bad record. ignore this entry
80 continue;
81 }
57 i.Friend = d.Friend; 82 i.Friend = d.Friend;
58 i.MyFlags = Convert.ToInt32(d.Data["Flags"]); 83 i.MyFlags = Convert.ToInt32(d.Data["Flags"]);
59 i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]); 84 i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]);
@@ -64,7 +89,7 @@ namespace OpenSim.Services.Friends
64 return info.ToArray(); 89 return info.ToArray();
65 } 90 }
66 91
67 public bool StoreFriend(UUID PrincipalID, string Friend, int flags) 92 public virtual bool StoreFriend(string PrincipalID, string Friend, int flags)
68 { 93 {
69 FriendsData d = new FriendsData(); 94 FriendsData d = new FriendsData();
70 95
@@ -76,7 +101,12 @@ namespace OpenSim.Services.Friends
76 return m_Database.Store(d); 101 return m_Database.Store(d);
77 } 102 }
78 103
79 public bool Delete(UUID PrincipalID, string Friend) 104 public bool Delete(string principalID, string friend)
105 {
106 return m_Database.Delete(principalID, friend);
107 }
108
109 public virtual bool Delete(UUID PrincipalID, string Friend)
80 { 110 {
81 return m_Database.Delete(PrincipalID, Friend); 111 return m_Database.Delete(PrincipalID, Friend);
82 } 112 }
diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
new file mode 100644
index 0000000..ca0fd7f
--- /dev/null
+++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
@@ -0,0 +1,317 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.InstantMessage;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
41
42using OpenMetaverse;
43using log4net;
44using Nini.Config;
45
46namespace OpenSim.Services.HypergridService
47{
48 /// <summary>
49 /// Inter-grid IM
50 /// </summary>
51 public class HGInstantMessageService : IInstantMessage
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours
58
59 static bool m_Initialized = false;
60
61 protected static IGridService m_GridService;
62 protected static IPresenceService m_PresenceService;
63 protected static IUserAgentService m_UserAgentService;
64
65 protected static IInstantMessageSimConnector m_IMSimConnector;
66
67 protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
68 private static ExpiringCache<UUID, GridRegion> m_RegionCache;
69
70 public HGInstantMessageService(IConfigSource config)
71 : this(config, null)
72 {
73 }
74
75 public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector)
76 {
77 if (imConnector != null)
78 m_IMSimConnector = imConnector;
79
80 if (!m_Initialized)
81 {
82 m_Initialized = true;
83
84 m_log.DebugFormat("[HG IM SERVICE]: Starting...");
85
86 IConfig serverConfig = config.Configs["HGInstantMessageService"];
87 if (serverConfig == null)
88 throw new Exception(String.Format("No section HGInstantMessageService in config file"));
89
90 string gridService = serverConfig.GetString("GridService", String.Empty);
91 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
92 string userAgentService = serverConfig.GetString("UserAgentService", String.Empty);
93
94 if (gridService == string.Empty || presenceService == string.Empty)
95 throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function."));
96
97 Object[] args = new Object[] { config };
98 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
99 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
100 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
101
102 m_RegionCache = new ExpiringCache<UUID, GridRegion>();
103
104 }
105 }
106
107 public bool IncomingInstantMessage(GridInstantMessage im)
108 {
109 m_log.DebugFormat("[HG IM SERVICE]: Received message {0} from {1} to {2}", im.message, im.fromAgentID, im.toAgentID);
110 UUID toAgentID = new UUID(im.toAgentID);
111
112 if (m_IMSimConnector != null)
113 {
114 m_log.DebugFormat("[XXX] SendIMToRegion local im connector");
115 return m_IMSimConnector.SendInstantMessage(im);
116 }
117 else
118 return TrySendInstantMessage(im, "", true);
119 }
120
121 public bool OutgoingInstantMessage(GridInstantMessage im, string url)
122 {
123 m_log.DebugFormat("[HG IM SERVICE]: Sending message {0} from {1} to {2}@{3}", im.message, im.fromAgentID, im.toAgentID, url);
124 if (url != string.Empty)
125 return TrySendInstantMessage(im, url, true);
126 else
127 {
128 PresenceInfo upd = new PresenceInfo();
129 upd.RegionID = UUID.Zero;
130 return TrySendInstantMessage(im, upd, true);
131 }
132 }
133
134 protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime)
135 {
136 UUID toAgentID = new UUID(im.toAgentID);
137
138 PresenceInfo upd = null;
139 string url = string.Empty;
140
141 bool lookupAgent = false;
142
143 lock (m_UserLocationMap)
144 {
145 if (m_UserLocationMap.ContainsKey(toAgentID))
146 {
147 object o = m_UserLocationMap[toAgentID];
148 if (o is PresenceInfo)
149 upd = (PresenceInfo)o;
150 else if (o is string)
151 url = (string)o;
152
153 // We need to compare the current location with the previous
154 // or the recursive loop will never end because it will never try to lookup the agent again
155 if (!firstTime)
156 {
157 lookupAgent = true;
158 upd = null;
159 url = string.Empty;
160 }
161 }
162 else
163 {
164 lookupAgent = true;
165 }
166 }
167
168 m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no"));
169
170 // Are we needing to look-up an agent?
171 if (lookupAgent)
172 {
173 // Non-cached user agent lookup.
174 PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() });
175 if (presences != null && presences.Length > 0)
176 {
177 foreach (PresenceInfo p in presences)
178 {
179 if (p.RegionID != UUID.Zero)
180 {
181 m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID);
182 upd = p;
183 break;
184 }
185 }
186 }
187
188 if (upd == null)
189 {
190 // Let's check with the UAS if the user is elsewhere
191 m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service");
192 url = m_UserAgentService.LocateUser(toAgentID);
193 }
194
195 if (upd != null || url != string.Empty)
196 {
197 // check if we've tried this before..
198 // This is one way to end the recursive loop
199 //
200 if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) ||
201 (previousLocation is string && upd == null && previousLocation.Equals(url))))
202 {
203 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
204 m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url);
205
206 return false;
207 }
208 }
209 }
210
211 if (upd != null)
212 {
213 // ok, the user is around somewhere. Let's send back the reply with "success"
214 // even though the IM may still fail. Just don't keep the caller waiting for
215 // the entire time we're trying to deliver the IM
216 return SendIMToRegion(upd, im, toAgentID);
217 }
218 else if (url != string.Empty)
219 {
220 // ok, the user is around somewhere. Let's send back the reply with "success"
221 // even though the IM may still fail. Just don't keep the caller waiting for
222 // the entire time we're trying to deliver the IM
223 return ForwardIMToGrid(url, im, toAgentID);
224 }
225 else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty)
226 {
227 return ForwardIMToGrid((string)previousLocation, im, toAgentID);
228 }
229 else
230 m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID);
231 return false;
232 }
233
234 bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID)
235 {
236 bool imresult = false;
237 GridRegion reginfo = null;
238 if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo))
239 {
240 reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID);
241 if (reginfo != null)
242 m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS);
243 }
244
245 if (reginfo != null)
246 {
247 imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im);
248 }
249 else
250 {
251 m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI);
252 return false;
253 }
254
255 if (imresult)
256 {
257 // IM delivery successful, so store the Agent's location in our local cache.
258 lock (m_UserLocationMap)
259 {
260 if (m_UserLocationMap.ContainsKey(toAgentID))
261 {
262 m_UserLocationMap[toAgentID] = upd;
263 }
264 else
265 {
266 m_UserLocationMap.Add(toAgentID, upd);
267 }
268 }
269 return true;
270 }
271 else
272 {
273 // try again, but lookup user this time.
274 // Warning, this must call the Async version
275 // of this method or we'll be making thousands of threads
276 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
277 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
278
279 // This is recursive!!!!!
280 return TrySendInstantMessage(im, upd, false);
281 }
282 }
283
284 bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID)
285 {
286 if (InstantMessageServiceConnector.SendInstantMessage(url, im))
287 {
288 // IM delivery successful, so store the Agent's location in our local cache.
289 lock (m_UserLocationMap)
290 {
291 if (m_UserLocationMap.ContainsKey(toAgentID))
292 {
293 m_UserLocationMap[toAgentID] = url;
294 }
295 else
296 {
297 m_UserLocationMap.Add(toAgentID, url);
298 }
299 }
300
301 return true;
302 }
303 else
304 {
305 // try again, but lookup user this time.
306 // Warning, this must call the Async version
307 // of this method or we'll be making thousands of threads
308 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
309 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
310
311 // This is recursive!!!!!
312 return TrySendInstantMessage(im, url, false);
313 }
314
315 }
316 }
317}
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 445d45e..387547e 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -31,10 +31,12 @@ using System.Net;
31using System.Reflection; 31using System.Reflection;
32 32
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
34using OpenSim.Services.Connectors.Hypergrid; 35using OpenSim.Services.Connectors.Hypergrid;
35using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion; 37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37using OpenSim.Server.Base; 38using OpenSim.Server.Base;
39using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38 40
39using OpenMetaverse; 41using OpenMetaverse;
40using log4net; 42using log4net;
@@ -63,19 +65,35 @@ namespace OpenSim.Services.HypergridService
63 protected static IGridService m_GridService; 65 protected static IGridService m_GridService;
64 protected static GatekeeperServiceConnector m_GatekeeperConnector; 66 protected static GatekeeperServiceConnector m_GatekeeperConnector;
65 protected static IGatekeeperService m_GatekeeperService; 67 protected static IGatekeeperService m_GatekeeperService;
68 protected static IFriendsService m_FriendsService;
69 protected static IPresenceService m_PresenceService;
70 protected static IUserAccountService m_UserAccountService;
71 protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
72 protected static FriendsSimConnector m_FriendsSimConnector; // grid
66 73
67 protected static string m_GridName; 74 protected static string m_GridName;
68 75
69 protected static bool m_BypassClientVerification; 76 protected static bool m_BypassClientVerification;
70 77
71 public UserAgentService(IConfigSource config) 78 public UserAgentService(IConfigSource config) : this(config, null)
72 { 79 {
80 }
81
82 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
83 {
84 // Let's set this always, because we don't know the sequence
85 // of instantiations
86 if (friendsConnector != null)
87 m_FriendsLocalSimConnector = friendsConnector;
88
73 if (!m_Initialized) 89 if (!m_Initialized)
74 { 90 {
75 m_Initialized = true; 91 m_Initialized = true;
76 92
77 m_log.DebugFormat("[HOME USERS SECURITY]: Starting..."); 93 m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
78 94
95 m_FriendsSimConnector = new FriendsSimConnector();
96
79 IConfig serverConfig = config.Configs["UserAgentService"]; 97 IConfig serverConfig = config.Configs["UserAgentService"];
80 if (serverConfig == null) 98 if (serverConfig == null)
81 throw new Exception(String.Format("No section UserAgentService in config file")); 99 throw new Exception(String.Format("No section UserAgentService in config file"));
@@ -83,6 +101,9 @@ namespace OpenSim.Services.HypergridService
83 string gridService = serverConfig.GetString("GridService", String.Empty); 101 string gridService = serverConfig.GetString("GridService", String.Empty);
84 string gridUserService = serverConfig.GetString("GridUserService", String.Empty); 102 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
85 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty); 103 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty);
104 string friendsService = serverConfig.GetString("FriendsService", String.Empty);
105 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
106 string userAccountService = serverConfig.GetString("UserAccountService", String.Empty);
86 107
87 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false); 108 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false);
88 109
@@ -94,6 +115,9 @@ namespace OpenSim.Services.HypergridService
94 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); 115 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
95 m_GatekeeperConnector = new GatekeeperServiceConnector(); 116 m_GatekeeperConnector = new GatekeeperServiceConnector();
96 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args); 117 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
118 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
119 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
120 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
97 121
98 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 122 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
99 if (m_GridName == string.Empty) 123 if (m_GridName == string.Empty)
@@ -156,11 +180,16 @@ namespace OpenSim.Services.HypergridService
156 string gridName = gatekeeper.ServerURI; 180 string gridName = gatekeeper.ServerURI;
157 181
158 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 182 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
159 183
160 if (m_GridName == gridName) 184 if (m_GridName == gridName)
161 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); 185 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
162 else 186 else
187 {
163 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason); 188 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason);
189 if (success)
190 // Report them as nowhere
191 m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero);
192 }
164 193
165 if (!success) 194 if (!success)
166 { 195 {
@@ -179,6 +208,7 @@ namespace OpenSim.Services.HypergridService
179 if (clientIP != null) 208 if (clientIP != null)
180 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString(); 209 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
181 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP; 210 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
211
182 return true; 212 return true;
183 } 213 }
184 214
@@ -291,6 +321,194 @@ namespace OpenSim.Services.HypergridService
291 return false; 321 return false;
292 } 322 }
293 323
324 public void StatusNotification(List<string> friends, UUID foreignUserID, bool online)
325 {
326 if (m_FriendsService == null || m_PresenceService == null)
327 {
328 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing");
329 return;
330 }
331
332 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count);
333
334 // First, let's double check that the reported friends are, indeed, friends of that user
335 // And let's check that the secret matches
336 List<string> usersToBeNotified = new List<string>();
337 foreach (string uui in friends)
338 {
339 UUID localUserID;
340 string secret = string.Empty, tmp = string.Empty;
341 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
342 {
343 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
344 foreach (FriendInfo finfo in friendInfos)
345 {
346 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret))
347 {
348 // great!
349 usersToBeNotified.Add(localUserID.ToString());
350 }
351 }
352 }
353 }
354
355 // Now, let's send the notifications
356 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count);
357
358 // First, let's send notifications to local users who are online in the home grid
359 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
360 if (friendSessions != null && friendSessions.Length > 0)
361 {
362 PresenceInfo friendSession = null;
363 foreach (PresenceInfo pinfo in friendSessions)
364 if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents
365 {
366 friendSession = pinfo;
367 break;
368 }
369
370 if (friendSession != null)
371 {
372 ForwardStatusNotificationToSim(friendSession.RegionID, friendSession.UserID, foreignUserID, online);
373 usersToBeNotified.Remove(friendSession.UserID.ToString());
374 }
375 }
376
377 // Lastly, let's notify the rest who may be online somewhere else
378 foreach (string user in usersToBeNotified)
379 {
380 UUID id = new UUID(user);
381 if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
382 {
383 string url = m_TravelingAgents[id].GridExternalName;
384 // forward
385 m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
386 }
387 }
388 }
389
390 protected void ForwardStatusNotificationToSim(UUID regionID, string user, UUID foreignUserID, bool online)
391 {
392 UUID userID;
393 if (UUID.TryParse(user, out userID))
394 {
395 if (m_FriendsLocalSimConnector != null)
396 {
397 m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
398 m_FriendsLocalSimConnector.StatusNotify(userID, foreignUserID, online);
399 }
400 else
401 {
402 GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
403 if (region != null)
404 {
405 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, user, foreignUserID, (online ? "online" : "offline"));
406 m_FriendsSimConnector.StatusNotify(region, userID, foreignUserID, online);
407 }
408 }
409 }
410 }
411
412 public List<UUID> GetOnlineFriends(UUID foreignUserID, List<string> friends)
413 {
414 List<UUID> online = new List<UUID>();
415
416 if (m_FriendsService == null || m_PresenceService == null)
417 {
418 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing");
419 return online;
420 }
421
422 m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count);
423
424 // First, let's double check that the reported friends are, indeed, friends of that user
425 // And let's check that the secret matches and the rights
426 List<string> usersToBeNotified = new List<string>();
427 foreach (string uui in friends)
428 {
429 UUID localUserID;
430 string secret = string.Empty, tmp = string.Empty;
431 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
432 {
433 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
434 foreach (FriendInfo finfo in friendInfos)
435 {
436 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) &&
437 (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1))
438 {
439 // great!
440 usersToBeNotified.Add(localUserID.ToString());
441 }
442 }
443 }
444 }
445
446 // Now, let's find out their status
447 m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count);
448
449 // First, let's send notifications to local users who are online in the home grid
450 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
451 if (friendSessions != null && friendSessions.Length > 0)
452 {
453 foreach (PresenceInfo pi in friendSessions)
454 {
455 UUID presenceID;
456 if (UUID.TryParse(pi.UserID, out presenceID))
457 online.Add(presenceID);
458 }
459 }
460
461 return online;
462 }
463
464 public Dictionary<string, object> GetServerURLs(UUID userID)
465 {
466 if (m_UserAccountService == null)
467 {
468 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing");
469 return new Dictionary<string, object>();
470 }
471 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID);
472 if (account != null)
473 return account.ServiceURLs;
474
475 return new Dictionary<string, object>();
476 }
477
478 public string LocateUser(UUID userID)
479 {
480 foreach (TravelingAgentInfo t in m_TravelingAgents.Values)
481 {
482 if (t.UserID == userID)
483 return t.GridExternalName;
484 }
485
486 return string.Empty;
487 }
488
489 public string GetUUI(UUID userID, UUID targetUserID)
490 {
491 // Let's see if it's a local user
492 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID);
493 if (account != null)
494 return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ;
495
496 // Let's try the list of friends
497 FriendInfo[] friends = m_FriendsService.GetFriends(userID);
498 if (friends != null && friends.Length > 0)
499 {
500 foreach (FriendInfo f in friends)
501 if (f.Friend.StartsWith(targetUserID.ToString()))
502 {
503 // Let's remove the secret
504 UUID id; string tmp = string.Empty, secret = string.Empty;
505 if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret))
506 return f.Friend.Replace(secret, "0");
507 }
508 }
509
510 return string.Empty;
511 }
294 } 512 }
295 513
296 class TravelingAgentInfo 514 class TravelingAgentInfo
diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs
index 0ddd5e5..1664f3b 100644
--- a/OpenSim/Services/Interfaces/IFriendsService.cs
+++ b/OpenSim/Services/Interfaces/IFriendsService.cs
@@ -74,7 +74,9 @@ namespace OpenSim.Services.Interfaces
74 public interface IFriendsService 74 public interface IFriendsService
75 { 75 {
76 FriendInfo[] GetFriends(UUID PrincipalID); 76 FriendInfo[] GetFriends(UUID PrincipalID);
77 bool StoreFriend(UUID PrincipalID, string Friend, int flags); 77 FriendInfo[] GetFriends(string PrincipalID);
78 bool StoreFriend(string PrincipalID, string Friend, int flags);
78 bool Delete(UUID PrincipalID, string Friend); 79 bool Delete(UUID PrincipalID, string Friend);
80 bool Delete(string PrincipalID, string Friend);
79 } 81 }
80} 82}
diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs
index aac8293..753c205 100644
--- a/OpenSim/Services/Interfaces/IGatekeeperService.cs
+++ b/OpenSim/Services/Interfaces/IHypergridServices.cs
@@ -54,9 +54,33 @@ namespace OpenSim.Services.Interfaces
54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); 54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
55 void LogoutAgent(UUID userID, UUID sessionID); 55 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); 56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 Dictionary<string, object> GetServerURLs(UUID userID);
58
59 string LocateUser(UUID userID);
60 // Tries to get the universal user identifier for the targetUserId
61 // on behalf of the userID
62 string GetUUI(UUID userID, UUID targetUserID);
63
64 void StatusNotification(List<string> friends, UUID userID, bool online);
65 List<UUID> GetOnlineFriends(UUID userID, List<string> friends);
57 66
58 bool AgentIsComingHome(UUID sessionID, string thisGridExternalName); 67 bool AgentIsComingHome(UUID sessionID, string thisGridExternalName);
59 bool VerifyAgent(UUID sessionID, string token); 68 bool VerifyAgent(UUID sessionID, string token);
60 bool VerifyClient(UUID sessionID, string reportedIP); 69 bool VerifyClient(UUID sessionID, string reportedIP);
61 } 70 }
71
72 public interface IInstantMessage
73 {
74 bool IncomingInstantMessage(GridInstantMessage im);
75 bool OutgoingInstantMessage(GridInstantMessage im, string url);
76 }
77 public interface IFriendsSimConnector
78 {
79 bool StatusNotify(UUID userID, UUID friendID, bool online);
80 }
81
82 public interface IInstantMessageSimConnector
83 {
84 bool SendInstantMessage(GridInstantMessage im);
85 }
62} 86}
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
index ddc8855..f68c078 100644
--- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -621,7 +621,19 @@ namespace OpenSim.Services.LLLoginService
621 if (finfo.TheirFlags == -1) 621 if (finfo.TheirFlags == -1)
622 continue; 622 continue;
623 LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend); 623 LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend);
624 buddyitem.BuddyID = finfo.Friend; 624 // finfo.Friend may not be a simple uuid
625 UUID friendID = UUID.Zero;
626 if (UUID.TryParse(finfo.Friend, out friendID))
627 buddyitem.BuddyID = finfo.Friend;
628 else
629 {
630 string tmp;
631 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
632 buddyitem.BuddyID = friendID.ToString();
633 else
634 // junk entry
635 continue;
636 }
625 buddyitem.BuddyRightsHave = (int)finfo.TheirFlags; 637 buddyitem.BuddyRightsHave = (int)finfo.TheirFlags;
626 buddyitem.BuddyRightsGiven = (int)finfo.MyFlags; 638 buddyitem.BuddyRightsGiven = (int)finfo.MyFlags;
627 buddylistreturn.AddNewBuddy(buddyitem); 639 buddylistreturn.AddNewBuddy(buddyitem);
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 2ca2d15..a5a728b 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -804,16 +804,13 @@ namespace OpenSim.Services.LLLoginService
804 // Old style: get the service keys from the DB 804 // Old style: get the service keys from the DB
805 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs) 805 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
806 { 806 {
807 if (kvp.Value == null || (kvp.Value != null && kvp.Value.ToString() == string.Empty)) 807 if (kvp.Value != null)
808 {
809 aCircuit.ServiceURLs[kvp.Key] = m_LoginServerConfig.GetString(kvp.Key, string.Empty);
810 }
811 else
812 { 808 {
813 aCircuit.ServiceURLs[kvp.Key] = kvp.Value; 809 aCircuit.ServiceURLs[kvp.Key] = kvp.Value;
810
811 if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/"))
812 aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/";
814 } 813 }
815 if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/"))
816 aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/";
817 } 814 }
818 815
819 // New style: service keys start with SRV_; override the previous 816 // New style: service keys start with SRV_; override the previous
@@ -821,16 +818,29 @@ namespace OpenSim.Services.LLLoginService
821 818
822 if (keys.Length > 0) 819 if (keys.Length > 0)
823 { 820 {
821 bool newUrls = false;
824 IEnumerable<string> serviceKeys = keys.Where(value => value.StartsWith("SRV_")); 822 IEnumerable<string> serviceKeys = keys.Where(value => value.StartsWith("SRV_"));
825 foreach (string serviceKey in serviceKeys) 823 foreach (string serviceKey in serviceKeys)
826 { 824 {
827 string keyName = serviceKey.Replace("SRV_", ""); 825 string keyName = serviceKey.Replace("SRV_", "");
828 aCircuit.ServiceURLs[keyName] = m_LoginServerConfig.GetString(serviceKey, string.Empty); 826 string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty);
829 if (!aCircuit.ServiceURLs[keyName].ToString().EndsWith("/")) 827 if (!keyValue.EndsWith("/"))
830 aCircuit.ServiceURLs[keyName] = aCircuit.ServiceURLs[keyName] + "/"; 828 keyValue = keyValue + "/";
829
830 if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue))
831 {
832 account.ServiceURLs[keyName] = keyValue;
833 newUrls = true;
834 }
835 aCircuit.ServiceURLs[keyName] = keyValue;
831 836
832 m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]); 837 m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]);
833 } 838 }
839
840 // The grid operator decided to override the defaults in the
841 // [LoginService] configuration. Let's store the correct ones.
842 if (newUrls)
843 m_UserAccountService.StoreUserAccount(account);
834 } 844 }
835 845
836 } 846 }