aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Data/IFriendsData.cs4
-rw-r--r--OpenSim/Data/MSSQL/MSSQLFriendsData.cs11
-rw-r--r--OpenSim/Data/MySQL/MySQLFriendsData.cs14
-rw-r--r--OpenSim/Data/MySQL/Resources/FriendsStore.migrations6
-rw-r--r--OpenSim/Data/Null/NullFriendsData.cs18
-rw-r--r--OpenSim/Data/SQLite/SQLiteFriendsData.cs12
-rw-r--r--OpenSim/Framework/AgentCircuitData.cs1
-rw-r--r--OpenSim/Framework/AssetBase.cs6
-rw-r--r--OpenSim/Framework/Util.cs63
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs353
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs599
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs342
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs14
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs38
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs41
-rw-r--r--OpenSim/Region/Framework/Interfaces/IFriendsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserManagement.cs2
-rw-r--r--OpenSim/Server/Base/ServerUtils.cs4
-rw-r--r--OpenSim/Server/Handlers/Friends/FriendServerConnector.cs6
-rw-r--r--OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs48
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs71
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs323
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs280
-rw-r--r--OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs205
-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
38 files changed, 3635 insertions, 179 deletions
diff --git a/OpenSim/Data/IFriendsData.cs b/OpenSim/Data/IFriendsData.cs
index 1f1a031..3fdf87b 100644
--- a/OpenSim/Data/IFriendsData.cs
+++ b/OpenSim/Data/IFriendsData.cs
@@ -34,7 +34,7 @@ namespace OpenSim.Data
34{ 34{
35 public class FriendsData 35 public class FriendsData
36 { 36 {
37 public UUID PrincipalID; 37 public string PrincipalID;
38 public string Friend; 38 public string Friend;
39 public Dictionary<string, string> Data; 39 public Dictionary<string, string> Data;
40 } 40 }
@@ -46,6 +46,8 @@ namespace OpenSim.Data
46 { 46 {
47 bool Store(FriendsData data); 47 bool Store(FriendsData data);
48 bool Delete(UUID ownerID, string friend); 48 bool Delete(UUID ownerID, string friend);
49 bool Delete(string ownerID, string friend);
49 FriendsData[] GetFriends(UUID principalID); 50 FriendsData[] GetFriends(UUID principalID);
51 FriendsData[] GetFriends(string principalID);
50 } 52 }
51} 53}
diff --git a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
index af4fd9b..0b178f1 100644
--- a/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLFriendsData.cs
@@ -52,6 +52,11 @@ namespace OpenSim.Data.MSSQL
52 52
53 public bool Delete(UUID principalID, string friend) 53 public bool Delete(UUID principalID, string friend)
54 { 54 {
55 return Delete(principalID.ToString(), friend);
56 }
57
58 public bool Delete(string principalID, string friend)
59 {
55 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 60 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
56 using (SqlCommand cmd = new SqlCommand()) 61 using (SqlCommand cmd = new SqlCommand())
57 { 62 {
@@ -68,6 +73,11 @@ namespace OpenSim.Data.MSSQL
68 73
69 public FriendsData[] GetFriends(UUID principalID) 74 public FriendsData[] GetFriends(UUID principalID)
70 { 75 {
76 return GetFriends(principalID.ToString());
77 }
78
79 public FriendsData[] GetFriends(string principalID)
80 {
71 using (SqlConnection conn = new SqlConnection(m_ConnectionString)) 81 using (SqlConnection conn = new SqlConnection(m_ConnectionString))
72 using (SqlCommand cmd = new SqlCommand()) 82 using (SqlCommand cmd = new SqlCommand())
73 { 83 {
@@ -79,5 +89,6 @@ namespace OpenSim.Data.MSSQL
79 return DoQuery(cmd); 89 return DoQuery(cmd);
80 } 90 }
81 } 91 }
92
82 } 93 }
83} 94}
diff --git a/OpenSim/Data/MySQL/MySQLFriendsData.cs b/OpenSim/Data/MySQL/MySQLFriendsData.cs
index 663fad6..130ba5e 100644
--- a/OpenSim/Data/MySQL/MySQLFriendsData.cs
+++ b/OpenSim/Data/MySQL/MySQLFriendsData.cs
@@ -44,6 +44,11 @@ namespace OpenSim.Data.MySQL
44 44
45 public bool Delete(UUID principalID, string friend) 45 public bool Delete(UUID principalID, string friend)
46 { 46 {
47 return Delete(principalID.ToString(), friend);
48 }
49
50 public bool Delete(string principalID, string friend)
51 {
47 MySqlCommand cmd = new MySqlCommand(); 52 MySqlCommand cmd = new MySqlCommand();
48 53
49 cmd.CommandText = String.Format("delete from {0} where PrincipalID = ?PrincipalID and Friend = ?Friend", m_Realm); 54 cmd.CommandText = String.Format("delete from {0} where PrincipalID = ?PrincipalID and Friend = ?Friend", m_Realm);
@@ -64,5 +69,14 @@ namespace OpenSim.Data.MySQL
64 69
65 return DoQuery(cmd); 70 return DoQuery(cmd);
66 } 71 }
72
73 public FriendsData[] GetFriends(string principalID)
74 {
75 MySqlCommand cmd = new MySqlCommand();
76
77 cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID LIKE ?PrincipalID", m_Realm);
78 cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString() + '%');
79 return DoQuery(cmd);
80 }
67 } 81 }
68} 82}
diff --git a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
index ce713bd..35e5e93 100644
--- a/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/FriendsStore.migrations
@@ -21,5 +21,11 @@ INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userf
21 21
22COMMIT; 22COMMIT;
23 23
24:VERSION 3 # -------------------------
24 25
26BEGIN;
27
28ALTER TABLE `Friends` MODIFY COLUMN PrincipalID varchar(255) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
29
30COMMIT;
25 31
diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs
index e7f7fd3..d90788a 100644
--- a/OpenSim/Data/Null/NullFriendsData.cs
+++ b/OpenSim/Data/Null/NullFriendsData.cs
@@ -42,6 +42,11 @@ namespace OpenSim.Data.Null
42 { 42 {
43 } 43 }
44 44
45 public FriendsData[] GetFriends(UUID principalID)
46 {
47 return GetFriends(principalID.ToString());
48 }
49
45 /// <summary> 50 /// <summary>
46 /// Tries to implement the Get [] semantics, but it cuts corners. 51 /// Tries to implement the Get [] semantics, but it cuts corners.
47 /// Specifically, it gets all friendships even if they weren't accepted yet. 52 /// Specifically, it gets all friendships even if they weren't accepted yet.
@@ -49,11 +54,11 @@ namespace OpenSim.Data.Null
49 /// <param name="fields"></param> 54 /// <param name="fields"></param>
50 /// <param name="values"></param> 55 /// <param name="values"></param>
51 /// <returns></returns> 56 /// <returns></returns>
52 public FriendsData[] GetFriends(UUID userID) 57 public FriendsData[] GetFriends(string userID)
53 { 58 {
54 List<FriendsData> lst = m_Data.FindAll(delegate (FriendsData fdata) 59 List<FriendsData> lst = m_Data.FindAll(delegate (FriendsData fdata)
55 { 60 {
56 return fdata.PrincipalID == userID; 61 return fdata.PrincipalID == userID.ToString();
57 }); 62 });
58 63
59 if (lst != null) 64 if (lst != null)
@@ -72,9 +77,14 @@ namespace OpenSim.Data.Null
72 return true; 77 return true;
73 } 78 }
74 79
75 public bool Delete(UUID userID, string friendID) 80 public bool Delete(UUID principalID, string friend)
81 {
82 return Delete(principalID.ToString(), friend);
83 }
84
85 public bool Delete(string userID, string friendID)
76 { 86 {
77 List<FriendsData> lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID; }); 87 List<FriendsData> lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); });
78 if (lst != null) 88 if (lst != null)
79 { 89 {
80 FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); 90 FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; });
diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs
index 4bfd228..b14c348 100644
--- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs
+++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs
@@ -46,7 +46,12 @@ namespace OpenSim.Data.SQLite
46 { 46 {
47 } 47 }
48 48
49 public FriendsData[] GetFriends(UUID userID) 49 public FriendsData[] GetFriends(UUID principalID)
50 {
51 return GetFriends(principalID.ToString());
52 }
53
54 public FriendsData[] GetFriends(string userID)
50 { 55 {
51 SqliteCommand cmd = new SqliteCommand(); 56 SqliteCommand cmd = new SqliteCommand();
52 57
@@ -59,6 +64,11 @@ namespace OpenSim.Data.SQLite
59 64
60 public bool Delete(UUID principalID, string friend) 65 public bool Delete(UUID principalID, string friend)
61 { 66 {
67 return Delete(principalID.ToString(), friend);
68 }
69
70 public bool Delete(string principalID, string friend)
71 {
62 SqliteCommand cmd = new SqliteCommand(); 72 SqliteCommand cmd = new SqliteCommand();
63 73
64 cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); 74 cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm);
diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs
index dbd47d3..125910e 100644
--- a/OpenSim/Framework/AgentCircuitData.cs
+++ b/OpenSim/Framework/AgentCircuitData.cs
@@ -345,6 +345,7 @@ namespace OpenSim.Framework
345 } 345 }
346 } 346 }
347 } 347 }
348
348 } 349 }
349 350
350 351
diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs
index 53d28be..5f68cda 100644
--- a/OpenSim/Framework/AssetBase.cs
+++ b/OpenSim/Framework/AssetBase.cs
@@ -215,6 +215,12 @@ namespace OpenSim.Framework
215 set { m_metadata.Temporary = value; } 215 set { m_metadata.Temporary = value; }
216 } 216 }
217 217
218 public string CreatorID
219 {
220 get { return m_metadata.CreatorID; }
221 set { m_metadata.CreatorID = value; }
222 }
223
218 public AssetFlags Flags 224 public AssetFlags Flags
219 { 225 {
220 get { return m_metadata.Flags; } 226 get { return m_metadata.Flags; }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index aaa2724..e5ff27a 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -1694,5 +1694,68 @@ namespace OpenSim.Framework
1694 return (T)Enum.Parse(typeof(T), value); ; 1694 return (T)Enum.Parse(typeof(T), value); ;
1695 } 1695 }
1696 #endregion 1696 #endregion
1697
1698 #region Universal User Identifiers
1699 /// <summary>
1700 /// </summary>
1701 /// <param name="value">uuid[;endpoint[;name]]</param>
1702 /// <param name="uuid"></param>
1703 /// <param name="url"></param>
1704 /// <param name="firstname"></param>
1705 /// <param name="lastname"></param>
1706 public static bool ParseUniversalUserIdentifier(string value, out UUID uuid, out string url, out string firstname, out string lastname, out string secret)
1707 {
1708 uuid = UUID.Zero; url = string.Empty; firstname = "Unknown"; lastname = "User"; secret = string.Empty;
1709
1710 string[] parts = value.Split(';');
1711 if (parts.Length >= 1)
1712 if (!UUID.TryParse(parts[0], out uuid))
1713 return false;
1714
1715 if (parts.Length >= 2)
1716 url = parts[1];
1717
1718 if (parts.Length >= 3)
1719 {
1720 string[] name = parts[2].Split();
1721 if (name.Length == 2)
1722 {
1723 firstname = name[0];
1724 lastname = name[1];
1725 }
1726 }
1727 if (parts.Length >= 4)
1728 secret = parts[3];
1729
1730 return true;
1731 }
1732
1733 /// <summary>
1734 ///
1735 /// </summary>
1736 /// <param name="acircuit"></param>
1737 /// <returns>uuid[;endpoint[;name]]</returns>
1738 public static string ProduceUserUniversalIdentifier(AgentCircuitData acircuit)
1739 {
1740 if (acircuit.ServiceURLs.ContainsKey("HomeURI"))
1741 {
1742 string agentsURI = acircuit.ServiceURLs["HomeURI"].ToString();
1743 if (!agentsURI.EndsWith("/"))
1744 agentsURI += "/";
1745
1746 // This is ugly, but there's no other way, given that the name is changed
1747 // in the agent circuit data for foreigners
1748 if (acircuit.lastname.Contains("@"))
1749 {
1750 string[] parts = acircuit.firstname.Split(new char[] { '.' });
1751 if (parts.Length == 2)
1752 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + parts[0] + " " + parts[1];
1753 }
1754 return acircuit.AgentID.ToString() + ";" + agentsURI + ";" + acircuit.firstname + " " + acircuit.lastname;
1755 }
1756 else
1757 return acircuit.AgentID.ToString();
1758 }
1759 #endregion
1697 } 1760 }
1698} 1761}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index 5baf078..f82716d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -49,6 +49,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
49{ 49{
50 public class FriendsModule : ISharedRegionModule, IFriendsModule 50 public class FriendsModule : ISharedRegionModule, IFriendsModule
51 { 51 {
52 protected bool m_Enabled = false;
53
52 protected class UserFriendData 54 protected class UserFriendData
53 { 55 {
54 public UUID PrincipalID; 56 public UUID PrincipalID;
@@ -67,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
67 } 69 }
68 } 70 }
69 71
70 private static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; 72 protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0];
71 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
72 74
73 protected List<Scene> m_Scenes = new List<Scene>(); 75 protected List<Scene> m_Scenes = new List<Scene>();
@@ -130,8 +132,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
130 } 132 }
131 } 133 }
132 134
135 #region ISharedRegionModule
133 public void Initialise(IConfigSource config) 136 public void Initialise(IConfigSource config)
134 { 137 {
138 IConfig moduleConfig = config.Configs["Modules"];
139 if (moduleConfig != null)
140 {
141 string name = moduleConfig.GetString("FriendsModule", "FriendsModule");
142 if (name == Name)
143 {
144 InitModule(config);
145
146 m_Enabled = true;
147 m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name);
148 }
149 }
150 }
151
152 protected void InitModule(IConfigSource config)
153 {
135 IConfig friendsConfig = config.Configs["Friends"]; 154 IConfig friendsConfig = config.Configs["Friends"];
136 if (friendsConfig != null) 155 if (friendsConfig != null)
137 { 156 {
@@ -153,7 +172,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
153 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue"); 172 m_log.Error("[FRIENDS]: No Connector defined in section Friends, or failed to load, cannot continue");
154 throw new Exception("Connector load error"); 173 throw new Exception("Connector load error");
155 } 174 }
156
157 } 175 }
158 176
159 public void PostInitialise() 177 public void PostInitialise()
@@ -164,8 +182,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
164 { 182 {
165 } 183 }
166 184
167 public void AddRegion(Scene scene) 185 public virtual void AddRegion(Scene scene)
168 { 186 {
187 if (!m_Enabled)
188 return;
189 m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name);
190
169 m_Scenes.Add(scene); 191 m_Scenes.Add(scene);
170 scene.RegisterModuleInterface<IFriendsModule>(this); 192 scene.RegisterModuleInterface<IFriendsModule>(this);
171 193
@@ -181,10 +203,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
181 203
182 public void RemoveRegion(Scene scene) 204 public void RemoveRegion(Scene scene)
183 { 205 {
206 if (!m_Enabled)
207 return;
208
184 m_Scenes.Remove(scene); 209 m_Scenes.Remove(scene);
185 } 210 }
186 211
187 public string Name 212 public virtual string Name
188 { 213 {
189 get { return "FriendsModule"; } 214 get { return "FriendsModule"; }
190 } 215 }
@@ -194,13 +219,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
194 get { return null; } 219 get { return null; }
195 } 220 }
196 221
197 public uint GetFriendPerms(UUID principalID, UUID friendID) 222 #endregion
223
224 public virtual uint GetFriendPerms(UUID principalID, UUID friendID)
198 { 225 {
199 FriendInfo[] friends = GetFriends(principalID); 226 FriendInfo[] friends = GetFriends(principalID);
200 foreach (FriendInfo fi in friends) 227 FriendInfo finfo = GetFriend(friends, friendID);
228 if (finfo != null)
201 { 229 {
202 if (fi.Friend == friendID.ToString()) 230 return (uint)finfo.TheirFlags;
203 return (uint)fi.TheirFlags;
204 } 231 }
205 232
206 return 0; 233 return 0;
@@ -214,30 +241,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
214 client.OnTerminateFriendship += OnTerminateFriendship; 241 client.OnTerminateFriendship += OnTerminateFriendship;
215 client.OnGrantUserRights += OnGrantUserRights; 242 client.OnGrantUserRights += OnGrantUserRights;
216 243
217 // Asynchronously fetch the friends list or increment the refcount for the existing 244 Util.FireAndForget(delegate { FetchFriendslist(client); });
218 // friends list 245 }
219 Util.FireAndForget( 246
220 delegate(object o) 247 /// Fetch the friends list or increment the refcount for the existing
248 /// friends list
249 /// Returns true if the list was fetched, false if it wasn't
250 protected virtual bool FetchFriendslist(IClientAPI client)
251 {
252 UUID agentID = client.AgentId;
253 lock (m_Friends)
254 {
255 UserFriendData friendsData;
256 if (m_Friends.TryGetValue(agentID, out friendsData))
221 { 257 {
222 lock (m_Friends) 258 friendsData.Refcount++;
223 { 259 return false;
224 UserFriendData friendsData; 260 }
225 if (m_Friends.TryGetValue(client.AgentId, out friendsData)) 261 else
226 { 262 {
227 friendsData.Refcount++; 263 friendsData = new UserFriendData();
228 } 264 friendsData.PrincipalID = agentID;
229 else 265 friendsData.Friends = GetFriendsFromService(client);
230 { 266 friendsData.Refcount = 1;
231 friendsData = new UserFriendData();
232 friendsData.PrincipalID = client.AgentId;
233 friendsData.Friends = FriendsService.GetFriends(client.AgentId);
234 friendsData.Refcount = 1;
235 267
236 m_Friends[client.AgentId] = friendsData; 268 m_Friends[agentID] = friendsData;
237 } 269 return true;
238 }
239 } 270 }
240 ); 271 }
241 } 272 }
242 273
243 private void OnClientClosed(UUID agentID, Scene scene) 274 private void OnClientClosed(UUID agentID, Scene scene)
@@ -263,14 +294,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
263 294
264 private void OnMakeRootAgent(ScenePresence sp) 295 private void OnMakeRootAgent(ScenePresence sp)
265 { 296 {
266 UUID agentID = sp.ControllingClient.AgentId; 297 RefetchFriends(sp.ControllingClient);
267 UpdateFriendsCache(agentID);
268 } 298 }
269 299
270 private void OnClientLogin(IClientAPI client) 300 private void OnClientLogin(IClientAPI client)
271 { 301 {
272 UUID agentID = client.AgentId; 302 UUID agentID = client.AgentId;
273 303
304 //m_log.DebugFormat("[XXX]: OnClientLogin!");
274 // Inform the friends that this user is online 305 // Inform the friends that this user is online
275 StatusChange(agentID, true); 306 StatusChange(agentID, true);
276 307
@@ -279,7 +310,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
279 m_NeedsListOfFriends.Add(agentID); 310 m_NeedsListOfFriends.Add(agentID);
280 } 311 }
281 312
282 public void SendFriendsOnlineIfNeeded(IClientAPI client) 313 public virtual bool SendFriendsOnlineIfNeeded(IClientAPI client)
283 { 314 {
284 UUID agentID = client.AgentId; 315 UUID agentID = client.AgentId;
285 316
@@ -287,7 +318,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
287 lock (m_NeedsListOfFriends) 318 lock (m_NeedsListOfFriends)
288 { 319 {
289 if (!m_NeedsListOfFriends.Remove(agentID)) 320 if (!m_NeedsListOfFriends.Remove(agentID))
290 return; 321 return false;
291 } 322 }
292 323
293 // Send the friends online 324 // Send the friends online
@@ -313,10 +344,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
313 foreach (string fid in outstanding) 344 foreach (string fid in outstanding)
314 { 345 {
315 UUID fromAgentID; 346 UUID fromAgentID;
316 if (!UUID.TryParse(fid, out fromAgentID)) 347 string firstname = "Unknown", lastname = "User";
348 if (!GetAgentInfo(client.Scene.RegionInfo.ScopeID, fid, out fromAgentID, out firstname, out lastname))
349 {
350 m_log.DebugFormat("[FRIENDS MODULE]: skipping malformed friend {0}", fid);
317 continue; 351 continue;
318 352 }
319 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID);
320 353
321 PresenceInfo presence = null; 354 PresenceInfo presence = null;
322 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); 355 PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid });
@@ -326,13 +359,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
326 im.offline = 0; 359 im.offline = 0;
327 360
328 im.fromAgentID = fromAgentID.Guid; 361 im.fromAgentID = fromAgentID.Guid;
329 im.fromAgentName = account.FirstName + " " + account.LastName; 362 im.fromAgentName = firstname + " " + lastname;
330 im.offline = (byte)((presence == null) ? 1 : 0); 363 im.offline = (byte)((presence == null) ? 1 : 0);
331 im.imSessionID = im.fromAgentID; 364 im.imSessionID = im.fromAgentID;
365 im.message = FriendshipMessage(fid);
332 366
333 // Finally 367 // Finally
334 LocalFriendshipOffered(agentID, im); 368 LocalFriendshipOffered(agentID, im);
335 } 369 }
370
371 return true;
372 }
373
374 protected virtual string FriendshipMessage(string friendID)
375 {
376 return "Will you be my friend?";
377 }
378
379 protected virtual bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
380 {
381 first = "Unknown"; last = "User";
382 if (!UUID.TryParse(fid, out agentID))
383 return false;
384
385 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(scopeID, agentID);
386 if (account != null)
387 {
388 first = account.FirstName;
389 last = account.LastName;
390 }
391
392 return true;
336 } 393 }
337 394
338 List<UUID> GetOnlineFriends(UUID userID) 395 List<UUID> GetOnlineFriends(UUID userID)
@@ -348,19 +405,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
348 } 405 }
349 406
350 if (friendList.Count > 0) 407 if (friendList.Count > 0)
351 { 408 GetOnlineFriends(userID, friendList, online);
352 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
353 foreach (PresenceInfo pi in presence)
354 {
355 UUID presenceID;
356 if (UUID.TryParse(pi.UserID, out presenceID))
357 online.Add(presenceID);
358 }
359 }
360 409
361 return online; 410 return online;
362 } 411 }
363 412
413 protected virtual void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
414 {
415 PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray());
416 foreach (PresenceInfo pi in presence)
417 {
418 UUID presenceID;
419 if (UUID.TryParse(pi.UserID, out presenceID))
420 online.Add(presenceID);
421 }
422 }
423
364 /// <summary> 424 /// <summary>
365 /// Find the client for a ID 425 /// Find the client for a ID
366 /// </summary> 426 /// </summary>
@@ -415,51 +475,51 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
415 Util.FireAndForget( 475 Util.FireAndForget(
416 delegate 476 delegate
417 { 477 {
418 foreach (FriendInfo fi in friendList) 478 m_log.DebugFormat("[FRIENDS MODULE]: Notifying {0} friends", friendList.Count);
419 { 479 // Notify about this user status
420 //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); 480 StatusNotify(friendList, agentID, online);
421 // Notify about this user status
422 StatusNotify(fi, agentID, online);
423 }
424 } 481 }
425 ); 482 );
426 } 483 }
427 } 484 }
428 485
429 private void StatusNotify(FriendInfo friend, UUID userID, bool online) 486 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
430 { 487 {
431 UUID friendID; 488 foreach (FriendInfo friend in friendList)
432 if (UUID.TryParse(friend.Friend, out friendID))
433 { 489 {
434 // Try local 490 UUID friendID;
435 if (LocalStatusNotification(userID, friendID, online)) 491 if (UUID.TryParse(friend.Friend, out friendID))
436 return;
437
438 // The friend is not here [as root]. Let's forward.
439 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
440 if (friendSessions != null && friendSessions.Length > 0)
441 { 492 {
442 PresenceInfo friendSession = null; 493 // Try local
443 foreach (PresenceInfo pinfo in friendSessions) 494 if (LocalStatusNotification(userID, friendID, online))
444 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad 495 return;
445 {
446 friendSession = pinfo;
447 break;
448 }
449 496
450 if (friendSession != null) 497 // The friend is not here [as root]. Let's forward.
498 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
499 if (friendSessions != null && friendSessions.Length > 0)
451 { 500 {
452 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); 501 PresenceInfo friendSession = null;
453 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); 502 foreach (PresenceInfo pinfo in friendSessions)
454 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); 503 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
504 {
505 friendSession = pinfo;
506 break;
507 }
508
509 if (friendSession != null)
510 {
511 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
512 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
513 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
514 }
455 } 515 }
456 }
457 516
458 // Friend is not online. Ignore. 517 // Friend is not online. Ignore.
459 } 518 }
460 else 519 else
461 { 520 {
462 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 521 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
522 }
463 } 523 }
464 } 524 }
465 525
@@ -475,7 +535,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
475 535
476 // This user wants to be friends with the other user. 536 // This user wants to be friends with the other user.
477 // Let's add the relation backwards, in case the other is not online 537 // Let's add the relation backwards, in case the other is not online
478 FriendsService.StoreFriend(friendID, principalID.ToString(), 0); 538 StoreBackwards(friendID, principalID);
479 539
480 // Now let's ask the other user to be friends with this user 540 // Now let's ask the other user to be friends with this user
481 ForwardFriendshipOffer(principalID, friendID, im); 541 ForwardFriendshipOffer(principalID, friendID, im);
@@ -487,11 +547,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
487 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID) 547 // !!!!!!!! This is a hack so that we don't have to keep state (transactionID/imSessionID)
488 // We stick this agent's ID as imSession, so that it's directly available on the receiving end 548 // We stick this agent's ID as imSession, so that it's directly available on the receiving end
489 im.imSessionID = im.fromAgentID; 549 im.imSessionID = im.fromAgentID;
550 im.fromAgentName = GetFriendshipRequesterName(agentID);
490 551
491 // Try the local sim 552 // Try the local sim
492 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
493 im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
494
495 if (LocalFriendshipOffered(friendID, im)) 553 if (LocalFriendshipOffered(friendID, im))
496 return; 554 return;
497 555
@@ -509,15 +567,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
509 // If the prospective friend is not online, he'll get the message upon login. 567 // If the prospective friend is not online, he'll get the message upon login.
510 } 568 }
511 569
570 protected virtual string GetFriendshipRequesterName(UUID agentID)
571 {
572 UserAccount account = UserAccountService.GetUserAccount(UUID.Zero, agentID);
573 return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName;
574 }
575
512 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) 576 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders)
513 { 577 {
514 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); 578 m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID);
515 579
516 FriendsService.StoreFriend(agentID, friendID.ToString(), 1); 580 StoreFriendships(agentID, friendID);
517 FriendsService.StoreFriend(friendID, agentID.ToString(), 1);
518 581
519 // Update the local cache 582 // Update the local cache
520 UpdateFriendsCache(agentID); 583 RefetchFriends(client);
521 584
522 // 585 //
523 // Notify the friend 586 // Notify the friend
@@ -548,8 +611,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
548 { 611 {
549 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); 612 m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID);
550 613
551 FriendsService.Delete(agentID, friendID.ToString()); 614 DeleteFriendship(agentID, friendID);
552 FriendsService.Delete(friendID, agentID.ToString());
553 615
554 // 616 //
555 // Notify the friend 617 // Notify the friend
@@ -576,11 +638,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
576 638
577 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) 639 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID)
578 { 640 {
579 FriendsService.Delete(agentID, exfriendID.ToString()); 641 if (!DeleteFriendship(agentID, exfriendID))
580 FriendsService.Delete(exfriendID, agentID.ToString()); 642 client.SendAlertMessage("Unable to terminate friendship on this sim.");
581 643
582 // Update local cache 644 // Update local cache
583 UpdateFriendsCache(agentID); 645 RefetchFriends(client);
584 646
585 client.SendTerminateFriend(exfriendID); 647 client.SendTerminateFriend(exfriendID);
586 648
@@ -606,23 +668,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
606 668
607 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) 669 private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
608 { 670 {
671 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
672
609 FriendInfo[] friends = GetFriends(remoteClient.AgentId); 673 FriendInfo[] friends = GetFriends(remoteClient.AgentId);
610 if (friends.Length == 0) 674 if (friends.Length == 0)
675 {
611 return; 676 return;
677 }
612 678
613 m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target);
614 // Let's find the friend in this user's friend list 679 // Let's find the friend in this user's friend list
615 FriendInfo friend = null; 680 FriendInfo friend = GetFriend(friends, target);
616 foreach (FriendInfo fi in friends)
617 {
618 if (fi.Friend == target.ToString())
619 friend = fi;
620 }
621 681
622 if (friend != null) // Found it 682 if (friend != null) // Found it
623 { 683 {
624 // Store it on the DB 684 // Store it on the DB
625 FriendsService.StoreFriend(requester, target.ToString(), rights); 685 if (!StoreRights(requester, target, rights))
686 {
687 remoteClient.SendAlertMessage("Unable to grant rights.");
688 return;
689 }
626 690
627 // Store it in the local cache 691 // Store it in the local cache
628 int myFlags = friend.MyFlags; 692 int myFlags = friend.MyFlags;
@@ -652,6 +716,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
652 } 716 }
653 } 717 }
654 } 718 }
719 else
720 m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester);
721 }
722
723 protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
724 {
725 foreach (FriendInfo fi in friends)
726 {
727 if (fi.Friend == friendID.ToString())
728 return fi;
729 }
730 return null;
655 } 731 }
656 732
657 #region Local 733 #region Local
@@ -680,7 +756,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
680 friendClient.SendInstantMessage(im); 756 friendClient.SendInstantMessage(im);
681 757
682 // Update the local cache 758 // Update the local cache
683 UpdateFriendsCache(friendID); 759 RefetchFriends(friendClient);
684 760
685 // we're done 761 // we're done
686 return true; 762 return true;
@@ -713,7 +789,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
713 // the friend in this sim as root agent 789 // the friend in this sim as root agent
714 friendClient.SendTerminateFriend(exfriendID); 790 friendClient.SendTerminateFriend(exfriendID);
715 // update local cache 791 // update local cache
716 UpdateFriendsCache(exfriendID); 792 RefetchFriends(friendClient);
717 // we're done 793 // we're done
718 return true; 794 return true;
719 } 795 }
@@ -743,15 +819,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
743 } 819 }
744 820
745 // Update local cache 821 // Update local cache
746 lock (m_Friends) 822 UpdateLocalCache(userID, friendID, rights);
747 {
748 FriendInfo[] friends = GetFriends(friendID);
749 foreach (FriendInfo finfo in friends)
750 {
751 if (finfo.Friend == userID.ToString())
752 finfo.TheirFlags = rights;
753 }
754 }
755 823
756 return true; 824 return true;
757 } 825 }
@@ -780,7 +848,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
780 848
781 #endregion 849 #endregion
782 850
783 private FriendInfo[] GetFriends(UUID agentID) 851 #region Get / Set friends in several flavours
852 /// <summary>
853 /// Get friends from local cache only
854 /// </summary>
855 /// <param name="agentID"></param>
856 /// <returns></returns>
857 protected FriendInfo[] GetFriends(UUID agentID)
784 { 858 {
785 UserFriendData friendsData; 859 UserFriendData friendsData;
786 860
@@ -793,14 +867,63 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
793 return EMPTY_FRIENDS; 867 return EMPTY_FRIENDS;
794 } 868 }
795 869
796 private void UpdateFriendsCache(UUID agentID) 870 /// <summary>
871 /// Update loca cache only
872 /// </summary>
873 /// <param name="userID"></param>
874 /// <param name="friendID"></param>
875 /// <param name="rights"></param>
876 protected void UpdateLocalCache(UUID userID, UUID friendID, int rights)
877 {
878 // Update local cache
879 lock (m_Friends)
880 {
881 FriendInfo[] friends = GetFriends(friendID);
882 FriendInfo finfo = GetFriend(friends, userID);
883 finfo.TheirFlags = rights;
884 }
885 }
886
887 protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client)
888 {
889 return FriendsService.GetFriends(client.AgentId);
890 }
891
892 private void RefetchFriends(IClientAPI client)
797 { 893 {
894 UUID agentID = client.AgentId;
798 lock (m_Friends) 895 lock (m_Friends)
799 { 896 {
800 UserFriendData friendsData; 897 UserFriendData friendsData;
801 if (m_Friends.TryGetValue(agentID, out friendsData)) 898 if (m_Friends.TryGetValue(agentID, out friendsData))
802 friendsData.Friends = FriendsService.GetFriends(agentID); 899 friendsData.Friends = GetFriendsFromService(client);
803 } 900 }
804 } 901 }
902
903 protected virtual bool StoreRights(UUID agentID, UUID friendID, int rights)
904 {
905 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), rights);
906 return true;
907 }
908
909 protected virtual void StoreBackwards(UUID friendID, UUID agentID)
910 {
911 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
912 }
913
914 protected virtual void StoreFriendships(UUID agentID, UUID friendID)
915 {
916 FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1);
917 FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1);
918 }
919
920 protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID)
921 {
922 FriendsService.Delete(agentID, exfriendID.ToString());
923 FriendsService.Delete(exfriendID, agentID.ToString());
924 return true;
925 }
926
927 #endregion
805 } 928 }
806} 929}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
new file mode 100644
index 0000000..b0a7567
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs
@@ -0,0 +1,599 @@
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;
30using System.Collections.Generic;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using Mono.Addins;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.Connectors.Hypergrid;
42using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
43using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45
46namespace OpenSim.Region.CoreModules.Avatar.Friends
47{
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class HGFriendsModule : FriendsModule, ISharedRegionModule, IFriendsModule, IFriendsSimConnector
50 {
51 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
52
53 #region ISharedRegionModule
54 public override string Name
55 {
56 get { return "HGFriendsModule"; }
57 }
58
59 public override void AddRegion(Scene scene)
60 {
61 if (!m_Enabled)
62 return;
63
64 base.AddRegion(scene);
65 scene.RegisterModuleInterface<IFriendsSimConnector>(this);
66 }
67
68 #endregion
69
70 #region IFriendsSimConnector
71
72 /// <summary>
73 /// Notify the user that the friend's status changed
74 /// </summary>
75 /// <param name="userID">user to be notified</param>
76 /// <param name="friendID">friend whose status changed</param>
77 /// <param name="online">status</param>
78 /// <returns></returns>
79 public bool StatusNotify(UUID userID, UUID friendID, bool online)
80 {
81 return LocalStatusNotification(friendID, userID, online);
82 }
83
84 #endregion
85
86 protected override bool FetchFriendslist(IClientAPI client)
87 {
88 if (base.FetchFriendslist(client))
89 {
90 UUID agentID = client.AgentId;
91 // We need to preload the user management cache with the names
92 // of foreign friends, just like we do with SOPs' creators
93 foreach (FriendInfo finfo in m_Friends[agentID].Friends)
94 {
95 if (finfo.TheirFlags != -1)
96 {
97 UUID id;
98 if (!UUID.TryParse(finfo.Friend, out id))
99 {
100 string url = string.Empty, first = string.Empty, last = string.Empty, tmp = string.Empty;
101 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out id, out url, out first, out last, out tmp))
102 {
103 IUserManagement uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
104 uMan.AddUser(id, url + ";" + first + " " + last);
105 }
106 }
107 }
108 }
109 return true;
110 }
111 return false;
112 }
113
114 public override bool SendFriendsOnlineIfNeeded(IClientAPI client)
115 {
116 if (base.SendFriendsOnlineIfNeeded(client))
117 {
118 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId);
119 if (account == null) // foreign
120 {
121 FriendInfo[] friends = GetFriends(client.AgentId);
122 foreach (FriendInfo f in friends)
123 {
124 client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags);
125 }
126 }
127 }
128 return false;
129 }
130
131 protected override void GetOnlineFriends(UUID userID, List<string> friendList, /*collector*/ List<UUID> online)
132 {
133 // Let's single out the UUIs
134 List<string> localFriends = new List<string>();
135 List<string> foreignFriends = new List<string>();
136 string tmp = string.Empty;
137
138 foreach (string s in friendList)
139 {
140 UUID id;
141 if (UUID.TryParse(s, out id))
142 localFriends.Add(s);
143 else if (Util.ParseUniversalUserIdentifier(s, out id, out tmp, out tmp, out tmp, out tmp))
144 {
145 foreignFriends.Add(s);
146 // add it here too, who knows maybe the foreign friends happens to be on this grid
147 localFriends.Add(id.ToString());
148 }
149 }
150
151 // OK, see who's present on this grid
152 List<string> toBeRemoved = new List<string>();
153 PresenceInfo[] presence = PresenceService.GetAgents(localFriends.ToArray());
154 foreach (PresenceInfo pi in presence)
155 {
156 UUID presenceID;
157 if (UUID.TryParse(pi.UserID, out presenceID))
158 {
159 online.Add(presenceID);
160 foreach (string s in foreignFriends)
161 if (s.StartsWith(pi.UserID))
162 toBeRemoved.Add(s);
163 }
164 }
165
166 foreach (string s in toBeRemoved)
167 foreignFriends.Remove(s);
168
169 // OK, let's send this up the stack, and leave a closure here
170 // collecting online friends in other grids
171 Util.FireAndForget(delegate { CollectOnlineFriendsElsewhere(userID, foreignFriends); });
172
173 }
174
175 private void CollectOnlineFriendsElsewhere(UUID userID, List<string> foreignFriends)
176 {
177 // let's divide the friends on a per-domain basis
178 Dictionary<string, List<string>> friendsPerDomain = new Dictionary<string, List<string>>();
179 foreach (string friend in foreignFriends)
180 {
181 UUID friendID;
182 if (!UUID.TryParse(friend, out friendID))
183 {
184 // it's a foreign friend
185 string url = string.Empty, tmp = string.Empty;
186 if (Util.ParseUniversalUserIdentifier(friend, out friendID, out url, out tmp, out tmp, out tmp))
187 {
188 if (!friendsPerDomain.ContainsKey(url))
189 friendsPerDomain[url] = new List<string>();
190 friendsPerDomain[url].Add(friend);
191 }
192 }
193 }
194
195 // Now, call those worlds
196
197 foreach (KeyValuePair<string, List<string>> kvp in friendsPerDomain)
198 {
199 List<string> ids = new List<string>();
200 foreach (string f in kvp.Value)
201 ids.Add(f);
202 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
203 List<UUID> online = uConn.GetOnlineFriends(userID, ids);
204 // Finally send the notifications to the user
205 // this whole process may take a while, so let's check at every
206 // iteration that the user is still here
207 IClientAPI client = LocateClientObject(userID);
208 if (client != null)
209 client.SendAgentOnline(online.ToArray());
210 else
211 break;
212 }
213
214 }
215
216 protected override void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
217 {
218 // First, let's divide the friends on a per-domain basis
219 Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
220 foreach (FriendInfo friend in friendList)
221 {
222 UUID friendID;
223 if (UUID.TryParse(friend.Friend, out friendID))
224 {
225 if (!friendsPerDomain.ContainsKey("local"))
226 friendsPerDomain["local"] = new List<FriendInfo>();
227 friendsPerDomain["local"].Add(friend);
228 }
229 else
230 {
231 // it's a foreign friend
232 string url = string.Empty, tmp = string.Empty;
233 if (Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out url, out tmp, out tmp, out tmp))
234 {
235 // Let's try our luck in the local sim. Who knows, maybe it's here
236 if (LocalStatusNotification(userID, friendID, online))
237 continue;
238
239 if (!friendsPerDomain.ContainsKey(url))
240 friendsPerDomain[url] = new List<FriendInfo>();
241 friendsPerDomain[url].Add(friend);
242 }
243 }
244 }
245
246 // For the local friends, just call the base method
247 // Let's do this first of all
248 if (friendsPerDomain.ContainsKey("local"))
249 base.StatusNotify(friendsPerDomain["local"], userID, online);
250
251 foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
252 {
253 if (kvp.Key != "local")
254 {
255 // For the others, call the user agent service
256 List<string> ids = new List<string>();
257 foreach (FriendInfo f in kvp.Value)
258 ids.Add(f.Friend);
259 UserAgentServiceConnector uConn = new UserAgentServiceConnector(kvp.Key);
260 uConn.StatusNotification(ids, userID, online);
261 }
262 }
263 }
264
265 protected override bool GetAgentInfo(UUID scopeID, string fid, out UUID agentID, out string first, out string last)
266 {
267 first = "Unknown"; last = "User";
268 if (base.GetAgentInfo(scopeID, fid, out agentID, out first, out last))
269 return true;
270
271 // fid is not a UUID...
272 string url = string.Empty, tmp = string.Empty;
273 if (Util.ParseUniversalUserIdentifier(fid, out agentID, out url, out first, out last, out tmp))
274 {
275 IUserManagement userMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
276 userMan.AddUser(agentID, url + ";" + first + " " + last);
277
278 try // our best
279 {
280 string[] parts = userMan.GetUserName(agentID).Split();
281 first = parts[0];
282 last = parts[1];
283 }
284 catch { }
285 return true;
286 }
287 return false;
288 }
289
290 protected override string GetFriendshipRequesterName(UUID agentID)
291 {
292 // For the time being we assume that HG friendship requests can only happen
293 // when avies are on the same region.
294 IClientAPI client = LocateClientObject(agentID);
295 if (client != null)
296 return client.FirstName + " " + client.LastName;
297 else
298 return base.GetFriendshipRequesterName(agentID);
299 }
300
301 protected override string FriendshipMessage(string friendID)
302 {
303 UUID id;
304 if (UUID.TryParse(friendID, out id))
305 return base.FriendshipMessage(friendID);
306
307 return "Please confirm this friendship you made while you were away.";
308 }
309
310 protected override FriendInfo GetFriend(FriendInfo[] friends, UUID friendID)
311 {
312 foreach (FriendInfo fi in friends)
313 {
314 if (fi.Friend.StartsWith(friendID.ToString()))
315 return fi;
316 }
317 return null;
318 }
319
320
321 protected override FriendInfo[] GetFriendsFromService(IClientAPI client)
322 {
323 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, client.AgentId);
324 if (account1 != null)
325 return base.GetFriendsFromService(client);
326
327 FriendInfo[] finfos = new FriendInfo[0];
328 // Foreigner
329 AgentCircuitData agentClientCircuit = ((Scene)(client.Scene)).AuthenticateHandler.GetAgentCircuitData(client.CircuitCode);
330 if (agentClientCircuit != null)
331 {
332 string agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
333
334 finfos = FriendsService.GetFriends(agentUUI);
335 m_log.DebugFormat("[HGFRIENDS MODULE]: Fetched {0} local friends for visitor {1}", finfos.Length, agentUUI);
336 }
337 return finfos;
338 }
339
340 protected override bool StoreRights(UUID agentID, UUID friendID, int rights)
341 {
342 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
343 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
344 // Are they both local users?
345 if (account1 != null && account2 != null)
346 {
347 // local grid users
348 return base.StoreRights(agentID, friendID, rights);
349 }
350
351 if (account1 != null) // agent is local, friend is foreigner
352 {
353 FriendInfo[] finfos = GetFriends(agentID);
354 FriendInfo finfo = GetFriend(finfos, friendID);
355 if (finfo != null)
356 {
357 FriendsService.StoreFriend(agentID.ToString(), finfo.Friend, rights);
358 return true;
359 }
360 }
361
362 if (account2 != null) // agent is foreigner, friend is local
363 {
364 string agentUUI = GetUUI(friendID, agentID);
365 if (agentUUI != string.Empty)
366 {
367 FriendsService.StoreFriend(agentUUI, friendID.ToString(), rights);
368 return true;
369 }
370 }
371
372 return false;
373
374 }
375
376 protected override void StoreBackwards(UUID friendID, UUID agentID)
377 {
378 UserAccount account1 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
379 UserAccount account2 = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
380 // Are they both local users?
381 if (account1 != null && account2 != null)
382 {
383 // local grid users
384 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
385 base.StoreBackwards(friendID, agentID);
386 return;
387 }
388
389 // no provision for this temporary friendship state
390 //FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 0);
391 }
392
393 protected override void StoreFriendships(UUID agentID, UUID friendID)
394 {
395 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
396 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friendID);
397 // Are they both local users?
398 if (agentAccount != null && friendAccount != null)
399 {
400 // local grid users
401 m_log.DebugFormat("[HGFRIENDS MODULE]: Users are both local");
402 base.StoreFriendships(agentID, friendID);
403 return;
404 }
405
406 // ok, at least one of them is foreigner, let's get their data
407 IClientAPI agentClient = LocateClientObject(agentID);
408 IClientAPI friendClient = LocateClientObject(friendID);
409 AgentCircuitData agentClientCircuit = null;
410 AgentCircuitData friendClientCircuit = null;
411 string agentUUI = string.Empty;
412 string friendUUI = string.Empty;
413 string agentFriendService = string.Empty;
414 string friendFriendService = string.Empty;
415
416 if (agentClient != null)
417 {
418 agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode);
419 agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit);
420 agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
421 }
422 if (friendClient != null)
423 {
424 friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode);
425 friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit);
426 friendFriendService = friendClientCircuit.ServiceURLs["FriendsServerURI"].ToString();
427 }
428
429 m_log.DebugFormat("[HGFRIENDS MODULE] HG Friendship! thisUUI={0}; friendUUI={1}; foreignThisFriendService={2}; foreignFriendFriendService={3}",
430 agentUUI, friendUUI, agentFriendService, friendFriendService);
431
432 // Generate a random 8-character hex number that will sign this friendship
433 string secret = UUID.Random().ToString().Substring(0, 8);
434
435 if (agentAccount != null) // agent is local, 'friend' is foreigner
436 {
437 // This may happen when the agent returned home, in which case the friend is not there
438 // We need to look for its information in the friends list itself
439 bool confirming = false;
440 if (friendUUI == string.Empty)
441 {
442 FriendInfo[] finfos = GetFriends(agentID);
443 foreach (FriendInfo finfo in finfos)
444 {
445 if (finfo.TheirFlags == -1)
446 {
447 if (finfo.Friend.StartsWith(friendID.ToString()))
448 {
449 friendUUI = finfo.Friend;
450 confirming = true;
451 }
452 }
453 }
454 }
455
456 // If it's confirming the friendship, we already have the full friendUUI with the secret
457 string theFriendUUID = confirming ? friendUUI : friendUUI + ";" + secret;
458
459 // store in the local friends service a reference to the foreign friend
460 FriendsService.StoreFriend(agentID.ToString(), theFriendUUID, 1);
461 // and also the converse
462 FriendsService.StoreFriend(theFriendUUID, agentID.ToString(), 1);
463
464 if (!confirming && friendClientCircuit != null)
465 {
466 // store in the foreign friends service a reference to the local agent
467 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
468 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
469 }
470 }
471 else if (friendAccount != null) // 'friend' is local, agent is foreigner
472 {
473 // store in the local friends service a reference to the foreign agent
474 FriendsService.StoreFriend(friendID.ToString(), agentUUI + ";" + secret, 1);
475 // and also the converse
476 FriendsService.StoreFriend(agentUUI + ";" + secret, friendID.ToString(), 1);
477
478 if (agentClientCircuit != null)
479 {
480 // store in the foreign friends service a reference to the local agent
481 HGFriendsServicesConnector friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
482 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
483 }
484 }
485 else // They're both foreigners!
486 {
487 HGFriendsServicesConnector friendsConn;
488 if (agentClientCircuit != null)
489 {
490 friendsConn = new HGFriendsServicesConnector(agentFriendService, agentClientCircuit.SessionID, agentClientCircuit.ServiceSessionID);
491 friendsConn.NewFriendship(agentID, friendUUI + ";" + secret);
492 }
493 if (friendClientCircuit != null)
494 {
495 friendsConn = new HGFriendsServicesConnector(friendFriendService, friendClientCircuit.SessionID, friendClientCircuit.ServiceSessionID);
496 friendsConn.NewFriendship(friendID, agentUUI + ";" + secret);
497 }
498 }
499 // my brain hurts now
500 }
501
502 protected override bool DeleteFriendship(UUID agentID, UUID exfriendID)
503 {
504 UserAccount agentAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, agentID);
505 UserAccount friendAccount = UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, exfriendID);
506 // Are they both local users?
507 if (agentAccount != null && friendAccount != null)
508 {
509 // local grid users
510 return base.DeleteFriendship(agentID, exfriendID);
511 }
512
513 // ok, at least one of them is foreigner, let's get their data
514 string agentUUI = string.Empty;
515 string friendUUI = string.Empty;
516
517 if (agentAccount != null) // agent is local, 'friend' is foreigner
518 {
519 // We need to look for its information in the friends list itself
520 FriendInfo[] finfos = GetFriends(agentID);
521 FriendInfo finfo = GetFriend(finfos, exfriendID);
522 if (finfo != null)
523 {
524 friendUUI = finfo.Friend;
525
526 // delete in the local friends service the reference to the foreign friend
527 FriendsService.Delete(agentID, friendUUI);
528 // and also the converse
529 FriendsService.Delete(friendUUI, agentID.ToString());
530
531 // notify the exfriend's service
532 Util.FireAndForget(delegate { Delete(exfriendID, agentID, friendUUI); });
533
534 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentID, friendUUI);
535 return true;
536 }
537 }
538 else if (friendAccount != null) // agent is foreigner, 'friend' is local
539 {
540 agentUUI = GetUUI(exfriendID, agentID);
541
542 if (agentUUI != string.Empty)
543 {
544 // delete in the local friends service the reference to the foreign agent
545 FriendsService.Delete(exfriendID, agentUUI);
546 // and also the converse
547 FriendsService.Delete(agentUUI, exfriendID.ToString());
548
549 // notify the agent's service?
550 Util.FireAndForget(delegate { Delete(agentID, exfriendID, agentUUI); });
551
552 m_log.DebugFormat("[HGFRIENDS MODULE]: {0} terminated {1}", agentUUI, exfriendID);
553 return true;
554 }
555 }
556 //else They're both foreigners! Can't handle this
557
558 return false;
559 }
560
561 private string GetUUI(UUID localUser, UUID foreignUser)
562 {
563 // Let's see if the user is here by any chance
564 FriendInfo[] finfos = GetFriends(localUser);
565 if (finfos != EMPTY_FRIENDS) // friend is here, cool
566 {
567 FriendInfo finfo = GetFriend(finfos, foreignUser);
568 if (finfo != null)
569 {
570 return finfo.Friend;
571 }
572 }
573 else // user is not currently on this sim, need to get from the service
574 {
575 finfos = FriendsService.GetFriends(localUser);
576 foreach (FriendInfo finfo in finfos)
577 {
578 if (finfo.Friend.StartsWith(foreignUser.ToString())) // found it!
579 {
580 return finfo.Friend;
581 }
582 }
583 }
584 return string.Empty;
585 }
586
587 private void Delete(UUID foreignUser, UUID localUser, string uui)
588 {
589 UUID id;
590 string url = string.Empty, secret = string.Empty, tmp = string.Empty;
591 if (Util.ParseUniversalUserIdentifier(uui, out id, out url, out tmp, out tmp, out secret))
592 {
593 m_log.DebugFormat("[HGFRIENDS MODULE]: Deleting friendship from {0}", url);
594 HGFriendsServicesConnector friendConn = new HGFriendsServicesConnector(url);
595 friendConn.DeleteFriendship(foreignUser, localUser, secret);
596 }
597 }
598 }
599}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
new file mode 100644
index 0000000..ed02119
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs
@@ -0,0 +1,342 @@
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;
32using log4net;
33using Nini.Config;
34using Nwc.XmlRpc;
35using Mono.Addins;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42using OpenSim.Services.Interfaces;
43using OpenSim.Services.Connectors.InstantMessage;
44using OpenSim.Services.Connectors.Hypergrid;
45using OpenSim.Server.Handlers.Hypergrid;
46
47namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
48{
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
50 public class HGMessageTransferModule : ISharedRegionModule, IMessageTransferModule, IInstantMessageSimConnector
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 protected bool m_Enabled = false;
55 protected List<Scene> m_Scenes = new List<Scene>();
56
57 protected IInstantMessage m_IMService;
58 protected Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
59
60 public event UndeliveredMessage OnUndeliveredMessage;
61
62 IUserManagement m_uMan;
63 IUserManagement UserManagementModule
64 {
65 get
66 {
67 if (m_uMan == null)
68 m_uMan = m_Scenes[0].RequestModuleInterface<IUserManagement>();
69 return m_uMan;
70 }
71 }
72
73 public virtual void Initialise(IConfigSource config)
74 {
75 IConfig cnf = config.Configs["Messaging"];
76 if (cnf != null && cnf.GetString(
77 "MessageTransferModule", "MessageTransferModule") != Name)
78 {
79 m_log.Debug("[HG MESSAGE TRANSFER]: Disabled by configuration");
80 return;
81 }
82
83 InstantMessageServerConnector imServer = new InstantMessageServerConnector(config, MainServer.Instance, this);
84 m_IMService = imServer.GetService();
85 m_Enabled = true;
86 }
87
88 public virtual void AddRegion(Scene scene)
89 {
90 if (!m_Enabled)
91 return;
92
93 lock (m_Scenes)
94 {
95 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Message transfer module {0} active", Name);
96 scene.RegisterModuleInterface<IMessageTransferModule>(this);
97 m_Scenes.Add(scene);
98 }
99 }
100
101 public virtual void PostInitialise()
102 {
103 if (!m_Enabled)
104 return;
105
106 }
107
108 public virtual void RegionLoaded(Scene scene)
109 {
110 }
111
112 public virtual void RemoveRegion(Scene scene)
113 {
114 if (!m_Enabled)
115 return;
116
117 lock (m_Scenes)
118 {
119 m_Scenes.Remove(scene);
120 }
121 }
122
123 public virtual void Close()
124 {
125 }
126
127 public virtual string Name
128 {
129 get { return "HGMessageTransferModule"; }
130 }
131
132 public virtual Type ReplaceableInterface
133 {
134 get { return null; }
135 }
136
137 public void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
138 {
139 UUID toAgentID = new UUID(im.toAgentID);
140
141 // Try root avatar only first
142 foreach (Scene scene in m_Scenes)
143 {
144 if (scene.Entities.ContainsKey(toAgentID) &&
145 scene.Entities[toAgentID] is ScenePresence)
146 {
147// m_log.DebugFormat(
148// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
149// toAgentID.ToString(), scene.RegionInfo.RegionName);
150
151 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
152 if (!user.IsChildAgent)
153 {
154 // Local message
155// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID);
156 user.ControllingClient.SendInstantMessage(im);
157
158 // Message sent
159 result(true);
160 return;
161 }
162 }
163 }
164
165 // try child avatar second
166 foreach (Scene scene in m_Scenes)
167 {
168// m_log.DebugFormat(
169// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
170
171 if (scene.Entities.ContainsKey(toAgentID) &&
172 scene.Entities[toAgentID] is ScenePresence)
173 {
174 // Local message
175 ScenePresence user = (ScenePresence) scene.Entities[toAgentID];
176
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID);
178 user.ControllingClient.SendInstantMessage(im);
179
180 // Message sent
181 result(true);
182 return;
183 }
184 }
185
186// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
187 // Is the user a local user?
188 UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID);
189 string url = string.Empty;
190 PresenceInfo upd;
191 if (account == null) // foreign user
192 url = UserManagementModule.GetUserServerURL(toAgentID, "IMServerURI");
193
194 Util.FireAndForget(delegate
195 {
196 bool success = m_IMService.OutgoingInstantMessage(im, url);
197 if (!success && account == null)
198 {
199 // One last chance
200 string recipientUUI = TryGetRecipientUUI(new UUID(im.fromAgentID), toAgentID);
201 m_log.DebugFormat("[HG MESSAGE TRANSFER]: Got UUI {0}", recipientUUI);
202 if (recipientUUI != string.Empty)
203 {
204 UUID id; string u = string.Empty, first = string.Empty, last = string.Empty, secret = string.Empty;
205 if (Util.ParseUniversalUserIdentifier(recipientUUI, out id, out u, out first, out last, out secret))
206 {
207 success = m_IMService.OutgoingInstantMessage(im, u);
208 if (success)
209 UserManagementModule.AddUser(toAgentID, u + ";" + first + " " + last);
210 }
211 }
212 }
213 result(success);
214 });
215
216 return;
217 }
218
219 protected bool SendIMToScene(GridInstantMessage gim, UUID toAgentID)
220 {
221 bool successful = false;
222 foreach (Scene scene in m_Scenes)
223 {
224 if (scene.Entities.ContainsKey(toAgentID) &&
225 scene.Entities[toAgentID] is ScenePresence)
226 {
227 ScenePresence user =
228 (ScenePresence)scene.Entities[toAgentID];
229
230 if (!user.IsChildAgent)
231 {
232 scene.EventManager.TriggerIncomingInstantMessage(gim);
233 successful = true;
234 }
235 }
236 }
237 if (!successful)
238 {
239 // If the message can't be delivered to an agent, it
240 // is likely to be a group IM. On a group IM, the
241 // imSessionID = toAgentID = group id. Raise the
242 // unhandled IM event to give the groups module
243 // a chance to pick it up. We raise that in a random
244 // scene, since the groups module is shared.
245 //
246 m_Scenes[0].EventManager.TriggerUnhandledInstantMessage(gim);
247 }
248
249 return successful;
250 }
251
252 protected void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
253 {
254 UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage;
255
256 // If this event has handlers, then an IM from an agent will be
257 // considered delivered. This will suppress the error message.
258 //
259 if (handlerUndeliveredMessage != null)
260 {
261 handlerUndeliveredMessage(im);
262 if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent)
263 result(true);
264 else
265 result(false);
266 return;
267 }
268
269 //m_log.DebugFormat("[INSTANT MESSAGE]: Undeliverable");
270 result(false);
271 }
272
273 private string TryGetRecipientUUI(UUID fromAgent, UUID toAgent)
274 {
275 // Let's call back the fromAgent's user agent service
276 // Maybe that service knows about the toAgent
277 IClientAPI client = LocateClientObject(fromAgent);
278 if (client != null)
279 {
280 AgentCircuitData circuit = m_Scenes[0].AuthenticateHandler.GetAgentCircuitData(client.AgentId);
281 if (circuit != null)
282 {
283 if (circuit.ServiceURLs.ContainsKey("HomeURI"))
284 {
285 string uasURL = circuit.ServiceURLs["HomeURI"].ToString();
286 m_log.DebugFormat("[HG MESSAGE TRANSFER]: getting UUI of user {0} from {1}", toAgent, uasURL);
287 UserAgentServiceConnector uasConn = new UserAgentServiceConnector(uasURL);
288 return uasConn.GetUUI(fromAgent, toAgent);
289 }
290 }
291 }
292
293 return string.Empty;
294 }
295
296
297 /// <summary>
298 /// Find the scene for an agent
299 /// </summary>
300 private Scene GetClientScene(UUID agentId)
301 {
302 lock (m_Scenes)
303 {
304 foreach (Scene scene in m_Scenes)
305 {
306 ScenePresence presence = scene.GetScenePresence(agentId);
307 if (presence != null && !presence.IsChildAgent)
308 return scene;
309 }
310 }
311
312 return null;
313 }
314
315 /// <summary>
316 /// Find the client for a ID
317 /// </summary>
318 public IClientAPI LocateClientObject(UUID agentID)
319 {
320 Scene scene = GetClientScene(agentID);
321 if (scene != null)
322 {
323 ScenePresence presence = scene.GetScenePresence(agentID);
324 if (presence != null)
325 return presence.ControllingClient;
326 }
327
328 return null;
329 }
330
331 #region IInstantMessageSimConnector
332 public bool SendInstantMessage(GridInstantMessage im)
333 {
334 //m_log.DebugFormat("[XXX] Hook SendInstantMessage {0}", im.message);
335 UUID agentID = new UUID(im.toAgentID);
336 return SendIMToScene(im, agentID);
337 }
338 #endregion
339
340
341 }
342}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 52791cb..429dda7 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -110,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
110 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel) 110 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
111 { 111 {
112 string userAssetServer = string.Empty; 112 string userAssetServer = string.Empty;
113 if (IsForeignUser(avatarID, out userAssetServer) && m_OutboundPermission) 113 if (IsForeignUser(avatarID, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
114 { 114 {
115 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); }); 115 Util.FireAndForget(delegate { m_assMapper.Post(assetID, avatarID, userAssetServer); });
116 } 116 }
@@ -180,10 +180,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
180 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver) 180 public override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
181 { 181 {
182 string userAssetServer = string.Empty; 182 string userAssetServer = string.Empty;
183 if (IsForeignUser(sender, out userAssetServer)) 183 if (IsForeignUser(sender, out userAssetServer) && userAssetServer != string.Empty)
184 m_assMapper.Get(item.AssetID, sender, userAssetServer); 184 m_assMapper.Get(item.AssetID, sender, userAssetServer);
185 185
186 if (IsForeignUser(receiver, out userAssetServer) && m_OutboundPermission) 186 if (IsForeignUser(receiver, out userAssetServer) && userAssetServer != string.Empty && m_OutboundPermission)
187 m_assMapper.Post(item.AssetID, receiver, userAssetServer); 187 m_assMapper.Post(item.AssetID, receiver, userAssetServer);
188 } 188 }
189 189
@@ -203,9 +203,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
203 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 203 if (aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
204 { 204 {
205 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 205 assetServerURL = aCircuit.ServiceURLs["AssetServerURI"].ToString();
206 assetServerURL = assetServerURL.Trim(new char[] { '/' }); return true; 206 assetServerURL = assetServerURL.Trim(new char[] { '/' });
207 } 207 }
208 } 208 }
209 else
210 {
211 assetServerURL = UserManagementModule.GetUserServerURL(userID, "AssetServerURI");
212 assetServerURL = assetServerURL.Trim(new char[] { '/' });
213 }
214 return true;
209 } 215 }
210 216
211 return false; 217 return false;
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 4cc6905..4d073b2 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -35,6 +35,7 @@ using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
38using OpenSim.Services.Connectors.Hypergrid;
38 39
39using OpenMetaverse; 40using OpenMetaverse;
40using log4net; 41using log4net;
@@ -47,7 +48,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
47 public UUID Id; 48 public UUID Id;
48 public string FirstName; 49 public string FirstName;
49 public string LastName; 50 public string LastName;
50 public string ProfileURL; 51 public string HomeURL;
52 public Dictionary<string, object> ServerURLs;
51 } 53 }
52 54
53 public class UserManagementModule : ISharedRegionModule, IUserManagement 55 public class UserManagementModule : ISharedRegionModule, IUserManagement
@@ -141,6 +143,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
141 143
142 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client) 144 void HandleUUIDNameRequest(UUID uuid, IClientAPI remote_client)
143 { 145 {
146 m_log.DebugFormat("[XXX] HandleUUIDNameRequest {0}", uuid);
144 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid)) 147 if (m_Scenes[0].LibraryService != null && (m_Scenes[0].LibraryService.LibraryRootFolder.Owner == uuid))
145 { 148 {
146 remote_client.SendNameReply(uuid, "Mr", "OpenSim"); 149 remote_client.SendNameReply(uuid, "Mr", "OpenSim");
@@ -210,6 +213,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
210 213
211 public string GetUserName(UUID uuid) 214 public string GetUserName(UUID uuid)
212 { 215 {
216 m_log.DebugFormat("[XXX] GetUserName {0}", uuid);
213 string[] names = GetUserNames(uuid); 217 string[] names = GetUserNames(uuid);
214 if (names.Length == 2) 218 if (names.Length == 2)
215 { 219 {
@@ -222,6 +226,34 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
222 return "(hippos)"; 226 return "(hippos)";
223 } 227 }
224 228
229 public string GetUserHomeURL(UUID userID)
230 {
231 if (m_UserCache.ContainsKey(userID))
232 return m_UserCache[userID].HomeURL;
233
234 return string.Empty;
235 }
236
237 public string GetUserServerURL(UUID userID, string serverType)
238 {
239 if (m_UserCache.ContainsKey(userID))
240 {
241 UserData userdata = m_UserCache[userID];
242 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
243 return userdata.ServerURLs[serverType].ToString();
244
245 if (userdata.HomeURL != string.Empty)
246 {
247 UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL);
248 userdata.ServerURLs = uConn.GetServerURLs(userID);
249 if (userdata.ServerURLs != null && userdata.ServerURLs.ContainsKey(serverType) && userdata.ServerURLs[serverType] != null)
250 return userdata.ServerURLs[serverType].ToString();
251 }
252 }
253
254 return string.Empty;
255 }
256
225 public void AddUser(UUID id, string creatorData) 257 public void AddUser(UUID id, string creatorData)
226 { 258 {
227 if (m_UserCache.ContainsKey(id)) 259 if (m_UserCache.ContainsKey(id))
@@ -247,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
247 string[] parts = creatorData.Split(';'); 279 string[] parts = creatorData.Split(';');
248 if (parts.Length >= 1) 280 if (parts.Length >= 1)
249 { 281 {
250 user.ProfileURL = parts[0]; 282 user.HomeURL = parts[0];
251 try 283 try
252 { 284 {
253 Uri uri = new Uri(parts[0]); 285 Uri uri = new Uri(parts[0]);
@@ -272,7 +304,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
272 lock (m_UserCache) 304 lock (m_UserCache)
273 m_UserCache[id] = user; 305 m_UserCache[id] = user;
274 306
275 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); 307 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.HomeURL);
276 } 308 }
277 309
278 public void AddUser(UUID uuid, string first, string last, string profileURL) 310 public void AddUser(UUID uuid, string first, string last, string profileURL)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
index d2343c9..a5b5637 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Hypergrid/HypergridServiceInConnectorModule.cs
@@ -113,8 +113,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Hypergrid
113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>(); 113 ISimulationService simService = scene.RequestModuleInterface<ISimulationService>();
114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService); 114 m_HypergridHandler = new GatekeeperServiceInConnector(m_Config, MainServer.Instance, simService);
115 115
116 new UserAgentServerConnector(m_Config, MainServer.Instance); 116 IFriendsSimConnector friendsConn = scene.RequestModuleInterface<IFriendsSimConnector>();
117 new UserAgentServerConnector(m_Config, MainServer.Instance, friendsConn);
117 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService"); 118 new HeloServiceInConnector(m_Config, MainServer.Instance, "HeloService");
119 new HGFriendsServerConnector(m_Config, MainServer.Instance, "HGFriendsService");
118 } 120 }
119 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper); 121 scene.RegisterModuleInterface<IGatekeeperService>(m_HypergridHandler.GateKeeper);
120 } 122 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index 3f63db3..eef60a1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -58,6 +58,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
58 58
59 private List<Scene> m_Scenes = new List<Scene>(); 59 private List<Scene> m_Scenes = new List<Scene>();
60 60
61 protected IUserManagement m_UserManagement;
62 protected IUserManagement UserManagementModule
63 {
64 get
65 {
66 if (m_UserManagement == null)
67 m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
68 return m_UserManagement;
69 }
70 }
71
61 public Type ReplaceableInterface 72 public Type ReplaceableInterface
62 { 73 {
63 get { return null; } 74 get { return null; }
@@ -206,6 +217,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
206 return; 217 return;
207 } 218 }
208 } 219 }
220 else
221 {
222 inventoryURL = UserManagementModule.GetUserServerURL(userID, "InventoryServerURI");
223 inventoryURL = inventoryURL.Trim(new char[] { '/' });
224 }
209 } 225 }
210 } 226 }
211 } 227 }
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 170c35f..d7324c6 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -548,18 +548,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
548 548
549 // libomv will moan about PrimFlags.ObjectYouOfficer being 549 // libomv will moan about PrimFlags.ObjectYouOfficer being
550 // deprecated 550 // deprecated
551 #pragma warning disable 0612 551#pragma warning disable 0612
552 objflags &= (uint) 552 objflags &= (uint)
553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object 553 ~(PrimFlags.ObjectCopy | // Tells client you can copy the object
554 PrimFlags.ObjectModify | // tells client you can modify the object 554 PrimFlags.ObjectModify | // tells client you can modify the object
555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) 555 PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod)
556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it 556 PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it
557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object 557 PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object
558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object 558 PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object
559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object 559 PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object
560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set 560 PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set
561 ); 561 );
562 #pragma warning restore 0612 562#pragma warning restore 0612
563 563
564 // Creating the three ObjectFlags options for this method to choose from. 564 // Creating the three ObjectFlags options for this method to choose from.
565 // Customize the OwnerMask 565 // Customize the OwnerMask
@@ -576,22 +576,27 @@ namespace OpenSim.Region.CoreModules.World.Permissions
576 576
577 if (m_bypassPermissions) 577 if (m_bypassPermissions)
578 return objectOwnerMask; 578 return objectOwnerMask;
579 579
580 // Object owners should be able to edit their own content 580 // Object owners should be able to edit their own content
581 if (user == objectOwner) 581 if (user == objectOwner)
582 return objectOwnerMask; 582 return objectOwnerMask;
583 583
584 if (IsFriendWithPerms(user, objectOwner)) 584 if (IsFriendWithPerms(user, objectOwner))
585 {
585 return objectOwnerMask; 586 return objectOwnerMask;
586 587 }
587 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set 588 // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
588 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) 589 if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
590 {
589 return objectOwnerMask; 591 return objectOwnerMask;
592 }
590 593
591 // Admin should be able to edit anything in the sim (including admin objects) 594 // Admin should be able to edit anything in the sim (including admin objects)
592 if (IsAdministrator(user)) 595 if (IsAdministrator(user))
596 {
593 return objectOwnerMask; 597 return objectOwnerMask;
594 598 }
599
595 // Users should be able to edit what is over their land. 600 // Users should be able to edit what is over their land.
596 Vector3 taskPos = task.AbsolutePosition; 601 Vector3 taskPos = task.AbsolutePosition;
597 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); 602 ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
@@ -599,13 +604,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions
599 { 604 {
600 // Admin objects should not be editable by the above 605 // Admin objects should not be editable by the above
601 if (!IsAdministrator(objectOwner)) 606 if (!IsAdministrator(objectOwner))
607 {
602 return objectOwnerMask; 608 return objectOwnerMask;
609 }
603 } 610 }
604 611
605 // Group permissions 612 // Group permissions
606 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) 613 if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
607 return objectGroupMask | objectEveryoneMask; 614 return objectGroupMask | objectEveryoneMask;
608 615
609 return objectEveryoneMask; 616 return objectEveryoneMask;
610 } 617 }
611 618
@@ -673,7 +680,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
673 // 680 //
674 // Nobody but the object owner can set permissions on an object 681 // Nobody but the object owner can set permissions on an object
675 // 682 //
676
677 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) 683 if (locked && (!IsAdministrator(currentUser)) && denyOnLocked)
678 { 684 {
679 return false; 685 return false;
@@ -704,6 +710,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
704 // Return immediately, so that the administrator can shares group objects 710 // Return immediately, so that the administrator can shares group objects
705 return true; 711 return true;
706 } 712 }
713
714 // Friends with benefits should be able to edit the objects too
715 if (IsFriendWithPerms(currentUser, objectOwner))
716 // Return immediately, so that the administrator can share objects with friends
717 return true;
707 718
708 // Users should be able to edit what is over their land. 719 // Users should be able to edit what is over their land.
709 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); 720 ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y);
diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
index 0ff7dee..d4a6857 100644
--- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
@@ -34,6 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces
34 public interface IFriendsModule 34 public interface IFriendsModule
35 { 35 {
36 uint GetFriendPerms(UUID PrincipalID, UUID FriendID); 36 uint GetFriendPerms(UUID PrincipalID, UUID FriendID);
37 void SendFriendsOnlineIfNeeded(IClientAPI client); 37 bool SendFriendsOnlineIfNeeded(IClientAPI client);
38 } 38 }
39} 39}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
index 2904ee8..9cac3b0 100644
--- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
@@ -8,6 +8,8 @@ namespace OpenSim.Region.Framework.Interfaces
8 public interface IUserManagement 8 public interface IUserManagement
9 { 9 {
10 string GetUserName(UUID uuid); 10 string GetUserName(UUID uuid);
11 string GetUserHomeURL(UUID uuid);
12 string GetUserServerURL(UUID uuid, string serverType);
11 void AddUser(UUID uuid, string userData); 13 void AddUser(UUID uuid, string userData);
12 void AddUser(UUID uuid, string firstName, string lastName, string profileURL); 14 void AddUser(UUID uuid, string firstName, string lastName, string profileURL);
13 } 15 }
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index f4472c7..6743a2e 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -65,6 +65,10 @@ namespace OpenSim.Server.Base
65 /// <returns></returns> 65 /// <returns></returns>
66 public static T LoadPlugin<T>(string dllName, Object[] args) where T:class 66 public static T LoadPlugin<T>(string dllName, Object[] args) where T:class
67 { 67 {
68 // This is good to debug configuration problems
69 //if (dllName == string.Empty)
70 // Util.PrintCallStack();
71
68 string[] parts = dllName.Split(new char[] {':'}); 72 string[] parts = dllName.Split(new char[] {':'});
69 73
70 dllName = parts[0]; 74 dllName = parts[0];
diff --git a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs
index 074f869..5784bdf 100644
--- a/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs
+++ b/OpenSim/Server/Handlers/Friends/FriendServerConnector.cs
@@ -46,14 +46,14 @@ namespace OpenSim.Server.Handlers.Friends
46 if (serverConfig == null) 46 if (serverConfig == null)
47 throw new Exception(String.Format("No section {0} in config file", m_ConfigName)); 47 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
48 48
49 string gridService = serverConfig.GetString("LocalServiceModule", 49 string theService = serverConfig.GetString("LocalServiceModule",
50 String.Empty); 50 String.Empty);
51 51
52 if (gridService == String.Empty) 52 if (theService == String.Empty)
53 throw new Exception("No LocalServiceModule in config file"); 53 throw new Exception("No LocalServiceModule in config file");
54 54
55 Object[] args = new Object[] { config }; 55 Object[] args = new Object[] { config };
56 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(gridService, args); 56 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
57 57
58 server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService)); 58 server.AddStreamHandler(new FriendsServerPostHandler(m_FriendsService));
59 } 59 }
diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
index b168bb3..9969086 100644
--- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs
@@ -82,12 +82,18 @@ namespace OpenSim.Server.Handlers.Friends
82 case "getfriends": 82 case "getfriends":
83 return GetFriends(request); 83 return GetFriends(request);
84 84
85 case "getfriends_string":
86 return GetFriendsString(request);
87
85 case "storefriend": 88 case "storefriend":
86 return StoreFriend(request); 89 return StoreFriend(request);
87 90
88 case "deletefriend": 91 case "deletefriend":
89 return DeleteFriend(request); 92 return DeleteFriend(request);
90 93
94 case "deletefriend_string":
95 return DeleteFriendString(request);
96
91 } 97 }
92 m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method); 98 m_log.DebugFormat("[FRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
93 } 99 }
@@ -111,7 +117,25 @@ namespace OpenSim.Server.Handlers.Friends
111 m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends"); 117 m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends");
112 118
113 FriendInfo[] finfos = m_FriendsService.GetFriends(principalID); 119 FriendInfo[] finfos = m_FriendsService.GetFriends(principalID);
114 //m_log.DebugFormat("[FRIENDS HANDLER]: neighbours for region {0}: {1}", regionID, rinfos.Count); 120
121 return PackageFriends(finfos);
122 }
123
124 byte[] GetFriendsString(Dictionary<string, object> request)
125 {
126 string principalID = string.Empty;
127 if (request.ContainsKey("PRINCIPALID"))
128 principalID = request["PRINCIPALID"].ToString();
129 else
130 m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to get friends");
131
132 FriendInfo[] finfos = m_FriendsService.GetFriends(principalID);
133
134 return PackageFriends(finfos);
135 }
136
137 private byte[] PackageFriends(FriendInfo[] finfos)
138 {
115 139
116 Dictionary<string, object> result = new Dictionary<string, object>(); 140 Dictionary<string, object> result = new Dictionary<string, object>();
117 if ((finfos == null) || ((finfos != null) && (finfos.Length == 0))) 141 if ((finfos == null) || ((finfos != null) && (finfos.Length == 0)))
@@ -138,7 +162,7 @@ namespace OpenSim.Server.Handlers.Friends
138 { 162 {
139 FriendInfo friend = new FriendInfo(request); 163 FriendInfo friend = new FriendInfo(request);
140 164
141 bool success = m_FriendsService.StoreFriend(friend.PrincipalID, friend.Friend, friend.MyFlags); 165 bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, friend.MyFlags);
142 166
143 if (success) 167 if (success)
144 return SuccessResult(); 168 return SuccessResult();
@@ -163,7 +187,25 @@ namespace OpenSim.Server.Handlers.Friends
163 else 187 else
164 return FailureResult(); 188 return FailureResult();
165 } 189 }
166 190
191 byte[] DeleteFriendString(Dictionary<string, object> request)
192 {
193 string principalID = string.Empty;
194 if (request.ContainsKey("PRINCIPALID"))
195 principalID = request["PRINCIPALID"].ToString();
196 else
197 m_log.WarnFormat("[FRIENDS HANDLER]: no principalID in request to delete friend");
198 string friend = string.Empty;
199 if (request.ContainsKey("FRIEND"))
200 friend = request["FRIEND"].ToString();
201
202 bool success = m_FriendsService.Delete(principalID, friend);
203 if (success)
204 return SuccessResult();
205 else
206 return FailureResult();
207 }
208
167 #endregion 209 #endregion
168 210
169 #region Misc 211 #region Misc
diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs
new file mode 100644
index 0000000..82a7220
--- /dev/null
+++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendServerConnector.cs
@@ -0,0 +1,71 @@
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 Nini.Config;
30using OpenSim.Server.Base;
31using OpenSim.Services.Interfaces;
32using OpenSim.Framework.Servers.HttpServer;
33using OpenSim.Server.Handlers.Base;
34
35namespace OpenSim.Server.Handlers.Hypergrid
36{
37 public class HGFriendsServerConnector : ServiceConnector
38 {
39 private IFriendsService m_FriendsService;
40 private IUserAgentService m_UserAgentService;
41 private string m_ConfigName = "HGFriendsService";
42
43 public HGFriendsServerConnector(IConfigSource config, IHttpServer server, string configName) :
44 base(config, server, configName)
45 {
46 if (configName != string.Empty)
47 m_ConfigName = configName;
48
49 IConfig serverConfig = config.Configs[m_ConfigName];
50 if (serverConfig == null)
51 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
52
53 string theService = serverConfig.GetString("LocalServiceModule",
54 String.Empty);
55
56 if (theService == String.Empty)
57 throw new Exception("No LocalServiceModule in config file");
58
59 Object[] args = new Object[] { config };
60 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(theService, args);
61
62 theService = serverConfig.GetString("UserAgentService", string.Empty);
63 if (theService == String.Empty)
64 throw new Exception("No UserAgentService in " + m_ConfigName);
65
66 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(theService, args);
67
68 server.AddStreamHandler(new HGFriendsServerPostHandler(m_FriendsService, m_UserAgentService));
69 }
70 }
71}
diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
new file mode 100644
index 0000000..841811e
--- /dev/null
+++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs
@@ -0,0 +1,323 @@
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 Nini.Config;
29using log4net;
30using System;
31using System.Reflection;
32using System.IO;
33using System.Net;
34using System.Text;
35using System.Text.RegularExpressions;
36using System.Xml;
37using System.Xml.Serialization;
38using System.Collections.Generic;
39using OpenSim.Server.Base;
40using OpenSim.Services.Interfaces;
41using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
42using OpenSim.Framework;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenMetaverse;
45
46namespace OpenSim.Server.Handlers.Hypergrid
47{
48 public class HGFriendsServerPostHandler : BaseStreamHandler
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private IFriendsService m_FriendsService;
53 private IUserAgentService m_UserAgentService;
54
55 public HGFriendsServerPostHandler(IFriendsService service, IUserAgentService uservice) :
56 base("POST", "/hgfriends")
57 {
58 m_FriendsService = service;
59 m_UserAgentService = uservice;
60 m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On");
61 }
62
63 public override byte[] Handle(string path, Stream requestData,
64 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
65 {
66 StreamReader sr = new StreamReader(requestData);
67 string body = sr.ReadToEnd();
68 sr.Close();
69 body = body.Trim();
70
71 //m_log.DebugFormat("[XXX]: query String: {0}", body);
72
73 try
74 {
75 Dictionary<string, object> request =
76 ServerUtils.ParseQueryString(body);
77
78 if (!request.ContainsKey("METHOD"))
79 return FailureResult();
80
81 string method = request["METHOD"].ToString();
82
83 switch (method)
84 {
85 case "getfriendperms":
86 return GetFriendPerms(request);
87
88 case "newfriendship":
89 return NewFriendship(request);
90
91 case "deletefriendship":
92 return DeleteFriendship(request);
93 }
94 m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0} request {1}", method.Length, method);
95 }
96 catch (Exception e)
97 {
98 m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e);
99 }
100
101 return FailureResult();
102
103 }
104
105 #region Method-specific handlers
106
107 byte[] GetFriendPerms(Dictionary<string, object> request)
108 {
109 if (!VerifyServiceKey(request))
110 return FailureResult();
111
112 UUID principalID = UUID.Zero;
113 if (request.ContainsKey("PRINCIPALID"))
114 UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID);
115 else
116 {
117 m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms");
118 return FailureResult();
119 }
120
121 UUID friendID = UUID.Zero;
122 if (request.ContainsKey("FRIENDID"))
123 UUID.TryParse(request["FRIENDID"].ToString(), out friendID);
124 else
125 {
126 m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms");
127 return FailureResult();
128 }
129
130 string perms = "0";
131 FriendInfo[] friendsInfo = m_FriendsService.GetFriends(principalID);
132 foreach (FriendInfo finfo in friendsInfo)
133 {
134 if (finfo.Friend.StartsWith(friendID.ToString()))
135 return SuccessResult(finfo.TheirFlags.ToString());
136 }
137
138 return FailureResult("Friend not found");
139 }
140
141 byte[] NewFriendship(Dictionary<string, object> request)
142 {
143 m_log.DebugFormat("[XXX] 1");
144 if (!VerifyServiceKey(request))
145 return FailureResult();
146
147 m_log.DebugFormat("[XXX] 2");
148 // OK, can proceed
149 FriendInfo friend = new FriendInfo(request);
150 UUID friendID;
151 string tmp = string.Empty;
152 m_log.DebugFormat("[XXX] 3");
153 if (!Util.ParseUniversalUserIdentifier(friend.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
154 return FailureResult();
155
156
157 m_log.DebugFormat("[HGFRIENDS HANDLER]: New friendship {0} {1}", friend.PrincipalID, friend.Friend);
158
159 // If the friendship already exists, return fail
160 FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
161 foreach (FriendInfo finfo in finfos)
162 if (finfo.Friend.StartsWith(friendID.ToString()))
163 return FailureResult();
164
165 // the user needs to confirm when he gets home
166 bool success = m_FriendsService.StoreFriend(friend.PrincipalID.ToString(), friend.Friend, 0);
167
168 if (success)
169 return SuccessResult();
170 else
171 return FailureResult();
172 }
173
174 byte[] DeleteFriendship(Dictionary<string, object> request)
175 {
176 FriendInfo friend = new FriendInfo(request);
177 string secret = string.Empty;
178 if (request.ContainsKey("SECRET"))
179 secret = request["SECRET"].ToString();
180
181 if (secret == string.Empty)
182 return FailureResult();
183
184 FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
185 foreach (FriendInfo finfo in finfos)
186 {
187 // We check the secret here
188 if (finfo.Friend.StartsWith(friend.Friend) && finfo.Friend.EndsWith(secret))
189 {
190 m_log.DebugFormat("[HGFRIENDS HANDLER]: Delete friendship {0} {1}", friend.PrincipalID, friend.Friend);
191 m_FriendsService.Delete(friend.PrincipalID, finfo.Friend);
192 m_FriendsService.Delete(finfo.Friend, friend.PrincipalID.ToString());
193
194 return SuccessResult();
195 }
196 }
197
198 return FailureResult();
199 }
200
201 #endregion
202
203 #region Misc
204
205 private bool VerifyServiceKey(Dictionary<string, object> request)
206 {
207 if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID"))
208 {
209 m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID");
210 return false;
211 }
212
213 string serviceKey = request["KEY"].ToString();
214 string sessionStr = request["SESSIONID"].ToString();
215 UUID sessionID;
216 UUID.TryParse(sessionStr, out sessionID);
217
218 if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
219 {
220 m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID);
221 return false;
222 }
223
224 m_log.DebugFormat("[XXX] Verification ok");
225 return true;
226 }
227
228 private byte[] SuccessResult()
229 {
230 XmlDocument doc = new XmlDocument();
231
232 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
233 "", "");
234
235 doc.AppendChild(xmlnode);
236
237 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
238 "");
239
240 doc.AppendChild(rootElement);
241
242 XmlElement result = doc.CreateElement("", "Result", "");
243 result.AppendChild(doc.CreateTextNode("Success"));
244
245 rootElement.AppendChild(result);
246
247 return DocToBytes(doc);
248 }
249
250 private byte[] SuccessResult(string value)
251 {
252 XmlDocument doc = new XmlDocument();
253
254 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
255 "", "");
256
257 doc.AppendChild(xmlnode);
258
259 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
260 "");
261
262 doc.AppendChild(rootElement);
263
264 XmlElement result = doc.CreateElement("", "Result", "");
265 result.AppendChild(doc.CreateTextNode("Success"));
266
267 rootElement.AppendChild(result);
268
269 XmlElement message = doc.CreateElement("", "Value", "");
270 message.AppendChild(doc.CreateTextNode(value));
271
272 rootElement.AppendChild(message);
273
274 return DocToBytes(doc);
275 }
276
277
278 private byte[] FailureResult()
279 {
280 return FailureResult(String.Empty);
281 }
282
283 private byte[] FailureResult(string msg)
284 {
285 XmlDocument doc = new XmlDocument();
286
287 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
288 "", "");
289
290 doc.AppendChild(xmlnode);
291
292 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
293 "");
294
295 doc.AppendChild(rootElement);
296
297 XmlElement result = doc.CreateElement("", "Result", "");
298 result.AppendChild(doc.CreateTextNode("Failure"));
299
300 rootElement.AppendChild(result);
301
302 XmlElement message = doc.CreateElement("", "Message", "");
303 message.AppendChild(doc.CreateTextNode(msg));
304
305 rootElement.AppendChild(message);
306
307 return DocToBytes(doc);
308 }
309
310 private byte[] DocToBytes(XmlDocument doc)
311 {
312 MemoryStream ms = new MemoryStream();
313 XmlTextWriter xw = new XmlTextWriter(ms, null);
314 xw.Formatting = Formatting.Indented;
315 doc.WriteTo(xw);
316 xw.Flush();
317
318 return ms.ToArray();
319 }
320
321 #endregion
322 }
323}
diff --git a/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs
new file mode 100644
index 0000000..138313a
--- /dev/null
+++ b/OpenSim/Server/Handlers/Hypergrid/InstantMessageServerConnector.cs
@@ -0,0 +1,280 @@
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;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenSim.Framework.Servers.HttpServer;
39using OpenSim.Server.Handlers.Base;
40using GridRegion = OpenSim.Services.Interfaces.GridRegion;
41
42using log4net;
43using Nwc.XmlRpc;
44using OpenMetaverse;
45
46namespace OpenSim.Server.Handlers.Hypergrid
47{
48 public class InstantMessageServerConnector : ServiceConnector
49 {
50 private static readonly ILog m_log =
51 LogManager.GetLogger(
52 MethodBase.GetCurrentMethod().DeclaringType);
53
54 private IInstantMessage m_IMService;
55
56 public InstantMessageServerConnector(IConfigSource config, IHttpServer server) :
57 this(config, server, null)
58 {
59 }
60
61 public InstantMessageServerConnector(IConfigSource config, IHttpServer server, IInstantMessageSimConnector simConnector) :
62 base(config, server, String.Empty)
63 {
64 IConfig gridConfig = config.Configs["HGInstantMessageService"];
65 if (gridConfig != null)
66 {
67 string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
68
69 Object[] args = new Object[] { config, simConnector };
70 m_IMService = ServerUtils.LoadPlugin<IInstantMessage>(serviceDll, args);
71 }
72 if (m_IMService == null)
73 throw new Exception("InstantMessage server connector cannot proceed because of missing service");
74
75 MainServer.Instance.AddXmlRPCHandler("grid_instant_message", ProcessInstantMessage, false);
76
77 }
78
79 public IInstantMessage GetService()
80 {
81 return m_IMService;
82 }
83
84 protected virtual XmlRpcResponse ProcessInstantMessage(XmlRpcRequest request, IPEndPoint remoteClient)
85 {
86 bool successful = false;
87
88 try
89 {
90 // various rational defaults
91 UUID fromAgentID = UUID.Zero;
92 UUID toAgentID = UUID.Zero;
93 UUID imSessionID = UUID.Zero;
94 uint timestamp = 0;
95 string fromAgentName = "";
96 string message = "";
97 byte dialog = (byte)0;
98 bool fromGroup = false;
99 byte offline = (byte)0;
100 uint ParentEstateID = 0;
101 Vector3 Position = Vector3.Zero;
102 UUID RegionID = UUID.Zero;
103 byte[] binaryBucket = new byte[0];
104
105 float pos_x = 0;
106 float pos_y = 0;
107 float pos_z = 0;
108 //m_log.Info("Processing IM");
109
110
111 Hashtable requestData = (Hashtable)request.Params[0];
112 // Check if it's got all the data
113 if (requestData.ContainsKey("from_agent_id")
114 && requestData.ContainsKey("to_agent_id") && requestData.ContainsKey("im_session_id")
115 && requestData.ContainsKey("timestamp") && requestData.ContainsKey("from_agent_name")
116 && requestData.ContainsKey("message") && requestData.ContainsKey("dialog")
117 && requestData.ContainsKey("from_group")
118 && requestData.ContainsKey("offline") && requestData.ContainsKey("parent_estate_id")
119 && requestData.ContainsKey("position_x") && requestData.ContainsKey("position_y")
120 && requestData.ContainsKey("position_z") && requestData.ContainsKey("region_id")
121 && requestData.ContainsKey("binary_bucket"))
122 {
123 // Do the easy way of validating the UUIDs
124 UUID.TryParse((string)requestData["from_agent_id"], out fromAgentID);
125 UUID.TryParse((string)requestData["to_agent_id"], out toAgentID);
126 UUID.TryParse((string)requestData["im_session_id"], out imSessionID);
127 UUID.TryParse((string)requestData["region_id"], out RegionID);
128
129 try
130 {
131 timestamp = (uint)Convert.ToInt32((string)requestData["timestamp"]);
132 }
133 catch (ArgumentException)
134 {
135 }
136 catch (FormatException)
137 {
138 }
139 catch (OverflowException)
140 {
141 }
142
143 fromAgentName = (string)requestData["from_agent_name"];
144 message = (string)requestData["message"];
145 if (message == null)
146 message = string.Empty;
147
148 // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them.
149 string requestData1 = (string)requestData["dialog"];
150 if (string.IsNullOrEmpty(requestData1))
151 {
152 dialog = 0;
153 }
154 else
155 {
156 byte[] dialogdata = Convert.FromBase64String(requestData1);
157 dialog = dialogdata[0];
158 }
159
160 if ((string)requestData["from_group"] == "TRUE")
161 fromGroup = true;
162
163 string requestData2 = (string)requestData["offline"];
164 if (String.IsNullOrEmpty(requestData2))
165 {
166 offline = 0;
167 }
168 else
169 {
170 byte[] offlinedata = Convert.FromBase64String(requestData2);
171 offline = offlinedata[0];
172 }
173
174 try
175 {
176 ParentEstateID = (uint)Convert.ToInt32((string)requestData["parent_estate_id"]);
177 }
178 catch (ArgumentException)
179 {
180 }
181 catch (FormatException)
182 {
183 }
184 catch (OverflowException)
185 {
186 }
187
188 try
189 {
190 pos_x = (uint)Convert.ToInt32((string)requestData["position_x"]);
191 }
192 catch (ArgumentException)
193 {
194 }
195 catch (FormatException)
196 {
197 }
198 catch (OverflowException)
199 {
200 }
201 try
202 {
203 pos_y = (uint)Convert.ToInt32((string)requestData["position_y"]);
204 }
205 catch (ArgumentException)
206 {
207 }
208 catch (FormatException)
209 {
210 }
211 catch (OverflowException)
212 {
213 }
214 try
215 {
216 pos_z = (uint)Convert.ToInt32((string)requestData["position_z"]);
217 }
218 catch (ArgumentException)
219 {
220 }
221 catch (FormatException)
222 {
223 }
224 catch (OverflowException)
225 {
226 }
227
228 Position = new Vector3(pos_x, pos_y, pos_z);
229
230 string requestData3 = (string)requestData["binary_bucket"];
231 if (string.IsNullOrEmpty(requestData3))
232 {
233 binaryBucket = new byte[0];
234 }
235 else
236 {
237 binaryBucket = Convert.FromBase64String(requestData3);
238 }
239
240 // Create a New GridInstantMessageObject the the data
241 GridInstantMessage gim = new GridInstantMessage();
242 gim.fromAgentID = fromAgentID.Guid;
243 gim.fromAgentName = fromAgentName;
244 gim.fromGroup = fromGroup;
245 gim.imSessionID = imSessionID.Guid;
246 gim.RegionID = UUID.Zero.Guid; // RegionID.Guid;
247 gim.timestamp = timestamp;
248 gim.toAgentID = toAgentID.Guid;
249 gim.message = message;
250 gim.dialog = dialog;
251 gim.offline = offline;
252 gim.ParentEstateID = ParentEstateID;
253 gim.Position = Position;
254 gim.binaryBucket = binaryBucket;
255
256 successful = m_IMService.IncomingInstantMessage(gim);
257
258 }
259 }
260 catch (Exception e)
261 {
262 m_log.Error("[INSTANT MESSAGE]: Caught unexpected exception:", e);
263 successful = false;
264 }
265
266 //Send response back to region calling if it was successful
267 // calling region uses this to know when to look up a user's location again.
268 XmlRpcResponse resp = new XmlRpcResponse();
269 Hashtable respdata = new Hashtable();
270 if (successful)
271 respdata["success"] = "TRUE";
272 else
273 respdata["success"] = "FALSE";
274 resp.Value = respdata;
275
276 return resp;
277 }
278
279 }
280}
diff --git a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
index 0e8ce80..eb184a5 100644
--- a/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
+++ b/OpenSim/Server/Handlers/Hypergrid/UserAgentServerConnector.cs
@@ -52,15 +52,24 @@ namespace OpenSim.Server.Handlers.Hypergrid
52// MethodBase.GetCurrentMethod().DeclaringType); 52// MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 private IUserAgentService m_HomeUsersService; 54 private IUserAgentService m_HomeUsersService;
55 private string[] m_AuthorizedCallers;
56
57 private bool m_VerifyCallers = false;
55 58
56 public UserAgentServerConnector(IConfigSource config, IHttpServer server) : 59 public UserAgentServerConnector(IConfigSource config, IHttpServer server) :
60 this(config, server, null)
61 {
62 }
63
64 public UserAgentServerConnector(IConfigSource config, IHttpServer server, IFriendsSimConnector friendsConnector) :
57 base(config, server, String.Empty) 65 base(config, server, String.Empty)
58 { 66 {
59 IConfig gridConfig = config.Configs["UserAgentService"]; 67 IConfig gridConfig = config.Configs["UserAgentService"];
60 if (gridConfig != null) 68 if (gridConfig != null)
61 { 69 {
62 string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty); 70 string serviceDll = gridConfig.GetString("LocalServiceModule", string.Empty);
63 Object[] args = new Object[] { config }; 71
72 Object[] args = new Object[] { config, friendsConnector };
64 m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args); 73 m_HomeUsersService = ServerUtils.LoadPlugin<IUserAgentService>(serviceDll, args);
65 } 74 }
66 if (m_HomeUsersService == null) 75 if (m_HomeUsersService == null)
@@ -69,12 +78,24 @@ namespace OpenSim.Server.Handlers.Hypergrid
69 string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1"); 78 string loginServerIP = gridConfig.GetString("LoginServerIP", "127.0.0.1");
70 bool proxy = gridConfig.GetBoolean("HasProxy", false); 79 bool proxy = gridConfig.GetBoolean("HasProxy", false);
71 80
81 m_VerifyCallers = gridConfig.GetBoolean("VerifyCallers", false);
82 string csv = gridConfig.GetString("AuthorizedCallers", "127.0.0.1");
83 csv = csv.Replace(" ", "");
84 m_AuthorizedCallers = csv.Split(',');
85
72 server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false); 86 server.AddXmlRPCHandler("agent_is_coming_home", AgentIsComingHome, false);
73 server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false); 87 server.AddXmlRPCHandler("get_home_region", GetHomeRegion, false);
74 server.AddXmlRPCHandler("verify_agent", VerifyAgent, false); 88 server.AddXmlRPCHandler("verify_agent", VerifyAgent, false);
75 server.AddXmlRPCHandler("verify_client", VerifyClient, false); 89 server.AddXmlRPCHandler("verify_client", VerifyClient, false);
76 server.AddXmlRPCHandler("logout_agent", LogoutAgent, false); 90 server.AddXmlRPCHandler("logout_agent", LogoutAgent, false);
77 91
92 server.AddXmlRPCHandler("status_notification", StatusNotification, false);
93 server.AddXmlRPCHandler("get_online_friends", GetOnlineFriends, false);
94 server.AddXmlRPCHandler("get_server_urls", GetServerURLs, false);
95
96 server.AddXmlRPCHandler("locate_user", LocateUser, false);
97 server.AddXmlRPCHandler("get_uui", GetUUI, false);
98
78 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler); 99 server.AddHTTPHandler("/homeagent/", new HomeAgentHandler(m_HomeUsersService, loginServerIP, proxy).Handler);
79 } 100 }
80 101
@@ -194,5 +215,187 @@ namespace OpenSim.Server.Handlers.Hypergrid
194 215
195 } 216 }
196 217
218 public XmlRpcResponse StatusNotification(XmlRpcRequest request, IPEndPoint remoteClient)
219 {
220 Hashtable hash = new Hashtable();
221 hash["result"] = "false";
222
223 Hashtable requestData = (Hashtable)request.Params[0];
224 //string host = (string)requestData["host"];
225 //string portstr = (string)requestData["port"];
226 if (requestData.ContainsKey("userID") && requestData.ContainsKey("online"))
227 {
228 string userID_str = (string)requestData["userID"];
229 UUID userID = UUID.Zero;
230 UUID.TryParse(userID_str, out userID);
231 List<string> ids = new List<string>();
232 foreach (object key in requestData.Keys)
233 {
234 if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
235 ids.Add(requestData[key].ToString());
236 }
237 bool online = false;
238 bool.TryParse(requestData["online"].ToString(), out online);
239
240 hash["result"] = "true";
241
242 // let's spawn a thread for this, because it may take a long time...
243 Util.FireAndForget(delegate { m_HomeUsersService.StatusNotification(ids, userID, online); });
244 }
245
246 XmlRpcResponse response = new XmlRpcResponse();
247 response.Value = hash;
248 return response;
249
250 }
251
252 public XmlRpcResponse GetOnlineFriends(XmlRpcRequest request, IPEndPoint remoteClient)
253 {
254 Hashtable hash = new Hashtable();
255
256 Hashtable requestData = (Hashtable)request.Params[0];
257 //string host = (string)requestData["host"];
258 //string portstr = (string)requestData["port"];
259 if (requestData.ContainsKey("userID"))
260 {
261 string userID_str = (string)requestData["userID"];
262 UUID userID = UUID.Zero;
263 UUID.TryParse(userID_str, out userID);
264 List<string> ids = new List<string>();
265 foreach (object key in requestData.Keys)
266 {
267 if (key is string && ((string)key).StartsWith("friend_") && requestData[key] != null)
268 ids.Add(requestData[key].ToString());
269 }
270
271 List<UUID> online = m_HomeUsersService.GetOnlineFriends(userID, ids);
272 if (online.Count > 0)
273 {
274 int i = 0;
275 foreach (UUID id in online)
276 {
277 hash["friend_" + i.ToString()] = id.ToString();
278 i++;
279 }
280 }
281 else
282 hash["result"] = "No Friends Online";
283 }
284
285 XmlRpcResponse response = new XmlRpcResponse();
286 response.Value = hash;
287 return response;
288
289 }
290
291 public XmlRpcResponse GetServerURLs(XmlRpcRequest request, IPEndPoint remoteClient)
292 {
293 Hashtable hash = new Hashtable();
294
295 Hashtable requestData = (Hashtable)request.Params[0];
296 //string host = (string)requestData["host"];
297 //string portstr = (string)requestData["port"];
298 if (requestData.ContainsKey("userID"))
299 {
300 string userID_str = (string)requestData["userID"];
301 UUID userID = UUID.Zero;
302 UUID.TryParse(userID_str, out userID);
303
304 Dictionary<string, object> serverURLs = m_HomeUsersService.GetServerURLs(userID);
305 if (serverURLs.Count > 0)
306 {
307 foreach (KeyValuePair<string, object> kvp in serverURLs)
308 hash["SRV_" + kvp.Key] = kvp.Value.ToString();
309 }
310 else
311 hash["result"] = "No Service URLs";
312 }
313
314 XmlRpcResponse response = new XmlRpcResponse();
315 response.Value = hash;
316 return response;
317
318 }
319
320 /// <summary>
321 /// Locates the user.
322 /// This is a sensitive operation, only authorized IP addresses can perform it.
323 /// </summary>
324 /// <param name="request"></param>
325 /// <param name="remoteClient"></param>
326 /// <returns></returns>
327 public XmlRpcResponse LocateUser(XmlRpcRequest request, IPEndPoint remoteClient)
328 {
329 Hashtable hash = new Hashtable();
330
331 bool authorized = true;
332 if (m_VerifyCallers)
333 {
334 authorized = false;
335 foreach (string s in m_AuthorizedCallers)
336 if (s == remoteClient.Address.ToString())
337 {
338 authorized = true;
339 break;
340 }
341 }
342
343 if (authorized)
344 {
345 Hashtable requestData = (Hashtable)request.Params[0];
346 //string host = (string)requestData["host"];
347 //string portstr = (string)requestData["port"];
348 if (requestData.ContainsKey("userID"))
349 {
350 string userID_str = (string)requestData["userID"];
351 UUID userID = UUID.Zero;
352 UUID.TryParse(userID_str, out userID);
353
354 string url = m_HomeUsersService.LocateUser(userID);
355 if (url != string.Empty)
356 hash["URL"] = url;
357 }
358 }
359
360 XmlRpcResponse response = new XmlRpcResponse();
361 response.Value = hash;
362 return response;
363
364 }
365
366 /// <summary>
367 /// Locates the user.
368 /// This is a sensitive operation, only authorized IP addresses can perform it.
369 /// </summary>
370 /// <param name="request"></param>
371 /// <param name="remoteClient"></param>
372 /// <returns></returns>
373 public XmlRpcResponse GetUUI(XmlRpcRequest request, IPEndPoint remoteClient)
374 {
375 Hashtable hash = new Hashtable();
376
377 Hashtable requestData = (Hashtable)request.Params[0];
378 //string host = (string)requestData["host"];
379 //string portstr = (string)requestData["port"];
380 if (requestData.ContainsKey("userID") && requestData.ContainsKey("targetUserID"))
381 {
382 string userID_str = (string)requestData["userID"];
383 UUID userID = UUID.Zero;
384 UUID.TryParse(userID_str, out userID);
385
386 string tuserID_str = (string)requestData["targetUserID"];
387 UUID targetUserID = UUID.Zero;
388 UUID.TryParse(tuserID_str, out targetUserID);
389 string uui = m_HomeUsersService.GetUUI(userID, targetUserID);
390 if (uui != string.Empty)
391 hash["UUI"] = uui;
392 }
393
394 XmlRpcResponse response = new XmlRpcResponse();
395 response.Value = hash;
396 return response;
397
398 }
399
197 } 400 }
198} 401}
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 }