aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs4
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs18
-rw-r--r--OpenSim/Data/IPresenceData.cs23
-rw-r--r--OpenSim/Data/IUserAccountData.cs13
-rw-r--r--OpenSim/Data/MSSQL/MSSQLUserAccountData.cs10
-rw-r--r--OpenSim/Data/Migration.cs9
-rw-r--r--OpenSim/Data/MySQL/MySQLGenericTableHandler.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLPresenceData.cs149
-rw-r--r--OpenSim/Data/MySQL/MySQLUserAccountData.cs138
-rw-r--r--OpenSim/Data/MySQL/Resources/001_Friends.sql9
-rw-r--r--OpenSim/Data/MySQL/Resources/001_Presence.sql15
-rw-r--r--OpenSim/Data/MySQL/Resources/001_UserAccount.sql13
-rw-r--r--OpenSim/Data/MySQL/Resources/002_Friends.sql5
-rw-r--r--OpenSim/Data/MySQL/Resources/002_Presence.sql7
-rw-r--r--OpenSim/Data/MySQL/Resources/002_UserAccount.sql5
-rw-r--r--OpenSim/Data/MySQL/Resources/003_Presence.sql6
-rw-r--r--OpenSim/Data/MySQL/Resources/003_UserAccount.sql9
-rw-r--r--OpenSim/Data/Null/NullPresenceData.cs223
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs1064
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs60
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs57
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs70
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs78
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs381
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs56
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs64
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml14
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs200
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs84
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs164
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs104
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs (renamed from OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs)59
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs (renamed from OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs)6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IPresenceModule.cs10
-rw-r--r--OpenSim/Server/Base/ServerUtils.cs71
-rw-r--r--OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs14
-rw-r--r--OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs92
-rw-r--r--OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs196
-rw-r--r--OpenSim/Server/Handlers/UserAccounts/UserAccountServerConnector.cs61
-rw-r--r--OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs276
-rw-r--r--OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServiceConnector.cs16
-rw-r--r--OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs421
-rw-r--r--OpenSim/Services/Connectors/User/UserServiceConnector.cs114
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs287
-rw-r--r--OpenSim/Services/Interfaces/IPresenceService.cs68
-rw-r--r--OpenSim/Services/Interfaces/IUserService.cs80
-rw-r--r--OpenSim/Services/PresenceService/PresenceService.cs146
-rw-r--r--OpenSim/Services/PresenceService/PresenceServiceBase.cs2
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs (renamed from OpenSim/Services/UserService/UserService.cs)30
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountServiceBase.cs (renamed from OpenSim/Services/UserService/UserServiceBase.cs)19
51 files changed, 3012 insertions, 2016 deletions
diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
index 6fd3d30..1e85a22 100644
--- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
+++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs
@@ -102,8 +102,6 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
102 m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules..."); 102 m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules...");
103 m_log.Info("[LOADREGIONSPLUGIN]: DynamicTextureModule..."); 103 m_log.Info("[LOADREGIONSPLUGIN]: DynamicTextureModule...");
104 m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule()); 104 m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule());
105 m_log.Info("[LOADREGIONSPLUGIN]: InstantMessageModule...");
106 m_openSim.ModuleLoader.LoadDefaultSharedModule(new InstantMessageModule());
107 m_log.Info("[LOADREGIONSPLUGIN]: LoadImageURLModule..."); 105 m_log.Info("[LOADREGIONSPLUGIN]: LoadImageURLModule...");
108 m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule()); 106 m_openSim.ModuleLoader.LoadDefaultSharedModule(new LoadImageURLModule());
109 m_log.Info("[LOADREGIONSPLUGIN]: XMLRPCModule..."); 107 m_log.Info("[LOADREGIONSPLUGIN]: XMLRPCModule...");
@@ -217,4 +215,4 @@ namespace OpenSim.ApplicationPlugins.LoadRegions
217 } 215 }
218 } 216 }
219 } 217 }
220} \ No newline at end of file 218}
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
index 6c0c74d..2e883d6 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
@@ -65,9 +65,13 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
65 65
66 public void Initialise (OpenSimBase openSim) 66 public void Initialise (OpenSimBase openSim)
67 { 67 {
68 m_log.DebugFormat("[REGIONMODULES]: Initializing...");
69 m_openSim = openSim; 68 m_openSim = openSim;
70 openSim.ApplicationRegistry.RegisterInterface<IRegionModulesController>(this); 69 }
70
71 public void PostInitialise ()
72 {
73 m_log.DebugFormat("[REGIONMODULES]: Initializing...");
74 m_openSim.ApplicationRegistry.RegisterInterface<IRegionModulesController>(this);
71 75
72 // Who we are 76 // Who we are
73 string id = AddinManager.CurrentAddin.Id; 77 string id = AddinManager.CurrentAddin.Id;
@@ -81,9 +85,9 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
81 85
82 // The [Modules] section in the ini file 86 // The [Modules] section in the ini file
83 IConfig modulesConfig = 87 IConfig modulesConfig =
84 openSim.ConfigSource.Source.Configs["Modules"]; 88 m_openSim.ConfigSource.Source.Configs["Modules"];
85 if (modulesConfig == null) 89 if (modulesConfig == null)
86 modulesConfig = openSim.ConfigSource.Source.AddConfig("Modules"); 90 modulesConfig = m_openSim.ConfigSource.Source.AddConfig("Modules");
87 91
88 // Scan modules and load all that aren't disabled 92 // Scan modules and load all that aren't disabled
89 foreach (TypeExtensionNode node in 93 foreach (TypeExtensionNode node in
@@ -195,7 +199,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
195 199
196 // OK, we're up and running 200 // OK, we're up and running
197 m_sharedInstances.Add(module); 201 m_sharedInstances.Add(module);
198 module.Initialise(openSim.ConfigSource.Source); 202 module.Initialise(m_openSim.ConfigSource.Source);
199 } 203 }
200 204
201 // Immediately run PostInitialise on shared modules 205 // Immediately run PostInitialise on shared modules
@@ -205,10 +209,6 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
205 } 209 }
206 } 210 }
207 211
208 public void PostInitialise ()
209 {
210 }
211
212#endregion 212#endregion
213 213
214#region IPlugin implementation 214#region IPlugin implementation
diff --git a/OpenSim/Data/IPresenceData.cs b/OpenSim/Data/IPresenceData.cs
index e5a8ebd..71d0e31 100644
--- a/OpenSim/Data/IPresenceData.cs
+++ b/OpenSim/Data/IPresenceData.cs
@@ -32,25 +32,28 @@ using OpenSim.Framework;
32 32
33namespace OpenSim.Data 33namespace OpenSim.Data
34{ 34{
35 public struct PresenceData 35 // This MUST be a ref type!
36 public class PresenceData
36 { 37 {
37 public UUID UUID; 38 public string UserID;
38 public UUID currentRegion; 39 public UUID RegionID;
40 public UUID SessionID;
39 public Dictionary<string, string> Data; 41 public Dictionary<string, string> Data;
40 } 42 }
41 43
42 /// <summary> 44 /// <summary>
43 /// An interface for connecting to the authentication datastore 45 /// An interface for connecting to the presence datastore
44 /// </summary> 46 /// </summary>
45 public interface IPresenceData 47 public interface IPresenceData
46 { 48 {
47 bool Store(PresenceData data); 49 bool Store(PresenceData data);
48 50
49 PresenceData Get(UUID principalID); 51 PresenceData Get(UUID sessionID);
50 52 void LogoutRegionAgents(UUID regionID);
51 bool SetUserDataItem(UUID principalID, string item, string value); 53 bool ReportAgent(UUID sessionID, UUID regionID, string position, string lookAt);
52 bool SetRegionDataItem(UUID principalID, string item, string value); 54 bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt);
53 55 PresenceData[] Get(string field, string data);
54 bool Delete(UUID regionID); 56 void Prune(string userID);
57 bool Delete(string field, string val);
55 } 58 }
56} 59}
diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs
index 6bec188..5ebe7d3 100644
--- a/OpenSim/Data/IUserAccountData.cs
+++ b/OpenSim/Data/IUserAccountData.cs
@@ -36,20 +36,17 @@ namespace OpenSim.Data
36 { 36 {
37 public UUID PrincipalID; 37 public UUID PrincipalID;
38 public UUID ScopeID; 38 public UUID ScopeID;
39 public string FirstName;
40 public string LastName;
39 public Dictionary<string, object> Data; 41 public Dictionary<string, object> Data;
40 } 42 }
41 43
42 /// <summary> 44 /// <summary>
43 /// An interface for connecting to the authentication datastore 45 /// An interface for connecting to the user accounts datastore
44 /// </summary> 46 /// </summary>
45 public interface IUserAccountData 47 public interface IUserAccountData
46 { 48 {
47 UserAccountData Get(UUID principalID, UUID ScopeID); 49 UserAccountData[] Get(string[] fields, string[] values);
48 50 bool Store(UserAccountData data, UUID principalID, string token);
49 List<UserAccountData> Query(UUID principalID, UUID ScopeID, string query);
50
51 bool Store(UserAccountData data);
52
53 bool SetDataItem(UUID principalID, string item, string value);
54 } 51 }
55} 52}
diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
index 2d92cb1..01750d8 100644
--- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs
@@ -168,6 +168,11 @@ namespace OpenSim.Data.MSSQL
168 return true; 168 return true;
169 } 169 }
170 170
171 public bool Store(UserAccountData data, UUID principalID, string token)
172 {
173 return false;
174 }
175
171 public bool SetDataItem(UUID principalID, string item, string value) 176 public bool SetDataItem(UUID principalID, string item, string value)
172 { 177 {
173 string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item); 178 string sql = string.Format("update {0} set {1} = @{1} where UUID = @UUID", m_Realm, item);
@@ -184,5 +189,10 @@ namespace OpenSim.Data.MSSQL
184 } 189 }
185 return false; 190 return false;
186 } 191 }
192
193 public UserAccountData[] Get(string[] keys, string[] vals)
194 {
195 return null;
196 }
187 } 197 }
188} 198}
diff --git a/OpenSim/Data/Migration.cs b/OpenSim/Data/Migration.cs
index e51dc22..5a9b01b 100644
--- a/OpenSim/Data/Migration.cs
+++ b/OpenSim/Data/Migration.cs
@@ -138,7 +138,14 @@ namespace OpenSim.Data
138 cmd.CommandText = kvp.Value; 138 cmd.CommandText = kvp.Value;
139 // we need to up the command timeout to infinite as we might be doing long migrations. 139 // we need to up the command timeout to infinite as we might be doing long migrations.
140 cmd.CommandTimeout = 0; 140 cmd.CommandTimeout = 0;
141 cmd.ExecuteNonQuery(); 141 try
142 {
143 cmd.ExecuteNonQuery();
144 }
145 catch (Exception e)
146 {
147 m_log.Debug("[MIGRATIONS]: An error has occurred in the migration. This may mean you could see errors trying to run OpenSim. If you see database related errors, you will need to fix the issue manually. Continuing.");
148 }
142 149
143 if (version == 0) 150 if (version == 0)
144 { 151 {
diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
index b2bd5f6..873d6d4 100644
--- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
+++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs
@@ -177,6 +177,8 @@ namespace OpenSim.Data.MySQL
177 result.Add(row); 177 result.Add(row);
178 } 178 }
179 179
180 reader.Close();
181
180 CloseReaderCommand(cmd); 182 CloseReaderCommand(cmd);
181 183
182 return result.ToArray(); 184 return result.ToArray();
diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs
new file mode 100644
index 0000000..72b8a0c
--- /dev/null
+++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs
@@ -0,0 +1,149 @@
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.Data;
31using System.Reflection;
32using System.Threading;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using MySql.Data.MySqlClient;
37
38namespace OpenSim.Data.MySQL
39{
40 /// <summary>
41 /// A MySQL Interface for the Grid Server
42 /// </summary>
43 public class MySQLPresenceData : MySQLGenericTableHandler<PresenceData>,
44 IPresenceData
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public MySQLPresenceData(string connectionString, string realm) :
49 base(connectionString, realm, "Presence")
50 {
51 }
52
53 public PresenceData Get(UUID sessionID)
54 {
55 PresenceData[] ret = Get("SessionID",
56 sessionID.ToString());
57
58 if (ret.Length == 0)
59 return null;
60
61 return ret[0];
62 }
63
64 public void LogoutRegionAgents(UUID regionID)
65 {
66 MySqlCommand cmd = new MySqlCommand();
67
68 cmd.CommandText = String.Format("update {0} set Online='false' where `RegionID`=?RegionID", m_Realm);
69
70 cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
71
72 ExecuteNonQuery(cmd);
73 }
74
75 public bool ReportAgent(UUID sessionID, UUID regionID, string position,
76 string lookAt)
77 {
78 PresenceData[] pd = Get("SessionID", sessionID.ToString());
79 if (pd.Length == 0)
80 return false;
81
82 MySqlCommand cmd = new MySqlCommand();
83
84 cmd.CommandText = String.Format("update {0} set RegionID=?RegionID, Position=?Position, LookAt=?LookAt', Online='true' where `SessionID`=?SessionID", m_Realm);
85
86 cmd.Parameters.AddWithValue("?SessionID", sessionID.ToString());
87 cmd.Parameters.AddWithValue("?RegionID", regionID.ToString());
88 cmd.Parameters.AddWithValue("?Position", position);
89 cmd.Parameters.AddWithValue("?LookAt", lookAt);
90
91 if (ExecuteNonQuery(cmd) == 0)
92 return false;
93
94 return true;
95 }
96
97 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
98 {
99 PresenceData[] pd = Get("UserID", userID);
100 if (pd.Length == 0)
101 return false;
102
103 MySqlCommand cmd = new MySqlCommand();
104
105 cmd.CommandText = String.Format("update {0} set HomeRegionID=?HomeRegionID, HomePosition=?HomePosition, HomeLookAt=?HomeLookAt where UserID=?UserID", m_Realm);
106
107 cmd.Parameters.AddWithValue("?UserID", userID);
108 cmd.Parameters.AddWithValue("?HomeRegionID", regionID.ToString());
109 cmd.Parameters.AddWithValue("?HomePosition", position);
110 cmd.Parameters.AddWithValue("?HomeLookAt", lookAt);
111
112 if (ExecuteNonQuery(cmd) == 0)
113 return false;
114
115 return true;
116 }
117
118 public void Prune(string userID)
119 {
120 MySqlCommand cmd = new MySqlCommand();
121
122 cmd.CommandText = String.Format("select * from {0} where UserID=?UserID", m_Realm);
123
124 cmd.Parameters.AddWithValue("?UserID", userID);
125
126 IDataReader reader = ExecuteReader(cmd);
127
128 List<UUID> deleteSessions = new List<UUID>();
129 int online = 0;
130
131 while(reader.Read())
132 {
133 if (bool.Parse(reader["Online"].ToString()))
134 online++;
135 else
136 deleteSessions.Add(new UUID(reader["SessionID"].ToString()));
137 }
138
139 if (online == 0 && deleteSessions.Count > 0)
140 deleteSessions.RemoveAt(0);
141
142 reader.Close();
143 CloseReaderCommand(cmd);
144
145 foreach (UUID s in deleteSessions)
146 Delete("SessionID", s.ToString());
147 }
148 }
149}
diff --git a/OpenSim/Data/MySQL/MySQLUserAccountData.cs b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
index d48144d..e2ce6d1 100644
--- a/OpenSim/Data/MySQL/MySQLUserAccountData.cs
+++ b/OpenSim/Data/MySQL/MySQLUserAccountData.cs
@@ -35,146 +35,16 @@ using MySql.Data.MySqlClient;
35 35
36namespace OpenSim.Data.MySQL 36namespace OpenSim.Data.MySQL
37{ 37{
38 public class MySqlUserAccountData : MySqlFramework, IUserAccountData 38 public class MySqlUserAccountData : MySQLGenericTableHandler<UserAccountData>, IUserAccountData
39 { 39 {
40 private string m_Realm;
41 private List<string> m_ColumnNames = null;
42// private int m_LastExpire = 0;
43
44 public MySqlUserAccountData(string connectionString, string realm) 40 public MySqlUserAccountData(string connectionString, string realm)
45 : base(connectionString) 41 : base(connectionString, realm, "UserAccount")
46 {
47 m_Realm = realm;
48
49 Migration m = new Migration(m_Connection, GetType().Assembly, "UserStore");
50 m.Update();
51 }
52
53 public List<UserAccountData> Query(UUID principalID, UUID scopeID, string query)
54 { 42 {
55 return null;
56 }
57
58 public UserAccountData Get(UUID principalID, UUID scopeID)
59 {
60 UserAccountData ret = new UserAccountData();
61 ret.Data = new Dictionary<string, object>();
62
63 string command = "select * from `"+m_Realm+"` where UUID = ?principalID";
64 if (scopeID != UUID.Zero)
65 command += " and ScopeID = ?scopeID";
66
67 MySqlCommand cmd = new MySqlCommand(command);
68
69 cmd.Parameters.AddWithValue("?principalID", principalID.ToString());
70 cmd.Parameters.AddWithValue("?scopeID", scopeID.ToString());
71
72 IDataReader result = ExecuteReader(cmd);
73
74 if (result.Read())
75 {
76 ret.PrincipalID = principalID;
77 UUID scope;
78 UUID.TryParse(result["ScopeID"].ToString(), out scope);
79 ret.ScopeID = scope;
80
81 if (m_ColumnNames == null)
82 {
83 m_ColumnNames = new List<string>();
84
85 DataTable schemaTable = result.GetSchemaTable();
86 foreach (DataRow row in schemaTable.Rows)
87 m_ColumnNames.Add(row["ColumnName"].ToString());
88 }
89
90 foreach (string s in m_ColumnNames)
91 {
92 if (s == "UUID")
93 continue;
94 if (s == "ScopeID")
95 continue;
96
97 ret.Data[s] = result[s].ToString();
98 }
99
100 result.Close();
101 CloseReaderCommand(cmd);
102
103 return ret;
104 }
105
106 result.Close();
107 CloseReaderCommand(cmd);
108
109 return null;
110 } 43 }
111 44
112 public bool Store(UserAccountData data) 45 public bool Store(UserAccountData data, UUID principalID, string token)
113 { 46 {
114 if (data.Data.ContainsKey("UUID")) 47 return Store(data);
115 data.Data.Remove("UUID");
116 if (data.Data.ContainsKey("ScopeID"))
117 data.Data.Remove("ScopeID");
118
119 string[] fields = new List<string>(data.Data.Keys).ToArray();
120
121 MySqlCommand cmd = new MySqlCommand();
122
123 string update = "update `"+m_Realm+"` set ";
124 bool first = true;
125 foreach (string field in fields)
126 {
127 if (!first)
128 update += ", ";
129 update += "`" + field + "` = ?"+field;
130
131 first = false;
132
133 cmd.Parameters.AddWithValue("?"+field, data.Data[field]);
134 }
135
136 update += " where UUID = ?principalID";
137
138 if (data.ScopeID != UUID.Zero)
139 update += " and ScopeID = ?scopeID";
140
141 cmd.CommandText = update;
142 cmd.Parameters.AddWithValue("?principalID", data.PrincipalID.ToString());
143 cmd.Parameters.AddWithValue("?scopeID", data.ScopeID.ToString());
144
145 if (ExecuteNonQuery(cmd) < 1)
146 {
147 string insert = "insert into `" + m_Realm + "` (`UUID`, `ScopeID`, `" +
148 String.Join("`, `", fields) +
149 "`) values (?principalID, ?scopeID, ?" + String.Join(", ?", fields) + ")";
150
151 cmd.CommandText = insert;
152
153 if (ExecuteNonQuery(cmd) < 1)
154 {
155 cmd.Dispose();
156 return false;
157 }
158 }
159
160 cmd.Dispose();
161
162 return true;
163 }
164
165 public bool SetDataItem(UUID principalID, string item, string value)
166 {
167 MySqlCommand cmd = new MySqlCommand("update `" + m_Realm +
168 "` set `" + item + "` = ?" + item + " where UUID = ?UUID");
169
170
171 cmd.Parameters.AddWithValue("?"+item, value);
172 cmd.Parameters.AddWithValue("?UUID", principalID.ToString());
173
174 if (ExecuteNonQuery(cmd) > 0)
175 return true;
176
177 return false;
178 } 48 }
179 } 49 }
180} 50}
diff --git a/OpenSim/Data/MySQL/Resources/001_Friends.sql b/OpenSim/Data/MySQL/Resources/001_Friends.sql
new file mode 100644
index 0000000..e158a2c
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/001_Friends.sql
@@ -0,0 +1,9 @@
1BEGIN;
2
3CREATE TABLE `Friends` (
4 `PrincipalID` CHAR(36) NOT NULL,
5 `FriendID` VARCHAR(255) NOT NULL,
6 `Flags` CHAR(16) NOT NULL DEFAULT '0'
7) ENGINE=InnoDB;
8
9COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/001_Presence.sql b/OpenSim/Data/MySQL/Resources/001_Presence.sql
new file mode 100644
index 0000000..b8abaf7
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/001_Presence.sql
@@ -0,0 +1,15 @@
1BEGIN;
2
3CREATE TABLE `Presence` (
4 `UserID` VARCHAR(255) NOT NULL,
5 `RegionID` CHAR(36) NOT NULL,
6 `SessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
7 `SecureSessionID` CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
8 `Online` CHAR(5) NOT NULL DEFAULT 'false',
9 `Login` CHAR(16) NOT NULL DEFAULT '0',
10 `Logout` CHAR(16) NOT NULL DEFAULT '0',
11 `Position` CHAR(64) NOT NULL DEFAULT '<0,0,0>',
12 `LookAt` CHAR(64) NOT NULL DEFAULT '<0,0,0>'
13) ENGINE=InnoDB;
14
15COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/001_UserAccount.sql b/OpenSim/Data/MySQL/Resources/001_UserAccount.sql
new file mode 100644
index 0000000..07da571
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/001_UserAccount.sql
@@ -0,0 +1,13 @@
1BEGIN;
2
3CREATE TABLE `UserAccounts` (
4 `PrincipalID` CHAR(36) NOT NULL,
5 `ScopeID` CHAR(36) NOT NULL,
6 `FirstName` VARCHAR(64) NOT NULL,
7 `LastName` VARCHAR(64) NOT NULL,
8 `Email` VARCHAR(64),
9 `ServiceURLs` TEXT,
10 `Created` INT(11)
11) ENGINE=InnoDB DEFAULT CHARSET=utf8;
12
13COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/002_Friends.sql b/OpenSim/Data/MySQL/Resources/002_Friends.sql
new file mode 100644
index 0000000..5ff6438
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/002_Friends.sql
@@ -0,0 +1,5 @@
1BEGIN;
2
3INSERT INTO Friends (PrincipalID, FriendID, Flags) SELECT ownerID, friendID, friendPerms FROM userfriends;
4
5COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/002_Presence.sql b/OpenSim/Data/MySQL/Resources/002_Presence.sql
new file mode 100644
index 0000000..e65f105
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/002_Presence.sql
@@ -0,0 +1,7 @@
1BEGIN;
2
3ALTER TABLE Presence ADD COLUMN `HomeRegionID` CHAR(36) NOT NULL;
4ALTER TABLE Presence ADD COLUMN `HomePosition` CHAR(64) NOT NULL DEFAULT '<0,0,0>';
5ALTER TABLE Presence ADD COLUMN `HomeLookAt` CHAR(64) NOT NULL DEFAULT '<0,0,0>';
6
7COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/002_UserAccount.sql b/OpenSim/Data/MySQL/Resources/002_UserAccount.sql
new file mode 100644
index 0000000..ad2ddda
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/002_UserAccount.sql
@@ -0,0 +1,5 @@
1BEGIN;
2
3INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, lastname AS LastName, email as Email, CONCAT('AssetServerURI=', userAssetURI, ' InventoryServerURI=', userInventoryURI, ' GatewayURI= HomeURI=') AS ServiceURLs, created as Created FROM users;
4
5COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/003_Presence.sql b/OpenSim/Data/MySQL/Resources/003_Presence.sql
new file mode 100644
index 0000000..0efefa8
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/003_Presence.sql
@@ -0,0 +1,6 @@
1BEGIN;
2
3CREATE UNIQUE INDEX SessionID ON Presence(SessionID);
4CREATE INDEX UserID ON Presence(UserID);
5
6COMMIT;
diff --git a/OpenSim/Data/MySQL/Resources/003_UserAccount.sql b/OpenSim/Data/MySQL/Resources/003_UserAccount.sql
new file mode 100644
index 0000000..e42d93b
--- /dev/null
+++ b/OpenSim/Data/MySQL/Resources/003_UserAccount.sql
@@ -0,0 +1,9 @@
1BEGIN;
2
3CREATE UNIQUE INDEX PrincipalID ON UserAccounts(PrincipalID);
4CREATE INDEX Email ON UserAccounts(Email);
5CREATE INDEX FirstName ON UserAccounts(FirstName);
6CREATE INDEX LastName ON UserAccounts(LastName);
7CREATE INDEX Name ON UserAccounts(FirstName,LastName);
8
9COMMIT;
diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs
new file mode 100644
index 0000000..52fdc6f
--- /dev/null
+++ b/OpenSim/Data/Null/NullPresenceData.cs
@@ -0,0 +1,223 @@
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 OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Data;
34
35namespace OpenSim.Data.Null
36{
37 public class NullPresenceData : IPresenceData
38 {
39 Dictionary<UUID, PresenceData> m_presenceData = new Dictionary<UUID, PresenceData>();
40
41 public NullPresenceData(string connectionString, string realm)
42 {
43 //Console.WriteLine("[XXX] NullRegionData constructor");
44 // Let's stick in a test presence
45 PresenceData p = new PresenceData();
46 p.SessionID = UUID.Zero;
47 p.UserID = UUID.Zero.ToString();
48 p.Data = new Dictionary<string, string>();
49 p.Data["Online"] = "true";
50 m_presenceData.Add(UUID.Zero, p);
51 }
52
53 public bool Store(PresenceData data)
54 {
55 m_presenceData[data.SessionID] = data;
56 return true;
57 }
58
59 public PresenceData Get(UUID sessionID)
60 {
61 if (m_presenceData.ContainsKey(sessionID))
62 return m_presenceData[sessionID];
63
64 return null;
65 }
66
67 public void LogoutRegionAgents(UUID regionID)
68 {
69 List<UUID> toBeDeleted = new List<UUID>();
70 foreach (KeyValuePair<UUID, PresenceData> kvp in m_presenceData)
71 if (kvp.Value.RegionID == regionID)
72 toBeDeleted.Add(kvp.Key);
73
74 foreach (UUID u in toBeDeleted)
75 m_presenceData.Remove(u);
76 }
77
78 public bool ReportAgent(UUID sessionID, UUID regionID, string position, string lookAt)
79 {
80 if (m_presenceData.ContainsKey(sessionID))
81 {
82 m_presenceData[sessionID].RegionID = regionID;
83 m_presenceData[sessionID].Data["Position"] = position;
84 m_presenceData[sessionID].Data["LookAt"] = lookAt;
85 return true;
86 }
87
88 return false;
89 }
90
91 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
92 {
93 bool foundone = false;
94 foreach (PresenceData p in m_presenceData.Values)
95 {
96 if (p.UserID == userID)
97 {
98 p.Data["HomeRegionID"] = regionID.ToString();
99 p.Data["HomePosition"] = position.ToString();
100 p.Data["HomeLookAt"] = lookAt.ToString();
101 foundone = true;
102 }
103 }
104
105 return foundone;
106 }
107
108 public PresenceData[] Get(string field, string data)
109 {
110 List<PresenceData> presences = new List<PresenceData>();
111 if (field == "UserID")
112 {
113 foreach (PresenceData p in m_presenceData.Values)
114 if (p.UserID == data)
115 presences.Add(p);
116 return presences.ToArray();
117 }
118 else if (field == "SessionID")
119 {
120 UUID session = UUID.Zero;
121 if (!UUID.TryParse(data, out session))
122 return presences.ToArray();
123
124 if (m_presenceData.ContainsKey(session))
125 {
126 presences.Add(m_presenceData[session]);
127 return presences.ToArray();
128 }
129 }
130 else if (field == "RegionID")
131 {
132 UUID region = UUID.Zero;
133 if (!UUID.TryParse(data, out region))
134 return presences.ToArray();
135 foreach (PresenceData p in m_presenceData.Values)
136 if (p.RegionID == region)
137 presences.Add(p);
138 return presences.ToArray();
139 }
140 else
141 {
142 foreach (PresenceData p in m_presenceData.Values)
143 {
144 if (p.Data.ContainsKey(field) && p.Data[field] == data)
145 presences.Add(p);
146 }
147 return presences.ToArray();
148 }
149
150 return presences.ToArray();
151 }
152
153 public void Prune(string userID)
154 {
155 List<UUID> deleteSessions = new List<UUID>();
156 int online = 0;
157
158 foreach (KeyValuePair<UUID, PresenceData> kvp in m_presenceData)
159 {
160 bool on = false;
161 if (bool.TryParse(kvp.Value.Data["Online"], out on) && on)
162 online++;
163 else
164 deleteSessions.Add(kvp.Key);
165 }
166 if (online == 0 && deleteSessions.Count > 0)
167 deleteSessions.RemoveAt(0);
168
169 foreach (UUID s in deleteSessions)
170 m_presenceData.Remove(s);
171
172 }
173
174 public bool Delete(string field, string data)
175 {
176 List<UUID> presences = new List<UUID>();
177 if (field == "UserID")
178 {
179 foreach (KeyValuePair<UUID, PresenceData> p in m_presenceData)
180 if (p.Value.UserID == data)
181 presences.Add(p.Key);
182 }
183 else if (field == "SessionID")
184 {
185 UUID session = UUID.Zero;
186 if (UUID.TryParse(data, out session))
187 {
188 if (m_presenceData.ContainsKey(session))
189 {
190 presences.Add(session);
191 }
192 }
193 }
194 else if (field == "RegionID")
195 {
196 UUID region = UUID.Zero;
197 if (UUID.TryParse(data, out region))
198 {
199 foreach (KeyValuePair<UUID, PresenceData> p in m_presenceData)
200 if (p.Value.RegionID == region)
201 presences.Add(p.Key);
202 }
203 }
204 else
205 {
206 foreach (KeyValuePair<UUID, PresenceData> p in m_presenceData)
207 {
208 if (p.Value.Data.ContainsKey(field) && p.Value.Data[field] == data)
209 presences.Add(p.Key);
210 }
211 }
212
213 foreach (UUID u in presences)
214 m_presenceData.Remove(u);
215
216 if (presences.Count == 0)
217 return false;
218
219 return true;
220 }
221
222 }
223}
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index d6a82ef..f5d30b7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -44,1088 +44,50 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.CoreModules.Avatar.Friends 45namespace OpenSim.Region.CoreModules.Avatar.Friends
46{ 46{
47 /* 47 public class FriendsModule : ISharedRegionModule, IFriendsModule
48 This module handles adding/removing friends, and the the presence
49 notification process for login/logoff of friends.
50
51 The presence notification works as follows:
52 - After the user initially connects to a region (so we now have a UDP
53 connection to work with), this module fetches the friends of user
54 (those are cached), their on-/offline status, and info about the
55 region they are in from the MessageServer.
56 - (*) It then informs the user about the on-/offline status of her friends.
57 - It then informs all online friends currently on this region-server about
58 user's new online status (this will save some network traffic, as local
59 messages don't have to be transferred inter-region, and it will be all
60 that has to be done in Standalone Mode).
61 - For the rest of the online friends (those not on this region-server),
62 this module uses the provided region-information to map users to
63 regions, and sends one notification to every region containing the
64 friends to inform on that server.
65 - The region-server will handle that in the following way:
66 - If it finds the friend, it informs her about the user being online.
67 - If it doesn't find the friend (maybe she TPed away in the meantime),
68 it stores that information.
69 - After it processed all friends, it returns the list of friends it
70 couldn't find.
71 - If this list isn't empty, the FriendsModule re-requests information
72 about those online friends that have been missed and starts at (*)
73 again until all friends have been found, or until it tried 3 times
74 (to prevent endless loops due to some uncaught error).
75
76 NOTE: Online/Offline notifications don't need to be sent on region change.
77
78 We implement two XMLRpc handlers here, handling all the inter-region things
79 we have to handle:
80 - On-/Offline-Notifications (bulk)
81 - Terminate Friendship messages (single)
82 */
83
84 public class FriendsModule : IRegionModule, IFriendsModule
85 { 48 {
86 private class Transaction 49 public void Initialise(IConfigSource config)
87 { 50 {
88 public UUID agentID;
89 public string agentName;
90 public uint count;
91
92 public Transaction(UUID agentID, string agentName)
93 {
94 this.agentID = agentID;
95 this.agentName = agentName;
96 this.count = 1;
97 }
98 }
99
100 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
101
102 private Cache m_friendLists = new Cache(CacheFlags.AllowUpdate);
103
104 private Dictionary<UUID, ulong> m_rootAgents = new Dictionary<UUID, ulong>();
105
106 private Dictionary<UUID, UUID> m_pendingCallingcardRequests = new Dictionary<UUID,UUID>();
107
108 private Scene m_initialScene; // saves a lookup if we don't have a specific scene
109 private Dictionary<ulong, Scene> m_scenes = new Dictionary<ulong,Scene>();
110 private IMessageTransferModule m_TransferModule = null;
111
112 private IGridService m_gridServices = null;
113
114 #region IRegionModule Members
115
116 public void Initialise(Scene scene, IConfigSource config)
117 {
118 lock (m_scenes)
119 {
120 if (m_scenes.Count == 0)
121 {
122 MainServer.Instance.AddXmlRPCHandler("presence_update_bulk", processPresenceUpdateBulk);
123 MainServer.Instance.AddXmlRPCHandler("terminate_friend", processTerminateFriend);
124 m_friendLists.DefaultTTL = new TimeSpan(1, 0, 0); // store entries for one hour max
125 m_initialScene = scene;
126 }
127
128 if (!m_scenes.ContainsKey(scene.RegionInfo.RegionHandle))
129 m_scenes[scene.RegionInfo.RegionHandle] = scene;
130 }
131
132 scene.RegisterModuleInterface<IFriendsModule>(this);
133
134 scene.EventManager.OnNewClient += OnNewClient;
135 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
136 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
137 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
138 scene.EventManager.OnClientClosed += ClientClosed;
139 } 51 }
140 52
141 public void PostInitialise() 53 public void PostInitialise()
142 { 54 {
143 if (m_scenes.Count > 0)
144 {
145 m_TransferModule = m_initialScene.RequestModuleInterface<IMessageTransferModule>();
146 m_gridServices = m_initialScene.GridService;
147 }
148 if (m_TransferModule == null)
149 m_log.Error("[FRIENDS]: Unable to find a message transfer module, friendship offers will not work");
150 }
151
152 public void Close()
153 {
154 }
155
156 public string Name
157 {
158 get { return "FriendsModule"; }
159 }
160
161 public bool IsSharedModule
162 {
163 get { return true; }
164 }
165
166 #endregion
167
168 #region IInterregionFriendsComms
169
170 public List<UUID> InformFriendsInOtherRegion(UUID agentId, ulong destRegionHandle, List<UUID> friends, bool online)
171 {
172 List<UUID> tpdAway = new List<UUID>();
173
174 // destRegionHandle is a region on another server
175 uint x = 0, y = 0;
176 Utils.LongToUInts(destRegionHandle, out x, out y);
177 GridRegion info = m_gridServices.GetRegionByPosition(m_initialScene.RegionInfo.ScopeID, (int)x, (int)y);
178 if (info != null)
179 {
180 string httpServer = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/presence_update_bulk";
181
182 Hashtable reqParams = new Hashtable();
183 reqParams["agentID"] = agentId.ToString();
184 reqParams["agentOnline"] = online;
185 int count = 0;
186 foreach (UUID uuid in friends)
187 {
188 reqParams["friendID_" + count++] = uuid.ToString();
189 }
190 reqParams["friendCount"] = count;
191
192 IList parameters = new ArrayList();
193 parameters.Add(reqParams);
194 try
195 {
196 XmlRpcRequest request = new XmlRpcRequest("presence_update_bulk", parameters);
197 XmlRpcResponse response = request.Send(httpServer, 5000);
198 Hashtable respData = (Hashtable)response.Value;
199
200 count = (int)respData["friendCount"];
201 for (int i = 0; i < count; ++i)
202 {
203 UUID uuid;
204 if (UUID.TryParse((string)respData["friendID_" + i], out uuid)) tpdAway.Add(uuid);
205 }
206 }
207 catch (WebException e)
208 {
209 // Ignore connect failures, simulators come and go
210 //
211 if (!e.Message.Contains("ConnectFailure"))
212 {
213 m_log.Error("[OGS1 GRID SERVICES]: InformFriendsInOtherRegion XMLRPC failure: ", e);
214 }
215 }
216 catch (Exception e)
217 {
218 m_log.Error("[OGS1 GRID SERVICES]: InformFriendsInOtherRegion XMLRPC failure: ", e);
219 }
220 }
221 else m_log.WarnFormat("[OGS1 GRID SERVICES]: Couldn't find region {0}???", destRegionHandle);
222
223 return tpdAway;
224 }
225
226 public bool TriggerTerminateFriend(ulong destRegionHandle, UUID agentID, UUID exFriendID)
227 {
228 // destRegionHandle is a region on another server
229 uint x = 0, y = 0;
230 Utils.LongToUInts(destRegionHandle, out x, out y);
231 GridRegion info = m_gridServices.GetRegionByPosition(m_initialScene.RegionInfo.ScopeID, (int)x, (int)y);
232 if (info == null)
233 {
234 m_log.WarnFormat("[OGS1 GRID SERVICES]: Couldn't find region {0}", destRegionHandle);
235 return false; // region not found???
236 }
237
238 string httpServer = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/presence_update_bulk";
239
240 Hashtable reqParams = new Hashtable();
241 reqParams["agentID"] = agentID.ToString();
242 reqParams["friendID"] = exFriendID.ToString();
243
244 IList parameters = new ArrayList();
245 parameters.Add(reqParams);
246 try
247 {
248 XmlRpcRequest request = new XmlRpcRequest("terminate_friend", parameters);
249 XmlRpcResponse response = request.Send(httpServer, 5000);
250 Hashtable respData = (Hashtable)response.Value;
251
252 return (bool)respData["success"];
253 }
254 catch (Exception e)
255 {
256 m_log.Error("[OGS1 GRID SERVICES]: InformFriendsInOtherRegion XMLRPC failure: ", e);
257 return false;
258 }
259 }
260
261 #endregion
262
263 #region Incoming XMLRPC messages
264 /// <summary>
265 /// Receive presence information changes about clients in other regions.
266 /// </summary>
267 /// <param name="req"></param>
268 /// <returns></returns>
269 public XmlRpcResponse processPresenceUpdateBulk(XmlRpcRequest req, IPEndPoint remoteClient)
270 {
271 Hashtable requestData = (Hashtable)req.Params[0];
272
273 List<UUID> friendsNotHere = new List<UUID>();
274
275 // this is called with the expectation that all the friends in the request are on this region-server.
276 // But as some time passed since we checked (on the other region-server, via the MessagingServer),
277 // some of the friends might have teleported away.
278 // Actually, even now, between this line and the sending below, some people could TP away. So,
279 // we'll have to lock the m_rootAgents list for the duration to prevent/delay that.
280 lock (m_rootAgents)
281 {
282 List<ScenePresence> friendsHere = new List<ScenePresence>();
283
284 try
285 {
286 UUID agentID = new UUID((string)requestData["agentID"]);
287 bool agentOnline = (bool)requestData["agentOnline"];
288 int count = (int)requestData["friendCount"];
289 for (int i = 0; i < count; ++i)
290 {
291 UUID uuid;
292 if (UUID.TryParse((string)requestData["friendID_" + i], out uuid))
293 {
294 if (m_rootAgents.ContainsKey(uuid)) friendsHere.Add(GetRootPresenceFromAgentID(uuid));
295 else friendsNotHere.Add(uuid);
296 }
297 }
298
299 // now send, as long as they are still here...
300 UUID[] agentUUID = new UUID[] { agentID };
301 if (agentOnline)
302 {
303 foreach (ScenePresence agent in friendsHere)
304 {
305 agent.ControllingClient.SendAgentOnline(agentUUID);
306 }
307 }
308 else
309 {
310 foreach (ScenePresence agent in friendsHere)
311 {
312 agent.ControllingClient.SendAgentOffline(agentUUID);
313 }
314 }
315 }
316 catch(Exception e)
317 {
318 m_log.Warn("[FRIENDS]: Got exception while parsing presence_update_bulk request:", e);
319 }
320 }
321
322 // no need to lock anymore; if TPs happen now, worst case is that we have an additional agent in this region,
323 // which should be caught on the next iteration...
324 Hashtable result = new Hashtable();
325 int idx = 0;
326 foreach (UUID uuid in friendsNotHere)
327 {
328 result["friendID_" + idx++] = uuid.ToString();
329 }
330 result["friendCount"] = idx;
331
332 XmlRpcResponse response = new XmlRpcResponse();
333 response.Value = result;
334
335 return response;
336 }
337
338 public XmlRpcResponse processTerminateFriend(XmlRpcRequest req, IPEndPoint remoteClient)
339 {
340 Hashtable requestData = (Hashtable)req.Params[0];
341
342 bool success = false;
343
344 UUID agentID;
345 UUID friendID;
346 if (requestData.ContainsKey("agentID") && UUID.TryParse((string)requestData["agentID"], out agentID) &&
347 requestData.ContainsKey("friendID") && UUID.TryParse((string)requestData["friendID"], out friendID))
348 {
349 // try to find it and if it is there, prevent it to vanish before we sent the message
350 lock (m_rootAgents)
351 {
352 if (m_rootAgents.ContainsKey(agentID))
353 {
354 m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", friendID, agentID);
355 GetRootPresenceFromAgentID(agentID).ControllingClient.SendTerminateFriend(friendID);
356 success = true;
357 }
358 }
359 }
360
361 // return whether we were successful
362 Hashtable result = new Hashtable();
363 result["success"] = success;
364
365 XmlRpcResponse response = new XmlRpcResponse();
366 response.Value = result;
367 return response;
368 }
369
370 #endregion
371
372 #region Scene events
373
374 private void OnNewClient(IClientAPI client)
375 {
376 // All friends establishment protocol goes over instant message
377 // There's no way to send a message from the sim
378 // to a user to 'add a friend' without causing dialog box spam
379
380 // Subscribe to instant messages
381 client.OnInstantMessage += OnInstantMessage;
382
383 // Friend list management
384 client.OnApproveFriendRequest += OnApproveFriendRequest;
385 client.OnDenyFriendRequest += OnDenyFriendRequest;
386 client.OnTerminateFriendship += OnTerminateFriendship;
387
388 // ... calling card handling...
389 client.OnOfferCallingCard += OnOfferCallingCard;
390 client.OnAcceptCallingCard += OnAcceptCallingCard;
391 client.OnDeclineCallingCard += OnDeclineCallingCard;
392
393 // we need this one exactly once per agent session (see comments in the handler below)
394 client.OnEconomyDataRequest += OnEconomyDataRequest;
395
396 // if it leaves, we want to know, too
397 client.OnLogout += OnLogout;
398 client.OnGrantUserRights += GrantUserFriendRights;
399
400 }
401
402 private void ClientClosed(UUID AgentId, Scene scene)
403 {
404 // agent's client was closed. As we handle logout in OnLogout, this here has only to handle
405 // TPing away (root agent is closed) or TPing/crossing in a region far enough away (client
406 // agent is closed).
407 // NOTE: In general, this doesn't mean that the agent logged out, just that it isn't around
408 // in one of the regions here anymore.
409 lock (m_rootAgents)
410 {
411 if (m_rootAgents.ContainsKey(AgentId))
412 {
413 m_rootAgents.Remove(AgentId);
414 }
415 }
416 }
417
418 private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID)
419 {
420 lock (m_rootAgents)
421 {
422 m_rootAgents[avatar.UUID] = avatar.RegionHandle;
423 // Claim User! my user! Mine mine mine!
424 }
425 }
426
427 private void MakeChildAgent(ScenePresence avatar)
428 {
429 lock (m_rootAgents)
430 {
431 if (m_rootAgents.ContainsKey(avatar.UUID))
432 {
433 // only delete if the region matches. As this is a shared module, the avatar could be
434 // root agent in another region on this server.
435 if (m_rootAgents[avatar.UUID] == avatar.RegionHandle)
436 {
437 m_rootAgents.Remove(avatar.UUID);
438// m_log.Debug("[FRIEND]: Removing " + avatar.Firstname + " " + avatar.Lastname + " as a root agent");
439 }
440 }
441 }
442 }
443 #endregion
444
445 private ScenePresence GetRootPresenceFromAgentID(UUID AgentID)
446 {
447 ScenePresence returnAgent = null;
448 lock (m_scenes)
449 {
450 ScenePresence queryagent = null;
451 foreach (Scene scene in m_scenes.Values)
452 {
453 queryagent = scene.GetScenePresence(AgentID);
454 if (queryagent != null)
455 {
456 if (!queryagent.IsChildAgent)
457 {
458 returnAgent = queryagent;
459 break;
460 }
461 }
462 }
463 }
464 return returnAgent;
465 }
466
467 private ScenePresence GetAnyPresenceFromAgentID(UUID AgentID)
468 {
469 ScenePresence returnAgent = null;
470 lock (m_scenes)
471 {
472 ScenePresence queryagent = null;
473 foreach (Scene scene in m_scenes.Values)
474 {
475 queryagent = scene.GetScenePresence(AgentID);
476 if (queryagent != null)
477 {
478 returnAgent = queryagent;
479 break;
480 }
481 }
482 }
483 return returnAgent;
484 }
485
486 public void OfferFriendship(UUID fromUserId, IClientAPI toUserClient, string offerMessage)
487 {
488 CachedUserInfo userInfo = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(fromUserId);
489
490 if (userInfo != null)
491 {
492 GridInstantMessage msg = new GridInstantMessage(
493 toUserClient.Scene, fromUserId, userInfo.UserProfile.Name, toUserClient.AgentId,
494 (byte)InstantMessageDialog.FriendshipOffered, offerMessage, false, Vector3.Zero);
495
496 FriendshipOffered(msg);
497 }
498 else
499 {
500 m_log.ErrorFormat("[FRIENDS]: No user found for id {0} in OfferFriendship()", fromUserId);
501 }
502 }
503
504 #region FriendRequestHandling
505
506 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
507 {
508 // Friend Requests go by Instant Message.. using the dialog param
509 // https://wiki.secondlife.com/wiki/ImprovedInstantMessage
510
511 if (im.dialog == (byte)InstantMessageDialog.FriendshipOffered) // 38
512 {
513 // fromAgentName is the *destination* name (the friend we offer friendship to)
514 ScenePresence initiator = GetAnyPresenceFromAgentID(new UUID(im.fromAgentID));
515 im.fromAgentName = initiator != null ? initiator.Name : "(hippo)";
516
517 FriendshipOffered(im);
518 }
519 else if (im.dialog == (byte)InstantMessageDialog.FriendshipAccepted) // 39
520 {
521 FriendshipAccepted(client, im);
522 }
523 else if (im.dialog == (byte)InstantMessageDialog.FriendshipDeclined) // 40
524 {
525 FriendshipDeclined(client, im);
526 }
527 }
528
529 /// <summary>
530 /// Invoked when a user offers a friendship.
531 /// </summary>
532 ///
533 /// <param name="im"></param>
534 /// <param name="client"></param>
535 private void FriendshipOffered(GridInstantMessage im)
536 {
537 // this is triggered by the initiating agent:
538 // A local agent offers friendship to some possibly remote friend.
539 // A IM is triggered, processed here and sent to the friend (possibly in a remote region).
540
541 m_log.DebugFormat("[FRIEND]: Offer(38) - From: {0}, FromName: {1} To: {2}, Session: {3}, Message: {4}, Offline {5}",
542 im.fromAgentID, im.fromAgentName, im.toAgentID, im.imSessionID, im.message, im.offline);
543
544 // 1.20 protocol sends an UUID in the message field, instead of the friendship offer text.
545 // For interoperability, we have to clear that
546 if (Util.isUUID(im.message)) im.message = "";
547
548 // be sneeky and use the initiator-UUID as transactionID. This means we can be stateless.
549 // we have to look up the agent name on friendship-approval, though.
550 im.imSessionID = im.fromAgentID;
551
552 if (m_TransferModule != null)
553 {
554 // Send it to whoever is the destination.
555 // If new friend is local, it will send an IM to the viewer.
556 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
557 m_TransferModule.SendInstantMessage(
558 im,
559 delegate(bool success)
560 {
561 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
562 }
563 );
564 }
565 }
566
567 /// <summary>
568 /// Invoked when a user accepts a friendship offer.
569 /// </summary>
570 /// <param name="im"></param>
571 /// <param name="client"></param>
572 private void FriendshipAccepted(IClientAPI client, GridInstantMessage im)
573 {
574 m_log.DebugFormat("[FRIEND]: 39 - from client {0}, agent {2} {3}, imsession {4} to {5}: {6} (dialog {7})",
575 client.AgentId, im.fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
576 }
577
578 /// <summary>
579 /// Invoked when a user declines a friendship offer.
580 /// </summary>
581 /// May not currently be used - see OnDenyFriendRequest() instead
582 /// <param name="im"></param>
583 /// <param name="client"></param>
584 private void FriendshipDeclined(IClientAPI client, GridInstantMessage im)
585 {
586 UUID fromAgentID = new UUID(im.fromAgentID);
587 UUID toAgentID = new UUID(im.toAgentID);
588
589 // declining the friendship offer causes a type 40 IM being sent to the (possibly remote) initiator
590 // toAgentID is initiator, fromAgentID declined friendship
591 m_log.DebugFormat("[FRIEND]: 40 - from client {0}, agent {1} {2}, imsession {3} to {4}: {5} (dialog {6})",
592 client != null ? client.AgentId.ToString() : "<null>",
593 fromAgentID, im.fromAgentName, im.imSessionID, im.toAgentID, im.message, im.dialog);
594
595 // Send the decline to whoever is the destination.
596 GridInstantMessage msg
597 = new GridInstantMessage(
598 client.Scene, fromAgentID, client.Name, toAgentID,
599 im.dialog, im.message, im.offline != 0, im.Position);
600
601 // If new friend is local, it will send an IM to the viewer.
602 // If new friend is remote, it will cause a OnGridInstantMessage on the remote server
603 m_TransferModule.SendInstantMessage(msg,
604 delegate(bool success) {
605 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
606 }
607 );
608 }
609
610 private void OnGridInstantMessage(GridInstantMessage msg)
611 {
612 // This event won't be raised unless we have that agent,
613 // so we can depend on the above not trying to send
614 // via grid again
615 //m_log.DebugFormat("[FRIEND]: Got GridIM from {0}, to {1}, imSession {2}, message {3}, dialog {4}",
616 // msg.fromAgentID, msg.toAgentID, msg.imSessionID, msg.message, msg.dialog);
617
618 if (msg.dialog == (byte)InstantMessageDialog.FriendshipOffered ||
619 msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted ||
620 msg.dialog == (byte)InstantMessageDialog.FriendshipDeclined)
621 {
622 // this should succeed as we *know* the root agent is here.
623 m_TransferModule.SendInstantMessage(msg,
624 delegate(bool success) {
625 //m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
626 }
627 );
628 }
629
630 if (msg.dialog == (byte)InstantMessageDialog.FriendshipAccepted)
631 {
632 // for accept friendship, we have to do a bit more
633 ApproveFriendship(new UUID(msg.fromAgentID), new UUID(msg.toAgentID), msg.fromAgentName);
634 }
635 }
636
637 private void ApproveFriendship(UUID fromAgentID, UUID toAgentID, string fromName)
638 {
639 m_log.DebugFormat("[FRIEND]: Approve friendship from {0} (ID: {1}) to {2}",
640 fromAgentID, fromName, toAgentID);
641
642 // a new friend was added in the initiator's and friend's data, so the cache entries are wrong now.
643 lock (m_friendLists)
644 {
645 m_friendLists.Invalidate(fromAgentID.ToString());
646 m_friendLists.Invalidate(toAgentID.ToString());
647 }
648
649 // now send presence update and add a calling card for the new friend
650
651 ScenePresence initiator = GetAnyPresenceFromAgentID(toAgentID);
652 if (initiator == null)
653 {
654 // quite wrong. Shouldn't happen.
655 m_log.WarnFormat("[FRIEND]: Coudn't find initiator of friend request {0}", toAgentID);
656 return;
657 }
658
659 m_log.DebugFormat("[FRIEND]: Tell {0} that {1} is online",
660 initiator.Name, fromName);
661 // tell initiator that friend is online
662 initiator.ControllingClient.SendAgentOnline(new UUID[] { fromAgentID });
663
664 // find the folder for the friend...
665 //InventoryFolderImpl folder =
666 // initiator.Scene.CommsManager.UserProfileCacheService.GetUserDetails(toAgentID).FindFolderForType((int)InventoryType.CallingCard);
667 IInventoryService invService = initiator.Scene.InventoryService;
668 InventoryFolderBase folder = invService.GetFolderForType(toAgentID, AssetType.CallingCard);
669 if (folder != null)
670 {
671 // ... and add the calling card
672 CreateCallingCard(initiator.ControllingClient, fromAgentID, folder.ID, fromName);
673 }
674 } 55 }
675 56
676 private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) 57 public void AddRegion(Scene scene)
677 { 58 {
678 m_log.DebugFormat("[FRIEND]: Got approve friendship from {0} {1}, agentID {2}, tid {3}",
679 client.Name, client.AgentId, agentID, friendID);
680
681 // store the new friend persistently for both avatars
682 m_initialScene.StoreAddFriendship(friendID, agentID, (uint) FriendRights.CanSeeOnline);
683
684 // The cache entries aren't valid anymore either, as we just added a friend to both sides.
685 lock (m_friendLists)
686 {
687 m_friendLists.Invalidate(agentID.ToString());
688 m_friendLists.Invalidate(friendID.ToString());
689 }
690
691 // if it's a local friend, we don't have to do the lookup
692 ScenePresence friendPresence = GetAnyPresenceFromAgentID(friendID);
693
694 if (friendPresence != null)
695 {
696 m_log.Debug("[FRIEND]: Local agent detected.");
697
698 // create calling card
699 CreateCallingCard(client, friendID, callingCardFolders[0], friendPresence.Name);
700
701 // local message means OnGridInstantMessage won't be triggered, so do the work here.
702 friendPresence.ControllingClient.SendInstantMessage(
703 new GridInstantMessage(client.Scene, agentID,
704 client.Name, friendID,
705 (byte)InstantMessageDialog.FriendshipAccepted,
706 agentID.ToString(), false, Vector3.Zero));
707 ApproveFriendship(agentID, friendID, client.Name);
708 }
709 else
710 {
711 m_log.Debug("[FRIEND]: Remote agent detected.");
712
713 // fetch the friend's name for the calling card.
714 CachedUserInfo info = m_initialScene.CommsManager.UserProfileCacheService.GetUserDetails(friendID);
715
716 // create calling card
717 CreateCallingCard(client, friendID, callingCardFolders[0],
718 info.UserProfile.FirstName + " " + info.UserProfile.SurName);
719
720 // Compose (remote) response to friend.
721 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
722 (byte)InstantMessageDialog.FriendshipAccepted,
723 agentID.ToString(), false, Vector3.Zero);
724 if (m_TransferModule != null)
725 {
726 m_TransferModule.SendInstantMessage(msg,
727 delegate(bool success) {
728 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
729 }
730 );
731 }
732 }
733
734 // tell client that new friend is online
735 client.SendAgentOnline(new UUID[] { friendID });
736 } 59 }
737 60
738 private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List<UUID> callingCardFolders) 61 public void RegionLoaded(Scene scene)
739 { 62 {
740 m_log.DebugFormat("[FRIEND]: Got deny friendship from {0} {1}, agentID {2}, tid {3}",
741 client.Name, client.AgentId, agentID, friendID);
742
743 // Compose response to other agent.
744 GridInstantMessage msg = new GridInstantMessage(client.Scene, agentID, client.Name, friendID,
745 (byte)InstantMessageDialog.FriendshipDeclined,
746 agentID.ToString(), false, Vector3.Zero);
747 // send decline to initiator
748 if (m_TransferModule != null)
749 {
750 m_TransferModule.SendInstantMessage(msg,
751 delegate(bool success) {
752 m_log.DebugFormat("[FRIEND]: sending IM success = {0}", success);
753 }
754 );
755 }
756 } 63 }
757 64
758 private void OnTerminateFriendship(IClientAPI client, UUID agentID, UUID exfriendID) 65 public void RemoveRegion(Scene scene)
759 { 66 {
760 // client.AgentId == agentID!
761
762 // this removes the friends from the stored friendlists. After the next login, they will be gone...
763 m_initialScene.StoreRemoveFriendship(agentID, exfriendID);
764
765 // ... now tell the two involved clients that they aren't friends anymore.
766
767 // I don't know why we have to tell <agent>, as this was caused by her, but that's how it works in SL...
768 client.SendTerminateFriend(exfriendID);
769
770 // now send the friend, if online
771 ScenePresence presence = GetAnyPresenceFromAgentID(exfriendID);
772 if (presence != null)
773 {
774 m_log.DebugFormat("[FRIEND]: Sending terminate friend {0} to agent {1}", agentID, exfriendID);
775 presence.ControllingClient.SendTerminateFriend(agentID);
776 }
777 else
778 {
779 // retry 3 times, in case the agent TPed from the last known region...
780 for (int retry = 0; retry < 3; ++retry)
781 {
782 // wasn't sent, so ex-friend wasn't around on this region-server. Fetch info and try to send
783 UserAgentData data = m_initialScene.CommsManager.UserService.GetAgentByUUID(exfriendID);
784
785 if (null == data)
786 break;
787
788 if (!data.AgentOnline)
789 {
790 m_log.DebugFormat("[FRIEND]: {0} is offline, so not sending TerminateFriend", exfriendID);
791 break; // if ex-friend isn't online, we don't need to send
792 }
793
794 m_log.DebugFormat("[FRIEND]: Sending remote terminate friend {0} to agent {1}@{2}",
795 agentID, exfriendID, data.Handle);
796
797 // try to send to foreign region, retry if it fails (friend TPed away, for example)
798 if (TriggerTerminateFriend(data.Handle, exfriendID, agentID)) break;
799 }
800 }
801
802 // clean up cache: FriendList is wrong now...
803 lock (m_friendLists)
804 {
805 m_friendLists.Invalidate(agentID.ToString());
806 m_friendLists.Invalidate(exfriendID.ToString());
807 }
808 } 67 }
809 68
810 #endregion 69 public void Close()
811
812 #region CallingCards
813
814 private void OnOfferCallingCard(IClientAPI client, UUID destID, UUID transactionID)
815 {
816 m_log.DebugFormat("[CALLING CARD]: got offer from {0} for {1}, transaction {2}",
817 client.AgentId, destID, transactionID);
818 // This might be slightly wrong. On a multi-region server, we might get the child-agent instead of the root-agent
819 // (or the root instead of the child)
820 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
821 if (destAgent == null)
822 {
823 client.SendAlertMessage("The person you have offered a card to can't be found anymore.");
824 return;
825 }
826
827 lock (m_pendingCallingcardRequests)
828 {
829 m_pendingCallingcardRequests[transactionID] = client.AgentId;
830 }
831 // inform the destination agent about the offer
832 destAgent.ControllingClient.SendOfferCallingCard(client.AgentId, transactionID);
833 }
834
835 private void CreateCallingCard(IClientAPI client, UUID creator, UUID folder, string name)
836 {
837 InventoryItemBase item = new InventoryItemBase();
838 item.AssetID = UUID.Zero;
839 item.AssetType = (int)AssetType.CallingCard;
840 item.BasePermissions = (uint)PermissionMask.Copy;
841 item.CreationDate = Util.UnixTimeSinceEpoch();
842 item.CreatorId = creator.ToString();
843 item.CurrentPermissions = item.BasePermissions;
844 item.Description = "";
845 item.EveryOnePermissions = (uint)PermissionMask.None;
846 item.Flags = 0;
847 item.Folder = folder;
848 item.GroupID = UUID.Zero;
849 item.GroupOwned = false;
850 item.ID = UUID.Random();
851 item.InvType = (int)InventoryType.CallingCard;
852 item.Name = name;
853 item.NextPermissions = item.EveryOnePermissions;
854 item.Owner = client.AgentId;
855 item.SalePrice = 10;
856 item.SaleType = (byte)SaleType.Not;
857 ((Scene)client.Scene).AddInventoryItem(client, item);
858 }
859
860 private void OnAcceptCallingCard(IClientAPI client, UUID transactionID, UUID folderID)
861 {
862 m_log.DebugFormat("[CALLING CARD]: User {0} ({1} {2}) accepted tid {3}, folder {4}",
863 client.AgentId,
864 client.FirstName, client.LastName,
865 transactionID, folderID);
866 UUID destID;
867 lock (m_pendingCallingcardRequests)
868 {
869 if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID))
870 {
871 m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.",
872 client.Name);
873 return;
874 }
875 // else found pending calling card request with that transaction.
876 m_pendingCallingcardRequests.Remove(transactionID);
877 }
878
879
880 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
881 // inform sender of the card that destination declined the offer
882 if (destAgent != null) destAgent.ControllingClient.SendAcceptCallingCard(transactionID);
883
884 // put a calling card into the inventory of receiver
885 CreateCallingCard(client, destID, folderID, destAgent.Name);
886 }
887
888 private void OnDeclineCallingCard(IClientAPI client, UUID transactionID)
889 { 70 {
890 m_log.DebugFormat("[CALLING CARD]: User {0} (ID:{1}) declined card, tid {2}",
891 client.Name, client.AgentId, transactionID);
892 UUID destID;
893 lock (m_pendingCallingcardRequests)
894 {
895 if (!m_pendingCallingcardRequests.TryGetValue(transactionID, out destID))
896 {
897 m_log.WarnFormat("[CALLING CARD]: Got a AcceptCallingCard from {0} without an offer before.",
898 client.Name);
899 return;
900 }
901 // else found pending calling card request with that transaction.
902 m_pendingCallingcardRequests.Remove(transactionID);
903 }
904
905 ScenePresence destAgent = GetAnyPresenceFromAgentID(destID);
906 // inform sender of the card that destination declined the offer
907 if (destAgent != null) destAgent.ControllingClient.SendDeclineCallingCard(transactionID);
908 } 71 }
909 72
910 /// <summary> 73 public string Name
911 /// Send presence information about a client to other clients in both this region and others.
912 /// </summary>
913 /// <param name="client"></param>
914 /// <param name="friendList"></param>
915 /// <param name="iAmOnline"></param>
916 private void SendPresenceState(IClientAPI client, List<FriendListItem> friendList, bool iAmOnline)
917 { 74 {
918 //m_log.DebugFormat("[FRIEND]: {0} logged {1}; sending presence updates", client.Name, iAmOnline ? "in" : "out"); 75 get { return "FriendsModule"; }
919
920 if (friendList == null || friendList.Count == 0)
921 {
922 //m_log.DebugFormat("[FRIEND]: {0} doesn't have friends.", client.Name);
923 return; // nothing we can do if she doesn't have friends...
924 }
925
926 // collect sets of friendIDs; to send to (online and offline), and to receive from
927 // TODO: If we ever switch to .NET >= 3, replace those Lists with HashSets.
928 // I can't believe that we have Dictionaries, but no Sets, considering Java introduced them years ago...
929 List<UUID> friendIDsToSendTo = new List<UUID>();
930 List<UUID> candidateFriendIDsToReceive = new List<UUID>();
931
932 foreach (FriendListItem item in friendList)
933 {
934 if (((item.FriendListOwnerPerms | item.FriendPerms) & (uint)FriendRights.CanSeeOnline) != 0)
935 {
936 // friend is allowed to see my presence => add
937 if ((item.FriendListOwnerPerms & (uint)FriendRights.CanSeeOnline) != 0)
938 friendIDsToSendTo.Add(item.Friend);
939
940 if ((item.FriendPerms & (uint)FriendRights.CanSeeOnline) != 0)
941 candidateFriendIDsToReceive.Add(item.Friend);
942 }
943 }
944
945 // we now have a list of "interesting" friends (which we have to find out on-/offline state for),
946 // friends we want to send our online state to (if *they* are online, too), and
947 // friends we want to receive online state for (currently unknown whether online or not)
948
949 // as this processing might take some time and friends might TP away, we try up to three times to
950 // reach them. Most of the time, we *will* reach them, and this loop won't loop
951 int retry = 0;
952 do
953 {
954 // build a list of friends to look up region-information and on-/offline-state for
955 List<UUID> friendIDsToLookup = new List<UUID>(friendIDsToSendTo);
956 foreach (UUID uuid in candidateFriendIDsToReceive)
957 {
958 if (!friendIDsToLookup.Contains(uuid)) friendIDsToLookup.Add(uuid);
959 }
960
961 m_log.DebugFormat(
962 "[FRIEND]: {0} to lookup, {1} to send to, {2} candidates to receive from for agent {3}",
963 friendIDsToLookup.Count, friendIDsToSendTo.Count, candidateFriendIDsToReceive.Count, client.Name);
964
965 // we have to fetch FriendRegionInfos, as the (cached) FriendListItems don't
966 // necessarily contain the correct online state...
967 Dictionary<UUID, FriendRegionInfo> friendRegions = m_initialScene.GetFriendRegionInfos(friendIDsToLookup);
968 m_log.DebugFormat(
969 "[FRIEND]: Found {0} regionInfos for {1} friends of {2}",
970 friendRegions.Count, friendIDsToLookup.Count, client.Name);
971
972 // argument for SendAgentOn/Offline; we shouldn't generate that repeatedly within loops.
973 UUID[] agentArr = new UUID[] { client.AgentId };
974
975 // first, send to friend presence state to me, if I'm online...
976 if (iAmOnline)
977 {
978 List<UUID> friendIDsToReceive = new List<UUID>();
979
980 for (int i = candidateFriendIDsToReceive.Count - 1; i >= 0; --i)
981 {
982 UUID uuid = candidateFriendIDsToReceive[i];
983 FriendRegionInfo info;
984 if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline)
985 {
986 friendIDsToReceive.Add(uuid);
987 }
988 }
989
990 m_log.DebugFormat(
991 "[FRIEND]: Sending {0} online friends to {1}", friendIDsToReceive.Count, client.Name);
992
993 if (friendIDsToReceive.Count > 0)
994 client.SendAgentOnline(friendIDsToReceive.ToArray());
995
996 // clear them for a possible second iteration; we don't have to repeat this
997 candidateFriendIDsToReceive.Clear();
998 }
999
1000 // now, send my presence state to my friends
1001 for (int i = friendIDsToSendTo.Count - 1; i >= 0; --i)
1002 {
1003 UUID uuid = friendIDsToSendTo[i];
1004 FriendRegionInfo info;
1005 if (friendRegions.TryGetValue(uuid, out info) && info != null && info.isOnline)
1006 {
1007 // any client is good enough, root or child...
1008 ScenePresence agent = GetAnyPresenceFromAgentID(uuid);
1009 if (agent != null)
1010 {
1011 //m_log.DebugFormat("[FRIEND]: Found local agent {0}", agent.Name);
1012
1013 // friend is online and on this server...
1014 if (iAmOnline) agent.ControllingClient.SendAgentOnline(agentArr);
1015 else agent.ControllingClient.SendAgentOffline(agentArr);
1016
1017 // done, remove it
1018 friendIDsToSendTo.RemoveAt(i);
1019 }
1020 }
1021 else
1022 {
1023 //m_log.DebugFormat("[FRIEND]: Friend {0} ({1}) is offline; not sending.", uuid, i);
1024
1025 // friend is offline => no need to try sending
1026 friendIDsToSendTo.RemoveAt(i);
1027 }
1028 }
1029
1030 m_log.DebugFormat("[FRIEND]: Have {0} friends to contact via inter-region comms.", friendIDsToSendTo.Count);
1031
1032 // we now have all the friends left that are online (we think), but not on this region-server
1033 if (friendIDsToSendTo.Count > 0)
1034 {
1035 // sort them into regions
1036 Dictionary<ulong, List<UUID>> friendsInRegion = new Dictionary<ulong,List<UUID>>();
1037 foreach (UUID uuid in friendIDsToSendTo)
1038 {
1039 ulong handle = friendRegions[uuid].regionHandle; // this can't fail as we filtered above already
1040 List<UUID> friends;
1041 if (!friendsInRegion.TryGetValue(handle, out friends))
1042 {
1043 friends = new List<UUID>();
1044 friendsInRegion[handle] = friends;
1045 }
1046 friends.Add(uuid);
1047 }
1048 m_log.DebugFormat("[FRIEND]: Found {0} regions to send to.", friendRegions.Count);
1049
1050 // clear uuids list and collect missed friends in it for the next retry
1051 friendIDsToSendTo.Clear();
1052
1053 // send bulk updates to the region
1054 foreach (KeyValuePair<ulong, List<UUID>> pair in friendsInRegion)
1055 {
1056 //m_log.DebugFormat("[FRIEND]: Inform {0} friends in region {1} that user {2} is {3}line",
1057 // pair.Value.Count, pair.Key, client.Name, iAmOnline ? "on" : "off");
1058
1059 friendIDsToSendTo.AddRange(InformFriendsInOtherRegion(client.AgentId, pair.Key, pair.Value, iAmOnline));
1060 }
1061 }
1062 // now we have in friendIDsToSendTo only the agents left that TPed away while we tried to contact them.
1063 // In most cases, it will be empty, and it won't loop here. But sometimes, we have to work harder and try again...
1064 }
1065 while (++retry < 3 && friendIDsToSendTo.Count > 0);
1066 } 76 }
1067 77
1068 private void OnEconomyDataRequest(UUID agentID) 78 public Type ReplaceableInterface
1069 { 79 {
1070 // KLUDGE: This is the only way I found to get a message (only) after login was completed and the 80 get { return null; }
1071 // client is connected enough to receive UDP packets).
1072 // This packet seems to be sent only once, just after connection was established to the first
1073 // region after login.
1074 // We use it here to trigger a presence update; the old update-on-login was never be heard by
1075 // the freshly logged in viewer, as it wasn't connected to the region at that time.
1076 // TODO: Feel free to replace this by a better solution if you find one.
1077
1078 // get the agent. This should work every time, as we just got a packet from it
1079 //ScenePresence agent = GetRootPresenceFromAgentID(agentID);
1080 // KLUDGE 2: As this is sent quite early, the avatar isn't here as root agent yet. So, we have to cheat a bit
1081 ScenePresence agent = GetAnyPresenceFromAgentID(agentID);
1082
1083 // just to be paranoid...
1084 if (agent == null)
1085 {
1086 m_log.ErrorFormat("[FRIEND]: Got a packet from agent {0} who can't be found anymore!?", agentID);
1087 return;
1088 }
1089
1090 List<FriendListItem> fl;
1091 lock (m_friendLists)
1092 {
1093 fl = (List<FriendListItem>)m_friendLists.Get(agent.ControllingClient.AgentId.ToString(),
1094 m_initialScene.GetFriendList);
1095 }
1096
1097 // tell everyone that we are online
1098 SendPresenceState(agent.ControllingClient, fl, true);
1099 } 81 }
1100 82
1101 private void OnLogout(IClientAPI remoteClient) 83 public void OfferFriendship(UUID fromUserId, IClientAPI toUserClient,
84 string offerMessage)
1102 { 85 {
1103 List<FriendListItem> fl;
1104 lock (m_friendLists)
1105 {
1106 fl = (List<FriendListItem>)m_friendLists.Get(remoteClient.AgentId.ToString(),
1107 m_initialScene.GetFriendList);
1108 }
1109
1110 // tell everyone that we are offline
1111 SendPresenceState(remoteClient, fl, false);
1112 }
1113 private void GrantUserFriendRights(IClientAPI remoteClient, UUID requester, UUID target, int rights)
1114 {
1115 ((Scene)remoteClient.Scene).CommsManager.UpdateUserFriendPerms(requester, target, (uint)rights);
1116 } 86 }
1117 87
1118 public List<FriendListItem> GetUserFriends(UUID agentID) 88 public List<FriendListItem> GetUserFriends(UUID agentID)
1119 { 89 {
1120 List<FriendListItem> fl; 90 return null;
1121 lock (m_friendLists)
1122 {
1123 fl = (List<FriendListItem>)m_friendLists.Get(agentID.ToString(),
1124 m_initialScene.GetFriendList);
1125 }
1126
1127 return fl;
1128 } 91 }
1129 } 92 }
1130 #endregion
1131} 93}
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
index 9a68749..ab141eb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs
@@ -24,6 +24,7 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System;
27using System.Collections.Generic; 28using System.Collections.Generic;
28using System.Reflection; 29using System.Reflection;
29using log4net; 30using log4net;
@@ -36,9 +37,10 @@ using OpenSim.Region.Framework.Scenes;
36 37
37namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 38namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
38{ 39{
39 public class InstantMessageModule : IRegionModule 40 public class InstantMessageModule : ISharedRegionModule
40 { 41 {
41 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(
43 MethodBase.GetCurrentMethod().DeclaringType);
42 44
43 /// <value> 45 /// <value>
44 /// Is this module enabled? 46 /// Is this module enabled?
@@ -51,7 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
51 53
52 private IMessageTransferModule m_TransferModule = null; 54 private IMessageTransferModule m_TransferModule = null;
53 55
54 public void Initialise(Scene scene, IConfigSource config) 56 public void Initialise(IConfigSource config)
55 { 57 {
56 if (config.Configs["Messaging"] != null) 58 if (config.Configs["Messaging"] != null)
57 { 59 {
@@ -62,6 +64,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
62 } 64 }
63 65
64 m_enabled = true; 66 m_enabled = true;
67 }
68
69 public void AddRegion(Scene scene)
70 {
71 if (!m_enabled)
72 return;
65 73
66 lock (m_scenes) 74 lock (m_scenes)
67 { 75 {
@@ -74,6 +82,39 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
74 } 82 }
75 } 83 }
76 84
85 public void RegionLoaded(Scene scene)
86 {
87 if (!m_enabled)
88 return;
89
90 if (m_TransferModule == null)
91 {
92 m_TransferModule =
93 scene.RequestModuleInterface<IMessageTransferModule>();
94
95 if (m_TransferModule == null)
96 {
97 m_log.Error("[INSTANT MESSAGE]: No message transfer module, IM will not work!");
98 scene.EventManager.OnClientConnect -= OnClientConnect;
99 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
100
101 m_scenes.Clear();
102 m_enabled = false;
103 }
104 }
105 }
106
107 public void RemoveRegion(Scene scene)
108 {
109 if (!m_enabled)
110 return;
111
112 lock (m_scenes)
113 {
114 m_scenes.Remove(scene);
115 }
116 }
117
77 void OnClientConnect(IClientCore client) 118 void OnClientConnect(IClientCore client)
78 { 119 {
79 IClientIM clientIM; 120 IClientIM clientIM;
@@ -85,15 +126,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
85 126
86 public void PostInitialise() 127 public void PostInitialise()
87 { 128 {
88 if (!m_enabled)
89 return;
90
91 m_TransferModule =
92 m_scenes[0].RequestModuleInterface<IMessageTransferModule>();
93
94 if (m_TransferModule == null)
95 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
96 "IM will not work!");
97 } 129 }
98 130
99 public void Close() 131 public void Close()
@@ -105,9 +137,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
105 get { return "InstantMessageModule"; } 137 get { return "InstantMessageModule"; }
106 } 138 }
107 139
108 public bool IsSharedModule 140 public Type ReplaceableInterface
109 { 141 {
110 get { return true; } 142 get { return null; }
111 } 143 }
112 144
113 #endregion 145 #endregion
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index e5159b3..2d4b421 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -40,18 +40,17 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40 40
41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
42{ 42{
43 public class MessageTransferModule : IRegionModule, IMessageTransferModule 43 public class MessageTransferModule : ISharedRegionModule, IMessageTransferModule
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 // private bool m_Enabled = false; 47 private bool m_Enabled = false;
48 protected bool m_Gridmode = false;
49 protected List<Scene> m_Scenes = new List<Scene>(); 48 protected List<Scene> m_Scenes = new List<Scene>();
50 protected Dictionary<UUID, ulong> m_UserRegionMap = new Dictionary<UUID, ulong>(); 49 protected Dictionary<UUID, ulong> m_UserRegionMap = new Dictionary<UUID, ulong>();
51 50
52 public event UndeliveredMessage OnUndeliveredMessage; 51 public event UndeliveredMessage OnUndeliveredMessage;
53 52
54 public virtual void Initialise(Scene scene, IConfigSource config) 53 public virtual void Initialise(IConfigSource config)
55 { 54 {
56 IConfig cnf = config.Configs["Messaging"]; 55 IConfig cnf = config.Configs["Messaging"];
57 if (cnf != null && cnf.GetString( 56 if (cnf != null && cnf.GetString(
@@ -62,20 +61,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
62 return; 61 return;
63 } 62 }
64 63
65 cnf = config.Configs["Startup"]; 64 m_Enabled = true;
66 if (cnf != null) 65 }
67 m_Gridmode = cnf.GetBoolean("gridmode", false);
68 66
69 // m_Enabled = true; 67 public virtual void AddRegion(Scene scene)
68 {
69 if (!m_Enabled)
70 return;
70 71
71 lock (m_Scenes) 72 lock (m_Scenes)
72 { 73 {
73 if (m_Scenes.Count == 0)
74 {
75 MainServer.Instance.AddXmlRPCHandler(
76 "grid_instant_message", processXMLRPCGridInstantMessage);
77 }
78
79 m_log.Debug("[MESSAGE TRANSFER]: Message transfer module active"); 74 m_log.Debug("[MESSAGE TRANSFER]: Message transfer module active");
80 scene.RegisterModuleInterface<IMessageTransferModule>(this); 75 scene.RegisterModuleInterface<IMessageTransferModule>(this);
81 m_Scenes.Add(scene); 76 m_Scenes.Add(scene);
@@ -84,6 +79,26 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
84 79
85 public virtual void PostInitialise() 80 public virtual void PostInitialise()
86 { 81 {
82 if (!m_Enabled)
83 return;
84
85 MainServer.Instance.AddXmlRPCHandler(
86 "grid_instant_message", processXMLRPCGridInstantMessage);
87 }
88
89 public virtual void RegionLoaded(Scene scene)
90 {
91 }
92
93 public virtual void RemoveRegion(Scene scene)
94 {
95 if (!m_Enabled)
96 return;
97
98 lock(m_Scenes)
99 {
100 m_Scenes.Remove(scene);
101 }
87 } 102 }
88 103
89 public virtual void Close() 104 public virtual void Close()
@@ -95,9 +110,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
95 get { return "MessageTransferModule"; } 110 get { return "MessageTransferModule"; }
96 } 111 }
97 112
98 public virtual bool IsSharedModule 113 public virtual Type ReplaceableInterface
99 { 114 {
100 get { return true; } 115 get { return null; }
101 } 116 }
102 117
103 public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) 118 public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result)
@@ -148,15 +163,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
148 } 163 }
149 } 164 }
150 165
151 if (m_Gridmode) 166 SendGridInstantMessageViaXMLRPC(im, result);
152 {
153 //m_log.DebugFormat("[INSTANT MESSAGE]: Delivering via grid");
154 // Still here, try send via Grid
155 SendGridInstantMessageViaXMLRPC(im, result);
156 return;
157 }
158
159 HandleUndeliveredMessage(im, result);
160 167
161 return; 168 return;
162 } 169 }
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
index 2d4a635..24cbaeb 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs
@@ -37,9 +37,9 @@ using OpenSim.Framework.Client;
37using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.MuteList 40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 41{
42 public class MuteListModule : IRegionModule 42 public class MuteListModule : ISharedRegionModule
43 { 43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
@@ -47,11 +47,8 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList
47 private List<Scene> m_SceneList = new List<Scene>(); 47 private List<Scene> m_SceneList = new List<Scene>();
48 private string m_RestURL = String.Empty; 48 private string m_RestURL = String.Empty;
49 49
50 public void Initialise(Scene scene, IConfigSource config) 50 public void Initialise(IConfigSource config)
51 { 51 {
52 if (!enabled)
53 return;
54
55 IConfig cnf = config.Configs["Messaging"]; 52 IConfig cnf = config.Configs["Messaging"];
56 if (cnf == null) 53 if (cnf == null)
57 { 54 {
@@ -59,39 +56,53 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList
59 return; 56 return;
60 } 57 }
61 58
62 if (cnf != null && cnf.GetString( 59 if (cnf != null && cnf.GetString("MuteListModule", "None") !=
63 "MuteListModule", "None") !=
64 "MuteListModule") 60 "MuteListModule")
65 { 61 {
66 enabled = false; 62 enabled = false;
67 return; 63 return;
68 } 64 }
69 65
66 m_RestURL = cnf.GetString("MuteListURL", "");
67 if (m_RestURL == "")
68 {
69 m_log.Error("[MUTE LIST] Module was enabled, but no URL is given, disabling");
70 enabled = false;
71 return;
72 }
73 }
74
75 public void AddRegion(Scene scene)
76 {
77 if (!enabled)
78 return;
79
70 lock (m_SceneList) 80 lock (m_SceneList)
71 { 81 {
72 if (m_SceneList.Count == 0) 82 m_SceneList.Add(scene);
73 {
74 m_RestURL = cnf.GetString("MuteListURL", "");
75 if (m_RestURL == "")
76 {
77 m_log.Error("[MUTE LIST] Module was enabled, but no URL is given, disabling");
78 enabled = false;
79 return;
80 }
81 }
82 if (!m_SceneList.Contains(scene))
83 m_SceneList.Add(scene);
84 83
85 scene.EventManager.OnNewClient += OnNewClient; 84 scene.EventManager.OnNewClient += OnNewClient;
86 } 85 }
87 } 86 }
88 87
89 public void PostInitialise() 88 public void RegionLoaded(Scene scene)
89 {
90 }
91
92 public void RemoveRegion(Scene scene)
90 { 93 {
91 if (!enabled) 94 if (!enabled)
92 return; 95 return;
93 96
94 if (m_SceneList.Count == 0) 97 lock (m_SceneList)
98 {
99 m_SceneList.Remove(scene);
100 }
101 }
102
103 public void PostInitialise()
104 {
105 if (!enabled)
95 return; 106 return;
96 107
97 m_log.Debug("[MUTE LIST] Mute list enabled"); 108 m_log.Debug("[MUTE LIST] Mute list enabled");
@@ -102,26 +113,15 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList
102 get { return "MuteListModule"; } 113 get { return "MuteListModule"; }
103 } 114 }
104 115
105 public bool IsSharedModule 116 public Type ReplaceableInterface
106 { 117 {
107 get { return true; } 118 get { return null; }
108 } 119 }
109 120
110 public void Close() 121 public void Close()
111 { 122 {
112 } 123 }
113 124
114// private IClientAPI FindClient(UUID agentID)
115// {
116// foreach (Scene s in m_SceneList)
117// {
118// ScenePresence presence = s.GetScenePresence(agentID);
119// if (presence != null && !presence.IsChildAgent)
120// return presence.ControllingClient;
121// }
122// return null;
123// }
124
125 private void OnNewClient(IClientAPI client) 125 private void OnNewClient(IClientAPI client)
126 { 126 {
127 client.OnMuteListRequest += OnMuteListRequest; 127 client.OnMuteListRequest += OnMuteListRequest;
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
index 1614b70..a835c52 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs
@@ -40,78 +40,88 @@ using OpenSim.Region.Framework.Scenes;
40 40
41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
42{ 42{
43 public class OfflineMessageModule : IRegionModule 43 public class OfflineMessageModule : ISharedRegionModule
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private bool enabled = true; 47 private bool enabled = true;
48 private List<Scene> m_SceneList = new List<Scene>(); 48 private List<Scene> m_SceneList = new List<Scene>();
49 private string m_RestURL = String.Empty; 49 private string m_RestURL = String.Empty;
50 IMessageTransferModule m_TransferModule = null;
50 51
51 public void Initialise(Scene scene, IConfigSource config) 52 public void Initialise(IConfigSource config)
52 { 53 {
53 if (!enabled)
54 return;
55
56 IConfig cnf = config.Configs["Messaging"]; 54 IConfig cnf = config.Configs["Messaging"];
57 if (cnf == null) 55 if (cnf == null)
58 { 56 {
59 enabled = false; 57 enabled = false;
60 return; 58 return;
61 } 59 }
62 if (cnf != null && cnf.GetString( 60 if (cnf != null && cnf.GetString("OfflineMessageModule", "None") !=
63 "OfflineMessageModule", "None") !=
64 "OfflineMessageModule") 61 "OfflineMessageModule")
65 { 62 {
66 enabled = false; 63 enabled = false;
67 return; 64 return;
68 } 65 }
69 66
67 m_RestURL = cnf.GetString("OfflineMessageURL", "");
68 if (m_RestURL == "")
69 {
70 m_log.Error("[OFFLINE MESSAGING] Module was enabled, but no URL is given, disabling");
71 enabled = false;
72 return;
73 }
74 }
75
76 public void AddRegion(Scene scene)
77 {
78 if (!enabled)
79 return;
80
70 lock (m_SceneList) 81 lock (m_SceneList)
71 { 82 {
72 if (m_SceneList.Count == 0) 83 m_SceneList.Add(scene);
73 {
74 m_RestURL = cnf.GetString("OfflineMessageURL", "");
75 if (m_RestURL == "")
76 {
77 m_log.Error("[OFFLINE MESSAGING] Module was enabled, but no URL is given, disabling");
78 enabled = false;
79 return;
80 }
81 }
82 if (!m_SceneList.Contains(scene))
83 m_SceneList.Add(scene);
84 84
85 scene.EventManager.OnNewClient += OnNewClient; 85 scene.EventManager.OnNewClient += OnNewClient;
86 } 86 }
87 } 87 }
88 88
89 public void PostInitialise() 89 public void RegionLoaded(Scene scene)
90 { 90 {
91 if (!enabled) 91 if (!enabled)
92 return; 92 return;
93 93
94 if (m_SceneList.Count == 0) 94 if (m_TransferModule == null)
95 return;
96
97 IMessageTransferModule trans = m_SceneList[0].RequestModuleInterface<IMessageTransferModule>();
98 if (trans == null)
99 { 95 {
100 enabled = false; 96 m_TransferModule = scene.RequestModuleInterface<IMessageTransferModule>();
101 97 if (m_TransferModule == null)
102 lock (m_SceneList)
103 { 98 {
104 foreach (Scene s in m_SceneList) 99 scene.EventManager.OnNewClient -= OnNewClient;
105 s.EventManager.OnNewClient -= OnNewClient;
106 100
101 enabled = false;
107 m_SceneList.Clear(); 102 m_SceneList.Clear();
103
104 m_log.Error("[OFFLINE MESSAGING] No message transfer module is enabled. Diabling offline messages");
108 } 105 }
106 m_TransferModule.OnUndeliveredMessage += UndeliveredMessage;
107 }
108 }
109 109
110 m_log.Error("[OFFLINE MESSAGING] No message transfer module is enabled. Diabling offline messages"); 110 public void RemoveRegion(Scene scene)
111 {
112 if (!enabled)
111 return; 113 return;
114
115 lock (m_SceneList)
116 {
117 m_SceneList.Remove(scene);
112 } 118 }
119 }
113 120
114 trans.OnUndeliveredMessage += UndeliveredMessage; 121 public void PostInitialise()
122 {
123 if (!enabled)
124 return;
115 125
116 m_log.Debug("[OFFLINE MESSAGING] Offline messages enabled"); 126 m_log.Debug("[OFFLINE MESSAGING] Offline messages enabled");
117 } 127 }
@@ -121,9 +131,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
121 get { return "OfflineMessageModule"; } 131 get { return "OfflineMessageModule"; }
122 } 132 }
123 133
124 public bool IsSharedModule 134 public Type ReplaceableInterface
125 { 135 {
126 get { return true; } 136 get { return null; }
127 } 137 }
128 138
129 public void Close() 139 public void Close()
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
index f5ab454..267a90a 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs
@@ -24,6 +24,7 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System;
27using System.Collections; 28using System.Collections;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Net; 30using System.Net;
@@ -39,404 +40,54 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39 40
40namespace OpenSim.Region.CoreModules.Avatar.InstantMessage 41namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
41{ 42{
42 public class PresenceModule : IRegionModule, IPresenceModule 43 public class PresenceModule : ISharedRegionModule, IPresenceModule
43 { 44 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(
45 46 MethodBase.GetCurrentMethod().DeclaringType);
46 private bool m_Enabled = false;
47 private bool m_Gridmode = false;
48
49 // some default scene for doing things that aren't connected to a specific scene. Avoids locking.
50 private Scene m_initialScene;
51
52 private List<Scene> m_Scenes = new List<Scene>();
53
54 // we currently are only interested in root-agents. If the root isn't here, we don't know the region the
55 // user is in, so we have to ask the messaging server anyway.
56 private Dictionary<UUID, Scene> m_RootAgents =
57 new Dictionary<UUID, Scene>();
58 47
59 public event PresenceChange OnPresenceChange; 48 public event PresenceChange OnPresenceChange;
60 public event BulkPresenceData OnBulkPresenceData; 49 public event BulkPresenceData OnBulkPresenceData;
61 50
62 public void Initialise(Scene scene, IConfigSource config) 51 public void Initialise(IConfigSource config)
63 { 52 {
64 lock (m_Scenes)
65 {
66 // This is a shared module; Initialise will be called for every region on this server.
67 // Only check config once for the first region.
68 if (m_Scenes.Count == 0)
69 {
70 IConfig cnf = config.Configs["Messaging"];
71 if (cnf != null && cnf.GetString(
72 "PresenceModule", "PresenceModule") !=
73 "PresenceModule")
74 return;
75
76 cnf = config.Configs["Startup"];
77 if (cnf != null)
78 m_Gridmode = cnf.GetBoolean("gridmode", false);
79
80 m_Enabled = true;
81
82 m_initialScene = scene;
83 }
84
85 if (m_Gridmode)
86 NotifyMessageServerOfStartup(scene);
87
88 m_Scenes.Add(scene);
89 }
90
91 scene.RegisterModuleInterface<IPresenceModule>(this);
92
93 scene.EventManager.OnNewClient += OnNewClient;
94 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
95 scene.EventManager.OnMakeChildAgent += OnMakeChildAgent;
96 } 53 }
97 54
98 public void PostInitialise() 55 public void AddRegion(Scene scene)
99 { 56 {
100 } 57 }
101 58
102 public void Close() 59 public void RegionLoaded(Scene scene)
103 { 60 {
104 if (!m_Gridmode || !m_Enabled)
105 return;
106
107 if (OnPresenceChange != null)
108 {
109 lock (m_RootAgents)
110 {
111 // on shutdown, users are kicked, too
112 foreach (KeyValuePair<UUID, Scene> pair in m_RootAgents)
113 {
114 OnPresenceChange(new PresenceInfo(pair.Key, UUID.Zero));
115 }
116 }
117 }
118
119 lock (m_Scenes)
120 {
121 foreach (Scene scene in m_Scenes)
122 NotifyMessageServerOfShutdown(scene);
123 }
124 } 61 }
125 62
126 public string Name 63 public void RemoveRegion(Scene scene)
127 { 64 {
128 get { return "PresenceModule"; }
129 }
130
131 public bool IsSharedModule
132 {
133 get { return true; }
134 }
135
136 public void RequestBulkPresenceData(UUID[] users)
137 {
138 if (OnBulkPresenceData != null)
139 {
140 PresenceInfo[] result = new PresenceInfo[users.Length];
141 if (m_Gridmode)
142 {
143 // first check the local information
144 List<UUID> uuids = new List<UUID>(); // the uuids to check remotely
145 List<int> indices = new List<int>(); // just for performance.
146 lock (m_RootAgents)
147 {
148 for (int i = 0; i < uuids.Count; ++i)
149 {
150 Scene scene;
151 if (m_RootAgents.TryGetValue(users[i], out scene))
152 {
153 result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID);
154 }
155 else
156 {
157 uuids.Add(users[i]);
158 indices.Add(i);
159 }
160 }
161 }
162
163 // now we have filtered out all the local root agents. The rest we have to request info about
164 Dictionary<UUID, FriendRegionInfo> infos = m_initialScene.GetFriendRegionInfos(uuids);
165 for (int i = 0; i < uuids.Count; ++i)
166 {
167 FriendRegionInfo info;
168 if (infos.TryGetValue(uuids[i], out info) && info.isOnline)
169 {
170 UUID regionID = info.regionID;
171 if (regionID == UUID.Zero)
172 {
173 // TODO this is the old messaging-server protocol; only the regionHandle is available.
174 // Fetch region-info to get the id
175 uint x = 0, y = 0;
176 Utils.LongToUInts(info.regionHandle, out x, out y);
177 GridRegion regionInfo = m_initialScene.GridService.GetRegionByPosition(m_initialScene.RegionInfo.ScopeID,
178 (int)x, (int)y);
179 regionID = regionInfo.RegionID;
180 }
181 result[indices[i]] = new PresenceInfo(uuids[i], regionID);
182 }
183 else result[indices[i]] = new PresenceInfo(uuids[i], UUID.Zero);
184 }
185 }
186 else
187 {
188 // in standalone mode, we have all the info locally available.
189 lock (m_RootAgents)
190 {
191 for (int i = 0; i < users.Length; ++i)
192 {
193 Scene scene;
194 if (m_RootAgents.TryGetValue(users[i], out scene))
195 {
196 result[i] = new PresenceInfo(users[i], scene.RegionInfo.RegionID);
197 }
198 else
199 {
200 result[i] = new PresenceInfo(users[i], UUID.Zero);
201 }
202 }
203 }
204 }
205
206 // tell everyone
207 OnBulkPresenceData(result);
208 }
209 }
210
211 // new client doesn't mean necessarily that user logged in, it just means it entered one of the
212 // the regions on this server
213 public void OnNewClient(IClientAPI client)
214 {
215 client.OnConnectionClosed += OnConnectionClosed;
216 client.OnLogout += OnLogout;
217
218 // KLUDGE: See handler for details.
219 client.OnEconomyDataRequest += OnEconomyDataRequest;
220 } 65 }
221 66
222 // connection closed just means *one* client connection has been closed. It doesn't mean that the 67 public void PostInitialise()
223 // user has logged off; it might have just TPed away.
224 public void OnConnectionClosed(IClientAPI client)
225 {
226 // TODO: Have to think what we have to do here...
227 // Should we just remove the root from the list (if scene matches)?
228 if (!(client.Scene is Scene))
229 return;
230 Scene scene = (Scene)client.Scene;
231
232 lock (m_RootAgents)
233 {
234 Scene rootScene;
235 if (!(m_RootAgents.TryGetValue(client.AgentId, out rootScene)) || scene != rootScene)
236 return;
237
238 m_RootAgents.Remove(client.AgentId);
239 }
240
241 // Should it have logged off, we'll do the logout part in OnLogout, even if no root is stored
242 // anymore. It logged off, after all...
243 }
244
245 // Triggered when the user logs off.
246 public void OnLogout(IClientAPI client)
247 {
248 if (!(client.Scene is Scene))
249 return;
250 Scene scene = (Scene)client.Scene;
251
252 // On logout, we really remove the client from rootAgents, even if the scene doesn't match
253 lock (m_RootAgents)
254 {
255 if (m_RootAgents.ContainsKey(client.AgentId)) m_RootAgents.Remove(client.AgentId);
256 }
257
258 // now inform the messaging server and anyone who is interested
259 NotifyMessageServerOfAgentLeaving(client.AgentId, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
260 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(client.AgentId, UUID.Zero));
261 }
262
263 public void OnSetRootAgentScene(UUID agentID, Scene scene)
264 {
265 // OnSetRootAgentScene can be called from several threads at once (with different agentID).
266 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
267 // correct locking).
268 lock (m_RootAgents)
269 {
270 Scene rootScene;
271 if (m_RootAgents.TryGetValue(agentID, out rootScene) && scene == rootScene)
272 {
273 return;
274 }
275 m_RootAgents[agentID] = scene;
276 }
277
278 // inform messaging server that agent changed the region
279 Util.FireAndForget(
280 delegate(object o)
281 {
282 NotifyMessageServerOfAgentLocation(agentID, scene.RegionInfo.RegionID, scene.RegionInfo.RegionHandle);
283 }
284 );
285 }
286
287 private void OnEconomyDataRequest(UUID agentID)
288 { 68 {
289 // KLUDGE: This is the only way I found to get a message (only) after login was completed and the
290 // client is connected enough to receive UDP packets.
291 // This packet seems to be sent only once, just after connection was established to the first
292 // region after login.
293 // We use it here to trigger a presence update; the old update-on-login was never be heard by
294 // the freshly logged in viewer, as it wasn't connected to the region at that time.
295 // TODO: Feel free to replace this by a better solution if you find one.
296
297 // get the agent. This should work every time, as we just got a packet from it
298 ScenePresence agent = null;
299 lock (m_Scenes)
300 {
301 foreach (Scene scene in m_Scenes)
302 {
303 agent = scene.GetScenePresence(agentID);
304 if (agent != null) break;
305 }
306 }
307
308 // just to be paranoid...
309 if (agent == null)
310 {
311 m_log.ErrorFormat("[PRESENCE]: Got a packet from agent {0} who can't be found anymore!?", agentID);
312 return;
313 }
314
315 // we are a bit premature here, but the next packet will switch this child agent to root.
316 if (OnPresenceChange != null) OnPresenceChange(new PresenceInfo(agentID, agent.Scene.RegionInfo.RegionID));
317 } 69 }
318 70
319 public void OnMakeChildAgent(ScenePresence agent) 71 public void Close()
320 { 72 {
321 // OnMakeChildAgent can be called from several threads at once (with different agent).
322 // Concurrent access to m_RootAgents is prone to failure on multi-core/-processor systems without
323 // correct locking).
324 lock (m_RootAgents)
325 {
326 Scene rootScene;
327 if (m_RootAgents.TryGetValue(agent.UUID, out rootScene) && agent.Scene == rootScene)
328 {
329 m_RootAgents.Remove(agent.UUID);
330 }
331 }
332 // don't notify the messaging-server; either this agent just had been downgraded and another one will be upgraded
333 // to root momentarily (which will notify the messaging-server), or possibly it will be closed in a moment,
334 // which will update the messaging-server, too.
335 } 73 }
336 74
337 private void NotifyMessageServerOfStartup(Scene scene) 75 public string Name
338 { 76 {
339 Hashtable xmlrpcdata = new Hashtable(); 77 get { return "PresenceModule"; }
340 xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString();
341 ArrayList SendParams = new ArrayList();
342 SendParams.Add(xmlrpcdata);
343 try
344 {
345 XmlRpcRequest UpRequest = new XmlRpcRequest("region_startup", SendParams);
346 XmlRpcResponse resp = UpRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000);
347
348 Hashtable responseData = (Hashtable)resp.Value;
349 if (responseData == null || (!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
350 {
351 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName);
352 }
353 }
354 catch (WebException)
355 {
356 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region startup for region {0}", scene.RegionInfo.RegionName);
357 }
358 } 78 }
359 79
360 private void NotifyMessageServerOfShutdown(Scene scene) 80 public Type ReplaceableInterface
361 { 81 {
362 if (m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL == string.Empty) 82 get { return null; }
363 return;
364
365 Hashtable xmlrpcdata = new Hashtable();
366 xmlrpcdata["RegionUUID"] = scene.RegionInfo.RegionID.ToString();
367 ArrayList SendParams = new ArrayList();
368 SendParams.Add(xmlrpcdata);
369 try
370 {
371 XmlRpcRequest DownRequest = new XmlRpcRequest("region_shutdown", SendParams);
372 XmlRpcResponse resp = DownRequest.Send(scene.CommsManager.NetworkServersInfo.MessagingURL, 5000);
373
374 Hashtable responseData = (Hashtable)resp.Value;
375 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
376 {
377 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName);
378 }
379 }
380 catch (WebException)
381 {
382 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of region shutdown for region {0}", scene.RegionInfo.RegionName);
383 }
384 } 83 }
385 84
386 private void NotifyMessageServerOfAgentLocation(UUID agentID, UUID region, ulong regionHandle) 85 public void RequestBulkPresenceData(UUID[] users)
387 { 86 {
388 if (m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL == string.Empty)
389 return;
390
391 Hashtable xmlrpcdata = new Hashtable();
392 xmlrpcdata["AgentID"] = agentID.ToString();
393 xmlrpcdata["RegionUUID"] = region.ToString();
394 xmlrpcdata["RegionHandle"] = regionHandle.ToString();
395 ArrayList SendParams = new ArrayList();
396 SendParams.Add(xmlrpcdata);
397 try
398 {
399 XmlRpcRequest LocationRequest = new XmlRpcRequest("agent_location", SendParams);
400 XmlRpcResponse resp = LocationRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000);
401
402 Hashtable responseData = (Hashtable)resp.Value;
403 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
404 {
405 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString());
406 }
407 }
408 catch (WebException)
409 {
410 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent location for {0}", agentID.ToString());
411 }
412 } 87 }
413 88
414 private void NotifyMessageServerOfAgentLeaving(UUID agentID, UUID region, ulong regionHandle) 89 public void OnNewClient(IClientAPI client)
415 { 90 {
416 if (m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL == string.Empty)
417 return;
418
419 Hashtable xmlrpcdata = new Hashtable();
420 xmlrpcdata["AgentID"] = agentID.ToString();
421 xmlrpcdata["RegionUUID"] = region.ToString();
422 xmlrpcdata["RegionHandle"] = regionHandle.ToString();
423 ArrayList SendParams = new ArrayList();
424 SendParams.Add(xmlrpcdata);
425 try
426 {
427 XmlRpcRequest LeavingRequest = new XmlRpcRequest("agent_leaving", SendParams);
428 XmlRpcResponse resp = LeavingRequest.Send(m_Scenes[0].CommsManager.NetworkServersInfo.MessagingURL, 5000);
429
430 Hashtable responseData = (Hashtable)resp.Value;
431 if ((!responseData.ContainsKey("success")) || (string)responseData["success"] != "TRUE")
432 {
433 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString());
434 }
435 }
436 catch (WebException)
437 {
438 m_log.ErrorFormat("[PRESENCE]: Failed to notify message server of agent leaving for {0}", agentID.ToString());
439 }
440 } 91 }
441 } 92 }
442} 93}
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index d9a021f..55d4f14 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
39 39
40namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer 40namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
41{ 41{
42 public class InventoryTransferModule : IInventoryTransferModule, IRegionModule 42 public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule
43 { 43 {
44 private static readonly ILog m_log 44 private static readonly ILog m_log
45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -50,10 +50,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
50 new Dictionary<UUID, Scene>(); 50 new Dictionary<UUID, Scene>();
51 51
52 private IMessageTransferModule m_TransferModule = null; 52 private IMessageTransferModule m_TransferModule = null;
53 private bool m_Enabled = true;
53 54
54 #region IRegionModule Members 55 #region IRegionModule Members
55 56
56 public void Initialise(Scene scene, IConfigSource config) 57 public void Initialise(IConfigSource config)
57 { 58 {
58 if (config.Configs["Messaging"] != null) 59 if (config.Configs["Messaging"] != null)
59 { 60 {
@@ -62,29 +63,56 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
62 if (config.Configs["Messaging"].GetString( 63 if (config.Configs["Messaging"].GetString(
63 "InventoryTransferModule", "InventoryTransferModule") != 64 "InventoryTransferModule", "InventoryTransferModule") !=
64 "InventoryTransferModule") 65 "InventoryTransferModule")
66 {
67 m_Enabled = false;
65 return; 68 return;
69 }
66 } 70 }
71 }
67 72
68 if (!m_Scenelist.Contains(scene)) 73 public void AddRegion(Scene scene)
69 { 74 {
70 m_Scenelist.Add(scene); 75 if (!m_Enabled)
76 return;
71 77
72 scene.RegisterModuleInterface<IInventoryTransferModule>(this); 78 m_Scenelist.Add(scene);
73 79
74 scene.EventManager.OnNewClient += OnNewClient; 80 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
75 scene.EventManager.OnClientClosed += ClientLoggedOut; 81
76 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 82 scene.EventManager.OnNewClient += OnNewClient;
77 } 83 scene.EventManager.OnClientClosed += ClientLoggedOut;
84 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
78 } 85 }
79 86
80 public void PostInitialise() 87 public void RegionLoaded(Scene scene)
81 { 88 {
82 if (m_Scenelist.Count > 0) 89 if (m_TransferModule == null)
83 { 90 {
84 m_TransferModule = m_Scenelist[0].RequestModuleInterface<IMessageTransferModule>(); 91 m_TransferModule = m_Scenelist[0].RequestModuleInterface<IMessageTransferModule>();
85 if (m_TransferModule == null) 92 if (m_TransferModule == null)
93 {
86 m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only"); 94 m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only");
95 m_Enabled = false;
96
97 m_Scenelist.Clear();
98 scene.EventManager.OnNewClient -= OnNewClient;
99 scene.EventManager.OnClientClosed -= ClientLoggedOut;
100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
101 }
87 } 102 }
103
104 }
105
106 public void RemoveRegion(Scene scene)
107 {
108 scene.EventManager.OnNewClient -= OnNewClient;
109 scene.EventManager.OnClientClosed -= ClientLoggedOut;
110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
111 m_Scenelist.Remove(scene);
112 }
113
114 public void PostInitialise()
115 {
88 } 116 }
89 117
90 public void Close() 118 public void Close()
@@ -96,9 +124,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 get { return "InventoryModule"; } 124 get { return "InventoryModule"; }
97 } 125 }
98 126
99 public bool IsSharedModule 127 public Type ReplaceableInterface
100 { 128 {
101 get { return true; } 129 get { return null; }
102 } 130 }
103 131
104 #endregion 132 #endregion
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 261bd6c..d1d7df2 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -37,34 +37,72 @@ using OpenSim.Region.Framework.Scenes;
37 37
38namespace OpenSim.Region.CoreModules.Avatar.Lure 38namespace OpenSim.Region.CoreModules.Avatar.Lure
39{ 39{
40 public class LureModule : IRegionModule 40 public class LureModule : ISharedRegionModule
41 { 41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(
43 MethodBase.GetCurrentMethod().DeclaringType);
43 44
44 private readonly List<Scene> m_scenes = new List<Scene>(); 45 private readonly List<Scene> m_scenes = new List<Scene>();
45 46
46 private IMessageTransferModule m_TransferModule = null; 47 private IMessageTransferModule m_TransferModule = null;
48 private bool m_Enabled = true;
47 49
48 public void Initialise(Scene scene, IConfigSource config) 50 public void Initialise(IConfigSource config)
49 { 51 {
50 if (config.Configs["Messaging"] != null) 52 if (config.Configs["Messaging"] != null)
51 { 53 {
52 if (config.Configs["Messaging"].GetString( 54 if (config.Configs["Messaging"].GetString(
53 "LureModule", "LureModule") != 55 "LureModule", "LureModule") !=
54 "LureModule") 56 "LureModule")
55 return; 57 m_Enabled = false;
56 } 58 }
59 }
60
61 public void AddRegion(Scene scene)
62 {
63 if (!m_Enabled)
64 return;
57 65
58 lock (m_scenes) 66 lock (m_scenes)
59 { 67 {
60 if (!m_scenes.Contains(scene)) 68 m_scenes.Add(scene);
69 scene.EventManager.OnNewClient += OnNewClient;
70 scene.EventManager.OnIncomingInstantMessage +=
71 OnGridInstantMessage;
72 }
73 }
74
75 public void RegionLoaded(Scene scene)
76 {
77 if (m_TransferModule == null)
78 {
79 m_TransferModule =
80 scene.RequestModuleInterface<IMessageTransferModule>();
81
82 if (m_TransferModule == null)
61 { 83 {
62 m_scenes.Add(scene); 84 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
63 scene.EventManager.OnNewClient += OnNewClient; 85 "lures will not work!");
64 scene.EventManager.OnIncomingInstantMessage += 86
87 m_Enabled = false;
88 m_scenes.Clear();
89 scene.EventManager.OnNewClient -= OnNewClient;
90 scene.EventManager.OnIncomingInstantMessage -=
65 OnGridInstantMessage; 91 OnGridInstantMessage;
66 } 92 }
67 } 93 }
94
95 }
96
97 public void RemoveRegion(Scene scene)
98 {
99 lock (m_scenes)
100 {
101 m_scenes.Remove(scene);
102 scene.EventManager.OnNewClient -= OnNewClient;
103 scene.EventManager.OnIncomingInstantMessage -=
104 OnGridInstantMessage;
105 }
68 } 106 }
69 107
70 void OnNewClient(IClientAPI client) 108 void OnNewClient(IClientAPI client)
@@ -76,12 +114,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
76 114
77 public void PostInitialise() 115 public void PostInitialise()
78 { 116 {
79 m_TransferModule =
80 m_scenes[0].RequestModuleInterface<IMessageTransferModule>();
81
82 if (m_TransferModule == null)
83 m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+
84 "lures will not work!");
85 } 117 }
86 118
87 public void Close() 119 public void Close()
@@ -93,9 +125,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
93 get { return "LureModule"; } 125 get { return "LureModule"; }
94 } 126 }
95 127
96 public bool IsSharedModule 128 public Type ReplaceableInterface
97 { 129 {
98 get { return true; } 130 get { return null; }
99 } 131 }
100 132
101 public void OnInstantMessage(IClientAPI client, GridInstantMessage im) 133 public void OnInstantMessage(IClientAPI client, GridInstantMessage im)
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index beb2307..e4b0fd5 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -17,13 +17,19 @@
17 <RegionModule id="HGWorldMapModule" type="OpenSim.Region.CoreModules.Hypergrid.HGWorldMapModule" /> 17 <RegionModule id="HGWorldMapModule" type="OpenSim.Region.CoreModules.Hypergrid.HGWorldMapModule" />
18 <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" /> 18 <RegionModule id="UrlModule" type="OpenSim.Region.CoreModules.Scripting.LSLHttp.UrlModule" />
19 <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" /> 19 <RegionModule id="Chat" type="OpenSim.Region.CoreModules.Avatar.Chat.ChatModule" />
20 <RegionModule id="FriendsModule" type="OpenSim.Region.CoreModules.Avatar.Friends.FriendsModule" />
21 <RegionModule id="PresenceModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.PresenceModule" />
22 <RegionModule id="MuteListModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MuteListModule" />
23 <RegionModule id="OfflineMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.OfflineMessageModule" />
24 <RegionModule id="InstantMessageModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.InstantMessageModule" />
25 <RegionModule id="MessageTransferModule" type="OpenSim.Region.CoreModules.Avatar.InstantMessage.MessageTransferModule" />
26 <RegionModule id="LureModule" type="OpenSim.Region.CoreModules.Avatar.Lure.LureModule" />
27 <RegionModule id="InventoryTransferModule" type="OpenSim.Region.CoreModules.Avatar.Inventory.Transfer.InventoryTransferModule" />
20 <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" /> 28 <RegionModule id="CoreAssetCache" type="OpenSim.Region.CoreModules.Asset.CoreAssetCache" />
21 <RegionModule id="GlynnTuckerAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" /> 29 <RegionModule id="GlynnTuckerAssetCache" type="OpenSim.Region.CoreModules.Asset.GlynnTuckerAssetCache" />
22 <RegionModule id="CenomeMemoryAssetCache" type="OpenSim.Region.CoreModules.Asset.CenomeMemoryAssetCache"/> 30 <RegionModule id="CenomeMemoryAssetCache" type="OpenSim.Region.CoreModules.Asset.CenomeMemoryAssetCache"/>
23 <RegionModule id="LibraryModule" type="OpenSim.Region.CoreModules.Framework.Library.LibraryModule"/> 31 <RegionModule id="LibraryModule" type="OpenSim.Region.CoreModules.Framework.Library.LibraryModule"/>
24 <!-- Service connectors OUT modules --> 32 <!-- Service connectors OUT modules -->
25 <RegionModule id="LocalUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.User.LocalUserServicesConnector" />
26 <RegionModule id="RemoteUserServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.User.RemoteUserServicesConnector" />
27 <RegionModule id="LocalAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.LocalAssetServicesConnector" /> 33 <RegionModule id="LocalAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.LocalAssetServicesConnector" />
28 <RegionModule id="RemoteAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.RemoteAssetServicesConnector" /> 34 <RegionModule id="RemoteAssetServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.RemoteAssetServicesConnector" />
29 <RegionModule id="LocalAuthorizationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization.LocalAuthorizationServicesConnector" /> 35 <RegionModule id="LocalAuthorizationServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization.LocalAuthorizationServicesConnector" />
@@ -41,6 +47,10 @@
41 <RegionModule id="LocalGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.LocalGridServicesConnector" /> 47 <RegionModule id="LocalGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.LocalGridServicesConnector" />
42 <RegionModule id="RemoteGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.RemoteGridServicesConnector" /> 48 <RegionModule id="RemoteGridServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.RemoteGridServicesConnector" />
43 <RegionModule id="HGGridConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.HGGridConnector" /> 49 <RegionModule id="HGGridConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.HGGridConnector" />
50 <RegionModule id="LocalPresenceServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.LocalPresenceServicesConnector" />
51 <RegionModule id="RemotePresenceServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.RemotePresenceServicesConnector" />
52 <RegionModule id="LocalUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.LocalUserAccountServicesConnector" />
53 <RegionModule id="RemoteUserAccountServicesConnector" type="OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts.RemoteUserAccountServicesConnector" />
44 <!-- Service connectors IN modules --> 54 <!-- Service connectors IN modules -->
45 <RegionModule id="AssetServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset.AssetServiceInConnectorModule" /> 55 <RegionModule id="AssetServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset.AssetServiceInConnectorModule" />
46 <RegionModule id="InventoryServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory.InventoryServiceInConnectorModule" /> 56 <RegionModule id="InventoryServiceInConnectorModule" type="OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory.InventoryServiceInConnectorModule" />
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
new file mode 100644
index 0000000..2cb18c7
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
@@ -0,0 +1,200 @@
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.Generic;
29using System.Reflection;
30
31using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
35using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
36
37using OpenMetaverse;
38using log4net;
39using Nini.Config;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
42{
43 public class LocalPresenceServicesConnector : ISharedRegionModule, IPresenceService
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 private bool m_Enabled = false;
48
49 private PresenceDetector m_PresenceDetector;
50 private IPresenceService m_PresenceService;
51
52 public LocalPresenceServicesConnector()
53 {
54 }
55
56 public LocalPresenceServicesConnector(IConfigSource source)
57 {
58 Initialise(source);
59 }
60
61 #region ISharedRegionModule
62
63 public Type ReplaceableInterface
64 {
65 get { return null; }
66 }
67
68 public string Name
69 {
70 get { return "LocalPresenceServicesConnector"; }
71 }
72
73 public void Initialise(IConfigSource source)
74 {
75 IConfig moduleConfig = source.Configs["Modules"];
76 if (moduleConfig != null)
77 {
78 string name = moduleConfig.GetString("PresenceServices", "");
79 if (name == Name)
80 {
81 IConfig inventoryConfig = source.Configs["PresenceService"];
82 if (inventoryConfig == null)
83 {
84 m_log.Error("[LOCAL PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini");
85 return;
86 }
87
88 string serviceDll = inventoryConfig.GetString("LocalServiceModule", String.Empty);
89
90 if (serviceDll == String.Empty)
91 {
92 m_log.Error("[LOCAL PRESENCE CONNECTOR]: No LocalServiceModule named in section PresenceService");
93 return;
94 }
95
96 Object[] args = new Object[] { source };
97 m_log.DebugFormat("[LOCAL PRESENCE CONNECTOR]: Service dll = {0}", serviceDll);
98
99 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(serviceDll, args);
100
101 if (m_PresenceService == null)
102 {
103 m_log.Error("[LOCAL PRESENCE CONNECTOR]: Can't load presence service");
104 //return;
105 throw new Exception("Unable to proceed. Please make sure your ini files in config-include are updated according to .example's");
106 }
107
108 //Init(source);
109
110 m_PresenceDetector = new PresenceDetector(this);
111
112 m_Enabled = true;
113 m_log.Info("[LOCAL PRESENCE CONNECTOR]: Local presence connector enabled");
114 }
115 }
116 }
117
118 public void PostInitialise()
119 {
120 }
121
122 public void Close()
123 {
124 }
125
126 public void AddRegion(Scene scene)
127 {
128 if (!m_Enabled)
129 return;
130
131 // m_log.DebugFormat(
132 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
133
134 scene.RegisterModuleInterface<IPresenceService>(this);
135 m_PresenceDetector.AddRegion(scene);
136
137 m_log.InfoFormat("[LOCAL PRESENCE CONNECTOR]: Enabled local presence for region {0}", scene.RegionInfo.RegionName);
138
139 }
140
141 public void RemoveRegion(Scene scene)
142 {
143 if (!m_Enabled)
144 return;
145
146 m_PresenceDetector.RemoveRegion(scene);
147 }
148
149 public void RegionLoaded(Scene scene)
150 {
151 if (!m_Enabled)
152 return;
153
154 }
155
156 #endregion
157
158 #region IPresenceService
159
160 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
161 {
162 m_log.Warn("[LOCAL PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
163 return false;
164 }
165
166 public bool LogoutAgent(UUID sessionID)
167 {
168 return m_PresenceService.LogoutAgent(sessionID);
169 }
170
171
172 public bool LogoutRegionAgents(UUID regionID)
173 {
174 return m_PresenceService.LogoutRegionAgents(regionID);
175 }
176
177 public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
178 {
179 return m_PresenceService.ReportAgent(sessionID, regionID, position, lookAt);
180 }
181
182 public PresenceInfo GetAgent(UUID sessionID)
183 {
184 return m_PresenceService.GetAgent(sessionID);
185 }
186
187 public PresenceInfo[] GetAgents(string[] userIDs)
188 {
189 return m_PresenceService.GetAgents(userIDs);
190 }
191
192 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
193 {
194 return m_PresenceService.SetHomeLocation(userID, regionID, position, lookAt);
195 }
196
197 #endregion
198
199 }
200}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
new file mode 100644
index 0000000..3ca5560
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs
@@ -0,0 +1,84 @@
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.Generic;
29using System.Reflection;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34
35using OpenMetaverse;
36using log4net;
37
38namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
39{
40 public class PresenceDetector
41 {
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43
44 private IPresenceService m_PresenceService;
45
46 public PresenceDetector(IPresenceService presenceservice)
47 {
48 m_PresenceService = presenceservice;
49 }
50
51 public void AddRegion(Scene scene)
52 {
53 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
54 scene.EventManager.OnNewClient += OnNewClient;
55
56 m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
57 }
58
59 public void RemoveRegion(Scene scene)
60 {
61 scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent;
62 scene.EventManager.OnNewClient -= OnNewClient;
63
64 m_PresenceService.LogoutRegionAgents(scene.RegionInfo.RegionID);
65 }
66
67 public void OnMakeRootAgent(ScenePresence sp)
68 {
69 m_log.DebugFormat("[PRESENCE DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
70 m_PresenceService.ReportAgent(sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
71 }
72
73 public void OnNewClient(IClientAPI client)
74 {
75 client.OnLogout += OnLogout;
76 }
77
78 public void OnLogout(IClientAPI client)
79 {
80 client.OnLogout -= OnLogout;
81 m_PresenceService.LogoutAgent(client.SessionId);
82 }
83 }
84}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
new file mode 100644
index 0000000..e8e140a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
@@ -0,0 +1,164 @@
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.Generic;
29using System.Reflection;
30
31using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Connectors;
36using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
37
38using OpenMetaverse;
39using log4net;
40using Nini.Config;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
43{
44 public class RemotePresenceServicesConnector : ISharedRegionModule, IPresenceService
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 #region ISharedRegionModule
49
50 private bool m_Enabled = false;
51
52 private PresenceDetector m_PresenceDetector;
53 private IPresenceService m_RemoteConnector;
54
55 public Type ReplaceableInterface
56 {
57 get { return null; }
58 }
59
60 public string Name
61 {
62 get { return "RemotePresenceServiceConnector"; }
63 }
64
65 public void Initialise(IConfigSource source)
66 {
67 IConfig moduleConfig = source.Configs["Modules"];
68 if (moduleConfig != null)
69 {
70 string name = moduleConfig.GetString("PresenceServices", "");
71 if (name == Name)
72 {
73 m_RemoteConnector = new PresenceServicesConnector(source);
74
75 m_Enabled = true;
76
77 m_PresenceDetector = new PresenceDetector(this);
78
79 m_log.Info("[INVENTORY CONNECTOR]: Remote presence enabled");
80 }
81 }
82
83 }
84
85 public void PostInitialise()
86 {
87 }
88
89 public void Close()
90 {
91 }
92
93 public void AddRegion(Scene scene)
94 {
95 if (!m_Enabled)
96 return;
97
98 scene.RegisterModuleInterface<IPresenceService>(this);
99 m_PresenceDetector.AddRegion(scene);
100
101 m_log.InfoFormat("[REMOTE PRESENCE CONNECTOR]: Enabled remote presence for region {0}", scene.RegionInfo.RegionName);
102
103 }
104
105 public void RemoveRegion(Scene scene)
106 {
107 if (!m_Enabled)
108 return;
109
110 m_PresenceDetector.RemoveRegion(scene);
111 }
112
113 public void RegionLoaded(Scene scene)
114 {
115 if (!m_Enabled)
116 return;
117
118 }
119
120 #endregion
121
122 #region IPresenceService
123
124 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
125 {
126 m_log.Warn("[REMOTE PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
127 return false;
128 }
129
130 public bool LogoutAgent(UUID sessionID)
131 {
132 return m_RemoteConnector.LogoutAgent(sessionID);
133 }
134
135
136 public bool LogoutRegionAgents(UUID regionID)
137 {
138 return m_RemoteConnector.LogoutRegionAgents(regionID);
139 }
140
141 public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
142 {
143 return m_RemoteConnector.ReportAgent(sessionID, regionID, position, lookAt);
144 }
145
146 public PresenceInfo GetAgent(UUID sessionID)
147 {
148 return m_RemoteConnector.GetAgent(sessionID);
149 }
150
151 public PresenceInfo[] GetAgents(string[] userIDs)
152 {
153 return m_RemoteConnector.GetAgents(userIDs);
154 }
155
156 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
157 {
158 return m_RemoteConnector.SetHomeLocation(userID, regionID, position, lookAt);
159 }
160
161 #endregion
162
163 }
164}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
new file mode 100644
index 0000000..ebb2c3e
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -0,0 +1,104 @@
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.IO;
31using System.Reflection;
32using System.Threading;
33using log4net.Config;
34using NUnit.Framework;
35using NUnit.Framework.SyntaxHelpers;
36using OpenMetaverse;
37using OpenSim.Framework;
38using Nini.Config;
39
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence;
41using OpenSim.Region.Framework.Scenes;
42using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Setup;
45
46namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
47{
48 [TestFixture]
49 public class PresenceConnectorsTests
50 {
51 LocalPresenceServicesConnector m_LocalConnector;
52 private void SetUp()
53 {
54 IConfigSource config = new IniConfigSource();
55 config.AddConfig("Modules");
56 config.AddConfig("PresenceService");
57 config.Configs["Modules"].Set("PresenceServices", "LocalPresenceServicesConnector");
58 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService");
59 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll:NullPresenceData");
60
61 m_LocalConnector = new LocalPresenceServicesConnector(config);
62 }
63
64 /// <summary>
65 /// Test OpenSim Presence.
66 /// </summary>
67 [Test]
68 public void TestPresenceV0_1()
69 {
70 SetUp();
71
72 string user1 = UUID.Zero.ToString();
73 UUID session1 = UUID.Zero;
74
75 // this is not implemented by this connector
76 //m_LocalConnector.LoginAgent(user1, session1, UUID.Zero);
77 PresenceInfo result = m_LocalConnector.GetAgent(session1);
78 Assert.IsNotNull(result, "Retrieved GetAgent is null");
79 Assert.That(result.UserID, Is.EqualTo(user1), "Retrieved userID does not match");
80 Assert.IsTrue(result.Online, "Agent just logged in but is offline");
81
82 UUID region1 = UUID.Random();
83 bool r = m_LocalConnector.ReportAgent(session1, region1, Vector3.Zero, Vector3.Zero);
84 Assert.IsTrue(r, "First ReportAgent returned false");
85 result = m_LocalConnector.GetAgent(session1);
86 Assert.That(result.RegionID, Is.EqualTo(region1), "Agent is not in the right region (region1)");
87
88 UUID region2 = UUID.Random();
89 r = m_LocalConnector.ReportAgent(session1, region2, Vector3.Zero, Vector3.Zero);
90 Assert.IsTrue(r, "Second ReportAgent returned false");
91 result = m_LocalConnector.GetAgent(session1);
92 Assert.That(result.RegionID, Is.EqualTo(region2), "Agent is not in the right region (region2)");
93
94 r = m_LocalConnector.LogoutAgent(session1);
95 Assert.IsTrue(r, "LogoutAgent returned false");
96 result = m_LocalConnector.GetAgent(session1);
97 Assert.IsNotNull(result, "Agent session disappeared from storage after logout");
98 Assert.IsFalse(result.Online, "Agent is reported to be Online after logout");
99
100 r = m_LocalConnector.ReportAgent(session1, region1, Vector3.Zero, Vector3.Zero);
101 Assert.IsFalse(r, "ReportAgent of non-logged in user returned true");
102 }
103 }
104}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
index cca5bb4..ce8c3a5 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/LocalUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
31using Nini.Config; 32using Nini.Config;
@@ -34,9 +35,11 @@ using OpenSim.Region.Framework.Scenes;
34using OpenSim.Server.Base; 35using OpenSim.Server.Base;
35using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
36 37
37namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User 38using OpenMetaverse;
39
40namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
38{ 41{
39 public class LocalUserServicesConnector : ISharedRegionModule 42 public class LocalUserAccountServicesConnector : ISharedRegionModule, IUserAccountService
40 { 43 {
41 private static readonly ILog m_log = 44 private static readonly ILog m_log =
42 LogManager.GetLogger( 45 LogManager.GetLogger(
@@ -46,6 +49,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
46 49
47 private bool m_Enabled = false; 50 private bool m_Enabled = false;
48 51
52 #region ISharedRegionModule
53
49 public Type ReplaceableInterface 54 public Type ReplaceableInterface
50 { 55 {
51 get { return null; } 56 get { return null; }
@@ -53,7 +58,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
53 58
54 public string Name 59 public string Name
55 { 60 {
56 get { return "LocalUserServicesConnector"; } 61 get { return "LocalUserAccountServicesConnector"; }
57 } 62 }
58 63
59 public void Initialise(IConfigSource source) 64 public void Initialise(IConfigSource source)
@@ -61,13 +66,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
61 IConfig moduleConfig = source.Configs["Modules"]; 66 IConfig moduleConfig = source.Configs["Modules"];
62 if (moduleConfig != null) 67 if (moduleConfig != null)
63 { 68 {
64 string name = moduleConfig.GetString("UserServices", ""); 69 string name = moduleConfig.GetString("UserAccountServices", "");
65 if (name == Name) 70 if (name == Name)
66 { 71 {
67 IConfig userConfig = source.Configs["UserService"]; 72 IConfig userConfig = source.Configs["UserAccountService"];
68 if (userConfig == null) 73 if (userConfig == null)
69 { 74 {
70 m_log.Error("[USER CONNECTOR]: UserService missing from OpenSim.ini"); 75 m_log.Error("[USER CONNECTOR]: UserAccountService missing from OpenSim.ini");
71 return; 76 return;
72 } 77 }
73 78
@@ -87,7 +92,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
87 92
88 if (m_UserService == null) 93 if (m_UserService == null)
89 { 94 {
90 m_log.Error("[USER CONNECTOR]: Can't load user service"); 95 m_log.Error("[USER CONNECTOR]: Can't load user account service");
91 return; 96 return;
92 } 97 }
93 m_Enabled = true; 98 m_Enabled = true;
@@ -127,5 +132,45 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
127 if (!m_Enabled) 132 if (!m_Enabled)
128 return; 133 return;
129 } 134 }
135
136 #endregion
137
138 #region IUserAccountService
139
140 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
141 {
142 return m_UserService.GetUserAccount(scopeID, userID);
143 }
144
145 public UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName)
146 {
147 return m_UserService.GetUserAccount(scopeID, FirstName, LastName);
148 }
149
150 public UserAccount GetUserAccount(UUID scopeID, string Email)
151 {
152 return m_UserService.GetUserAccount(scopeID, Email);
153 }
154
155 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
156 {
157 return m_UserService.GetUserAccounts(scopeID, query);
158 }
159
160 // Update all updatable fields
161 //
162 public bool SetUserAccount(UserAccount data)
163 {
164 return m_UserService.SetUserAccount(data);
165 }
166
167 // Creates a user data record
168 public bool CreateUserAccount(UserAccount data)
169 {
170 return m_UserService.CreateUserAccount(data);
171 }
172
173 #endregion
174
130 } 175 }
131} 176}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
index cef9129..d322aba 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/User/RemoteUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/RemoteUserAccountServiceConnector.cs
@@ -34,9 +34,9 @@ using OpenSim.Region.Framework.Scenes;
34using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Connectors; 35using OpenSim.Services.Connectors;
36 36
37namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User 37namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
38{ 38{
39 public class RemoteUserServicesConnector : UserServicesConnector, 39 public class RemoteUserAccountServicesConnector : UserAccountServicesConnector,
40 ISharedRegionModule, IUserAccountService 40 ISharedRegionModule, IUserAccountService
41 { 41 {
42 private static readonly ILog m_log = 42 private static readonly ILog m_log =
@@ -52,7 +52,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.User
52 52
53 public string Name 53 public string Name
54 { 54 {
55 get { return "RemoteUserServicesConnector"; } 55 get { return "RemoteUserAccountServicesConnector"; }
56 } 56 }
57 57
58 public override void Initialise(IConfigSource source) 58 public override void Initialise(IConfigSource source)
diff --git a/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs b/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
index 630c6a3..d44c1e1 100644
--- a/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
@@ -31,13 +31,13 @@ namespace OpenSim.Region.Framework.Interfaces
31{ 31{
32 public struct PresenceInfo 32 public struct PresenceInfo
33 { 33 {
34 public UUID userID; 34 public string UserID;
35 public UUID regionID; 35 public UUID RegionID;
36 36
37 public PresenceInfo(UUID userID, UUID regionID) 37 public PresenceInfo(string userID, UUID regionID)
38 { 38 {
39 this.userID = userID; 39 UserID = userID;
40 this.regionID = regionID; 40 RegionID = regionID;
41 } 41 }
42 } 42 }
43 43
diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs
index 0964caa..a5d28a4 100644
--- a/OpenSim/Server/Base/ServerUtils.cs
+++ b/OpenSim/Server/Base/ServerUtils.cs
@@ -160,9 +160,9 @@ namespace OpenSim.Server.Base
160 } 160 }
161 } 161 }
162 162
163 public static Dictionary<string, string> ParseQueryString(string query) 163 public static Dictionary<string, object> ParseQueryString(string query)
164 { 164 {
165 Dictionary<string, string> result = new Dictionary<string, string>(); 165 Dictionary<string, object> result = new Dictionary<string, object>();
166 string[] terms = query.Split(new char[] {'&'}); 166 string[] terms = query.Split(new char[] {'&'});
167 167
168 if (terms.Length == 0) 168 if (terms.Length == 0)
@@ -180,33 +180,76 @@ namespace OpenSim.Server.Base
180 if (elems.Length > 1) 180 if (elems.Length > 1)
181 value = System.Web.HttpUtility.UrlDecode(elems[1]); 181 value = System.Web.HttpUtility.UrlDecode(elems[1]);
182 182
183 result[name] = value; 183 if (name.EndsWith("[]"))
184 {
185 if (result.ContainsKey(name))
186 {
187 if (!(result[name] is List<string>))
188 continue;
189
190 List<string> l = (List<string>)result[name];
191
192 l.Add(value);
193 }
194 else
195 {
196 List<string> newList = new List<string>();
197
198 newList.Add(value);
199
200 result[name] = newList;
201 }
202 }
203 else
204 {
205 if (!result.ContainsKey(name))
206 result[name] = value;
207 }
184 } 208 }
185 209
186 return result; 210 return result;
187 } 211 }
188 212
189 public static string BuildQueryString(Dictionary<string, string> data) 213 public static string BuildQueryString(Dictionary<string, object> data)
190 { 214 {
191 string qstring = String.Empty; 215 string qstring = String.Empty;
192 216
193 foreach (KeyValuePair<string, string> kvp in data) 217 string part;
218
219 foreach (KeyValuePair<string, object> kvp in data)
194 { 220 {
195 string part; 221 if (kvp.Value is List<string>)
196 if (kvp.Value != String.Empty)
197 { 222 {
198 part = System.Web.HttpUtility.UrlEncode(kvp.Key) + 223 List<string> l = (List<String>)kvp.Value;
199 "=" + System.Web.HttpUtility.UrlEncode(kvp.Value); 224
225 foreach (string s in l)
226 {
227 part = System.Web.HttpUtility.UrlEncode(kvp.Key) +
228 "[]=" + System.Web.HttpUtility.UrlEncode(s);
229
230 if (qstring != String.Empty)
231 qstring += "&";
232
233 qstring += part;
234 }
200 } 235 }
201 else 236 else
202 { 237 {
203 part = System.Web.HttpUtility.UrlEncode(kvp.Key); 238 if (kvp.Value.ToString() != String.Empty)
204 } 239 {
240 part = System.Web.HttpUtility.UrlEncode(kvp.Key) +
241 "=" + System.Web.HttpUtility.UrlEncode(kvp.Value.ToString());
242 }
243 else
244 {
245 part = System.Web.HttpUtility.UrlEncode(kvp.Key);
246 }
205 247
206 if (qstring != String.Empty) 248 if (qstring != String.Empty)
207 qstring += "&"; 249 qstring += "&";
208 250
209 qstring += part; 251 qstring += part;
252 }
210 } 253 }
211 254
212 return qstring; 255 return qstring;
diff --git a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
index 490a13a..47bc860 100644
--- a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs
@@ -86,14 +86,14 @@ namespace OpenSim.Server.Handlers.Authentication
86 86
87 private byte[] DoPlainMethods(string body) 87 private byte[] DoPlainMethods(string body)
88 { 88 {
89 Dictionary<string, string> request = 89 Dictionary<string, object> request =
90 ServerUtils.ParseQueryString(body); 90 ServerUtils.ParseQueryString(body);
91 91
92 int lifetime = 30; 92 int lifetime = 30;
93 93
94 if (request.ContainsKey("LIFETIME")) 94 if (request.ContainsKey("LIFETIME"))
95 { 95 {
96 lifetime = Convert.ToInt32(request["LIFETIME"]); 96 lifetime = Convert.ToInt32(request["LIFETIME"].ToString());
97 if (lifetime > 30) 97 if (lifetime > 30)
98 lifetime = 30; 98 lifetime = 30;
99 } 99 }
@@ -103,12 +103,12 @@ namespace OpenSim.Server.Handlers.Authentication
103 if (!request.ContainsKey("PRINCIPAL")) 103 if (!request.ContainsKey("PRINCIPAL"))
104 return FailureResult(); 104 return FailureResult();
105 105
106 string method = request["METHOD"]; 106 string method = request["METHOD"].ToString();
107 107
108 UUID principalID; 108 UUID principalID;
109 string token; 109 string token;
110 110
111 if (!UUID.TryParse(request["PRINCIPAL"], out principalID)) 111 if (!UUID.TryParse(request["PRINCIPAL"].ToString(), out principalID))
112 return FailureResult(); 112 return FailureResult();
113 113
114 switch (method) 114 switch (method)
@@ -117,7 +117,7 @@ namespace OpenSim.Server.Handlers.Authentication
117 if (!request.ContainsKey("PASSWORD")) 117 if (!request.ContainsKey("PASSWORD"))
118 return FailureResult(); 118 return FailureResult();
119 119
120 token = m_AuthenticationService.Authenticate(principalID, request["PASSWORD"], lifetime); 120 token = m_AuthenticationService.Authenticate(principalID, request["PASSWORD"].ToString(), lifetime);
121 121
122 if (token != String.Empty) 122 if (token != String.Empty)
123 return SuccessResult(token); 123 return SuccessResult(token);
@@ -126,7 +126,7 @@ namespace OpenSim.Server.Handlers.Authentication
126 if (!request.ContainsKey("TOKEN")) 126 if (!request.ContainsKey("TOKEN"))
127 return FailureResult(); 127 return FailureResult();
128 128
129 if (m_AuthenticationService.Verify(principalID, request["TOKEN"], lifetime)) 129 if (m_AuthenticationService.Verify(principalID, request["TOKEN"].ToString(), lifetime))
130 return SuccessResult(); 130 return SuccessResult();
131 131
132 return FailureResult(); 132 return FailureResult();
@@ -134,7 +134,7 @@ namespace OpenSim.Server.Handlers.Authentication
134 if (!request.ContainsKey("TOKEN")) 134 if (!request.ContainsKey("TOKEN"))
135 return FailureResult(); 135 return FailureResult();
136 136
137 if (m_AuthenticationService.Release(principalID, request["TOKEN"])) 137 if (m_AuthenticationService.Release(principalID, request["TOKEN"].ToString()))
138 return SuccessResult(); 138 return SuccessResult();
139 139
140 return FailureResult(); 140 return FailureResult();
diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
index 433ed0b..d99b791 100644
--- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs
@@ -69,13 +69,13 @@ namespace OpenSim.Server.Handlers.Grid
69 69
70 try 70 try
71 { 71 {
72 Dictionary<string, string> request = 72 Dictionary<string, object> request =
73 ServerUtils.ParseQueryString(body); 73 ServerUtils.ParseQueryString(body);
74 74
75 if (!request.ContainsKey("METHOD")) 75 if (!request.ContainsKey("METHOD"))
76 return FailureResult(); 76 return FailureResult();
77 77
78 string method = request["METHOD"]; 78 string method = request["METHOD"].ToString();
79 79
80 switch (method) 80 switch (method)
81 { 81 {
@@ -117,22 +117,22 @@ namespace OpenSim.Server.Handlers.Grid
117 117
118 #region Method-specific handlers 118 #region Method-specific handlers
119 119
120 byte[] Register(Dictionary<string, string> request) 120 byte[] Register(Dictionary<string, object> request)
121 { 121 {
122 UUID scopeID = UUID.Zero; 122 UUID scopeID = UUID.Zero;
123 if (request.ContainsKey("SCOPEID")) 123 if (request.ContainsKey("SCOPEID"))
124 UUID.TryParse(request["SCOPEID"], out scopeID); 124 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
125 else 125 else
126 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to register region"); 126 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to register region");
127 127
128 int versionNumberMin = 0, versionNumberMax = 0; 128 int versionNumberMin = 0, versionNumberMax = 0;
129 if (request.ContainsKey("VERSIONMIN")) 129 if (request.ContainsKey("VERSIONMIN"))
130 Int32.TryParse(request["VERSIONMIN"], out versionNumberMin); 130 Int32.TryParse(request["VERSIONMIN"].ToString(), out versionNumberMin);
131 else 131 else
132 m_log.WarnFormat("[GRID HANDLER]: no minimum protocol version in request to register region"); 132 m_log.WarnFormat("[GRID HANDLER]: no minimum protocol version in request to register region");
133 133
134 if (request.ContainsKey("VERSIONMAX")) 134 if (request.ContainsKey("VERSIONMAX"))
135 Int32.TryParse(request["VERSIONMAX"], out versionNumberMax); 135 Int32.TryParse(request["VERSIONMAX"].ToString(), out versionNumberMax);
136 else 136 else
137 m_log.WarnFormat("[GRID HANDLER]: no maximum protocol version in request to register region"); 137 m_log.WarnFormat("[GRID HANDLER]: no maximum protocol version in request to register region");
138 138
@@ -147,8 +147,8 @@ namespace OpenSim.Server.Handlers.Grid
147 GridRegion rinfo = null; 147 GridRegion rinfo = null;
148 try 148 try
149 { 149 {
150 foreach (KeyValuePair<string, string> kvp in request) 150 foreach (KeyValuePair<string, object> kvp in request)
151 rinfoData[kvp.Key] = kvp.Value; 151 rinfoData[kvp.Key] = kvp.Value.ToString();
152 rinfo = new GridRegion(rinfoData); 152 rinfo = new GridRegion(rinfoData);
153 } 153 }
154 catch (Exception e) 154 catch (Exception e)
@@ -166,11 +166,11 @@ namespace OpenSim.Server.Handlers.Grid
166 return FailureResult(); 166 return FailureResult();
167 } 167 }
168 168
169 byte[] Deregister(Dictionary<string, string> request) 169 byte[] Deregister(Dictionary<string, object> request)
170 { 170 {
171 UUID regionID = UUID.Zero; 171 UUID regionID = UUID.Zero;
172 if (request["REGIONID"] != null) 172 if (request.ContainsKey("REGIONID"))
173 UUID.TryParse(request["REGIONID"], out regionID); 173 UUID.TryParse(request["REGIONID"].ToString(), out regionID);
174 else 174 else
175 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to deregister region"); 175 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to deregister region");
176 176
@@ -183,17 +183,17 @@ namespace OpenSim.Server.Handlers.Grid
183 183
184 } 184 }
185 185
186 byte[] GetNeighbours(Dictionary<string, string> request) 186 byte[] GetNeighbours(Dictionary<string, object> request)
187 { 187 {
188 UUID scopeID = UUID.Zero; 188 UUID scopeID = UUID.Zero;
189 if (request["SCOPEID"] != null) 189 if (request.ContainsKey("SCOPEID"))
190 UUID.TryParse(request["SCOPEID"], out scopeID); 190 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
191 else 191 else
192 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours"); 192 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours");
193 193
194 UUID regionID = UUID.Zero; 194 UUID regionID = UUID.Zero;
195 if (request["REGIONID"] != null) 195 if (request.ContainsKey("REGIONID"))
196 UUID.TryParse(request["REGIONID"], out regionID); 196 UUID.TryParse(request["REGIONID"].ToString(), out regionID);
197 else 197 else
198 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours"); 198 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours");
199 199
@@ -221,17 +221,17 @@ namespace OpenSim.Server.Handlers.Grid
221 221
222 } 222 }
223 223
224 byte[] GetRegionByUUID(Dictionary<string, string> request) 224 byte[] GetRegionByUUID(Dictionary<string, object> request)
225 { 225 {
226 UUID scopeID = UUID.Zero; 226 UUID scopeID = UUID.Zero;
227 if (request["SCOPEID"] != null) 227 if (request.ContainsKey("SCOPEID"))
228 UUID.TryParse(request["SCOPEID"], out scopeID); 228 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
229 else 229 else
230 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours"); 230 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get neighbours");
231 231
232 UUID regionID = UUID.Zero; 232 UUID regionID = UUID.Zero;
233 if (request["REGIONID"] != null) 233 if (request.ContainsKey("REGIONID"))
234 UUID.TryParse(request["REGIONID"], out regionID); 234 UUID.TryParse(request["REGIONID"].ToString(), out regionID);
235 else 235 else
236 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours"); 236 m_log.WarnFormat("[GRID HANDLER]: no regionID in request to get neighbours");
237 237
@@ -250,21 +250,21 @@ namespace OpenSim.Server.Handlers.Grid
250 return encoding.GetBytes(xmlString); 250 return encoding.GetBytes(xmlString);
251 } 251 }
252 252
253 byte[] GetRegionByPosition(Dictionary<string, string> request) 253 byte[] GetRegionByPosition(Dictionary<string, object> request)
254 { 254 {
255 UUID scopeID = UUID.Zero; 255 UUID scopeID = UUID.Zero;
256 if (request["SCOPEID"] != null) 256 if (request.ContainsKey("SCOPEID"))
257 UUID.TryParse(request["SCOPEID"], out scopeID); 257 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
258 else 258 else
259 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region by position"); 259 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region by position");
260 260
261 int x = 0, y = 0; 261 int x = 0, y = 0;
262 if (request["X"] != null) 262 if (request.ContainsKey("X"))
263 Int32.TryParse(request["X"], out x); 263 Int32.TryParse(request["X"].ToString(), out x);
264 else 264 else
265 m_log.WarnFormat("[GRID HANDLER]: no X in request to get region by position"); 265 m_log.WarnFormat("[GRID HANDLER]: no X in request to get region by position");
266 if (request["Y"] != null) 266 if (request.ContainsKey("Y"))
267 Int32.TryParse(request["Y"], out y); 267 Int32.TryParse(request["Y"].ToString(), out y);
268 else 268 else
269 m_log.WarnFormat("[GRID HANDLER]: no Y in request to get region by position"); 269 m_log.WarnFormat("[GRID HANDLER]: no Y in request to get region by position");
270 270
@@ -283,17 +283,17 @@ namespace OpenSim.Server.Handlers.Grid
283 return encoding.GetBytes(xmlString); 283 return encoding.GetBytes(xmlString);
284 } 284 }
285 285
286 byte[] GetRegionByName(Dictionary<string, string> request) 286 byte[] GetRegionByName(Dictionary<string, object> request)
287 { 287 {
288 UUID scopeID = UUID.Zero; 288 UUID scopeID = UUID.Zero;
289 if (request["SCOPEID"] != null) 289 if (request.ContainsKey("SCOPEID"))
290 UUID.TryParse(request["SCOPEID"], out scopeID); 290 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
291 else 291 else
292 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region by name"); 292 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region by name");
293 293
294 string regionName = string.Empty; 294 string regionName = string.Empty;
295 if (request["NAME"] != null) 295 if (request.ContainsKey("NAME"))
296 regionName = request["NAME"]; 296 regionName = request["NAME"].ToString();
297 else 297 else
298 m_log.WarnFormat("[GRID HANDLER]: no name in request to get region by name"); 298 m_log.WarnFormat("[GRID HANDLER]: no name in request to get region by name");
299 299
@@ -312,23 +312,23 @@ namespace OpenSim.Server.Handlers.Grid
312 return encoding.GetBytes(xmlString); 312 return encoding.GetBytes(xmlString);
313 } 313 }
314 314
315 byte[] GetRegionsByName(Dictionary<string, string> request) 315 byte[] GetRegionsByName(Dictionary<string, object> request)
316 { 316 {
317 UUID scopeID = UUID.Zero; 317 UUID scopeID = UUID.Zero;
318 if (request["SCOPEID"] != null) 318 if (request.ContainsKey("SCOPEID"))
319 UUID.TryParse(request["SCOPEID"], out scopeID); 319 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
320 else 320 else
321 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get regions by name"); 321 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get regions by name");
322 322
323 string regionName = string.Empty; 323 string regionName = string.Empty;
324 if (request["NAME"] != null) 324 if (request.ContainsKey("NAME"))
325 regionName = request["NAME"]; 325 regionName = request["NAME"].ToString();
326 else 326 else
327 m_log.WarnFormat("[GRID HANDLER]: no NAME in request to get regions by name"); 327 m_log.WarnFormat("[GRID HANDLER]: no NAME in request to get regions by name");
328 328
329 int max = 0; 329 int max = 0;
330 if (request["MAX"] != null) 330 if (request.ContainsKey("MAX"))
331 Int32.TryParse(request["MAX"], out max); 331 Int32.TryParse(request["MAX"].ToString(), out max);
332 else 332 else
333 m_log.WarnFormat("[GRID HANDLER]: no MAX in request to get regions by name"); 333 m_log.WarnFormat("[GRID HANDLER]: no MAX in request to get regions by name");
334 334
@@ -355,30 +355,30 @@ namespace OpenSim.Server.Handlers.Grid
355 return encoding.GetBytes(xmlString); 355 return encoding.GetBytes(xmlString);
356 } 356 }
357 357
358 byte[] GetRegionRange(Dictionary<string, string> request) 358 byte[] GetRegionRange(Dictionary<string, object> request)
359 { 359 {
360 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange"); 360 //m_log.DebugFormat("[GRID HANDLER]: GetRegionRange");
361 UUID scopeID = UUID.Zero; 361 UUID scopeID = UUID.Zero;
362 if (request.ContainsKey("SCOPEID")) 362 if (request.ContainsKey("SCOPEID"))
363 UUID.TryParse(request["SCOPEID"], out scopeID); 363 UUID.TryParse(request["SCOPEID"].ToString(), out scopeID);
364 else 364 else
365 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region range"); 365 m_log.WarnFormat("[GRID HANDLER]: no scopeID in request to get region range");
366 366
367 int xmin = 0, xmax = 0, ymin = 0, ymax = 0; 367 int xmin = 0, xmax = 0, ymin = 0, ymax = 0;
368 if (request.ContainsKey("XMIN")) 368 if (request.ContainsKey("XMIN"))
369 Int32.TryParse(request["XMIN"], out xmin); 369 Int32.TryParse(request["XMIN"].ToString(), out xmin);
370 else 370 else
371 m_log.WarnFormat("[GRID HANDLER]: no XMIN in request to get region range"); 371 m_log.WarnFormat("[GRID HANDLER]: no XMIN in request to get region range");
372 if (request.ContainsKey("XMAX")) 372 if (request.ContainsKey("XMAX"))
373 Int32.TryParse(request["XMAX"], out xmax); 373 Int32.TryParse(request["XMAX"].ToString(), out xmax);
374 else 374 else
375 m_log.WarnFormat("[GRID HANDLER]: no XMAX in request to get region range"); 375 m_log.WarnFormat("[GRID HANDLER]: no XMAX in request to get region range");
376 if (request.ContainsKey("YMIN")) 376 if (request.ContainsKey("YMIN"))
377 Int32.TryParse(request["YMIN"], out ymin); 377 Int32.TryParse(request["YMIN"].ToString(), out ymin);
378 else 378 else
379 m_log.WarnFormat("[GRID HANDLER]: no YMIN in request to get region range"); 379 m_log.WarnFormat("[GRID HANDLER]: no YMIN in request to get region range");
380 if (request.ContainsKey("YMAX")) 380 if (request.ContainsKey("YMAX"))
381 Int32.TryParse(request["YMAX"], out ymax); 381 Int32.TryParse(request["YMAX"].ToString(), out ymax);
382 else 382 else
383 m_log.WarnFormat("[GRID HANDLER]: no YMAX in request to get region range"); 383 m_log.WarnFormat("[GRID HANDLER]: no YMAX in request to get region range");
384 384
diff --git a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
index 2558fa0..11adc4a 100644
--- a/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Presence/PresenceServerPostHandler.cs
@@ -68,18 +68,30 @@ namespace OpenSim.Server.Handlers.Presence
68 68
69 try 69 try
70 { 70 {
71 Dictionary<string, string> request = 71 Dictionary<string, object> request =
72 ServerUtils.ParseQueryString(body); 72 ServerUtils.ParseQueryString(body);
73 73
74 if (!request.ContainsKey("METHOD")) 74 if (!request.ContainsKey("METHOD"))
75 return FailureResult(); 75 return FailureResult();
76 76
77 string method = request["METHOD"]; 77 string method = request["METHOD"].ToString();
78 78
79 switch (method) 79 switch (method)
80 { 80 {
81 case "login":
82 return LoginAgent(request);
83 case "logout":
84 return LogoutAgent(request);
85 case "logoutregion":
86 return LogoutRegionAgents(request);
81 case "report": 87 case "report":
82 return Report(request); 88 return Report(request);
89 case "getagent":
90 return GetAgent(request);
91 case "getagents":
92 return GetAgents(request);
93 case "sethome":
94 return SetHome(request);
83 } 95 }
84 m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method); 96 m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method);
85 } 97 }
@@ -92,38 +104,153 @@ namespace OpenSim.Server.Handlers.Presence
92 104
93 } 105 }
94 106
95 byte[] Report(Dictionary<string, string> request) 107 byte[] LoginAgent(Dictionary<string, object> request)
96 { 108 {
97 PresenceInfo info = new PresenceInfo(); 109 string user = String.Empty;
98 info.Data = new Dictionary<string, string>(); 110 UUID session = UUID.Zero;
111 UUID ssession = UUID.Zero;
99 112
100 if (request["PrincipalID"] == null || request["RegionID"] == null) 113 if (!request.ContainsKey("UserID") || !request.ContainsKey("SessionID"))
101 return FailureResult(); 114 return FailureResult();
102 115
103 if (!UUID.TryParse(request["PrincipalID"].ToString(), 116 user = request["UserID"].ToString();
104 out info.PrincipalID)) 117
118 if (!UUID.TryParse(request["SessionID"].ToString(), out session))
105 return FailureResult(); 119 return FailureResult();
106 120
107 if (!UUID.TryParse(request["RegionID"].ToString(), 121 if (request.ContainsKey("SecureSessionID"))
108 out info.RegionID)) 122 // If it's malformed, we go on with a Zero on it
123 UUID.TryParse(request["SecureSessionID"].ToString(), out ssession);
124
125 if (m_PresenceService.LoginAgent(user, session, ssession))
126 return SuccessResult();
127
128 return FailureResult();
129 }
130
131 byte[] LogoutAgent(Dictionary<string, object> request)
132 {
133 UUID session = UUID.Zero;
134
135 if (!request.ContainsKey("SessionID"))
109 return FailureResult(); 136 return FailureResult();
110 137
111 foreach (KeyValuePair<string, string> kvp in request) 138 if (!UUID.TryParse(request["SessionID"].ToString(), out session))
112 { 139 return FailureResult();
113 if (kvp.Key == "METHOD" ||
114 kvp.Key == "PrincipalID" ||
115 kvp.Key == "RegionID")
116 continue;
117 140
118 info.Data[kvp.Key] = kvp.Value; 141 if (m_PresenceService.LogoutAgent(session))
119 } 142 return SuccessResult();
143
144 return FailureResult();
145 }
146
147 byte[] LogoutRegionAgents(Dictionary<string, object> request)
148 {
149 UUID region = UUID.Zero;
150
151 if (!request.ContainsKey("RegionID"))
152 return FailureResult();
120 153
121 if (m_PresenceService.Report(info)) 154 if (!UUID.TryParse(request["RegionID"].ToString(), out region))
155 return FailureResult();
156
157 if (m_PresenceService.LogoutRegionAgents(region))
122 return SuccessResult(); 158 return SuccessResult();
123 159
124 return FailureResult(); 160 return FailureResult();
125 } 161 }
162
163 byte[] Report(Dictionary<string, object> request)
164 {
165 UUID session = UUID.Zero;
166 UUID region = UUID.Zero;
167 Vector3 position = new Vector3(128, 128, 70);
168 Vector3 look = Vector3.Zero;
169
170 if (!request.ContainsKey("SessionID") || !request.ContainsKey("RegionID"))
171 return FailureResult();
172
173 if (!UUID.TryParse(request["SessionID"].ToString(), out session))
174 return FailureResult();
175
176 if (!UUID.TryParse(request["RegionID"].ToString(), out region))
177 return FailureResult();
178
179 if (request.ContainsKey("position"))
180 Vector3.TryParse(request["position"].ToString(), out position);
181
182 if (request.ContainsKey("lookAt"))
183 Vector3.TryParse(request["lookAt"].ToString(), out look);
184
185 if (m_PresenceService.ReportAgent(session, region, position, look))
186 return SuccessResult();
187
188 return FailureResult();
189 }
190
191 byte[] GetAgent(Dictionary<string, object> request)
192 {
193 UUID session = UUID.Zero;
194
195 if (!request.ContainsKey("SessionID"))
196 return FailureResult();
126 197
198 if (!UUID.TryParse(request["SessionID"].ToString(), out session))
199 return FailureResult();
200
201 PresenceInfo pinfo = m_PresenceService.GetAgent(session);
202
203 Dictionary<string, object> result = new Dictionary<string, object>();
204 if (pinfo == null)
205 result["result"] = "null";
206 else
207 result["result"] = pinfo.ToKeyValuePairs();
208
209 string xmlString = ServerUtils.BuildXmlResponse(result);
210 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
211 UTF8Encoding encoding = new UTF8Encoding();
212 return encoding.GetBytes(xmlString);
213 }
214
215 byte[] GetAgents(Dictionary<string, object> request)
216 {
217
218 string[] userIDs;
219
220 if (!request.ContainsKey("uuids"))
221 return FailureResult();
222
223 if (!(request["uuids"] is List<string>))
224 {
225 m_log.DebugFormat("[PRESENCE HANDLER]: GetAgents input argument was of unexpected type {0}", request["uuids"].GetType().ToString());
226 return FailureResult();
227 }
228
229 userIDs = ((List<string>)request["uuids"]).ToArray();
230
231 PresenceInfo[] pinfos = m_PresenceService.GetAgents(userIDs);
232
233 Dictionary<string, object> result = new Dictionary<string, object>();
234 if ((pinfos == null) || ((pinfos != null) && (pinfos.Length == 0)))
235 result["result"] = "null";
236 else
237 {
238 int i = 0;
239 foreach (PresenceInfo pinfo in pinfos)
240 {
241 Dictionary<string, object> rinfoDict = pinfo.ToKeyValuePairs();
242 result["presence" + i] = rinfoDict;
243 i++;
244 }
245 }
246
247 string xmlString = ServerUtils.BuildXmlResponse(result);
248 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
249 UTF8Encoding encoding = new UTF8Encoding();
250 return encoding.GetBytes(xmlString);
251 }
252
253
127 private byte[] SuccessResult() 254 private byte[] SuccessResult()
128 { 255 {
129 XmlDocument doc = new XmlDocument(); 256 XmlDocument doc = new XmlDocument();
@@ -138,7 +265,7 @@ namespace OpenSim.Server.Handlers.Presence
138 265
139 doc.AppendChild(rootElement); 266 doc.AppendChild(rootElement);
140 267
141 XmlElement result = doc.CreateElement("", "Result", ""); 268 XmlElement result = doc.CreateElement("", "result", "");
142 result.AppendChild(doc.CreateTextNode("Success")); 269 result.AppendChild(doc.CreateTextNode("Success"));
143 270
144 rootElement.AppendChild(result); 271 rootElement.AppendChild(result);
@@ -160,7 +287,7 @@ namespace OpenSim.Server.Handlers.Presence
160 287
161 doc.AppendChild(rootElement); 288 doc.AppendChild(rootElement);
162 289
163 XmlElement result = doc.CreateElement("", "Result", ""); 290 XmlElement result = doc.CreateElement("", "result", "");
164 result.AppendChild(doc.CreateTextNode("Failure")); 291 result.AppendChild(doc.CreateTextNode("Failure"));
165 292
166 rootElement.AppendChild(result); 293 rootElement.AppendChild(result);
@@ -178,5 +305,32 @@ namespace OpenSim.Server.Handlers.Presence
178 305
179 return ms.ToArray(); 306 return ms.ToArray();
180 } 307 }
308
309 byte[] SetHome(Dictionary<string, object> request)
310 {
311 UUID region = UUID.Zero;
312 Vector3 position = new Vector3(128, 128, 70);
313 Vector3 look = Vector3.Zero;
314
315 if (!request.ContainsKey("SessionID") || !request.ContainsKey("RegionID"))
316 return FailureResult();
317
318 string user = request["UserID"].ToString();
319
320 if (!UUID.TryParse(request["RegionID"].ToString(), out region))
321 return FailureResult();
322
323 if (request.ContainsKey("position"))
324 Vector3.TryParse(request["position"].ToString(), out position);
325
326 if (request.ContainsKey("lookAt"))
327 Vector3.TryParse(request["lookAt"].ToString(), out look);
328
329 if (m_PresenceService.SetHomeLocation(user, region, position, look))
330 return SuccessResult();
331
332 return FailureResult();
333 }
334
181 } 335 }
182} 336}
diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerConnector.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerConnector.cs
new file mode 100644
index 0000000..f17a8de
--- /dev/null
+++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerConnector.cs
@@ -0,0 +1,61 @@
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.UserAccounts
36{
37 public class UserAccountServiceConnector : ServiceConnector
38 {
39 private IUserAccountService m_UserAccountService;
40 private string m_ConfigName = "UserAccountService";
41
42 public UserAccountServiceConnector(IConfigSource config, IHttpServer server, string configName) :
43 base(config, server, configName)
44 {
45 IConfig serverConfig = config.Configs[m_ConfigName];
46 if (serverConfig == null)
47 throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
48
49 string service = serverConfig.GetString("LocalServiceModule",
50 String.Empty);
51
52 if (service == String.Empty)
53 throw new Exception("No LocalServiceModule in config file");
54
55 Object[] args = new Object[] { config };
56 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(service, args);
57
58 server.AddStreamHandler(new UserAccountServerPostHandler(m_UserAccountService));
59 }
60 }
61}
diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
new file mode 100644
index 0000000..a92148c
--- /dev/null
+++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs
@@ -0,0 +1,276 @@
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 OpenSim.Framework;
42using OpenSim.Framework.Servers.HttpServer;
43using OpenMetaverse;
44
45namespace OpenSim.Server.Handlers.UserAccounts
46{
47 public class UserAccountServerPostHandler : BaseStreamHandler
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IUserAccountService m_UserAccountService;
52
53 public UserAccountServerPostHandler(IUserAccountService service) :
54 base("POST", "/accounts")
55 {
56 m_UserAccountService = service;
57 }
58
59 public override byte[] Handle(string path, Stream requestData,
60 OSHttpRequest httpRequest, OSHttpResponse httpResponse)
61 {
62 StreamReader sr = new StreamReader(requestData);
63 string body = sr.ReadToEnd();
64 sr.Close();
65 body = body.Trim();
66
67 // We need to check the authorization header
68 //httpRequest.Headers["authorization"] ...
69
70 //m_log.DebugFormat("[XXX]: query String: {0}", body);
71
72 try
73 {
74 Dictionary<string, object> request =
75 ServerUtils.ParseQueryString(body);
76
77 if (!request.ContainsKey("METHOD"))
78 return FailureResult();
79
80 string method = request["METHOD"].ToString();
81
82 switch (method)
83 {
84 case "getaccount":
85 return GetAccount(request);
86 case "getaccounts":
87 return GetAccounts(request);
88 case "createaccount":
89 return CreateAccount(request);
90 case "setaccount":
91 return SetAccount(request);
92 }
93 m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method);
94 }
95 catch (Exception e)
96 {
97 m_log.Debug("[PRESENCE HANDLER]: Exception {0}" + e);
98 }
99
100 return FailureResult();
101
102 }
103
104 byte[] GetAccount(Dictionary<string, object> request)
105 {
106 UserAccount account = null;
107 UUID scopeID = UUID.Zero;
108 Dictionary<string, object> result = new Dictionary<string, object>();
109
110 if (!request.ContainsKey("ScopeID"))
111 {
112 result["result"] = "null";
113 return ResultToBytes(result);
114 }
115
116 if (!UUID.TryParse(request["ScopeID"].ToString(), out scopeID))
117 {
118 result["result"] = "null";
119 return ResultToBytes(result);
120 }
121
122 if (request.ContainsKey("UserID") && request["UserID"] != null)
123 {
124 UUID userID;
125 if (UUID.TryParse(request["UserID"].ToString(), out userID))
126 account = m_UserAccountService.GetUserAccount(scopeID, userID);
127 }
128
129 else if (request.ContainsKey("Email") && request["Email"] != null)
130 account = m_UserAccountService.GetUserAccount(scopeID, request["Email"].ToString());
131
132 else if (request.ContainsKey("FirstName") && request.ContainsKey("LastName") &&
133 request["FirstName"] != null && request["LastName"] != null)
134 account = m_UserAccountService.GetUserAccount(scopeID, request["FirstName"].ToString(), request["LastName"].ToString());
135
136 if (account == null)
137 result["result"] = "null";
138 else
139 result["result"] = account.ToKeyValuePairs();
140
141 return ResultToBytes(result);
142 }
143
144 byte[] GetAccounts(Dictionary<string, object> request)
145 {
146 if (!request.ContainsKey("ScopeID") || !request.ContainsKey("query"))
147 return FailureResult();
148
149 UUID scopeID = UUID.Zero;
150 if (!UUID.TryParse(request["ScopeID"].ToString(), out scopeID))
151 return FailureResult();
152
153 string query = request["query"].ToString();
154
155 List<UserAccount> accounts = m_UserAccountService.GetUserAccounts(scopeID, query);
156
157 Dictionary<string, object> result = new Dictionary<string, object>();
158 if ((accounts == null) || ((accounts != null) && (accounts.Count == 0)))
159 result["result"] = "null";
160 else
161 {
162 int i = 0;
163 foreach (UserAccount acc in accounts)
164 {
165 Dictionary<string, object> rinfoDict = acc.ToKeyValuePairs();
166 result["account" + i] = rinfoDict;
167 i++;
168 }
169 }
170
171 string xmlString = ServerUtils.BuildXmlResponse(result);
172 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
173 UTF8Encoding encoding = new UTF8Encoding();
174 return encoding.GetBytes(xmlString);
175 }
176
177 byte[] CreateAccount(Dictionary<string, object> request)
178 {
179 if (!request.ContainsKey("account"))
180 return FailureResult();
181 if (request["account"] == null)
182 return FailureResult();
183 if (!(request["account"] is Dictionary<string, object>))
184 return FailureResult();
185
186 UserAccount account = new UserAccount((Dictionary<string, object>) request["account"]);
187
188 if (m_UserAccountService.CreateUserAccount(account))
189 return SuccessResult();
190
191 return FailureResult();
192 }
193
194 byte[] SetAccount(Dictionary<string, object> request)
195 {
196 if (!request.ContainsKey("account"))
197 return FailureResult();
198 if (request["account"] == null)
199 return FailureResult();
200 if (!(request["account"] is Dictionary<string, object>))
201 return FailureResult();
202
203 UserAccount account = new UserAccount((Dictionary<string, object>)request["account"]);
204
205 if (m_UserAccountService.SetUserAccount(account))
206 return SuccessResult();
207
208 return FailureResult();
209 }
210
211 private byte[] SuccessResult()
212 {
213 XmlDocument doc = new XmlDocument();
214
215 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
216 "", "");
217
218 doc.AppendChild(xmlnode);
219
220 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
221 "");
222
223 doc.AppendChild(rootElement);
224
225 XmlElement result = doc.CreateElement("", "result", "");
226 result.AppendChild(doc.CreateTextNode("Success"));
227
228 rootElement.AppendChild(result);
229
230 return DocToBytes(doc);
231 }
232
233 private byte[] FailureResult()
234 {
235 XmlDocument doc = new XmlDocument();
236
237 XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
238 "", "");
239
240 doc.AppendChild(xmlnode);
241
242 XmlElement rootElement = doc.CreateElement("", "ServerResponse",
243 "");
244
245 doc.AppendChild(rootElement);
246
247 XmlElement result = doc.CreateElement("", "result", "");
248 result.AppendChild(doc.CreateTextNode("Failure"));
249
250 rootElement.AppendChild(result);
251
252 return DocToBytes(doc);
253 }
254
255 private byte[] DocToBytes(XmlDocument doc)
256 {
257 MemoryStream ms = new MemoryStream();
258 XmlTextWriter xw = new XmlTextWriter(ms, null);
259 xw.Formatting = Formatting.Indented;
260 doc.WriteTo(xw);
261 xw.Flush();
262
263 return ms.ToArray();
264 }
265
266 private byte[] ResultToBytes(Dictionary<string, object> result)
267 {
268 string xmlString = ServerUtils.BuildXmlResponse(result);
269 //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
270 UTF8Encoding encoding = new UTF8Encoding();
271 return encoding.GetBytes(xmlString);
272 }
273
274
275 }
276}
diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
index 50e817e..19bb3e2 100644
--- a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Services.Connectors
84 84
85 public string Authenticate(UUID principalID, string password, int lifetime) 85 public string Authenticate(UUID principalID, string password, int lifetime)
86 { 86 {
87 Dictionary<string, string> sendData = new Dictionary<string, string>(); 87 Dictionary<string, object> sendData = new Dictionary<string, object>();
88 sendData["LIFETIME"] = lifetime.ToString(); 88 sendData["LIFETIME"] = lifetime.ToString();
89 sendData["PRINCIPAL"] = principalID.ToString(); 89 sendData["PRINCIPAL"] = principalID.ToString();
90 sendData["PASSWORD"] = password; 90 sendData["PASSWORD"] = password;
@@ -106,7 +106,7 @@ namespace OpenSim.Services.Connectors
106 106
107 public bool Verify(UUID principalID, string token, int lifetime) 107 public bool Verify(UUID principalID, string token, int lifetime)
108 { 108 {
109 Dictionary<string, string> sendData = new Dictionary<string, string>(); 109 Dictionary<string, object> sendData = new Dictionary<string, object>();
110 sendData["LIFETIME"] = lifetime.ToString(); 110 sendData["LIFETIME"] = lifetime.ToString();
111 sendData["PRINCIPAL"] = principalID.ToString(); 111 sendData["PRINCIPAL"] = principalID.ToString();
112 sendData["TOKEN"] = token; 112 sendData["TOKEN"] = token;
@@ -128,7 +128,7 @@ namespace OpenSim.Services.Connectors
128 128
129 public bool Release(UUID principalID, string token) 129 public bool Release(UUID principalID, string token)
130 { 130 {
131 Dictionary<string, string> sendData = new Dictionary<string, string>(); 131 Dictionary<string, object> sendData = new Dictionary<string, object>();
132 sendData["PRINCIPAL"] = principalID.ToString(); 132 sendData["PRINCIPAL"] = principalID.ToString();
133 sendData["TOKEN"] = token; 133 sendData["TOKEN"] = token;
134 134
diff --git a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
index 02f2b79..99aa3fb 100644
--- a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
@@ -89,7 +89,7 @@ namespace OpenSim.Services.Connectors
89 public virtual bool RegisterRegion(UUID scopeID, GridRegion regionInfo) 89 public virtual bool RegisterRegion(UUID scopeID, GridRegion regionInfo)
90 { 90 {
91 Dictionary<string, object> rinfo = regionInfo.ToKeyValuePairs(); 91 Dictionary<string, object> rinfo = regionInfo.ToKeyValuePairs();
92 Dictionary<string, string> sendData = new Dictionary<string,string>(); 92 Dictionary<string, object> sendData = new Dictionary<string,object>();
93 foreach (KeyValuePair<string, object> kvp in rinfo) 93 foreach (KeyValuePair<string, object> kvp in rinfo)
94 sendData[kvp.Key] = (string)kvp.Value; 94 sendData[kvp.Key] = (string)kvp.Value;
95 95
@@ -130,7 +130,7 @@ namespace OpenSim.Services.Connectors
130 130
131 public virtual bool DeregisterRegion(UUID regionID) 131 public virtual bool DeregisterRegion(UUID regionID)
132 { 132 {
133 Dictionary<string, string> sendData = new Dictionary<string, string>(); 133 Dictionary<string, object> sendData = new Dictionary<string, object>();
134 134
135 sendData["REGIONID"] = regionID.ToString(); 135 sendData["REGIONID"] = regionID.ToString();
136 136
@@ -162,7 +162,7 @@ namespace OpenSim.Services.Connectors
162 162
163 public virtual List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID) 163 public virtual List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
164 { 164 {
165 Dictionary<string, string> sendData = new Dictionary<string, string>(); 165 Dictionary<string, object> sendData = new Dictionary<string, object>();
166 166
167 sendData["SCOPEID"] = scopeID.ToString(); 167 sendData["SCOPEID"] = scopeID.ToString();
168 sendData["REGIONID"] = regionID.ToString(); 168 sendData["REGIONID"] = regionID.ToString();
@@ -212,7 +212,7 @@ namespace OpenSim.Services.Connectors
212 212
213 public virtual GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 213 public virtual GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
214 { 214 {
215 Dictionary<string, string> sendData = new Dictionary<string, string>(); 215 Dictionary<string, object> sendData = new Dictionary<string, object>();
216 216
217 sendData["SCOPEID"] = scopeID.ToString(); 217 sendData["SCOPEID"] = scopeID.ToString();
218 sendData["REGIONID"] = regionID.ToString(); 218 sendData["REGIONID"] = regionID.ToString();
@@ -258,7 +258,7 @@ namespace OpenSim.Services.Connectors
258 258
259 public virtual GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 259 public virtual GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
260 { 260 {
261 Dictionary<string, string> sendData = new Dictionary<string, string>(); 261 Dictionary<string, object> sendData = new Dictionary<string, object>();
262 262
263 sendData["SCOPEID"] = scopeID.ToString(); 263 sendData["SCOPEID"] = scopeID.ToString();
264 sendData["X"] = x.ToString(); 264 sendData["X"] = x.ToString();
@@ -303,7 +303,7 @@ namespace OpenSim.Services.Connectors
303 303
304 public virtual GridRegion GetRegionByName(UUID scopeID, string regionName) 304 public virtual GridRegion GetRegionByName(UUID scopeID, string regionName)
305 { 305 {
306 Dictionary<string, string> sendData = new Dictionary<string, string>(); 306 Dictionary<string, object> sendData = new Dictionary<string, object>();
307 307
308 sendData["SCOPEID"] = scopeID.ToString(); 308 sendData["SCOPEID"] = scopeID.ToString();
309 sendData["NAME"] = regionName; 309 sendData["NAME"] = regionName;
@@ -344,7 +344,7 @@ namespace OpenSim.Services.Connectors
344 344
345 public virtual List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber) 345 public virtual List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
346 { 346 {
347 Dictionary<string, string> sendData = new Dictionary<string, string>(); 347 Dictionary<string, object> sendData = new Dictionary<string, object>();
348 348
349 sendData["SCOPEID"] = scopeID.ToString(); 349 sendData["SCOPEID"] = scopeID.ToString();
350 sendData["NAME"] = name; 350 sendData["NAME"] = name;
@@ -396,7 +396,7 @@ namespace OpenSim.Services.Connectors
396 396
397 public virtual List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax) 397 public virtual List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
398 { 398 {
399 Dictionary<string, string> sendData = new Dictionary<string, string>(); 399 Dictionary<string, object> sendData = new Dictionary<string, object>();
400 400
401 sendData["SCOPEID"] = scopeID.ToString(); 401 sendData["SCOPEID"] = scopeID.ToString();
402 sendData["XMIN"] = xmin.ToString(); 402 sendData["XMIN"] = xmin.ToString();
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
new file mode 100644
index 0000000..29cfd6e
--- /dev/null
+++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
@@ -0,0 +1,421 @@
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.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class PresenceServicesConnector : IPresenceService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49
50 private string m_ServerURI = String.Empty;
51
52 public PresenceServicesConnector()
53 {
54 }
55
56 public PresenceServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public PresenceServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["PresenceService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini");
72 throw new Exception("Presence connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("PresenceServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[PRESENCE CONNECTOR]: No Server URI named in section PresenceService");
81 throw new Exception("Presence connector init error");
82 }
83 m_ServerURI = serviceURI;
84 }
85
86
87 #region IPresenceService
88
89 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
90 {
91 Dictionary<string, object> sendData = new Dictionary<string, object>();
92 //sendData["SCOPEID"] = scopeID.ToString();
93 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
94 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
95 sendData["METHOD"] = "login";
96
97 sendData["UserID"] = userID;
98 sendData["SessionID"] = sessionID.ToString();
99 sendData["SecureSessionID"] = secureSessionID.ToString();
100
101 string reqString = ServerUtils.BuildQueryString(sendData);
102 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
103 try
104 {
105 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
106 m_ServerURI + "/presence",
107 reqString);
108 if (reply != string.Empty)
109 {
110 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
111
112 if (replyData.ContainsKey("result"))
113 {
114 if (replyData["result"].ToString().ToLower() == "success")
115 return true;
116 else
117 return false;
118 }
119 else
120 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent reply data does not contain result field");
121
122 }
123 else
124 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent received empty reply");
125 }
126 catch (Exception e)
127 {
128 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
129 }
130
131 return false;
132
133 }
134
135 public bool LogoutAgent(UUID sessionID)
136 {
137 Dictionary<string, object> sendData = new Dictionary<string, object>();
138 //sendData["SCOPEID"] = scopeID.ToString();
139 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
140 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
141 sendData["METHOD"] = "logout";
142
143 sendData["SessionID"] = sessionID.ToString();
144
145 string reqString = ServerUtils.BuildQueryString(sendData);
146 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
147 try
148 {
149 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
150 m_ServerURI + "/presence",
151 reqString);
152 if (reply != string.Empty)
153 {
154 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
155
156 if (replyData.ContainsKey("result"))
157 {
158 if (replyData["result"].ToString().ToLower() == "success")
159 return true;
160 else
161 return false;
162 }
163 else
164 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent reply data does not contain result field");
165
166 }
167 else
168 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent received empty reply");
169 }
170 catch (Exception e)
171 {
172 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
173 }
174
175 return false;
176 }
177
178 public bool LogoutRegionAgents(UUID regionID)
179 {
180 Dictionary<string, object> sendData = new Dictionary<string, object>();
181 //sendData["SCOPEID"] = scopeID.ToString();
182 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
183 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
184 sendData["METHOD"] = "logoutregion";
185
186 sendData["RegionID"] = regionID.ToString();
187
188 string reqString = ServerUtils.BuildQueryString(sendData);
189 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
190 try
191 {
192 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
193 m_ServerURI + "/presence",
194 reqString);
195 if (reply != string.Empty)
196 {
197 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
198
199 if (replyData.ContainsKey("result"))
200 {
201 if (replyData["result"].ToString().ToLower() == "success")
202 return true;
203 else
204 return false;
205 }
206 else
207 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents reply data does not contain result field");
208
209 }
210 else
211 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents received empty reply");
212 }
213 catch (Exception e)
214 {
215 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
216 }
217
218 return false;
219 }
220
221 public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
222 {
223 Dictionary<string, object> sendData = new Dictionary<string, object>();
224 //sendData["SCOPEID"] = scopeID.ToString();
225 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
226 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
227 sendData["METHOD"] = "report";
228
229 sendData["SessionID"] = sessionID.ToString();
230 sendData["RegionID"] = regionID.ToString();
231 sendData["position"] = position.ToString();
232 sendData["lookAt"] = lookAt.ToString();
233
234 string reqString = ServerUtils.BuildQueryString(sendData);
235 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
236 try
237 {
238 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
239 m_ServerURI + "/presence",
240 reqString);
241 if (reply != string.Empty)
242 {
243 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
244
245 if (replyData.ContainsKey("result"))
246 {
247 if (replyData["result"].ToString().ToLower() == "success")
248 return true;
249 else
250 return false;
251 }
252 else
253 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent reply data does not contain result field");
254
255 }
256 else
257 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent received empty reply");
258 }
259 catch (Exception e)
260 {
261 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
262 }
263
264 return false;
265 }
266
267 public PresenceInfo GetAgent(UUID sessionID)
268 {
269 Dictionary<string, object> sendData = new Dictionary<string, object>();
270 //sendData["SCOPEID"] = scopeID.ToString();
271 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
272 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
273 sendData["METHOD"] = "getagent";
274
275 sendData["SessionID"] = sessionID.ToString();
276
277 string reply = string.Empty;
278 string reqString = ServerUtils.BuildQueryString(sendData);
279 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
280 try
281 {
282 reply = SynchronousRestFormsRequester.MakeRequest("POST",
283 m_ServerURI + "/presence",
284 reqString);
285 if (reply == null || (reply != null && reply == string.Empty))
286 {
287 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply");
288 return null;
289 }
290 }
291 catch (Exception e)
292 {
293 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
294 }
295
296 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
297 PresenceInfo pinfo = null;
298
299 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
300 {
301 if (replyData["result"] is Dictionary<string, object>)
302 {
303 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]);
304 }
305 }
306
307 return pinfo;
308 }
309
310 public PresenceInfo[] GetAgents(string[] userIDs)
311 {
312 Dictionary<string, object> sendData = new Dictionary<string, object>();
313 //sendData["SCOPEID"] = scopeID.ToString();
314 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
315 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
316 sendData["METHOD"] = "getagents";
317
318 sendData["uuids"] = new List<string>(userIDs);
319
320 string reply = string.Empty;
321 string reqString = ServerUtils.BuildQueryString(sendData);
322 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
323 try
324 {
325 reply = SynchronousRestFormsRequester.MakeRequest("POST",
326 m_ServerURI + "/presence",
327 reqString);
328 if (reply == null || (reply != null && reply == string.Empty))
329 {
330 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply");
331 return null;
332 }
333 }
334 catch (Exception e)
335 {
336 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
337 }
338
339 List<PresenceInfo> rinfos = new List<PresenceInfo>();
340
341 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
342
343 if (replyData != null)
344 {
345 if (replyData.ContainsKey("result") &&
346 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
347 {
348 return new PresenceInfo[0];
349 }
350
351 Dictionary<string, object>.ValueCollection pinfosList = replyData.Values;
352 //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
353 foreach (object presence in pinfosList)
354 {
355 if (presence is Dictionary<string, object>)
356 {
357 PresenceInfo pinfo = new PresenceInfo((Dictionary<string, object>)presence);
358 rinfos.Add(pinfo);
359 }
360 else
361 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received invalid response type {0}",
362 presence.GetType());
363 }
364 }
365 else
366 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null response");
367
368 return rinfos.ToArray();
369 }
370
371
372 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
373 {
374 Dictionary<string, object> sendData = new Dictionary<string, object>();
375 //sendData["SCOPEID"] = scopeID.ToString();
376 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
377 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
378 sendData["METHOD"] = "sethome";
379
380 sendData["UserID"] = userID;
381 sendData["RegionID"] = regionID.ToString();
382 sendData["position"] = position.ToString();
383 sendData["lookAt"] = lookAt.ToString();
384
385 string reqString = ServerUtils.BuildQueryString(sendData);
386 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
387 try
388 {
389 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
390 m_ServerURI + "/presence",
391 reqString);
392 if (reply != string.Empty)
393 {
394 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
395
396 if (replyData.ContainsKey("result"))
397 {
398 if (replyData["result"].ToString().ToLower() == "success")
399 return true;
400 else
401 return false;
402 }
403 else
404 m_log.DebugFormat("[PRESENCE CONNECTOR]: SetHomeLocation reply data does not contain result field");
405
406 }
407 else
408 m_log.DebugFormat("[PRESENCE CONNECTOR]: SetHomeLocation received empty reply");
409 }
410 catch (Exception e)
411 {
412 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
413 }
414
415 return false;
416 }
417
418 #endregion
419
420 }
421}
diff --git a/OpenSim/Services/Connectors/User/UserServiceConnector.cs b/OpenSim/Services/Connectors/User/UserServiceConnector.cs
deleted file mode 100644
index 683990f..0000000
--- a/OpenSim/Services/Connectors/User/UserServiceConnector.cs
+++ /dev/null
@@ -1,114 +0,0 @@
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.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class UserServicesConnector : IUserAccountService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48// private string m_ServerURI = String.Empty;
49
50 public UserServicesConnector()
51 {
52 }
53
54 public UserServicesConnector(string serverURI)
55 {
56// m_ServerURI = serverURI.TrimEnd('/');
57 }
58
59 public UserServicesConnector(IConfigSource source)
60 {
61 Initialise(source);
62 }
63
64 public virtual void Initialise(IConfigSource source)
65 {
66 IConfig assetConfig = source.Configs["UserService"];
67 if (assetConfig == null)
68 {
69 m_log.Error("[USER CONNECTOR]: UserService missing from OpanSim.ini");
70 throw new Exception("User connector init error");
71 }
72
73 string serviceURI = assetConfig.GetString("UserServerURI",
74 String.Empty);
75
76 if (serviceURI == String.Empty)
77 {
78 m_log.Error("[USER CONNECTOR]: No Server URI named in section UserService");
79 throw new Exception("User connector init error");
80 }
81 //m_ServerURI = serviceURI;
82 }
83
84 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
85 {
86 return null;
87 }
88
89 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
90 {
91 return null;
92 }
93
94 public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret)
95 {
96 return false;
97 }
98
99 public bool SetUserAccount(UserAccount data, UUID principalID, string token)
100 {
101 return false;
102 }
103
104 public bool CreateUserAccount(UserAccount data, UUID principalID, string token)
105 {
106 return false;
107 }
108
109 public List<UserAccount> GetUserAccount(UUID scopeID, string query)
110 {
111 return null;
112 }
113 }
114}
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
new file mode 100644
index 0000000..d4b906a
--- /dev/null
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
@@ -0,0 +1,287 @@
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.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Server.Base;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors
42{
43 public class UserAccountServicesConnector : IUserAccountService
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private string m_ServerURI = String.Empty;
50
51 public UserAccountServicesConnector()
52 {
53 }
54
55 public UserAccountServicesConnector(string serverURI)
56 {
57 m_ServerURI = serverURI.TrimEnd('/');
58 }
59
60 public UserAccountServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig assetConfig = source.Configs["UserAccountService"];
68 if (assetConfig == null)
69 {
70 m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini");
71 throw new Exception("User account connector init error");
72 }
73
74 string serviceURI = assetConfig.GetString("UserAccountServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[ACCOUNT CONNECTOR]: No Server URI named in section UserAccountService");
80 throw new Exception("User account connector init error");
81 }
82 m_ServerURI = serviceURI;
83 }
84
85 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
86 {
87 Dictionary<string, object> sendData = new Dictionary<string, object>();
88 //sendData["SCOPEID"] = scopeID.ToString();
89 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
90 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
91 sendData["METHOD"] = "getaccount";
92
93 sendData["ScopeID"] = scopeID;
94 sendData["FirstName"] = firstName.ToString();
95 sendData["LastName"] = lastName.ToString();
96
97 return SendAndGetReply(sendData);
98 }
99
100 public UserAccount GetUserAccount(UUID scopeID, string email)
101 {
102 Dictionary<string, object> sendData = new Dictionary<string, object>();
103 //sendData["SCOPEID"] = scopeID.ToString();
104 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
105 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
106 sendData["METHOD"] = "getaccount";
107
108 sendData["ScopeID"] = scopeID;
109 sendData["Email"] = email;
110
111 return SendAndGetReply(sendData);
112 }
113
114 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
115 {
116 Dictionary<string, object> sendData = new Dictionary<string, object>();
117 //sendData["SCOPEID"] = scopeID.ToString();
118 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
119 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
120 sendData["METHOD"] = "getaccount";
121
122 sendData["ScopeID"] = scopeID;
123 sendData["UserID"] = userID.ToString();
124
125 return SendAndGetReply(sendData);
126 }
127
128 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
129 {
130 Dictionary<string, object> sendData = new Dictionary<string, object>();
131 //sendData["SCOPEID"] = scopeID.ToString();
132 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
133 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
134 sendData["METHOD"] = "getagents";
135
136 sendData["ScopeID"] = scopeID.ToString();
137 sendData["query"] = query;
138
139 string reply = string.Empty;
140 string reqString = ServerUtils.BuildQueryString(sendData);
141 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
142 try
143 {
144 reply = SynchronousRestFormsRequester.MakeRequest("POST",
145 m_ServerURI + "/accounts",
146 reqString);
147 if (reply == null || (reply != null && reply == string.Empty))
148 {
149 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccounts received null or empty reply");
150 return null;
151 }
152 }
153 catch (Exception e)
154 {
155 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting accounts server: {0}", e.Message);
156 }
157
158 List<UserAccount> accounts = new List<UserAccount>();
159
160 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
161
162 if (replyData != null)
163 {
164 if (replyData.ContainsKey("result") && replyData.ContainsKey("result").ToString() == "null")
165 {
166 return accounts;
167 }
168
169 Dictionary<string, object>.ValueCollection accountList = replyData.Values;
170 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
171 foreach (object acc in accountList)
172 {
173 if (acc is Dictionary<string, object>)
174 {
175 UserAccount pinfo = new UserAccount((Dictionary<string, object>)acc);
176 accounts.Add(pinfo);
177 }
178 else
179 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccounts received invalid response type {0}",
180 acc.GetType());
181 }
182 }
183 else
184 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccounts received null response");
185
186 return accounts;
187 }
188
189 public bool SetUserAccount(UserAccount data)
190 {
191 Dictionary<string, object> sendData = new Dictionary<string, object>();
192 //sendData["SCOPEID"] = scopeID.ToString();
193 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
194 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
195 sendData["METHOD"] = "setaccount";
196
197 sendData["account"] = data.ToKeyValuePairs();
198
199 return SendAndGetBoolReply(sendData);
200 }
201
202 public bool CreateUserAccount(UserAccount data)
203 {
204 Dictionary<string, object> sendData = new Dictionary<string, object>();
205 //sendData["SCOPEID"] = scopeID.ToString();
206 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
207 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
208 sendData["METHOD"] = "createaccount";
209
210 sendData["account"] = data.ToKeyValuePairs();
211
212 return SendAndGetBoolReply(sendData);
213 }
214
215 private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
216 {
217 string reply = string.Empty;
218 string reqString = ServerUtils.BuildQueryString(sendData);
219 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
220 try
221 {
222 reply = SynchronousRestFormsRequester.MakeRequest("POST",
223 m_ServerURI + "/accounts",
224 reqString);
225 if (reply == null || (reply != null && reply == string.Empty))
226 {
227 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccount received null or empty reply");
228 return null;
229 }
230 }
231 catch (Exception e)
232 {
233 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user account server: {0}", e.Message);
234 }
235
236 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
237 UserAccount account = null;
238
239 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
240 {
241 if (replyData["result"] is Dictionary<string, object>)
242 {
243 account = new UserAccount((Dictionary<string, object>)replyData["result"]);
244 }
245 }
246
247 return account;
248
249 }
250
251 private bool SendAndGetBoolReply(Dictionary<string, object> sendData)
252 {
253 string reqString = ServerUtils.BuildQueryString(sendData);
254 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
255 try
256 {
257 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
258 m_ServerURI + "/accounts",
259 reqString);
260 if (reply != string.Empty)
261 {
262 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
263
264 if (replyData.ContainsKey("result"))
265 {
266 if (replyData["result"].ToString().ToLower() == "success")
267 return true;
268 else
269 return false;
270 }
271 else
272 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount reply data does not contain result field");
273
274 }
275 else
276 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount received empty reply");
277 }
278 catch (Exception e)
279 {
280 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Exception when contacting user account server: {0}", e.Message);
281 }
282
283 return false;
284 }
285
286 }
287}
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs
index aa1c5bf..2dad7e6 100644
--- a/OpenSim/Services/Interfaces/IPresenceService.cs
+++ b/OpenSim/Services/Interfaces/IPresenceService.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using OpenSim.Framework; 29using OpenSim.Framework;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
@@ -33,13 +34,74 @@ namespace OpenSim.Services.Interfaces
33{ 34{
34 public class PresenceInfo 35 public class PresenceInfo
35 { 36 {
36 public UUID PrincipalID; 37 public string UserID;
37 public UUID RegionID; 38 public UUID RegionID;
38 public Dictionary<string, string> Data; 39 public bool Online;
40 public DateTime Login;
41 public DateTime Logout;
42 public Vector3 Position;
43 public Vector3 LookAt;
44 public UUID HomeRegionID;
45 public Vector3 HomePosition;
46 public Vector3 HomeLookAt;
47
48 public PresenceInfo()
49 {
50 }
51
52 public PresenceInfo(Dictionary<string, object> kvp)
53 {
54 if (kvp.ContainsKey("UserID"))
55 UserID = kvp["UserID"].ToString();
56 if (kvp.ContainsKey("RegionID"))
57 UUID.TryParse(kvp["RegionID"].ToString(), out RegionID);
58 if (kvp.ContainsKey("login"))
59 DateTime.TryParse(kvp["login"].ToString(), out Login);
60 if (kvp.ContainsKey("logout"))
61 DateTime.TryParse(kvp["logout"].ToString(), out Logout);
62 if (kvp.ContainsKey("lookAt"))
63 Vector3.TryParse(kvp["lookAt"].ToString(), out LookAt);
64 if (kvp.ContainsKey("online"))
65 Boolean.TryParse(kvp["online"].ToString(), out Online);
66 if (kvp.ContainsKey("position"))
67 Vector3.TryParse(kvp["position"].ToString(), out Position);
68 if (kvp.ContainsKey("HomeRegionID"))
69 UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID);
70 if (kvp.ContainsKey("HomePosition"))
71 Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition);
72 if (kvp.ContainsKey("HomeLookAt"))
73 Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt);
74
75 }
76
77 public Dictionary<string, object> ToKeyValuePairs()
78 {
79 Dictionary<string, object> result = new Dictionary<string, object>();
80 result["UserID"] = UserID;
81 result["RegionID"] = RegionID.ToString();
82 result["online"] = Online.ToString();
83 result["login"] = Login.ToString();
84 result["logout"] = Logout.ToString();
85 result["position"] = Position.ToString();
86 result["lookAt"] = LookAt.ToString();
87 result["HomeRegionID"] = HomeRegionID.ToString();
88 result["HomePosition"] = HomePosition.ToString();
89 result["HomeLookAt"] = HomeLookAt.ToString();
90
91 return result;
92 }
39 } 93 }
40 94
41 public interface IPresenceService 95 public interface IPresenceService
42 { 96 {
43 bool Report(PresenceInfo presence); 97 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID);
98 bool LogoutAgent(UUID sessionID);
99 bool LogoutRegionAgents(UUID regionID);
100
101 bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt);
102 bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt);
103
104 PresenceInfo GetAgent(UUID sessionID);
105 PresenceInfo[] GetAgents(string[] userIDs);
44 } 106 }
45} 107}
diff --git a/OpenSim/Services/Interfaces/IUserService.cs b/OpenSim/Services/Interfaces/IUserService.cs
index 92bd8ef..1bdaaab 100644
--- a/OpenSim/Services/Interfaces/IUserService.cs
+++ b/OpenSim/Services/Interfaces/IUserService.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using OpenMetaverse; 30using OpenMetaverse;
30 31
@@ -36,68 +37,69 @@ namespace OpenSim.Services.Interfaces
36 { 37 {
37 } 38 }
38 39
39 public UserAccount(UUID userID, UUID homeRegionID, float homePositionX, 40 public UserAccount(UUID principalID)
40 float homePositionY, float homePositionZ, float homeLookAtX,
41 float homeLookAtY, float homeLookAtZ)
42 { 41 {
43 UserID = userID; 42 PrincipalID = principalID;
44 HomeRegionID = homeRegionID;
45 HomePositionX = homePositionX;
46 HomePositionY = homePositionY;
47 HomePositionZ = homePositionZ;
48 HomeLookAtX = homeLookAtX;
49 HomeLookAtY = homeLookAtY;
50 HomeLookAtZ = homeLookAtZ;
51 } 43 }
52 44
53 public string FirstName; 45 public string FirstName;
54 public string LastName; 46 public string LastName;
55 public UUID UserID; 47 public string Email;
48 public UUID PrincipalID;
56 public UUID ScopeID; 49 public UUID ScopeID;
57 50
58 // For informational purposes only! 51 public Dictionary<string, object> ServiceURLs;
59 //
60 public string HomeRegionName;
61 52
62 public UUID HomeRegionID; 53 public int Created;
63 public float HomePositionX;
64 public float HomePositionY;
65 public float HomePositionZ;
66 public float HomeLookAtX;
67 public float HomeLookAtY;
68 public float HomeLookAtZ;
69 54
70 // These are here because they 55 public UserAccount(Dictionary<string, object> kvp)
71 // concern the account rather than 56 {
72 // the profile. They just happen to 57 if (kvp.ContainsKey("FirstName"))
73 // be used in the Linden profile as well 58 FirstName = kvp["FirstName"].ToString();
74 // 59 if (kvp.ContainsKey("LastName"))
75 public int GodLevel; 60 LastName = kvp["LastName"].ToString();
76 public int UserFlags; 61 if (kvp.ContainsKey("Email"))
77 public string AccountType; 62 Email = kvp["Email"].ToString();
63 if (kvp.ContainsKey("PrincipalID"))
64 UUID.TryParse(kvp["PrincipalID"].ToString(), out PrincipalID);
65 if (kvp.ContainsKey("ScopeID"))
66 UUID.TryParse(kvp["ScopeID"].ToString(), out ScopeID);
67 if (kvp.ContainsKey("Created"))
68 Convert.ToInt32(kvp["Created"].ToString());
69 if (kvp.ContainsKey("ServiceURLs") && kvp["ServiceURLs"] != null && (kvp["ServiceURLs"] is Dictionary<string, string>))
70 ServiceURLs = (Dictionary<string, object>)kvp["ServiceURLs"];
71 }
72
73 public Dictionary<string, object> ToKeyValuePairs()
74 {
75 Dictionary<string, object> result = new Dictionary<string, object>();
76 result["FirstName"] = FirstName;
77 result["LastName"] = LastName;
78 result["Email"] = Email;
79 result["PrincipalID"] = PrincipalID.ToString();
80 result["ScopeID"] = ScopeID.ToString();
81 result["Created"] = Created.ToString();
82 result["ServiceURLs"] = ServiceURLs;
78 83
84 return result;
85 }
79 }; 86 };
80 87
81 public interface IUserAccountService 88 public interface IUserAccountService
82 { 89 {
83 UserAccount GetUserAccount(UUID scopeID, UUID userID); 90 UserAccount GetUserAccount(UUID scopeID, UUID userID);
84 UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName); 91 UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName);
92 UserAccount GetUserAccount(UUID scopeID, string Email);
85 // Returns the list of avatars that matches both the search 93 // Returns the list of avatars that matches both the search
86 // criterion and the scope ID passed 94 // criterion and the scope ID passed
87 // 95 //
88 List<UserAccount> GetUserAccount(UUID scopeID, string query); 96 List<UserAccount> GetUserAccounts(UUID scopeID, string query);
89
90
91 // This will set only the home region portion of the data!
92 // Can't be used to set god level, flags, type or change the name!
93 //
94 bool SetHomePosition(UserAccount data, UUID RegionID, UUID RegionSecret);
95 97
96 // Update all updatable fields 98 // Update all updatable fields
97 // 99 //
98 bool SetUserAccount(UserAccount data, UUID PrincipalID, string token); 100 bool SetUserAccount(UserAccount data);
99 101
100 // Creates a user data record 102 // Creates a user data record
101 bool CreateUserAccount(UserAccount data, UUID PrincipalID, string token); 103 bool CreateUserAccount(UserAccount data);
102 } 104 }
103} 105}
diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs
index 2157462..fc6a6e1 100644
--- a/OpenSim/Services/PresenceService/PresenceService.cs
+++ b/OpenSim/Services/PresenceService/PresenceService.cs
@@ -41,27 +41,151 @@ namespace OpenSim.Services.PresenceService
41{ 41{
42 public class PresenceService : PresenceServiceBase, IPresenceService 42 public class PresenceService : PresenceServiceBase, IPresenceService
43 { 43 {
44// private static readonly ILog m_log = 44 private static readonly ILog m_log =
45// LogManager.GetLogger( 45 LogManager.GetLogger(
46// MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 public PresenceService(IConfigSource config) 48 public PresenceService(IConfigSource config)
49 : base(config) 49 : base(config)
50 { 50 {
51 m_log.Debug("[PRESENCE SERVICE]: Starting presence service");
51 } 52 }
52 53
53 public bool Report(PresenceInfo presence) 54 public bool LoginAgent(string userID, UUID sessionID,
55 UUID secureSessionID)
54 { 56 {
55 PresenceData p = new PresenceData(); 57 m_Database.Prune(userID);
56 p.Data = new Dictionary<string, string>();
57 58
58 p.UUID = presence.PrincipalID; 59 PresenceData[] d = m_Database.Get("UserID", userID);
59 p.currentRegion = presence.RegionID;
60 60
61 foreach (KeyValuePair<string, string> kvp in presence.Data) 61 PresenceData data = new PresenceData();
62 p.Data[kvp.Key] = kvp.Value;
63 62
64 return false; 63 data.UserID = userID;
64 data.RegionID = UUID.Zero;
65 data.SessionID = sessionID;
66 data.Data["SecureSessionID"] = secureSessionID.ToString();
67 data.Data["Online"] = "true";
68 data.Data["Login"] = Util.UnixTimeSinceEpoch().ToString();
69 if (d.Length > 0)
70 {
71 data.Data["HomeRegionID"] = d[0].Data["HomeRegionID"];
72 data.Data["HomePosition"] = d[0].Data["HomePosition"];
73 data.Data["HomeLookAt"] = d[0].Data["HomeLookAt"];
74 }
75
76 m_Database.Store(data);
77
78 return true;
79 }
80
81 public bool LogoutAgent(UUID sessionID)
82 {
83 PresenceData data = m_Database.Get(sessionID);
84 if (data == null)
85 return false;
86
87 PresenceData[] d = m_Database.Get("UserID", data.UserID);
88
89 if (d.Length > 1)
90 {
91 m_Database.Delete("SessionID", sessionID.ToString());
92 }
93
94 data.Data["Online"] = "false";
95 data.Data["Logout"] = Util.UnixTimeSinceEpoch().ToString();
96
97 m_Database.Store(data);
98
99 return true;
100 }
101
102 public bool LogoutRegionAgents(UUID regionID)
103 {
104 m_Database.LogoutRegionAgents(regionID);
105
106 return true;
107 }
108
109
110 public bool ReportAgent(UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
111 {
112 m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent with session {0} in region {1}", sessionID, regionID);
113 PresenceData pdata = m_Database.Get(sessionID);
114 if (pdata == null)
115 return false;
116 if (pdata.Data["Online"] == "false")
117 return false;
118
119 return m_Database.ReportAgent(sessionID, regionID,
120 position.ToString(), lookAt.ToString());
121 }
122
123 public PresenceInfo GetAgent(UUID sessionID)
124 {
125 PresenceInfo ret = new PresenceInfo();
126
127 PresenceData data = m_Database.Get(sessionID);
128 if (data == null)
129 return null;
130
131 ret.UserID = data.UserID;
132 ret.RegionID = data.RegionID;
133 if (data.Data.ContainsKey("Online"))
134 ret.Online = bool.Parse(data.Data["Online"]);
135 if (data.Data.ContainsKey("Login"))
136 ret.Login = Util.ToDateTime(Convert.ToInt32(data.Data["Login"]));
137 if (data.Data.ContainsKey("Logout"))
138 ret.Logout = Util.ToDateTime(Convert.ToInt32(data.Data["Logout"]));
139 if (data.Data.ContainsKey("Position"))
140 ret.Position = Vector3.Parse(data.Data["Position"]);
141 if (data.Data.ContainsKey("LookAt"))
142 ret.LookAt = Vector3.Parse(data.Data["LookAt"]);
143 if (data.Data.ContainsKey("HomeRegionID"))
144 ret.HomeRegionID = new UUID(data.Data["HomeRegionID"]);
145 if (data.Data.ContainsKey("HomePosition"))
146 ret.HomePosition = Vector3.Parse(data.Data["HomePosition"]);
147 if (data.Data.ContainsKey("HomeLookAt"))
148 ret.HomeLookAt = Vector3.Parse(data.Data["HomeLookAt"]);
149
150 return ret;
151 }
152
153 public PresenceInfo[] GetAgents(string[] userIDs)
154 {
155 List<PresenceInfo> info = new List<PresenceInfo>();
156
157 foreach (string userIDStr in userIDs)
158 {
159 PresenceData[] data = m_Database.Get("UserID",
160 userIDStr);
161
162 foreach (PresenceData d in data)
163 {
164 PresenceInfo ret = new PresenceInfo();
165
166 ret.UserID = d.UserID;
167 ret.RegionID = d.RegionID;
168 ret.Online = bool.Parse(d.Data["Online"]);
169 ret.Login = Util.ToDateTime(Convert.ToInt32(
170 d.Data["Login"]));
171 ret.Logout = Util.ToDateTime(Convert.ToInt32(
172 d.Data["Logout"]));
173 ret.Position = Vector3.Parse(d.Data["Position"]);
174 ret.LookAt = Vector3.Parse(d.Data["LookAt"]);
175 ret.HomeRegionID = new UUID(d.Data["HomeRegionID"]);
176 ret.HomePosition = Vector3.Parse(d.Data["HomePosition"]);
177 ret.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]);
178
179 info.Add(ret);
180 }
181 }
182
183 return info.ToArray();
184 }
185
186 public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
187 {
188 return m_Database.SetHomeLocation(userID, regionID, position, lookAt);
65 } 189 }
66 } 190 }
67} 191}
diff --git a/OpenSim/Services/PresenceService/PresenceServiceBase.cs b/OpenSim/Services/PresenceService/PresenceServiceBase.cs
index 60a246b..3ca70c1 100644
--- a/OpenSim/Services/PresenceService/PresenceServiceBase.cs
+++ b/OpenSim/Services/PresenceService/PresenceServiceBase.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Services.PresenceService
44 { 44 {
45 string dllName = String.Empty; 45 string dllName = String.Empty;
46 string connString = String.Empty; 46 string connString = String.Empty;
47 string realm = "agents"; 47 string realm = "presence";
48 48
49 // 49 //
50 // Try reading the [DatabaseService] section, if it exists 50 // Try reading the [DatabaseService] section, if it exists
diff --git a/OpenSim/Services/UserService/UserService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
index e8b9fc3..ee9ea94 100644
--- a/OpenSim/Services/UserService/UserService.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -44,31 +44,45 @@ namespace OpenSim.Services.UserAccountService
44 public UserAccount GetUserAccount(UUID scopeID, string firstName, 44 public UserAccount GetUserAccount(UUID scopeID, string firstName,
45 string lastName) 45 string lastName)
46 { 46 {
47 UserAccountData[] d = m_Database.Get(
48 new string[] {"ScopeID", "FirstName", "LastName"},
49 new string[] {scopeID.ToString(), firstName, lastName});
50
51 if (d.Length < 1)
52 return null;
53
54 UserAccount u = new UserAccount();
55 u.FirstName = d[0].FirstName;
56 u.LastName = d[0].LastName;
57 u.PrincipalID = d[0].PrincipalID;
58 u.ScopeID = d[0].ScopeID;
59 u.Email = d[0].Data["Email"].ToString();
60 u.Created = Convert.ToInt32(d[0].Data["Created"].ToString());
61
47 return null; 62 return null;
48 } 63 }
49 64
50 public UserAccount GetUserAccount(UUID scopeID, UUID userID) 65 public UserAccount GetUserAccount(UUID scopeID, string email)
51 { 66 {
52 return null; 67 return null;
53 } 68 }
54 69
55 public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret) 70 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
56 { 71 {
57 return false; 72 return null;
58 } 73 }
59 74
60 public bool SetUserAccount(UserAccount data, UUID principalID, string token) 75 public bool SetUserAccount(UserAccount data)
61 { 76 {
62 return false; 77 return false;
63 } 78 }
64 79
65 public bool CreateUserAccount(UserAccount data, UUID principalID, string token) 80 public bool CreateUserAccount(UserAccount data)
66 { 81 {
67 return false; 82 return false;
68 } 83 }
69 84
70 public List<UserAccount> GetUserAccount(UUID scopeID, 85 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
71 string query)
72 { 86 {
73 return null; 87 return null;
74 } 88 }
diff --git a/OpenSim/Services/UserService/UserServiceBase.cs b/OpenSim/Services/UserAccountService/UserAccountServiceBase.cs
index fea8b01..70ed594 100644
--- a/OpenSim/Services/UserService/UserServiceBase.cs
+++ b/OpenSim/Services/UserAccountService/UserAccountServiceBase.cs
@@ -40,20 +40,29 @@ namespace OpenSim.Services.UserAccountService
40 40
41 public UserAccountServiceBase(IConfigSource config) : base(config) 41 public UserAccountServiceBase(IConfigSource config) : base(config)
42 { 42 {
43 string dllName = String.Empty;
44 string connString = String.Empty;
45 string realm = "useraccounts";
46
47 IConfig dbConfig = config.Configs["DatabaseService"];
48 if (dbConfig != null)
49 {
50 dllName = dbConfig.GetString("StorageProvider", String.Empty);
51 connString = dbConfig.GetString("ConnectionString", String.Empty);
52 }
53
43 IConfig userConfig = config.Configs["UserAccountService"]; 54 IConfig userConfig = config.Configs["UserAccountService"];
44 if (userConfig == null) 55 if (userConfig == null)
45 throw new Exception("No UserAccountService configuration"); 56 throw new Exception("No UserAccountService configuration");
46 57
47 string dllName = userConfig.GetString("StorageProvider", 58 dllName = userConfig.GetString("StorageProvider", dllName);
48 String.Empty);
49 59
50 if (dllName == String.Empty) 60 if (dllName == String.Empty)
51 throw new Exception("No StorageProvider configured"); 61 throw new Exception("No StorageProvider configured");
52 62
53 string connString = userConfig.GetString("ConnectionString", 63 connString = userConfig.GetString("ConnectionString", connString);
54 String.Empty);
55 64
56 string realm = userConfig.GetString("Realm", "users"); 65 realm = userConfig.GetString("Realm", realm);
57 66
58 m_Database = LoadPlugin<IUserAccountData>(dllName, new Object[] {connString, realm}); 67 m_Database = LoadPlugin<IUserAccountData>(dllName, new Object[] {connString, realm});
59 68