aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services')
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs186
-rw-r--r--OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs90
-rw-r--r--OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs71
-rw-r--r--OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs44
-rw-r--r--OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs92
-rw-r--r--OpenSim/Services/AuthorizationService/AuthorizationService.cs5
-rw-r--r--OpenSim/Services/AvatarService/AvatarService.cs185
-rw-r--r--OpenSim/Services/AvatarService/AvatarServiceBase.cs84
-rw-r--r--OpenSim/Services/Base/ServiceBase.cs21
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs248
-rw-r--r--OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs23
-rw-r--r--OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs23
-rw-r--r--OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs1
-rw-r--r--OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs328
-rw-r--r--OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs (renamed from OpenSim/Services/Connectors/User/UserServiceConnector.cs)63
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs271
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs174
-rw-r--r--OpenSim/Services/Connectors/Grid/GridServiceConnector.cs226
-rw-r--r--OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs254
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs227
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs334
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs206
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs77
-rw-r--r--OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs796
-rw-r--r--OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs131
-rw-r--r--OpenSim/Services/Connectors/Inventory/HGInventoryServiceConnector.cs335
-rw-r--r--OpenSim/Services/Connectors/Inventory/ISessionAuthInventoryService.cs140
-rw-r--r--OpenSim/Services/Connectors/Inventory/InventoryServiceConnector.cs582
-rw-r--r--OpenSim/Services/Connectors/Inventory/QuickAndDirtyInventoryServiceConnector.cs196
-rw-r--r--OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs219
-rw-r--r--OpenSim/Services/Connectors/Land/LandServiceConnector.cs25
-rw-r--r--OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs158
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs70
-rw-r--r--OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs383
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs114
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs497
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs307
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs344
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs236
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs33
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs262
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs524
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs922
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs477
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs478
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs333
-rw-r--r--OpenSim/Services/Connectors/Simulation/EstateDataService.cs139
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationDataService.cs152
-rw-r--r--OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs457
-rw-r--r--OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs282
-rw-r--r--OpenSim/Services/FreeswitchService/FreeswitchService.cs360
-rw-r--r--OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs36
-rw-r--r--OpenSim/Services/Friends/FriendsService.cs115
-rw-r--r--OpenSim/Services/Friends/FriendsServiceBase.cs89
-rw-r--r--OpenSim/Services/GridService/GridService.cs365
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs724
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs383
-rw-r--r--OpenSim/Services/HypergridService/HGAssetService.cs148
-rw-r--r--OpenSim/Services/HypergridService/HGInstantMessageService.cs346
-rw-r--r--OpenSim/Services/HypergridService/HGInventoryService.cs342
-rw-r--r--OpenSim/Services/HypergridService/UserAccountCache.cs111
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs545
-rw-r--r--OpenSim/Services/Interfaces/IAssetService.cs13
-rw-r--r--OpenSim/Services/Interfaces/IAttachmentsService.cs17
-rw-r--r--OpenSim/Services/Interfaces/IAuthenticationService.cs37
-rw-r--r--OpenSim/Services/Interfaces/IAuthorizationService.cs32
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs342
-rw-r--r--OpenSim/Services/Interfaces/IFreeswitchService.cs5
-rw-r--r--OpenSim/Services/Interfaces/IFriendsService.cs82
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs106
-rw-r--r--OpenSim/Services/Interfaces/IGridUserService.cs135
-rw-r--r--OpenSim/Services/Interfaces/IHypergridServices.cs87
-rw-r--r--OpenSim/Services/Interfaces/IInventoryService.cs9
-rw-r--r--OpenSim/Services/Interfaces/ILandService.cs2
-rw-r--r--OpenSim/Services/Interfaces/ILibraryService.cs (renamed from OpenSim/Services/Interfaces/IMapService.cs)11
-rw-r--r--OpenSim/Services/Interfaces/ILoginService.cs (renamed from OpenSim/Services/UserService/UserService.cs)58
-rw-r--r--OpenSim/Services/Interfaces/IMapImageService.cs (renamed from OpenSim/Services/Interfaces/IHyperlink.cs)21
-rw-r--r--OpenSim/Services/Interfaces/IPresenceService.cs34
-rw-r--r--OpenSim/Services/Interfaces/ISimulationService.cs44
-rw-r--r--OpenSim/Services/Interfaces/IUserAccountService.cs194
-rw-r--r--OpenSim/Services/Interfaces/IUserService.cs103
-rw-r--r--OpenSim/Services/InventoryService/InventoryService.cs19
-rw-r--r--OpenSim/Services/InventoryService/LibraryService.cs284
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs215
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginResponse.cs1026
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs938
-rw-r--r--OpenSim/Services/MapImageService/MapImageService.cs300
-rw-r--r--OpenSim/Services/PresenceService/PresenceService.cs116
-rw-r--r--OpenSim/Services/PresenceService/PresenceServiceBase.cs4
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs159
-rw-r--r--OpenSim/Services/UserAccountService/GridUserServiceBase.cs82
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountService.cs687
-rw-r--r--OpenSim/Services/UserAccountService/UserAccountServiceBase.cs (renamed from OpenSim/Services/UserService/UserServiceBase.cs)19
93 files changed, 18490 insertions, 2080 deletions
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index ed87f3f..ec424c0 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -26,6 +26,8 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using System.IO;
29using System.Reflection; 31using System.Reflection;
30using Nini.Config; 32using Nini.Config;
31using log4net; 33using log4net;
@@ -43,74 +45,114 @@ namespace OpenSim.Services.AssetService
43 LogManager.GetLogger( 45 LogManager.GetLogger(
44 MethodBase.GetCurrentMethod().DeclaringType); 46 MethodBase.GetCurrentMethod().DeclaringType);
45 47
48 protected static AssetService m_RootInstance;
49
46 public AssetService(IConfigSource config) : base(config) 50 public AssetService(IConfigSource config) : base(config)
47 { 51 {
48 MainConsole.Instance.Commands.AddCommand("kfs", false, 52 if (m_RootInstance == null)
49 "show digest", 53 {
50 "show digest <ID>", 54 m_RootInstance = this;
51 "Show asset digest", HandleShowDigest);
52 55
53 MainConsole.Instance.Commands.AddCommand("kfs", false, 56 MainConsole.Instance.Commands.AddCommand("kfs", false,
54 "delete asset", 57 "show digest",
55 "delete asset <ID>", 58 "show digest <ID>",
56 "Delete asset from database", HandleDeleteAsset); 59 "Show asset digest", HandleShowDigest);
57 60
58 if (m_AssetLoader != null) 61 MainConsole.Instance.Commands.AddCommand("kfs", false,
59 { 62 "delete asset",
60 IConfig assetConfig = config.Configs["AssetService"]; 63 "delete asset <ID>",
61 if (assetConfig == null) 64 "Delete asset from database", HandleDeleteAsset);
62 throw new Exception("No AssetService configuration"); 65
66 MainConsole.Instance.Commands.AddCommand("kfs", false,
67 "dump asset",
68 "dump asset <ID>",
69 "Dump asset to a file",
70 "The filename is the same as the ID given.",
71 HandleDumpAsset);
72
73 if (m_AssetLoader != null)
74 {
75 IConfig assetConfig = config.Configs["AssetService"];
76 if (assetConfig == null)
77 throw new Exception("No AssetService configuration");
63 78
64 string loaderArgs = assetConfig.GetString("AssetLoaderArgs", 79 string loaderArgs = assetConfig.GetString("AssetLoaderArgs",
65 String.Empty); 80 String.Empty);
66 81
67 bool assetLoaderEnabled = assetConfig.GetBoolean("AssetLoaderEnabled", true); 82 bool assetLoaderEnabled = assetConfig.GetBoolean("AssetLoaderEnabled", true);
68 83
69 if (assetLoaderEnabled) 84 if (assetLoaderEnabled)
70 { 85 {
71 m_log.InfoFormat("[ASSET]: Loading default asset set from {0}", loaderArgs); 86 m_log.DebugFormat("[ASSET]: Loading default asset set from {0}", loaderArgs);
72 m_AssetLoader.ForEachDefaultXmlAsset(loaderArgs, 87
88 m_AssetLoader.ForEachDefaultXmlAsset(
89 loaderArgs,
73 delegate(AssetBase a) 90 delegate(AssetBase a)
74 { 91 {
75 Store(a); 92 AssetBase existingAsset = Get(a.ID);
93// AssetMetadata existingMetadata = GetMetadata(a.ID);
94
95 if (existingAsset == null || Util.SHA1Hash(existingAsset.Data) != Util.SHA1Hash(a.Data))
96 {
97// m_log.DebugFormat("[ASSET]: Storing {0} {1}", a.Name, a.ID);
98 Store(a);
99 }
76 }); 100 });
101 }
102
103 m_log.Debug("[ASSET SERVICE]: Local asset service enabled");
77 } 104 }
78
79 m_log.Info("[ASSET SERVICE]: Local asset service enabled");
80 } 105 }
81 } 106 }
82 107
83 public AssetBase Get(string id) 108 public virtual AssetBase Get(string id)
84 { 109 {
110// m_log.DebugFormat("[ASSET SERVICE]: Get asset for {0}", id);
111
85 UUID assetID; 112 UUID assetID;
86 113
87 if (!UUID.TryParse(id, out assetID)) 114 if (!UUID.TryParse(id, out assetID))
88 { 115 {
89 m_log.WarnFormat("[ASSET SERVICE]: Could not parse requested sset id {0}", id); 116 m_log.WarnFormat("[ASSET SERVICE]: Could not parse requested asset id {0}", id);
90 return null; 117 return null;
91 } 118 }
92 119
93 return m_Database.GetAsset(assetID); 120 try
121 {
122 return m_Database.GetAsset(assetID);
123 }
124 catch (Exception e)
125 {
126 m_log.ErrorFormat("[ASSET SERVICE]: Exception getting asset {0} {1}", assetID, e);
127 return null;
128 }
94 } 129 }
95 130
96 public AssetBase GetCached(string id) 131 public virtual AssetBase GetCached(string id)
97 { 132 {
98 return Get(id); 133 return Get(id);
99 } 134 }
100 135
101 public AssetMetadata GetMetadata(string id) 136 public virtual AssetMetadata GetMetadata(string id)
102 { 137 {
138// m_log.DebugFormat("[ASSET SERVICE]: Get asset metadata for {0}", id);
139
103 UUID assetID; 140 UUID assetID;
104 141
105 if (!UUID.TryParse(id, out assetID)) 142 if (!UUID.TryParse(id, out assetID))
106 return null; 143 return null;
107 144
108 AssetBase asset = m_Database.GetAsset(assetID); 145 AssetBase asset = m_Database.GetAsset(assetID);
109 return asset.Metadata; 146 if (asset != null)
147 return asset.Metadata;
148
149 return null;
110 } 150 }
111 151
112 public byte[] GetData(string id) 152 public virtual byte[] GetData(string id)
113 { 153 {
154// m_log.DebugFormat("[ASSET SERVICE]: Get asset data for {0}", id);
155
114 UUID assetID; 156 UUID assetID;
115 157
116 if (!UUID.TryParse(id, out assetID)) 158 if (!UUID.TryParse(id, out assetID))
@@ -120,7 +162,7 @@ namespace OpenSim.Services.AssetService
120 return asset.Data; 162 return asset.Data;
121 } 163 }
122 164
123 public bool Get(string id, Object sender, AssetRetrieved handler) 165 public virtual bool Get(string id, Object sender, AssetRetrieved handler)
124 { 166 {
125 //m_log.DebugFormat("[AssetService]: Get asset async {0}", id); 167 //m_log.DebugFormat("[AssetService]: Get asset async {0}", id);
126 168
@@ -138,10 +180,22 @@ namespace OpenSim.Services.AssetService
138 return true; 180 return true;
139 } 181 }
140 182
141 public string Store(AssetBase asset) 183 public virtual string Store(AssetBase asset)
142 { 184 {
143 //m_log.DebugFormat("[ASSET SERVICE]: Store asset {0} {1}", asset.Name, asset.ID); 185 if (!m_Database.ExistsAsset(asset.FullID))
144 m_Database.StoreAsset(asset); 186 {
187// m_log.DebugFormat(
188// "[ASSET SERVICE]: Storing asset {0} {1}, bytes {2}", asset.Name, asset.FullID, asset.Data.Length);
189 if (!m_Database.StoreAsset(asset))
190 {
191 return UUID.Zero.ToString();
192 }
193 }
194// else
195// {
196// m_log.DebugFormat(
197// "[ASSET SERVICE]: Not storing asset {0} {1}, bytes {2} as it already exists", asset.Name, asset.FullID, asset.Data.Length);
198// }
145 199
146 return asset.ID; 200 return asset.ID;
147 } 201 }
@@ -151,10 +205,63 @@ namespace OpenSim.Services.AssetService
151 return false; 205 return false;
152 } 206 }
153 207
154 public bool Delete(string id) 208 public virtual bool Delete(string id)
155 { 209 {
210 m_log.DebugFormat("[ASSET SERVICE]: Deleting asset {0}", id);
211 UUID assetID;
212 if (!UUID.TryParse(id, out assetID))
213 return false;
214
215 AssetBase asset = m_Database.GetAsset(assetID);
216 if (asset == null)
217 return false;
218
219 if ((int)(asset.Flags & AssetFlags.Maptile) != 0)
220 {
221 return m_Database.Delete(id);
222 }
223 else
224 m_log.DebugFormat("[ASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id);
225
156 return false; 226 return false;
157 } 227 }
228
229 void HandleDumpAsset(string module, string[] args)
230 {
231 if (args.Length < 3)
232 {
233 MainConsole.Instance.Output("Usage is dump asset <ID>");
234 return;
235 }
236
237 string rawAssetId = args[2];
238 UUID assetId;
239
240 if (!UUID.TryParse(rawAssetId, out assetId))
241 {
242 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId);
243 return;
244 }
245
246 AssetBase asset = m_Database.GetAsset(assetId);
247 if (asset == null)
248 {
249 MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId);
250 return;
251 }
252
253 string fileName = rawAssetId;
254
255 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
256 {
257 using (BinaryWriter bw = new BinaryWriter(fs))
258 {
259 bw.Write(asset.Data);
260 }
261 }
262
263 MainConsole.Instance.OutputFormat("Asset dumped to file {0}", fileName);
264 }
158 265
159 void HandleShowDigest(string module, string[] args) 266 void HandleShowDigest(string module, string[] args)
160 { 267 {
@@ -174,10 +281,11 @@ namespace OpenSim.Services.AssetService
174 281
175 int i; 282 int i;
176 283
177 MainConsole.Instance.Output(String.Format("Name: {0}", asset.Name)); 284 MainConsole.Instance.OutputFormat("Name: {0}", asset.Name);
178 MainConsole.Instance.Output(String.Format("Description: {0}", asset.Description)); 285 MainConsole.Instance.OutputFormat("Description: {0}", asset.Description);
179 MainConsole.Instance.Output(String.Format("Type: {0}", asset.Type)); 286 MainConsole.Instance.OutputFormat("Type: {0} (type number = {1})", (AssetType)asset.Type, asset.Type);
180 MainConsole.Instance.Output(String.Format("Content-type: {0}", asset.Metadata.ContentType)); 287 MainConsole.Instance.OutputFormat("Content-type: {0}", asset.Metadata.ContentType);
288 MainConsole.Instance.OutputFormat("Flags: {0}", asset.Metadata.Flags);
181 289
182 for (i = 0 ; i < 5 ; i++) 290 for (i = 0 ; i < 5 ; i++)
183 { 291 {
diff --git a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
index dcf090e..e42f9a0 100644
--- a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
+++ b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs
@@ -30,8 +30,11 @@ using OpenMetaverse;
30using log4net; 30using log4net;
31using Nini.Config; 31using Nini.Config;
32using System.Reflection; 32using System.Reflection;
33using OpenSim.Services.Base; 33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
34using OpenSim.Data; 35using OpenSim.Data;
36using OpenSim.Framework;
37using OpenSim.Services.Base;
35 38
36namespace OpenSim.Services.AuthenticationService 39namespace OpenSim.Services.AuthenticationService
37{ 40{
@@ -43,11 +46,17 @@ namespace OpenSim.Services.AuthenticationService
43 // 46 //
44 public class AuthenticationServiceBase : ServiceBase 47 public class AuthenticationServiceBase : ServiceBase
45 { 48 {
46// private static readonly ILog m_log = 49 private static readonly ILog m_log =
47// LogManager.GetLogger( 50 LogManager.GetLogger(
48// MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
49 52
50 protected IAuthenticationData m_Database; 53 protected IAuthenticationData m_Database;
54 protected IUserAccountService m_UserAccountService = null;
55
56 public AuthenticationServiceBase(IConfigSource config, IUserAccountService acct) : this(config)
57 {
58 m_UserAccountService = acct;
59 }
51 60
52 public AuthenticationServiceBase(IConfigSource config) : base(config) 61 public AuthenticationServiceBase(IConfigSource config) : base(config)
53 { 62 {
@@ -87,7 +96,7 @@ namespace OpenSim.Services.AuthenticationService
87 m_Database = LoadPlugin<IAuthenticationData>(dllName, 96 m_Database = LoadPlugin<IAuthenticationData>(dllName,
88 new Object[] {connString, realm}); 97 new Object[] {connString, realm});
89 if (m_Database == null) 98 if (m_Database == null)
90 throw new Exception("Could not find a storage interface in the given module"); 99 throw new Exception(string.Format("Could not find a storage interface in module {0}", dllName));
91 } 100 }
92 101
93 public bool Verify(UUID principalID, string token, int lifetime) 102 public bool Verify(UUID principalID, string token, int lifetime)
@@ -100,6 +109,76 @@ namespace OpenSim.Services.AuthenticationService
100 return m_Database.CheckToken(principalID, token, 0); 109 return m_Database.CheckToken(principalID, token, 0);
101 } 110 }
102 111
112 public virtual bool SetPassword(UUID principalID, string password)
113 {
114 string passwordSalt = Util.Md5Hash(UUID.Random().ToString());
115 string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + passwordSalt);
116
117 AuthenticationData auth = m_Database.Get(principalID);
118 if (auth == null)
119 {
120 auth = new AuthenticationData();
121 auth.PrincipalID = principalID;
122 auth.Data = new System.Collections.Generic.Dictionary<string, object>();
123 auth.Data["accountType"] = "UserAccount";
124 auth.Data["webLoginKey"] = UUID.Zero.ToString();
125 }
126 auth.Data["passwordHash"] = md5PasswdHash;
127 auth.Data["passwordSalt"] = passwordSalt;
128 if (!m_Database.Store(auth))
129 {
130 m_log.DebugFormat("[AUTHENTICATION DB]: Failed to store authentication data");
131 return false;
132 }
133
134 m_log.InfoFormat("[AUTHENTICATION DB]: Set password for principalID {0}", principalID);
135 return true;
136 }
137
138 public virtual AuthInfo GetAuthInfo(UUID principalID)
139 {
140 AuthenticationData data = m_Database.Get(principalID);
141
142 if (data == null)
143 {
144 return null;
145 }
146 else
147 {
148 AuthInfo info
149 = new AuthInfo()
150 {
151 PrincipalID = data.PrincipalID,
152 AccountType = data.Data["accountType"] as string,
153 PasswordHash = data.Data["passwordHash"] as string,
154 PasswordSalt = data.Data["passwordSalt"] as string,
155 WebLoginKey = data.Data["webLoginKey"] as string
156 };
157
158 return info;
159 }
160 }
161
162 public virtual bool SetAuthInfo(AuthInfo info)
163 {
164 AuthenticationData auth = new AuthenticationData();
165 auth.PrincipalID = info.PrincipalID;
166 auth.Data = new System.Collections.Generic.Dictionary<string, object>();
167 auth.Data["accountType"] = info.AccountType;
168 auth.Data["webLoginKey"] = info.WebLoginKey;
169 auth.Data["passwordHash"] = info.PasswordHash;
170 auth.Data["passwordSalt"] = info.PasswordSalt;
171
172 if (!m_Database.Store(auth))
173 {
174 m_log.ErrorFormat("[AUTHENTICATION DB]: Failed to store authentication info.");
175 return false;
176 }
177
178 m_log.DebugFormat("[AUTHENTICATION DB]: Set authentication info for principalID {0}", info.PrincipalID);
179 return true;
180 }
181
103 protected string GetToken(UUID principalID, int lifetime) 182 protected string GetToken(UUID principalID, int lifetime)
104 { 183 {
105 UUID token = UUID.Random(); 184 UUID token = UUID.Random();
@@ -109,5 +188,6 @@ namespace OpenSim.Services.AuthenticationService
109 188
110 return String.Empty; 189 return String.Empty;
111 } 190 }
191
112 } 192 }
113} 193}
diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
index d65665a..d5a6521 100644
--- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs
@@ -47,10 +47,16 @@ namespace OpenSim.Services.AuthenticationService
47 public class PasswordAuthenticationService : 47 public class PasswordAuthenticationService :
48 AuthenticationServiceBase, IAuthenticationService 48 AuthenticationServiceBase, IAuthenticationService
49 { 49 {
50// private static readonly ILog m_log = 50 private static readonly ILog m_log =
51// LogManager.GetLogger( 51 LogManager.GetLogger(
52// MethodBase.GetCurrentMethod().DeclaringType); 52 MethodBase.GetCurrentMethod().DeclaringType);
53 53
54 public PasswordAuthenticationService(IConfigSource config, IUserAccountService userService) :
55 base(config, userService)
56 {
57 m_log.Debug("[AUTH SERVICE]: Started with User Account access");
58 }
59
54 public PasswordAuthenticationService(IConfigSource config) : 60 public PasswordAuthenticationService(IConfigSource config) :
55 base(config) 61 base(config)
56 { 62 {
@@ -58,22 +64,77 @@ namespace OpenSim.Services.AuthenticationService
58 64
59 public string Authenticate(UUID principalID, string password, int lifetime) 65 public string Authenticate(UUID principalID, string password, int lifetime)
60 { 66 {
67 m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null);
61 AuthenticationData data = m_Database.Get(principalID); 68 AuthenticationData data = m_Database.Get(principalID);
62 69 UserAccount user = null;
70 if (m_UserAccountService != null)
71 user = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
72
73 if (data == null || data.Data == null)
74 {
75 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
76 return String.Empty;
77 }
78
63 if (!data.Data.ContainsKey("passwordHash") || 79 if (!data.Data.ContainsKey("passwordHash") ||
64 !data.Data.ContainsKey("passwordSalt")) 80 !data.Data.ContainsKey("passwordSalt"))
65 { 81 {
66 return String.Empty; 82 return String.Empty;
67 } 83 }
68 84
69 string hashed = Util.Md5Hash(Util.Md5Hash(password) + ":" + 85 string hashed = Util.Md5Hash(password + ":" +
70 data.Data["passwordSalt"].ToString()); 86 data.Data["passwordSalt"].ToString());
71 87
88 m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString());
89
72 if (data.Data["passwordHash"].ToString() == hashed) 90 if (data.Data["passwordHash"].ToString() == hashed)
73 { 91 {
74 return GetToken(principalID, lifetime); 92 return GetToken(principalID, lifetime);
75 } 93 }
76 94
95 if (user == null)
96 {
97 m_log.DebugFormat("[PASS AUTH]: No user record for {0}", principalID);
98 return String.Empty;
99 }
100
101 int impersonateFlag = 1 << 6;
102
103 if ((user.UserFlags & impersonateFlag) == 0)
104 return String.Empty;
105
106 List<UserAccount> accounts = m_UserAccountService.GetUserAccountsWhere(UUID.Zero, "UserLevel >= 200");
107 if (accounts == null || accounts.Count == 0)
108 return String.Empty;
109
110 foreach (UserAccount a in accounts)
111 {
112 data = m_Database.Get(a.PrincipalID);
113 if (data == null || data.Data == null ||
114 !data.Data.ContainsKey("passwordHash") ||
115 !data.Data.ContainsKey("passwordSalt"))
116 {
117 continue;
118 }
119
120 hashed = Util.Md5Hash(password + ":" +
121 data.Data["passwordSalt"].ToString());
122
123 if (data.Data["passwordHash"].ToString() == hashed)
124 {
125 m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID);
126 return GetToken(principalID, lifetime);
127 }
128 else
129 {
130 m_log.DebugFormat(
131 "[AUTH SERVICE]: Salted hash {0} of given password did not match salted hash of {1} for PrincipalID {2}. Authentication failure.",
132 principalID);
133 return String.Empty;
134 }
135 }
136
137 m_log.DebugFormat("[PASS AUTH]: Impersonation of {0} failed", principalID);
77 return String.Empty; 138 return String.Empty;
78 } 139 }
79 } 140 }
diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
index d1a5b0f..d02ff9b 100644
--- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
+++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs
@@ -31,6 +31,9 @@ using OpenSim.Services.Interfaces;
31using log4net; 31using log4net;
32using Nini.Config; 32using Nini.Config;
33using System.Reflection; 33using System.Reflection;
34using OpenSim.Data;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
34 37
35namespace OpenSim.Services.AuthenticationService 38namespace OpenSim.Services.AuthenticationService
36{ 39{
@@ -43,17 +46,50 @@ namespace OpenSim.Services.AuthenticationService
43 public class WebkeyAuthenticationService : 46 public class WebkeyAuthenticationService :
44 AuthenticationServiceBase, IAuthenticationService 47 AuthenticationServiceBase, IAuthenticationService
45 { 48 {
46// private static readonly ILog m_log = 49 private static readonly ILog m_log =
47// LogManager.GetLogger( 50 LogManager.GetLogger(
48// MethodBase.GetCurrentMethod().DeclaringType); 51 MethodBase.GetCurrentMethod().DeclaringType);
49 52
53 public WebkeyAuthenticationService(IConfigSource config, IUserAccountService userService) :
54 base(config, userService)
55 {
56 }
57
50 public WebkeyAuthenticationService(IConfigSource config) : 58 public WebkeyAuthenticationService(IConfigSource config) :
51 base(config) 59 base(config)
52 { 60 {
53 } 61 }
54 62
55 public string Authenticate(UUID principalID, string password, int lifetime) 63 public string Authenticate(UUID principalID, string password, int lifetime)
56 { 64 {
65 if (new UUID(password) == UUID.Zero)
66 {
67 m_log.DebugFormat("[AUTH SERVICE]: UUID.Zero is not a valid web_login_key on PrincipalID {0}", principalID);
68 }
69 else
70 {
71 AuthenticationData data = m_Database.Get(principalID);
72 if (data != null && data.Data != null)
73 {
74 if (data.Data.ContainsKey("webLoginKey"))
75 {
76 string key = data.Data["webLoginKey"].ToString();
77 if (key == password)
78 {
79 data.Data["webLoginKey"] = UUID.Zero.ToString();
80 m_Database.Store(data);
81 return GetToken(principalID, lifetime);
82 }
83 else
84 {
85 m_log.DebugFormat("[AUTH SERVICE]: web login auth failed, got PrincipalID {0} gave {1} instead of {2}", principalID, password, key);
86 }
87 }else{
88 m_log.DebugFormat("[AUTH SERVICE]: no col webLoginKey in passwd.db");
89 }
90 }
91 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
92 }
57 return String.Empty; 93 return String.Empty;
58 } 94 }
59 } 95 }
diff --git a/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs
new file mode 100644
index 0000000..2c6cebd
--- /dev/null
+++ b/OpenSim/Services/AuthenticationService/WebkeyOrPasswordAuthenticationService.cs
@@ -0,0 +1,92 @@
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 OpenMetaverse;
31using OpenSim.Services.Interfaces;
32using log4net;
33using Nini.Config;
34using System.Reflection;
35using OpenSim.Data;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Server.Base;
39
40namespace OpenSim.Services.AuthenticationService
41{
42 public class WebkeyOrPasswordAuthenticationService : AuthenticationServiceBase, IAuthenticationService
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 private Dictionary<string, IAuthenticationService> m_svcChecks
47 = new Dictionary<string, IAuthenticationService>();
48
49 public WebkeyOrPasswordAuthenticationService(IConfigSource config)
50 : base(config)
51 {
52 m_svcChecks["web_login_key"] = new WebkeyAuthenticationService(config);
53 m_svcChecks["password"] = new PasswordAuthenticationService(config);
54 }
55
56 public string Authenticate(UUID principalID, string password, int lifetime)
57 {
58 AuthenticationData data = m_Database.Get(principalID);
59 string result = String.Empty;
60 if (data != null && data.Data != null)
61 {
62 if (data.Data.ContainsKey("webLoginKey"))
63 {
64 m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID);
65 result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime);
66 if (result == String.Empty)
67 {
68 m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID);
69 }
70 }
71 if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt"))
72 {
73 m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID);
74 result = m_svcChecks["password"].Authenticate(principalID, password, lifetime);
75 if (result == String.Empty)
76 {
77 m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID);
78 }
79 }
80 if (result == string.Empty)
81 {
82 m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID);
83 }
84 }
85 else
86 {
87 m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID);
88 }
89 return result;
90 }
91 }
92} \ No newline at end of file
diff --git a/OpenSim/Services/AuthorizationService/AuthorizationService.cs b/OpenSim/Services/AuthorizationService/AuthorizationService.cs
index d658368..03da6e1 100644
--- a/OpenSim/Services/AuthorizationService/AuthorizationService.cs
+++ b/OpenSim/Services/AuthorizationService/AuthorizationService.cs
@@ -48,10 +48,11 @@ namespace OpenSim.Services.AuthorizationService
48 m_log.Info("[AUTHORIZATION CONNECTOR]: Local Authorization service enabled"); 48 m_log.Info("[AUTHORIZATION CONNECTOR]: Local Authorization service enabled");
49 } 49 }
50 50
51 public bool IsAuthorizedForRegion(string userID, string regionID, out string message) 51 public bool IsAuthorizedForRegion(
52 string userID, string firstName, string lastName, string regionID, out string message)
52 { 53 {
53 message = "Authorized"; 54 message = "Authorized";
54 return true; 55 return true;
55 } 56 }
56 } 57 }
57} 58} \ No newline at end of file
diff --git a/OpenSim/Services/AvatarService/AvatarService.cs b/OpenSim/Services/AvatarService/AvatarService.cs
new file mode 100644
index 0000000..c59a9e0
--- /dev/null
+++ b/OpenSim/Services/AvatarService/AvatarService.cs
@@ -0,0 +1,185 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using Nini.Config;
33using log4net;
34using OpenSim.Framework;
35using OpenSim.Framework.Console;
36using OpenSim.Data;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39
40namespace OpenSim.Services.AvatarService
41{
42 public class AvatarService : AvatarServiceBase, IAvatarService
43 {
44 private static readonly ILog m_log =
45 LogManager.GetLogger(
46 MethodBase.GetCurrentMethod().DeclaringType);
47
48 public AvatarService(IConfigSource config)
49 : base(config)
50 {
51 m_log.Debug("[AVATAR SERVICE]: Starting avatar service");
52 }
53
54 public AvatarAppearance GetAppearance(UUID principalID)
55 {
56 AvatarData avatar = GetAvatar(principalID);
57 return avatar.ToAvatarAppearance();
58 }
59
60 public bool SetAppearance(UUID principalID, AvatarAppearance appearance)
61 {
62 AvatarData avatar = new AvatarData(appearance);
63 return SetAvatar(principalID,avatar);
64 }
65
66 public AvatarData GetAvatar(UUID principalID)
67 {
68 AvatarBaseData[] av = m_Database.Get("PrincipalID", principalID.ToString());
69 AvatarData ret = new AvatarData();
70 ret.Data = new Dictionary<string,string>();
71
72 if (av.Length == 0)
73 {
74 ret.AvatarType = 1; // SL avatar
75 return ret;
76 }
77
78 foreach (AvatarBaseData b in av)
79 {
80 if (b.Data["Name"] == "AvatarType")
81 ret.AvatarType = Convert.ToInt32(b.Data["Value"]);
82 else
83 ret.Data[b.Data["Name"]] = b.Data["Value"];
84 }
85
86 return ret;
87 }
88
89 public bool SetAvatar(UUID principalID, AvatarData avatar)
90 {
91 int count = 0;
92 foreach (KeyValuePair<string, string> kvp in avatar.Data)
93 if (kvp.Key.StartsWith("_"))
94 count++;
95
96 m_log.DebugFormat("[AVATAR SERVICE]: SetAvatar for {0}, attachs={1}", principalID, count);
97 m_Database.Delete("PrincipalID", principalID.ToString());
98
99 AvatarBaseData av = new AvatarBaseData();
100 av.Data = new Dictionary<string,string>();
101
102 av.PrincipalID = principalID;
103 av.Data["Name"] = "AvatarType";
104 av.Data["Value"] = avatar.AvatarType.ToString();
105
106 if (!m_Database.Store(av))
107 return false;
108
109 foreach (KeyValuePair<string,string> kvp in avatar.Data)
110 {
111 av.Data["Name"] = kvp.Key;
112
113 // justincc 20110730. Yes, this is a hack to get around the fact that a bug in OpenSim is causing
114 // various simulators on osgrid to inject bad values. Since these simulators might be around for a
115 // long time, we are going to manually police the value.
116 //
117 // It should be possible to remove this in half a year if we don't want to police values server side.
118 if (kvp.Key == "AvatarHeight")
119 {
120 float height;
121 if (!float.TryParse(kvp.Value, out height) || height < 0 || height > 10)
122 {
123 string rawHeight = kvp.Value.Replace(",", ".");
124
125 if (!float.TryParse(rawHeight, out height) || height < 0 || height > 10)
126 height = 1.771488f;
127
128 m_log.DebugFormat(
129 "[AVATAR SERVICE]: Rectifying height of avatar {0} from {1} to {2}",
130 principalID, kvp.Value, height);
131 }
132
133 av.Data["Value"] = height.ToString();
134 }
135 else
136 {
137 av.Data["Value"] = kvp.Value;
138 }
139
140 if (!m_Database.Store(av))
141 {
142 m_Database.Delete("PrincipalID", principalID.ToString());
143 return false;
144 }
145 }
146
147 return true;
148 }
149
150 public bool ResetAvatar(UUID principalID)
151 {
152 return m_Database.Delete("PrincipalID", principalID.ToString());
153 }
154
155 public bool SetItems(UUID principalID, string[] names, string[] values)
156 {
157 AvatarBaseData av = new AvatarBaseData();
158 av.Data = new Dictionary<string,string>();
159 av.PrincipalID = principalID;
160
161 if (names.Length != values.Length)
162 return false;
163
164 for (int i = 0 ; i < names.Length ; i++)
165 {
166 av.Data["Name"] = names[i];
167 av.Data["Value"] = values[i];
168
169 if (!m_Database.Store(av))
170 return false;
171 }
172
173 return true;
174 }
175
176 public bool RemoveItems(UUID principalID, string[] names)
177 {
178 foreach (string name in names)
179 {
180 m_Database.Delete(principalID, name);
181 }
182 return true;
183 }
184 }
185}
diff --git a/OpenSim/Services/AvatarService/AvatarServiceBase.cs b/OpenSim/Services/AvatarService/AvatarServiceBase.cs
new file mode 100644
index 0000000..ab9d7cd
--- /dev/null
+++ b/OpenSim/Services/AvatarService/AvatarServiceBase.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 */
27
28using System;
29using System.Reflection;
30using Nini.Config;
31using OpenSim.Framework;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Services.Base;
35
36namespace OpenSim.Services.AvatarService
37{
38 public class AvatarServiceBase : ServiceBase
39 {
40 protected IAvatarData m_Database = null;
41
42 public AvatarServiceBase(IConfigSource config)
43 : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47 string realm = "Avatars";
48
49 //
50 // Try reading the [DatabaseService] section, if it exists
51 //
52 IConfig dbConfig = config.Configs["DatabaseService"];
53 if (dbConfig != null)
54 {
55 if (dllName == String.Empty)
56 dllName = dbConfig.GetString("StorageProvider", String.Empty);
57 if (connString == String.Empty)
58 connString = dbConfig.GetString("ConnectionString", String.Empty);
59 }
60
61 //
62 // [AvatarService] section overrides [DatabaseService], if it exists
63 //
64 IConfig presenceConfig = config.Configs["AvatarService"];
65 if (presenceConfig != null)
66 {
67 dllName = presenceConfig.GetString("StorageProvider", dllName);
68 connString = presenceConfig.GetString("ConnectionString", connString);
69 realm = presenceConfig.GetString("Realm", realm);
70 }
71
72 //
73 // We tried, but this doesn't exist. We can't proceed.
74 //
75 if (dllName.Equals(String.Empty))
76 throw new Exception("No StorageProvider configured");
77
78 m_Database = LoadPlugin<IAvatarData>(dllName, new Object[] { connString, realm });
79 if (m_Database == null)
80 throw new Exception("Could not find a storage interface in the given module " + dllName);
81
82 }
83 }
84}
diff --git a/OpenSim/Services/Base/ServiceBase.cs b/OpenSim/Services/Base/ServiceBase.cs
index 6bbe978..ef30cba 100644
--- a/OpenSim/Services/Base/ServiceBase.cs
+++ b/OpenSim/Services/Base/ServiceBase.cs
@@ -26,7 +26,9 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
31using log4net;
30using Nini.Config; 32using Nini.Config;
31using OpenSim.Services.Interfaces; 33using OpenSim.Services.Interfaces;
32 34
@@ -34,6 +36,8 @@ namespace OpenSim.Services.Base
34{ 36{
35 public class ServiceBase 37 public class ServiceBase
36 { 38 {
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40
37 public T LoadPlugin<T>(string dllName) where T:class 41 public T LoadPlugin<T>(string dllName) where T:class
38 { 42 {
39 return LoadPlugin<T>(dllName, new Object[0]); 43 return LoadPlugin<T>(dllName, new Object[0]);
@@ -61,8 +65,12 @@ namespace OpenSim.Services.Base
61 { 65 {
62 Assembly pluginAssembly = Assembly.LoadFrom(dllName); 66 Assembly pluginAssembly = Assembly.LoadFrom(dllName);
63 67
68// m_log.DebugFormat("[SERVICE BASE]: Found assembly {0}", dllName);
69
64 foreach (Type pluginType in pluginAssembly.GetTypes()) 70 foreach (Type pluginType in pluginAssembly.GetTypes())
65 { 71 {
72// m_log.DebugFormat("[SERVICE BASE]: Found type {0}", pluginType);
73
66 if (pluginType.IsPublic) 74 if (pluginType.IsPublic)
67 { 75 {
68 if (className != String.Empty && 76 if (className != String.Empty &&
@@ -84,8 +92,17 @@ namespace OpenSim.Services.Base
84 92
85 return null; 93 return null;
86 } 94 }
87 catch (Exception) 95 catch (Exception e)
88 { 96 {
97 List<string> strArgs = new List<string>();
98 foreach (Object arg in args)
99 strArgs.Add(arg.ToString());
100
101 m_log.Error(
102 string.Format(
103 "[SERVICE BASE]: Failed to load plugin {0} from {1} with args {2}",
104 interfaceName, dllName, string.Join(", ", strArgs.ToArray())), e);
105
89 return null; 106 return null;
90 } 107 }
91 } 108 }
@@ -94,4 +111,4 @@ namespace OpenSim.Services.Base
94 { 111 {
95 } 112 }
96 } 113 }
97} 114} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
index 84fbcd3..c753c6a 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs
@@ -30,11 +30,11 @@ using System;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Timers;
33using Nini.Config; 34using Nini.Config;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Framework.Console; 36using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
@@ -48,6 +48,15 @@ namespace OpenSim.Services.Connectors
48 48
49 private string m_ServerURI = String.Empty; 49 private string m_ServerURI = String.Empty;
50 private IImprovedAssetCache m_Cache = null; 50 private IImprovedAssetCache m_Cache = null;
51 private int m_retryCounter;
52 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
53 private Timer m_retryTimer;
54 private delegate void AssetRetrievedEx(AssetBase asset);
55
56 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
57 // Maps: Asset ID -> Handlers which will be called when the asset has been loaded
58 private Dictionary<string, AssetRetrievedEx> m_AssetHandlers = new Dictionary<string, AssetRetrievedEx>();
59 private Dictionary<string, string> m_UriMap = new Dictionary<string, string>();
51 60
52 public AssetServicesConnector() 61 public AssetServicesConnector()
53 { 62 {
@@ -68,7 +77,7 @@ namespace OpenSim.Services.Connectors
68 IConfig assetConfig = source.Configs["AssetService"]; 77 IConfig assetConfig = source.Configs["AssetService"];
69 if (assetConfig == null) 78 if (assetConfig == null)
70 { 79 {
71 m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpanSim.ini"); 80 m_log.Error("[ASSET CONNECTOR]: AssetService missing from OpenSim.ini");
72 throw new Exception("Asset connector init error"); 81 throw new Exception("Asset connector init error");
73 } 82 }
74 83
@@ -85,6 +94,83 @@ namespace OpenSim.Services.Connectors
85 MainConsole.Instance.Commands.AddCommand("asset", false, "dump asset", 94 MainConsole.Instance.Commands.AddCommand("asset", false, "dump asset",
86 "dump asset <id> <file>", 95 "dump asset <id> <file>",
87 "dump one cached asset", HandleDumpAsset); 96 "dump one cached asset", HandleDumpAsset);
97
98 m_retryTimer = new Timer();
99 m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck);
100 m_retryTimer.Interval = 60000;
101
102 Uri serverUri = new Uri(m_ServerURI);
103
104 string groupHost = serverUri.Host;
105
106 for (int i = 0 ; i < 256 ; i++)
107 {
108 string prefix = i.ToString("x2");
109 groupHost = assetConfig.GetString("AssetServerHost_"+prefix, groupHost);
110
111 m_UriMap[prefix] = groupHost;
112 //m_log.DebugFormat("[ASSET]: Using {0} for prefix {1}", groupHost, prefix);
113 }
114 }
115
116 private string MapServer(string id)
117 {
118 UriBuilder serverUri = new UriBuilder(m_ServerURI);
119
120 string prefix = id.Substring(0, 2).ToLower();
121
122 string host = m_UriMap[prefix];
123
124 serverUri.Host = host;
125
126 // m_log.DebugFormat("[ASSET]: Using {0} for host name for prefix {1}", host, prefix);
127
128 return serverUri.Uri.AbsoluteUri;
129 }
130
131 protected void retryCheck(object source, ElapsedEventArgs e)
132 {
133 m_retryCounter++;
134 if (m_retryCounter > 60) m_retryCounter -= 60;
135 List<int> keys = new List<int>();
136 foreach (int a in m_retryQueue.Keys)
137 {
138 keys.Add(a);
139 }
140 foreach (int a in keys)
141 {
142 //We exponentially fall back on frequency until we reach one attempt per hour
143 //The net result is that we end up in the queue for roughly 24 hours..
144 //24 hours worth of assets could be a lot, so the hope is that the region admin
145 //will have gotten the asset connector back online quickly!
146
147 int timefactor = a ^ 2;
148 if (timefactor > 60)
149 {
150 timefactor = 60;
151 }
152
153 //First, find out if we care about this timefactor
154 if (timefactor % a == 0)
155 {
156 //Yes, we do!
157 List<AssetBase> retrylist = m_retryQueue[a];
158 m_retryQueue.Remove(a);
159
160 foreach(AssetBase ass in retrylist)
161 {
162 Store(ass); //Store my ass. This function will put it back in the dictionary if it fails
163 }
164 }
165 }
166
167 if (m_retryQueue.Count == 0)
168 {
169 //It might only be one tick per minute, but I have
170 //repented and abandoned my wasteful ways
171 m_retryCounter = 0;
172 m_retryTimer.Stop();
173 }
88 } 174 }
89 175
90 protected void SetCache(IImprovedAssetCache cache) 176 protected void SetCache(IImprovedAssetCache cache)
@@ -94,13 +180,13 @@ namespace OpenSim.Services.Connectors
94 180
95 public AssetBase Get(string id) 181 public AssetBase Get(string id)
96 { 182 {
97 string uri = m_ServerURI + "/assets/" + id; 183 string uri = MapServer(id) + "/assets/" + id;
98 184
99 AssetBase asset = null; 185 AssetBase asset = null;
100 if (m_Cache != null) 186 if (m_Cache != null)
101 asset = m_Cache.Get(id); 187 asset = m_Cache.Get(id);
102 188
103 if (asset == null) 189 if (asset == null || asset.Data == null || asset.Data.Length == 0)
104 { 190 {
105 asset = SynchronousRestObjectRequester. 191 asset = SynchronousRestObjectRequester.
106 MakeRequest<int, AssetBase>("GET", uri, 0); 192 MakeRequest<int, AssetBase>("GET", uri, 0);
@@ -129,7 +215,7 @@ namespace OpenSim.Services.Connectors
129 return fullAsset.Metadata; 215 return fullAsset.Metadata;
130 } 216 }
131 217
132 string uri = m_ServerURI + "/assets/" + id + "/metadata"; 218 string uri = MapServer(id) + "/assets/" + id + "/metadata";
133 219
134 AssetMetadata asset = SynchronousRestObjectRequester. 220 AssetMetadata asset = SynchronousRestObjectRequester.
135 MakeRequest<int, AssetMetadata>("GET", uri, 0); 221 MakeRequest<int, AssetMetadata>("GET", uri, 0);
@@ -146,7 +232,7 @@ namespace OpenSim.Services.Connectors
146 return fullAsset.Data; 232 return fullAsset.Data;
147 } 233 }
148 234
149 RestClient rc = new RestClient(m_ServerURI); 235 RestClient rc = new RestClient(MapServer(id));
150 rc.AddResourcePath("assets"); 236 rc.AddResourcePath("assets");
151 rc.AddResourcePath(id); 237 rc.AddResourcePath(id);
152 rc.AddResourcePath("data"); 238 rc.AddResourcePath("data");
@@ -171,31 +257,64 @@ namespace OpenSim.Services.Connectors
171 257
172 public bool Get(string id, Object sender, AssetRetrieved handler) 258 public bool Get(string id, Object sender, AssetRetrieved handler)
173 { 259 {
174 string uri = m_ServerURI + "/assets/" + id; 260 string uri = MapServer(id) + "/assets/" + id;
175 261
176 AssetBase asset = null; 262 AssetBase asset = null;
177 if (m_Cache != null) 263 if (m_Cache != null)
178 asset = m_Cache.Get(id); 264 asset = m_Cache.Get(id);
179 265
180 if (asset == null) 266 if (asset == null || asset.Data == null || asset.Data.Length == 0)
181 { 267 {
182 bool result = false; 268 lock (m_AssetHandlers)
183 269 {
184 AsynchronousRestObjectRequester. 270 AssetRetrievedEx handlerEx = new AssetRetrievedEx(delegate(AssetBase _asset) { handler(id, sender, _asset); });
185 MakeRequest<int, AssetBase>("GET", uri, 0, 271
272 AssetRetrievedEx handlers;
273 if (m_AssetHandlers.TryGetValue(id, out handlers))
274 {
275 // Someone else is already loading this asset. It will notify our handler when done.
276 handlers += handlerEx;
277 return true;
278 }
279
280 // Load the asset ourselves
281 handlers += handlerEx;
282 m_AssetHandlers.Add(id, handlers);
283 }
284
285 bool success = false;
286 try
287 {
288 AsynchronousRestObjectRequester.MakeRequest<int, AssetBase>("GET", uri, 0,
186 delegate(AssetBase a) 289 delegate(AssetBase a)
187 { 290 {
188 if (m_Cache != null) 291 if (m_Cache != null)
189 m_Cache.Cache(a); 292 m_Cache.Cache(a);
190 handler(id, sender, a);
191 result = true;
192 });
193 293
194 return result; 294 AssetRetrievedEx handlers;
295 lock (m_AssetHandlers)
296 {
297 handlers = m_AssetHandlers[id];
298 m_AssetHandlers.Remove(id);
299 }
300 handlers.Invoke(a);
301 });
302
303 success = true;
304 }
305 finally
306 {
307 if (!success)
308 {
309 lock (m_AssetHandlers)
310 {
311 m_AssetHandlers.Remove(id);
312 }
313 }
314 }
195 } 315 }
196 else 316 else
197 { 317 {
198 //Util.FireAndForget(delegate { handler(id, sender, asset); });
199 handler(id, sender, asset); 318 handler(id, sender, asset);
200 } 319 }
201 320
@@ -204,38 +323,95 @@ namespace OpenSim.Services.Connectors
204 323
205 public string Store(AssetBase asset) 324 public string Store(AssetBase asset)
206 { 325 {
207 if (asset.Temporary || asset.Local) 326 // Have to assign the asset ID here. This isn't likely to
327 // trigger since current callers don't pass emtpy IDs
328 // We need the asset ID to route the request to the proper
329 // cluster member, so we can't have the server assign one.
330 if (asset.ID == string.Empty)
208 { 331 {
209 if (m_Cache != null) 332 if (asset.FullID == UUID.Zero)
210 m_Cache.Cache(asset); 333 {
334 asset.FullID = UUID.Random();
335 }
336 asset.ID = asset.FullID.ToString();
337 }
338 else if (asset.FullID == UUID.Zero)
339 {
340 UUID uuid = UUID.Zero;
341 if (UUID.TryParse(asset.ID, out uuid))
342 {
343 asset.FullID = uuid;
344 }
345 else
346 {
347 asset.FullID = UUID.Random();
348 }
349 }
211 350
351 if (m_Cache != null)
352 m_Cache.Cache(asset);
353 if (asset.Temporary || asset.Local)
354 {
212 return asset.ID; 355 return asset.ID;
213 } 356 }
214 357
215 string uri = m_ServerURI + "/assets/"; 358 string uri = MapServer(asset.FullID.ToString()) + "/assets/";
216 359
217 string newID = string.Empty; 360 string newID = string.Empty;
218 try 361 try
219 { 362 {
220 newID = SynchronousRestObjectRequester. 363 newID = SynchronousRestObjectRequester.
221 MakeRequest<AssetBase, string>("POST", uri, asset); 364 MakeRequest<AssetBase, string>("POST", uri, asset, 25);
365 if (newID == null || newID == "")
366 {
367 newID = UUID.Zero.ToString();
368 }
222 } 369 }
223 catch (Exception e) 370 catch (Exception e)
224 { 371 {
225 m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message); 372 newID = UUID.Zero.ToString();
226 } 373 }
227 374
228 if (newID != String.Empty) 375 if (newID == UUID.Zero.ToString())
229 { 376 {
230 // Placing this here, so that this work with old asset servers that don't send any reply back 377 //The asset upload failed, put it in a queue for later
231 // SynchronousRestObjectRequester returns somethins that is not an empty string 378 asset.UploadAttempts++;
232 if (newID != null) 379 if (asset.UploadAttempts > 30)
233 asset.ID = newID; 380 {
234 381 //By this stage we've been in the queue for a good few hours;
235 if (m_Cache != null) 382 //We're going to drop the asset.
236 m_Cache.Cache(asset); 383 m_log.ErrorFormat("[Assets] Dropping asset {0} - Upload has been in the queue for too long.", asset.ID.ToString());
384 }
385 else
386 {
387 if (!m_retryQueue.ContainsKey(asset.UploadAttempts))
388 {
389 m_retryQueue.Add(asset.UploadAttempts, new List<AssetBase>());
390 }
391 List<AssetBase> m_queue = m_retryQueue[asset.UploadAttempts];
392 m_queue.Add(asset);
393 m_log.WarnFormat("[Assets] Upload failed: {0} - Requeuing asset for another run.", asset.ID.ToString());
394 m_retryTimer.Start();
395 }
396 }
397 else
398 {
399 if (asset.UploadAttempts > 0)
400 {
401 m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString());
402 }
403 if (newID != String.Empty)
404 {
405 // Placing this here, so that this work with old asset servers that don't send any reply back
406 // SynchronousRestObjectRequester returns somethins that is not an empty string
407 if (newID != null)
408 asset.ID = newID;
409
410 if (m_Cache != null)
411 m_Cache.Cache(asset);
412 }
237 } 413 }
238 return newID; 414 return asset.ID;
239 } 415 }
240 416
241 public bool UpdateContent(string id, byte[] data) 417 public bool UpdateContent(string id, byte[] data)
@@ -251,12 +427,12 @@ namespace OpenSim.Services.Connectors
251 if (metadata == null) 427 if (metadata == null)
252 return false; 428 return false;
253 429
254 asset = new AssetBase(metadata.FullID, metadata.Name, metadata.Type); 430 asset = new AssetBase(metadata.FullID, metadata.Name, metadata.Type, UUID.Zero.ToString());
255 asset.Metadata = metadata; 431 asset.Metadata = metadata;
256 } 432 }
257 asset.Data = data; 433 asset.Data = data;
258 434
259 string uri = m_ServerURI + "/assets/" + id; 435 string uri = MapServer(id) + "/assets/" + id;
260 436
261 if (SynchronousRestObjectRequester. 437 if (SynchronousRestObjectRequester.
262 MakeRequest<AssetBase, bool>("POST", uri, asset)) 438 MakeRequest<AssetBase, bool>("POST", uri, asset))
@@ -271,7 +447,7 @@ namespace OpenSim.Services.Connectors
271 447
272 public bool Delete(string id) 448 public bool Delete(string id)
273 { 449 {
274 string uri = m_ServerURI + "/assets/" + id; 450 string uri = MapServer(id) + "/assets/" + id;
275 451
276 if (SynchronousRestObjectRequester. 452 if (SynchronousRestObjectRequester.
277 MakeRequest<int, bool>("DELETE", uri, 0)) 453 MakeRequest<int, bool>("DELETE", uri, 0))
diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs
index 34df54a..5c31639 100644
--- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs
@@ -32,6 +32,8 @@ using System.Collections.Generic;
32using System.Reflection; 32using System.Reflection;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Services.Interfaces; 34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Connectors.SimianGrid;
35 37
36namespace OpenSim.Services.Connectors 38namespace OpenSim.Services.Connectors
37{ 39{
@@ -41,7 +43,7 @@ namespace OpenSim.Services.Connectors
41 LogManager.GetLogger( 43 LogManager.GetLogger(
42 MethodBase.GetCurrentMethod().DeclaringType); 44 MethodBase.GetCurrentMethod().DeclaringType);
43 45
44 private Dictionary<string, AssetServicesConnector> m_connectors = new Dictionary<string, AssetServicesConnector>(); 46 private Dictionary<string, IAssetService> m_connectors = new Dictionary<string, IAssetService>();
45 47
46 public HGAssetServiceConnector(IConfigSource source) 48 public HGAssetServiceConnector(IConfigSource source)
47 { 49 {
@@ -81,7 +83,7 @@ namespace OpenSim.Services.Connectors
81 83
82 private IAssetService GetConnector(string url) 84 private IAssetService GetConnector(string url)
83 { 85 {
84 AssetServicesConnector connector = null; 86 IAssetService connector = null;
85 lock (m_connectors) 87 lock (m_connectors)
86 { 88 {
87 if (m_connectors.ContainsKey(url)) 89 if (m_connectors.ContainsKey(url))
@@ -90,12 +92,17 @@ namespace OpenSim.Services.Connectors
90 } 92 }
91 else 93 else
92 { 94 {
93 // We're instantiating this class explicitly, but this won't 95 // Still not as flexible as I would like this to be,
94 // work in general, because the remote grid may be running 96 // but good enough for now
95 // an asset server that has a different protocol. 97 string connectorType = new HeloServicesConnector(url).Helo();
96 // Eventually we will want a piece of protocol asking 98 m_log.DebugFormat("[HG ASSET SERVICE]: HELO returned {0}", connectorType);
97 // the remote server about its kind. Definitely cool thing to do! 99 if (connectorType == "opensim-simian")
98 connector = new AssetServicesConnector(url); 100 {
101 connector = new SimianAssetServiceConnector(url);
102 }
103 else
104 connector = new AssetServicesConnector(url);
105
99 m_connectors.Add(url, connector); 106 m_connectors.Add(url, connector);
100 } 107 }
101 } 108 }
diff --git a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
index 19bb3e2..2b77154 100644
--- a/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Authentication/AuthenticationServiceConnector.cs
@@ -33,7 +33,6 @@ using System.Reflection;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
38using OpenSim.Server.Base; 37using OpenSim.Server.Base;
39using OpenMetaverse; 38using OpenMetaverse;
@@ -67,7 +66,7 @@ namespace OpenSim.Services.Connectors
67 IConfig assetConfig = source.Configs["AuthenticationService"]; 66 IConfig assetConfig = source.Configs["AuthenticationService"];
68 if (assetConfig == null) 67 if (assetConfig == null)
69 { 68 {
70 m_log.Error("[USER CONNECTOR]: AuthenticationService missing from OpanSim.ini"); 69 m_log.Error("[AUTH CONNECTOR]: AuthenticationService missing from OpenSim.ini");
71 throw new Exception("Authentication connector init error"); 70 throw new Exception("Authentication connector init error");
72 } 71 }
73 72
@@ -76,7 +75,7 @@ namespace OpenSim.Services.Connectors
76 75
77 if (serviceURI == String.Empty) 76 if (serviceURI == String.Empty)
78 { 77 {
79 m_log.Error("[USER CONNECTOR]: No Server URI named in section AuthenticationService"); 78 m_log.Error("[AUTH CONNECTOR]: No Server URI named in section AuthenticationService");
80 throw new Exception("Authentication connector init error"); 79 throw new Exception("Authentication connector init error");
81 } 80 }
82 m_ServerURI = serviceURI; 81 m_ServerURI = serviceURI;
@@ -146,5 +145,23 @@ namespace OpenSim.Services.Connectors
146 145
147 return true; 146 return true;
148 } 147 }
148
149 public bool SetPassword(UUID principalID, string passwd)
150 {
151 // nope, we don't do this
152 return false;
153 }
154
155 public AuthInfo GetAuthInfo(UUID principalID)
156 {
157 // not done from remote simulators
158 return null;
159 }
160
161 public bool SetAuthInfo(AuthInfo info)
162 {
163 // not done from remote simulators
164 return false;
165 }
149 } 166 }
150} 167}
diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs
index 4eb4bd2..35b7109 100644
--- a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs
@@ -33,7 +33,6 @@ using System.Reflection;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
38using OpenMetaverse; 37using OpenMetaverse;
39 38
diff --git a/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs
new file mode 100644
index 0000000..8fdb4d0
--- /dev/null
+++ b/OpenSim/Services/Connectors/Avatar/AvatarServiceConnector.cs
@@ -0,0 +1,328 @@
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.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using IAvatarService = OpenSim.Services.Interfaces.IAvatarService;
39using OpenSim.Server.Base;
40using OpenMetaverse;
41
42namespace OpenSim.Services.Connectors
43{
44 public class AvatarServicesConnector : IAvatarService
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 AvatarServicesConnector()
53 {
54 }
55
56 public AvatarServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public AvatarServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig gridConfig = source.Configs["AvatarService"];
69 if (gridConfig == null)
70 {
71 m_log.Error("[AVATAR CONNECTOR]: AvatarService missing from OpenSim.ini");
72 throw new Exception("Avatar connector init error");
73 }
74
75 string serviceURI = gridConfig.GetString("AvatarServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[AVATAR CONNECTOR]: No Server URI named in section AvatarService");
81 throw new Exception("Avatar connector init error");
82 }
83 m_ServerURI = serviceURI;
84 }
85
86
87 #region IAvatarService
88
89 public AvatarAppearance GetAppearance(UUID userID)
90 {
91 AvatarData avatar = GetAvatar(userID);
92 return avatar.ToAvatarAppearance();
93 }
94
95 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
96 {
97 AvatarData avatar = new AvatarData(appearance);
98 return SetAvatar(userID,avatar);
99 }
100
101 public AvatarData GetAvatar(UUID userID)
102 {
103 Dictionary<string, object> sendData = new Dictionary<string, object>();
104 //sendData["SCOPEID"] = scopeID.ToString();
105 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
106 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
107 sendData["METHOD"] = "getavatar";
108
109 sendData["UserID"] = userID;
110
111 string reply = string.Empty;
112 string reqString = ServerUtils.BuildQueryString(sendData);
113 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
114 try
115 {
116 reply = SynchronousRestFormsRequester.MakeRequest("POST",
117 m_ServerURI + "/avatar",
118 reqString);
119 if (reply == null || (reply != null && reply == string.Empty))
120 {
121 m_log.DebugFormat("[AVATAR CONNECTOR]: GetAgent received null or empty reply");
122 return null;
123 }
124 }
125 catch (Exception e)
126 {
127 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
128 }
129
130 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
131 AvatarData avatar = null;
132
133 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
134 {
135 if (replyData["result"] is Dictionary<string, object>)
136 {
137 avatar = new AvatarData((Dictionary<string, object>)replyData["result"]);
138 }
139 }
140
141 return avatar;
142
143 }
144
145 public bool SetAvatar(UUID userID, AvatarData avatar)
146 {
147 Dictionary<string, object> sendData = new Dictionary<string, object>();
148 //sendData["SCOPEID"] = scopeID.ToString();
149 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
150 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
151 sendData["METHOD"] = "setavatar";
152
153 sendData["UserID"] = userID.ToString();
154
155 Dictionary<string, object> structData = avatar.ToKeyValuePairs();
156
157 foreach (KeyValuePair<string, object> kvp in structData)
158 sendData[kvp.Key] = kvp.Value.ToString();
159
160
161 string reqString = ServerUtils.BuildQueryString(sendData);
162 //m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
163 try
164 {
165 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
166 m_ServerURI + "/avatar",
167 reqString);
168 if (reply != string.Empty)
169 {
170 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
171
172 if (replyData.ContainsKey("result"))
173 {
174 if (replyData["result"].ToString().ToLower() == "success")
175 return true;
176 else
177 return false;
178 }
179 else
180 m_log.DebugFormat("[AVATAR CONNECTOR]: SetAvatar reply data does not contain result field");
181
182 }
183 else
184 m_log.DebugFormat("[AVATAR CONNECTOR]: SetAvatar received empty reply");
185 }
186 catch (Exception e)
187 {
188 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting avatar server: {0}", e.Message);
189 }
190
191 return false;
192 }
193
194 public bool ResetAvatar(UUID userID)
195 {
196 Dictionary<string, object> sendData = new Dictionary<string, object>();
197 //sendData["SCOPEID"] = scopeID.ToString();
198 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
199 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
200 sendData["METHOD"] = "resetavatar";
201
202 sendData["UserID"] = userID.ToString();
203
204 string reqString = ServerUtils.BuildQueryString(sendData);
205 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
206 try
207 {
208 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
209 m_ServerURI + "/avatar",
210 reqString);
211 if (reply != string.Empty)
212 {
213 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
214
215 if (replyData.ContainsKey("result"))
216 {
217 if (replyData["result"].ToString().ToLower() == "success")
218 return true;
219 else
220 return false;
221 }
222 else
223 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems reply data does not contain result field");
224
225 }
226 else
227 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems received empty reply");
228 }
229 catch (Exception e)
230 {
231 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting avatar server: {0}", e.Message);
232 }
233
234 return false;
235 }
236
237 public bool SetItems(UUID userID, string[] names, string[] values)
238 {
239 Dictionary<string, object> sendData = new Dictionary<string, object>();
240 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
241 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
242 sendData["METHOD"] = "setitems";
243
244 sendData["UserID"] = userID.ToString();
245 sendData["Names"] = new List<string>(names);
246 sendData["Values"] = new List<string>(values);
247
248 string reqString = ServerUtils.BuildQueryString(sendData);
249 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
250 try
251 {
252 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
253 m_ServerURI + "/avatar",
254 reqString);
255 if (reply != string.Empty)
256 {
257 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
258
259 if (replyData.ContainsKey("result"))
260 {
261 if (replyData["result"].ToString().ToLower() == "success")
262 return true;
263 else
264 return false;
265 }
266 else
267 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems reply data does not contain result field");
268
269 }
270 else
271 m_log.DebugFormat("[AVATAR CONNECTOR]: SetItems received empty reply");
272 }
273 catch (Exception e)
274 {
275 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting avatar server: {0}", e.Message);
276 }
277
278 return false;
279 }
280
281 public bool RemoveItems(UUID userID, string[] names)
282 {
283 Dictionary<string, object> sendData = new Dictionary<string, object>();
284 //sendData["SCOPEID"] = scopeID.ToString();
285 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
286 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
287 sendData["METHOD"] = "removeitems";
288
289 sendData["UserID"] = userID.ToString();
290 sendData["Names"] = new List<string>(names);
291
292 string reqString = ServerUtils.BuildQueryString(sendData);
293 // m_log.DebugFormat("[AVATAR CONNECTOR]: queryString = {0}", reqString);
294 try
295 {
296 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
297 m_ServerURI + "/avatar",
298 reqString);
299 if (reply != string.Empty)
300 {
301 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
302
303 if (replyData.ContainsKey("result"))
304 {
305 if (replyData["result"].ToString().ToLower() == "success")
306 return true;
307 else
308 return false;
309 }
310 else
311 m_log.DebugFormat("[AVATAR CONNECTOR]: RemoveItems reply data does not contain result field");
312
313 }
314 else
315 m_log.DebugFormat("[AVATAR CONNECTOR]: RemoveItems received empty reply");
316 }
317 catch (Exception e)
318 {
319 m_log.DebugFormat("[AVATAR CONNECTOR]: Exception when contacting avatar server: {0}", e.Message);
320 }
321
322 return false;
323 }
324
325 #endregion
326
327 }
328}
diff --git a/OpenSim/Services/Connectors/User/UserServiceConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs
index 683990f..d688299 100644
--- a/OpenSim/Services/Connectors/User/UserServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs
@@ -27,88 +27,77 @@
27 27
28using log4net; 28using log4net;
29using System; 29using System;
30using System.Collections.Generic;
31using System.IO; 30using System.IO;
31using System.Collections;
32using System.Reflection; 32using System.Reflection;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
37using OpenSim.Server.Base;
38using OpenMetaverse; 38using OpenMetaverse;
39 39
40namespace OpenSim.Services.Connectors 40namespace OpenSim.Services.Connectors
41{ 41{
42 public class UserServicesConnector : IUserAccountService 42 public class RemoteFreeswitchConnector : IFreeswitchService
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// private string m_ServerURI = String.Empty; 48 private string m_ServerURI = String.Empty;
49 49
50 public UserServicesConnector() 50 public RemoteFreeswitchConnector()
51 { 51 {
52 } 52 }
53 53
54 public UserServicesConnector(string serverURI) 54 public RemoteFreeswitchConnector(string serverURI)
55 { 55 {
56// m_ServerURI = serverURI.TrimEnd('/'); 56 m_ServerURI = serverURI.TrimEnd('/') + "/region-config";
57 } 57 }
58 58
59 public UserServicesConnector(IConfigSource source) 59 public RemoteFreeswitchConnector(IConfigSource source)
60 { 60 {
61 Initialise(source); 61 Initialise(source);
62 } 62 }
63 63
64 public virtual void Initialise(IConfigSource source) 64 public virtual void Initialise(IConfigSource source)
65 { 65 {
66 IConfig assetConfig = source.Configs["UserService"]; 66 IConfig freeswitchConfig = source.Configs["FreeSwitchVoice"];
67 if (assetConfig == null) 67 if (freeswitchConfig == null)
68 { 68 {
69 m_log.Error("[USER CONNECTOR]: UserService missing from OpanSim.ini"); 69 m_log.Error("[FREESWITCH CONNECTOR]: FreeSwitchVoice missing from OpenSim.ini");
70 throw new Exception("User connector init error"); 70 throw new Exception("Freeswitch connector init error");
71 } 71 }
72 72
73 string serviceURI = assetConfig.GetString("UserServerURI", 73 string serviceURI = freeswitchConfig.GetString("FreeswitchServiceURL",
74 String.Empty); 74 String.Empty);
75 75
76 if (serviceURI == String.Empty) 76 if (serviceURI == String.Empty)
77 { 77 {
78 m_log.Error("[USER CONNECTOR]: No Server URI named in section UserService"); 78 m_log.Error("[FREESWITCH CONNECTOR]: No FreeswitchServiceURL named in section FreeSwitchVoice");
79 throw new Exception("User connector init error"); 79 throw new Exception("Freeswitch connector init error");
80 } 80 }
81 //m_ServerURI = serviceURI; 81 m_ServerURI = serviceURI.TrimEnd('/') + "/region-config";
82 } 82 }
83 83
84 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) 84 public Hashtable HandleDirectoryRequest(Hashtable requestBody)
85 { 85 {
86 return null; 86 // not used here
87 return new Hashtable();
87 } 88 }
88 89
89 public UserAccount GetUserAccount(UUID scopeID, UUID userID) 90 public Hashtable HandleDialplanRequest(Hashtable requestBody)
90 { 91 {
91 return null; 92 // not used here
93 return new Hashtable();
92 } 94 }
93 95
94 public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret) 96 public string GetJsonConfig()
95 { 97 {
96 return false; 98 m_log.DebugFormat("[FREESWITCH CONNECTOR]: Requesting config from {0}", m_ServerURI);
97 } 99 return SynchronousRestFormsRequester.MakeRequest("GET",
98 100 m_ServerURI, String.Empty);
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 } 101 }
113 } 102 }
114} 103}
diff --git a/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs
new file mode 100644
index 0000000..41361ab
--- /dev/null
+++ b/OpenSim/Services/Connectors/Friends/FriendsServiceConnector.cs
@@ -0,0 +1,271 @@
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.Services.Interfaces;
37using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors.Friends
42{
43 public class FriendsServicesConnector : IFriendsService
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 FriendsServicesConnector()
52 {
53 }
54
55 public FriendsServicesConnector(string serverURI)
56 {
57 m_ServerURI = serverURI.TrimEnd('/');
58 }
59
60 public FriendsServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig gridConfig = source.Configs["FriendsService"];
68 if (gridConfig == null)
69 {
70 m_log.Error("[FRIENDS SERVICE CONNECTOR]: FriendsService missing from OpenSim.ini");
71 throw new Exception("Friends connector init error");
72 }
73
74 string serviceURI = gridConfig.GetString("FriendsServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[FRIENDS SERVICE CONNECTOR]: No Server URI named in section FriendsService");
80 throw new Exception("Friends connector init error");
81 }
82 m_ServerURI = serviceURI;
83 }
84
85
86 #region IFriendsService
87
88 public FriendInfo[] GetFriends(UUID PrincipalID)
89 {
90 Dictionary<string, object> sendData = new Dictionary<string, object>();
91
92 sendData["PRINCIPALID"] = PrincipalID.ToString();
93 sendData["METHOD"] = "getfriends";
94
95 return GetFriends(sendData, PrincipalID.ToString());
96 }
97
98 public FriendInfo[] GetFriends(string PrincipalID)
99 {
100 Dictionary<string, object> sendData = new Dictionary<string, object>();
101
102 sendData["PRINCIPALID"] = PrincipalID;
103 sendData["METHOD"] = "getfriends_string";
104
105 return GetFriends(sendData, PrincipalID);
106 }
107
108 protected FriendInfo[] GetFriends(Dictionary<string, object> sendData, string PrincipalID)
109 {
110 string reqString = ServerUtils.BuildQueryString(sendData);
111
112 try
113 {
114 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
115 m_ServerURI + "/friends",
116 reqString);
117 if (reply != string.Empty)
118 {
119 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
120
121 if (replyData != null)
122 {
123 if (replyData.ContainsKey("result") && (replyData["result"].ToString().ToLower() == "null"))
124 {
125 return new FriendInfo[0];
126 }
127
128 List<FriendInfo> finfos = new List<FriendInfo>();
129 Dictionary<string, object>.ValueCollection finfosList = replyData.Values;
130 //m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: get neighbours returned {0} elements", rinfosList.Count);
131 foreach (object f in finfosList)
132 {
133 if (f is Dictionary<string, object>)
134 {
135 FriendInfo finfo = new FriendInfo((Dictionary<string, object>)f);
136 finfos.Add(finfo);
137 }
138 else
139 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: GetFriends {0} received invalid response type {1}",
140 PrincipalID, f.GetType());
141 }
142
143 // Success
144 return finfos.ToArray();
145 }
146
147 else
148 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: GetFriends {0} received null response",
149 PrincipalID);
150
151 }
152 }
153 catch (Exception e)
154 {
155 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
156 }
157
158 return new FriendInfo[0];
159
160 }
161
162 public bool StoreFriend(string PrincipalID, string Friend, int flags)
163 {
164
165 Dictionary<string, object> sendData = ToKeyValuePairs(PrincipalID, Friend, flags);
166
167 sendData["METHOD"] = "storefriend";
168
169 string reply = string.Empty;
170 try
171 {
172 reply = SynchronousRestFormsRequester.MakeRequest("POST",
173 m_ServerURI + "/friends",
174 ServerUtils.BuildQueryString(sendData));
175 }
176 catch (Exception e)
177 {
178 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
179 return false;
180 }
181
182 if (reply != string.Empty)
183 {
184 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
185
186 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
187 {
188 bool success = false;
189 Boolean.TryParse(replyData["Result"].ToString(), out success);
190 return success;
191 }
192 else
193 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: StoreFriend {0} {1} received null response",
194 PrincipalID, Friend);
195 }
196 else
197 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: StoreFriend received null reply");
198
199 return false;
200
201 }
202
203 public bool Delete(string PrincipalID, string Friend)
204 {
205 Dictionary<string, object> sendData = new Dictionary<string, object>();
206 sendData["PRINCIPALID"] = PrincipalID.ToString();
207 sendData["FRIEND"] = Friend;
208 sendData["METHOD"] = "deletefriend_string";
209
210 return Delete(sendData, PrincipalID, Friend);
211 }
212
213 public bool Delete(UUID PrincipalID, string Friend)
214 {
215 Dictionary<string, object> sendData = new Dictionary<string, object>();
216 sendData["PRINCIPALID"] = PrincipalID.ToString();
217 sendData["FRIEND"] = Friend;
218 sendData["METHOD"] = "deletefriend";
219
220 return Delete(sendData, PrincipalID.ToString(), Friend);
221 }
222
223 public bool Delete(Dictionary<string, object> sendData, string PrincipalID, string Friend)
224 {
225 string reply = string.Empty;
226 try
227 {
228 reply = SynchronousRestFormsRequester.MakeRequest("POST",
229 m_ServerURI + "/friends",
230 ServerUtils.BuildQueryString(sendData));
231 }
232 catch (Exception e)
233 {
234 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
235 return false;
236 }
237
238 if (reply != string.Empty)
239 {
240 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
241
242 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
243 {
244 bool success = false;
245 Boolean.TryParse(replyData["Result"].ToString(), out success);
246 return success;
247 }
248 else
249 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: DeleteFriend {0} {1} received null response",
250 PrincipalID, Friend);
251 }
252 else
253 m_log.DebugFormat("[FRIENDS SERVICE CONNECTOR]: DeleteFriend received null reply");
254
255 return false;
256 }
257
258 #endregion
259
260 public Dictionary<string, object> ToKeyValuePairs(string principalID, string friend, int flags)
261 {
262 Dictionary<string, object> result = new Dictionary<string, object>();
263 result["PrincipalID"] = principalID;
264 result["Friend"] = friend;
265 result["MyFlags"] = flags;
266
267 return result;
268 }
269
270 }
271} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
new file mode 100644
index 0000000..d0a20fc
--- /dev/null
+++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
@@ -0,0 +1,174 @@
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.Reflection;
31
32using OpenSim.Services.Interfaces;
33using GridRegion = OpenSim.Services.Interfaces.GridRegion;
34using OpenSim.Server.Base;
35using OpenSim.Framework;
36
37using OpenMetaverse;
38using log4net;
39
40namespace OpenSim.Services.Connectors.Friends
41{
42 public class FriendsSimConnector
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45
46 public bool FriendshipOffered(GridRegion region, UUID userID, UUID friendID, string message)
47 {
48 Dictionary<string, object> sendData = new Dictionary<string, object>();
49 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
50 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
51 sendData["METHOD"] = "friendship_offered";
52
53 sendData["FromID"] = userID.ToString();
54 sendData["ToID"] = friendID.ToString();
55 sendData["Message"] = message;
56
57 return Call(region, sendData);
58
59 }
60
61 public bool FriendshipApproved(GridRegion region, UUID userID, string userName, UUID friendID)
62 {
63 Dictionary<string, object> sendData = new Dictionary<string, object>();
64 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
65 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
66 sendData["METHOD"] = "friendship_approved";
67
68 sendData["FromID"] = userID.ToString();
69 sendData["FromName"] = userName;
70 sendData["ToID"] = friendID.ToString();
71
72 return Call(region, sendData);
73 }
74
75 public bool FriendshipDenied(GridRegion region, UUID userID, string userName, UUID friendID)
76 {
77 if (region == null)
78 return false;
79
80 Dictionary<string, object> sendData = new Dictionary<string, object>();
81 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
82 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
83 sendData["METHOD"] = "friendship_denied";
84
85 sendData["FromID"] = userID.ToString();
86 sendData["FromName"] = userName;
87 sendData["ToID"] = friendID.ToString();
88
89 return Call(region, sendData);
90 }
91
92 public bool FriendshipTerminated(GridRegion region, UUID userID, UUID friendID)
93 {
94 Dictionary<string, object> sendData = new Dictionary<string, object>();
95 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
96 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
97 sendData["METHOD"] = "friendship_terminated";
98
99 sendData["FromID"] = userID.ToString();
100 sendData["ToID"] = friendID.ToString();
101
102 return Call(region, sendData);
103 }
104
105 public bool GrantRights(GridRegion region, UUID userID, UUID friendID, int userFlags, int rights)
106 {
107 Dictionary<string, object> sendData = new Dictionary<string, object>();
108 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
109 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
110 sendData["METHOD"] = "grant_rights";
111
112 sendData["FromID"] = userID.ToString();
113 sendData["ToID"] = friendID.ToString();
114 sendData["UserFlags"] = userFlags.ToString();
115 sendData["Rights"] = rights.ToString();
116
117 return Call(region, sendData);
118 }
119
120 public bool StatusNotify(GridRegion region, UUID userID, UUID friendID, bool online)
121 {
122 Dictionary<string, object> sendData = new Dictionary<string, object>();
123 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
124 //sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
125 sendData["METHOD"] = "status";
126
127 sendData["FromID"] = userID.ToString();
128 sendData["ToID"] = friendID.ToString();
129 sendData["Online"] = online.ToString();
130
131 return Call(region, sendData);
132 }
133
134 private bool Call(GridRegion region, Dictionary<string, object> sendData)
135 {
136 string reqString = ServerUtils.BuildQueryString(sendData);
137 //m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: queryString = {0}", reqString);
138 if (region == null)
139 return false;
140
141 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: region: {0}", region.ExternalHostName + ":" + region.HttpPort);
142 try
143 {
144 string url = "http://" + region.ExternalHostName + ":" + region.HttpPort;
145 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
146 url + "/friends",
147 reqString);
148 if (reply != string.Empty)
149 {
150 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
151
152 if (replyData.ContainsKey("RESULT"))
153 {
154 if (replyData["RESULT"].ToString().ToLower() == "true")
155 return true;
156 else
157 return false;
158 }
159 else
160 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: reply data does not contain result field");
161
162 }
163 else
164 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: received empty reply");
165 }
166 catch (Exception e)
167 {
168 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: Exception when contacting remote sim: {0}", e.ToString());
169 }
170
171 return false;
172 }
173 }
174}
diff --git a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
index 04c7c53..e57f28b 100644
--- a/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Grid/GridServiceConnector.cs
@@ -33,7 +33,6 @@ using System.Reflection;
33using Nini.Config; 33using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Framework.Servers.HttpServer;
37using OpenSim.Services.Interfaces; 36using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion; 37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base; 38using OpenSim.Server.Base;
@@ -86,7 +85,7 @@ namespace OpenSim.Services.Connectors
86 85
87 #region IGridService 86 #region IGridService
88 87
89 public virtual string RegisterRegion(UUID scopeID, GridRegion regionInfo) 88 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
90 { 89 {
91 Dictionary<string, object> rinfo = regionInfo.ToKeyValuePairs(); 90 Dictionary<string, object> rinfo = regionInfo.ToKeyValuePairs();
92 Dictionary<string, object> sendData = new Dictionary<string,object>(); 91 Dictionary<string, object> sendData = new Dictionary<string,object>();
@@ -140,7 +139,7 @@ namespace OpenSim.Services.Connectors
140 return "Error communicating with grid service"; 139 return "Error communicating with grid service";
141 } 140 }
142 141
143 public virtual bool DeregisterRegion(UUID regionID) 142 public bool DeregisterRegion(UUID regionID)
144 { 143 {
145 Dictionary<string, object> sendData = new Dictionary<string, object>(); 144 Dictionary<string, object> sendData = new Dictionary<string, object>();
146 145
@@ -172,7 +171,7 @@ namespace OpenSim.Services.Connectors
172 return false; 171 return false;
173 } 172 }
174 173
175 public virtual List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID) 174 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
176 { 175 {
177 Dictionary<string, object> sendData = new Dictionary<string, object>(); 176 Dictionary<string, object> sendData = new Dictionary<string, object>();
178 177
@@ -210,9 +209,6 @@ namespace OpenSim.Services.Connectors
210 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r); 209 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
211 rinfos.Add(rinfo); 210 rinfos.Add(rinfo);
212 } 211 }
213 else
214 m_log.DebugFormat("[GRID CONNECTOR]: GetNeighbours {0}, {1} received invalid response type {2}",
215 scopeID, regionID, r.GetType());
216 } 212 }
217 } 213 }
218 else 214 else
@@ -222,7 +218,7 @@ namespace OpenSim.Services.Connectors
222 return rinfos; 218 return rinfos;
223 } 219 }
224 220
225 public virtual GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) 221 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
226 { 222 {
227 Dictionary<string, object> sendData = new Dictionary<string, object>(); 223 Dictionary<string, object> sendData = new Dictionary<string, object>();
228 224
@@ -268,7 +264,7 @@ namespace OpenSim.Services.Connectors
268 return rinfo; 264 return rinfo;
269 } 265 }
270 266
271 public virtual GridRegion GetRegionByPosition(UUID scopeID, int x, int y) 267 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
272 { 268 {
273 Dictionary<string, object> sendData = new Dictionary<string, object>(); 269 Dictionary<string, object> sendData = new Dictionary<string, object>();
274 270
@@ -299,9 +295,9 @@ namespace OpenSim.Services.Connectors
299 { 295 {
300 if (replyData["result"] is Dictionary<string, object>) 296 if (replyData["result"] is Dictionary<string, object>)
301 rinfo = new GridRegion((Dictionary<string, object>)replyData["result"]); 297 rinfo = new GridRegion((Dictionary<string, object>)replyData["result"]);
302 else 298 //else
303 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received invalid response", 299 // m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received no region",
304 scopeID, x, y); 300 // scopeID, x, y);
305 } 301 }
306 else 302 else
307 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received null response", 303 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionByPosition {0}, {1}-{2} received null response",
@@ -313,7 +309,7 @@ namespace OpenSim.Services.Connectors
313 return rinfo; 309 return rinfo;
314 } 310 }
315 311
316 public virtual GridRegion GetRegionByName(UUID scopeID, string regionName) 312 public GridRegion GetRegionByName(UUID scopeID, string regionName)
317 { 313 {
318 Dictionary<string, object> sendData = new Dictionary<string, object>(); 314 Dictionary<string, object> sendData = new Dictionary<string, object>();
319 315
@@ -354,7 +350,7 @@ namespace OpenSim.Services.Connectors
354 return rinfo; 350 return rinfo;
355 } 351 }
356 352
357 public virtual List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber) 353 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
358 { 354 {
359 Dictionary<string, object> sendData = new Dictionary<string, object>(); 355 Dictionary<string, object> sendData = new Dictionary<string, object>();
360 356
@@ -391,9 +387,6 @@ namespace OpenSim.Services.Connectors
391 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r); 387 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
392 rinfos.Add(rinfo); 388 rinfos.Add(rinfo);
393 } 389 }
394 else
395 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionsByName {0}, {1}, {2} received invalid response",
396 scopeID, name, maxNumber);
397 } 390 }
398 } 391 }
399 else 392 else
@@ -406,7 +399,7 @@ namespace OpenSim.Services.Connectors
406 return rinfos; 399 return rinfos;
407 } 400 }
408 401
409 public virtual List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax) 402 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
410 { 403 {
411 Dictionary<string, object> sendData = new Dictionary<string, object>(); 404 Dictionary<string, object> sendData = new Dictionary<string, object>();
412 405
@@ -460,6 +453,203 @@ namespace OpenSim.Services.Connectors
460 return rinfos; 453 return rinfos;
461 } 454 }
462 455
456 public List<GridRegion> GetDefaultRegions(UUID scopeID)
457 {
458 Dictionary<string, object> sendData = new Dictionary<string, object>();
459
460 sendData["SCOPEID"] = scopeID.ToString();
461
462 sendData["METHOD"] = "get_default_regions";
463
464 List<GridRegion> rinfos = new List<GridRegion>();
465 string reply = string.Empty;
466 try
467 {
468 reply = SynchronousRestFormsRequester.MakeRequest("POST",
469 m_ServerURI + "/grid",
470 ServerUtils.BuildQueryString(sendData));
471
472 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
473 }
474 catch (Exception e)
475 {
476 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server: {0}", e.Message);
477 return rinfos;
478 }
479
480 if (reply != string.Empty)
481 {
482 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
483
484 if (replyData != null)
485 {
486 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
487 foreach (object r in rinfosList)
488 {
489 if (r is Dictionary<string, object>)
490 {
491 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
492 rinfos.Add(rinfo);
493 }
494 }
495 }
496 else
497 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultRegions {0} received null response",
498 scopeID);
499 }
500 else
501 m_log.DebugFormat("[GRID CONNECTOR]: GetDefaultRegions received null reply");
502
503 return rinfos;
504 }
505
506 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
507 {
508 Dictionary<string, object> sendData = new Dictionary<string, object>();
509
510 sendData["SCOPEID"] = scopeID.ToString();
511 sendData["X"] = x.ToString();
512 sendData["Y"] = y.ToString();
513
514 sendData["METHOD"] = "get_fallback_regions";
515
516 List<GridRegion> rinfos = new List<GridRegion>();
517 string reply = string.Empty;
518 try
519 {
520 reply = SynchronousRestFormsRequester.MakeRequest("POST",
521 m_ServerURI + "/grid",
522 ServerUtils.BuildQueryString(sendData));
523
524 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
525 }
526 catch (Exception e)
527 {
528 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server: {0}", e.Message);
529 return rinfos;
530 }
531
532 if (reply != string.Empty)
533 {
534 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
535
536 if (replyData != null)
537 {
538 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
539 foreach (object r in rinfosList)
540 {
541 if (r is Dictionary<string, object>)
542 {
543 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
544 rinfos.Add(rinfo);
545 }
546 }
547 }
548 else
549 m_log.DebugFormat("[GRID CONNECTOR]: GetFallbackRegions {0}, {1}-{2} received null response",
550 scopeID, x, y);
551 }
552 else
553 m_log.DebugFormat("[GRID CONNECTOR]: GetFallbackRegions received null reply");
554
555 return rinfos;
556 }
557
558 public List<GridRegion> GetHyperlinks(UUID scopeID)
559 {
560 Dictionary<string, object> sendData = new Dictionary<string, object>();
561
562 sendData["SCOPEID"] = scopeID.ToString();
563
564 sendData["METHOD"] = "get_hyperlinks";
565
566 List<GridRegion> rinfos = new List<GridRegion>();
567 string reply = string.Empty;
568 try
569 {
570 reply = SynchronousRestFormsRequester.MakeRequest("POST",
571 m_ServerURI + "/grid",
572 ServerUtils.BuildQueryString(sendData));
573
574 //m_log.DebugFormat("[GRID CONNECTOR]: reply was {0}", reply);
575 }
576 catch (Exception e)
577 {
578 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server: {0}", e.Message);
579 return rinfos;
580 }
581
582 if (reply != string.Empty)
583 {
584 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
585
586 if (replyData != null)
587 {
588 Dictionary<string, object>.ValueCollection rinfosList = replyData.Values;
589 foreach (object r in rinfosList)
590 {
591 if (r is Dictionary<string, object>)
592 {
593 GridRegion rinfo = new GridRegion((Dictionary<string, object>)r);
594 rinfos.Add(rinfo);
595 }
596 }
597 }
598 else
599 m_log.DebugFormat("[GRID CONNECTOR]: GetHyperlinks {0} received null response",
600 scopeID);
601 }
602 else
603 m_log.DebugFormat("[GRID CONNECTOR]: GetHyperlinks received null reply");
604
605 return rinfos;
606 }
607
608 public int GetRegionFlags(UUID scopeID, UUID regionID)
609 {
610 Dictionary<string, object> sendData = new Dictionary<string, object>();
611
612 sendData["SCOPEID"] = scopeID.ToString();
613 sendData["REGIONID"] = regionID.ToString();
614
615 sendData["METHOD"] = "get_region_flags";
616
617 string reply = string.Empty;
618 try
619 {
620 reply = SynchronousRestFormsRequester.MakeRequest("POST",
621 m_ServerURI + "/grid",
622 ServerUtils.BuildQueryString(sendData));
623 }
624 catch (Exception e)
625 {
626 m_log.DebugFormat("[GRID CONNECTOR]: Exception when contacting grid server: {0}", e.Message);
627 return -1;
628 }
629
630 int flags = -1;
631
632 if (reply != string.Empty)
633 {
634 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
635
636 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
637 {
638 Int32.TryParse((string)replyData["result"], out flags);
639 //else
640 // m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags {0}, {1} received wrong type {2}",
641 // scopeID, regionID, replyData["result"].GetType());
642 }
643 else
644 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags {0}, {1} received null response",
645 scopeID, regionID);
646 }
647 else
648 m_log.DebugFormat("[GRID CONNECTOR]: GetRegionFlags received null reply");
649
650 return flags;
651 }
652
463 #endregion 653 #endregion
464 654
465 } 655 }
diff --git a/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs b/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs
deleted file mode 100644
index 7098b07..0000000
--- a/OpenSim/Services/Connectors/Grid/HypergridServiceConnector.cs
+++ /dev/null
@@ -1,254 +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 System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using System.Drawing;
33using System.Net;
34using System.Reflection;
35using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37
38using OpenSim.Framework;
39
40using OpenMetaverse;
41using OpenMetaverse.Imaging;
42using log4net;
43using Nwc.XmlRpc;
44
45namespace OpenSim.Services.Connectors.Grid
46{
47 public class HypergridServiceConnector
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private IAssetService m_AssetService;
52
53 public HypergridServiceConnector(IAssetService assService)
54 {
55 m_AssetService = assService;
56 }
57
58 public UUID LinkRegion(GridRegion info, out ulong realHandle)
59 {
60 UUID uuid = UUID.Zero;
61 realHandle = 0;
62
63 Hashtable hash = new Hashtable();
64 hash["region_name"] = info.RegionName;
65
66 IList paramList = new ArrayList();
67 paramList.Add(hash);
68
69 XmlRpcRequest request = new XmlRpcRequest("link_region", paramList);
70 string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/";
71 m_log.Debug("[HGrid]: Linking to " + uri);
72 XmlRpcResponse response = null;
73 try
74 {
75 response = request.Send(uri, 10000);
76 }
77 catch (Exception e)
78 {
79 m_log.Debug("[HGrid]: Exception " + e.Message);
80 return uuid;
81 }
82
83 if (response.IsFault)
84 {
85 m_log.ErrorFormat("[HGrid]: remote call returned an error: {0}", response.FaultString);
86 }
87 else
88 {
89 hash = (Hashtable)response.Value;
90 //foreach (Object o in hash)
91 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
92 try
93 {
94 UUID.TryParse((string)hash["uuid"], out uuid);
95 //m_log.Debug(">> HERE, uuid: " + uuid);
96 info.RegionID = uuid;
97 if ((string)hash["handle"] != null)
98 {
99 realHandle = Convert.ToUInt64((string)hash["handle"]);
100 //m_log.Debug(">> HERE, realHandle: " + realHandle);
101 }
102 //if (hash["region_image"] != null)
103 //{
104 // UUID img = UUID.Zero;
105 // UUID.TryParse((string)hash["region_image"], out img);
106 // info.RegionSettings.TerrainImageID = img;
107 //}
108 if (hash["region_name"] != null)
109 {
110 info.RegionName = (string)hash["region_name"];
111 //m_log.Debug(">> " + info.RegionName);
112 }
113 if (hash["internal_port"] != null)
114 {
115 int port = Convert.ToInt32((string)hash["internal_port"]);
116 info.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), port);
117 //m_log.Debug(">> " + info.InternalEndPoint.ToString());
118 }
119
120 }
121 catch (Exception e)
122 {
123 m_log.Error("[HGrid]: Got exception while parsing hyperlink response " + e.StackTrace);
124 }
125 }
126 return uuid;
127 }
128
129 public void GetMapImage(GridRegion info)
130 {
131 try
132 {
133 string regionimage = "regionImage" + info.RegionID.ToString();
134 regionimage = regionimage.Replace("-", "");
135
136 WebClient c = new WebClient();
137 string uri = "http://" + info.ExternalHostName + ":" + info.HttpPort + "/index.php?method=" + regionimage;
138 //m_log.Debug("JPEG: " + uri);
139 c.DownloadFile(uri, info.RegionID.ToString() + ".jpg");
140 Bitmap m = new Bitmap(info.RegionID.ToString() + ".jpg");
141 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
142 byte[] imageData = OpenJPEG.EncodeFromImage(m, true);
143 AssetBase ass = new AssetBase(UUID.Random(), "region " + info.RegionID.ToString(), (sbyte)AssetType.Texture);
144
145 // !!! for now
146 //info.RegionSettings.TerrainImageID = ass.FullID;
147
148 ass.Temporary = true;
149 ass.Local = true;
150 ass.Data = imageData;
151
152 m_AssetService.Store(ass);
153
154 // finally
155 info.TerrainImage = ass.FullID;
156
157 }
158 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
159 {
160 m_log.Warn("[HGrid]: Failed getting/storing map image, because it is probably already in the cache");
161 }
162 }
163
164 public bool InformRegionOfUser(GridRegion regInfo, AgentCircuitData agentData, GridRegion home, string userServer, string assetServer, string inventoryServer)
165 {
166 string capsPath = agentData.CapsPath;
167 Hashtable loginParams = new Hashtable();
168 loginParams["session_id"] = agentData.SessionID.ToString();
169
170 loginParams["firstname"] = agentData.firstname;
171 loginParams["lastname"] = agentData.lastname;
172
173 loginParams["agent_id"] = agentData.AgentID.ToString();
174 loginParams["circuit_code"] = agentData.circuitcode.ToString();
175 loginParams["startpos_x"] = agentData.startpos.X.ToString();
176 loginParams["startpos_y"] = agentData.startpos.Y.ToString();
177 loginParams["startpos_z"] = agentData.startpos.Z.ToString();
178 loginParams["caps_path"] = capsPath;
179
180 if (home != null)
181 {
182 loginParams["region_uuid"] = home.RegionID.ToString();
183 loginParams["regionhandle"] = home.RegionHandle.ToString();
184 loginParams["home_address"] = home.ExternalHostName;
185 loginParams["home_port"] = home.HttpPort.ToString();
186 loginParams["internal_port"] = home.InternalEndPoint.Port.ToString();
187
188 m_log.Debug(" --------- Home -------");
189 m_log.Debug(" >> " + loginParams["home_address"] + " <<");
190 m_log.Debug(" >> " + loginParams["region_uuid"] + " <<");
191 m_log.Debug(" >> " + loginParams["regionhandle"] + " <<");
192 m_log.Debug(" >> " + loginParams["home_port"] + " <<");
193 m_log.Debug(" --------- ------------ -------");
194 }
195 else
196 m_log.WarnFormat("[HGrid]: Home region not found for {0} {1}", agentData.firstname, agentData.lastname);
197
198 loginParams["userserver_id"] = userServer;
199 loginParams["assetserver_id"] = assetServer;
200 loginParams["inventoryserver_id"] = inventoryServer;
201
202
203 ArrayList SendParams = new ArrayList();
204 SendParams.Add(loginParams);
205
206 // Send
207 string uri = "http://" + regInfo.ExternalHostName + ":" + regInfo.HttpPort + "/";
208 //m_log.Debug("XXX uri: " + uri);
209 XmlRpcRequest request = new XmlRpcRequest("expect_hg_user", SendParams);
210 XmlRpcResponse reply;
211 try
212 {
213 reply = request.Send(uri, 6000);
214 }
215 catch (Exception e)
216 {
217 m_log.Warn("[HGrid]: Failed to notify region about user. Reason: " + e.Message);
218 return false;
219 }
220
221 if (!reply.IsFault)
222 {
223 bool responseSuccess = true;
224 if (reply.Value != null)
225 {
226 Hashtable resp = (Hashtable)reply.Value;
227 if (resp.ContainsKey("success"))
228 {
229 if ((string)resp["success"] == "FALSE")
230 {
231 responseSuccess = false;
232 }
233 }
234 }
235 if (responseSuccess)
236 {
237 m_log.Info("[HGrid]: Successfully informed remote region about user " + agentData.AgentID);
238 return true;
239 }
240 else
241 {
242 m_log.ErrorFormat("[HGrid]: Region responded that it is not available to receive clients");
243 return false;
244 }
245 }
246 else
247 {
248 m_log.ErrorFormat("[HGrid]: XmlRpc request to region failed with message {0}, code {1} ", reply.FaultString, reply.FaultCode);
249 return false;
250 }
251 }
252
253 }
254}
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
new file mode 100644
index 0000000..738cc06
--- /dev/null
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs
@@ -0,0 +1,227 @@
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.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors
42{
43 public class GridUserServicesConnector : IGridUserService
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 GridUserServicesConnector()
52 {
53 }
54
55 public GridUserServicesConnector(string serverURI)
56 {
57 m_ServerURI = serverURI.TrimEnd('/');
58 }
59
60 public GridUserServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig gridConfig = source.Configs["GridUserService"];
68 if (gridConfig == null)
69 {
70 m_log.Error("[GRID USER CONNECTOR]: GridUserService missing from OpenSim.ini");
71 throw new Exception("GridUser connector init error");
72 }
73
74 string serviceURI = gridConfig.GetString("GridUserServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[GRID USER CONNECTOR]: No Server URI named in section GridUserService");
80 throw new Exception("GridUser connector init error");
81 }
82 m_ServerURI = serviceURI;
83 }
84
85
86 #region IGridUserService
87
88
89 public GridUserInfo LoggedIn(string userID)
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"] = "loggedin";
96
97 sendData["UserID"] = userID;
98
99 return Get(sendData);
100
101 }
102
103 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
104 {
105 Dictionary<string, object> sendData = new Dictionary<string, object>();
106 //sendData["SCOPEID"] = scopeID.ToString();
107 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
108 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
109 sendData["METHOD"] = "loggedout";
110
111 return Set(sendData, userID, region, position, lookat);
112 }
113
114 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
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"] = "sethome";
121
122 return Set(sendData, userID, regionID, position, lookAt);
123 }
124
125 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
126 {
127 Dictionary<string, object> sendData = new Dictionary<string, object>();
128 //sendData["SCOPEID"] = scopeID.ToString();
129 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
130 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
131 sendData["METHOD"] = "setposition";
132
133 return Set(sendData, userID, regionID, position, lookAt);
134 }
135
136 public GridUserInfo GetGridUserInfo(string userID)
137 {
138 Dictionary<string, object> sendData = new Dictionary<string, object>();
139 //sendData["SCOPEID"] = scopeID.ToString();
140 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
141 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
142 sendData["METHOD"] = "getgriduserinfo";
143
144 sendData["UserID"] = userID;
145
146 return Get(sendData);
147 }
148
149 #endregion
150
151 protected bool Set(Dictionary<string, object> sendData, string userID, UUID regionID, Vector3 position, Vector3 lookAt)
152 {
153 sendData["UserID"] = userID;
154 sendData["RegionID"] = regionID.ToString();
155 sendData["Position"] = position.ToString();
156 sendData["LookAt"] = lookAt.ToString();
157
158 string reqString = ServerUtils.BuildQueryString(sendData);
159 // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString);
160 try
161 {
162 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
163 m_ServerURI + "/griduser",
164 reqString);
165 if (reply != string.Empty)
166 {
167 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
168
169 if (replyData.ContainsKey("result"))
170 {
171 if (replyData["result"].ToString().ToLower() == "success")
172 return true;
173 else
174 return false;
175 }
176 else
177 m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition reply data does not contain result field");
178
179 }
180 else
181 m_log.DebugFormat("[GRID USER CONNECTOR]: SetPosition received empty reply");
182 }
183 catch (Exception e)
184 {
185 m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server: {0}", e.Message);
186 }
187
188 return false;
189 }
190
191 protected GridUserInfo Get(Dictionary<string, object> sendData)
192 {
193 string reqString = ServerUtils.BuildQueryString(sendData);
194 // m_log.DebugFormat("[GRID USER CONNECTOR]: queryString = {0}", reqString);
195 try
196 {
197 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
198 m_ServerURI + "/griduser",
199 reqString);
200 if (reply != string.Empty)
201 {
202 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
203 GridUserInfo guinfo = null;
204
205 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
206 {
207 if (replyData["result"] is Dictionary<string, object>)
208 guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]);
209 }
210
211 return guinfo;
212
213 }
214 else
215 m_log.DebugFormat("[GRID USER CONNECTOR]: Loggedin received empty reply");
216 }
217 catch (Exception e)
218 {
219 m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server: {0}", e.Message);
220 }
221
222 return null;
223
224 }
225
226 }
227}
diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
new file mode 100644
index 0000000..bc0bc54
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs
@@ -0,0 +1,334 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Drawing;
32using System.IO;
33using System.Net;
34using System.Reflection;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using OpenMetaverse;
39using OpenMetaverse.Imaging;
40using OpenMetaverse.StructuredData;
41using Nwc.XmlRpc;
42using log4net;
43
44using OpenSim.Services.Connectors.Simulation;
45
46namespace OpenSim.Services.Connectors.Hypergrid
47{
48 public class GatekeeperServiceConnector : SimulationServiceConnector
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private static UUID m_HGMapImage = new UUID("00000000-0000-1111-9999-000000000013");
53
54 private IAssetService m_AssetService;
55
56 public GatekeeperServiceConnector() : base()
57 {
58 }
59
60 public GatekeeperServiceConnector(IAssetService assService)
61 {
62 m_AssetService = assService;
63 }
64
65 protected override string AgentPath()
66 {
67 return "foreignagent/";
68 }
69
70 protected override string ObjectPath()
71 {
72 return "foreignobject/";
73 }
74
75 public bool LinkRegion(GridRegion info, out UUID regionID, out ulong realHandle, out string externalName, out string imageURL, out string reason)
76 {
77 regionID = UUID.Zero;
78 imageURL = string.Empty;
79 realHandle = 0;
80 externalName = string.Empty;
81 reason = string.Empty;
82
83 Hashtable hash = new Hashtable();
84 hash["region_name"] = info.RegionName;
85
86 IList paramList = new ArrayList();
87 paramList.Add(hash);
88
89 XmlRpcRequest request = new XmlRpcRequest("link_region", paramList);
90 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + info.ServerURI);
91 XmlRpcResponse response = null;
92 try
93 {
94 response = request.Send(info.ServerURI, 10000);
95 }
96 catch (Exception e)
97 {
98 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message);
99 reason = "Error contacting remote server";
100 return false;
101 }
102
103 if (response.IsFault)
104 {
105 reason = response.FaultString;
106 m_log.ErrorFormat("[GATEKEEPER SERVICE CONNECTOR]: remote call returned an error: {0}", response.FaultString);
107 return false;
108 }
109
110 hash = (Hashtable)response.Value;
111 //foreach (Object o in hash)
112 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
113 try
114 {
115 bool success = false;
116 Boolean.TryParse((string)hash["result"], out success);
117 if (success)
118 {
119 UUID.TryParse((string)hash["uuid"], out regionID);
120 //m_log.Debug(">> HERE, uuid: " + regionID);
121 if ((string)hash["handle"] != null)
122 {
123 realHandle = Convert.ToUInt64((string)hash["handle"]);
124 //m_log.Debug(">> HERE, realHandle: " + realHandle);
125 }
126 if (hash["region_image"] != null) {
127 imageURL = (string)hash["region_image"];
128 //m_log.Debug(">> HERE, imageURL: " + imageURL);
129 }
130 if (hash["external_name"] != null) {
131 externalName = (string)hash["external_name"];
132 //m_log.Debug(">> HERE, externalName: " + externalName);
133 }
134 }
135
136 }
137 catch (Exception e)
138 {
139 reason = "Error parsing return arguments";
140 m_log.Error("[GATEKEEPER SERVICE CONNECTOR]: Got exception while parsing hyperlink response " + e.StackTrace);
141 return false;
142 }
143
144 return true;
145 }
146
147 public UUID GetMapImage(UUID regionID, string imageURL, string storagePath)
148 {
149 if (m_AssetService == null)
150 {
151 m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: No AssetService defined. Map tile not retrieved.");
152 return m_HGMapImage;
153 }
154
155 UUID mapTile = m_HGMapImage;
156 string filename = string.Empty;
157 Bitmap bitmap = null;
158 try
159 {
160 WebClient c = new WebClient();
161 //m_log.Debug("JPEG: " + imageURL);
162 string name = regionID.ToString();
163 filename = Path.Combine(storagePath, name + ".jpg");
164 c.DownloadFile(imageURL, filename);
165 bitmap = new Bitmap(filename);
166 //m_log.Debug("Size: " + m.PhysicalDimension.Height + "-" + m.PhysicalDimension.Width);
167 byte[] imageData = OpenJPEG.EncodeFromImage(bitmap, true);
168 AssetBase ass = new AssetBase(UUID.Random(), "region " + name, (sbyte)AssetType.Texture, regionID.ToString());
169
170 // !!! for now
171 //info.RegionSettings.TerrainImageID = ass.FullID;
172
173 ass.Data = imageData;
174
175 m_AssetService.Store(ass);
176
177 // finally
178 mapTile = ass.FullID;
179 }
180 catch // LEGIT: Catching problems caused by OpenJPEG p/invoke
181 {
182 m_log.Info("[GATEKEEPER SERVICE CONNECTOR]: Failed getting/storing map image, because it is probably already in the cache");
183 }
184 return mapTile;
185 }
186
187 public GridRegion GetHyperlinkRegion(GridRegion gatekeeper, UUID regionID)
188 {
189 Hashtable hash = new Hashtable();
190 hash["region_uuid"] = regionID.ToString();
191
192 IList paramList = new ArrayList();
193 paramList.Add(hash);
194
195 XmlRpcRequest request = new XmlRpcRequest("get_region", paramList);
196 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + gatekeeper.ServerURI);
197 XmlRpcResponse response = null;
198 try
199 {
200 response = request.Send(gatekeeper.ServerURI, 10000);
201 }
202 catch (Exception e)
203 {
204 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Exception " + e.Message);
205 return null;
206 }
207
208 if (response.IsFault)
209 {
210 m_log.ErrorFormat("[GATEKEEPER SERVICE CONNECTOR]: remote call returned an error: {0}", response.FaultString);
211 return null;
212 }
213
214 hash = (Hashtable)response.Value;
215 //foreach (Object o in hash)
216 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
217 try
218 {
219 bool success = false;
220 Boolean.TryParse((string)hash["result"], out success);
221 if (success)
222 {
223 GridRegion region = new GridRegion();
224
225 UUID.TryParse((string)hash["uuid"], out region.RegionID);
226 //m_log.Debug(">> HERE, uuid: " + region.RegionID);
227 int n = 0;
228 if (hash["x"] != null)
229 {
230 Int32.TryParse((string)hash["x"], out n);
231 region.RegionLocX = n;
232 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
233 }
234 if (hash["y"] != null)
235 {
236 Int32.TryParse((string)hash["y"], out n);
237 region.RegionLocY = n;
238 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
239 }
240 if (hash["region_name"] != null)
241 {
242 region.RegionName = (string)hash["region_name"];
243 //m_log.Debug(">> HERE, region_name: " + region.RegionName);
244 }
245 if (hash["hostname"] != null) {
246 region.ExternalHostName = (string)hash["hostname"];
247 //m_log.Debug(">> HERE, hostname: " + region.ExternalHostName);
248 }
249 if (hash["http_port"] != null)
250 {
251 uint p = 0;
252 UInt32.TryParse((string)hash["http_port"], out p);
253 region.HttpPort = p;
254 //m_log.Debug(">> HERE, http_port: " + region.HttpPort);
255 }
256 if (hash["internal_port"] != null)
257 {
258 int p = 0;
259 Int32.TryParse((string)hash["internal_port"], out p);
260 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
261 //m_log.Debug(">> HERE, internal_port: " + region.InternalEndPoint);
262 }
263
264 if (hash["server_uri"] != null)
265 {
266 region.ServerURI = (string) hash["server_uri"];
267 //m_log.Debug(">> HERE, server_uri: " + region.ServerURI);
268 }
269
270 // Successful return
271 return region;
272 }
273
274 }
275 catch (Exception e)
276 {
277 m_log.Error("[GATEKEEPER SERVICE CONNECTOR]: Got exception while parsing hyperlink response " + e.StackTrace);
278 return null;
279 }
280
281 return null;
282 }
283
284 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string myipaddress, out string reason)
285 {
286 // m_log.DebugFormat("[GATEKEEPER SERVICE CONNECTOR]: CreateAgent start");
287
288 myipaddress = String.Empty;
289 reason = String.Empty;
290
291 if (destination == null)
292 {
293 m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Given destination is null");
294 return false;
295 }
296
297 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
298
299 try
300 {
301 OSDMap args = aCircuit.PackAgentCircuitData();
302
303 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
304 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
305 args["destination_name"] = OSD.FromString(destination.RegionName);
306 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
307 args["teleport_flags"] = OSD.FromString(flags.ToString());
308
309 OSDMap result = WebUtil.PostToService(uri, args, 20000);
310 if (result["Success"].AsBoolean())
311 {
312 OSDMap unpacked = (OSDMap)result["_Result"];
313
314 if (unpacked != null)
315 {
316 reason = unpacked["reason"].AsString();
317 myipaddress = unpacked["your_ip"].AsString();
318 return unpacked["success"].AsBoolean();
319 }
320 }
321
322 reason = result["Message"] != null ? result["Message"].AsString() : "error";
323 return false;
324 }
325 catch (Exception e)
326 {
327 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
328 reason = e.Message;
329 }
330
331 return false;
332 }
333 }
334}
diff --git a/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs
new file mode 100644
index 0000000..d699f59
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/HGFriendsServiceConnector.cs
@@ -0,0 +1,206 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using log4net;
29using System;
30using System.Collections.Generic;
31using System.IO;
32using System.Reflection;
33using Nini.Config;
34using OpenSim.Framework;
35using OpenSim.Services.Interfaces;
36using OpenSim.Services.Connectors.Friends;
37using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors.Hypergrid
42{
43 public class HGFriendsServicesConnector
44 {
45 private static readonly ILog m_log =
46 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType);
48
49 private string m_ServerURI = String.Empty;
50 private string m_ServiceKey = String.Empty;
51 private UUID m_SessionID;
52
53 public HGFriendsServicesConnector()
54 {
55 }
56
57 public HGFriendsServicesConnector(string serverURI)
58 {
59 m_ServerURI = serverURI.TrimEnd('/');
60 }
61
62 public HGFriendsServicesConnector(string serverURI, UUID sessionID, string serviceKey)
63 {
64 m_ServerURI = serverURI.TrimEnd('/');
65 m_ServiceKey = serviceKey;
66 m_SessionID = sessionID;
67 }
68
69 #region IFriendsService
70
71 public uint GetFriendPerms(UUID PrincipalID, UUID friendID)
72 {
73 Dictionary<string, object> sendData = new Dictionary<string, object>();
74
75 sendData["PRINCIPALID"] = PrincipalID.ToString();
76 sendData["FRIENDID"] = friendID.ToString();
77 sendData["METHOD"] = "getfriendperms";
78 sendData["KEY"] = m_ServiceKey;
79 sendData["SESSIONID"] = m_SessionID.ToString();
80
81 string reqString = ServerUtils.BuildQueryString(sendData);
82
83 try
84 {
85 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
86 m_ServerURI + "/hgfriends",
87 reqString);
88 if (reply != string.Empty)
89 {
90 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
91
92 if ((replyData != null) && replyData.ContainsKey("Value") && (replyData["Value"] != null))
93 {
94 uint perms = 0;
95 uint.TryParse(replyData["Value"].ToString(), out perms);
96 return perms;
97 }
98 else
99 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: GetFriendPerms {0} received null response",
100 PrincipalID);
101
102 }
103 }
104 catch (Exception e)
105 {
106 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
107 }
108
109 return 0;
110
111 }
112
113 public bool NewFriendship(UUID PrincipalID, string Friend)
114 {
115 FriendInfo finfo = new FriendInfo();
116 finfo.PrincipalID = PrincipalID;
117 finfo.Friend = Friend;
118
119 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
120
121 sendData["METHOD"] = "newfriendship";
122 sendData["KEY"] = m_ServiceKey;
123 sendData["SESSIONID"] = m_SessionID.ToString();
124
125 string reply = string.Empty;
126 try
127 {
128 reply = SynchronousRestFormsRequester.MakeRequest("POST",
129 m_ServerURI + "/hgfriends",
130 ServerUtils.BuildQueryString(sendData));
131 }
132 catch (Exception e)
133 {
134 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
135 return false;
136 }
137
138 if (reply != string.Empty)
139 {
140 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
141
142 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
143 {
144 bool success = false;
145 Boolean.TryParse(replyData["Result"].ToString(), out success);
146 return success;
147 }
148 else
149 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend {0} {1} received null response",
150 PrincipalID, Friend);
151 }
152 else
153 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: StoreFriend received null reply");
154
155 return false;
156
157 }
158
159 public bool DeleteFriendship(UUID PrincipalID, UUID Friend, string secret)
160 {
161 FriendInfo finfo = new FriendInfo();
162 finfo.PrincipalID = PrincipalID;
163 finfo.Friend = Friend.ToString();
164
165 Dictionary<string, object> sendData = finfo.ToKeyValuePairs();
166
167 sendData["METHOD"] = "deletefriendship";
168 sendData["SECRET"] = secret;
169
170 string reply = string.Empty;
171 try
172 {
173 reply = SynchronousRestFormsRequester.MakeRequest("POST",
174 m_ServerURI + "/hgfriends",
175 ServerUtils.BuildQueryString(sendData));
176 }
177 catch (Exception e)
178 {
179 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Exception when contacting friends server: {0}", e.Message);
180 return false;
181 }
182
183 if (reply != string.Empty)
184 {
185 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
186
187 if ((replyData != null) && replyData.ContainsKey("Result") && (replyData["Result"] != null))
188 {
189 bool success = false;
190 Boolean.TryParse(replyData["Result"].ToString(), out success);
191 return success;
192 }
193 else
194 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: Delete {0} {1} received null response",
195 PrincipalID, Friend);
196 }
197 else
198 m_log.DebugFormat("[HGFRIENDS CONNECTOR]: DeleteFriend received null reply");
199
200 return false;
201
202 }
203
204 #endregion
205 }
206} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs
new file mode 100644
index 0000000..7cfd6e8
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs
@@ -0,0 +1,77 @@
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.Net;
31using System.Reflection;
32using Nini.Config;
33
34namespace OpenSim.Services.Connectors
35{
36 public class HeloServicesConnector
37 {
38 private static readonly ILog m_log =
39 LogManager.GetLogger(
40 MethodBase.GetCurrentMethod().DeclaringType);
41
42 private string m_ServerURI = String.Empty;
43
44 public HeloServicesConnector()
45 {
46 }
47
48 public HeloServicesConnector(string serverURI)
49 {
50 m_ServerURI = serverURI.TrimEnd('/');
51 }
52
53
54 public virtual string Helo()
55 {
56 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI + "/helo");
57 // Eventually we need to switch to HEAD
58 /* req.Method = "HEAD"; */
59
60 try
61 {
62 WebResponse response = req.GetResponse();
63 if (response.Headers.Get("X-Handlers-Provided") == null) // just in case this ever returns a null
64 return string.Empty;
65 return response.Headers.Get("X-Handlers-Provided");
66 }
67 catch (Exception e)
68 {
69 m_log.DebugFormat("[HELO SERVICE]: Unable to perform HELO request to {0}: {1}", m_ServerURI, e.Message);
70 }
71
72 // fail
73 return string.Empty;
74 }
75
76 }
77}
diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
new file mode 100644
index 0000000..a59b9ee
--- /dev/null
+++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs
@@ -0,0 +1,796 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34using System.Text;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.Simulation;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using log4net;
42using Nwc.XmlRpc;
43using Nini.Config;
44
45namespace OpenSim.Services.Connectors.Hypergrid
46{
47 public class UserAgentServiceConnector : IUserAgentService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 string m_ServerURL;
54
55 public UserAgentServiceConnector(string url) : this(url, true)
56 {
57 }
58
59 public UserAgentServiceConnector(string url, bool dnsLookup)
60 {
61 m_ServerURL = url;
62
63 if (dnsLookup)
64 {
65 // Doing this here, because XML-RPC or mono have some strong ideas about
66 // caching DNS translations.
67 try
68 {
69 Uri m_Uri = new Uri(m_ServerURL);
70 IPAddress ip = Util.GetHostFromDNS(m_Uri.Host);
71 m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString());
72 if (!m_ServerURL.EndsWith("/"))
73 m_ServerURL += "/";
74 }
75 catch (Exception e)
76 {
77 m_log.DebugFormat("[USER AGENT CONNECTOR]: Malformed Uri {0}: {1}", m_ServerURL, e.Message);
78 }
79 }
80 m_log.DebugFormat("[USER AGENT CONNECTOR]: new connector to {0} ({1})", url, m_ServerURL);
81 }
82
83 public UserAgentServiceConnector(IConfigSource config)
84 {
85 IConfig serviceConfig = config.Configs["UserAgentService"];
86 if (serviceConfig == null)
87 {
88 m_log.Error("[USER AGENT CONNECTOR]: UserAgentService missing from ini");
89 throw new Exception("UserAgent connector init error");
90 }
91
92 string serviceURI = serviceConfig.GetString("UserAgentServerURI",
93 String.Empty);
94
95 if (serviceURI == String.Empty)
96 {
97 m_log.Error("[USER AGENT CONNECTOR]: No Server URI named in section UserAgentService");
98 throw new Exception("UserAgent connector init error");
99 }
100 m_ServerURL = serviceURI;
101
102 m_log.DebugFormat("[USER AGENT CONNECTOR]: UserAgentServiceConnector started for {0}", m_ServerURL);
103 }
104
105
106 // The Login service calls this interface with a non-null [client] ipaddress
107 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress, out string reason)
108 {
109 reason = String.Empty;
110
111 if (destination == null)
112 {
113 reason = "Destination is null";
114 m_log.Debug("[USER AGENT CONNECTOR]: Given destination is null");
115 return false;
116 }
117
118 string uri = m_ServerURL + "homeagent/" + aCircuit.AgentID + "/";
119
120 Console.WriteLine(" >>> LoginAgentToGrid <<< " + uri);
121
122 HttpWebRequest AgentCreateRequest = (HttpWebRequest)WebRequest.Create(uri);
123 AgentCreateRequest.Method = "POST";
124 AgentCreateRequest.ContentType = "application/json";
125 AgentCreateRequest.Timeout = 10000;
126 //AgentCreateRequest.KeepAlive = false;
127 //AgentCreateRequest.Headers.Add("Authorization", authKey);
128
129 // Fill it in
130 OSDMap args = PackCreateAgentArguments(aCircuit, gatekeeper, destination, ipaddress);
131
132 string strBuffer = "";
133 byte[] buffer = new byte[1];
134 try
135 {
136 strBuffer = OSDParser.SerializeJsonString(args);
137 Encoding str = Util.UTF8;
138 buffer = str.GetBytes(strBuffer);
139
140 }
141 catch (Exception e)
142 {
143 m_log.WarnFormat("[USER AGENT CONNECTOR]: Exception thrown on serialization of ChildCreate: {0}", e.Message);
144 // ignore. buffer will be empty, caller should check.
145 }
146
147 Stream os = null;
148 try
149 { // send the Post
150 AgentCreateRequest.ContentLength = buffer.Length; //Count bytes to send
151 os = AgentCreateRequest.GetRequestStream();
152 os.Write(buffer, 0, strBuffer.Length); //Send it
153 m_log.InfoFormat("[USER AGENT CONNECTOR]: Posted CreateAgent request to remote sim {0}, region {1}, x={2} y={3}",
154 uri, destination.RegionName, destination.RegionLocX, destination.RegionLocY);
155 }
156 //catch (WebException ex)
157 catch
158 {
159 //m_log.InfoFormat("[USER AGENT CONNECTOR]: Bad send on ChildAgentUpdate {0}", ex.Message);
160 reason = "cannot contact remote region";
161 return false;
162 }
163 finally
164 {
165 if (os != null)
166 os.Close();
167 }
168
169 // Let's wait for the response
170 //m_log.Info("[USER AGENT CONNECTOR]: Waiting for a reply after DoCreateChildAgentCall");
171
172 WebResponse webResponse = null;
173 StreamReader sr = null;
174 try
175 {
176 webResponse = AgentCreateRequest.GetResponse();
177 if (webResponse == null)
178 {
179 m_log.Info("[USER AGENT CONNECTOR]: Null reply on DoCreateChildAgentCall post");
180 }
181 else
182 {
183
184 sr = new StreamReader(webResponse.GetResponseStream());
185 string response = sr.ReadToEnd().Trim();
186 m_log.InfoFormat("[USER AGENT CONNECTOR]: DoCreateChildAgentCall reply was {0} ", response);
187
188 if (!String.IsNullOrEmpty(response))
189 {
190 try
191 {
192 // we assume we got an OSDMap back
193 OSDMap r = Util.GetOSDMap(response);
194 bool success = r["success"].AsBoolean();
195 reason = r["reason"].AsString();
196 return success;
197 }
198 catch (NullReferenceException e)
199 {
200 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", e.Message);
201
202 // check for old style response
203 if (response.ToLower().StartsWith("true"))
204 return true;
205
206 return false;
207 }
208 }
209 }
210 }
211 catch (WebException ex)
212 {
213 m_log.InfoFormat("[USER AGENT CONNECTOR]: exception on reply of DoCreateChildAgentCall {0}", ex.Message);
214 reason = "Destination did not reply";
215 return false;
216 }
217 finally
218 {
219 if (sr != null)
220 sr.Close();
221 }
222
223 return true;
224
225 }
226
227
228 // The simulators call this interface
229 public bool LoginAgentToGrid(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, out string reason)
230 {
231 return LoginAgentToGrid(aCircuit, gatekeeper, destination, null, out reason);
232 }
233
234 protected OSDMap PackCreateAgentArguments(AgentCircuitData aCircuit, GridRegion gatekeeper, GridRegion destination, IPEndPoint ipaddress)
235 {
236 OSDMap args = null;
237 try
238 {
239 args = aCircuit.PackAgentCircuitData();
240 }
241 catch (Exception e)
242 {
243 m_log.Debug("[USER AGENT CONNECTOR]: PackAgentCircuitData failed with exception: " + e.Message);
244 }
245
246 // Add the input arguments
247 args["gatekeeper_serveruri"] = OSD.FromString(gatekeeper.ServerURI);
248 args["gatekeeper_host"] = OSD.FromString(gatekeeper.ExternalHostName);
249 args["gatekeeper_port"] = OSD.FromString(gatekeeper.HttpPort.ToString());
250 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
251 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
252 args["destination_name"] = OSD.FromString(destination.RegionName);
253 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
254 args["destination_serveruri"] = OSD.FromString(destination.ServerURI);
255
256 // 10/3/2010
257 // I added the client_ip up to the regular AgentCircuitData, so this doesn't need to be here.
258 // This need cleaning elsewhere...
259 //if (ipaddress != null)
260 // args["client_ip"] = OSD.FromString(ipaddress.Address.ToString());
261
262 return args;
263 }
264
265 public void SetClientToken(UUID sessionID, string token)
266 {
267 // no-op
268 }
269
270 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
271 {
272 position = Vector3.UnitY; lookAt = Vector3.UnitY;
273
274 Hashtable hash = new Hashtable();
275 hash["userID"] = userID.ToString();
276
277 IList paramList = new ArrayList();
278 paramList.Add(hash);
279
280 XmlRpcRequest request = new XmlRpcRequest("get_home_region", paramList);
281 XmlRpcResponse response = null;
282 try
283 {
284 response = request.Send(m_ServerURL, 10000);
285 }
286 catch (Exception)
287 {
288 return null;
289 }
290
291 if (response.IsFault)
292 {
293 return null;
294 }
295
296 hash = (Hashtable)response.Value;
297 //foreach (Object o in hash)
298 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
299 try
300 {
301 bool success = false;
302 Boolean.TryParse((string)hash["result"], out success);
303 if (success)
304 {
305 GridRegion region = new GridRegion();
306
307 UUID.TryParse((string)hash["uuid"], out region.RegionID);
308 //m_log.Debug(">> HERE, uuid: " + region.RegionID);
309 int n = 0;
310 if (hash["x"] != null)
311 {
312 Int32.TryParse((string)hash["x"], out n);
313 region.RegionLocX = n;
314 //m_log.Debug(">> HERE, x: " + region.RegionLocX);
315 }
316 if (hash["y"] != null)
317 {
318 Int32.TryParse((string)hash["y"], out n);
319 region.RegionLocY = n;
320 //m_log.Debug(">> HERE, y: " + region.RegionLocY);
321 }
322 if (hash["region_name"] != null)
323 {
324 region.RegionName = (string)hash["region_name"];
325 //m_log.Debug(">> HERE, name: " + region.RegionName);
326 }
327 if (hash["hostname"] != null)
328 region.ExternalHostName = (string)hash["hostname"];
329 if (hash["http_port"] != null)
330 {
331 uint p = 0;
332 UInt32.TryParse((string)hash["http_port"], out p);
333 region.HttpPort = p;
334 }
335 if (hash["internal_port"] != null)
336 {
337 int p = 0;
338 Int32.TryParse((string)hash["internal_port"], out p);
339 region.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), p);
340 }
341 if (hash["position"] != null)
342 Vector3.TryParse((string)hash["position"], out position);
343 if (hash["lookAt"] != null)
344 Vector3.TryParse((string)hash["lookAt"], out lookAt);
345
346 // Successful return
347 return region;
348 }
349
350 }
351 catch (Exception)
352 {
353 return null;
354 }
355
356 return null;
357 }
358
359 public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
360 {
361 Hashtable hash = new Hashtable();
362 hash["sessionID"] = sessionID.ToString();
363 hash["externalName"] = thisGridExternalName;
364
365 IList paramList = new ArrayList();
366 paramList.Add(hash);
367
368 XmlRpcRequest request = new XmlRpcRequest("agent_is_coming_home", paramList);
369 string reason = string.Empty;
370 return GetBoolResponse(request, out reason);
371 }
372
373 public bool VerifyAgent(UUID sessionID, string token)
374 {
375 Hashtable hash = new Hashtable();
376 hash["sessionID"] = sessionID.ToString();
377 hash["token"] = token;
378
379 IList paramList = new ArrayList();
380 paramList.Add(hash);
381
382 XmlRpcRequest request = new XmlRpcRequest("verify_agent", paramList);
383 string reason = string.Empty;
384 return GetBoolResponse(request, out reason);
385 }
386
387 public bool VerifyClient(UUID sessionID, string token)
388 {
389 Hashtable hash = new Hashtable();
390 hash["sessionID"] = sessionID.ToString();
391 hash["token"] = token;
392
393 IList paramList = new ArrayList();
394 paramList.Add(hash);
395
396 XmlRpcRequest request = new XmlRpcRequest("verify_client", paramList);
397 string reason = string.Empty;
398 return GetBoolResponse(request, out reason);
399 }
400
401 public void LogoutAgent(UUID userID, UUID sessionID)
402 {
403 Hashtable hash = new Hashtable();
404 hash["sessionID"] = sessionID.ToString();
405 hash["userID"] = userID.ToString();
406
407 IList paramList = new ArrayList();
408 paramList.Add(hash);
409
410 XmlRpcRequest request = new XmlRpcRequest("logout_agent", paramList);
411 string reason = string.Empty;
412 GetBoolResponse(request, out reason);
413 }
414
415 public List<UUID> StatusNotification(List<string> friends, UUID userID, bool online)
416 {
417 Hashtable hash = new Hashtable();
418 hash["userID"] = userID.ToString();
419 hash["online"] = online.ToString();
420 int i = 0;
421 foreach (string s in friends)
422 {
423 hash["friend_" + i.ToString()] = s;
424 i++;
425 }
426
427 IList paramList = new ArrayList();
428 paramList.Add(hash);
429
430 XmlRpcRequest request = new XmlRpcRequest("status_notification", paramList);
431// string reason = string.Empty;
432
433 // Send and get reply
434 List<UUID> friendsOnline = new List<UUID>();
435 XmlRpcResponse response = null;
436 try
437 {
438 response = request.Send(m_ServerURL, 6000);
439 }
440 catch
441 {
442 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURL);
443// reason = "Exception: " + e.Message;
444 return friendsOnline;
445 }
446
447 if (response.IsFault)
448 {
449 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURL, response.FaultString);
450// reason = "XMLRPC Fault";
451 return friendsOnline;
452 }
453
454 hash = (Hashtable)response.Value;
455 //foreach (Object o in hash)
456 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
457 try
458 {
459 if (hash == null)
460 {
461 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
462// reason = "Internal error 1";
463 return friendsOnline;
464 }
465
466 // Here is the actual response
467 foreach (object key in hash.Keys)
468 {
469 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
470 {
471 UUID uuid;
472 if (UUID.TryParse(hash[key].ToString(), out uuid))
473 friendsOnline.Add(uuid);
474 }
475 }
476
477 }
478 catch
479 {
480 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
481// reason = "Exception: " + e.Message;
482 }
483
484 return friendsOnline;
485 }
486
487 public List<UUID> GetOnlineFriends(UUID userID, List<string> friends)
488 {
489 Hashtable hash = new Hashtable();
490 hash["userID"] = userID.ToString();
491 int i = 0;
492 foreach (string s in friends)
493 {
494 hash["friend_" + i.ToString()] = s;
495 i++;
496 }
497
498 IList paramList = new ArrayList();
499 paramList.Add(hash);
500
501 XmlRpcRequest request = new XmlRpcRequest("get_online_friends", paramList);
502// string reason = string.Empty;
503
504 // Send and get reply
505 List<UUID> online = new List<UUID>();
506 XmlRpcResponse response = null;
507 try
508 {
509 response = request.Send(m_ServerURL, 10000);
510 }
511 catch
512 {
513 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURL);
514// reason = "Exception: " + e.Message;
515 return online;
516 }
517
518 if (response.IsFault)
519 {
520 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURL, response.FaultString);
521// reason = "XMLRPC Fault";
522 return online;
523 }
524
525 hash = (Hashtable)response.Value;
526 //foreach (Object o in hash)
527 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
528 try
529 {
530 if (hash == null)
531 {
532 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetOnlineFriends Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
533// reason = "Internal error 1";
534 return online;
535 }
536
537 // Here is the actual response
538 foreach (object key in hash.Keys)
539 {
540 if (key is string && ((string)key).StartsWith("friend_") && hash[key] != null)
541 {
542 UUID uuid;
543 if (UUID.TryParse(hash[key].ToString(), out uuid))
544 online.Add(uuid);
545 }
546 }
547
548 }
549 catch
550 {
551 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
552// reason = "Exception: " + e.Message;
553 }
554
555 return online;
556 }
557
558 public Dictionary<string, object> GetServerURLs(UUID userID)
559 {
560 Hashtable hash = new Hashtable();
561 hash["userID"] = userID.ToString();
562
563 IList paramList = new ArrayList();
564 paramList.Add(hash);
565
566 XmlRpcRequest request = new XmlRpcRequest("get_server_urls", paramList);
567// string reason = string.Empty;
568
569 // Send and get reply
570 Dictionary<string, object> serverURLs = new Dictionary<string,object>();
571 XmlRpcResponse response = null;
572 try
573 {
574 response = request.Send(m_ServerURL, 10000);
575 }
576 catch
577 {
578 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetServerURLs", m_ServerURL);
579// reason = "Exception: " + e.Message;
580 return serverURLs;
581 }
582
583 if (response.IsFault)
584 {
585 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetServerURLs returned an error: {1}", m_ServerURL, response.FaultString);
586// reason = "XMLRPC Fault";
587 return serverURLs;
588 }
589
590 hash = (Hashtable)response.Value;
591 //foreach (Object o in hash)
592 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
593 try
594 {
595 if (hash == null)
596 {
597 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetServerURLs Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
598// reason = "Internal error 1";
599 return serverURLs;
600 }
601
602 // Here is the actual response
603 foreach (object key in hash.Keys)
604 {
605 if (key is string && ((string)key).StartsWith("SRV_") && hash[key] != null)
606 {
607 string serverType = key.ToString().Substring(4); // remove "SRV_"
608 serverURLs.Add(serverType, hash[key].ToString());
609 }
610 }
611
612 }
613 catch
614 {
615 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetOnlineFriends response.");
616// reason = "Exception: " + e.Message;
617 }
618
619 return serverURLs;
620 }
621
622 public string LocateUser(UUID userID)
623 {
624 Hashtable hash = new Hashtable();
625 hash["userID"] = userID.ToString();
626
627 IList paramList = new ArrayList();
628 paramList.Add(hash);
629
630 XmlRpcRequest request = new XmlRpcRequest("locate_user", paramList);
631// string reason = string.Empty;
632
633 // Send and get reply
634 string url = string.Empty;
635 XmlRpcResponse response = null;
636 try
637 {
638 response = request.Send(m_ServerURL, 10000);
639 }
640 catch
641 {
642 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for LocateUser", m_ServerURL);
643// reason = "Exception: " + e.Message;
644 return url;
645 }
646
647 if (response.IsFault)
648 {
649 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for LocateUser returned an error: {1}", m_ServerURL, response.FaultString);
650// reason = "XMLRPC Fault";
651 return url;
652 }
653
654 hash = (Hashtable)response.Value;
655 //foreach (Object o in hash)
656 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
657 try
658 {
659 if (hash == null)
660 {
661 m_log.ErrorFormat("[USER AGENT CONNECTOR]: LocateUser Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
662// reason = "Internal error 1";
663 return url;
664 }
665
666 // Here's the actual response
667 if (hash.ContainsKey("URL"))
668 url = hash["URL"].ToString();
669
670 }
671 catch
672 {
673 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response.");
674// reason = "Exception: " + e.Message;
675 }
676
677 return url;
678 }
679
680 public string GetUUI(UUID userID, UUID targetUserID)
681 {
682 Hashtable hash = new Hashtable();
683 hash["userID"] = userID.ToString();
684 hash["targetUserID"] = targetUserID.ToString();
685
686 IList paramList = new ArrayList();
687 paramList.Add(hash);
688
689 XmlRpcRequest request = new XmlRpcRequest("get_uui", paramList);
690// string reason = string.Empty;
691
692 // Send and get reply
693 string uui = string.Empty;
694 XmlRpcResponse response = null;
695 try
696 {
697 response = request.Send(m_ServerURL, 10000);
698 }
699 catch
700 {
701 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUUI", m_ServerURL);
702// reason = "Exception: " + e.Message;
703 return uui;
704 }
705
706 if (response.IsFault)
707 {
708 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetUUI returned an error: {1}", m_ServerURL, response.FaultString);
709// reason = "XMLRPC Fault";
710 return uui;
711 }
712
713 hash = (Hashtable)response.Value;
714 //foreach (Object o in hash)
715 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
716 try
717 {
718 if (hash == null)
719 {
720 m_log.ErrorFormat("[USER AGENT CONNECTOR]: GetUUI Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
721// reason = "Internal error 1";
722 return uui;
723 }
724
725 // Here's the actual response
726 if (hash.ContainsKey("UUI"))
727 uui = hash["UUI"].ToString();
728
729 }
730 catch
731 {
732 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on LocateUser response.");
733// reason = "Exception: " + e.Message;
734 }
735
736 return uui;
737 }
738
739 private bool GetBoolResponse(XmlRpcRequest request, out string reason)
740 {
741 //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL);
742 XmlRpcResponse response = null;
743 try
744 {
745 response = request.Send(m_ServerURL, 10000);
746 }
747 catch (Exception e)
748 {
749 m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURL);
750 reason = "Exception: " + e.Message;
751 return false;
752 }
753
754 if (response.IsFault)
755 {
756 m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURL, response.FaultString);
757 reason = "XMLRPC Fault";
758 return false;
759 }
760
761 Hashtable hash = (Hashtable)response.Value;
762 //foreach (Object o in hash)
763 // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
764 try
765 {
766 if (hash == null)
767 {
768 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
769 reason = "Internal error 1";
770 return false;
771 }
772 bool success = false;
773 reason = string.Empty;
774 if (hash.ContainsKey("result"))
775 Boolean.TryParse((string)hash["result"], out success);
776 else
777 {
778 reason = "Internal error 2";
779 m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURL);
780 }
781
782 return success;
783 }
784 catch (Exception e)
785 {
786 m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got exception on GetBoolResponse response.");
787 if (hash.ContainsKey("result") && hash["result"] != null)
788 m_log.ErrorFormat("Reply was ", (string)hash["result"]);
789 reason = "Exception: " + e.Message;
790 return false;
791 }
792
793 }
794
795 }
796}
diff --git a/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
new file mode 100644
index 0000000..dbce9f6
--- /dev/null
+++ b/OpenSim/Services/Connectors/InstantMessage/InstantMessageServiceConnector.cs
@@ -0,0 +1,131 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27using System;
28using System.Collections;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenMetaverse;
34using Nwc.XmlRpc;
35using log4net;
36
37using OpenSim.Framework;
38
39namespace OpenSim.Services.Connectors.InstantMessage
40{
41 public class InstantMessageServiceConnector
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 /// <summary>
48 /// This actually does the XMLRPC Request
49 /// </summary>
50 /// <param name="url">URL we pull the data out of to send the request to</param>
51 /// <param name="im">The Instant Message </param>
52 /// <returns>Bool if the message was successfully delivered at the other side.</returns>
53 public static bool SendInstantMessage(string url, GridInstantMessage im)
54 {
55 Hashtable xmlrpcdata = ConvertGridInstantMessageToXMLRPC(im);
56 xmlrpcdata["region_handle"] = 0;
57
58 ArrayList SendParams = new ArrayList();
59 SendParams.Add(xmlrpcdata);
60 XmlRpcRequest GridReq = new XmlRpcRequest("grid_instant_message", SendParams);
61 try
62 {
63
64 XmlRpcResponse GridResp = GridReq.Send(url, 10000);
65
66 Hashtable responseData = (Hashtable)GridResp.Value;
67
68 if (responseData.ContainsKey("success"))
69 {
70 if ((string)responseData["success"] == "TRUE")
71 {
72 //m_log.DebugFormat("[XXX] Success");
73 return true;
74 }
75 else
76 {
77 //m_log.DebugFormat("[XXX] Fail");
78 return false;
79 }
80 }
81 else
82 {
83 m_log.DebugFormat("[GRID INSTANT MESSAGE]: No response from {0}", url);
84 return false;
85 }
86 }
87 catch (WebException e)
88 {
89 m_log.ErrorFormat("[GRID INSTANT MESSAGE]: Error sending message to {0} the host didn't respond " + e.ToString(), url);
90 }
91
92 return false;
93 }
94
95 /// <summary>
96 /// Takes a GridInstantMessage and converts it into a Hashtable for XMLRPC
97 /// </summary>
98 /// <param name="msg">The GridInstantMessage object</param>
99 /// <returns>Hashtable containing the XMLRPC request</returns>
100 protected static Hashtable ConvertGridInstantMessageToXMLRPC(GridInstantMessage msg)
101 {
102 Hashtable gim = new Hashtable();
103 gim["from_agent_id"] = msg.fromAgentID.ToString();
104 // Kept for compatibility
105 gim["from_agent_session"] = UUID.Zero.ToString();
106 gim["to_agent_id"] = msg.toAgentID.ToString();
107 gim["im_session_id"] = msg.imSessionID.ToString();
108 gim["timestamp"] = msg.timestamp.ToString();
109 gim["from_agent_name"] = msg.fromAgentName;
110 gim["message"] = msg.message;
111 byte[] dialogdata = new byte[1]; dialogdata[0] = msg.dialog;
112 gim["dialog"] = Convert.ToBase64String(dialogdata, Base64FormattingOptions.None);
113
114 if (msg.fromGroup)
115 gim["from_group"] = "TRUE";
116 else
117 gim["from_group"] = "FALSE";
118 byte[] offlinedata = new byte[1]; offlinedata[0] = msg.offline;
119 gim["offline"] = Convert.ToBase64String(offlinedata, Base64FormattingOptions.None);
120 gim["parent_estate_id"] = msg.ParentEstateID.ToString();
121 gim["position_x"] = msg.Position.X.ToString();
122 gim["position_y"] = msg.Position.Y.ToString();
123 gim["position_z"] = msg.Position.Z.ToString();
124 gim["region_id"] = msg.RegionID.ToString();
125 gim["binary_bucket"] = Convert.ToBase64String(msg.binaryBucket, Base64FormattingOptions.None);
126
127 return gim;
128 }
129
130 }
131}
diff --git a/OpenSim/Services/Connectors/Inventory/HGInventoryServiceConnector.cs b/OpenSim/Services/Connectors/Inventory/HGInventoryServiceConnector.cs
deleted file mode 100644
index 9878855..0000000
--- a/OpenSim/Services/Connectors/Inventory/HGInventoryServiceConnector.cs
+++ /dev/null
@@ -1,335 +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 Nini.Config;
30using System;
31using System.Collections.Generic;
32using System.Reflection;
33using OpenSim.Framework;
34using OpenSim.Services.Interfaces;
35using OpenMetaverse;
36
37namespace OpenSim.Services.Connectors.Inventory
38{
39 public class HGInventoryServiceConnector : ISessionAuthInventoryService
40 {
41 private static readonly ILog m_log =
42 LogManager.GetLogger(
43 MethodBase.GetCurrentMethod().DeclaringType);
44
45 private Dictionary<string, InventoryServicesConnector> m_connectors = new Dictionary<string, InventoryServicesConnector>();
46
47 public HGInventoryServiceConnector(IConfigSource source)
48 {
49 IConfig moduleConfig = source.Configs["Modules"];
50 if (moduleConfig != null)
51 {
52
53 IConfig inventoryConfig = source.Configs["InventoryService"];
54 if (inventoryConfig == null)
55 {
56 m_log.Error("[HG INVENTORY SERVICE]: InventoryService missing from OpenSim.ini");
57 return;
58 }
59
60 m_log.Info("[HG INVENTORY SERVICE]: HG inventory service enabled");
61 }
62 }
63
64 private bool StringToUrlAndUserID(string id, out string url, out string userID)
65 {
66 url = String.Empty;
67 userID = String.Empty;
68
69 Uri assetUri;
70
71 if (Uri.TryCreate(id, UriKind.Absolute, out assetUri) &&
72 assetUri.Scheme == Uri.UriSchemeHttp)
73 {
74 url = "http://" + assetUri.Authority;
75 userID = assetUri.LocalPath.Trim(new char[] { '/' });
76 return true;
77 }
78
79 return false;
80 }
81 private ISessionAuthInventoryService GetConnector(string url)
82 {
83 InventoryServicesConnector connector = null;
84 lock (m_connectors)
85 {
86 if (m_connectors.ContainsKey(url))
87 {
88 connector = m_connectors[url];
89 }
90 else
91 {
92 // We're instantiating this class explicitly, but this won't
93 // work in general, because the remote grid may be running
94 // an inventory server that has a different protocol.
95 // Eventually we will want a piece of protocol asking
96 // the remote server about its kind. Definitely cool thing to do!
97 connector = new InventoryServicesConnector(url);
98 m_connectors.Add(url, connector);
99 }
100 }
101 return connector;
102 }
103
104 public string Host
105 {
106 get { return string.Empty; }
107 }
108
109 public void GetUserInventory(string id, UUID sessionID, InventoryReceiptCallback callback)
110 {
111 m_log.Debug("[HGInventory]: GetUserInventory " + id);
112 string url = string.Empty;
113 string userID = string.Empty;
114
115 if (StringToUrlAndUserID(id, out url, out userID))
116 {
117 ISessionAuthInventoryService connector = GetConnector(url);
118 connector.GetUserInventory(userID, sessionID, callback);
119 }
120
121 }
122
123 /// <summary>
124 /// Gets the user folder for the given folder-type
125 /// </summary>
126 /// <param name="userID"></param>
127 /// <param name="type"></param>
128 /// <returns></returns>
129 public Dictionary<AssetType, InventoryFolderBase> GetSystemFolders(string id, UUID sessionID)
130 {
131 m_log.Debug("[HGInventory]: GetSystemFolders " + id);
132 string url = string.Empty;
133 string userID = string.Empty;
134
135 if (StringToUrlAndUserID(id, out url, out userID))
136 {
137 ISessionAuthInventoryService connector = GetConnector(url);
138 return connector.GetSystemFolders(userID, sessionID);
139 }
140
141 return new Dictionary<AssetType, InventoryFolderBase>();
142 }
143
144 /// <summary>
145 /// Gets everything (folders and items) inside a folder
146 /// </summary>
147 /// <param name="userId"></param>
148 /// <param name="folderID"></param>
149 /// <returns></returns>
150 public InventoryCollection GetFolderContent(string id, UUID folderID, UUID sessionID)
151 {
152 m_log.Debug("[HGInventory]: GetFolderContent " + id);
153 string url = string.Empty;
154 string userID = string.Empty;
155
156 if (StringToUrlAndUserID(id, out url, out userID))
157 {
158 ISessionAuthInventoryService connector = GetConnector(url);
159 return connector.GetFolderContent(userID, folderID, sessionID);
160 }
161
162 return null;
163 }
164
165 public bool AddFolder(string id, InventoryFolderBase folder, UUID sessionID)
166 {
167 string url = string.Empty;
168 string userID = string.Empty;
169
170 if (StringToUrlAndUserID(id, out url, out userID))
171 {
172 ISessionAuthInventoryService connector = GetConnector(url);
173 return connector.AddFolder(userID, folder, sessionID);
174 }
175 return false;
176 }
177
178 public bool UpdateFolder(string id, InventoryFolderBase folder, UUID sessionID)
179 {
180 string url = string.Empty;
181 string userID = string.Empty;
182
183 if (StringToUrlAndUserID(id, out url, out userID))
184 {
185 ISessionAuthInventoryService connector = GetConnector(url);
186 return connector.UpdateFolder(userID, folder, sessionID);
187 }
188 return false;
189 }
190
191 public bool MoveFolder(string id, InventoryFolderBase folder, UUID sessionID)
192 {
193 string url = string.Empty;
194 string userID = string.Empty;
195
196 if (StringToUrlAndUserID(id, out url, out userID))
197 {
198 ISessionAuthInventoryService connector = GetConnector(url);
199 return connector.MoveFolder(userID, folder, sessionID);
200 }
201 return false;
202 }
203
204 public bool DeleteFolders(string id, List<UUID> folders, UUID sessionID)
205 {
206 string url = string.Empty;
207 string userID = string.Empty;
208
209 if (StringToUrlAndUserID(id, out url, out userID))
210 {
211 ISessionAuthInventoryService connector = GetConnector(url);
212 return connector.DeleteFolders(userID, folders, sessionID);
213 }
214 return false;
215 }
216
217 public bool PurgeFolder(string id, InventoryFolderBase folder, UUID sessionID)
218 {
219 string url = string.Empty;
220 string userID = string.Empty;
221
222 if (StringToUrlAndUserID(id, out url, out userID))
223 {
224 ISessionAuthInventoryService connector = GetConnector(url);
225 return connector.PurgeFolder(userID, folder, sessionID);
226 }
227 return false;
228 }
229
230 public List<InventoryItemBase> GetFolderItems(string id, UUID folderID, UUID sessionID)
231 {
232 string url = string.Empty;
233 string userID = string.Empty;
234
235 if (StringToUrlAndUserID(id, out url, out userID))
236 {
237 ISessionAuthInventoryService connector = GetConnector(url);
238 return connector.GetFolderItems(userID, folderID, sessionID);
239 }
240 return new List<InventoryItemBase>();
241 }
242
243 public bool AddItem(string id, InventoryItemBase item, UUID sessionID)
244 {
245 string url = string.Empty;
246 string userID = string.Empty;
247
248 if (StringToUrlAndUserID(id, out url, out userID))
249 {
250 ISessionAuthInventoryService connector = GetConnector(url);
251 return connector.AddItem(userID, item, sessionID);
252 }
253 return false;
254 }
255
256 public bool UpdateItem(string id, InventoryItemBase item, UUID sessionID)
257 {
258 string url = string.Empty;
259 string userID = string.Empty;
260
261 if (StringToUrlAndUserID(id, out url, out userID))
262 {
263 ISessionAuthInventoryService connector = GetConnector(url);
264 return connector.UpdateItem(userID, item, sessionID);
265 }
266 return false;
267 }
268
269 public bool MoveItems(string id, List<InventoryItemBase> items, UUID sessionID)
270 {
271 string url = string.Empty;
272 string userID = string.Empty;
273
274 if (StringToUrlAndUserID(id, out url, out userID))
275 {
276 ISessionAuthInventoryService connector = GetConnector(url);
277 return connector.MoveItems(userID, items, sessionID);
278 }
279 return false;
280 }
281
282 public bool DeleteItems(string id, List<UUID> itemIDs, UUID sessionID)
283 {
284 string url = string.Empty;
285 string userID = string.Empty;
286
287 if (StringToUrlAndUserID(id, out url, out userID))
288 {
289 ISessionAuthInventoryService connector = GetConnector(url);
290 return connector.DeleteItems(userID, itemIDs, sessionID);
291 }
292 return false;
293 }
294
295 public InventoryItemBase QueryItem(string id, InventoryItemBase item, UUID sessionID)
296 {
297 string url = string.Empty;
298 string userID = string.Empty;
299
300 if (StringToUrlAndUserID(id, out url, out userID))
301 {
302 //m_log.DebugFormat("[HGInventory CONNECTOR]: calling {0}", url);
303 ISessionAuthInventoryService connector = GetConnector(url);
304 return connector.QueryItem(userID, item, sessionID);
305 }
306 return null;
307 }
308
309 public InventoryFolderBase QueryFolder(string id, InventoryFolderBase folder, UUID sessionID)
310 {
311 string url = string.Empty;
312 string userID = string.Empty;
313
314 if (StringToUrlAndUserID(id, out url, out userID))
315 {
316 ISessionAuthInventoryService connector = GetConnector(url);
317 return connector.QueryFolder(userID, folder, sessionID);
318 }
319 return null;
320 }
321
322 public int GetAssetPermissions(string id, UUID assetID, UUID sessionID)
323 {
324 string url = string.Empty;
325 string userID = string.Empty;
326
327 if (StringToUrlAndUserID(id, out url, out userID))
328 {
329 ISessionAuthInventoryService connector = GetConnector(url);
330 return connector.GetAssetPermissions(userID, assetID, sessionID);
331 }
332 return 0;
333 }
334 }
335}
diff --git a/OpenSim/Services/Connectors/Inventory/ISessionAuthInventoryService.cs b/OpenSim/Services/Connectors/Inventory/ISessionAuthInventoryService.cs
deleted file mode 100644
index da8c7e2..0000000
--- a/OpenSim/Services/Connectors/Inventory/ISessionAuthInventoryService.cs
+++ /dev/null
@@ -1,140 +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 System.Collections.Generic;
29using OpenSim.Framework;
30using OpenSim.Services.Interfaces;
31using OpenMetaverse;
32
33namespace OpenSim.Services.Connectors
34{
35 /// <summary>
36 /// Defines all operations to access a remote inventory service
37 /// using session authentication as a form of security.
38 /// </summary>
39 public interface ISessionAuthInventoryService
40 {
41 string Host
42 {
43 get;
44 }
45
46 /// <summary>
47 /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the
48 /// inventory has been received
49 /// </summary>
50 /// <param name="userID"></param>
51 /// <param name="callback"></param>
52 void GetUserInventory(string userID, UUID session_id, InventoryReceiptCallback callback);
53
54 /// <summary>
55 /// Gets the user folder for the given folder-type
56 /// </summary>
57 /// <param name="userID"></param>
58 /// <param name="type"></param>
59 /// <returns></returns>
60 Dictionary<AssetType, InventoryFolderBase> GetSystemFolders(string userID, UUID session_id);
61
62 /// <summary>
63 /// Gets everything (folders and items) inside a folder
64 /// </summary>
65 /// <param name="userId"></param>
66 /// <param name="folderID"></param>
67 /// <returns></returns>
68 InventoryCollection GetFolderContent(string userID, UUID folderID, UUID session_id);
69
70 /// <summary>
71 /// Add a new folder to the user's inventory
72 /// </summary>
73 /// <param name="folder"></param>
74 /// <returns>true if the folder was successfully added</returns>
75 bool AddFolder(string userID, InventoryFolderBase folder, UUID session_id);
76
77 /// <summary>
78 /// Update a folder in the user's inventory
79 /// </summary>
80 /// <param name="folder"></param>
81 /// <returns>true if the folder was successfully updated</returns>
82 bool UpdateFolder(string userID, InventoryFolderBase folder, UUID session_id);
83
84 /// <summary>
85 /// Move an inventory folder to a new location
86 /// </summary>
87 /// <param name="folder">A folder containing the details of the new location</param>
88 /// <returns>true if the folder was successfully moved</returns>
89 bool MoveFolder(string userID, InventoryFolderBase folder, UUID session_id);
90
91 /// <summary>
92 /// Delete a list of inventory folders (from trash)
93 /// </summary>
94 bool DeleteFolders(string userID, List<UUID> folders, UUID session_id);
95
96 /// <summary>
97 /// Purge an inventory folder of all its items and subfolders.
98 /// </summary>
99 /// <param name="folder"></param>
100 /// <returns>true if the folder was successfully purged</returns>
101 bool PurgeFolder(string userID, InventoryFolderBase folder, UUID session_id);
102
103 /// <summary>
104 /// Get items from a folder.
105 /// </summary>
106 /// <param name="folder"></param>
107 /// <returns>true if the folder was successfully purged</returns>
108 List<InventoryItemBase> GetFolderItems(string userID, UUID folderID, UUID session_id);
109
110 /// <summary>
111 /// Add a new item to the user's inventory
112 /// </summary>
113 /// <param name="item"></param>
114 /// <returns>true if the item was successfully added</returns>
115 bool AddItem(string userID, InventoryItemBase item, UUID session_id);
116
117 /// <summary>
118 /// Update an item in the user's inventory
119 /// </summary>
120 /// <param name="item"></param>
121 /// <returns>true if the item was successfully updated</returns>
122 bool UpdateItem(string userID, InventoryItemBase item, UUID session_id);
123
124 bool MoveItems(string userID, List<InventoryItemBase> items, UUID session_id);
125
126 /// <summary>
127 /// Delete an item from the user's inventory
128 /// </summary>
129 /// <param name="item"></param>
130 /// <returns>true if the item was successfully deleted</returns>
131 bool DeleteItems(string userID, List<UUID> itemIDs, UUID session_id);
132
133 InventoryItemBase QueryItem(string userID, InventoryItemBase item, UUID session_id);
134
135 InventoryFolderBase QueryFolder(string userID, InventoryFolderBase item, UUID session_id);
136
137 int GetAssetPermissions(string userID, UUID assetID, UUID session_id);
138
139 }
140}
diff --git a/OpenSim/Services/Connectors/Inventory/InventoryServiceConnector.cs b/OpenSim/Services/Connectors/Inventory/InventoryServiceConnector.cs
deleted file mode 100644
index f86b453..0000000
--- a/OpenSim/Services/Connectors/Inventory/InventoryServiceConnector.cs
+++ /dev/null
@@ -1,582 +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.Servers.HttpServer;
36using OpenSim.Services.Interfaces;
37using OpenMetaverse;
38
39namespace OpenSim.Services.Connectors
40{
41 public class InventoryServicesConnector : ISessionAuthInventoryService
42 {
43 private static readonly ILog m_log =
44 LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType);
46
47 private string m_ServerURI = String.Empty;
48
49 private Dictionary<UUID, InventoryReceiptCallback> m_RequestingInventory = new Dictionary<UUID, InventoryReceiptCallback>();
50 private Dictionary<UUID, DateTime> m_RequestTime = new Dictionary<UUID, DateTime>();
51
52 public InventoryServicesConnector()
53 {
54 }
55
56 public InventoryServicesConnector(string serverURI)
57 {
58 m_ServerURI = serverURI.TrimEnd('/');
59 }
60
61 public InventoryServicesConnector(IConfigSource source)
62 {
63 Initialise(source);
64 }
65
66 public virtual void Initialise(IConfigSource source)
67 {
68 IConfig inventoryConfig = source.Configs["InventoryService"];
69 if (inventoryConfig == null)
70 {
71 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
72 throw new Exception("InventoryService missing from OpenSim.ini");
73 }
74
75 string serviceURI = inventoryConfig.GetString("InventoryServerURI",
76 String.Empty);
77
78 if (serviceURI == String.Empty)
79 {
80 m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService");
81 throw new Exception("Unable to proceed. Please make sure your ini files in config-include are updated according to .example's");
82 }
83 m_ServerURI = serviceURI.TrimEnd('/');
84 }
85
86 #region ISessionAuthInventoryService
87
88 public string Host
89 {
90 get { return m_ServerURI; }
91 }
92
93 /// <summary>
94 /// Caller must catch eventual Exceptions.
95 /// </summary>
96 /// <param name="userID"></param>
97 /// <param name="sessionID"></param>
98 /// <param name="callback"></param>
99 public void GetUserInventory(string userIDStr, UUID sessionID, InventoryReceiptCallback callback)
100 {
101 UUID userID = UUID.Zero;
102 if (UUID.TryParse(userIDStr, out userID))
103 {
104 lock (m_RequestingInventory)
105 {
106 // *HACK ALERT*
107
108 // If an inventory request times out, it blocks any further requests from the
109 // same user, even after a relog. This is bad, and makes me sad.
110
111 // Really, we should detect a timeout and report a failure to the callback,
112 // BUT in my testing i found that it's hard to detect a timeout.. sometimes,
113 // a partial response is recieved, and sometimes a null response.
114
115 // So, for now, add a timer of ten seconds (which is the request timeout).
116
117 // This should basically have the same effect.
118
119 lock (m_RequestTime)
120 {
121 if (m_RequestTime.ContainsKey(userID))
122 {
123 TimeSpan interval = DateTime.Now - m_RequestTime[userID];
124 if (interval.TotalSeconds > 10)
125 {
126 m_RequestTime.Remove(userID);
127 if (m_RequestingInventory.ContainsKey(userID))
128 {
129 m_RequestingInventory.Remove(userID);
130 }
131 }
132 }
133 if (!m_RequestingInventory.ContainsKey(userID))
134 {
135 m_RequestTime.Add(userID, DateTime.Now);
136 m_RequestingInventory.Add(userID, callback);
137 }
138 else
139 {
140 m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetUserInventory - ignoring repeated request for user {0}", userID);
141 return;
142 }
143 }
144 }
145
146 m_log.InfoFormat(
147 "[INVENTORY CONNECTOR]: Requesting inventory from {0}/GetInventory/ for user {1}",
148 m_ServerURI, userID);
149
150 RestSessionObjectPosterResponse<Guid, InventoryCollection> requester
151 = new RestSessionObjectPosterResponse<Guid, InventoryCollection>();
152 requester.ResponseCallback = InventoryResponse;
153
154 requester.BeginPostObject(m_ServerURI + "/GetInventory/", userID.Guid, sessionID.ToString(), userID.ToString());
155 }
156 }
157
158 /// <summary>
159 /// Gets the user folder for the given folder-type
160 /// </summary>
161 /// <param name="userID"></param>
162 /// <param name="type"></param>
163 /// <returns></returns>
164 public Dictionary<AssetType, InventoryFolderBase> GetSystemFolders(string userID, UUID sessionID)
165 {
166 List<InventoryFolderBase> folders = null;
167 Dictionary<AssetType, InventoryFolderBase> dFolders = new Dictionary<AssetType, InventoryFolderBase>();
168 try
169 {
170 folders = SynchronousRestSessionObjectPoster<Guid, List<InventoryFolderBase>>.BeginPostObject(
171 "POST", m_ServerURI + "/SystemFolders/", new Guid(userID), sessionID.ToString(), userID.ToString());
172
173 foreach (InventoryFolderBase f in folders)
174 dFolders[(AssetType)f.Type] = f;
175
176 return dFolders;
177 }
178 catch (Exception e)
179 {
180 // Maybe we're talking to an old inventory server. Try this other thing.
181 m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetSystemFolders operation failed, {0} {1} (old sever?). Trying GetInventory.",
182 e.Source, e.Message);
183
184 try
185 {
186 InventoryCollection inventory = SynchronousRestSessionObjectPoster<Guid, InventoryCollection>.BeginPostObject(
187 "POST", m_ServerURI + "/GetInventory/", new Guid(userID), sessionID.ToString(), userID.ToString());
188 folders = inventory.Folders;
189 }
190 catch (Exception ex)
191 {
192 m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetInventory operation also failed, {0} {1}. Giving up.",
193 e.Source, ex.Message);
194 }
195
196 if ((folders != null) && (folders.Count > 0))
197 {
198 m_log.DebugFormat("[INVENTORY CONNECTOR]: Received entire inventory ({0} folders) for user {1}",
199 folders.Count, userID);
200 foreach (InventoryFolderBase f in folders)
201 {
202 if ((f.Type != (short)AssetType.Folder) && (f.Type != (short)AssetType.Unknown))
203 dFolders[(AssetType)f.Type] = f;
204 }
205
206 UUID rootFolderID = dFolders[AssetType.Animation].ParentID;
207 InventoryFolderBase rootFolder = new InventoryFolderBase(rootFolderID, new UUID(userID));
208 rootFolder = QueryFolder(userID, rootFolder, sessionID);
209 dFolders[AssetType.Folder] = rootFolder;
210 m_log.DebugFormat("[INVENTORY CONNECTOR]: {0} system folders for user {1}", dFolders.Count, userID);
211 return dFolders;
212 }
213 }
214
215 return new Dictionary<AssetType, InventoryFolderBase>();
216 }
217
218 /// <summary>
219 /// Gets everything (folders and items) inside a folder
220 /// </summary>
221 /// <param name="userId"></param>
222 /// <param name="folderID"></param>
223 /// <returns></returns>
224 public InventoryCollection GetFolderContent(string userID, UUID folderID, UUID sessionID)
225 {
226 try
227 {
228 // normal case
229 return SynchronousRestSessionObjectPoster<Guid, InventoryCollection>.BeginPostObject(
230 "POST", m_ServerURI + "/GetFolderContent/", folderID.Guid, sessionID.ToString(), userID.ToString());
231 }
232 catch (TimeoutException e)
233 {
234 m_log.ErrorFormat(
235 "[INVENTORY CONNECTOR]: GetFolderContent operation to {0} for {1} timed out {2} {3}.",
236 m_ServerURI, folderID, e.Source, e.Message);
237 }
238 catch (Exception e)
239 {
240 m_log.ErrorFormat("[INVENTORY CONNECTOR]: GetFolderContent operation failed for {0}, {1} {2} (old server?).",
241 folderID, e.Source, e.Message);
242 }
243
244 InventoryCollection nullCollection = new InventoryCollection();
245 nullCollection.Folders = new List<InventoryFolderBase>();
246 nullCollection.Items = new List<InventoryItemBase>();
247 nullCollection.UserID = new UUID(userID);
248 return nullCollection;
249 }
250
251 public bool AddFolder(string userID, InventoryFolderBase folder, UUID sessionID)
252 {
253 try
254 {
255 return SynchronousRestSessionObjectPoster<InventoryFolderBase, bool>.BeginPostObject(
256 "POST", m_ServerURI + "/NewFolder/", folder, sessionID.ToString(), folder.Owner.ToString());
257 }
258 catch (Exception e)
259 {
260 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory folder operation failed for {0} {1}, {2} {3}",
261 folder.Name, folder.ID, e.Source, e.Message);
262 }
263
264 return false;
265 }
266
267 public bool UpdateFolder(string userID, InventoryFolderBase folder, UUID sessionID)
268 {
269 try
270 {
271 return SynchronousRestSessionObjectPoster<InventoryFolderBase, bool>.BeginPostObject(
272 "POST", m_ServerURI + "/UpdateFolder/", folder, sessionID.ToString(), folder.Owner.ToString());
273 }
274 catch (Exception e)
275 {
276 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update inventory folder operation failed for {0} {1}, {2} {3}",
277 folder.Name, folder.ID, e.Source, e.Message);
278 }
279
280 return false;
281 }
282
283 public bool DeleteFolders(string userID, List<UUID> folderIDs, UUID sessionID)
284 {
285 try
286 {
287 List<Guid> guids = new List<Guid>();
288 foreach (UUID u in folderIDs)
289 guids.Add(u.Guid);
290 return SynchronousRestSessionObjectPoster<List<Guid>, bool>.BeginPostObject(
291 "POST", m_ServerURI + "/DeleteFolders/", guids, sessionID.ToString(), userID);
292 }
293 catch (Exception e)
294 {
295 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Delete inventory folders operation failed, {0} {1}",
296 e.Source, e.Message);
297 }
298
299 return false;
300 }
301
302 public bool MoveFolder(string userID, InventoryFolderBase folder, UUID sessionID)
303 {
304 try
305 {
306 return SynchronousRestSessionObjectPoster<InventoryFolderBase, bool>.BeginPostObject(
307 "POST", m_ServerURI + "/MoveFolder/", folder, sessionID.ToString(), folder.Owner.ToString());
308 }
309 catch (Exception e)
310 {
311 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Move inventory folder operation failed for {0} {1}, {2} {3}",
312 folder.Name, folder.ID, e.Source, e.Message);
313 }
314
315 return false;
316 }
317
318 public bool PurgeFolder(string userID, InventoryFolderBase folder, UUID sessionID)
319 {
320 try
321 {
322 return SynchronousRestSessionObjectPoster<InventoryFolderBase, bool>.BeginPostObject(
323 "POST", m_ServerURI + "/PurgeFolder/", folder, sessionID.ToString(), folder.Owner.ToString());
324 }
325 catch (Exception e)
326 {
327 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Purge inventory folder operation failed for {0} {1}, {2} {3}",
328 folder.Name, folder.ID, e.Source, e.Message);
329 }
330
331 return false;
332 }
333
334 public List<InventoryItemBase> GetFolderItems(string userID, UUID folderID, UUID sessionID)
335 {
336 try
337 {
338 InventoryFolderBase folder = new InventoryFolderBase(folderID, new UUID(userID));
339 return SynchronousRestSessionObjectPoster<InventoryFolderBase, List<InventoryItemBase>>.BeginPostObject(
340 "POST", m_ServerURI + "/GetItems/", folder, sessionID.ToString(), userID);
341 }
342 catch (Exception e)
343 {
344 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Get folder items operation failed for folder {0}, {1} {2}",
345 folderID, e.Source, e.Message);
346 }
347
348 return null;
349 }
350
351 public bool AddItem(string userID, InventoryItemBase item, UUID sessionID)
352 {
353 try
354 {
355 return SynchronousRestSessionObjectPoster<InventoryItemBase, bool>.BeginPostObject(
356 "POST", m_ServerURI + "/NewItem/", item, sessionID.ToString(), item.Owner.ToString());
357 }
358 catch (Exception e)
359 {
360 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Add new inventory item operation failed for {0} {1}, {2} {3}",
361 item.Name, item.ID, e.Source, e.Message);
362 }
363
364 return false;
365 }
366
367 public bool UpdateItem(string userID, InventoryItemBase item, UUID sessionID)
368 {
369 try
370 {
371 return SynchronousRestSessionObjectPoster<InventoryItemBase, bool>.BeginPostObject(
372 "POST", m_ServerURI + "/NewItem/", item, sessionID.ToString(), item.Owner.ToString());
373 }
374 catch (Exception e)
375 {
376 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Update new inventory item operation failed for {0} {1}, {2} {3}",
377 item.Name, item.ID, e.Source, e.Message);
378 }
379
380 return false;
381 }
382
383 /**
384 * MoveItems Async group
385 */
386
387 delegate void MoveItemsDelegate(string userID, List<InventoryItemBase> items, UUID sessionID);
388
389 private void MoveItemsAsync(string userID, List<InventoryItemBase> items, UUID sessionID)
390 {
391 if (items == null)
392 {
393 m_log.WarnFormat("[INVENTORY CONNECTOR]: request to move items got a null list.");
394 return;
395 }
396
397 try
398 {
399 //SynchronousRestSessionObjectPoster<List<InventoryItemBase>, bool>.BeginPostObject(
400 // "POST", m_ServerURI + "/MoveItems/", items, sessionID.ToString(), userID.ToString());
401
402 //// Success
403 //return;
404 string uri = m_ServerURI + "/inventory/" + userID;
405 if (SynchronousRestObjectRequester.
406 MakeRequest<List<InventoryItemBase>, bool>("PUT", uri, items))
407 m_log.DebugFormat("[INVENTORY CONNECTOR]: move {0} items poster succeeded {1}", items.Count, uri);
408 else
409 m_log.DebugFormat("[INVENTORY CONNECTOR]: move {0} items poster failed {1}", items.Count, uri); ;
410
411 return;
412
413 }
414 catch (Exception e)
415 {
416 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Move inventory items operation failed, {0} {1} (old server?). Trying slow way.",
417 e.Source, e.Message);
418 }
419
420 }
421
422 private void MoveItemsCompleted(IAsyncResult iar)
423 {
424 MoveItemsDelegate d = (MoveItemsDelegate)iar.AsyncState;
425 d.EndInvoke(iar);
426 }
427
428 public bool MoveItems(string userID, List<InventoryItemBase> items, UUID sessionID)
429 {
430 MoveItemsDelegate d = MoveItemsAsync;
431 d.BeginInvoke(userID, items, sessionID, MoveItemsCompleted, d);
432 return true;
433 }
434
435 public bool DeleteItems(string userID, List<UUID> items, UUID sessionID)
436 {
437 try
438 {
439 List<Guid> guids = new List<Guid>();
440 foreach (UUID u in items)
441 guids.Add(u.Guid);
442 return SynchronousRestSessionObjectPoster<List<Guid>, bool>.BeginPostObject(
443 "POST", m_ServerURI + "/DeleteItem/", guids, sessionID.ToString(), userID);
444 }
445 catch (Exception e)
446 {
447 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Delete inventory items operation failed, {0} {1}",
448 e.Source, e.Message);
449 }
450
451 return false;
452 }
453
454 public InventoryItemBase QueryItem(string userID, InventoryItemBase item, UUID sessionID)
455 {
456 try
457 {
458 return SynchronousRestSessionObjectPoster<InventoryItemBase, InventoryItemBase>.BeginPostObject(
459 "POST", m_ServerURI + "/QueryItem/", item, sessionID.ToString(), item.Owner.ToString());
460 }
461 catch (Exception e)
462 {
463 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Query inventory item operation failed, {0} {1}",
464 e.Source, e.Message);
465 }
466
467 return null;
468 }
469
470 public InventoryFolderBase QueryFolder(string userID, InventoryFolderBase folder, UUID sessionID)
471 {
472 try
473 {
474 return SynchronousRestSessionObjectPoster<InventoryFolderBase, InventoryFolderBase>.BeginPostObject(
475 "POST", m_ServerURI + "/QueryFolder/", folder, sessionID.ToString(), userID);
476 }
477 catch (Exception e)
478 {
479 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Query inventory folder operation failed, {0} {1}",
480 e.Source, e.Message);
481 }
482
483 return null;
484 }
485
486 public int GetAssetPermissions(string userID, UUID assetID, UUID sessionID)
487 {
488 try
489 {
490 InventoryItemBase item = new InventoryItemBase();
491 item.Owner = new UUID(userID);
492 item.AssetID = assetID;
493 return SynchronousRestSessionObjectPoster<InventoryItemBase, int>.BeginPostObject(
494 "POST", m_ServerURI + "/AssetPermissions/", item, sessionID.ToString(), userID);
495 }
496 catch (Exception e)
497 {
498 m_log.ErrorFormat("[INVENTORY CONNECTOR]: AssetPermissions operation failed, {0} {1}",
499 e.Source, e.Message);
500 }
501
502 return 0;
503 }
504
505 #endregion
506
507 /// <summary>
508 /// Callback used by the inventory server GetInventory request
509 /// </summary>
510 /// <param name="userID"></param>
511 private void InventoryResponse(InventoryCollection response)
512 {
513 UUID userID = response.UserID;
514 InventoryReceiptCallback callback = null;
515 lock (m_RequestingInventory)
516 {
517 if (m_RequestingInventory.ContainsKey(userID))
518 {
519 callback = m_RequestingInventory[userID];
520 m_RequestingInventory.Remove(userID);
521 lock (m_RequestTime)
522 {
523 if (m_RequestTime.ContainsKey(userID))
524 {
525 m_RequestTime.Remove(userID);
526 }
527 }
528 }
529 else
530 {
531 m_log.WarnFormat(
532 "[INVENTORY CONNECTOR]: " +
533 "Received inventory response for {0} for which we do not have a record of requesting!",
534 userID);
535 return;
536 }
537 }
538
539 m_log.InfoFormat("[INVENTORY CONNECTOR]: " +
540 "Received inventory response for user {0} containing {1} folders and {2} items",
541 userID, response.Folders.Count, response.Items.Count);
542
543 InventoryFolderImpl rootFolder = null;
544
545 ICollection<InventoryFolderImpl> folders = new List<InventoryFolderImpl>();
546 ICollection<InventoryItemBase> items = new List<InventoryItemBase>();
547
548 foreach (InventoryFolderBase folder in response.Folders)
549 {
550 if (folder.ParentID == UUID.Zero)
551 {
552 rootFolder = new InventoryFolderImpl(folder);
553 folders.Add(rootFolder);
554
555 break;
556 }
557 }
558
559 if (rootFolder != null)
560 {
561 foreach (InventoryFolderBase folder in response.Folders)
562 {
563 if (folder.ID != rootFolder.ID)
564 {
565 folders.Add(new InventoryFolderImpl(folder));
566 }
567 }
568
569 foreach (InventoryItemBase item in response.Items)
570 {
571 items.Add(item);
572 }
573 }
574 else
575 {
576 m_log.ErrorFormat("[INVENTORY CONNECTOR]: Did not get back an inventory containing a root folder for user {0}", userID);
577 }
578
579 callback(folders, items);
580 }
581 }
582}
diff --git a/OpenSim/Services/Connectors/Inventory/QuickAndDirtyInventoryServiceConnector.cs b/OpenSim/Services/Connectors/Inventory/QuickAndDirtyInventoryServiceConnector.cs
deleted file mode 100644
index a7aa138..0000000
--- a/OpenSim/Services/Connectors/Inventory/QuickAndDirtyInventoryServiceConnector.cs
+++ /dev/null
@@ -1,196 +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.Servers.HttpServer;
36using OpenSim.Services.Interfaces;
37using OpenMetaverse;
38
39namespace OpenSim.Services.Connectors
40{
41 /// <summary>
42 /// This connector is temporary. It's used by the user server, before that server is refactored.
43 /// </summary>
44 public class QuickAndDirtyInventoryServiceConnector : IInventoryService
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 //private Dictionary<UUID, InventoryReceiptCallback> m_RequestingInventory = new Dictionary<UUID, InventoryReceiptCallback>();
53
54 public QuickAndDirtyInventoryServiceConnector()
55 {
56 }
57
58 public QuickAndDirtyInventoryServiceConnector(string serverURI)
59 {
60 m_ServerURI = serverURI.TrimEnd('/');
61 }
62
63 /// <summary>
64 /// <see cref="OpenSim.Framework.Communications.IInterServiceInventoryServices"/>
65 /// </summary>
66 /// <param name="userId"></param>
67 /// <returns></returns>
68 public bool CreateUserInventory(UUID userId)
69 {
70 return SynchronousRestObjectPoster.BeginPostObject<Guid, bool>(
71 "POST", m_ServerURI + "CreateInventory/", userId.Guid);
72 }
73
74 /// <summary>
75 /// <see cref="OpenSim.Framework.Communications.IInterServiceInventoryServices"/>
76 /// </summary>
77 /// <param name="userId"></param>
78 /// <returns></returns>
79 public List<InventoryFolderBase> GetInventorySkeleton(UUID userId)
80 {
81 return SynchronousRestObjectPoster.BeginPostObject<Guid, List<InventoryFolderBase>>(
82 "POST", m_ServerURI + "RootFolders/", userId.Guid);
83 }
84
85 /// <summary>
86 /// Returns a list of all the active gestures in a user's inventory.
87 /// </summary>
88 /// <param name="userId">
89 /// The <see cref="UUID"/> of the user
90 /// </param>
91 /// <returns>
92 /// A flat list of the gesture items.
93 /// </returns>
94 public List<InventoryItemBase> GetActiveGestures(UUID userId)
95 {
96 return SynchronousRestObjectPoster.BeginPostObject<Guid, List<InventoryItemBase>>(
97 "POST", m_ServerURI + "ActiveGestures/", userId.Guid);
98 }
99
100 public InventoryCollection GetUserInventory(UUID userID)
101 {
102 return null;
103 }
104
105 public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
106 {
107 }
108
109 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
110 {
111 return null;
112 }
113
114 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
115 {
116 return null;
117 }
118
119 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
120 {
121 return null;
122 }
123
124 public bool AddFolder(InventoryFolderBase folder)
125 {
126 return false;
127 }
128
129 public bool UpdateFolder(InventoryFolderBase folder)
130 {
131 return false;
132 }
133
134 public bool MoveFolder(InventoryFolderBase folder)
135 {
136 return false;
137 }
138
139 public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
140 {
141 return false;
142 }
143
144
145 public bool PurgeFolder(InventoryFolderBase folder)
146 {
147 return false;
148 }
149
150 public bool AddItem(InventoryItemBase item)
151 {
152 return false;
153 }
154
155 public bool UpdateItem(InventoryItemBase item)
156 {
157 return false;
158 }
159
160 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
161 {
162 return false;
163 }
164
165 public bool DeleteItems(UUID owner, List<UUID> itemIDs)
166 {
167 return false;
168 }
169
170 public InventoryItemBase GetItem(InventoryItemBase item)
171 {
172 return null;
173 }
174
175 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
176 {
177 return null;
178 }
179
180 public bool HasInventoryForUser(UUID userID)
181 {
182 return false;
183 }
184
185 public InventoryFolderBase GetRootFolder(UUID userID)
186 {
187 return null;
188 }
189
190 public int GetAssetPermissions(UUID userID, UUID assetID)
191 {
192 return 0;
193 }
194
195 }
196}
diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs
index b9ccd7e..a662abb 100644
--- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs
+++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs
@@ -34,7 +34,6 @@ using Nini.Config;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Console; 35using OpenSim.Framework.Console;
36using OpenSim.Framework.Communications; 36using OpenSim.Framework.Communications;
37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
39using OpenSim.Server.Base; 38using OpenSim.Server.Base;
40using OpenMetaverse; 39using OpenMetaverse;
@@ -68,7 +67,7 @@ namespace OpenSim.Services.Connectors
68 IConfig assetConfig = source.Configs["InventoryService"]; 67 IConfig assetConfig = source.Configs["InventoryService"];
69 if (assetConfig == null) 68 if (assetConfig == null)
70 { 69 {
71 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpanSim.ini"); 70 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
72 throw new Exception("Inventory connector init error"); 71 throw new Exception("Inventory connector init error");
73 } 72 }
74 73
@@ -92,6 +91,8 @@ namespace OpenSim.Services.Connectors
92 91
93 if (ret == null) 92 if (ret == null)
94 return false; 93 return false;
94 if (ret.Count == 0)
95 return false;
95 96
96 return bool.Parse(ret["RESULT"].ToString()); 97 return bool.Parse(ret["RESULT"].ToString());
97 } 98 }
@@ -105,11 +106,20 @@ namespace OpenSim.Services.Connectors
105 106
106 if (ret == null) 107 if (ret == null)
107 return null; 108 return null;
109 if (ret.Count == 0)
110 return null;
108 111
109 List<InventoryFolderBase> folders = new List<InventoryFolderBase>(); 112 List<InventoryFolderBase> folders = new List<InventoryFolderBase>();
110 113
111 foreach (Object o in ret.Values) 114 try
112 folders.Add(BuildFolder((Dictionary<string,object>)o)); 115 {
116 foreach (Object o in ret.Values)
117 folders.Add(BuildFolder((Dictionary<string, object>)o));
118 }
119 catch (Exception e)
120 {
121 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception unwrapping folder list: {0}", e.Message);
122 }
113 123
114 return folders; 124 return folders;
115 } 125 }
@@ -123,11 +133,10 @@ namespace OpenSim.Services.Connectors
123 133
124 if (ret == null) 134 if (ret == null)
125 return null; 135 return null;
126
127 if (ret.Count == 0) 136 if (ret.Count == 0)
128 return null; 137 return null;
129 138
130 return BuildFolder(ret); 139 return BuildFolder((Dictionary<string, object>)ret["folder"]);
131 } 140 }
132 141
133 public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 142 public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
@@ -140,49 +149,53 @@ namespace OpenSim.Services.Connectors
140 149
141 if (ret == null) 150 if (ret == null)
142 return null; 151 return null;
143
144 if (ret.Count == 0) 152 if (ret.Count == 0)
145 return null; 153 return null;
146 154
147 return BuildFolder(ret); 155 return BuildFolder((Dictionary<string, object>)ret["folder"]);
148 } 156 }
149 157
150 public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) 158 public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
151 { 159 {
152 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
153 new Dictionary<string,object> {
154 { "PRINCIPAL", principalID.ToString() },
155 { "FOLDER", folderID.ToString() }
156 });
157
158 if (ret == null)
159 return null;
160
161 if (ret.Count == 0)
162 return null;
163
164
165 InventoryCollection inventory = new InventoryCollection(); 160 InventoryCollection inventory = new InventoryCollection();
166 inventory.Folders = new List<InventoryFolderBase>(); 161 inventory.Folders = new List<InventoryFolderBase>();
167 inventory.Items = new List<InventoryItemBase>(); 162 inventory.Items = new List<InventoryItemBase>();
168 inventory.UserID = principalID; 163 inventory.UserID = principalID;
169
170 Dictionary<string,object> folders =
171 (Dictionary<string,object>)ret["FOLDERS"];
172 Dictionary<string,object> items =
173 (Dictionary<string,object>)ret["ITEMS"];
174 164
175 foreach (Object o in folders.Values) 165 try
176 inventory.Folders.Add(BuildFolder((Dictionary<string,object>)o)); 166 {
177 foreach (Object o in items.Values) 167 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
178 inventory.Items.Add(BuildItem((Dictionary<string,object>)o)); 168 new Dictionary<string,object> {
169 { "PRINCIPAL", principalID.ToString() },
170 { "FOLDER", folderID.ToString() }
171 });
172
173 if (ret == null)
174 return null;
175 if (ret.Count == 0)
176 return null;
177
178 Dictionary<string,object> folders =
179 (Dictionary<string,object>)ret["FOLDERS"];
180 Dictionary<string,object> items =
181 (Dictionary<string,object>)ret["ITEMS"];
182
183 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
184 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
185 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
186 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
187 }
188 catch (Exception e)
189 {
190 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolderContent: {0}", e.Message);
191 }
179 192
180 return inventory; 193 return inventory;
181 } 194 }
182 195
183 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 196 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
184 { 197 {
185 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT", 198 Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
186 new Dictionary<string,object> { 199 new Dictionary<string,object> {
187 { "PRINCIPAL", principalID.ToString() }, 200 { "PRINCIPAL", principalID.ToString() },
188 { "FOLDER", folderID.ToString() } 201 { "FOLDER", folderID.ToString() }
@@ -190,17 +203,15 @@ namespace OpenSim.Services.Connectors
190 203
191 if (ret == null) 204 if (ret == null)
192 return null; 205 return null;
193
194 if (ret.Count == 0) 206 if (ret.Count == 0)
195 return null; 207 return null;
196 208
197 209 Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
198 List<InventoryItemBase> items = new List<InventoryItemBase>(); 210 List<InventoryItemBase> fitems = new List<InventoryItemBase>();
199 211 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
200 foreach (Object o in ret.Values) 212 fitems.Add(BuildItem((Dictionary<string, object>)o));
201 items.Add(BuildItem((Dictionary<string,object>)o));
202 213
203 return items; 214 return fitems;
204 } 215 }
205 216
206 public bool AddFolder(InventoryFolderBase folder) 217 public bool AddFolder(InventoryFolderBase folder)
@@ -244,7 +255,8 @@ namespace OpenSim.Services.Connectors
244 Dictionary<string,object> ret = MakeRequest("MOVEFOLDER", 255 Dictionary<string,object> ret = MakeRequest("MOVEFOLDER",
245 new Dictionary<string,object> { 256 new Dictionary<string,object> {
246 { "ParentID", folder.ParentID.ToString() }, 257 { "ParentID", folder.ParentID.ToString() },
247 { "ID", folder.ID.ToString() } 258 { "ID", folder.ID.ToString() },
259 { "PRINCIPAL", folder.Owner.ToString() }
248 }); 260 });
249 261
250 if (ret == null) 262 if (ret == null)
@@ -287,6 +299,8 @@ namespace OpenSim.Services.Connectors
287 299
288 public bool AddItem(InventoryItemBase item) 300 public bool AddItem(InventoryItemBase item)
289 { 301 {
302 if (item.CreatorData == null)
303 item.CreatorData = String.Empty;
290 Dictionary<string,object> ret = MakeRequest("ADDITEM", 304 Dictionary<string,object> ret = MakeRequest("ADDITEM",
291 new Dictionary<string,object> { 305 new Dictionary<string,object> {
292 { "AssetID", item.AssetID.ToString() }, 306 { "AssetID", item.AssetID.ToString() },
@@ -297,6 +311,7 @@ namespace OpenSim.Services.Connectors
297 { "InvType", item.InvType.ToString() }, 311 { "InvType", item.InvType.ToString() },
298 { "Folder", item.Folder.ToString() }, 312 { "Folder", item.Folder.ToString() },
299 { "CreatorId", item.CreatorId.ToString() }, 313 { "CreatorId", item.CreatorId.ToString() },
314 { "CreatorData", item.CreatorData.ToString() },
300 { "Description", item.Description.ToString() }, 315 { "Description", item.Description.ToString() },
301 { "NextPermissions", item.NextPermissions.ToString() }, 316 { "NextPermissions", item.NextPermissions.ToString() },
302 { "CurrentPermissions", item.CurrentPermissions.ToString() }, 317 { "CurrentPermissions", item.CurrentPermissions.ToString() },
@@ -319,6 +334,8 @@ namespace OpenSim.Services.Connectors
319 334
320 public bool UpdateItem(InventoryItemBase item) 335 public bool UpdateItem(InventoryItemBase item)
321 { 336 {
337 if (item.CreatorData == null)
338 item.CreatorData = String.Empty;
322 Dictionary<string,object> ret = MakeRequest("UPDATEITEM", 339 Dictionary<string,object> ret = MakeRequest("UPDATEITEM",
323 new Dictionary<string,object> { 340 new Dictionary<string,object> {
324 { "AssetID", item.AssetID.ToString() }, 341 { "AssetID", item.AssetID.ToString() },
@@ -329,6 +346,7 @@ namespace OpenSim.Services.Connectors
329 { "InvType", item.InvType.ToString() }, 346 { "InvType", item.InvType.ToString() },
330 { "Folder", item.Folder.ToString() }, 347 { "Folder", item.Folder.ToString() },
331 { "CreatorId", item.CreatorId.ToString() }, 348 { "CreatorId", item.CreatorId.ToString() },
349 { "CreatorData", item.CreatorData.ToString() },
332 { "Description", item.Description.ToString() }, 350 { "Description", item.Description.ToString() },
333 { "NextPermissions", item.NextPermissions.ToString() }, 351 { "NextPermissions", item.NextPermissions.ToString() },
334 { "CurrentPermissions", item.CurrentPermissions.ToString() }, 352 { "CurrentPermissions", item.CurrentPermissions.ToString() },
@@ -362,7 +380,7 @@ namespace OpenSim.Services.Connectors
362 380
363 Dictionary<string,object> ret = MakeRequest("MOVEITEMS", 381 Dictionary<string,object> ret = MakeRequest("MOVEITEMS",
364 new Dictionary<string,object> { 382 new Dictionary<string,object> {
365 { "PrincipalID", principalID.ToString() }, 383 { "PRINCIPAL", principalID.ToString() },
366 { "IDLIST", idlist }, 384 { "IDLIST", idlist },
367 { "DESTLIST", destlist } 385 { "DESTLIST", destlist }
368 }); 386 });
@@ -394,34 +412,50 @@ namespace OpenSim.Services.Connectors
394 412
395 public InventoryItemBase GetItem(InventoryItemBase item) 413 public InventoryItemBase GetItem(InventoryItemBase item)
396 { 414 {
397 Dictionary<string,object> ret = MakeRequest("GETITEM", 415 try
398 new Dictionary<string,object> { 416 {
417 Dictionary<string, object> ret = MakeRequest("GETITEM",
418 new Dictionary<string, object> {
399 { "ID", item.ID.ToString() } 419 { "ID", item.ID.ToString() }
400 }); 420 });
401 421
402 if (ret == null) 422 if (ret == null)
403 return null; 423 return null;
424 if (ret.Count == 0)
425 return null;
404 426
405 if (ret.Count == 0) 427 return BuildItem((Dictionary<string, object>)ret["item"]);
406 return null; 428 }
429 catch (Exception e)
430 {
431 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetItem: {0}", e.Message);
432 }
407 433
408 return BuildItem(ret); 434 return null;
409 } 435 }
410 436
411 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 437 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
412 { 438 {
413 Dictionary<string,object> ret = MakeRequest("GETFOLDER", 439 try
414 new Dictionary<string,object> { 440 {
441 Dictionary<string, object> ret = MakeRequest("GETFOLDER",
442 new Dictionary<string, object> {
415 { "ID", folder.ID.ToString() } 443 { "ID", folder.ID.ToString() }
416 }); 444 });
417 445
418 if (ret == null) 446 if (ret == null)
419 return null; 447 return null;
448 if (ret.Count == 0)
449 return null;
420 450
421 if (ret.Count == 0) 451 return BuildFolder((Dictionary<string, object>)ret["folder"]);
422 return null; 452 }
453 catch (Exception e)
454 {
455 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception in GetFolder: {0}", e.Message);
456 }
423 457
424 return BuildFolder(ret); 458 return null;
425 } 459 }
426 460
427 public List<InventoryItemBase> GetActiveGestures(UUID principalID) 461 public List<InventoryItemBase> GetActiveGestures(UUID principalID)
@@ -436,8 +470,8 @@ namespace OpenSim.Services.Connectors
436 470
437 List<InventoryItemBase> items = new List<InventoryItemBase>(); 471 List<InventoryItemBase> items = new List<InventoryItemBase>();
438 472
439 foreach (Object o in ret.Values) 473 foreach (Object o in ret.Values) // getting the values directly, we don't care about the keys item_i
440 items.Add(BuildItem((Dictionary<string,object>)o)); 474 items.Add(BuildItem((Dictionary<string, object>)o));
441 475
442 return items; 476 return items;
443 } 477 }
@@ -494,13 +528,20 @@ namespace OpenSim.Services.Connectors
494 { 528 {
495 InventoryFolderBase folder = new InventoryFolderBase(); 529 InventoryFolderBase folder = new InventoryFolderBase();
496 530
497 folder.ParentID = new UUID(data["ParentID"].ToString()); 531 try
498 folder.Type = short.Parse(data["Type"].ToString()); 532 {
499 folder.Version = ushort.Parse(data["Version"].ToString()); 533 folder.ParentID = new UUID(data["ParentID"].ToString());
500 folder.Name = data["Name"].ToString(); 534 folder.Type = short.Parse(data["Type"].ToString());
501 folder.Owner = new UUID(data["Owner"].ToString()); 535 folder.Version = ushort.Parse(data["Version"].ToString());
502 folder.ID = new UUID(data["ID"].ToString()); 536 folder.Name = data["Name"].ToString();
503 537 folder.Owner = new UUID(data["Owner"].ToString());
538 folder.ID = new UUID(data["ID"].ToString());
539 }
540 catch (Exception e)
541 {
542 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building folder: {0}", e.Message);
543 }
544
504 return folder; 545 return folder;
505 } 546 }
506 547
@@ -508,28 +549,40 @@ namespace OpenSim.Services.Connectors
508 { 549 {
509 InventoryItemBase item = new InventoryItemBase(); 550 InventoryItemBase item = new InventoryItemBase();
510 551
511 item.AssetID = new UUID(data["AssetID"].ToString()); 552 try
512 item.AssetType = int.Parse(data["AssetType"].ToString()); 553 {
513 item.Name = data["Name"].ToString(); 554 item.AssetID = new UUID(data["AssetID"].ToString());
514 item.Owner = new UUID(data["Owner"].ToString()); 555 item.AssetType = int.Parse(data["AssetType"].ToString());
515 item.ID = new UUID(data["ID"].ToString()); 556 item.Name = data["Name"].ToString();
516 item.InvType = int.Parse(data["InvType"].ToString()); 557 item.Owner = new UUID(data["Owner"].ToString());
517 item.Folder = new UUID(data["Folder"].ToString()); 558 item.ID = new UUID(data["ID"].ToString());
518 item.CreatorId = data["CreatorId"].ToString(); 559 item.InvType = int.Parse(data["InvType"].ToString());
519 item.Description = data["Description"].ToString(); 560 item.Folder = new UUID(data["Folder"].ToString());
520 item.NextPermissions = uint.Parse(data["NextPermissions"].ToString()); 561 item.CreatorId = data["CreatorId"].ToString();
521 item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString()); 562 if (data.ContainsKey("CreatorData"))
522 item.BasePermissions = uint.Parse(data["BasePermissions"].ToString()); 563 item.CreatorData = data["CreatorData"].ToString();
523 item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString()); 564 else
524 item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString()); 565 item.CreatorData = String.Empty;
525 item.GroupID = new UUID(data["GroupID"].ToString()); 566 item.Description = data["Description"].ToString();
526 item.GroupOwned = bool.Parse(data["GroupOwned"].ToString()); 567 item.NextPermissions = uint.Parse(data["NextPermissions"].ToString());
527 item.SalePrice = int.Parse(data["SalePrice"].ToString()); 568 item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString());
528 item.SaleType = byte.Parse(data["SaleType"].ToString()); 569 item.BasePermissions = uint.Parse(data["BasePermissions"].ToString());
529 item.Flags = uint.Parse(data["Flags"].ToString()); 570 item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString());
530 item.CreationDate = int.Parse(data["CreationDate"].ToString()); 571 item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString());
572 item.GroupID = new UUID(data["GroupID"].ToString());
573 item.GroupOwned = bool.Parse(data["GroupOwned"].ToString());
574 item.SalePrice = int.Parse(data["SalePrice"].ToString());
575 item.SaleType = byte.Parse(data["SaleType"].ToString());
576 item.Flags = uint.Parse(data["Flags"].ToString());
577 item.CreationDate = int.Parse(data["CreationDate"].ToString());
578 }
579 catch (Exception e)
580 {
581 m_log.DebugFormat("[XINVENTORY CONNECTOR STUB]: Exception building item: {0}", e.Message);
582 }
531 583
532 return item; 584 return item;
533 } 585 }
586
534 } 587 }
535} 588}
diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
index 06bc11c..833e22a 100644
--- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs
@@ -34,7 +34,6 @@ using System.Reflection;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Framework.Communications; 36using OpenSim.Framework.Communications;
37using OpenSim.Framework.Servers.HttpServer;
38using OpenSim.Services.Interfaces; 37using OpenSim.Services.Interfaces;
39using OpenMetaverse; 38using OpenMetaverse;
40using Nwc.XmlRpc; 39using Nwc.XmlRpc;
@@ -64,7 +63,7 @@ namespace OpenSim.Services.Connectors
64 m_GridService = gridServices; 63 m_GridService = gridServices;
65 } 64 }
66 65
67 public virtual LandData GetLandData(ulong regionHandle, uint x, uint y) 66 public virtual LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess)
68 { 67 {
69 LandData landData = null; 68 LandData landData = null;
70 Hashtable hash = new Hashtable(); 69 Hashtable hash = new Hashtable();
@@ -74,20 +73,20 @@ namespace OpenSim.Services.Connectors
74 73
75 IList paramList = new ArrayList(); 74 IList paramList = new ArrayList();
76 paramList.Add(hash); 75 paramList.Add(hash);
76 regionAccess = 42; // Default to adult. Better safe...
77 77
78 try 78 try
79 { 79 {
80 uint xpos = 0, ypos = 0; 80 uint xpos = 0, ypos = 0;
81 Utils.LongToUInts(regionHandle, out xpos, out ypos); 81 Utils.LongToUInts(regionHandle, out xpos, out ypos);
82 GridRegion info = m_GridService.GetRegionByPosition(UUID.Zero, (int)xpos, (int)ypos); 82 GridRegion info = m_GridService.GetRegionByPosition(scopeID, (int)xpos, (int)ypos);
83 if (info != null) // just to be sure 83 if (info != null) // just to be sure
84 { 84 {
85 XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); 85 XmlRpcRequest request = new XmlRpcRequest("land_data", paramList);
86 string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; 86 XmlRpcResponse response = request.Send(info.ServerURI, 10000);
87 XmlRpcResponse response = request.Send(uri, 10000);
88 if (response.IsFault) 87 if (response.IsFault)
89 { 88 {
90 m_log.ErrorFormat("[LAND CONNECTOR] remote call returned an error: {0}", response.FaultString); 89 m_log.ErrorFormat("[LAND CONNECTOR]: remote call returned an error: {0}", response.FaultString);
91 } 90 }
92 else 91 else
93 { 92 {
@@ -107,19 +106,25 @@ namespace OpenSim.Services.Connectors
107 landData.SalePrice = Convert.ToInt32(hash["SalePrice"]); 106 landData.SalePrice = Convert.ToInt32(hash["SalePrice"]);
108 landData.SnapshotID = new UUID((string)hash["SnapshotID"]); 107 landData.SnapshotID = new UUID((string)hash["SnapshotID"]);
109 landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]); 108 landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]);
110 m_log.DebugFormat("[OGS1 GRID SERVICES] Got land data for parcel {0}", landData.Name); 109 if (hash["RegionAccess"] != null)
110 regionAccess = (byte)Convert.ToInt32((string)hash["RegionAccess"]);
111 m_log.DebugFormat("[LAND CONNECTOR]: Got land data for parcel {0}", landData.Name);
111 } 112 }
112 catch (Exception e) 113 catch (Exception e)
113 { 114 {
114 m_log.Error("[LAND CONNECTOR] Got exception while parsing land-data:", e); 115 m_log.ErrorFormat(
116 "[LAND CONNECTOR]: Got exception while parsing land-data: {0} {1}",
117 e.Message, e.StackTrace);
115 } 118 }
116 } 119 }
117 } 120 }
118 else m_log.WarnFormat("[LAND CONNECTOR] Couldn't find region with handle {0}", regionHandle); 121 else
122 m_log.WarnFormat("[LAND CONNECTOR]: Couldn't find region with handle {0}", regionHandle);
119 } 123 }
120 catch (Exception e) 124 catch (Exception e)
121 { 125 {
122 m_log.ErrorFormat("[LAND CONNECTOR] Couldn't contact region {0}: {1}", regionHandle, e); 126 m_log.ErrorFormat(
127 "[LAND CONNECTOR]: Couldn't contact region {0}: {1} {2}", regionHandle, e.Message, e.StackTrace);
123 } 128 }
124 129
125 return landData; 130 return landData;
diff --git a/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs
new file mode 100644
index 0000000..e46714e
--- /dev/null
+++ b/OpenSim/Services/Connectors/MapImage/MapImageServiceConnector.cs
@@ -0,0 +1,158 @@
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.Net;
33using System.Reflection;
34
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Framework.Console;
38using OpenSim.Framework.Communications;
39using OpenSim.Server.Base;
40using OpenSim.Services.Interfaces;
41using OpenMetaverse;
42using OpenMetaverse.StructuredData;
43
44namespace OpenSim.Services.Connectors
45{
46 public class MapImageServicesConnector : IMapImageService
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 private string m_ServerURI = String.Empty;
53
54 public MapImageServicesConnector()
55 {
56 }
57
58 public MapImageServicesConnector(string serverURI)
59 {
60 m_ServerURI = serverURI.TrimEnd('/');
61 }
62
63 public MapImageServicesConnector(IConfigSource source)
64 {
65 Initialise(source);
66 }
67
68 public virtual void Initialise(IConfigSource source)
69 {
70 IConfig config = source.Configs["MapImageService"];
71 if (config == null)
72 {
73 m_log.Error("[MAP IMAGE CONNECTOR]: MapImageService missing");
74 throw new Exception("MapImage connector init error");
75 }
76
77 string serviceURI = config.GetString("MapImageServerURI",
78 String.Empty);
79
80 if (serviceURI == String.Empty)
81 {
82 m_log.Error("[MAP IMAGE CONNECTOR]: No Server URI named in section MapImageService");
83 throw new Exception("MapImage connector init error");
84 }
85 m_ServerURI = serviceURI;
86 m_ServerURI = serviceURI.TrimEnd('/');
87 }
88
89 public bool AddMapTile(int x, int y, byte[] jpgData, out string reason)
90 {
91 reason = string.Empty;
92 int tickstart = Util.EnvironmentTickCount();
93 Dictionary<string, object> sendData = new Dictionary<string, object>();
94 sendData["X"] = x.ToString();
95 sendData["Y"] = y.ToString();
96 sendData["TYPE"] = "image/jpeg";
97 sendData["DATA"] = Convert.ToBase64String(jpgData);
98
99 string reqString = ServerUtils.BuildQueryString(sendData);
100
101 try
102 {
103 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
104 m_ServerURI + "/map",
105 reqString);
106 if (reply != string.Empty)
107 {
108 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
109
110 if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "success"))
111 {
112 return true;
113 }
114 else if (replyData.ContainsKey("Result") && (replyData["Result"].ToString().ToLower() == "failure"))
115 {
116 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Registration failed: {0}", replyData["Message"].ToString());
117 reason = replyData["Message"].ToString();
118 return false;
119 }
120 else if (!replyData.ContainsKey("Result"))
121 {
122 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: reply data does not contain result field");
123 }
124 else
125 {
126 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: unexpected result {0}", replyData["Result"].ToString());
127 reason = "Unexpected result " + replyData["Result"].ToString();
128 }
129
130 }
131 else
132 {
133 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Map post received null reply");
134 }
135 }
136 catch (Exception e)
137 {
138 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: Exception when contacting grid server: {0}", e.Message);
139 }
140 finally
141 {
142 // This just dumps a warning for any operation that takes more than 100 ms
143 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
144 m_log.DebugFormat("[MAP IMAGE CONNECTOR]: map tile uploaded in {0}ms", tickdiff);
145 }
146
147 return false;
148
149 }
150
151 public byte[] GetMapTile(string fileName, out string format)
152 {
153 format = string.Empty;
154 new Exception("GetMapTile method not Implemented");
155 return null;
156 }
157 }
158}
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
index 0a982f8..888b072 100644
--- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
@@ -36,7 +36,6 @@ using System.Text;
36using Nini.Config; 36using Nini.Config;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Communications; 38using OpenSim.Framework.Communications;
39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Services.Interfaces; 39using OpenSim.Services.Interfaces;
41using OpenMetaverse; 40using OpenMetaverse;
42using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
@@ -71,7 +70,7 @@ namespace OpenSim.Services.Connectors
71 { 70 {
72 uint x = 0, y = 0; 71 uint x = 0, y = 0;
73 Utils.LongToUInts(regionHandle, out x, out y); 72 Utils.LongToUInts(regionHandle, out x, out y);
74 GridRegion regInfo = m_GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 73 GridRegion regInfo = m_GridService.GetRegionByPosition(thisRegion.ScopeID, (int)x, (int)y);
75 if ((regInfo != null) && 74 if ((regInfo != null) &&
76 // Don't remote-call this instance; that's a startup hickup 75 // Don't remote-call this instance; that's a startup hickup
77 !((regInfo.ExternalHostName == thisRegion.ExternalHostName) && (regInfo.HttpPort == thisRegion.HttpPort))) 76 !((regInfo.ExternalHostName == thisRegion.ExternalHostName) && (regInfo.HttpPort == thisRegion.HttpPort)))
@@ -87,13 +86,27 @@ namespace OpenSim.Services.Connectors
87 86
88 public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) 87 public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion)
89 { 88 {
90 string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; 89 string uri = region.ServerURI + "region/" + thisRegion.RegionID + "/";
91 //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); 90// m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
92 91
93 WebRequest HelloNeighbourRequest = WebRequest.Create(uri); 92 WebRequest helloNeighbourRequest;
94 HelloNeighbourRequest.Method = "POST"; 93
95 HelloNeighbourRequest.ContentType = "application/json"; 94 try
96 HelloNeighbourRequest.Timeout = 10000; 95 {
96 helloNeighbourRequest = WebRequest.Create(uri);
97 }
98 catch (Exception e)
99 {
100 m_log.WarnFormat(
101 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}",
102 uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
103
104 return false;
105 }
106
107 helloNeighbourRequest.Method = "POST";
108 helloNeighbourRequest.ContentType = "application/json";
109 helloNeighbourRequest.Timeout = 10000;
97 110
98 // Fill it in 111 // Fill it in
99 OSDMap args = null; 112 OSDMap args = null;
@@ -103,38 +116,48 @@ namespace OpenSim.Services.Connectors
103 } 116 }
104 catch (Exception e) 117 catch (Exception e)
105 { 118 {
106 m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message); 119 m_log.WarnFormat(
120 "[NEIGHBOUR SERVICE CONNCTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}",
121 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
122
107 return false; 123 return false;
108 } 124 }
125
109 // Add the regionhandle of the destination region 126 // Add the regionhandle of the destination region
110 args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString()); 127 args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString());
111 128
112 string strBuffer = ""; 129 string strBuffer = "";
113 byte[] buffer = new byte[1]; 130 byte[] buffer = new byte[1];
131
114 try 132 try
115 { 133 {
116 strBuffer = OSDParser.SerializeJsonString(args); 134 strBuffer = OSDParser.SerializeJsonString(args);
117 UTF8Encoding str = new UTF8Encoding(); 135 UTF8Encoding str = new UTF8Encoding();
118 buffer = str.GetBytes(strBuffer); 136 buffer = str.GetBytes(strBuffer);
119
120 } 137 }
121 catch (Exception e) 138 catch (Exception e)
122 { 139 {
123 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message); 140 m_log.WarnFormat(
141 "[NEIGHBOUR SERVICE CONNCTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}",
142 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
143
124 return false; 144 return false;
125 } 145 }
126 146
127 Stream os = null; 147 Stream os = null;
128 try 148 try
129 { // send the Post 149 { // send the Post
130 HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send 150 helloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
131 os = HelloNeighbourRequest.GetRequestStream(); 151 os = helloNeighbourRequest.GetRequestStream();
132 os.Write(buffer, 0, strBuffer.Length); //Send it 152 os.Write(buffer, 0, strBuffer.Length); //Send it
133 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri); 153 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
134 } 154 }
135 catch (Exception ex) 155 catch (Exception e)
136 { 156 {
137 m_log.InfoFormat("[REST COMMS]: Unable to send HelloNeighbour to {0}: {1}", region.RegionName, ex.Message); 157 m_log.WarnFormat(
158 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}",
159 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
160
138 return false; 161 return false;
139 } 162 }
140 finally 163 finally
@@ -149,10 +172,12 @@ namespace OpenSim.Services.Connectors
149 StreamReader sr = null; 172 StreamReader sr = null;
150 try 173 try
151 { 174 {
152 WebResponse webResponse = HelloNeighbourRequest.GetResponse(); 175 WebResponse webResponse = helloNeighbourRequest.GetResponse();
153 if (webResponse == null) 176 if (webResponse == null)
154 { 177 {
155 m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post"); 178 m_log.DebugFormat(
179 "[REST COMMS]: Null reply on DoHelloNeighbourCall post from {0} to {1}",
180 thisRegion.RegionName, region.RegionName);
156 } 181 }
157 182
158 sr = new StreamReader(webResponse.GetResponseStream()); 183 sr = new StreamReader(webResponse.GetResponseStream());
@@ -161,9 +186,12 @@ namespace OpenSim.Services.Connectors
161 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); 186 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
162 187
163 } 188 }
164 catch (Exception ex) 189 catch (Exception e)
165 { 190 {
166 m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message); 191 m_log.WarnFormat(
192 "[NEIGHBOUR SERVICE CONNCTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}",
193 region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace);
194
167 return false; 195 return false;
168 } 196 }
169 finally 197 finally
@@ -173,8 +201,6 @@ namespace OpenSim.Services.Connectors
173 } 201 }
174 202
175 return true; 203 return true;
176
177 } 204 }
178
179 } 205 }
180} 206} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
new file mode 100644
index 0000000..e16dc36
--- /dev/null
+++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs
@@ -0,0 +1,383 @@
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.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using OpenSim.Server.Base;
39using OpenMetaverse;
40
41namespace OpenSim.Services.Connectors
42{
43 public class PresenceServicesConnector : IPresenceService
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 PresenceServicesConnector()
52 {
53 }
54
55 public PresenceServicesConnector(string serverURI)
56 {
57 m_ServerURI = serverURI.TrimEnd('/');
58 }
59
60 public PresenceServicesConnector(IConfigSource source)
61 {
62 Initialise(source);
63 }
64
65 public virtual void Initialise(IConfigSource source)
66 {
67 IConfig gridConfig = source.Configs["PresenceService"];
68 if (gridConfig == null)
69 {
70 m_log.Error("[PRESENCE CONNECTOR]: PresenceService missing from OpenSim.ini");
71 throw new Exception("Presence connector init error");
72 }
73
74 string serviceURI = gridConfig.GetString("PresenceServerURI",
75 String.Empty);
76
77 if (serviceURI == String.Empty)
78 {
79 m_log.Error("[PRESENCE CONNECTOR]: No Server URI named in section PresenceService");
80 throw new Exception("Presence connector init error");
81 }
82 m_ServerURI = serviceURI;
83 }
84
85
86 #region IPresenceService
87
88 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
89 {
90 Dictionary<string, object> sendData = new Dictionary<string, object>();
91 //sendData["SCOPEID"] = scopeID.ToString();
92 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
93 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
94 sendData["METHOD"] = "login";
95
96 sendData["UserID"] = userID;
97 sendData["SessionID"] = sessionID.ToString();
98 sendData["SecureSessionID"] = secureSessionID.ToString();
99
100 string reqString = ServerUtils.BuildQueryString(sendData);
101 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
102 try
103 {
104 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
105 m_ServerURI + "/presence",
106 reqString);
107 if (reply != string.Empty)
108 {
109 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
110
111 if (replyData.ContainsKey("result"))
112 {
113 if (replyData["result"].ToString().ToLower() == "success")
114 return true;
115 else
116 return false;
117 }
118 else
119 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent reply data does not contain result field");
120
121 }
122 else
123 m_log.DebugFormat("[PRESENCE CONNECTOR]: LoginAgent received empty reply");
124 }
125 catch (Exception e)
126 {
127 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
128 }
129
130 return false;
131
132 }
133
134 public bool LogoutAgent(UUID sessionID)
135 {
136 Dictionary<string, object> sendData = new Dictionary<string, object>();
137 //sendData["SCOPEID"] = scopeID.ToString();
138 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
139 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
140 sendData["METHOD"] = "logout";
141
142 sendData["SessionID"] = sessionID.ToString();
143
144 string reqString = ServerUtils.BuildQueryString(sendData);
145 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
146 try
147 {
148 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
149 m_ServerURI + "/presence",
150 reqString);
151 if (reply != string.Empty)
152 {
153 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
154
155 if (replyData.ContainsKey("result"))
156 {
157 if (replyData["result"].ToString().ToLower() == "success")
158 return true;
159 else
160 return false;
161 }
162 else
163 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent reply data does not contain result field");
164
165 }
166 else
167 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutAgent received empty reply");
168 }
169 catch (Exception e)
170 {
171 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
172 }
173
174 return false;
175 }
176
177 public bool LogoutRegionAgents(UUID regionID)
178 {
179 Dictionary<string, object> sendData = new Dictionary<string, object>();
180 //sendData["SCOPEID"] = scopeID.ToString();
181 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
182 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
183 sendData["METHOD"] = "logoutregion";
184
185 sendData["RegionID"] = regionID.ToString();
186
187 string reqString = ServerUtils.BuildQueryString(sendData);
188 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
189 try
190 {
191 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
192 m_ServerURI + "/presence",
193 reqString);
194 if (reply != string.Empty)
195 {
196 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
197
198 if (replyData.ContainsKey("result"))
199 {
200 if (replyData["result"].ToString().ToLower() == "success")
201 return true;
202 else
203 return false;
204 }
205 else
206 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents reply data does not contain result field");
207
208 }
209 else
210 m_log.DebugFormat("[PRESENCE CONNECTOR]: LogoutRegionAgents received empty reply");
211 }
212 catch (Exception e)
213 {
214 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
215 }
216
217 return false;
218 }
219
220 public bool ReportAgent(UUID sessionID, UUID regionID)
221 {
222 Dictionary<string, object> sendData = new Dictionary<string, object>();
223 //sendData["SCOPEID"] = scopeID.ToString();
224 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
225 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
226 sendData["METHOD"] = "report";
227
228 sendData["SessionID"] = sessionID.ToString();
229 sendData["RegionID"] = regionID.ToString();
230
231 string reqString = ServerUtils.BuildQueryString(sendData);
232 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
233 try
234 {
235 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
236 m_ServerURI + "/presence",
237 reqString);
238 if (reply != string.Empty)
239 {
240 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
241
242 if (replyData.ContainsKey("result"))
243 {
244 if (replyData["result"].ToString().ToLower() == "success")
245 return true;
246 else
247 return false;
248 }
249 else
250 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent reply data does not contain result field");
251
252 }
253 else
254 m_log.DebugFormat("[PRESENCE CONNECTOR]: ReportAgent received empty reply");
255 }
256 catch (Exception e)
257 {
258 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
259 }
260
261 return false;
262 }
263
264 public PresenceInfo GetAgent(UUID sessionID)
265 {
266 Dictionary<string, object> sendData = new Dictionary<string, object>();
267 //sendData["SCOPEID"] = scopeID.ToString();
268 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
269 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
270 sendData["METHOD"] = "getagent";
271
272 sendData["SessionID"] = sessionID.ToString();
273
274 string reply = string.Empty;
275 string reqString = ServerUtils.BuildQueryString(sendData);
276 // m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
277 try
278 {
279 reply = SynchronousRestFormsRequester.MakeRequest("POST",
280 m_ServerURI + "/presence",
281 reqString);
282 if (reply == null || (reply != null && reply == string.Empty))
283 {
284 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgent received null or empty reply");
285 return null;
286 }
287 }
288 catch (Exception e)
289 {
290 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
291 }
292
293 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
294 PresenceInfo pinfo = null;
295
296 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
297 {
298 if (replyData["result"] is Dictionary<string, object>)
299 {
300 pinfo = new PresenceInfo((Dictionary<string, object>)replyData["result"]);
301 }
302 else
303 {
304 if (replyData["result"].ToString() == "null")
305 return null;
306
307 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString());
308 }
309 }
310 else
311 {
312 m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply received from presence server when querying for sessionID {0}", sessionID.ToString());
313 }
314
315 return pinfo;
316 }
317
318 public PresenceInfo[] GetAgents(string[] userIDs)
319 {
320 Dictionary<string, object> sendData = new Dictionary<string, object>();
321 //sendData["SCOPEID"] = scopeID.ToString();
322 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
323 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
324 sendData["METHOD"] = "getagents";
325
326 sendData["uuids"] = new List<string>(userIDs);
327
328 string reply = string.Empty;
329 string reqString = ServerUtils.BuildQueryString(sendData);
330 //m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString);
331 try
332 {
333 reply = SynchronousRestFormsRequester.MakeRequest("POST",
334 m_ServerURI + "/presence",
335 reqString);
336 if (reply == null || (reply != null && reply == string.Empty))
337 {
338 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null or empty reply");
339 return null;
340 }
341 }
342 catch (Exception e)
343 {
344 m_log.DebugFormat("[PRESENCE CONNECTOR]: Exception when contacting presence server: {0}", e.Message);
345 }
346
347 List<PresenceInfo> rinfos = new List<PresenceInfo>();
348
349 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
350
351 if (replyData != null)
352 {
353 if (replyData.ContainsKey("result") &&
354 (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure"))
355 {
356 return new PresenceInfo[0];
357 }
358
359 Dictionary<string, object>.ValueCollection pinfosList = replyData.Values;
360 //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count);
361 foreach (object presence in pinfosList)
362 {
363 if (presence is Dictionary<string, object>)
364 {
365 PresenceInfo pinfo = new PresenceInfo((Dictionary<string, object>)presence);
366 rinfos.Add(pinfo);
367 }
368 else
369 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received invalid response type {0}",
370 presence.GetType());
371 }
372 }
373 else
374 m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents received null response");
375
376 return rinfos.ToArray();
377 }
378
379
380 #endregion
381
382 }
383}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
new file mode 100644
index 0000000..2267325
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianActivityDetector.cs
@@ -0,0 +1,114 @@
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.Reflection;
30using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes;
32using OpenSim.Services.Interfaces;
33using OpenMetaverse;
34using log4net;
35
36namespace OpenSim.Services.Connectors.SimianGrid
37{
38 public class SimianActivityDetector
39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 private IGridUserService m_GridUserService;
43
44 public SimianActivityDetector(IGridUserService guService)
45 {
46 m_GridUserService = guService;
47 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Started");
48 }
49
50 public void AddRegion(Scene scene)
51 {
52 // For now the only events we listen to are these
53 // But we could trigger the position update more often
54 scene.EventManager.OnMakeRootAgent += OnMakeRootAgent;
55 scene.EventManager.OnNewClient += OnNewClient;
56 scene.EventManager.OnAvatarEnteringNewParcel += OnEnteringNewParcel;
57 }
58
59 public void RemoveRegion(Scene scene)
60 {
61 scene.EventManager.OnMakeRootAgent -= OnMakeRootAgent;
62 scene.EventManager.OnNewClient -= OnNewClient;
63 scene.EventManager.OnAvatarEnteringNewParcel -= OnEnteringNewParcel;
64 }
65
66 public void OnMakeRootAgent(ScenePresence sp)
67 {
68 m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
69 Util.FireAndForget(delegate(object o)
70 {
71 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
72 });
73 }
74
75 public void OnNewClient(IClientAPI client)
76 {
77 client.OnConnectionClosed += OnConnectionClose;
78 }
79
80 public void OnConnectionClose(IClientAPI client)
81 {
82 if (client.IsLoggingOut)
83 {
84 object sp = null;
85 Vector3 position = new Vector3(128, 128, 0);
86 Vector3 lookat = new Vector3(0, 1, 0);
87
88 if (client.Scene.TryGetScenePresence(client.AgentId, out sp))
89 {
90 if (sp is ScenePresence)
91 {
92 if (((ScenePresence)sp).IsChildAgent)
93 return;
94
95 position = ((ScenePresence)sp).AbsolutePosition;
96 lookat = ((ScenePresence)sp).Lookat;
97 }
98 }
99
100// m_log.DebugFormat("[SIMIAN ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
101 m_GridUserService.LoggedOut(client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, position, lookat);
102 }
103 }
104
105 void OnEnteringNewParcel(ScenePresence sp, int localLandID, UUID regionID)
106 {
107 // Asynchronously update the position stored in the session table for this agent
108 Util.FireAndForget(delegate(object o)
109 {
110 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
111 });
112 }
113 }
114}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
new file mode 100644
index 0000000..9573e21
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -0,0 +1,497 @@
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.Net;
32using System.Reflection;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42
43namespace OpenSim.Services.Connectors.SimianGrid
44{
45 /// <summary>
46 /// Connects to the SimianGrid asset service
47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class SimianAssetServiceConnector : IAssetService, ISharedRegionModule
50 {
51 private static readonly ILog m_log =
52 LogManager.GetLogger(
53 MethodBase.GetCurrentMethod().DeclaringType);
54 private static string ZeroID = UUID.Zero.ToString();
55
56 private string m_serverUrl = String.Empty;
57 private IImprovedAssetCache m_cache;
58 private bool m_Enabled = false;
59
60 #region ISharedRegionModule
61
62 public Type ReplaceableInterface { get { return null; } }
63 public void RegionLoaded(Scene scene)
64 {
65 if (m_cache == null)
66 {
67 IImprovedAssetCache cache = scene.RequestModuleInterface<IImprovedAssetCache>();
68 if (cache is ISharedRegionModule)
69 m_cache = cache;
70 }
71 }
72 public void PostInitialise() { }
73 public void Close() { }
74
75 public SimianAssetServiceConnector() { }
76 public string Name { get { return "SimianAssetServiceConnector"; } }
77 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAssetService>(this); } }
78 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAssetService>(this); } }
79
80 #endregion ISharedRegionModule
81
82 public SimianAssetServiceConnector(IConfigSource source)
83 {
84 CommonInit(source);
85 }
86
87 public SimianAssetServiceConnector(string url)
88 {
89 m_serverUrl = url;
90 }
91
92 public void Initialise(IConfigSource source)
93 {
94 IConfig moduleConfig = source.Configs["Modules"];
95 if (moduleConfig != null)
96 {
97 string name = moduleConfig.GetString("AssetServices", "");
98 if (name == Name)
99 CommonInit(source);
100 }
101 }
102
103 private void CommonInit(IConfigSource source)
104 {
105 IConfig gridConfig = source.Configs["AssetService"];
106 if (gridConfig != null)
107 {
108 string serviceUrl = gridConfig.GetString("AssetServerURI");
109 if (!String.IsNullOrEmpty(serviceUrl))
110 {
111 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
112 serviceUrl = serviceUrl + '/';
113 m_serverUrl = serviceUrl;
114 }
115 }
116
117 if (String.IsNullOrEmpty(m_serverUrl))
118 m_log.Info("[SIMIAN ASSET CONNECTOR]: No AssetServerURI specified, disabling connector");
119 else
120 m_Enabled = true;
121 }
122
123 #region IAssetService
124
125 public AssetBase Get(string id)
126 {
127 if (String.IsNullOrEmpty(m_serverUrl))
128 {
129 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
130 throw new InvalidOperationException();
131 }
132
133 // Cache fetch
134 if (m_cache != null)
135 {
136 AssetBase asset = m_cache.Get(id);
137 if (asset != null)
138 return asset;
139 }
140
141 return GetRemote(id);
142 }
143
144 public AssetBase GetCached(string id)
145 {
146 if (m_cache != null)
147 return m_cache.Get(id);
148
149 return null;
150 }
151
152 /// <summary>
153 /// Get an asset's metadata
154 /// </summary>
155 /// <param name="id"></param>
156 /// <returns></returns>
157 public AssetMetadata GetMetadata(string id)
158 {
159 if (String.IsNullOrEmpty(m_serverUrl))
160 {
161 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
162 throw new InvalidOperationException();
163 }
164
165 AssetMetadata metadata = null;
166
167 // Cache fetch
168 if (m_cache != null)
169 {
170 AssetBase asset = m_cache.Get(id);
171 if (asset != null)
172 return asset.Metadata;
173 }
174
175 Uri url;
176
177 // Determine if id is an absolute URL or a grid-relative UUID
178 if (!Uri.TryCreate(id, UriKind.Absolute, out url))
179 url = new Uri(m_serverUrl + id);
180
181 try
182 {
183 HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
184 request.Method = "HEAD";
185
186 using (WebResponse response = request.GetResponse())
187 {
188 using (Stream responseStream = response.GetResponseStream())
189 {
190 // Create the metadata object
191 metadata = new AssetMetadata();
192 metadata.ContentType = response.ContentType;
193 metadata.ID = id;
194
195 UUID uuid;
196 if (UUID.TryParse(id, out uuid))
197 metadata.FullID = uuid;
198
199 string lastModifiedStr = response.Headers.Get("Last-Modified");
200 if (!String.IsNullOrEmpty(lastModifiedStr))
201 {
202 DateTime lastModified;
203 if (DateTime.TryParse(lastModifiedStr, out lastModified))
204 metadata.CreationDate = lastModified;
205 }
206 }
207 }
208 }
209 catch (Exception ex)
210 {
211 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
212 }
213
214 return metadata;
215 }
216
217 public byte[] GetData(string id)
218 {
219 AssetBase asset = Get(id);
220
221 if (asset != null)
222 return asset.Data;
223
224 return null;
225 }
226
227 /// <summary>
228 /// Get an asset asynchronously
229 /// </summary>
230 /// <param name="id">The asset id</param>
231 /// <param name="sender">Represents the requester. Passed back via the handler</param>
232 /// <param name="handler">The handler to call back once the asset has been retrieved</param>
233 /// <returns>True if the id was parseable, false otherwise</returns>
234 public bool Get(string id, Object sender, AssetRetrieved handler)
235 {
236 if (String.IsNullOrEmpty(m_serverUrl))
237 {
238 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
239 throw new InvalidOperationException();
240 }
241
242 // Cache fetch
243 if (m_cache != null)
244 {
245 AssetBase asset = m_cache.Get(id);
246 if (asset != null)
247 {
248 handler(id, sender, asset);
249 return true;
250 }
251 }
252
253 Util.FireAndForget(
254 delegate(object o)
255 {
256 AssetBase asset = GetRemote(id);
257 handler(id, sender, asset);
258 }
259 );
260
261 return true;
262 }
263
264 /// <summary>
265 /// Creates a new asset
266 /// </summary>
267 /// Returns a random ID if none is passed into it
268 /// <param name="asset"></param>
269 /// <returns></returns>
270 public string Store(AssetBase asset)
271 {
272 if (String.IsNullOrEmpty(m_serverUrl))
273 {
274 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
275 throw new InvalidOperationException();
276 }
277
278 bool storedInCache = false;
279 string errorMessage = null;
280
281 // AssetID handling
282 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID)
283 {
284 asset.FullID = UUID.Random();
285 asset.ID = asset.FullID.ToString();
286 }
287
288 // Cache handling
289 if (m_cache != null)
290 {
291 m_cache.Cache(asset);
292 storedInCache = true;
293 }
294
295 // Local asset handling
296 if (asset.Local)
297 {
298 if (!storedInCache)
299 {
300 m_log.Error("Cannot store local " + asset.Metadata.ContentType + " asset without an asset cache");
301 asset.ID = null;
302 asset.FullID = UUID.Zero;
303 }
304
305 return asset.ID;
306 }
307
308 // Distinguish public and private assets
309 bool isPublic = true;
310 switch ((AssetType)asset.Type)
311 {
312 case AssetType.CallingCard:
313 case AssetType.Gesture:
314 case AssetType.LSLBytecode:
315 case AssetType.LSLText:
316 isPublic = false;
317 break;
318 }
319
320 // Make sure ContentType is set
321 if (String.IsNullOrEmpty(asset.Metadata.ContentType))
322 asset.Metadata.ContentType = SLUtil.SLAssetTypeToContentType(asset.Type);
323
324 // Build the remote storage request
325 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
326 {
327 new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
328 new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
329 new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
330 new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
331 new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
332 };
333
334 // Make the remote storage request
335 try
336 {
337 // Simian does not require the asset ID to be in the URL because it's in the post data.
338 // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
339 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
340
341 HttpWebResponse response = MultipartForm.Post(request, postParameters);
342 using (Stream responseStream = response.GetResponseStream())
343 {
344 string responseStr = null;
345
346 try
347 {
348 responseStr = responseStream.GetStreamString();
349 OSD responseOSD = OSDParser.Deserialize(responseStr);
350 if (responseOSD.Type == OSDType.Map)
351 {
352 OSDMap responseMap = (OSDMap)responseOSD;
353 if (responseMap["Success"].AsBoolean())
354 return asset.ID;
355 else
356 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
357 }
358 else
359 {
360 errorMessage = "Response format was invalid:\n" + responseStr;
361 }
362 }
363 catch (Exception ex)
364 {
365 if (!String.IsNullOrEmpty(responseStr))
366 errorMessage = "Failed to parse the response:\n" + responseStr;
367 else
368 errorMessage = "Failed to retrieve the response: " + ex.Message;
369 }
370 }
371 }
372 catch (WebException ex)
373 {
374 errorMessage = ex.Message;
375 }
376
377 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
378 asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
379 return null;
380 }
381
382 /// <summary>
383 /// Update an asset's content
384 /// </summary>
385 /// Attachments and bare scripts need this!!
386 /// <param name="id"> </param>
387 /// <param name="data"></param>
388 /// <returns></returns>
389 public bool UpdateContent(string id, byte[] data)
390 {
391 AssetBase asset = Get(id);
392
393 if (asset == null)
394 {
395 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset " + id + " for updating");
396 return false;
397 }
398
399 asset.Data = data;
400
401 string result = Store(asset);
402 return !String.IsNullOrEmpty(result);
403 }
404
405 /// <summary>
406 /// Delete an asset
407 /// </summary>
408 /// <param name="id"></param>
409 /// <returns></returns>
410 public bool Delete(string id)
411 {
412 if (String.IsNullOrEmpty(m_serverUrl))
413 {
414 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
415 throw new InvalidOperationException();
416 }
417
418 //string errorMessage = String.Empty;
419 string url = m_serverUrl + id;
420
421 if (m_cache != null)
422 m_cache.Expire(id);
423
424 try
425 {
426 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
427 request.Method = "DELETE";
428
429 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
430 {
431 if (response.StatusCode != HttpStatusCode.NoContent)
432 {
433 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Unexpected response when deleting asset " + url + ": " +
434 response.StatusCode + " (" + response.StatusDescription + ")");
435 }
436 }
437
438 return true;
439 }
440 catch (Exception ex)
441 {
442 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to delete asset " + id + " from the asset service: " + ex.Message);
443 return false;
444 }
445 }
446
447 #endregion IAssetService
448
449 private AssetBase GetRemote(string id)
450 {
451 AssetBase asset = null;
452 Uri url;
453
454 // Determine if id is an absolute URL or a grid-relative UUID
455 if (!Uri.TryCreate(id, UriKind.Absolute, out url))
456 url = new Uri(m_serverUrl + id);
457
458 try
459 {
460 HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
461
462 using (WebResponse response = request.GetResponse())
463 {
464 using (Stream responseStream = response.GetResponseStream())
465 {
466 string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
467
468 // Create the asset object
469 asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
470
471 UUID assetID;
472 if (UUID.TryParse(id, out assetID))
473 asset.FullID = assetID;
474
475 // Grab the asset data from the response stream
476 using (MemoryStream stream = new MemoryStream())
477 {
478 responseStream.CopyTo(stream, 4096);
479 asset.Data = stream.ToArray();
480 }
481 }
482 }
483
484 // Cache store
485 if (m_cache != null && asset != null)
486 m_cache.Cache(asset);
487
488 return asset;
489 }
490 catch (Exception ex)
491 {
492 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message);
493 return null;
494 }
495 }
496 }
497}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
new file mode 100644
index 0000000..69f6ed2
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs
@@ -0,0 +1,307 @@
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.Specialized;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
40
41namespace OpenSim.Services.Connectors.SimianGrid
42{
43 /// <summary>
44 /// Connects authentication/authorization to the SimianGrid backend
45 /// </summary>
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
47 public class SimianAuthenticationServiceConnector : IAuthenticationService, ISharedRegionModule
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private string m_serverUrl = String.Empty;
54 private bool m_Enabled = false;
55
56 #region ISharedRegionModule
57
58 public Type ReplaceableInterface { get { return null; } }
59 public void RegionLoaded(Scene scene) { }
60 public void PostInitialise() { }
61 public void Close() { }
62
63 public SimianAuthenticationServiceConnector() { }
64 public string Name { get { return "SimianAuthenticationServiceConnector"; } }
65 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAuthenticationService>(this); } }
66 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAuthenticationService>(this); } }
67
68 #endregion ISharedRegionModule
69
70 public SimianAuthenticationServiceConnector(IConfigSource source)
71 {
72 CommonInit(source);
73 }
74
75 public void Initialise(IConfigSource source)
76 {
77 IConfig moduleConfig = source.Configs["Modules"];
78 if (moduleConfig != null)
79 {
80 string name = moduleConfig.GetString("AuthenticationServices", "");
81 if (name == Name)
82 CommonInit(source);
83 }
84 }
85
86 private void CommonInit(IConfigSource source)
87 {
88 IConfig gridConfig = source.Configs["AuthenticationService"];
89 if (gridConfig != null)
90 {
91 string serviceUrl = gridConfig.GetString("AuthenticationServerURI");
92 if (!String.IsNullOrEmpty(serviceUrl))
93 {
94 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
95 serviceUrl = serviceUrl + '/';
96 m_serverUrl = serviceUrl;
97 m_Enabled = true;
98 }
99 }
100
101 if (String.IsNullOrEmpty(m_serverUrl))
102 m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector");
103 }
104
105 public string Authenticate(UUID principalID, string password, int lifetime)
106 {
107 NameValueCollection requestArgs = new NameValueCollection
108 {
109 { "RequestMethod", "GetIdentities" },
110 { "UserID", principalID.ToString() }
111 };
112
113 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
114 if (response["Success"].AsBoolean() && response["Identities"] is OSDArray)
115 {
116 bool md5hashFound = false;
117
118 OSDArray identities = (OSDArray)response["Identities"];
119 for (int i = 0; i < identities.Count; i++)
120 {
121 OSDMap identity = identities[i] as OSDMap;
122 if (identity != null)
123 {
124 if (identity["Type"].AsString() == "md5hash")
125 {
126 string authorizeResult;
127 if (CheckPassword(principalID, password, identity["Credential"].AsString(), out authorizeResult))
128 return authorizeResult;
129
130 md5hashFound = true;
131 break;
132 }
133 }
134 }
135
136 if (!md5hashFound)
137 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + principalID + ", no md5hash identity found");
138 }
139 else
140 {
141 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to retrieve identities for " + principalID + ": " +
142 response["Message"].AsString());
143 }
144
145 return String.Empty;
146 }
147
148 public bool Verify(UUID principalID, string token, int lifetime)
149 {
150 NameValueCollection requestArgs = new NameValueCollection
151 {
152 { "RequestMethod", "GetSession" },
153 { "SessionID", token }
154 };
155
156 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
157 if (response["Success"].AsBoolean())
158 {
159 return true;
160 }
161 else
162 {
163 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Could not verify session for " + principalID + ": " +
164 response["Message"].AsString());
165 }
166
167 return false;
168 }
169
170 public bool Release(UUID principalID, string token)
171 {
172 NameValueCollection requestArgs = new NameValueCollection
173 {
174 { "RequestMethod", "RemoveSession" },
175 { "UserID", principalID.ToString() }
176 };
177
178 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
179 if (response["Success"].AsBoolean())
180 {
181 return true;
182 }
183 else
184 {
185 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to remove session for " + principalID + ": " +
186 response["Message"].AsString());
187 }
188
189 return false;
190 }
191
192 public bool SetPassword(UUID principalID, string passwd)
193 {
194 // Fetch the user name first
195 NameValueCollection requestArgs = new NameValueCollection
196 {
197 { "RequestMethod", "GetUser" },
198 { "UserID", principalID.ToString() }
199 };
200
201 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
202 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
203 {
204 OSDMap userMap = (OSDMap)response["User"];
205 string identifier = userMap["Name"].AsString();
206
207 if (!String.IsNullOrEmpty(identifier))
208 {
209 // Add/update the md5hash identity
210 // TODO: Support salts when AddIdentity does
211 // TODO: Create an a1hash too for WebDAV logins
212 requestArgs = new NameValueCollection
213 {
214 { "RequestMethod", "AddIdentity" },
215 { "Identifier", identifier },
216 { "Credential", "$1$" + Utils.MD5String(passwd) },
217 { "Type", "md5hash" },
218 { "UserID", principalID.ToString() }
219 };
220
221 response = WebUtil.PostToService(m_serverUrl, requestArgs);
222 bool success = response["Success"].AsBoolean();
223
224 if (!success)
225 m_log.WarnFormat("[SIMIAN AUTH CONNECTOR]: Failed to set password for {0} ({1})", identifier, principalID);
226
227 return success;
228 }
229 }
230 else
231 {
232 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Failed to retrieve identities for " + principalID + ": " +
233 response["Message"].AsString());
234 }
235
236 return false;
237 }
238
239 public AuthInfo GetAuthInfo(UUID principalID)
240 {
241 throw new NotImplementedException();
242 }
243
244 public bool SetAuthInfo(AuthInfo info)
245 {
246 throw new NotImplementedException();
247 }
248
249 private bool CheckPassword(UUID userID, string password, string simianGridCredential, out string authorizeResult)
250 {
251 if (simianGridCredential.Contains(":"))
252 {
253 // Salted version
254 int idx = simianGridCredential.IndexOf(':');
255 string finalhash = simianGridCredential.Substring(0, idx);
256 string salt = simianGridCredential.Substring(idx + 1);
257
258 if (finalhash == Utils.MD5String(password + ":" + salt))
259 {
260 authorizeResult = Authorize(userID);
261 return true;
262 }
263 else
264 {
265 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + userID +
266 " using md5hash " + Utils.MD5String(password) + ":" + salt);
267 }
268 }
269 else
270 {
271 // Unsalted version
272 if (password == simianGridCredential ||
273 "$1$" + password == simianGridCredential ||
274 "$1$" + Utils.MD5String(password) == simianGridCredential ||
275 Utils.MD5String(password) == simianGridCredential ||
276 "$1$" + Utils.MD5String(password + ":") == simianGridCredential)
277 {
278 authorizeResult = Authorize(userID);
279 return true;
280 }
281 else
282 {
283 m_log.Warn("[SIMIAN AUTH CONNECTOR]: Authentication failed for " + userID +
284 " using md5hash $1$" + Utils.MD5String(password));
285 }
286 }
287
288 authorizeResult = null;
289 return false;
290 }
291
292 private string Authorize(UUID userID)
293 {
294 NameValueCollection requestArgs = new NameValueCollection
295 {
296 { "RequestMethod", "AddSession" },
297 { "UserID", userID.ToString() }
298 };
299
300 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
301 if (response["Success"].AsBoolean())
302 return response["SessionID"].AsUUID().ToString();
303 else
304 return String.Empty;
305 }
306 }
307}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
new file mode 100644
index 0000000..360f0dd
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs
@@ -0,0 +1,344 @@
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.Collections.Specialized;
31// DEBUG ON
32using System.Diagnostics;
33// DEBUG OFF
34using System.Reflection;
35using log4net;
36using Mono.Addins;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42using OpenMetaverse;
43using OpenMetaverse.StructuredData;
44
45namespace OpenSim.Services.Connectors.SimianGrid
46{
47 /// <summary>
48 /// Connects avatar appearance data to the SimianGrid backend
49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class SimianAvatarServiceConnector : IAvatarService, ISharedRegionModule
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56// private static string ZeroID = UUID.Zero.ToString();
57
58 private string m_serverUrl = String.Empty;
59 private bool m_Enabled = false;
60
61 #region ISharedRegionModule
62
63 public Type ReplaceableInterface { get { return null; } }
64 public void RegionLoaded(Scene scene) { }
65 public void PostInitialise() { }
66 public void Close() { }
67
68 public SimianAvatarServiceConnector() { }
69 public string Name { get { return "SimianAvatarServiceConnector"; } }
70 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IAvatarService>(this); } }
71 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IAvatarService>(this); } }
72
73 #endregion ISharedRegionModule
74
75 public SimianAvatarServiceConnector(IConfigSource source)
76 {
77 CommonInit(source);
78 }
79
80 public void Initialise(IConfigSource source)
81 {
82 IConfig moduleConfig = source.Configs["Modules"];
83 if (moduleConfig != null)
84 {
85 string name = moduleConfig.GetString("AvatarServices", "");
86 if (name == Name)
87 CommonInit(source);
88 }
89 }
90
91 private void CommonInit(IConfigSource source)
92 {
93 IConfig gridConfig = source.Configs["AvatarService"];
94 if (gridConfig != null)
95 {
96 string serviceUrl = gridConfig.GetString("AvatarServerURI");
97 if (!String.IsNullOrEmpty(serviceUrl))
98 {
99 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
100 serviceUrl = serviceUrl + '/';
101 m_serverUrl = serviceUrl;
102 m_Enabled = true;
103 }
104 }
105
106 if (String.IsNullOrEmpty(m_serverUrl))
107 m_log.Info("[SIMIAN AVATAR CONNECTOR]: No AvatarServerURI specified, disabling connector");
108 }
109
110 #region IAvatarService
111
112 // <summary>
113 // Retrieves the LLPackedAppearance field from user data and unpacks
114 // it into an AvatarAppearance structure
115 // </summary>
116 // <param name="userID"></param>
117 public AvatarAppearance GetAppearance(UUID userID)
118 {
119 NameValueCollection requestArgs = new NameValueCollection
120 {
121 { "RequestMethod", "GetUser" },
122 { "UserID", userID.ToString() }
123 };
124
125 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
126 if (response["Success"].AsBoolean())
127 {
128 OSDMap map = null;
129 try { map = OSDParser.DeserializeJson(response["LLPackedAppearance"].AsString()) as OSDMap; }
130 catch { }
131
132 if (map != null)
133 {
134 AvatarAppearance appearance = new AvatarAppearance(map);
135// DEBUG ON
136 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR] retrieved appearance for {0}:\n{1}",userID,appearance.ToString());
137// DEBUG OFF
138 return appearance;
139 }
140
141 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to decode appearance for {0}",userID);
142 return null;
143 }
144
145 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to get appearance for {0}: {1}",
146 userID,response["Message"].AsString());
147 return null;
148 }
149
150 // <summary>
151 // </summary>
152 // <param name=""></param>
153 public bool SetAppearance(UUID userID, AvatarAppearance appearance)
154 {
155 OSDMap map = appearance.Pack();
156 if (map == null)
157 {
158 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to encode appearance for {0}",userID);
159 return false;
160 }
161
162 // m_log.DebugFormat("[SIMIAN AVATAR CONNECTOR] save appearance for {0}",userID);
163
164 NameValueCollection requestArgs = new NameValueCollection
165 {
166 { "RequestMethod", "AddUserData" },
167 { "UserID", userID.ToString() },
168 { "LLPackedAppearance", OSDParser.SerializeJsonString(map) }
169 };
170
171 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
172 bool success = response["Success"].AsBoolean();
173
174 if (! success)
175 m_log.WarnFormat("[SIMIAN AVATAR CONNECTOR]: Failed to save appearance for {0}: {1}",
176 userID,response["Message"].AsString());
177
178 return success;
179 }
180
181 // <summary>
182 // </summary>
183 // <param name=""></param>
184 public AvatarData GetAvatar(UUID userID)
185 {
186 NameValueCollection requestArgs = new NameValueCollection
187 {
188 { "RequestMethod", "GetUser" },
189 { "UserID", userID.ToString() }
190 };
191
192 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
193 if (response["Success"].AsBoolean())
194 {
195 OSDMap map = null;
196 try { map = OSDParser.DeserializeJson(response["LLAppearance"].AsString()) as OSDMap; }
197 catch { }
198
199 if (map != null)
200 {
201 AvatarWearable[] wearables = new AvatarWearable[13];
202 wearables[0] = new AvatarWearable(map["ShapeItem"].AsUUID(), map["ShapeAsset"].AsUUID());
203 wearables[1] = new AvatarWearable(map["SkinItem"].AsUUID(), map["SkinAsset"].AsUUID());
204 wearables[2] = new AvatarWearable(map["HairItem"].AsUUID(), map["HairAsset"].AsUUID());
205 wearables[3] = new AvatarWearable(map["EyesItem"].AsUUID(), map["EyesAsset"].AsUUID());
206 wearables[4] = new AvatarWearable(map["ShirtItem"].AsUUID(), map["ShirtAsset"].AsUUID());
207 wearables[5] = new AvatarWearable(map["PantsItem"].AsUUID(), map["PantsAsset"].AsUUID());
208 wearables[6] = new AvatarWearable(map["ShoesItem"].AsUUID(), map["ShoesAsset"].AsUUID());
209 wearables[7] = new AvatarWearable(map["SocksItem"].AsUUID(), map["SocksAsset"].AsUUID());
210 wearables[8] = new AvatarWearable(map["JacketItem"].AsUUID(), map["JacketAsset"].AsUUID());
211 wearables[9] = new AvatarWearable(map["GlovesItem"].AsUUID(), map["GlovesAsset"].AsUUID());
212 wearables[10] = new AvatarWearable(map["UndershirtItem"].AsUUID(), map["UndershirtAsset"].AsUUID());
213 wearables[11] = new AvatarWearable(map["UnderpantsItem"].AsUUID(), map["UnderpantsAsset"].AsUUID());
214 wearables[12] = new AvatarWearable(map["SkirtItem"].AsUUID(), map["SkirtAsset"].AsUUID());
215
216 AvatarAppearance appearance = new AvatarAppearance();
217 appearance.Wearables = wearables;
218 appearance.AvatarHeight = (float)map["Height"].AsReal();
219
220 AvatarData avatar = new AvatarData(appearance);
221
222 // Get attachments
223 map = null;
224 try { map = OSDParser.DeserializeJson(response["LLAttachments"].AsString()) as OSDMap; }
225 catch { }
226
227 if (map != null)
228 {
229 foreach (KeyValuePair<string, OSD> kvp in map)
230 avatar.Data[kvp.Key] = kvp.Value.AsString();
231 }
232
233 return avatar;
234 }
235 else
236 {
237 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed to get user appearance for " + userID +
238 ", LLAppearance is missing or invalid");
239 return null;
240 }
241 }
242 else
243 {
244 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed to get user appearance for " + userID + ": " +
245 response["Message"].AsString());
246 }
247
248 return null;
249 }
250
251 // <summary>
252 // </summary>
253 // <param name=""></param>
254 public bool SetAvatar(UUID userID, AvatarData avatar)
255 {
256 m_log.Debug("[SIMIAN AVATAR CONNECTOR]: SetAvatar called for " + userID);
257
258 if (avatar.AvatarType == 1) // LLAvatar
259 {
260 AvatarAppearance appearance = avatar.ToAvatarAppearance();
261
262 OSDMap map = new OSDMap();
263
264 map["Height"] = OSD.FromReal(appearance.AvatarHeight);
265
266 map["BodyItem"] = appearance.Wearables[AvatarWearable.BODY][0].ItemID.ToString();
267 map["EyesItem"] = appearance.Wearables[AvatarWearable.EYES][0].ItemID.ToString();
268 map["GlovesItem"] = appearance.Wearables[AvatarWearable.GLOVES][0].ItemID.ToString();
269 map["HairItem"] = appearance.Wearables[AvatarWearable.HAIR][0].ItemID.ToString();
270 map["JacketItem"] = appearance.Wearables[AvatarWearable.JACKET][0].ItemID.ToString();
271 map["PantsItem"] = appearance.Wearables[AvatarWearable.PANTS][0].ItemID.ToString();
272 map["ShirtItem"] = appearance.Wearables[AvatarWearable.SHIRT][0].ItemID.ToString();
273 map["ShoesItem"] = appearance.Wearables[AvatarWearable.SHOES][0].ItemID.ToString();
274 map["SkinItem"] = appearance.Wearables[AvatarWearable.SKIN][0].ItemID.ToString();
275 map["SkirtItem"] = appearance.Wearables[AvatarWearable.SKIRT][0].ItemID.ToString();
276 map["SocksItem"] = appearance.Wearables[AvatarWearable.SOCKS][0].ItemID.ToString();
277 map["UnderPantsItem"] = appearance.Wearables[AvatarWearable.UNDERPANTS][0].ItemID.ToString();
278 map["UnderShirtItem"] = appearance.Wearables[AvatarWearable.UNDERSHIRT][0].ItemID.ToString();
279 map["BodyAsset"] = appearance.Wearables[AvatarWearable.BODY][0].AssetID.ToString();
280 map["EyesAsset"] = appearance.Wearables[AvatarWearable.EYES][0].AssetID.ToString();
281 map["GlovesAsset"] = appearance.Wearables[AvatarWearable.GLOVES][0].AssetID.ToString();
282 map["HairAsset"] = appearance.Wearables[AvatarWearable.HAIR][0].AssetID.ToString();
283 map["JacketAsset"] = appearance.Wearables[AvatarWearable.JACKET][0].AssetID.ToString();
284 map["PantsAsset"] = appearance.Wearables[AvatarWearable.PANTS][0].AssetID.ToString();
285 map["ShirtAsset"] = appearance.Wearables[AvatarWearable.SHIRT][0].AssetID.ToString();
286 map["ShoesAsset"] = appearance.Wearables[AvatarWearable.SHOES][0].AssetID.ToString();
287 map["SkinAsset"] = appearance.Wearables[AvatarWearable.SKIN][0].AssetID.ToString();
288 map["SkirtAsset"] = appearance.Wearables[AvatarWearable.SKIRT][0].AssetID.ToString();
289 map["SocksAsset"] = appearance.Wearables[AvatarWearable.SOCKS][0].AssetID.ToString();
290 map["UnderPantsAsset"] = appearance.Wearables[AvatarWearable.UNDERPANTS][0].AssetID.ToString();
291 map["UnderShirtAsset"] = appearance.Wearables[AvatarWearable.UNDERSHIRT][0].AssetID.ToString();
292
293
294 OSDMap items = new OSDMap();
295 foreach (KeyValuePair<string, string> kvp in avatar.Data)
296 {
297 if (kvp.Key.StartsWith("_ap_"))
298 items.Add(kvp.Key, OSD.FromString(kvp.Value));
299 }
300
301 NameValueCollection requestArgs = new NameValueCollection
302 {
303 { "RequestMethod", "AddUserData" },
304 { "UserID", userID.ToString() },
305 { "LLAppearance", OSDParser.SerializeJsonString(map) },
306 { "LLAttachments", OSDParser.SerializeJsonString(items) }
307 };
308
309 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
310 bool success = response["Success"].AsBoolean();
311
312 if (!success)
313 m_log.Warn("[SIMIAN AVATAR CONNECTOR]: Failed saving appearance for " + userID + ": " + response["Message"].AsString());
314
315 return success;
316 }
317 else
318 {
319 m_log.Error("[SIMIAN AVATAR CONNECTOR]: Can't save appearance for " + userID + ". Unhandled avatar type " + avatar.AvatarType);
320 return false;
321 }
322 }
323
324 public bool ResetAvatar(UUID userID)
325 {
326 m_log.Error("[SIMIAN AVATAR CONNECTOR]: ResetAvatar called for " + userID + ", implement this");
327 return false;
328 }
329
330 public bool SetItems(UUID userID, string[] names, string[] values)
331 {
332 m_log.Error("[SIMIAN AVATAR CONNECTOR]: SetItems called for " + userID + " with " + names.Length + " names and " + values.Length + " values, implement this");
333 return false;
334 }
335
336 public bool RemoveItems(UUID userID, string[] names)
337 {
338 m_log.Error("[SIMIAN AVATAR CONNECTOR]: RemoveItems called for " + userID + " with " + names.Length + " names, implement this");
339 return false;
340 }
341
342 #endregion IAvatarService
343 }
344}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
new file mode 100644
index 0000000..7422d94
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianFriendsServiceConnector.cs
@@ -0,0 +1,236 @@
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.Collections.Specialized;
31using System.Reflection;
32using log4net;
33using Nini.Config;
34using OpenMetaverse;
35using OpenMetaverse.StructuredData;
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38
39using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
40
41namespace OpenSim.Services.Connectors.SimianGrid
42{
43 /// <summary>
44 /// Stores and retrieves friend lists from the SimianGrid backend
45 /// </summary>
46 public class SimianFriendsServiceConnector : IFriendsService
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 private string m_serverUrl = String.Empty;
53
54 public SimianFriendsServiceConnector(IConfigSource source)
55 {
56 Initialise(source);
57 }
58
59 public void Initialise(IConfigSource source)
60 {
61 IConfig gridConfig = source.Configs["FriendsService"];
62 if (gridConfig != null)
63 {
64 string serviceUrl = gridConfig.GetString("FriendsServerURI");
65 if (!String.IsNullOrEmpty(serviceUrl))
66 {
67 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
68 serviceUrl = serviceUrl + '/';
69 m_serverUrl = serviceUrl;
70 }
71 }
72
73 if (String.IsNullOrEmpty(m_serverUrl))
74 m_log.Info("[SIMIAN FRIENDS CONNECTOR]: No FriendsServerURI specified, disabling connector");
75 }
76
77 #region IFriendsService
78
79 public FriendInfo[] GetFriends(UUID principalID)
80 {
81 return GetFriends(principalID.ToString());
82 }
83
84 public FriendInfo[] GetFriends(string principalID)
85 {
86 if (String.IsNullOrEmpty(m_serverUrl))
87 return new FriendInfo[0];
88
89 Dictionary<UUID, FriendInfo> friends = new Dictionary<UUID, FriendInfo>();
90
91 OSDArray friendsArray = GetFriended(principalID);
92 OSDArray friendedMeArray = GetFriendedBy(principalID);
93
94 // Load the list of friends and their granted permissions
95 for (int i = 0; i < friendsArray.Count; i++)
96 {
97 OSDMap friendEntry = friendsArray[i] as OSDMap;
98 if (friendEntry != null)
99 {
100 UUID friendID = friendEntry["Key"].AsUUID();
101
102 FriendInfo friend = new FriendInfo();
103 if (!UUID.TryParse(principalID, out friend.PrincipalID))
104 {
105 string tmp = string.Empty;
106 if (!Util.ParseUniversalUserIdentifier(principalID, out friend.PrincipalID, out tmp, out tmp, out tmp, out tmp))
107 // bad record. ignore this entry
108 continue;
109 }
110
111 friend.Friend = friendID.ToString();
112 friend.MyFlags = friendEntry["Value"].AsInteger();
113 friend.TheirFlags = -1;
114
115 friends[friendID] = friend;
116 }
117 }
118
119 // Load the permissions those friends have granted to this user
120 for (int i = 0; i < friendedMeArray.Count; i++)
121 {
122 OSDMap friendedMeEntry = friendedMeArray[i] as OSDMap;
123 if (friendedMeEntry != null)
124 {
125 UUID friendID = friendedMeEntry["OwnerID"].AsUUID();
126
127 FriendInfo friend;
128 if (friends.TryGetValue(friendID, out friend))
129 friend.TheirFlags = friendedMeEntry["Value"].AsInteger();
130 }
131 }
132
133 // Convert the dictionary of friends to an array and return it
134 FriendInfo[] array = new FriendInfo[friends.Count];
135 int j = 0;
136 foreach (FriendInfo friend in friends.Values)
137 array[j++] = friend;
138
139 return array;
140 }
141
142 public bool StoreFriend(string principalID, string friend, int flags)
143 {
144 if (String.IsNullOrEmpty(m_serverUrl))
145 return true;
146
147 NameValueCollection requestArgs = new NameValueCollection
148 {
149 { "RequestMethod", "AddGeneric" },
150 { "OwnerID", principalID.ToString() },
151 { "Type", "Friend" },
152 { "Key", friend },
153 { "Value", flags.ToString() }
154 };
155
156 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
157 bool success = response["Success"].AsBoolean();
158
159 if (!success)
160 m_log.Error("[SIMIAN FRIENDS CONNECTOR]: Failed to store friend " + friend + " for user " + principalID + ": " + response["Message"].AsString());
161
162 return success;
163 }
164
165 public bool Delete(UUID principalID, string friend)
166 {
167 return Delete(principalID.ToString(), friend);
168 }
169
170 public bool Delete(string principalID, string friend)
171 {
172 if (String.IsNullOrEmpty(m_serverUrl))
173 return true;
174
175 NameValueCollection requestArgs = new NameValueCollection
176 {
177 { "RequestMethod", "RemoveGeneric" },
178 { "OwnerID", principalID.ToString() },
179 { "Type", "Friend" },
180 { "Key", friend }
181 };
182
183 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
184 bool success = response["Success"].AsBoolean();
185
186 if (!success)
187 m_log.Error("[SIMIAN FRIENDS CONNECTOR]: Failed to remove friend " + friend + " for user " + principalID + ": " + response["Message"].AsString());
188
189 return success;
190 }
191
192 #endregion IFriendsService
193
194 private OSDArray GetFriended(string ownerID)
195 {
196 NameValueCollection requestArgs = new NameValueCollection
197 {
198 { "RequestMethod", "GetGenerics" },
199 { "OwnerID", ownerID.ToString() },
200 { "Type", "Friend" }
201 };
202
203 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
204 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
205 {
206 return (OSDArray)response["Entries"];
207 }
208 else
209 {
210 m_log.Warn("[SIMIAN FRIENDS CONNECTOR]: Failed to retrieve friends for user " + ownerID + ": " + response["Message"].AsString());
211 return new OSDArray(0);
212 }
213 }
214
215 private OSDArray GetFriendedBy(string ownerID)
216 {
217 NameValueCollection requestArgs = new NameValueCollection
218 {
219 { "RequestMethod", "GetGenerics" },
220 { "Key", ownerID.ToString() },
221 { "Type", "Friend" }
222 };
223
224 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
225 if (response["Success"].AsBoolean() && response["Entries"] is OSDArray)
226 {
227 return (OSDArray)response["Entries"];
228 }
229 else
230 {
231 m_log.Warn("[SIMIAN FRIENDS CONNECTOR]: Failed to retrieve reverse friends for user " + ownerID + ": " + response["Message"].AsString());
232 return new OSDArray(0);
233 }
234 }
235 }
236}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
new file mode 100644
index 0000000..847319c
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGrid.cs
@@ -0,0 +1,33 @@
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 Mono.Addins;
30using Nini.Config;
31
32[assembly: Addin("SimianGrid", "1.0")]
33[assembly: AddinDependency("OpenSim", "0.5")]
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
new file mode 100644
index 0000000..93fdae3
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridMaptileModule.cs
@@ -0,0 +1,262 @@
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.Reflection;
31using System.Net;
32using System.IO;
33using System.Timers;
34using System.Drawing;
35using System.Drawing.Imaging;
36
37using log4net;
38using Mono.Addins;
39using Nini.Config;
40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using OpenMetaverse;
44using OpenMetaverse.StructuredData;
45
46namespace OpenSim.Region.OptionalModules.Simian
47{
48 /// <summary>
49 /// </summary>
50 /// <remarks>
51 /// </remarks>
52
53 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SimianGridMaptile")]
54 public class SimianGridMaptile : ISharedRegionModule
55 {
56 private static readonly ILog m_log =
57 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58
59 private bool m_enabled = false;
60 private string m_serverUrl = String.Empty;
61 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
62
63 private int m_refreshtime = 0;
64 private int m_lastrefresh = 0;
65 private System.Timers.Timer m_refreshTimer = new System.Timers.Timer();
66
67 #region ISharedRegionModule
68
69 public Type ReplaceableInterface { get { return null; } }
70 public string Name { get { return "SimianGridMaptile"; } }
71 public void RegionLoaded(Scene scene) { }
72 public void Close() { }
73
74 ///<summary>
75 ///
76 ///</summary>
77 public void Initialise(IConfigSource source)
78 {
79 IConfig config = source.Configs["SimianGridMaptiles"];
80 if (config == null)
81 return;
82
83 if (! config.GetBoolean("Enabled", false))
84 return;
85
86 m_serverUrl = config.GetString("MaptileURL");
87 if (String.IsNullOrEmpty(m_serverUrl))
88 return;
89
90 int refreshseconds = Convert.ToInt32(config.GetString("RefreshTime"));
91 if (refreshseconds <= 0)
92 return;
93
94 m_refreshtime = refreshseconds * 1000; // convert from seconds to ms
95 m_log.InfoFormat("[SIMIAN MAPTILE] enabled with refresh timeout {0} and URL {1}",
96 m_refreshtime,m_serverUrl);
97
98 m_enabled = true;
99 }
100
101 ///<summary>
102 ///
103 ///</summary>
104 public void PostInitialise()
105 {
106 if (m_enabled)
107 {
108 m_refreshTimer.Enabled = true;
109 m_refreshTimer.AutoReset = true;
110 m_refreshTimer.Interval = 5 * 60 * 1000; // every 5 minutes
111 m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh);
112 }
113 }
114
115
116 ///<summary>
117 ///
118 ///</summary>
119 public void AddRegion(Scene scene)
120 {
121 if (! m_enabled)
122 return;
123
124 // Every shared region module has to maintain an indepedent list of
125 // currently running regions
126 lock (m_scenes)
127 m_scenes[scene.RegionInfo.RegionID] = scene;
128 }
129
130 ///<summary>
131 ///
132 ///</summary>
133 public void RemoveRegion(Scene scene)
134 {
135 if (! m_enabled)
136 return;
137
138 lock (m_scenes)
139 m_scenes.Remove(scene.RegionInfo.RegionID);
140 }
141
142 #endregion ISharedRegionModule
143
144 ///<summary>
145 ///
146 ///</summary>
147 private void HandleMaptileRefresh(object sender, EventArgs ea)
148 {
149 // this approach is a bit convoluted becase we want to wait for the
150 // first upload to happen on startup but after all the objects are
151 // loaded and initialized
152 if (m_lastrefresh > 0 && Util.EnvironmentTickCountSubtract(m_lastrefresh) < m_refreshtime)
153 return;
154
155 m_log.DebugFormat("[SIMIAN MAPTILE] map refresh fired");
156 lock (m_scenes)
157 {
158 foreach (IScene scene in m_scenes.Values)
159 {
160 try
161 {
162 UploadMapTile(scene);
163 }
164 catch (Exception ex)
165 {
166 m_log.WarnFormat("[SIMIAN MAPTILE] something bad happened {0}",ex.Message);
167 }
168 }
169 }
170
171 m_lastrefresh = Util.EnvironmentTickCount();
172 }
173
174 ///<summary>
175 ///
176 ///</summary>
177 private void UploadMapTile(IScene scene)
178 {
179 m_log.DebugFormat("[SIMIAN MAPTILE]: upload maptile for {0}",scene.RegionInfo.RegionName);
180
181 // Create a PNG map tile and upload it to the AddMapTile API
182 byte[] pngData = Utils.EmptyBytes;
183 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
184 if (tileGenerator == null)
185 {
186 m_log.Warn("[SIMIAN MAPTILE]: Cannot upload PNG map tile without an ImageGenerator");
187 return;
188 }
189
190 using (Image mapTile = tileGenerator.CreateMapTile())
191 {
192 using (MemoryStream stream = new MemoryStream())
193 {
194 mapTile.Save(stream, ImageFormat.Png);
195 pngData = stream.ToArray();
196 }
197 }
198
199 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
200 {
201 new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
202 new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
203 new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
204 };
205
206 string errorMessage = null;
207 int tickstart = Util.EnvironmentTickCount();
208
209 // Make the remote storage request
210 try
211 {
212 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl);
213 request.Timeout = 20000;
214 request.ReadWriteTimeout = 5000;
215
216 using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
217 {
218 using (Stream responseStream = response.GetResponseStream())
219 {
220 string responseStr = responseStream.GetStreamString();
221 OSD responseOSD = OSDParser.Deserialize(responseStr);
222 if (responseOSD.Type == OSDType.Map)
223 {
224 OSDMap responseMap = (OSDMap)responseOSD;
225 if (responseMap["Success"].AsBoolean())
226 return;
227
228 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
229 }
230 else
231 {
232 errorMessage = "Response format was invalid:\n" + responseStr;
233 }
234 }
235 }
236 }
237 catch (WebException we)
238 {
239 errorMessage = we.Message;
240 if (we.Status == WebExceptionStatus.ProtocolError)
241 {
242 HttpWebResponse webResponse = (HttpWebResponse)we.Response;
243 errorMessage = String.Format("[{0}] {1}",
244 webResponse.StatusCode,webResponse.StatusDescription);
245 }
246 }
247 catch (Exception ex)
248 {
249 errorMessage = ex.Message;
250 }
251 finally
252 {
253 // This just dumps a warning for any operation that takes more than 100 ms
254 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
255 m_log.DebugFormat("[SIMIAN MAPTILE]: map tile uploaded in {0}ms",tickdiff);
256 }
257
258 m_log.WarnFormat("[SIMIAN MAPTILE]: Failed to store {0} byte tile for {1}: {2}",
259 pngData.Length, scene.RegionInfo.RegionName, errorMessage);
260 }
261 }
262} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
new file mode 100644
index 0000000..feea196
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -0,0 +1,524 @@
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.Collections.Specialized;
31using System.Drawing;
32using System.Drawing.Imaging;
33using System.IO;
34using System.Net;
35using System.Reflection;
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39using OpenSim.Framework;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Services.Interfaces;
43using OpenMetaverse;
44using OpenMetaverse.StructuredData;
45
46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
47
48namespace OpenSim.Services.Connectors.SimianGrid
49{
50 /// <summary>
51 /// Connects region registration and neighbor lookups to the SimianGrid
52 /// backend
53 /// </summary>
54 public class SimianGridServiceConnector : IGridService
55 {
56 private static readonly ILog m_log =
57 LogManager.GetLogger(
58 MethodBase.GetCurrentMethod().DeclaringType);
59
60 private string m_ServerURI = String.Empty;
61// private bool m_Enabled = false;
62
63 public SimianGridServiceConnector() { }
64 public SimianGridServiceConnector(string serverURI)
65 {
66 m_ServerURI = serverURI.TrimEnd('/');
67 }
68
69 public SimianGridServiceConnector(IConfigSource source)
70 {
71 CommonInit(source);
72 }
73
74 public void Initialise(IConfigSource source)
75 {
76 CommonInit(source);
77 }
78
79 private void CommonInit(IConfigSource source)
80 {
81 IConfig gridConfig = source.Configs["GridService"];
82 if (gridConfig == null)
83 {
84 m_log.Error("[SIMIAN GRID CONNECTOR]: GridService missing from OpenSim.ini");
85 throw new Exception("Grid connector init error");
86 }
87
88 string serviceUrl = gridConfig.GetString("GridServerURI");
89 if (String.IsNullOrEmpty(serviceUrl))
90 {
91 m_log.Error("[SIMIAN GRID CONNECTOR]: No Server URI named in section GridService");
92 throw new Exception("Grid connector init error");
93 }
94
95 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
96 serviceUrl = serviceUrl + '/';
97 m_ServerURI = serviceUrl;
98// m_Enabled = true;
99 }
100
101 #region IGridService
102
103 public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
104 {
105 IPEndPoint ext = regionInfo.ExternalEndPoint;
106 if (ext == null) return "Region registration for " + regionInfo.RegionName + " failed: Could not resolve EndPoint";
107 // Generate and upload our map tile in PNG format to the SimianGrid AddMapTile service
108// Scene scene;
109// if (m_scenes.TryGetValue(regionInfo.RegionID, out scene))
110// UploadMapTile(scene);
111// else
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113
114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
116
117 OSDMap extraData = new OSDMap
118 {
119 { "ServerURI", OSD.FromString(regionInfo.ServerURI) },
120 { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) },
121 { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) },
122 { "ExternalAddress", OSD.FromString(ext.Address.ToString()) },
123 { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) },
124 { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) },
125 { "Access", OSD.FromInteger(regionInfo.Access) },
126 { "RegionSecret", OSD.FromString(regionInfo.RegionSecret) },
127 { "EstateOwner", OSD.FromUUID(regionInfo.EstateOwner) },
128 { "Token", OSD.FromString(regionInfo.Token) }
129 };
130
131 NameValueCollection requestArgs = new NameValueCollection
132 {
133 { "RequestMethod", "AddScene" },
134 { "SceneID", regionInfo.RegionID.ToString() },
135 { "Name", regionInfo.RegionName },
136 { "MinPosition", minPosition.ToString() },
137 { "MaxPosition", maxPosition.ToString() },
138 { "Address", regionInfo.ServerURI },
139 { "Enabled", "1" },
140 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
141 };
142
143 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
144 if (response["Success"].AsBoolean())
145 return String.Empty;
146 else
147 return "Region registration for " + regionInfo.RegionName + " failed: " + response["Message"].AsString();
148 }
149
150 public bool DeregisterRegion(UUID regionID)
151 {
152 NameValueCollection requestArgs = new NameValueCollection
153 {
154 { "RequestMethod", "AddScene" },
155 { "SceneID", regionID.ToString() },
156 { "Enabled", "0" }
157 };
158
159 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
160 bool success = response["Success"].AsBoolean();
161
162 if (!success)
163 m_log.Warn("[SIMIAN GRID CONNECTOR]: Region deregistration for " + regionID + " failed: " + response["Message"].AsString());
164
165 return success;
166 }
167
168 public List<GridRegion> GetNeighbours(UUID scopeID, UUID regionID)
169 {
170 const int NEIGHBOR_RADIUS = 128;
171
172 GridRegion region = GetRegionByUUID(scopeID, regionID);
173
174 if (region != null)
175 {
176 List<GridRegion> regions = GetRegionRange(scopeID,
177 region.RegionLocX - NEIGHBOR_RADIUS, region.RegionLocX + (int)Constants.RegionSize + NEIGHBOR_RADIUS,
178 region.RegionLocY - NEIGHBOR_RADIUS, region.RegionLocY + (int)Constants.RegionSize + NEIGHBOR_RADIUS);
179
180 for (int i = 0; i < regions.Count; i++)
181 {
182 if (regions[i].RegionID == regionID)
183 {
184 regions.RemoveAt(i);
185 break;
186 }
187 }
188
189// m_log.Debug("[SIMIAN GRID CONNECTOR]: Found " + regions.Count + " neighbors for region " + regionID);
190 return regions;
191 }
192
193 return new List<GridRegion>(0);
194 }
195
196 public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID)
197 {
198 NameValueCollection requestArgs = new NameValueCollection
199 {
200 { "RequestMethod", "GetScene" },
201 { "SceneID", regionID.ToString() }
202 };
203
204 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region with uuid {0}",regionID.ToString());
205
206 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
207 if (response["Success"].AsBoolean())
208 {
209 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] uuid request successful {0}",response["Name"].AsString());
210 return ResponseToGridRegion(response);
211 }
212 else
213 {
214 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID);
215 return null;
216 }
217 }
218
219 public GridRegion GetRegionByPosition(UUID scopeID, int x, int y)
220 {
221 // Go one meter in from the requested x/y coords to avoid requesting a position
222 // that falls on the border of two sims
223 Vector3d position = new Vector3d(x + 1, y + 1, 0.0);
224
225 NameValueCollection requestArgs = new NameValueCollection
226 {
227 { "RequestMethod", "GetScene" },
228 { "Position", position.ToString() },
229 { "Enabled", "1" }
230 };
231
232 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request grid at {0}",position.ToString());
233
234 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
235 if (response["Success"].AsBoolean())
236 {
237 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] position request successful {0}",response["Name"].AsString());
238 return ResponseToGridRegion(response);
239 }
240 else
241 {
242 // m_log.InfoFormat("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at {0},{1}",
243 // x / Constants.RegionSize, y / Constants.RegionSize);
244 return null;
245 }
246 }
247
248 public GridRegion GetRegionByName(UUID scopeID, string regionName)
249 {
250 List<GridRegion> regions = GetRegionsByName(scopeID, regionName, 1);
251
252 m_log.Debug("[SIMIAN GRID CONNECTOR]: Got " + regions.Count + " matches for region name " + regionName);
253
254 if (regions.Count > 0)
255 return regions[0];
256
257 return null;
258 }
259
260 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
261 {
262 List<GridRegion> foundRegions = new List<GridRegion>();
263
264 NameValueCollection requestArgs = new NameValueCollection
265 {
266 { "RequestMethod", "GetScenes" },
267 { "NameQuery", name },
268 { "Enabled", "1" }
269 };
270 if (maxNumber > 0)
271 requestArgs["MaxNumber"] = maxNumber.ToString();
272
273 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions with name {0}",name);
274
275 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
276 if (response["Success"].AsBoolean())
277 {
278 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] found regions with name {0}",name);
279
280 OSDArray array = response["Scenes"] as OSDArray;
281 if (array != null)
282 {
283 for (int i = 0; i < array.Count; i++)
284 {
285 GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
286 if (region != null)
287 foundRegions.Add(region);
288 }
289 }
290 }
291
292 return foundRegions;
293 }
294
295 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
296 {
297 List<GridRegion> foundRegions = new List<GridRegion>();
298
299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
300 Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0);
301
302 NameValueCollection requestArgs = new NameValueCollection
303 {
304 { "RequestMethod", "GetScenes" },
305 { "MinPosition", minPosition.ToString() },
306 { "MaxPosition", maxPosition.ToString() },
307 { "Enabled", "1" }
308 };
309
310 //m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request regions by range {0} to {1}",minPosition.ToString(),maxPosition.ToString());
311
312
313 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
314 if (response["Success"].AsBoolean())
315 {
316 OSDArray array = response["Scenes"] as OSDArray;
317 if (array != null)
318 {
319 for (int i = 0; i < array.Count; i++)
320 {
321 GridRegion region = ResponseToGridRegion(array[i] as OSDMap);
322 if (region != null)
323 foundRegions.Add(region);
324 }
325 }
326 }
327
328 return foundRegions;
329 }
330
331 public List<GridRegion> GetDefaultRegions(UUID scopeID)
332 {
333 // TODO: Allow specifying the default grid location
334 const int DEFAULT_X = 1000 * 256;
335 const int DEFAULT_Y = 1000 * 256;
336
337 GridRegion defRegion = GetNearestRegion(new Vector3d(DEFAULT_X, DEFAULT_Y, 0.0), true);
338 if (defRegion != null)
339 return new List<GridRegion>(1) { defRegion };
340 else
341 return new List<GridRegion>(0);
342 }
343
344 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
345 {
346 GridRegion defRegion = GetNearestRegion(new Vector3d(x, y, 0.0), true);
347 if (defRegion != null)
348 return new List<GridRegion>(1) { defRegion };
349 else
350 return new List<GridRegion>(0);
351 }
352
353 public List<GridRegion> GetHyperlinks(UUID scopeID)
354 {
355 // Hypergrid/linked regions are not supported
356 return new List<GridRegion>();
357 }
358
359 public int GetRegionFlags(UUID scopeID, UUID regionID)
360 {
361 const int REGION_ONLINE = 4;
362
363 NameValueCollection requestArgs = new NameValueCollection
364 {
365 { "RequestMethod", "GetScene" },
366 { "SceneID", regionID.ToString() }
367 };
368
369 // m_log.DebugFormat("[SIMIAN GRID CONNECTOR] request region flags for {0}",regionID.ToString());
370
371 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
372 if (response["Success"].AsBoolean())
373 {
374 return response["Enabled"].AsBoolean() ? REGION_ONLINE : 0;
375 }
376 else
377 {
378 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region " + regionID + " during region flags check");
379 return -1;
380 }
381 }
382
383 #endregion IGridService
384
385 private void UploadMapTile(IScene scene)
386 {
387 string errorMessage = null;
388
389 // Create a PNG map tile and upload it to the AddMapTile API
390 byte[] pngData = Utils.EmptyBytes;
391 IMapImageGenerator tileGenerator = scene.RequestModuleInterface<IMapImageGenerator>();
392 if (tileGenerator == null)
393 {
394 m_log.Warn("[SIMIAN GRID CONNECTOR]: Cannot upload PNG map tile without an IMapImageGenerator");
395 return;
396 }
397
398 using (Image mapTile = tileGenerator.CreateMapTile())
399 {
400 using (MemoryStream stream = new MemoryStream())
401 {
402 mapTile.Save(stream, ImageFormat.Png);
403 pngData = stream.ToArray();
404 }
405 }
406
407 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
408 {
409 new MultipartForm.Parameter("X", scene.RegionInfo.RegionLocX.ToString()),
410 new MultipartForm.Parameter("Y", scene.RegionInfo.RegionLocY.ToString()),
411 new MultipartForm.File("Tile", "tile.png", "image/png", pngData)
412 };
413
414 // Make the remote storage request
415 try
416 {
417 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_ServerURI);
418
419 HttpWebResponse response = MultipartForm.Post(request, postParameters);
420 using (Stream responseStream = response.GetResponseStream())
421 {
422 string responseStr = null;
423
424 try
425 {
426 responseStr = responseStream.GetStreamString();
427 OSD responseOSD = OSDParser.Deserialize(responseStr);
428 if (responseOSD.Type == OSDType.Map)
429 {
430 OSDMap responseMap = (OSDMap)responseOSD;
431 if (responseMap["Success"].AsBoolean())
432 m_log.Info("[SIMIAN GRID CONNECTOR]: Uploaded " + pngData.Length + " byte PNG map tile to AddMapTile");
433 else
434 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
435 }
436 else
437 {
438 errorMessage = "Response format was invalid:\n" + responseStr;
439 }
440 }
441 catch (Exception ex)
442 {
443 if (!String.IsNullOrEmpty(responseStr))
444 errorMessage = "Failed to parse the response:\n" + responseStr;
445 else
446 errorMessage = "Failed to retrieve the response: " + ex.Message;
447 }
448 }
449 }
450 catch (WebException ex)
451 {
452 errorMessage = ex.Message;
453 }
454
455 if (!String.IsNullOrEmpty(errorMessage))
456 {
457 m_log.WarnFormat("[SIMIAN GRID CONNECTOR]: Failed to store {0} byte PNG map tile for {1}: {2}",
458 pngData.Length, scene.RegionInfo.RegionName, errorMessage.Replace('\n', ' '));
459 }
460 }
461
462 private GridRegion GetNearestRegion(Vector3d position, bool onlyEnabled)
463 {
464 NameValueCollection requestArgs = new NameValueCollection
465 {
466 { "RequestMethod", "GetScene" },
467 { "Position", position.ToString() },
468 { "FindClosest", "1" }
469 };
470 if (onlyEnabled)
471 requestArgs["Enabled"] = "1";
472
473 OSDMap response = WebUtil.PostToService(m_ServerURI, requestArgs);
474 if (response["Success"].AsBoolean())
475 {
476 return ResponseToGridRegion(response);
477 }
478 else
479 {
480 m_log.Warn("[SIMIAN GRID CONNECTOR]: Grid service did not find a match for region at " + position);
481 return null;
482 }
483 }
484
485 private GridRegion ResponseToGridRegion(OSDMap response)
486 {
487 if (response == null)
488 return null;
489
490 OSDMap extraData = response["ExtraData"] as OSDMap;
491 if (extraData == null)
492 return null;
493
494 GridRegion region = new GridRegion();
495
496 region.RegionID = response["SceneID"].AsUUID();
497 region.RegionName = response["Name"].AsString();
498
499 Vector3d minPosition = response["MinPosition"].AsVector3d();
500 region.RegionLocX = (int)minPosition.X;
501 region.RegionLocY = (int)minPosition.Y;
502
503 Uri httpAddress = response["Address"].AsUri();
504 region.ExternalHostName = httpAddress.Host;
505 region.HttpPort = (uint)httpAddress.Port;
506
507 region.ServerURI = extraData["ServerURI"].AsString();
508
509 IPAddress internalAddress;
510 IPAddress.TryParse(extraData["InternalAddress"].AsString(), out internalAddress);
511 if (internalAddress == null)
512 internalAddress = IPAddress.Any;
513
514 region.InternalEndPoint = new IPEndPoint(internalAddress, extraData["InternalPort"].AsInteger());
515 region.TerrainImage = extraData["MapTexture"].AsUUID();
516 region.Access = (byte)extraData["Access"].AsInteger();
517 region.RegionSecret = extraData["RegionSecret"].AsString();
518 region.EstateOwner = extraData["EstateOwner"].AsUUID();
519 region.Token = extraData["Token"].AsString();
520
521 return region;
522 }
523 }
524}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
new file mode 100644
index 0000000..39df1f5
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs
@@ -0,0 +1,922 @@
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.Collections.Specialized;
31using System.Reflection;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41
42namespace OpenSim.Services.Connectors.SimianGrid
43{
44 /// <summary>
45 /// Permissions bitflags
46 /// </summary>
47 [Flags]
48 public enum PermissionMask : uint
49 {
50 None = 0,
51 Transfer = 1 << 13,
52 Modify = 1 << 14,
53 Copy = 1 << 15,
54 Move = 1 << 19,
55 Damage = 1 << 20,
56 All = 0x7FFFFFFF
57 }
58
59 /// <summary>
60 /// Connects avatar inventories to the SimianGrid backend
61 /// </summary>
62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
63 public class SimianInventoryServiceConnector : IInventoryService, ISharedRegionModule
64 {
65 private static readonly ILog m_log =
66 LogManager.GetLogger(
67 MethodBase.GetCurrentMethod().DeclaringType);
68
69 private string m_serverUrl = String.Empty;
70 private string m_userServerUrl = String.Empty;
71// private object m_gestureSyncRoot = new object();
72 private bool m_Enabled = false;
73
74 #region ISharedRegionModule
75
76 public Type ReplaceableInterface { get { return null; } }
77 public void RegionLoaded(Scene scene) { }
78 public void PostInitialise() { }
79 public void Close() { }
80
81 public SimianInventoryServiceConnector() { }
82 public string Name { get { return "SimianInventoryServiceConnector"; } }
83 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IInventoryService>(this); } }
84 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IInventoryService>(this); } }
85
86 #endregion ISharedRegionModule
87
88 public SimianInventoryServiceConnector(IConfigSource source)
89 {
90 CommonInit(source);
91 }
92
93 public SimianInventoryServiceConnector(string url)
94 {
95 m_serverUrl = url;
96 }
97
98 public void Initialise(IConfigSource source)
99 {
100 IConfig moduleConfig = source.Configs["Modules"];
101 if (moduleConfig != null)
102 {
103 string name = moduleConfig.GetString("InventoryServices", "");
104 if (name == Name)
105 CommonInit(source);
106 }
107 }
108
109 private void CommonInit(IConfigSource source)
110 {
111 IConfig gridConfig = source.Configs["InventoryService"];
112 if (gridConfig != null)
113 {
114 string serviceUrl = gridConfig.GetString("InventoryServerURI");
115 if (!String.IsNullOrEmpty(serviceUrl))
116 {
117 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
118 serviceUrl = serviceUrl + '/';
119 m_serverUrl = serviceUrl;
120
121 gridConfig = source.Configs["UserAccountService"];
122 if (gridConfig != null)
123 {
124 serviceUrl = gridConfig.GetString("UserAccountServerURI");
125 if (!String.IsNullOrEmpty(serviceUrl))
126 {
127 m_userServerUrl = serviceUrl;
128 m_Enabled = true;
129 }
130 }
131 }
132 }
133
134 if (String.IsNullOrEmpty(m_serverUrl))
135 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector");
136 else if (String.IsNullOrEmpty(m_userServerUrl))
137 m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector");
138 }
139
140 /// <summary>
141 /// Create the entire inventory for a given user
142 /// </summary>
143 /// <param name="user"></param>
144 /// <returns></returns>
145 public bool CreateUserInventory(UUID userID)
146 {
147 NameValueCollection requestArgs = new NameValueCollection
148 {
149 { "RequestMethod", "AddInventory" },
150 { "OwnerID", userID.ToString() }
151 };
152
153 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
154 bool success = response["Success"].AsBoolean();
155
156 if (!success)
157 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Inventory creation for " + userID + " failed: " + response["Message"].AsString());
158
159 return success;
160 }
161
162 /// <summary>
163 /// Gets the skeleton of the inventory -- folders only
164 /// </summary>
165 /// <param name="userID"></param>
166 /// <returns></returns>
167 public List<InventoryFolderBase> GetInventorySkeleton(UUID userID)
168 {
169 NameValueCollection requestArgs = new NameValueCollection
170 {
171 { "RequestMethod", "GetInventoryNode" },
172 { "ItemID", userID.ToString() },
173 { "OwnerID", userID.ToString() },
174 { "IncludeFolders", "1" },
175 { "IncludeItems", "0" },
176 { "ChildrenOnly", "0" }
177 };
178
179 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
180 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
181 {
182 OSDArray items = (OSDArray)response["Items"];
183 return GetFoldersFromResponse(items, userID, true);
184 }
185 else
186 {
187 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to retrieve inventory skeleton for " + userID + ": " +
188 response["Message"].AsString());
189 return new List<InventoryFolderBase>(0);
190 }
191 }
192
193 /// <summary>
194 /// Synchronous inventory fetch.
195 /// </summary>
196 /// <param name="userID"></param>
197 /// <returns></returns>
198 [Obsolete]
199 public InventoryCollection GetUserInventory(UUID userID)
200 {
201 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID);
202
203 InventoryCollection inventory = new InventoryCollection();
204 inventory.UserID = userID;
205 inventory.Folders = new List<InventoryFolderBase>();
206 inventory.Items = new List<InventoryItemBase>();
207
208 return inventory;
209 }
210
211 /// <summary>
212 /// Request the inventory for a user. This is an asynchronous operation that will call the callback when the
213 /// inventory has been received
214 /// </summary>
215 /// <param name="userID"></param>
216 /// <param name="callback"></param>
217 [Obsolete]
218 public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
219 {
220 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Obsolete GetUserInventory called for " + userID);
221 callback(new List<InventoryFolderImpl>(0), new List<InventoryItemBase>(0));
222 }
223
224 /// <summary>
225 /// Retrieve the root inventory folder for the given user.
226 /// </summary>
227 /// <param name="userID"></param>
228 /// <returns>null if no root folder was found</returns>
229 public InventoryFolderBase GetRootFolder(UUID userID)
230 {
231 NameValueCollection requestArgs = new NameValueCollection
232 {
233 { "RequestMethod", "GetInventoryNode" },
234 { "ItemID", userID.ToString() },
235 { "OwnerID", userID.ToString() },
236 { "IncludeFolders", "1" },
237 { "IncludeItems", "0" },
238 { "ChildrenOnly", "1" }
239 };
240
241 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
242 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
243 {
244 OSDArray items = (OSDArray)response["Items"];
245 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, userID, true);
246
247 if (folders.Count > 0)
248 return folders[0];
249 }
250
251 return null;
252 }
253
254 /// <summary>
255 /// Gets the user folder for the given folder-type
256 /// </summary>
257 /// <param name="userID"></param>
258 /// <param name="type"></param>
259 /// <returns></returns>
260 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
261 {
262 string contentType = SLUtil.SLAssetTypeToContentType((int)type);
263
264 NameValueCollection requestArgs = new NameValueCollection
265 {
266 { "RequestMethod", "GetFolderForType" },
267 { "ContentType", contentType },
268 { "OwnerID", userID.ToString() }
269 };
270
271 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
272 if (response["Success"].AsBoolean() && response["Folder"] is OSDMap)
273 {
274 OSDMap folder = (OSDMap)response["Folder"];
275
276 return new InventoryFolderBase(
277 folder["ID"].AsUUID(),
278 folder["Name"].AsString(),
279 folder["OwnerID"].AsUUID(),
280 (short)SLUtil.ContentTypeToSLAssetType(folder["ContentType"].AsString()),
281 folder["ParentID"].AsUUID(),
282 (ushort)folder["Version"].AsInteger()
283 );
284 }
285 else
286 {
287 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Default folder not found for content type " + contentType + ": " + response["Message"].AsString());
288 return GetRootFolder(userID);
289 }
290 }
291
292 /// <summary>
293 /// Get an item, given by its UUID
294 /// </summary>
295 /// <param name="item"></param>
296 /// <returns></returns>
297 public InventoryItemBase GetItem(InventoryItemBase item)
298 {
299 NameValueCollection requestArgs = new NameValueCollection
300 {
301 { "RequestMethod", "GetInventoryNode" },
302 { "ItemID", item.ID.ToString() },
303 { "OwnerID", item.Owner.ToString() },
304 { "IncludeFolders", "1" },
305 { "IncludeItems", "1" },
306 { "ChildrenOnly", "1" }
307 };
308
309 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
310 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
311 {
312 List<InventoryItemBase> items = GetItemsFromResponse((OSDArray)response["Items"]);
313 if (items.Count > 0)
314 {
315 // The requested item should be the first in this list, but loop through
316 // and sanity check just in case
317 for (int i = 0; i < items.Count; i++)
318 {
319 if (items[i].ID == item.ID)
320 return items[i];
321 }
322 }
323 }
324
325 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Item " + item.ID + " owned by " + item.Owner + " not found");
326 return null;
327 }
328
329 /// <summary>
330 /// Get a folder, given by its UUID
331 /// </summary>
332 /// <param name="folder"></param>
333 /// <returns></returns>
334 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
335 {
336 NameValueCollection requestArgs = new NameValueCollection
337 {
338 { "RequestMethod", "GetInventoryNode" },
339 { "ItemID", folder.ID.ToString() },
340 { "OwnerID", folder.Owner.ToString() },
341 { "IncludeFolders", "1" },
342 { "IncludeItems", "0" },
343 { "ChildrenOnly", "1" }
344 };
345
346 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
347 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
348 {
349 OSDArray items = (OSDArray)response["Items"];
350 List<InventoryFolderBase> folders = GetFoldersFromResponse(items, folder.ID, true);
351
352 if (folders.Count > 0)
353 return folders[0];
354 }
355
356 return null;
357 }
358
359 /// <summary>
360 /// Gets everything (folders and items) inside a folder
361 /// </summary>
362 /// <param name="userID"></param>
363 /// <param name="folderID"></param>
364 /// <returns></returns>
365 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
366 {
367 InventoryCollection inventory = new InventoryCollection();
368 inventory.UserID = userID;
369
370 NameValueCollection requestArgs = new NameValueCollection
371 {
372 { "RequestMethod", "GetInventoryNode" },
373 { "ItemID", folderID.ToString() },
374 { "OwnerID", userID.ToString() },
375 { "IncludeFolders", "1" },
376 { "IncludeItems", "1" },
377 { "ChildrenOnly", "1" }
378 };
379
380 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
381 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
382 {
383 OSDArray items = (OSDArray)response["Items"];
384
385 inventory.Folders = GetFoldersFromResponse(items, folderID, false);
386 inventory.Items = GetItemsFromResponse(items);
387 }
388 else
389 {
390 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " content for " + userID + ": " +
391 response["Message"].AsString());
392 inventory.Folders = new List<InventoryFolderBase>(0);
393 inventory.Items = new List<InventoryItemBase>(0);
394 }
395
396 return inventory;
397 }
398
399 /// <summary>
400 /// Gets the items inside a folder
401 /// </summary>
402 /// <param name="userID"></param>
403 /// <param name="folderID"></param>
404 /// <returns></returns>
405 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
406 {
407 InventoryCollection inventory = new InventoryCollection();
408 inventory.UserID = userID;
409
410 NameValueCollection requestArgs = new NameValueCollection
411 {
412 { "RequestMethod", "GetInventoryNode" },
413 { "ItemID", folderID.ToString() },
414 { "OwnerID", userID.ToString() },
415 { "IncludeFolders", "0" },
416 { "IncludeItems", "1" },
417 { "ChildrenOnly", "1" }
418 };
419
420 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
421 if (response["Success"].AsBoolean() && response["Items"] is OSDArray)
422 {
423 OSDArray items = (OSDArray)response["Items"];
424 return GetItemsFromResponse(items);
425 }
426 else
427 {
428 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error fetching folder " + folderID + " for " + userID + ": " +
429 response["Message"].AsString());
430 return new List<InventoryItemBase>(0);
431 }
432 }
433
434 /// <summary>
435 /// Add a new folder to the user's inventory
436 /// </summary>
437 /// <param name="folder"></param>
438 /// <returns>true if the folder was successfully added</returns>
439 public bool AddFolder(InventoryFolderBase folder)
440 {
441 NameValueCollection requestArgs = new NameValueCollection
442 {
443 { "RequestMethod", "AddInventoryFolder" },
444 { "FolderID", folder.ID.ToString() },
445 { "ParentID", folder.ParentID.ToString() },
446 { "OwnerID", folder.Owner.ToString() },
447 { "Name", folder.Name },
448 { "ContentType", SLUtil.SLAssetTypeToContentType(folder.Type) }
449 };
450
451 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
452 bool success = response["Success"].AsBoolean();
453
454 if (!success)
455 {
456 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating folder " + folder.Name + " for " + folder.Owner + ": " +
457 response["Message"].AsString());
458 }
459
460 return success;
461 }
462
463 /// <summary>
464 /// Update a folder in the user's inventory
465 /// </summary>
466 /// <param name="folder"></param>
467 /// <returns>true if the folder was successfully updated</returns>
468 public bool UpdateFolder(InventoryFolderBase folder)
469 {
470 return AddFolder(folder);
471 }
472
473 /// <summary>
474 /// Move an inventory folder to a new location
475 /// </summary>
476 /// <param name="folder">A folder containing the details of the new location</param>
477 /// <returns>true if the folder was successfully moved</returns>
478 public bool MoveFolder(InventoryFolderBase folder)
479 {
480 return AddFolder(folder);
481 }
482
483 /// <summary>
484 /// Delete an item from the user's inventory
485 /// </summary>
486 /// <param name="item"></param>
487 /// <returns>true if the item was successfully deleted</returns>
488 //bool DeleteItem(InventoryItemBase item);
489 public bool DeleteFolders(UUID userID, List<UUID> folderIDs)
490 {
491 return DeleteItems(userID, folderIDs);
492 }
493
494 /// <summary>
495 /// Delete an item from the user's inventory
496 /// </summary>
497 /// <param name="item"></param>
498 /// <returns>true if the item was successfully deleted</returns>
499 public bool DeleteItems(UUID userID, List<UUID> itemIDs)
500 {
501 // TODO: RemoveInventoryNode should be replaced with RemoveInventoryNodes
502 bool allSuccess = true;
503
504 for (int i = 0; i < itemIDs.Count; i++)
505 {
506 UUID itemID = itemIDs[i];
507
508 NameValueCollection requestArgs = new NameValueCollection
509 {
510 { "RequestMethod", "RemoveInventoryNode" },
511 { "OwnerID", userID.ToString() },
512 { "ItemID", itemID.ToString() }
513 };
514
515 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
516 bool success = response["Success"].AsBoolean();
517
518 if (!success)
519 {
520 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error removing item " + itemID + " for " + userID + ": " +
521 response["Message"].AsString());
522 allSuccess = false;
523 }
524 }
525
526 return allSuccess;
527 }
528
529 /// <summary>
530 /// Purge an inventory folder of all its items and subfolders.
531 /// </summary>
532 /// <param name="folder"></param>
533 /// <returns>true if the folder was successfully purged</returns>
534 public bool PurgeFolder(InventoryFolderBase folder)
535 {
536 NameValueCollection requestArgs = new NameValueCollection
537 {
538 { "RequestMethod", "PurgeInventoryFolder" },
539 { "OwnerID", folder.Owner.ToString() },
540 { "FolderID", folder.ID.ToString() }
541 };
542
543 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
544 bool success = response["Success"].AsBoolean();
545
546 if (!success)
547 {
548 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error purging folder " + folder.ID + " for " + folder.Owner + ": " +
549 response["Message"].AsString());
550 }
551
552 return success;
553 }
554
555 /// <summary>
556 /// Add a new item to the user's inventory
557 /// </summary>
558 /// <param name="item"></param>
559 /// <returns>true if the item was successfully added</returns>
560 public bool AddItem(InventoryItemBase item)
561 {
562 // A folder of UUID.Zero means we need to find the most appropriate home for this item
563 if (item.Folder == UUID.Zero)
564 {
565 InventoryFolderBase folder = GetFolderForType(item.Owner, (AssetType)item.AssetType);
566 if (folder != null && folder.ID != UUID.Zero)
567 item.Folder = folder.ID;
568 else
569 item.Folder = item.Owner; // Root folder
570 }
571
572 if ((AssetType)item.AssetType == AssetType.Gesture)
573 UpdateGesture(item.Owner, item.ID, item.Flags == 1);
574
575 if (item.BasePermissions == 0)
576 m_log.WarnFormat("[SIMIAN INVENTORY CONNECTOR]: Adding inventory item {0} ({1}) with no base permissions", item.Name, item.ID);
577
578 OSDMap permissions = new OSDMap
579 {
580 { "BaseMask", OSD.FromInteger(item.BasePermissions) },
581 { "EveryoneMask", OSD.FromInteger(item.EveryOnePermissions) },
582 { "GroupMask", OSD.FromInteger(item.GroupPermissions) },
583 { "NextOwnerMask", OSD.FromInteger(item.NextPermissions) },
584 { "OwnerMask", OSD.FromInteger(item.CurrentPermissions) }
585 };
586
587 OSDMap extraData = new OSDMap()
588 {
589 { "Flags", OSD.FromInteger(item.Flags) },
590 { "GroupID", OSD.FromUUID(item.GroupID) },
591 { "GroupOwned", OSD.FromBoolean(item.GroupOwned) },
592 { "SalePrice", OSD.FromInteger(item.SalePrice) },
593 { "SaleType", OSD.FromInteger(item.SaleType) },
594 { "Permissions", permissions }
595 };
596
597 // Add different asset type only if it differs from inventory type
598 // (needed for links)
599 string invContentType = SLUtil.SLInvTypeToContentType(item.InvType);
600 string assetContentType = SLUtil.SLAssetTypeToContentType(item.AssetType);
601
602 if (invContentType != assetContentType)
603 extraData["LinkedItemType"] = OSD.FromString(assetContentType);
604
605 NameValueCollection requestArgs = new NameValueCollection
606 {
607 { "RequestMethod", "AddInventoryItem" },
608 { "ItemID", item.ID.ToString() },
609 { "AssetID", item.AssetID.ToString() },
610 { "ParentID", item.Folder.ToString() },
611 { "OwnerID", item.Owner.ToString() },
612 { "Name", item.Name },
613 { "Description", item.Description },
614 { "CreatorID", item.CreatorId },
615 { "CreatorData", item.CreatorData },
616 { "ContentType", invContentType },
617 { "ExtraData", OSDParser.SerializeJsonString(extraData) }
618 };
619
620 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
621 bool success = response["Success"].AsBoolean();
622
623 if (!success)
624 {
625 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Error creating item " + item.Name + " for " + item.Owner + ": " +
626 response["Message"].AsString());
627 }
628
629 return success;
630 }
631
632 /// <summary>
633 /// Update an item in the user's inventory
634 /// </summary>
635 /// <param name="item"></param>
636 /// <returns>true if the item was successfully updated</returns>
637 public bool UpdateItem(InventoryItemBase item)
638 {
639 if (item.AssetID != UUID.Zero)
640 {
641 return AddItem(item);
642 }
643 else
644 {
645 // This is actually a folder update
646 InventoryFolderBase folder = new InventoryFolderBase(item.ID, item.Name, item.Owner, (short)item.AssetType, item.Folder, 0);
647 return UpdateFolder(folder);
648 }
649 }
650
651 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
652 {
653 bool success = true;
654
655 while (items.Count > 0)
656 {
657 List<InventoryItemBase> currentItems = new List<InventoryItemBase>();
658 UUID destFolderID = items[0].Folder;
659
660 // Find all of the items being moved to the current destination folder
661 for (int i = 0; i < items.Count; i++)
662 {
663 InventoryItemBase item = items[i];
664 if (item.Folder == destFolderID)
665 currentItems.Add(item);
666 }
667
668 // Do the inventory move for the current items
669 success &= MoveItems(ownerID, items, destFolderID);
670
671 // Remove the processed items from the list
672 for (int i = 0; i < currentItems.Count; i++)
673 items.Remove(currentItems[i]);
674 }
675
676 return success;
677 }
678
679 /// <summary>
680 /// Does the given user have an inventory structure?
681 /// </summary>
682 /// <param name="userID"></param>
683 /// <returns></returns>
684 public bool HasInventoryForUser(UUID userID)
685 {
686 return GetRootFolder(userID) != null;
687 }
688
689 /// <summary>
690 /// Get the active gestures of the agent.
691 /// </summary>
692 /// <param name="userID"></param>
693 /// <returns></returns>
694 public List<InventoryItemBase> GetActiveGestures(UUID userID)
695 {
696 OSDArray items = FetchGestures(userID);
697
698 string[] itemIDs = new string[items.Count];
699 for (int i = 0; i < items.Count; i++)
700 itemIDs[i] = items[i].AsUUID().ToString();
701
702// NameValueCollection requestArgs = new NameValueCollection
703// {
704// { "RequestMethod", "GetInventoryNodes" },
705// { "OwnerID", userID.ToString() },
706// { "Items", String.Join(",", itemIDs) }
707// };
708
709 // FIXME: Implement this in SimianGrid
710 return new List<InventoryItemBase>(0);
711 }
712
713 /// <summary>
714 /// Get the union of permissions of all inventory items
715 /// that hold the given assetID.
716 /// </summary>
717 /// <param name="userID"></param>
718 /// <param name="assetID"></param>
719 /// <returns>The permissions or 0 if no such asset is found in
720 /// the user's inventory</returns>
721 public int GetAssetPermissions(UUID userID, UUID assetID)
722 {
723// NameValueCollection requestArgs = new NameValueCollection
724// {
725// { "RequestMethod", "GetInventoryNodes" },
726// { "OwnerID", userID.ToString() },
727// { "AssetID", assetID.ToString() }
728// };
729
730 // FIXME: Implement this in SimianGrid
731 return (int)PermissionMask.All;
732 }
733
734 private List<InventoryFolderBase> GetFoldersFromResponse(OSDArray items, UUID baseFolder, bool includeBaseFolder)
735 {
736 List<InventoryFolderBase> invFolders = new List<InventoryFolderBase>(items.Count);
737
738 for (int i = 0; i < items.Count; i++)
739 {
740 OSDMap item = items[i] as OSDMap;
741
742 if (item != null && item["Type"].AsString() == "Folder")
743 {
744 UUID folderID = item["ID"].AsUUID();
745
746 if (folderID == baseFolder && !includeBaseFolder)
747 continue;
748
749 invFolders.Add(new InventoryFolderBase(
750 folderID,
751 item["Name"].AsString(),
752 item["OwnerID"].AsUUID(),
753 (short)SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString()),
754 item["ParentID"].AsUUID(),
755 (ushort)item["Version"].AsInteger()
756 ));
757 }
758 }
759
760// m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invFolders.Count + " folders from SimianGrid response");
761 return invFolders;
762 }
763
764 private List<InventoryItemBase> GetItemsFromResponse(OSDArray items)
765 {
766 List<InventoryItemBase> invItems = new List<InventoryItemBase>(items.Count);
767
768 for (int i = 0; i < items.Count; i++)
769 {
770 OSDMap item = items[i] as OSDMap;
771
772 if (item != null && item["Type"].AsString() == "Item")
773 {
774 InventoryItemBase invItem = new InventoryItemBase();
775
776 invItem.AssetID = item["AssetID"].AsUUID();
777 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(item["ContentType"].AsString());
778 invItem.CreationDate = item["CreationDate"].AsInteger();
779 invItem.CreatorId = item["CreatorID"].AsString();
780 invItem.CreatorData = item["CreatorData"].AsString();
781 invItem.CreatorIdAsUuid = item["CreatorID"].AsUUID();
782 invItem.Description = item["Description"].AsString();
783 invItem.Folder = item["ParentID"].AsUUID();
784 invItem.ID = item["ID"].AsUUID();
785 invItem.InvType = SLUtil.ContentTypeToSLInvType(item["ContentType"].AsString());
786 invItem.Name = item["Name"].AsString();
787 invItem.Owner = item["OwnerID"].AsUUID();
788
789 OSDMap extraData = item["ExtraData"] as OSDMap;
790 if (extraData != null && extraData.Count > 0)
791 {
792 invItem.Flags = extraData["Flags"].AsUInteger();
793 invItem.GroupID = extraData["GroupID"].AsUUID();
794 invItem.GroupOwned = extraData["GroupOwned"].AsBoolean();
795 invItem.SalePrice = extraData["SalePrice"].AsInteger();
796 invItem.SaleType = (byte)extraData["SaleType"].AsInteger();
797
798 OSDMap perms = extraData["Permissions"] as OSDMap;
799 if (perms != null)
800 {
801 invItem.BasePermissions = perms["BaseMask"].AsUInteger();
802 invItem.CurrentPermissions = perms["OwnerMask"].AsUInteger();
803 invItem.EveryOnePermissions = perms["EveryoneMask"].AsUInteger();
804 invItem.GroupPermissions = perms["GroupMask"].AsUInteger();
805 invItem.NextPermissions = perms["NextOwnerMask"].AsUInteger();
806 }
807
808 if (extraData.ContainsKey("LinkedItemType"))
809 invItem.AssetType = SLUtil.ContentTypeToSLAssetType(extraData["LinkedItemType"].AsString());
810 }
811
812 if (invItem.BasePermissions == 0)
813 {
814 m_log.InfoFormat("[SIMIAN INVENTORY CONNECTOR]: Forcing item permissions to full for item {0} ({1})",
815 invItem.Name, invItem.ID);
816 invItem.BasePermissions = (uint)PermissionMask.All;
817 invItem.CurrentPermissions = (uint)PermissionMask.All;
818 invItem.EveryOnePermissions = (uint)PermissionMask.All;
819 invItem.GroupPermissions = (uint)PermissionMask.All;
820 invItem.NextPermissions = (uint)PermissionMask.All;
821 }
822
823 invItems.Add(invItem);
824 }
825 }
826
827// m_log.Debug("[SIMIAN INVENTORY CONNECTOR]: Parsed " + invItems.Count + " items from SimianGrid response");
828 return invItems;
829 }
830
831 private bool MoveItems(UUID ownerID, List<InventoryItemBase> items, UUID destFolderID)
832 {
833 string[] itemIDs = new string[items.Count];
834 for (int i = 0; i < items.Count; i++)
835 itemIDs[i] = items[i].ID.ToString();
836
837 NameValueCollection requestArgs = new NameValueCollection
838 {
839 { "RequestMethod", "MoveInventoryNodes" },
840 { "OwnerID", ownerID.ToString() },
841 { "FolderID", destFolderID.ToString() },
842 { "Items", String.Join(",", itemIDs) }
843 };
844
845 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
846 bool success = response["Success"].AsBoolean();
847
848 if (!success)
849 {
850 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to move " + items.Count + " items to " +
851 destFolderID + ": " + response["Message"].AsString());
852 }
853
854 return success;
855 }
856
857 private void UpdateGesture(UUID userID, UUID itemID, bool enabled)
858 {
859 OSDArray gestures = FetchGestures(userID);
860 OSDArray newGestures = new OSDArray();
861
862 for (int i = 0; i < gestures.Count; i++)
863 {
864 UUID gesture = gestures[i].AsUUID();
865 if (gesture != itemID)
866 newGestures.Add(OSD.FromUUID(gesture));
867 }
868
869 if (enabled)
870 newGestures.Add(OSD.FromUUID(itemID));
871
872 SaveGestures(userID, newGestures);
873 }
874
875 private OSDArray FetchGestures(UUID userID)
876 {
877 NameValueCollection requestArgs = new NameValueCollection
878 {
879 { "RequestMethod", "GetUser" },
880 { "UserID", userID.ToString() }
881 };
882
883 OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs);
884 if (response["Success"].AsBoolean())
885 {
886 OSDMap user = response["User"] as OSDMap;
887 if (user != null && response.ContainsKey("Gestures"))
888 {
889 OSD gestures = OSDParser.DeserializeJson(response["Gestures"].AsString());
890 if (gestures != null && gestures is OSDArray)
891 return (OSDArray)gestures;
892 else
893 m_log.Error("[SIMIAN INVENTORY CONNECTOR]: Unrecognized active gestures data for " + userID);
894 }
895 }
896 else
897 {
898 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to fetch active gestures for " + userID + ": " +
899 response["Message"].AsString());
900 }
901
902 return new OSDArray();
903 }
904
905 private void SaveGestures(UUID userID, OSDArray gestures)
906 {
907 NameValueCollection requestArgs = new NameValueCollection
908 {
909 { "RequestMethod", "AddUserData" },
910 { "UserID", userID.ToString() },
911 { "Gestures", OSDParser.SerializeJsonString(gestures) }
912 };
913
914 OSDMap response = WebUtil.PostToService(m_userServerUrl, requestArgs);
915 if (!response["Success"].AsBoolean())
916 {
917 m_log.Warn("[SIMIAN INVENTORY CONNECTOR]: Failed to save active gestures for " + userID + ": " +
918 response["Message"].AsString());
919 }
920 }
921 }
922}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
new file mode 100644
index 0000000..678f738
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs
@@ -0,0 +1,477 @@
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.Collections.Specialized;
31using System.Reflection;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
43
44namespace OpenSim.Services.Connectors.SimianGrid
45{
46 /// <summary>
47 /// Connects avatar presence information (for tracking current location and
48 /// message routing) to the SimianGrid backend
49 /// </summary>
50 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
51 public class SimianPresenceServiceConnector : IPresenceService, IGridUserService, ISharedRegionModule
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private string m_serverUrl = String.Empty;
58 private SimianActivityDetector m_activityDetector;
59 private bool m_Enabled = false;
60
61 #region ISharedRegionModule
62
63 public Type ReplaceableInterface { get { return null; } }
64 public void RegionLoaded(Scene scene) { }
65 public void PostInitialise() { }
66 public void Close() { }
67
68 public SimianPresenceServiceConnector() { m_activityDetector = new SimianActivityDetector(this); }
69 public string Name { get { return "SimianPresenceServiceConnector"; } }
70 public void AddRegion(Scene scene)
71 {
72 if (m_Enabled)
73 {
74 scene.RegisterModuleInterface<IPresenceService>(this);
75 scene.RegisterModuleInterface<IGridUserService>(this);
76
77 m_activityDetector.AddRegion(scene);
78
79 LogoutRegionAgents(scene.RegionInfo.RegionID);
80 }
81 }
82 public void RemoveRegion(Scene scene)
83 {
84 if (m_Enabled)
85 {
86 scene.UnregisterModuleInterface<IPresenceService>(this);
87 scene.UnregisterModuleInterface<IGridUserService>(this);
88
89 m_activityDetector.RemoveRegion(scene);
90
91 LogoutRegionAgents(scene.RegionInfo.RegionID);
92 }
93 }
94
95 #endregion ISharedRegionModule
96
97 public SimianPresenceServiceConnector(IConfigSource source)
98 {
99 CommonInit(source);
100 }
101
102 public void Initialise(IConfigSource source)
103 {
104 IConfig moduleConfig = source.Configs["Modules"];
105 if (moduleConfig != null)
106 {
107 string name = moduleConfig.GetString("PresenceServices", "");
108 if (name == Name)
109 CommonInit(source);
110 }
111 }
112
113 private void CommonInit(IConfigSource source)
114 {
115 IConfig gridConfig = source.Configs["PresenceService"];
116 if (gridConfig != null)
117 {
118 string serviceUrl = gridConfig.GetString("PresenceServerURI");
119 if (!String.IsNullOrEmpty(serviceUrl))
120 {
121 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
122 serviceUrl = serviceUrl + '/';
123 m_serverUrl = serviceUrl;
124 m_Enabled = true;
125 }
126 }
127
128 if (String.IsNullOrEmpty(m_serverUrl))
129 m_log.Info("[SIMIAN PRESENCE CONNECTOR]: No PresenceServerURI specified, disabling connector");
130 }
131
132 #region IPresenceService
133
134 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
135 {
136 m_log.ErrorFormat("[SIMIAN PRESENCE CONNECTOR]: Login requested, UserID={0}, SessionID={1}, SecureSessionID={2}",
137 userID, sessionID, secureSessionID);
138
139 NameValueCollection requestArgs = new NameValueCollection
140 {
141 { "RequestMethod", "AddSession" },
142 { "UserID", userID.ToString() }
143 };
144 if (sessionID != UUID.Zero)
145 {
146 requestArgs["SessionID"] = sessionID.ToString();
147 requestArgs["SecureSessionID"] = secureSessionID.ToString();
148 }
149
150 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
151 bool success = response["Success"].AsBoolean();
152
153 if (!success)
154 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to login agent " + userID + ": " + response["Message"].AsString());
155
156 return success;
157 }
158
159 public bool LogoutAgent(UUID sessionID)
160 {
161// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for agent with sessionID " + sessionID);
162
163 NameValueCollection requestArgs = new NameValueCollection
164 {
165 { "RequestMethod", "RemoveSession" },
166 { "SessionID", sessionID.ToString() }
167 };
168
169 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
170 bool success = response["Success"].AsBoolean();
171
172 if (!success)
173 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to logout agent with sessionID " + sessionID + ": " + response["Message"].AsString());
174
175 return success;
176 }
177
178 public bool LogoutRegionAgents(UUID regionID)
179 {
180// m_log.InfoFormat("[SIMIAN PRESENCE CONNECTOR]: Logout requested for all agents in region " + regionID);
181
182 NameValueCollection requestArgs = new NameValueCollection
183 {
184 { "RequestMethod", "RemoveSessions" },
185 { "SceneID", regionID.ToString() }
186 };
187
188 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
189 bool success = response["Success"].AsBoolean();
190
191 if (!success)
192 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to logout agents from region " + regionID + ": " + response["Message"].AsString());
193
194 return success;
195 }
196
197 public bool ReportAgent(UUID sessionID, UUID regionID)
198 {
199 // Not needed for SimianGrid
200 return true;
201 }
202
203 public PresenceInfo GetAgent(UUID sessionID)
204 {
205// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent with sessionID " + sessionID);
206
207 NameValueCollection requestArgs = new NameValueCollection
208 {
209 { "RequestMethod", "GetSession" },
210 { "SessionID", sessionID.ToString() }
211 };
212
213 OSDMap sessionResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
214 if (sessionResponse["Success"].AsBoolean())
215 {
216 UUID userID = sessionResponse["UserID"].AsUUID();
217 m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
218
219 requestArgs = new NameValueCollection
220 {
221 { "RequestMethod", "GetUser" },
222 { "UserID", userID.ToString() }
223 };
224
225 OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
226 if (userResponse["Success"].AsBoolean())
227 return ResponseToPresenceInfo(sessionResponse, userResponse);
228 else
229 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
230 }
231 else
232 {
233 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve session " + sessionID + ": " + sessionResponse["Message"].AsString());
234 }
235
236 return null;
237 }
238
239 public PresenceInfo[] GetAgents(string[] userIDs)
240 {
241 List<PresenceInfo> presences = new List<PresenceInfo>(userIDs.Length);
242
243 for (int i = 0; i < userIDs.Length; i++)
244 {
245 UUID userID;
246 if (UUID.TryParse(userIDs[i], out userID) && userID != UUID.Zero)
247 presences.AddRange(GetSessions(userID));
248 }
249
250 return presences.ToArray();
251 }
252
253 #endregion IPresenceService
254
255 #region IGridUserService
256
257 public GridUserInfo LoggedIn(string userID)
258 {
259 // Never implemented at the sim
260 return null;
261 }
262
263 public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
264 {
265// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Logging out user " + userID);
266
267 // Remove the session to mark this user offline
268 if (!LogoutAgent(sessionID))
269 return false;
270
271 // Save our last position as user data
272 NameValueCollection requestArgs = new NameValueCollection
273 {
274 { "RequestMethod", "AddUserData" },
275 { "UserID", userID.ToString() },
276 { "LastLocation", SerializeLocation(regionID, lastPosition, lastLookAt) }
277 };
278
279 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
280 bool success = response["Success"].AsBoolean();
281
282 if (!success)
283 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set last location for " + userID + ": " + response["Message"].AsString());
284
285 return success;
286 }
287
288 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
289 {
290// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Setting home location for user " + userID);
291
292 NameValueCollection requestArgs = new NameValueCollection
293 {
294 { "RequestMethod", "AddUserData" },
295 { "UserID", userID.ToString() },
296 { "HomeLocation", SerializeLocation(regionID, position, lookAt) }
297 };
298
299 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
300 bool success = response["Success"].AsBoolean();
301
302 if (!success)
303 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to set home location for " + userID + ": " + response["Message"].AsString());
304
305 return success;
306 }
307
308 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
309 {
310 return UpdateSession(sessionID, regionID, lastPosition, lastLookAt);
311 }
312
313 public GridUserInfo GetGridUserInfo(string user)
314 {
315// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting session data for agent " + user);
316
317 UUID userID = new UUID(user);
318// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
319
320 NameValueCollection requestArgs = new NameValueCollection
321 {
322 { "RequestMethod", "GetUser" },
323 { "UserID", userID.ToString() }
324 };
325
326 OSDMap userResponse = WebUtil.PostToService(m_serverUrl, requestArgs);
327 if (userResponse["Success"].AsBoolean())
328 return ResponseToGridUserInfo(userResponse);
329 else
330 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + userResponse["Message"].AsString());
331
332 return null;
333 }
334
335 #endregion
336
337 #region Helpers
338
339 private OSDMap GetUserData(UUID userID)
340 {
341// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting user data for " + userID);
342
343 NameValueCollection requestArgs = new NameValueCollection
344 {
345 { "RequestMethod", "GetUser" },
346 { "UserID", userID.ToString() }
347 };
348
349 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
350 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
351 return response;
352 else
353 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to retrieve user data for " + userID + ": " + response["Message"].AsString());
354
355 return null;
356 }
357
358 private List<PresenceInfo> GetSessions(UUID userID)
359 {
360 List<PresenceInfo> presences = new List<PresenceInfo>(1);
361
362 OSDMap userResponse = GetUserData(userID);
363 if (userResponse != null)
364 {
365// m_log.DebugFormat("[SIMIAN PRESENCE CONNECTOR]: Requesting sessions for " + userID);
366
367 NameValueCollection requestArgs = new NameValueCollection
368 {
369 { "RequestMethod", "GetSession" },
370 { "UserID", userID.ToString() }
371 };
372
373 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
374 if (response["Success"].AsBoolean())
375 {
376 PresenceInfo presence = ResponseToPresenceInfo(response, userResponse);
377 if (presence != null)
378 presences.Add(presence);
379 }
380// else
381// {
382// m_log.Debug("[SIMIAN PRESENCE CONNECTOR]: No session returned for " + userID + ": " + response["Message"].AsString());
383// }
384 }
385
386 return presences;
387 }
388
389 private bool UpdateSession(UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
390 {
391 // Save our current location as session data
392 NameValueCollection requestArgs = new NameValueCollection
393 {
394 { "RequestMethod", "UpdateSession" },
395 { "SessionID", sessionID.ToString() },
396 { "SceneID", regionID.ToString() },
397 { "ScenePosition", lastPosition.ToString() },
398 { "SceneLookAt", lastLookAt.ToString() }
399 };
400
401 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
402 bool success = response["Success"].AsBoolean();
403
404 if (!success)
405 m_log.Warn("[SIMIAN PRESENCE CONNECTOR]: Failed to update agent session " + sessionID + ": " + response["Message"].AsString());
406
407 return success;
408 }
409
410 private PresenceInfo ResponseToPresenceInfo(OSDMap sessionResponse, OSDMap userResponse)
411 {
412 if (sessionResponse == null)
413 return null;
414
415 PresenceInfo info = new PresenceInfo();
416
417 info.UserID = sessionResponse["UserID"].AsUUID().ToString();
418 info.RegionID = sessionResponse["SceneID"].AsUUID();
419
420 return info;
421 }
422
423 private GridUserInfo ResponseToGridUserInfo(OSDMap userResponse)
424 {
425 if (userResponse != null && userResponse["User"] is OSDMap)
426 {
427 GridUserInfo info = new GridUserInfo();
428
429 info.Online = true;
430 info.UserID = userResponse["UserID"].AsUUID().ToString();
431 info.LastRegionID = userResponse["SceneID"].AsUUID();
432 info.LastPosition = userResponse["ScenePosition"].AsVector3();
433 info.LastLookAt = userResponse["SceneLookAt"].AsVector3();
434
435 OSDMap user = (OSDMap)userResponse["User"];
436
437 info.Login = user["LastLoginDate"].AsDate();
438 info.Logout = user["LastLogoutDate"].AsDate();
439 DeserializeLocation(user["HomeLocation"].AsString(), out info.HomeRegionID, out info.HomePosition, out info.HomeLookAt);
440
441 return info;
442 }
443
444 return null;
445 }
446
447 private string SerializeLocation(UUID regionID, Vector3 position, Vector3 lookAt)
448 {
449 return "{" + String.Format("\"SceneID\":\"{0}\",\"Position\":\"{1}\",\"LookAt\":\"{2}\"", regionID, position, lookAt) + "}";
450 }
451
452 private bool DeserializeLocation(string location, out UUID regionID, out Vector3 position, out Vector3 lookAt)
453 {
454 OSDMap map = null;
455
456 try { map = OSDParser.DeserializeJson(location) as OSDMap; }
457 catch { }
458
459 if (map != null)
460 {
461 regionID = map["SceneID"].AsUUID();
462 if (Vector3.TryParse(map["Position"].AsString(), out position) &&
463 Vector3.TryParse(map["LookAt"].AsString(), out lookAt))
464 {
465 return true;
466 }
467 }
468
469 regionID = UUID.Zero;
470 position = Vector3.Zero;
471 lookAt = Vector3.Zero;
472 return false;
473 }
474
475 #endregion Helpers
476 }
477}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
new file mode 100644
index 0000000..6aefc38
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs
@@ -0,0 +1,478 @@
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.Collections.Specialized;
31using System.Reflection;
32using log4net;
33using Mono.Addins;
34using Nini.Config;
35using OpenMetaverse;
36using OpenMetaverse.StructuredData;
37using OpenSim.Framework;
38using OpenSim.Framework.Client;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
42
43namespace OpenSim.Services.Connectors.SimianGrid
44{
45 /// <summary>
46 /// Avatar profile flags
47 /// </summary>
48 [Flags]
49 public enum ProfileFlags : uint
50 {
51 AllowPublish = 1,
52 MaturePublish = 2,
53 Identified = 4,
54 Transacted = 8,
55 Online = 16
56 }
57
58 /// <summary>
59 /// Connects avatar profile and classified queries to the SimianGrid
60 /// backend
61 /// </summary>
62 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
63 public class SimianProfiles : INonSharedRegionModule
64 {
65 private static readonly ILog m_log =
66 LogManager.GetLogger(
67 MethodBase.GetCurrentMethod().DeclaringType);
68
69 private string m_serverUrl = String.Empty;
70 private bool m_Enabled = false;
71
72 #region INonSharedRegionModule
73
74 public Type ReplaceableInterface { get { return null; } }
75 public void RegionLoaded(Scene scene) { }
76 public void Close() { }
77
78 public SimianProfiles() { }
79 public string Name { get { return "SimianProfiles"; } }
80
81 public void AddRegion(Scene scene)
82 {
83 if (m_Enabled)
84 {
85 CheckEstateManager(scene);
86 scene.EventManager.OnClientConnect += ClientConnectHandler;
87 }
88 }
89
90 public void RemoveRegion(Scene scene)
91 {
92 if (m_Enabled)
93 {
94 scene.EventManager.OnClientConnect -= ClientConnectHandler;
95 }
96 }
97
98 #endregion INonSharedRegionModule
99
100 public SimianProfiles(IConfigSource source)
101 {
102 Initialise(source);
103 }
104
105 public void Initialise(IConfigSource source)
106 {
107 IConfig profileConfig = source.Configs["Profiles"];
108 if (profileConfig == null)
109 return;
110
111 if (profileConfig.GetString("Module", String.Empty) != Name)
112 return;
113
114 m_log.DebugFormat("[SIMIAN PROFILES] module enabled");
115 m_Enabled = true;
116
117 IConfig gridConfig = source.Configs["UserAccountService"];
118 if (gridConfig != null)
119 {
120 string serviceUrl = gridConfig.GetString("UserAccountServerURI");
121 if (!String.IsNullOrEmpty(serviceUrl))
122 {
123 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
124 serviceUrl = serviceUrl + '/';
125 m_serverUrl = serviceUrl;
126 }
127 }
128
129 if (String.IsNullOrEmpty(m_serverUrl))
130 m_log.Info("[SIMIAN PROFILES]: No UserAccountServerURI specified, disabling connector");
131 }
132
133 private void ClientConnectHandler(IClientCore clientCore)
134 {
135 if (clientCore is IClientAPI)
136 {
137 IClientAPI client = (IClientAPI)clientCore;
138
139 // Classifieds
140 client.AddGenericPacketHandler("avatarclassifiedsrequest", AvatarClassifiedsRequestHandler);
141 client.OnClassifiedInfoRequest += ClassifiedInfoRequestHandler;
142 client.OnClassifiedInfoUpdate += ClassifiedInfoUpdateHandler;
143 client.OnClassifiedDelete += ClassifiedDeleteHandler;
144
145 // Picks
146 client.AddGenericPacketHandler("avatarpicksrequest", HandleAvatarPicksRequest);
147 client.AddGenericPacketHandler("pickinforequest", HandlePickInfoRequest);
148 client.OnPickInfoUpdate += PickInfoUpdateHandler;
149 client.OnPickDelete += PickDeleteHandler;
150
151 // Notes
152 client.AddGenericPacketHandler("avatarnotesrequest", HandleAvatarNotesRequest);
153 client.OnAvatarNotesUpdate += AvatarNotesUpdateHandler;
154
155 // Profiles
156 client.OnRequestAvatarProperties += RequestAvatarPropertiesHandler;
157
158 client.OnUpdateAvatarProperties += UpdateAvatarPropertiesHandler;
159 client.OnAvatarInterestUpdate += AvatarInterestUpdateHandler;
160 client.OnUserInfoRequest += UserInfoRequestHandler;
161 client.OnUpdateUserInfo += UpdateUserInfoHandler;
162 }
163 }
164
165 #region Classifieds
166
167 private void AvatarClassifiedsRequestHandler(Object sender, string method, List<String> args)
168 {
169 if (!(sender is IClientAPI))
170 return;
171 IClientAPI client = (IClientAPI)sender;
172
173 UUID targetAvatarID;
174 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
175 {
176 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
177 return;
178 }
179
180 // FIXME: Query the generic key/value store for classifieds
181 client.SendAvatarClassifiedReply(targetAvatarID, new Dictionary<UUID, string>(0));
182 }
183
184 private void ClassifiedInfoRequestHandler(UUID classifiedID, IClientAPI client)
185 {
186 // FIXME: Fetch this info
187 client.SendClassifiedInfoReply(classifiedID, UUID.Zero, 0, Utils.DateTimeToUnixTime(DateTime.UtcNow + TimeSpan.FromDays(1)),
188 0, String.Empty, String.Empty, UUID.Zero, 0, UUID.Zero, String.Empty, Vector3.Zero, String.Empty, 0, 0);
189 }
190
191 private void ClassifiedInfoUpdateHandler(UUID classifiedID, uint category, string name, string description,
192 UUID parcelID, uint parentEstate, UUID snapshotID, Vector3 globalPos, byte classifiedFlags, int price,
193 IClientAPI client)
194 {
195 // FIXME: Save this info
196 }
197
198 private void ClassifiedDeleteHandler(UUID classifiedID, IClientAPI client)
199 {
200 // FIXME: Delete the specified classified ad
201 }
202
203 #endregion Classifieds
204
205 #region Picks
206
207 private void HandleAvatarPicksRequest(Object sender, string method, List<String> args)
208 {
209 if (!(sender is IClientAPI))
210 return;
211 IClientAPI client = (IClientAPI)sender;
212
213 UUID targetAvatarID;
214 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
215 {
216 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
217 return;
218 }
219
220 // FIXME: Fetch these
221 client.SendAvatarPicksReply(targetAvatarID, new Dictionary<UUID, string>(0));
222 }
223
224 private void HandlePickInfoRequest(Object sender, string method, List<String> args)
225 {
226 if (!(sender is IClientAPI))
227 return;
228 IClientAPI client = (IClientAPI)sender;
229
230 UUID avatarID;
231 UUID pickID;
232 if (args.Count < 2 || !UUID.TryParse(args[0], out avatarID) || !UUID.TryParse(args[1], out pickID))
233 {
234 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
235 return;
236 }
237
238 // FIXME: Fetch this
239 client.SendPickInfoReply(pickID, avatarID, false, UUID.Zero, String.Empty, String.Empty, UUID.Zero, String.Empty,
240 String.Empty, String.Empty, Vector3.Zero, 0, false);
241 }
242
243 private void PickInfoUpdateHandler(IClientAPI client, UUID pickID, UUID creatorID, bool topPick, string name,
244 string desc, UUID snapshotID, int sortOrder, bool enabled)
245 {
246 // FIXME: Save this
247 }
248
249 private void PickDeleteHandler(IClientAPI client, UUID pickID)
250 {
251 // FIXME: Delete
252 }
253
254 #endregion Picks
255
256 #region Notes
257
258 private void HandleAvatarNotesRequest(Object sender, string method, List<String> args)
259 {
260 if (!(sender is IClientAPI))
261 return;
262 IClientAPI client = (IClientAPI)sender;
263
264 UUID targetAvatarID;
265 if (args.Count < 1 || !UUID.TryParse(args[0], out targetAvatarID))
266 {
267 m_log.Error("[SIMIAN PROFILES]: Unrecognized arguments for " + method);
268 return;
269 }
270
271 // FIXME: Fetch this
272 client.SendAvatarNotesReply(targetAvatarID, String.Empty);
273 }
274
275 private void AvatarNotesUpdateHandler(IClientAPI client, UUID targetID, string notes)
276 {
277 // FIXME: Save this
278 }
279
280 #endregion Notes
281
282 #region Profiles
283
284 private void RequestAvatarPropertiesHandler(IClientAPI client, UUID avatarID)
285 {
286 m_log.DebugFormat("[SIMIAN PROFILES]: Request avatar properties for {0}",avatarID);
287
288 OSDMap user = FetchUserData(avatarID);
289
290 ProfileFlags flags = ProfileFlags.AllowPublish | ProfileFlags.MaturePublish;
291
292 if (user != null)
293 {
294 OSDMap about = null;
295 if (user.ContainsKey("LLAbout"))
296 {
297 try
298 {
299 about = OSDParser.DeserializeJson(user["LLAbout"].AsString()) as OSDMap;
300 }
301 catch
302 {
303 m_log.WarnFormat("[SIMIAN PROFILES]: Unable to decode LLAbout");
304 }
305 }
306
307 if (about == null)
308 about = new OSDMap(0);
309
310 // Check if this user is a grid operator
311 byte[] charterMember;
312 if (user["AccessLevel"].AsInteger() >= 200)
313 charterMember = Utils.StringToBytes("Operator");
314 else
315 charterMember = Utils.EmptyBytes;
316
317 // Check if the user is online
318 if (client.Scene is Scene)
319 {
320 OpenSim.Services.Interfaces.PresenceInfo[] presences = ((Scene)client.Scene).PresenceService.GetAgents(new string[] { avatarID.ToString() });
321 if (presences != null && presences.Length > 0)
322 flags |= ProfileFlags.Online;
323 }
324
325 // Check if the user is identified
326 if (user["Identified"].AsBoolean())
327 flags |= ProfileFlags.Identified;
328
329 client.SendAvatarProperties(avatarID, about["About"].AsString(), user["CreationDate"].AsDate().ToString("M/d/yyyy",
330 System.Globalization.CultureInfo.InvariantCulture), charterMember, about["FLAbout"].AsString(), (uint)flags,
331 about["FLImage"].AsUUID(), about["Image"].AsUUID(), about["URL"].AsString(), user["Partner"].AsUUID());
332
333 OSDMap interests = null;
334 if (user.ContainsKey("LLInterests"))
335 {
336 try
337 {
338 interests = OSDParser.DeserializeJson(user["LLInterests"].AsString()) as OSDMap;
339 client.SendAvatarInterestsReply(avatarID, interests["WantMask"].AsUInteger(), interests["WantText"].AsString(), interests["SkillsMask"].AsUInteger(), interests["SkillsText"].AsString(), interests["Languages"].AsString());
340 }
341 catch { }
342 }
343
344 if (about == null)
345 about = new OSDMap(0);
346 }
347 else
348 {
349 m_log.Warn("[SIMIAN PROFILES]: Failed to fetch profile information for " + client.Name + ", returning default values");
350 client.SendAvatarProperties(avatarID, String.Empty, "1/1/1970", Utils.EmptyBytes,
351 String.Empty, (uint)flags, UUID.Zero, UUID.Zero, String.Empty, UUID.Zero);
352 }
353 }
354
355 private void UpdateAvatarPropertiesHandler(IClientAPI client, UserProfileData profileData)
356 {
357 OSDMap map = new OSDMap
358 {
359 { "About", OSD.FromString(profileData.AboutText) },
360 { "Image", OSD.FromUUID(profileData.Image) },
361 { "FLAbout", OSD.FromString(profileData.FirstLifeAboutText) },
362 { "FLImage", OSD.FromUUID(profileData.FirstLifeImage) },
363 { "URL", OSD.FromString(profileData.ProfileUrl) }
364 };
365
366 AddUserData(client.AgentId, "LLAbout", map);
367 }
368
369 private void AvatarInterestUpdateHandler(IClientAPI client, uint wantmask, string wanttext, uint skillsmask,
370 string skillstext, string languages)
371 {
372 OSDMap map = new OSDMap
373 {
374 { "WantMask", OSD.FromInteger(wantmask) },
375 { "WantText", OSD.FromString(wanttext) },
376 { "SkillsMask", OSD.FromInteger(skillsmask) },
377 { "SkillsText", OSD.FromString(skillstext) },
378 { "Languages", OSD.FromString(languages) }
379 };
380
381 AddUserData(client.AgentId, "LLInterests", map);
382 }
383
384 private void UserInfoRequestHandler(IClientAPI client)
385 {
386 m_log.Error("[SIMIAN PROFILES]: UserInfoRequestHandler");
387
388 // Fetch this user's e-mail address
389 NameValueCollection requestArgs = new NameValueCollection
390 {
391 { "RequestMethod", "GetUser" },
392 { "UserID", client.AgentId.ToString() }
393 };
394
395 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
396 string email = response["Email"].AsString();
397
398 if (!response["Success"].AsBoolean())
399 m_log.Warn("[SIMIAN PROFILES]: GetUser failed during a user info request for " + client.Name);
400
401 client.SendUserInfoReply(false, true, email);
402 }
403
404 private void UpdateUserInfoHandler(bool imViaEmail, bool visible, IClientAPI client)
405 {
406 m_log.Info("[SIMIAN PROFILES]: Ignoring user info update from " + client.Name);
407 }
408
409 #endregion Profiles
410
411 /// <summary>
412 /// Sanity checks regions for a valid estate owner at startup
413 /// </summary>
414 private void CheckEstateManager(Scene scene)
415 {
416 EstateSettings estate = scene.RegionInfo.EstateSettings;
417
418 if (estate.EstateOwner == UUID.Zero)
419 {
420 // Attempt to lookup the grid admin
421 UserAccount admin = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, UUID.Zero);
422 if (admin != null)
423 {
424 m_log.InfoFormat("[SIMIAN PROFILES]: Setting estate {0} (ID: {1}) owner to {2}", estate.EstateName,
425 estate.EstateID, admin.Name);
426
427 estate.EstateOwner = admin.PrincipalID;
428 estate.Save();
429 }
430 else
431 {
432 m_log.WarnFormat("[SIMIAN PROFILES]: Estate {0} (ID: {1}) does not have an owner", estate.EstateName, estate.EstateID);
433 }
434 }
435 }
436
437 private bool AddUserData(UUID userID, string key, OSDMap value)
438 {
439 NameValueCollection requestArgs = new NameValueCollection
440 {
441 { "RequestMethod", "AddUserData" },
442 { "UserID", userID.ToString() },
443 { key, OSDParser.SerializeJsonString(value) }
444 };
445
446 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
447 bool success = response["Success"].AsBoolean();
448
449 if (!success)
450 m_log.WarnFormat("[SIMIAN PROFILES]: Failed to add user data with key {0} for {1}: {2}", key, userID, response["Message"].AsString());
451
452 return success;
453 }
454
455 private OSDMap FetchUserData(UUID userID)
456 {
457 m_log.DebugFormat("[SIMIAN PROFILES]: Fetch information about {0}",userID);
458
459 NameValueCollection requestArgs = new NameValueCollection
460 {
461 { "RequestMethod", "GetUser" },
462 { "UserID", userID.ToString() }
463 };
464
465 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
466 if (response["Success"].AsBoolean() && response["User"] is OSDMap)
467 {
468 return (OSDMap)response["User"];
469 }
470 else
471 {
472 m_log.Error("[SIMIAN PROFILES]: Failed to fetch user data for " + userID + ": " + response["Message"].AsString());
473 }
474
475 return null;
476 }
477 }
478}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
new file mode 100644
index 0000000..801b424
--- /dev/null
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs
@@ -0,0 +1,333 @@
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.Collections.Specialized;
31using System.Reflection;
32using OpenSim.Framework;
33using OpenSim.Region.Framework.Interfaces;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Services.Interfaces;
36using log4net;
37using Mono.Addins;
38using Nini.Config;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41
42namespace OpenSim.Services.Connectors.SimianGrid
43{
44 /// <summary>
45 /// Connects user account data (creating new users, looking up existing
46 /// users) to the SimianGrid backend
47 /// </summary>
48 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
49 public class SimianUserAccountServiceConnector : IUserAccountService, ISharedRegionModule
50 {
51 private const double CACHE_EXPIRATION_SECONDS = 120.0;
52
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private string m_serverUrl = String.Empty;
58 private ExpiringCache<UUID, UserAccount> m_accountCache = new ExpiringCache<UUID,UserAccount>();
59 private bool m_Enabled;
60
61 #region ISharedRegionModule
62
63 public Type ReplaceableInterface { get { return null; } }
64 public void RegionLoaded(Scene scene) { }
65 public void PostInitialise() { }
66 public void Close() { }
67
68 public SimianUserAccountServiceConnector() { }
69 public string Name { get { return "SimianUserAccountServiceConnector"; } }
70 public void AddRegion(Scene scene) { if (m_Enabled) { scene.RegisterModuleInterface<IUserAccountService>(this); } }
71 public void RemoveRegion(Scene scene) { if (m_Enabled) { scene.UnregisterModuleInterface<IUserAccountService>(this); } }
72
73 #endregion ISharedRegionModule
74
75 public SimianUserAccountServiceConnector(IConfigSource source)
76 {
77 CommonInit(source);
78 }
79
80 public void Initialise(IConfigSource source)
81 {
82 IConfig moduleConfig = source.Configs["Modules"];
83 if (moduleConfig != null)
84 {
85 string name = moduleConfig.GetString("UserAccountServices", "");
86 if (name == Name)
87 CommonInit(source);
88 }
89 }
90
91 private void CommonInit(IConfigSource source)
92 {
93 IConfig gridConfig = source.Configs["UserAccountService"];
94 if (gridConfig != null)
95 {
96 string serviceUrl = gridConfig.GetString("UserAccountServerURI");
97 if (!String.IsNullOrEmpty(serviceUrl))
98 {
99 if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("="))
100 serviceUrl = serviceUrl + '/';
101 m_serverUrl = serviceUrl;
102 m_Enabled = true;
103 }
104 }
105
106 if (String.IsNullOrEmpty(m_serverUrl))
107 m_log.Info("[SIMIAN ACCOUNT CONNECTOR]: No UserAccountServerURI specified, disabling connector");
108 }
109
110 public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
111 {
112 NameValueCollection requestArgs = new NameValueCollection
113 {
114 { "RequestMethod", "GetUser" },
115 { "Name", firstName + ' ' + lastName }
116 };
117
118 return GetUser(requestArgs);
119 }
120
121 public UserAccount GetUserAccount(UUID scopeID, string email)
122 {
123 NameValueCollection requestArgs = new NameValueCollection
124 {
125 { "RequestMethod", "GetUser" },
126 { "Email", email }
127 };
128
129 return GetUser(requestArgs);
130 }
131
132 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
133 {
134 // Cache check
135 UserAccount account;
136 if (m_accountCache.TryGetValue(userID, out account))
137 return account;
138
139 NameValueCollection requestArgs = new NameValueCollection
140 {
141 { "RequestMethod", "GetUser" },
142 { "UserID", userID.ToString() }
143 };
144
145 account = GetUser(requestArgs);
146
147 if (account == null)
148 {
149 // Store null responses too, to avoid repeated lookups for missing accounts
150 m_accountCache.AddOrUpdate(userID, null, CACHE_EXPIRATION_SECONDS);
151 }
152
153 return account;
154 }
155
156 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
157 {
158 List<UserAccount> accounts = new List<UserAccount>();
159
160// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Searching for user accounts with name query " + query);
161
162 NameValueCollection requestArgs = new NameValueCollection
163 {
164 { "RequestMethod", "GetUsers" },
165 { "NameQuery", query }
166 };
167
168 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
169 if (response["Success"].AsBoolean())
170 {
171 OSDArray array = response["Users"] as OSDArray;
172 if (array != null && array.Count > 0)
173 {
174 for (int i = 0; i < array.Count; i++)
175 {
176 UserAccount account = ResponseToUserAccount(array[i] as OSDMap);
177 if (account != null)
178 accounts.Add(account);
179 }
180 }
181 else
182 {
183 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format");
184 }
185 }
186 else
187 {
188 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to search for account data by name " + query);
189 }
190
191 return accounts;
192 }
193
194 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
195 {
196 return null;
197 }
198
199 public bool StoreUserAccount(UserAccount data)
200 {
201// m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name);
202
203 NameValueCollection requestArgs = new NameValueCollection
204 {
205 { "RequestMethod", "AddUser" },
206 { "UserID", data.PrincipalID.ToString() },
207 { "Name", data.Name },
208 { "Email", data.Email },
209 { "AccessLevel", data.UserLevel.ToString() }
210 };
211
212 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
213
214 if (response["Success"].AsBoolean())
215 {
216 m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account data for " + data.Name);
217
218 requestArgs = new NameValueCollection
219 {
220 { "RequestMethod", "AddUserData" },
221 { "UserID", data.PrincipalID.ToString() },
222 { "CreationDate", data.Created.ToString() },
223 { "UserFlags", data.UserFlags.ToString() },
224 { "UserTitle", data.UserTitle }
225 };
226
227 response = WebUtil.PostToService(m_serverUrl, requestArgs);
228 bool success = response["Success"].AsBoolean();
229
230 if (success)
231 {
232 // Cache the user account info
233 m_accountCache.AddOrUpdate(data.PrincipalID, data, CACHE_EXPIRATION_SECONDS);
234 }
235 else
236 {
237 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to store user account data for " + data.Name + ": " + response["Message"].AsString());
238 }
239
240 return success;
241 }
242 else
243 {
244 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to store user account for " + data.Name + ": " + response["Message"].AsString());
245 }
246
247 return false;
248 }
249
250 /// <summary>
251 /// Helper method for the various ways of retrieving a user account
252 /// </summary>
253 /// <param name="requestArgs">Service query parameters</param>
254 /// <returns>A UserAccount object on success, null on failure</returns>
255 private UserAccount GetUser(NameValueCollection requestArgs)
256 {
257 string lookupValue = (requestArgs.Count > 1) ? requestArgs[1] : "(Unknown)";
258// m_log.DebugFormat("[SIMIAN ACCOUNT CONNECTOR]: Looking up user account with query: " + lookupValue);
259
260 OSDMap response = WebUtil.PostToService(m_serverUrl, requestArgs);
261 if (response["Success"].AsBoolean())
262 {
263 OSDMap user = response["User"] as OSDMap;
264 if (user != null)
265 return ResponseToUserAccount(user);
266 else
267 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Account search failed, response data was in an invalid format");
268 }
269 else
270 {
271 m_log.Warn("[SIMIAN ACCOUNT CONNECTOR]: Failed to lookup user account with query: " + lookupValue);
272 }
273
274 return null;
275 }
276
277 /// <summary>
278 /// Convert a User object in LLSD format to a UserAccount
279 /// </summary>
280 /// <param name="response">LLSD containing user account data</param>
281 /// <returns>A UserAccount object on success, null on failure</returns>
282 private UserAccount ResponseToUserAccount(OSDMap response)
283 {
284 if (response == null)
285 return null;
286
287 UserAccount account = new UserAccount();
288 account.PrincipalID = response["UserID"].AsUUID();
289 account.Created = response["CreationDate"].AsInteger();
290 account.Email = response["Email"].AsString();
291 account.ServiceURLs = new Dictionary<string, object>(0);
292 account.UserFlags = response["UserFlags"].AsInteger();
293 account.UserLevel = response["AccessLevel"].AsInteger();
294 account.UserTitle = response["UserTitle"].AsString();
295 GetFirstLastName(response["Name"].AsString(), out account.FirstName, out account.LastName);
296
297 // Cache the user account info
298 m_accountCache.AddOrUpdate(account.PrincipalID, account, CACHE_EXPIRATION_SECONDS);
299
300 return account;
301 }
302
303 /// <summary>
304 /// Convert a name with a single space in it to a first and last name
305 /// </summary>
306 /// <param name="name">A full name such as "John Doe"</param>
307 /// <param name="firstName">First name</param>
308 /// <param name="lastName">Last name (surname)</param>
309 private static void GetFirstLastName(string name, out string firstName, out string lastName)
310 {
311 if (String.IsNullOrEmpty(name))
312 {
313 firstName = String.Empty;
314 lastName = String.Empty;
315 }
316 else
317 {
318 string[] names = name.Split(' ');
319
320 if (names.Length == 2)
321 {
322 firstName = names[0];
323 lastName = names[1];
324 }
325 else
326 {
327 firstName = String.Empty;
328 lastName = name;
329 }
330 }
331 }
332 }
333} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs
new file mode 100644
index 0000000..cdcdecf
--- /dev/null
+++ b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs
@@ -0,0 +1,139 @@
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 OpenMetaverse;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using System.Reflection;
35using OpenSim.Services.Base;
36using OpenSim.Services.Interfaces;
37using OpenSim.Data;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Services.Connectors
43{
44 public class EstateDataService : ServiceBase, IEstateDataService
45 {
46// private static readonly ILog m_log =
47// LogManager.GetLogger(
48// MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected IEstateDataStore m_database;
51
52 public EstateDataService(IConfigSource config)
53 : base(config)
54 {
55 string dllName = String.Empty;
56 string connString = String.Empty;
57
58 // Try reading the [DatabaseService] section, if it exists
59 IConfig dbConfig = config.Configs["DatabaseService"];
60 if (dbConfig != null)
61 {
62 dllName = dbConfig.GetString("StorageProvider", String.Empty);
63 connString = dbConfig.GetString("ConnectionString", String.Empty);
64 connString = dbConfig.GetString("EstateConnectionString", connString);
65 }
66
67 // Try reading the [EstateDataStore] section, if it exists
68 IConfig estConfig = config.Configs["EstateDataStore"];
69 if (estConfig != null)
70 {
71 dllName = estConfig.GetString("StorageProvider", dllName);
72 connString = estConfig.GetString("ConnectionString", connString);
73 }
74
75 // We tried, but this doesn't exist. We can't proceed
76 if (dllName == String.Empty)
77 throw new Exception("No StorageProvider configured");
78
79 m_database = LoadPlugin<IEstateDataStore>(dllName, new Object[] { connString });
80 if (m_database == null)
81 throw new Exception("Could not find a storage interface in the given module");
82 }
83
84 public EstateSettings LoadEstateSettings(UUID regionID, bool create)
85 {
86 return m_database.LoadEstateSettings(regionID, create);
87 }
88
89 public EstateSettings LoadEstateSettings(int estateID)
90 {
91 return m_database.LoadEstateSettings(estateID);
92 }
93
94 public EstateSettings CreateNewEstate()
95 {
96 return m_database.CreateNewEstate();
97 }
98
99 public List<EstateSettings> LoadEstateSettingsAll()
100 {
101 return m_database.LoadEstateSettingsAll();
102 }
103
104 public void StoreEstateSettings(EstateSettings es)
105 {
106 m_database.StoreEstateSettings(es);
107 }
108
109 public List<int> GetEstates(string search)
110 {
111 return m_database.GetEstates(search);
112 }
113
114 public List<int> GetEstatesAll()
115 {
116 return m_database.GetEstatesAll();
117 }
118
119 public List<int> GetEstatesByOwner(UUID ownerID)
120 {
121 return m_database.GetEstatesByOwner(ownerID);
122 }
123
124 public bool LinkRegion(UUID regionID, int estateID)
125 {
126 return m_database.LinkRegion(regionID, estateID);
127 }
128
129 public List<UUID> GetRegions(int estateID)
130 {
131 return m_database.GetRegions(estateID);
132 }
133
134 public bool DeleteEstate(int estateID)
135 {
136 return m_database.DeleteEstate(estateID);
137 }
138 }
139}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
new file mode 100644
index 0000000..ccef50b
--- /dev/null
+++ b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs
@@ -0,0 +1,152 @@
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 OpenMetaverse;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using System.Reflection;
35using OpenSim.Services.Base;
36using OpenSim.Services.Interfaces;
37using OpenSim.Data;
38using OpenSim.Framework;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Services.Connectors
43{
44 public class SimulationDataService : ServiceBase, ISimulationDataService
45 {
46// private static readonly ILog m_log =
47// LogManager.GetLogger(
48// MethodBase.GetCurrentMethod().DeclaringType);
49
50 protected ISimulationDataStore m_database;
51
52 public SimulationDataService(IConfigSource config)
53 : base(config)
54 {
55 string dllName = String.Empty;
56 string connString = String.Empty;
57
58 // Try reading the [DatabaseService] section, if it exists
59 IConfig dbConfig = config.Configs["DatabaseService"];
60 if (dbConfig != null)
61 {
62 dllName = dbConfig.GetString("StorageProvider", String.Empty);
63 connString = dbConfig.GetString("ConnectionString", String.Empty);
64 }
65
66 // Try reading the [SimulationDataStore] section
67 IConfig simConfig = config.Configs["SimulationDataStore"];
68 if (simConfig != null)
69 {
70 dllName = simConfig.GetString("StorageProvider", dllName);
71 connString = simConfig.GetString("ConnectionString", connString);
72 }
73
74 // We tried, but this doesn't exist. We can't proceed
75 if (dllName == String.Empty)
76 throw new Exception("No StorageProvider configured");
77
78 m_database = LoadPlugin<ISimulationDataStore>(dllName, new Object[] { connString });
79 if (m_database == null)
80 throw new Exception("Could not find a storage interface in the given module");
81 }
82
83 public void StoreObject(SceneObjectGroup obj, UUID regionUUID)
84 {
85 m_database.StoreObject(obj, regionUUID);
86 }
87
88 public void RemoveObject(UUID uuid, UUID regionUUID)
89 {
90 m_database.RemoveObject(uuid, regionUUID);
91 }
92
93 public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)
94 {
95 m_database.StorePrimInventory(primID, items);
96 }
97
98 public List<SceneObjectGroup> LoadObjects(UUID regionUUID)
99 {
100 return m_database.LoadObjects(regionUUID);
101 }
102
103 public void StoreTerrain(double[,] terrain, UUID regionID)
104 {
105 m_database.StoreTerrain(terrain, regionID);
106 }
107
108 public double[,] LoadTerrain(UUID regionID)
109 {
110 return m_database.LoadTerrain(regionID);
111 }
112
113 public void StoreLandObject(ILandObject Parcel)
114 {
115 m_database.StoreLandObject(Parcel);
116 }
117
118 public void RemoveLandObject(UUID globalID)
119 {
120 m_database.RemoveLandObject(globalID);
121 }
122
123 public List<LandData> LoadLandObjects(UUID regionUUID)
124 {
125 return m_database.LoadLandObjects(regionUUID);
126 }
127
128 public void StoreRegionSettings(RegionSettings rs)
129 {
130 m_database.StoreRegionSettings(rs);
131 }
132
133 public RegionSettings LoadRegionSettings(UUID regionUUID)
134 {
135 return m_database.LoadRegionSettings(regionUUID);
136 }
137
138 public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
139 {
140 return m_database.LoadRegionWindlightSettings(regionUUID);
141 }
142
143 public void StoreRegionWindlightSettings(RegionLightShareData wl)
144 {
145 m_database.StoreRegionWindlightSettings(wl);
146 }
147 public void RemoveRegionWindlightSettings(UUID regionID)
148 {
149 m_database.RemoveRegionWindlightSettings(regionID);
150 }
151 }
152}
diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
new file mode 100644
index 0000000..24a23dd
--- /dev/null
+++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
@@ -0,0 +1,457 @@
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.Net;
32using System.Reflection;
33using System.Text;
34using System.Collections;
35
36using OpenSim.Framework;
37using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Services.Connectors.Simulation
46{
47 public class SimulationServiceConnector : ISimulationService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 // we use this dictionary to track the pending updateagent requests, maps URI --> position update
52 private Dictionary<string,AgentPosition> m_updateAgentQueue = new Dictionary<string,AgentPosition>();
53
54 //private GridRegion m_Region;
55
56 public SimulationServiceConnector()
57 {
58 }
59
60 public SimulationServiceConnector(IConfigSource config)
61 {
62 //m_Region = region;
63 }
64
65 public IScene GetScene(ulong regionHandle)
66 {
67 return null;
68 }
69
70 public ISimulationService GetInnerService()
71 {
72 return null;
73 }
74
75 #region Agents
76
77 protected virtual string AgentPath()
78 {
79 return "agent/";
80 }
81
82 public bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason)
83 {
84 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateAgent start");
85
86 reason = String.Empty;
87 if (destination == null)
88 {
89 m_log.Debug("[REMOTE SIMULATION CONNECTOR]: Given destination is null");
90 return false;
91 }
92
93 string uri = destination.ServerURI + AgentPath() + aCircuit.AgentID + "/";
94
95 try
96 {
97 OSDMap args = aCircuit.PackAgentCircuitData();
98
99 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
100 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
101 args["destination_name"] = OSD.FromString(destination.RegionName);
102 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
103 args["teleport_flags"] = OSD.FromString(flags.ToString());
104
105 OSDMap result = WebUtil.PostToServiceCompressed(uri, args, 30000);
106 bool success = result["success"].AsBoolean();
107 if (success && result.ContainsKey("_Result"))
108 {
109 OSDMap data = (OSDMap)result["_Result"];
110
111 reason = data["reason"].AsString();
112 success = data["success"].AsBoolean();
113 return success;
114 }
115
116 // Try the old version, uncompressed
117 result = WebUtil.PostToService(uri, args, 30000);
118
119 if (result["Success"].AsBoolean())
120 {
121 if (result.ContainsKey("_Result"))
122 {
123 OSDMap data = (OSDMap)result["_Result"];
124
125 reason = data["reason"].AsString();
126 success = data["success"].AsBoolean();
127 m_log.WarnFormat(
128 "[REMOTE SIMULATION CONNECTOR]: Remote simulator {0} did not accept compressed transfer, suggest updating it.", destination.RegionName);
129 return success;
130 }
131 }
132
133 m_log.WarnFormat(
134 "[REMOTE SIMULATION CONNECTOR]: Failed to create agent {0} {1} at remote simulator {2}",
135 aCircuit.firstname, aCircuit.lastname, destination.RegionName);
136 reason = result["Message"] != null ? result["Message"].AsString() : "error";
137 return false;
138 }
139 catch (Exception e)
140 {
141 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: CreateAgent failed with exception: " + e.ToString());
142 reason = e.Message;
143 }
144
145 return false;
146 }
147
148 /// <summary>
149 /// Send complete data about an agent in this region to a neighbor
150 /// </summary>
151 public bool UpdateAgent(GridRegion destination, AgentData data)
152 {
153 return UpdateAgent(destination, (IAgentData)data, 200000); // yes, 200 seconds
154 }
155
156 /// <summary>
157 /// Send updated position information about an agent in this region to a neighbor
158 /// This operation may be called very frequently if an avatar is moving about in
159 /// the region.
160 /// </summary>
161 public bool UpdateAgent(GridRegion destination, AgentPosition data)
162 {
163 // The basic idea of this code is that the first thread that needs to
164 // send an update for a specific avatar becomes the worker for any subsequent
165 // requests until there are no more outstanding requests. Further, only send the most
166 // recent update; this *should* never be needed but some requests get
167 // slowed down and once that happens the problem with service end point
168 // limits kicks in and nothing proceeds
169 string uri = destination.ServerURI + AgentPath() + data.AgentID + "/";
170 lock (m_updateAgentQueue)
171 {
172 if (m_updateAgentQueue.ContainsKey(uri))
173 {
174 // Another thread is already handling
175 // updates for this simulator, just update
176 // the position and return, overwrites are
177 // not a problem since we only care about the
178 // last update anyway
179 m_updateAgentQueue[uri] = data;
180 return true;
181 }
182
183 // Otherwise update the reference and start processing
184 m_updateAgentQueue[uri] = data;
185 }
186
187 AgentPosition pos = null;
188 while (true)
189 {
190 lock (m_updateAgentQueue)
191 {
192 // save the position
193 AgentPosition lastpos = pos;
194
195 pos = m_updateAgentQueue[uri];
196
197 // this is true if no one put a new
198 // update in the map since the last
199 // one we processed, if thats the
200 // case then we are done
201 if (pos == lastpos)
202 {
203 m_updateAgentQueue.Remove(uri);
204 return true;
205 }
206 }
207
208 UpdateAgent(destination, (IAgentData)pos, 10000);
209 }
210
211 // unreachable
212// return true;
213 }
214
215 /// <summary>
216 /// This is the worker function to send AgentData to a neighbor region
217 /// </summary>
218 private bool UpdateAgent(GridRegion destination, IAgentData cAgentData, int timeout)
219 {
220 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: UpdateAgent start");
221
222 // Eventually, we want to use a caps url instead of the agentID
223 string uri = destination.ServerURI + AgentPath() + cAgentData.AgentID + "/";
224
225 try
226 {
227 OSDMap args = cAgentData.Pack();
228
229 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
230 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
231 args["destination_name"] = OSD.FromString(destination.RegionName);
232 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
233
234 OSDMap result = WebUtil.PutToServiceCompressed(uri, args, timeout);
235 if (result["Success"].AsBoolean())
236 return true;
237
238 result = WebUtil.PutToService(uri, args, timeout);
239
240 return result["Success"].AsBoolean();
241 }
242 catch (Exception e)
243 {
244 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: UpdateAgent failed with exception: " + e.ToString());
245 }
246
247 return false;
248 }
249
250 /// <summary>
251 /// Not sure what sequence causes this function to be invoked. The only calling
252 /// path is through the GET method
253 /// </summary>
254 public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent)
255 {
256 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: RetrieveAgent start");
257
258 agent = null;
259
260 // Eventually, we want to use a caps url instead of the agentID
261 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/";
262
263 try
264 {
265 OSDMap result = WebUtil.GetFromService(uri, 10000);
266 if (result["Success"].AsBoolean())
267 {
268 // OSDMap args = Util.GetOSDMap(result["_RawResult"].AsString());
269 OSDMap args = (OSDMap)result["_Result"];
270 if (args != null)
271 {
272 agent = new CompleteAgentData();
273 agent.Unpack(args, null);
274 return true;
275 }
276 }
277 }
278 catch (Exception e)
279 {
280 m_log.Warn("[REMOTE SIMULATION CONNECTOR]: UpdateAgent failed with exception: " + e.ToString());
281 }
282
283 return false;
284 }
285
286 /// <summary>
287 /// </summary>
288 public bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason)
289 {
290 reason = "Failed to contact destination";
291 version = "Unknown";
292
293 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position);
294
295 IPEndPoint ext = destination.ExternalEndPoint;
296 if (ext == null) return false;
297
298 // Eventually, we want to use a caps url instead of the agentID
299 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/";
300
301 OSDMap request = new OSDMap();
302 request.Add("position", OSD.FromString(position.ToString()));
303
304 try
305 {
306 OSDMap result = WebUtil.ServiceOSDRequest(uri, request, "QUERYACCESS", 10000, false);
307 bool success = result["success"].AsBoolean();
308 if (result.ContainsKey("_Result"))
309 {
310 OSDMap data = (OSDMap)result["_Result"];
311
312 reason = data["reason"].AsString();
313 if (data["version"] != null && data["version"].AsString() != string.Empty)
314 version = data["version"].AsString();
315
316 m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess to {0} returned {1} version {2} ({3})", uri, success, version, data["version"].AsString());
317 }
318
319 if (!success)
320 {
321 if (result.ContainsKey("Message"))
322 {
323 string message = result["Message"].AsString();
324 if (message == "Service request failed: [MethodNotAllowed] MethodNotAllowed") // Old style region
325 {
326 m_log.Info("[REMOTE SIMULATION CONNECTOR]: The above web util error was caused by a TP to a sim that doesn't support QUERYACCESS and can be ignored");
327 return true;
328 }
329
330 reason = result["Message"];
331 }
332 else
333 {
334 reason = "Communications failure";
335 }
336
337 return false;
338 }
339
340 OSDMap resp = (OSDMap)result["_Result"];
341 success = resp["success"].AsBoolean();
342 reason = resp["reason"].AsString();
343
344 return success;
345 }
346 catch (Exception e)
347 {
348 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] QueryAcess failed with exception; {0}",e.ToString());
349 }
350
351 return false;
352 }
353
354 /// <summary>
355 /// </summary>
356 public bool ReleaseAgent(UUID origin, UUID id, string uri)
357 {
358 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: ReleaseAgent start");
359
360 try
361 {
362 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false);
363 }
364 catch (Exception e)
365 {
366 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] ReleaseAgent failed with exception; {0}",e.ToString());
367 }
368
369 return true;
370 }
371
372 private bool CloseAgent(GridRegion destination, UUID id, bool ChildOnly)
373 {
374// m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CloseAgent start");
375
376 string uri = destination.ServerURI + AgentPath() + id + "/" + destination.RegionID.ToString() + "/";
377
378 try
379 {
380 WebUtil.ServiceOSDRequest(uri, null, "DELETE", 10000, false);
381 }
382 catch (Exception e)
383 {
384 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CloseAgent failed with exception; {0}",e.ToString());
385 }
386
387 return true;
388 }
389
390 public bool CloseChildAgent(GridRegion destination, UUID id)
391 {
392 return CloseAgent(destination, id, true);
393 }
394
395 public bool CloseAgent(GridRegion destination, UUID id)
396 {
397 return CloseAgent(destination, id, false);
398 }
399
400 #endregion Agents
401
402 #region Objects
403
404 protected virtual string ObjectPath()
405 {
406 return "object/";
407 }
408
409 /// <summary>
410 ///
411 /// </summary>
412 public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall)
413 {
414 // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: CreateObject start");
415
416 string uri = destination.ServerURI + ObjectPath() + sog.UUID + "/";
417
418 try
419 {
420 OSDMap args = new OSDMap(2);
421
422 args["sog"] = OSD.FromString(sog.ToXml2());
423 args["extra"] = OSD.FromString(sog.ExtraToXmlString());
424 args["modified"] = OSD.FromBoolean(sog.HasGroupChanged);
425
426 string state = sog.GetStateSnapshot();
427 if (state.Length > 0)
428 args["state"] = OSD.FromString(state);
429
430 // Add the input general arguments
431 args["destination_x"] = OSD.FromString(destination.RegionLocX.ToString());
432 args["destination_y"] = OSD.FromString(destination.RegionLocY.ToString());
433 args["destination_name"] = OSD.FromString(destination.RegionName);
434 args["destination_uuid"] = OSD.FromString(destination.RegionID.ToString());
435
436 WebUtil.PostToService(uri, args, 40000);
437 }
438 catch (Exception e)
439 {
440 m_log.WarnFormat("[REMOTE SIMULATION CONNECTOR] CreateObject failed with exception; {0}",e.ToString());
441 }
442
443 return true;
444 }
445
446 /// <summary>
447 ///
448 /// </summary>
449 public bool CreateObject(GridRegion destination, UUID userID, UUID itemID)
450 {
451 // TODO, not that urgent
452 return false;
453 }
454
455 #endregion Objects
456 }
457}
diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
new file mode 100644
index 0000000..60f3abe
--- /dev/null
+++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs
@@ -0,0 +1,282 @@
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.Server.Base;
37using OpenSim.Services.Interfaces;
38using OpenMetaverse;
39
40namespace OpenSim.Services.Connectors
41{
42 public class UserAccountServicesConnector : 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 UserAccountServicesConnector()
51 {
52 }
53
54 public UserAccountServicesConnector(string serverURI)
55 {
56 m_ServerURI = serverURI.TrimEnd('/');
57 }
58
59 public UserAccountServicesConnector(IConfigSource source)
60 {
61 Initialise(source);
62 }
63
64 public virtual void Initialise(IConfigSource source)
65 {
66 IConfig assetConfig = source.Configs["UserAccountService"];
67 if (assetConfig == null)
68 {
69 m_log.Error("[ACCOUNT CONNECTOR]: UserAccountService missing from OpenSim.ini");
70 throw new Exception("User account connector init error");
71 }
72
73 string serviceURI = assetConfig.GetString("UserAccountServerURI",
74 String.Empty);
75
76 if (serviceURI == String.Empty)
77 {
78 m_log.Error("[ACCOUNT CONNECTOR]: No Server URI named in section UserAccountService");
79 throw new Exception("User account connector init error");
80 }
81 m_ServerURI = serviceURI;
82 }
83
84 public virtual UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName)
85 {
86 Dictionary<string, object> sendData = new Dictionary<string, object>();
87 //sendData["SCOPEID"] = scopeID.ToString();
88 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
89 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
90 sendData["METHOD"] = "getaccount";
91
92 sendData["ScopeID"] = scopeID;
93 sendData["FirstName"] = firstName.ToString();
94 sendData["LastName"] = lastName.ToString();
95
96 return SendAndGetReply(sendData);
97 }
98
99 public virtual UserAccount GetUserAccount(UUID scopeID, string email)
100 {
101 Dictionary<string, object> sendData = new Dictionary<string, object>();
102 //sendData["SCOPEID"] = scopeID.ToString();
103 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
104 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
105 sendData["METHOD"] = "getaccount";
106
107 sendData["ScopeID"] = scopeID;
108 sendData["Email"] = email;
109
110 return SendAndGetReply(sendData);
111 }
112
113 public virtual UserAccount GetUserAccount(UUID scopeID, UUID userID)
114 {
115 //m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccount {0}", userID);
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"] = "getaccounts";
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 List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
190 {
191 return null; // Not implemented for regions
192 }
193
194 public virtual bool StoreUserAccount(UserAccount data)
195 {
196 Dictionary<string, object> sendData = new Dictionary<string, object>();
197 //sendData["SCOPEID"] = scopeID.ToString();
198 sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
199 sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
200 sendData["METHOD"] = "setaccount";
201
202 Dictionary<string, object> structData = data.ToKeyValuePairs();
203
204 foreach (KeyValuePair<string,object> kvp in structData)
205 sendData[kvp.Key] = kvp.Value.ToString();
206
207 return SendAndGetBoolReply(sendData);
208 }
209
210 private UserAccount SendAndGetReply(Dictionary<string, object> sendData)
211 {
212 string reply = string.Empty;
213 string reqString = ServerUtils.BuildQueryString(sendData);
214 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
215 try
216 {
217 reply = SynchronousRestFormsRequester.MakeRequest("POST",
218 m_ServerURI + "/accounts",
219 reqString);
220 if (reply == null || (reply != null && reply == string.Empty))
221 {
222 m_log.DebugFormat("[ACCOUNT CONNECTOR]: GetUserAccount received null or empty reply");
223 return null;
224 }
225 }
226 catch (Exception e)
227 {
228 m_log.DebugFormat("[ACCOUNT CONNECTOR]: Exception when contacting user account server: {0}", e.Message);
229 }
230
231 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
232 UserAccount account = null;
233
234 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
235 {
236 if (replyData["result"] is Dictionary<string, object>)
237 {
238 account = new UserAccount((Dictionary<string, object>)replyData["result"]);
239 }
240 }
241
242 return account;
243
244 }
245
246 private bool SendAndGetBoolReply(Dictionary<string, object> sendData)
247 {
248 string reqString = ServerUtils.BuildQueryString(sendData);
249 // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: queryString = {0}", reqString);
250 try
251 {
252 string reply = SynchronousRestFormsRequester.MakeRequest("POST",
253 m_ServerURI + "/accounts",
254 reqString);
255 if (reply != string.Empty)
256 {
257 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
258
259 if (replyData.ContainsKey("result"))
260 {
261 if (replyData["result"].ToString().ToLower() == "success")
262 return true;
263 else
264 return false;
265 }
266 else
267 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount reply data does not contain result field");
268
269 }
270 else
271 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Set or Create UserAccount received empty reply");
272 }
273 catch (Exception e)
274 {
275 m_log.DebugFormat("[ACCOUNTS CONNECTOR]: Exception when contacting user account server: {0}", e.Message);
276 }
277
278 return false;
279 }
280
281 }
282}
diff --git a/OpenSim/Services/FreeswitchService/FreeswitchService.cs b/OpenSim/Services/FreeswitchService/FreeswitchService.cs
index 0a38300..201e72f 100644
--- a/OpenSim/Services/FreeswitchService/FreeswitchService.cs
+++ b/OpenSim/Services/FreeswitchService/FreeswitchService.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Text;
29using System.Reflection; 30using System.Reflection;
30using Nini.Config; 31using Nini.Config;
31using log4net; 32using log4net;
@@ -33,19 +34,374 @@ using OpenSim.Framework;
33using OpenSim.Data; 34using OpenSim.Data;
34using OpenSim.Services.Interfaces; 35using OpenSim.Services.Interfaces;
35using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using System.Collections;
36 39
37namespace OpenSim.Services.FreeswitchService 40namespace OpenSim.Services.FreeswitchService
38{ 41{
39 public class FreeswitchService : FreeswitchServiceBase, IFreeswitchService 42 public class FreeswitchService : FreeswitchServiceBase, IFreeswitchService
40 { 43 {
41 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 45
43 public FreeswitchService(IConfigSource config) : base(config) 46 public FreeswitchService(IConfigSource config) : base(config)
44 { 47 {
45 // Perform initilialization here 48 // Perform initilialization here
46 } 49 }
47 50
51 public Hashtable HandleDialplanRequest(Hashtable request)
52 {
53 m_log.DebugFormat("[FreeSwitchVoice]: HandleDialplanRequest called with {0}",request.ToString());
54
55 Hashtable response = new Hashtable();
56
57// foreach (DictionaryEntry item in request)
58// {
59//// m_log.InfoFormat("[FreeSwitchDirectory]: requestBody item {0} {1}",item.Key, item.Value);
60// }
61
62 string requestcontext = (string) request["Hunt-Context"];
63 response["content_type"] = "text/xml";
64 response["keepalive"] = false;
65 response["int_response_code"] = 200;
66
67 if (m_freeSwitchContext != String.Empty && m_freeSwitchContext != requestcontext)
68 {
69 m_log.Debug("[FreeSwitchDirectory]: returning empty as it's for another context");
70 response["str_response_string"] = "";
71 }
72 else
73 {
74 response["str_response_string"] = String.Format(@"<?xml version=""1.0"" encoding=""utf-8""?>
75 <document type=""freeswitch/xml"">
76 <section name=""dialplan"">
77 <context name=""{0}"">" +
78
79/* <!-- dial via SIP uri -->
80 <extension name=""sip_uri"">
81 <condition field=""destination_number"" expression=""^sip:(.*)$"">
82 <action application=""bridge"" data=""sofia/${use_profile}/$1""/>
83 <!--<action application=""bridge"" data=""$1""/>-->
84 </condition>
85 </extension>*/
86
87 @"<extension name=""opensim_conferences"">
88 <condition field=""destination_number"" expression=""^confctl-(.*)$"">
89 <action application=""answer""/>
90 <action application=""conference"" data=""$1-{1}@{0}""/>
91 </condition>
92 </extension>
93
94 <extension name=""opensim_conf"">
95 <condition field=""destination_number"" expression=""^conf-(.*)$"">
96 <action application=""answer""/>
97 <action application=""conference"" data=""$1-{1}@{0}""/>
98 </condition>
99 </extension>
100
101 <extension name=""avatar"">
102 <condition field=""destination_number"" expression=""^(x.*)$"">
103 <action application=""bridge"" data=""user/$1""/>
104 </condition>
105 </extension>
106
107 </context>
108 </section>
109 </document>", m_freeSwitchContext, m_freeSwitchRealm);
110 }
111
112 return response;
113 }
114
115 public Hashtable HandleDirectoryRequest(Hashtable request)
116 {
117 Hashtable response = new Hashtable();
118 string domain = (string) request["domain"];
119 if (domain != m_freeSwitchRealm)
120 {
121 response["content_type"] = "text/xml";
122 response["keepalive"] = false;
123 response["int_response_code"] = 200;
124 response["str_response_string"] = "";
125 }
126 else
127 {
128// m_log.DebugFormat("[FreeSwitchDirectory]: HandleDirectoryRequest called with {0}",request.ToString());
129
130 // information in the request we might be interested in
131
132 // Request 1 sip_auth for users account
133
134 //Event-Calling-Function=sofia_reg_parse_auth
135 //Event-Calling-Line-Number=1494
136 //action=sip_auth
137 //sip_user_agent=Vivox-SDK-2.1.3010.6151-Mac%20(Feb-11-2009/16%3A42%3A41)
138 //sip_auth_username=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==)
139 //sip_auth_realm=9.20.151.43
140 //sip_contact_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==)
141 //sip_contact_host=192.168.0.3 // this shouldnt really be a local IP, investigate STUN servers
142 //sip_to_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D
143 //sip_to_host=9.20.151.43
144 //sip_auth_method=REGISTER
145 //user=xhZuXKmRpECyr2AARJYyGgg%3D%3D
146 //domain=9.20.151.43
147 //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup
148
149// foreach (DictionaryEntry item in request)
150// m_log.DebugFormat("[FreeSwitchDirectory]: requestBody item {0} {1}", item.Key, item.Value);
151
152 string eventCallingFunction = (string) request["Event-Calling-Function"];
153 if (eventCallingFunction == null)
154 {
155 eventCallingFunction = "sofia_reg_parse_auth";
156 }
157
158 if (eventCallingFunction.Length == 0)
159 {
160 eventCallingFunction = "sofia_reg_parse_auth";
161 }
162
163 if (eventCallingFunction == "sofia_reg_parse_auth")
164 {
165 string sipAuthMethod = (string)request["sip_auth_method"];
166
167 if (sipAuthMethod == "REGISTER")
168 {
169 response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request);
170 }
171 else if (sipAuthMethod == "INVITE")
172 {
173 response = HandleInvite(m_freeSwitchContext, m_freeSwitchRealm, request);
174 }
175 else
176 {
177 m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod);
178 response["int_response_code"] = 404;
179 response["content_type"] = "text/xml";
180 response["str_response_string"] = "";
181 }
182 }
183 else if (eventCallingFunction == "switch_xml_locate_user")
184 {
185 response = HandleLocateUser(m_freeSwitchRealm, request);
186 }
187 else if (eventCallingFunction == "user_data_function") // gets called when an avatar to avatar call is made
188 {
189 response = HandleLocateUser(m_freeSwitchRealm, request);
190 }
191 else if (eventCallingFunction == "user_outgoing_channel")
192 {
193 response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request);
194 }
195 else if (eventCallingFunction == "config_sofia") // happens once on freeswitch startup
196 {
197 response = HandleConfigSofia(m_freeSwitchContext, m_freeSwitchRealm, request);
198 }
199 else if (eventCallingFunction == "switch_load_network_lists")
200 {
201 //response = HandleLoadNetworkLists(request);
202 response["int_response_code"] = 404;
203 response["keepalive"] = false;
204 response["content_type"] = "text/xml";
205 response["str_response_string"] = "";
206 }
207 else
208 {
209 m_log.ErrorFormat("[FreeSwitchVoice]: HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction);
210 response["int_response_code"] = 404;
211 response["keepalive"] = false;
212 response["content_type"] = "text/xml";
213 response["str_response_string"] = "";
214 }
215 }
216 return response;
217 }
218
219 private Hashtable HandleRegister(string Context, string Realm, Hashtable request)
220 {
221 m_log.Info("[FreeSwitchDirectory]: HandleRegister called");
222
223 // TODO the password we return needs to match that sent in the request, this is hard coded for now
224 string password = "1234";
225 string domain = (string) request["domain"];
226 string user = (string) request["user"];
227
228 Hashtable response = new Hashtable();
229 response["content_type"] = "text/xml";
230 response["keepalive"] = false;
231 response["int_response_code"] = 200;
232
233 response["str_response_string"] = String.Format(
234 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
235 "<document type=\"freeswitch/xml\">\r\n" +
236 "<section name=\"directory\" description=\"User Directory\">\r\n" +
237 "<domain name=\"{0}\">\r\n" +
238 "<user id=\"{1}\">\r\n" +
239 "<params>\r\n" +
240 "<param name=\"password\" value=\"{2}\" />\r\n" +
241 "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" +
242 "</params>\r\n" +
243 "<variables>\r\n" +
244 "<variable name=\"user_context\" value=\"{3}\" />\r\n" +
245 "<variable name=\"presence_id\" value=\"{1}@{0}\"/>"+
246 "</variables>\r\n" +
247 "</user>\r\n" +
248 "</domain>\r\n" +
249 "</section>\r\n" +
250 "</document>\r\n",
251 domain , user, password, Context);
252
253 return response;
254 }
255
256 private Hashtable HandleInvite(string Context, string Realm, Hashtable request)
257 {
258 m_log.Info("[FreeSwitchDirectory]: HandleInvite called");
259
260 // TODO the password we return needs to match that sent in the request, this is hard coded for now
261 string password = "1234";
262 string domain = (string) request["domain"];
263 string user = (string) request["user"];
264 string sipRequestUser = (string) request["sip_request_user"];
265
266 Hashtable response = new Hashtable();
267 response["content_type"] = "text/xml";
268 response["keepalive"] = false;
269 response["int_response_code"] = 200;
270 response["str_response_string"] = String.Format(
271 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
272 "<document type=\"freeswitch/xml\">\r\n" +
273 "<section name=\"directory\" description=\"User Directory\">\r\n" +
274 "<domain name=\"{0}\">\r\n" +
275 "<user id=\"{1}\">\r\n" +
276 "<params>\r\n" +
277 "<param name=\"password\" value=\"{2}\" />\r\n" +
278 "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${1}@${{dialed_domain}}}}${{sofia_contact(${1}@${{dialed_domain}})}}\"/>\r\n" +
279 "</params>\r\n" +
280 "<variables>\r\n" +
281 "<variable name=\"user_context\" value=\"{4}\" />\r\n" +
282 "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+
283 "</variables>\r\n" +
284 "</user>\r\n" +
285 "<user id=\"{3}\">\r\n" +
286 "<params>\r\n" +
287 "<param name=\"password\" value=\"{2}\" />\r\n" +
288 "<param name=\"dial-string\" value=\"{{sip_contact_user={1}}}{{presence_id=${3}@${{dialed_domain}}}}${{sofia_contact(${3}@${{dialed_domain}})}}\"/>\r\n" +
289 "</params>\r\n" +
290 "<variables>\r\n" +
291 "<variable name=\"user_context\" value=\"{4}\" />\r\n" +
292 "<variable name=\"presence_id\" value=\"{3}@$${{domain}}\"/>"+
293 "</variables>\r\n" +
294 "</user>\r\n" +
295 "</domain>\r\n" +
296 "</section>\r\n" +
297 "</document>\r\n",
298 domain , user, password,sipRequestUser, Context);
299
300 return response;
301 }
48 302
49 // Implement IFreeswitchService here 303 private Hashtable HandleLocateUser(String Realm, Hashtable request)
304 {
305 m_log.Info("[FreeSwitchDirectory]: HandleLocateUser called");
306
307 // TODO the password we return needs to match that sent in the request, this is hard coded for now
308 string domain = (string) request["domain"];
309 string user = (string) request["user"];
310
311 Hashtable response = new Hashtable();
312 response["content_type"] = "text/xml";
313 response["keepalive"] = false;
314 response["int_response_code"] = 200;
315 response["str_response_string"] = String.Format(
316 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
317 "<document type=\"freeswitch/xml\">\r\n" +
318 "<section name=\"directory\" description=\"User Directory\">\r\n" +
319 "<domain name=\"{0}\">\r\n" +
320 "<params>\r\n" +
321 "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" +
322 "</params>\r\n" +
323 "<user id=\"{1}\">\r\n" +
324 "<variables>\r\n"+
325 "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+
326 "<variable name=\"presence_id\" value=\"{1}@$${{domain}}\"/>"+
327 "</variables>\r\n"+
328 "</user>\r\n" +
329 "</domain>\r\n" +
330 "</section>\r\n" +
331 "</document>\r\n",
332 domain , user);
333
334 return response;
335 }
336
337 private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request)
338 {
339 m_log.Info("[FreeSwitchDirectory]: HandleConfigSofia called.");
340
341 // TODO the password we return needs to match that sent in the request, this is hard coded for now
342 string domain = (string) request["domain"];
343
344 Hashtable response = new Hashtable();
345 response["content_type"] = "text/xml";
346 response["keepalive"] = false;
347 response["int_response_code"] = 200;
348 response["str_response_string"] = String.Format(
349 "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
350 "<document type=\"freeswitch/xml\">\r\n" +
351 "<section name=\"directory\" description=\"User Directory\">\r\n" +
352 "<domain name=\"{0}\">\r\n" +
353 "<params>\r\n" +
354 "<param name=\"dial-string\" value=\"{{sip_contact_user=${{dialed_user}}}}{{presence_id=${{dialed_user}}@${{dialed_domain}}}}${{sofia_contact(${{dialed_user}}@${{dialed_domain}})}}\"/>\r\n" +
355 "</params>\r\n" +
356 "<groups name=\"default\">\r\n"+
357 "<users>\r\n"+
358 "<user id=\"$${{default_provider}}\">\r\n"+
359 "<gateways>\r\n"+
360 "<gateway name=\"$${{default_provider}}\">\r\n"+
361 "<param name=\"username\" value=\"$${{default_provider_username}}\"/>\r\n"+
362 "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+
363 "<param name=\"from-user\" value=\"$${{default_provider_username}}\"/>\r\n"+
364 "<param name=\"from-domain\" value=\"$${{default_provider_from_domain}}\"/>\r\n"+
365 "<param name=\"expire-seconds\" value=\"600\"/>\r\n"+
366 "<param name=\"register\" value=\"$${{default_provider_register}}\"/>\r\n"+
367 "<param name=\"retry-seconds\" value=\"30\"/>\r\n"+
368 "<param name=\"extension\" value=\"$${{default_provider_contact}}\"/>\r\n"+
369 "<param name=\"contact-params\" value=\"domain_name=$${{domain}}\"/>\r\n"+
370 "<param name=\"context\" value=\"{1}\"/>\r\n"+
371 "</gateway>\r\n"+
372 "</gateways>\r\n"+
373 "<params>\r\n"+
374 "<param name=\"password\" value=\"$${{default_provider_password}}\"/>\r\n"+
375 "</params>\r\n"+
376 "</user>\r\n"+
377 "</users>"+
378 "</groups>\r\n" +
379 "<variables>\r\n"+
380 "<variable name=\"default_gateway\" value=\"$${{default_provider}}\"/>\r\n"+
381 "</variables>\r\n"+
382 "</domain>\r\n" +
383 "</section>\r\n" +
384 "</document>\r\n",
385 domain, Context);
386
387 return response;
388 }
389
390 public string GetJsonConfig()
391 {
392 OSDMap map = new OSDMap(9);
393
394 map.Add("Realm", m_freeSwitchRealm);
395 map.Add("SIPProxy", m_freeSwitchSIPProxy);
396 map.Add("AttemptUseSTUN", m_freeSwitchAttemptUseSTUN);
397 map.Add("EchoServer", m_freeSwitchEchoServer);
398 map.Add("EchoPort", m_freeSwitchEchoPort);
399 map.Add("DefaultWellKnownIP", m_freeSwitchDefaultWellKnownIP);
400 map.Add("DefaultTimeout", m_freeSwitchDefaultTimeout);
401 map.Add("Context", m_freeSwitchContext);
402 map.Add("APIPrefix", m_freeSwitchAPIPrefix);
403
404 return OSDParser.SerializeJsonString(map);
405 }
50 } 406 }
51} 407}
diff --git a/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs b/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs
index 83fecef..25c18b6 100644
--- a/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs
+++ b/OpenSim/Services/FreeswitchService/FreeswitchServiceBase.cs
@@ -31,11 +31,28 @@ using Nini.Config;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Services.Interfaces; 32using OpenSim.Services.Interfaces;
33using OpenSim.Services.Base; 33using OpenSim.Services.Base;
34using log4net;
34 35
35namespace OpenSim.Services.FreeswitchService 36namespace OpenSim.Services.FreeswitchService
36{ 37{
37 public class FreeswitchServiceBase : ServiceBase 38 public class FreeswitchServiceBase : ServiceBase
38 { 39 {
40 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 protected string m_freeSwitchRealm;
43 protected string m_freeSwitchSIPProxy;
44 protected bool m_freeSwitchAttemptUseSTUN = false;
45 protected string m_freeSwitchEchoServer;
46 protected int m_freeSwitchEchoPort = 50505;
47 protected string m_freeSwitchDefaultWellKnownIP;
48 protected int m_freeSwitchDefaultTimeout = 5000;
49 protected string m_freeSwitchContext = "default";
50 protected string m_freeSwitchServerUser = "freeswitch";
51 protected string m_freeSwitchServerPass = "password";
52 protected readonly string m_freeSwitchAPIPrefix = "/fsapi";
53
54 protected bool m_Enabled = false;
55
39 public FreeswitchServiceBase(IConfigSource config) : base(config) 56 public FreeswitchServiceBase(IConfigSource config) : base(config)
40 { 57 {
41 // 58 //
@@ -44,7 +61,24 @@ namespace OpenSim.Services.FreeswitchService
44 IConfig freeswitchConfig = config.Configs["FreeswitchService"]; 61 IConfig freeswitchConfig = config.Configs["FreeswitchService"];
45 if (freeswitchConfig != null) 62 if (freeswitchConfig != null)
46 { 63 {
47 // Read config here !! 64 m_freeSwitchDefaultWellKnownIP = freeswitchConfig.GetString("ServerAddress", String.Empty);
65 if (m_freeSwitchDefaultWellKnownIP == String.Empty)
66 {
67 m_log.Error("[FREESWITCH]: No ServerAddress given, cannot start service.");
68 return;
69 }
70
71 m_freeSwitchRealm = freeswitchConfig.GetString("Realm", m_freeSwitchDefaultWellKnownIP);
72 m_freeSwitchSIPProxy = freeswitchConfig.GetString("SIPProxy", m_freeSwitchDefaultWellKnownIP + ":5060");
73 m_freeSwitchEchoServer = freeswitchConfig.GetString("EchoServer", m_freeSwitchDefaultWellKnownIP);
74 m_freeSwitchEchoPort = freeswitchConfig.GetInt("EchoPort", m_freeSwitchEchoPort);
75 m_freeSwitchAttemptUseSTUN = freeswitchConfig.GetBoolean("AttemptSTUN", false); // This may not work
76 m_freeSwitchDefaultTimeout = freeswitchConfig.GetInt("DefaultTimeout", m_freeSwitchDefaultTimeout);
77 m_freeSwitchContext = freeswitchConfig.GetString("Context", m_freeSwitchContext);
78 m_freeSwitchServerUser = freeswitchConfig.GetString("UserName", m_freeSwitchServerUser);
79 m_freeSwitchServerPass = freeswitchConfig.GetString("Password", m_freeSwitchServerPass);
80
81 m_Enabled = true;
48 } 82 }
49 } 83 }
50 } 84 }
diff --git a/OpenSim/Services/Friends/FriendsService.cs b/OpenSim/Services/Friends/FriendsService.cs
new file mode 100644
index 0000000..e2033ac
--- /dev/null
+++ b/OpenSim/Services/Friends/FriendsService.cs
@@ -0,0 +1,115 @@
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 OpenMetaverse;
29using OpenSim.Framework;
30using System;
31using System.Collections.Generic;
32using OpenSim.Services.Interfaces;
33using OpenSim.Data;
34using Nini.Config;
35using log4net;
36using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
37
38namespace OpenSim.Services.Friends
39{
40 public class FriendsService : FriendsServiceBase, IFriendsService
41 {
42 public FriendsService(IConfigSource config) : base(config)
43 {
44 }
45
46 public virtual FriendInfo[] GetFriends(UUID PrincipalID)
47 {
48 FriendsData[] data = m_Database.GetFriends(PrincipalID);
49 List<FriendInfo> info = new List<FriendInfo>();
50
51 foreach (FriendsData d in data)
52 {
53 FriendInfo i = new FriendInfo();
54
55 i.PrincipalID = new UUID(d.PrincipalID);
56 i.Friend = d.Friend;
57 i.MyFlags = Convert.ToInt32(d.Data["Flags"]);
58 i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]);
59
60 info.Add(i);
61 }
62
63 return info.ToArray();
64 }
65
66 public virtual FriendInfo[] GetFriends(string PrincipalID)
67 {
68 FriendsData[] data = m_Database.GetFriends(PrincipalID);
69 List<FriendInfo> info = new List<FriendInfo>();
70
71 foreach (FriendsData d in data)
72 {
73 FriendInfo i = new FriendInfo();
74
75 if (!UUID.TryParse(d.PrincipalID, out i.PrincipalID))
76 {
77 string tmp = string.Empty;
78 if (!Util.ParseUniversalUserIdentifier(d.PrincipalID, out i.PrincipalID, out tmp, out tmp, out tmp, out tmp))
79 // bad record. ignore this entry
80 continue;
81 }
82 i.Friend = d.Friend;
83 i.MyFlags = Convert.ToInt32(d.Data["Flags"]);
84 i.TheirFlags = Convert.ToInt32(d.Data["TheirFlags"]);
85
86 info.Add(i);
87 }
88
89 return info.ToArray();
90 }
91
92 public virtual bool StoreFriend(string PrincipalID, string Friend, int flags)
93 {
94 FriendsData d = new FriendsData();
95
96 d.PrincipalID = PrincipalID;
97 d.Friend = Friend;
98 d.Data = new Dictionary<string, string>();
99 d.Data["Flags"] = flags.ToString();
100
101 return m_Database.Store(d);
102 }
103
104 public bool Delete(string principalID, string friend)
105 {
106 return m_Database.Delete(principalID, friend);
107 }
108
109 public virtual bool Delete(UUID PrincipalID, string Friend)
110 {
111 return m_Database.Delete(PrincipalID, Friend);
112 }
113
114 }
115}
diff --git a/OpenSim/Services/Friends/FriendsServiceBase.cs b/OpenSim/Services/Friends/FriendsServiceBase.cs
new file mode 100644
index 0000000..6ab0bff
--- /dev/null
+++ b/OpenSim/Services/Friends/FriendsServiceBase.cs
@@ -0,0 +1,89 @@
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.Reflection;
30using log4net;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Data;
34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Base;
36
37namespace OpenSim.Services.Friends
38{
39 public class FriendsServiceBase : ServiceBase
40 {
41 protected IFriendsData m_Database = null;
42
43 public FriendsServiceBase(IConfigSource config) : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47
48 //
49 // Try reading the [FriendsService] section first, if it exists
50 //
51 IConfig friendsConfig = config.Configs["FriendsService"];
52 if (friendsConfig != null)
53 {
54 dllName = friendsConfig.GetString("StorageProvider", dllName);
55 connString = friendsConfig.GetString("ConnectionString", connString);
56 }
57
58 //
59 // Try reading the [DatabaseService] section, if it exists
60 //
61 IConfig dbConfig = config.Configs["DatabaseService"];
62 if (dbConfig != null)
63 {
64 if (dllName == String.Empty)
65 dllName = dbConfig.GetString("StorageProvider", String.Empty);
66 if (connString == String.Empty)
67 connString = dbConfig.GetString("ConnectionString", String.Empty);
68 }
69
70 //
71 // We tried, but this doesn't exist. We can't proceed.
72 //
73 if (String.Empty.Equals(dllName))
74 throw new Exception("No StorageProvider configured");
75
76 string realm = "Friends";
77 if (friendsConfig != null)
78 realm = friendsConfig.GetString("Realm", realm);
79
80 m_Database = LoadPlugin<IFriendsData>(dllName, new Object[] { connString, realm });
81 if (m_Database == null)
82 {
83 throw new Exception(
84 string.Format(
85 "Could not find a storage interface {0} in the given StorageProvider {1}", "IFriendsData", dllName));
86 }
87 }
88 }
89}
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index 7749c37..89f0716 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -34,6 +34,7 @@ using log4net;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Console; 35using OpenSim.Framework.Console;
36using OpenSim.Data; 36using OpenSim.Data;
37using OpenSim.Server.Base;
37using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion; 39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenMetaverse; 40using OpenMetaverse;
@@ -46,17 +47,58 @@ namespace OpenSim.Services.GridService
46 LogManager.GetLogger( 47 LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
48 49
50 private bool m_DeleteOnUnregister = true;
51 private static GridService m_RootInstance = null;
52 protected IConfigSource m_config;
53 protected static HypergridLinker m_HypergridLinker;
54
55 protected IAuthenticationService m_AuthenticationService = null;
49 protected bool m_AllowDuplicateNames = false; 56 protected bool m_AllowDuplicateNames = false;
57 protected bool m_AllowHypergridMapSearch = false;
50 58
51 public GridService(IConfigSource config) 59 public GridService(IConfigSource config)
52 : base(config) 60 : base(config)
53 { 61 {
54 m_log.DebugFormat("[GRID SERVICE]: Starting..."); 62 m_log.DebugFormat("[GRID SERVICE]: Starting...");
55 63
64 m_config = config;
56 IConfig gridConfig = config.Configs["GridService"]; 65 IConfig gridConfig = config.Configs["GridService"];
57 if (gridConfig != null) 66 if (gridConfig != null)
58 { 67 {
68 m_DeleteOnUnregister = gridConfig.GetBoolean("DeleteOnUnregister", true);
69
70 string authService = gridConfig.GetString("AuthenticationService", String.Empty);
71
72 if (authService != String.Empty)
73 {
74 Object[] args = new Object[] { config };
75 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args);
76 }
59 m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames); 77 m_AllowDuplicateNames = gridConfig.GetBoolean("AllowDuplicateNames", m_AllowDuplicateNames);
78 m_AllowHypergridMapSearch = gridConfig.GetBoolean("AllowHypergridMapSearch", m_AllowHypergridMapSearch);
79 }
80
81 if (m_RootInstance == null)
82 {
83 m_RootInstance = this;
84
85 if (MainConsole.Instance != null)
86 {
87 MainConsole.Instance.Commands.AddCommand("grid", true,
88 "show region",
89 "show region <Region name>",
90 "Show details on a region",
91 String.Empty,
92 HandleShowRegion);
93
94 MainConsole.Instance.Commands.AddCommand("grid", true,
95 "set region flags",
96 "set region flags <Region name> <flags>",
97 "Set database flags for region",
98 String.Empty,
99 HandleSetFlags);
100 }
101 m_HypergridLinker = new HypergridLinker(m_config, this, m_Database);
60 } 102 }
61 } 103 }
62 104
@@ -64,18 +106,63 @@ namespace OpenSim.Services.GridService
64 106
65 public string RegisterRegion(UUID scopeID, GridRegion regionInfos) 107 public string RegisterRegion(UUID scopeID, GridRegion regionInfos)
66 { 108 {
109 IConfig gridConfig = m_config.Configs["GridService"];
110
111 if (regionInfos.RegionID == UUID.Zero)
112 return "Invalid RegionID - cannot be zero UUID";
113
67 // This needs better sanity testing. What if regionInfo is registering in 114 // This needs better sanity testing. What if regionInfo is registering in
68 // overlapping coords? 115 // overlapping coords?
69 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 116 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
117 if (region != null)
118 {
119 // There is a preexisting record
120 //
121 // Get it's flags
122 //
123 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]);
124
125 // Is this a reservation?
126 //
127 if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0)
128 {
129 // Regions reserved for the null key cannot be taken.
130 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
131 return "Region location is reserved";
132
133 // Treat it as an auth request
134 //
135 // NOTE: Fudging the flags value here, so these flags
136 // should not be used elsewhere. Don't optimize
137 // this with the later retrieval of the same flags!
138 rflags |= OpenSim.Data.RegionFlags.Authenticate;
139 }
140
141 if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0)
142 {
143 // Can we authenticate at all?
144 //
145 if (m_AuthenticationService == null)
146 return "No authentication possible";
147
148 if (!m_AuthenticationService.Verify(new UUID(region.Data["PrincipalID"].ToString()), regionInfos.Token, 30))
149 return "Bad authentication";
150 }
151 }
152
70 if ((region != null) && (region.RegionID != regionInfos.RegionID)) 153 if ((region != null) && (region.RegionID != regionInfos.RegionID))
71 { 154 {
72 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", 155 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
73 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 156 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
74 return "Region overlaps another region"; 157 return "Region overlaps another region";
75 } 158 }
159
76 if ((region != null) && (region.RegionID == regionInfos.RegionID) && 160 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
77 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) 161 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
78 { 162 {
163 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
164 return "Can't move this region";
165
79 // Region reregistering in other coordinates. Delete the old entry 166 // Region reregistering in other coordinates. Delete the old entry
80 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.", 167 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
81 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 168 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
@@ -110,8 +197,38 @@ namespace OpenSim.Services.GridService
110 // Everything is ok, let's register 197 // Everything is ok, let's register
111 RegionData rdata = RegionInfo2RegionData(regionInfos); 198 RegionData rdata = RegionInfo2RegionData(regionInfos);
112 rdata.ScopeID = scopeID; 199 rdata.ScopeID = scopeID;
200
201 if (region != null)
202 {
203 int oldFlags = Convert.ToInt32(region.Data["flags"]);
204 if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
205 return "Region locked out";
206
207 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
208
209 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
210 }
211 else
212 {
213 rdata.Data["flags"] = "0";
214 if ((gridConfig != null) && rdata.RegionName != string.Empty)
215 {
216 int newFlags = 0;
217 string regionName = rdata.RegionName.Trim().Replace(' ', '_');
218 newFlags = ParseFlags(newFlags, gridConfig.GetString("DefaultRegionFlags", String.Empty));
219 newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + regionName, String.Empty));
220 newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + rdata.RegionID.ToString(), String.Empty));
221 rdata.Data["flags"] = newFlags.ToString();
222 }
223 }
224
225 int flags = Convert.ToInt32(rdata.Data["flags"]);
226 flags |= (int)OpenSim.Data.RegionFlags.RegionOnline;
227 rdata.Data["flags"] = flags.ToString();
228
113 try 229 try
114 { 230 {
231 rdata.Data["last_seen"] = Util.UnixTimeSinceEpoch();
115 m_Database.Store(rdata); 232 m_Database.Store(rdata);
116 } 233 }
117 catch (Exception e) 234 catch (Exception e)
@@ -120,14 +237,41 @@ namespace OpenSim.Services.GridService
120 } 237 }
121 238
122 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}", 239 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) registered successfully at {2}-{3}",
123 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 240 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionCoordX, regionInfos.RegionCoordY);
124 241
125 return String.Empty; 242 return String.Empty;
126 } 243 }
127 244
128 public bool DeregisterRegion(UUID regionID) 245 public bool DeregisterRegion(UUID regionID)
129 { 246 {
130 m_log.DebugFormat("[GRID SERVICE]: Region {0} deregistered", regionID); 247 RegionData region = m_Database.Get(regionID, UUID.Zero);
248 if (region == null)
249 return false;
250
251 m_log.DebugFormat(
252 "[GRID SERVICE]: Deregistering region {0} ({1}) at {2}-{3}",
253 region.RegionName, region.RegionID, region.coordX, region.coordY);
254
255 int flags = Convert.ToInt32(region.Data["flags"]);
256
257 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0)
258 {
259 flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline;
260 region.Data["flags"] = flags.ToString();
261 region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
262 try
263 {
264 m_Database.Store(region);
265 }
266 catch (Exception e)
267 {
268 m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
269 }
270
271 return true;
272
273 }
274
131 return m_Database.Delete(regionID); 275 return m_Database.Delete(regionID);
132 } 276 }
133 277
@@ -135,17 +279,32 @@ namespace OpenSim.Services.GridService
135 { 279 {
136 List<GridRegion> rinfos = new List<GridRegion>(); 280 List<GridRegion> rinfos = new List<GridRegion>();
137 RegionData region = m_Database.Get(regionID, scopeID); 281 RegionData region = m_Database.Get(regionID, scopeID);
282
138 if (region != null) 283 if (region != null)
139 { 284 {
140 // Not really? Maybe? 285 // Not really? Maybe?
141 List<RegionData> rdatas = m_Database.Get(region.posX - (int)Constants.RegionSize, region.posY - (int)Constants.RegionSize, 286 List<RegionData> rdatas = m_Database.Get(region.posX - (int)Constants.RegionSize - 1, region.posY - (int)Constants.RegionSize - 1,
142 region.posX + (int)Constants.RegionSize, region.posY + (int)Constants.RegionSize, scopeID); 287 region.posX + (int)Constants.RegionSize + 1, region.posY + (int)Constants.RegionSize + 1, scopeID);
143 288
144 foreach (RegionData rdata in rdatas) 289 foreach (RegionData rdata in rdatas)
290 {
145 if (rdata.RegionID != regionID) 291 if (rdata.RegionID != regionID)
146 rinfos.Add(RegionData2RegionInfo(rdata)); 292 {
293 int flags = Convert.ToInt32(rdata.Data["flags"]);
294 if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
295 rinfos.Add(RegionData2RegionInfo(rdata));
296 }
297 }
147 298
299// m_log.DebugFormat("[GRID SERVICE]: region {0} has {1} neighbours", region.RegionName, rinfos.Count);
148 } 300 }
301 else
302 {
303 m_log.WarnFormat(
304 "[GRID SERVICE]: GetNeighbours() called for scope {0}, region {1} but no such region found",
305 scopeID, regionID);
306 }
307
149 return rinfos; 308 return rinfos;
150 } 309 }
151 310
@@ -169,24 +328,34 @@ namespace OpenSim.Services.GridService
169 return null; 328 return null;
170 } 329 }
171 330
172 public GridRegion GetRegionByName(UUID scopeID, string regionName) 331 public GridRegion GetRegionByName(UUID scopeID, string name)
173 { 332 {
174 List<RegionData> rdatas = m_Database.Get(regionName + "%", scopeID); 333 List<RegionData> rdatas = m_Database.Get(name, scopeID);
175 if ((rdatas != null) && (rdatas.Count > 0)) 334 if ((rdatas != null) && (rdatas.Count > 0))
176 return RegionData2RegionInfo(rdatas[0]); // get the first 335 return RegionData2RegionInfo(rdatas[0]); // get the first
177 336
337 if (m_AllowHypergridMapSearch)
338 {
339 GridRegion r = GetHypergridRegionByName(scopeID, name);
340 if (r != null)
341 return r;
342 }
343
178 return null; 344 return null;
179 } 345 }
180 346
181 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber) 347 public List<GridRegion> GetRegionsByName(UUID scopeID, string name, int maxNumber)
182 { 348 {
183 List<RegionData> rdatas = m_Database.Get("%" + name + "%", scopeID); 349// m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name);
350
351 List<RegionData> rdatas = m_Database.Get(name + "%", scopeID);
184 352
185 int count = 0; 353 int count = 0;
186 List<GridRegion> rinfos = new List<GridRegion>(); 354 List<GridRegion> rinfos = new List<GridRegion>();
187 355
188 if (rdatas != null) 356 if (rdatas != null)
189 { 357 {
358// m_log.DebugFormat("[GRID SERVICE]: Found {0} regions", rdatas.Count);
190 foreach (RegionData rdata in rdatas) 359 foreach (RegionData rdata in rdatas)
191 { 360 {
192 if (count++ < maxNumber) 361 if (count++ < maxNumber)
@@ -194,9 +363,30 @@ namespace OpenSim.Services.GridService
194 } 363 }
195 } 364 }
196 365
366 if (m_AllowHypergridMapSearch && (rdatas == null || (rdatas != null && rdatas.Count == 0)))
367 {
368 GridRegion r = GetHypergridRegionByName(scopeID, name);
369 if (r != null)
370 rinfos.Add(r);
371 }
372
197 return rinfos; 373 return rinfos;
198 } 374 }
199 375
376 /// <summary>
377 /// Get a hypergrid region.
378 /// </summary>
379 /// <param name="scopeID"></param>
380 /// <param name="name"></param>
381 /// <returns>null if no hypergrid region could be found.</returns>
382 protected GridRegion GetHypergridRegionByName(UUID scopeID, string name)
383 {
384 if (name.Contains("."))
385 return m_HypergridLinker.LinkRegion(scopeID, name);
386 else
387 return null;
388 }
389
200 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax) 390 public List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax)
201 { 391 {
202 int xminSnap = (int)(xmin / Constants.RegionSize) * (int)Constants.RegionSize; 392 int xminSnap = (int)(xmin / Constants.RegionSize) * (int)Constants.RegionSize;
@@ -216,7 +406,7 @@ namespace OpenSim.Services.GridService
216 406
217 #region Data structure conversions 407 #region Data structure conversions
218 408
219 protected RegionData RegionInfo2RegionData(GridRegion rinfo) 409 public RegionData RegionInfo2RegionData(GridRegion rinfo)
220 { 410 {
221 RegionData rdata = new RegionData(); 411 RegionData rdata = new RegionData();
222 rdata.posX = (int)rinfo.RegionLocX; 412 rdata.posX = (int)rinfo.RegionLocX;
@@ -229,7 +419,7 @@ namespace OpenSim.Services.GridService
229 return rdata; 419 return rdata;
230 } 420 }
231 421
232 protected GridRegion RegionData2RegionInfo(RegionData rdata) 422 public GridRegion RegionData2RegionInfo(RegionData rdata)
233 { 423 {
234 GridRegion rinfo = new GridRegion(rdata.Data); 424 GridRegion rinfo = new GridRegion(rdata.Data);
235 rinfo.RegionLocX = rdata.posX; 425 rinfo.RegionLocX = rdata.posX;
@@ -243,5 +433,160 @@ namespace OpenSim.Services.GridService
243 433
244 #endregion 434 #endregion
245 435
436 public List<GridRegion> GetDefaultRegions(UUID scopeID)
437 {
438 List<GridRegion> ret = new List<GridRegion>();
439
440 List<RegionData> regions = m_Database.GetDefaultRegions(scopeID);
441
442 foreach (RegionData r in regions)
443 {
444 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
445 ret.Add(RegionData2RegionInfo(r));
446 }
447
448 m_log.DebugFormat("[GRID SERVICE]: GetDefaultRegions returning {0} regions", ret.Count);
449 return ret;
450 }
451
452 public List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y)
453 {
454 List<GridRegion> ret = new List<GridRegion>();
455
456 List<RegionData> regions = m_Database.GetFallbackRegions(scopeID, x, y);
457
458 foreach (RegionData r in regions)
459 {
460 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
461 ret.Add(RegionData2RegionInfo(r));
462 }
463
464 m_log.DebugFormat("[GRID SERVICE]: Fallback returned {0} regions", ret.Count);
465 return ret;
466 }
467
468 public List<GridRegion> GetHyperlinks(UUID scopeID)
469 {
470 List<GridRegion> ret = new List<GridRegion>();
471
472 List<RegionData> regions = m_Database.GetHyperlinks(scopeID);
473
474 foreach (RegionData r in regions)
475 {
476 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
477 ret.Add(RegionData2RegionInfo(r));
478 }
479
480 m_log.DebugFormat("[GRID SERVICE]: Hyperlinks returned {0} regions", ret.Count);
481 return ret;
482 }
483
484 public int GetRegionFlags(UUID scopeID, UUID regionID)
485 {
486 RegionData region = m_Database.Get(regionID, scopeID);
487
488 if (region != null)
489 {
490 int flags = Convert.ToInt32(region.Data["flags"]);
491 //m_log.DebugFormat("[GRID SERVICE]: Request for flags of {0}: {1}", regionID, flags);
492 return flags;
493 }
494 else
495 return -1;
496 }
497
498 private void HandleShowRegion(string module, string[] cmd)
499 {
500 if (cmd.Length != 3)
501 {
502 MainConsole.Instance.Output("Syntax: show region <region name>");
503 return;
504 }
505 List<RegionData> regions = m_Database.Get(cmd[2], UUID.Zero);
506 if (regions == null || regions.Count < 1)
507 {
508 MainConsole.Instance.Output("Region not found");
509 return;
510 }
511
512 MainConsole.Instance.Output("Region Name Region UUID");
513 MainConsole.Instance.Output("Location URI");
514 MainConsole.Instance.Output("Owner ID Flags");
515 MainConsole.Instance.Output("-------------------------------------------------------------------------------");
516 foreach (RegionData r in regions)
517 {
518 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]);
519 MainConsole.Instance.Output(String.Format("{0,-20} {1}\n{2,-20} {3}\n{4,-39} {5}\n\n",
520 r.RegionName, r.RegionID,
521 String.Format("{0},{1}", r.posX / Constants.RegionSize, r.posY / Constants.RegionSize),
522 r.Data["serverURI"],
523 r.Data["owner_uuid"], flags));
524 }
525 return;
526 }
527
528 private int ParseFlags(int prev, string flags)
529 {
530 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev;
531
532 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
533
534 foreach (string p in parts)
535 {
536 int val;
537
538 try
539 {
540 if (p.StartsWith("+"))
541 {
542 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
543 f |= (OpenSim.Data.RegionFlags)val;
544 }
545 else if (p.StartsWith("-"))
546 {
547 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
548 f &= ~(OpenSim.Data.RegionFlags)val;
549 }
550 else
551 {
552 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p);
553 f |= (OpenSim.Data.RegionFlags)val;
554 }
555 }
556 catch (Exception)
557 {
558 MainConsole.Instance.Output("Error in flag specification: " + p);
559 }
560 }
561
562 return (int)f;
563 }
564
565 private void HandleSetFlags(string module, string[] cmd)
566 {
567 if (cmd.Length < 5)
568 {
569 MainConsole.Instance.Output("Syntax: set region flags <region name> <flags>");
570 return;
571 }
572
573 List<RegionData> regions = m_Database.Get(cmd[3], UUID.Zero);
574 if (regions == null || regions.Count < 1)
575 {
576 MainConsole.Instance.Output("Region not found");
577 return;
578 }
579
580 foreach (RegionData r in regions)
581 {
582 int flags = Convert.ToInt32(r.Data["flags"]);
583 flags = ParseFlags(flags, cmd[4]);
584 r.Data["flags"] = flags.ToString();
585 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags;
586
587 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
588 m_Database.Store(r);
589 }
590 }
246 } 591 }
247} 592}
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
new file mode 100644
index 0000000..b70b425
--- /dev/null
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -0,0 +1,724 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.IO;
32using System.Linq;
33using System.Net;
34using System.Reflection;
35using System.Xml;
36
37using Nini.Config;
38using log4net;
39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Data;
42using OpenSim.Server.Base;
43using OpenSim.Services.Interfaces;
44using OpenSim.Services.Connectors.Hypergrid;
45using GridRegion = OpenSim.Services.Interfaces.GridRegion;
46using OpenMetaverse;
47
48namespace OpenSim.Services.GridService
49{
50 public class HypergridLinker
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 private static uint m_autoMappingX = 0;
57 private static uint m_autoMappingY = 0;
58 private static bool m_enableAutoMapping = false;
59
60 protected IRegionData m_Database;
61 protected GridService m_GridService;
62 protected IAssetService m_AssetService;
63 protected GatekeeperServiceConnector m_GatekeeperConnector;
64
65 protected UUID m_ScopeID = UUID.Zero;
66// protected bool m_Check4096 = true;
67 protected string m_MapTileDirectory = string.Empty;
68 protected string m_ThisGatekeeper = string.Empty;
69 protected Uri m_ThisGatekeeperURI = null;
70
71 // Hyperlink regions are hyperlinks on the map
72 public readonly Dictionary<UUID, GridRegion> m_HyperlinkRegions = new Dictionary<UUID, GridRegion>();
73 protected Dictionary<UUID, ulong> m_HyperlinkHandles = new Dictionary<UUID, ulong>();
74
75 protected GridRegion m_DefaultRegion;
76 protected GridRegion DefaultRegion
77 {
78 get
79 {
80 if (m_DefaultRegion == null)
81 {
82 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
83 if (defs != null && defs.Count > 0)
84 m_DefaultRegion = defs[0];
85 else
86 {
87 // Get any region
88 defs = m_GridService.GetRegionsByName(m_ScopeID, "", 1);
89 if (defs != null && defs.Count > 0)
90 m_DefaultRegion = defs[0];
91 else
92 {
93 // This shouldn't happen
94 m_DefaultRegion = new GridRegion(1000, 1000);
95 m_log.Error("[HYPERGRID LINKER]: Something is wrong with this grid. It has no regions?");
96 }
97 }
98 }
99 return m_DefaultRegion;
100 }
101 }
102
103 public HypergridLinker(IConfigSource config, GridService gridService, IRegionData db)
104 {
105 IConfig modulesConfig = config.Configs["Modules"];
106 if (modulesConfig == null)
107 return;
108
109 if (modulesConfig.GetString("HypergridLinker", "") != "HypergridLinker")
110 return;
111
112 m_log.DebugFormat("[HYPERGRID LINKER]: Starting with db {0}", db.GetType());
113
114 m_Database = db;
115 m_GridService = gridService;
116
117 IConfig gridConfig = config.Configs["GridService"];
118 if (gridConfig != null)
119 {
120 string assetService = gridConfig.GetString("AssetService", string.Empty);
121
122 Object[] args = new Object[] { config };
123
124 if (assetService != string.Empty)
125 m_AssetService = ServerUtils.LoadPlugin<IAssetService>(assetService, args);
126
127 string scope = gridConfig.GetString("ScopeID", string.Empty);
128 if (scope != string.Empty)
129 UUID.TryParse(scope, out m_ScopeID);
130
131// m_Check4096 = gridConfig.GetBoolean("Check4096", true);
132
133 m_MapTileDirectory = gridConfig.GetString("MapTileDirectory", "maptiles");
134
135 m_ThisGatekeeper = gridConfig.GetString("Gatekeeper", string.Empty);
136 try
137 {
138 m_ThisGatekeeperURI = new Uri(m_ThisGatekeeper);
139 }
140 catch
141 {
142 m_log.WarnFormat("[HYPERGRID LINKER]: Malformed URL in [GridService], variable Gatekeeper = {0}", m_ThisGatekeeper);
143 }
144
145 m_GatekeeperConnector = new GatekeeperServiceConnector(m_AssetService);
146
147 m_log.Debug("[HYPERGRID LINKER]: Loaded all services...");
148 }
149
150 if (!string.IsNullOrEmpty(m_MapTileDirectory))
151 {
152 try
153 {
154 Directory.CreateDirectory(m_MapTileDirectory);
155 }
156 catch (Exception e)
157 {
158 m_log.WarnFormat("[HYPERGRID LINKER]: Could not create map tile storage directory {0}: {1}", m_MapTileDirectory, e);
159 m_MapTileDirectory = string.Empty;
160 }
161 }
162
163 if (MainConsole.Instance != null)
164 {
165 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region",
166 "link-region <Xloc> <Yloc> <ServerURI> [<RemoteRegionName>]",
167 "Link a HyperGrid Region. Examples for <ServerURI>: http://grid.net:8002/ or http://example.org/path/foo.php", RunCommand);
168 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-region",
169 "link-region <Xloc> <Yloc> <RegionIP> <RegionPort> [<RemoteRegionName>]",
170 "Link a hypergrid region (deprecated)", RunCommand);
171 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "unlink-region",
172 "unlink-region <local name>",
173 "Unlink a hypergrid region", RunCommand);
174 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "link-mapping", "link-mapping [<x> <y>]",
175 "Set local coordinate to map HG regions to", RunCommand);
176 MainConsole.Instance.Commands.AddCommand("hypergrid", false, "show hyperlinks", "show hyperlinks",
177 "List the HG regions", HandleShow);
178 }
179 }
180
181
182 #region Link Region
183
184 public GridRegion LinkRegion(UUID scopeID, string regionDescriptor)
185 {
186 string reason = string.Empty;
187 int xloc = random.Next(0, Int16.MaxValue) * (int)Constants.RegionSize;
188 return TryLinkRegionToCoords(scopeID, regionDescriptor, xloc, 0, out reason);
189 }
190
191 private static Random random = new Random();
192
193 // From the command line link-region
194 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, out string reason)
195 {
196 return TryLinkRegionToCoords(scopeID, mapName, xloc, yloc, UUID.Zero, out reason);
197 }
198
199 public GridRegion TryLinkRegionToCoords(UUID scopeID, string mapName, int xloc, int yloc, UUID ownerID, out string reason)
200 {
201 reason = string.Empty;
202 uint port = 0;
203 string[] parts = mapName.Split(new char[] {':'});
204 string regionName = String.Empty;
205 if (parts.Length > 1)
206 {
207 regionName = mapName.Substring(parts[0].Length + 1);
208 regionName = regionName.Trim(new char[] {'"'});
209 }
210 GridRegion regInfo;
211 if (TryCreateLink(scopeID, xloc, yloc, regionName, 0, null, parts[0], ownerID, out regInfo, out reason))
212 {
213 regInfo.RegionName = mapName;
214 return regInfo;
215 }
216
217 return null;
218 }
219
220 public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, UUID ownerID, out GridRegion regInfo, out string reason)
221 {
222 return TryCreateLink(scopeID, xloc, yloc, remoteRegionName, externalPort, externalHostName, null, ownerID, out regInfo, out reason);
223 }
224
225 public bool TryCreateLink(UUID scopeID, int xloc, int yloc, string remoteRegionName, uint externalPort, string externalHostName, string serverURI, UUID ownerID, out GridRegion regInfo, out string reason)
226 {
227 m_log.DebugFormat("[HYPERGRID LINKER]: Link to {0}:{1}, in {2}-{3}",
228 ((serverURI == null) ? (externalHostName + ":" + externalPort) : serverURI),
229 remoteRegionName, xloc / Constants.RegionSize, yloc / Constants.RegionSize);
230
231 reason = string.Empty;
232 Uri uri = null;
233
234 regInfo = new GridRegion();
235 if ( externalPort > 0)
236 regInfo.HttpPort = externalPort;
237 else
238 regInfo.HttpPort = 0;
239 if ( externalHostName != null)
240 regInfo.ExternalHostName = externalHostName;
241 else
242 regInfo.ExternalHostName = "0.0.0.0";
243 if ( serverURI != null)
244 {
245 regInfo.ServerURI = serverURI;
246 try
247 {
248 uri = new Uri(serverURI);
249 regInfo.ExternalHostName = uri.Host;
250 regInfo.HttpPort = (uint)uri.Port;
251 }
252 catch {}
253 }
254
255 if ( remoteRegionName != string.Empty )
256 regInfo.RegionName = remoteRegionName;
257
258 regInfo.RegionLocX = xloc;
259 regInfo.RegionLocY = yloc;
260 regInfo.ScopeID = scopeID;
261 regInfo.EstateOwner = ownerID;
262
263 // Make sure we're not hyperlinking to regions on this grid!
264 if (m_ThisGatekeeperURI != null)
265 {
266 if (regInfo.ExternalHostName == m_ThisGatekeeperURI.Host && regInfo.HttpPort == m_ThisGatekeeperURI.Port)
267 {
268 reason = "Cannot hyperlink to regions on the same grid";
269 return false;
270 }
271 }
272 else
273 m_log.WarnFormat("[HYPERGRID LINKER]: Please set this grid's Gatekeeper's address in [GridService]!");
274
275 // Check for free coordinates
276 GridRegion region = m_GridService.GetRegionByPosition(regInfo.ScopeID, regInfo.RegionLocX, regInfo.RegionLocY);
277 if (region != null)
278 {
279 m_log.WarnFormat("[HYPERGRID LINKER]: Coordinates {0}-{1} are already occupied by region {2} with uuid {3}",
280 regInfo.RegionLocX / Constants.RegionSize, regInfo.RegionLocY / Constants.RegionSize,
281 region.RegionName, region.RegionID);
282 reason = "Coordinates are already in use";
283 return false;
284 }
285
286 try
287 {
288 regInfo.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)0);
289 }
290 catch (Exception e)
291 {
292 m_log.Warn("[HYPERGRID LINKER]: Wrong format for link-region: " + e.Message);
293 reason = "Internal error";
294 return false;
295 }
296
297 // Finally, link it
298 ulong handle = 0;
299 UUID regionID = UUID.Zero;
300 string externalName = string.Empty;
301 string imageURL = string.Empty;
302 if (!m_GatekeeperConnector.LinkRegion(regInfo, out regionID, out handle, out externalName, out imageURL, out reason))
303 return false;
304
305 if (regionID == UUID.Zero)
306 {
307 m_log.Warn("[HYPERGRID LINKER]: Unable to link region");
308 reason = "Remote region could not be found";
309 return false;
310 }
311
312 region = m_GridService.GetRegionByUUID(scopeID, regionID);
313 if (region != null)
314 {
315 m_log.DebugFormat("[HYPERGRID LINKER]: Region already exists in coordinates {0} {1}",
316 region.RegionLocX / Constants.RegionSize, region.RegionLocY / Constants.RegionSize);
317 regInfo = region;
318 return true;
319 }
320
321 // We are now performing this check for each individual teleport in the EntityTransferModule instead. This
322 // allows us to give better feedback when teleports fail because of the distance reason (which can't be
323 // done here) and it also hypergrid teleports that are within range (possibly because the source grid
324 // itself has regions that are very far apart).
325// uint x, y;
326// if (m_Check4096 && !Check4096(handle, out x, out y))
327// {
328// //RemoveHyperlinkRegion(regInfo.RegionID);
329// reason = "Region is too far (" + x + ", " + y + ")";
330// m_log.Info("[HYPERGRID LINKER]: Unable to link, region is too far (" + x + ", " + y + ")");
331// //return false;
332// }
333
334 regInfo.RegionID = regionID;
335
336 if (externalName == string.Empty)
337 regInfo.RegionName = regInfo.ServerURI;
338 else
339 regInfo.RegionName = externalName;
340
341 m_log.DebugFormat("[HYPERGRID LINKER]: naming linked region {0}, handle {1}", regInfo.RegionName, handle.ToString());
342
343 // Get the map image
344 regInfo.TerrainImage = GetMapImage(regionID, imageURL);
345
346 // Store the origin's coordinates somewhere
347 regInfo.RegionSecret = handle.ToString();
348
349 AddHyperlinkRegion(regInfo, handle);
350 m_log.Info("[HYPERGRID LINKER]: Successfully linked to region_uuid " + regInfo.RegionID);
351 return true;
352 }
353
354 public bool TryUnlinkRegion(string mapName)
355 {
356 m_log.DebugFormat("[HYPERGRID LINKER]: Request to unlink {0}", mapName);
357 GridRegion regInfo = null;
358
359 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
360 if (regions != null && regions.Count > 0)
361 {
362 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
363 if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0)
364 {
365 regInfo = new GridRegion();
366 regInfo.RegionID = regions[0].RegionID;
367 regInfo.ScopeID = m_ScopeID;
368 }
369 }
370
371 if (regInfo != null)
372 {
373 RemoveHyperlinkRegion(regInfo.RegionID);
374 return true;
375 }
376 else
377 {
378 m_log.InfoFormat("[HYPERGRID LINKER]: Region {0} not found", mapName);
379 return false;
380 }
381 }
382
383// Not currently used
384// /// <summary>
385// /// Cope with this viewer limitation.
386// /// </summary>
387// /// <param name="regInfo"></param>
388// /// <returns></returns>
389// public bool Check4096(ulong realHandle, out uint x, out uint y)
390// {
391// uint ux = 0, uy = 0;
392// Utils.LongToUInts(realHandle, out ux, out uy);
393// x = ux / Constants.RegionSize;
394// y = uy / Constants.RegionSize;
395//
396// const uint limit = (4096 - 1) * Constants.RegionSize;
397// uint xmin = ux - limit;
398// uint xmax = ux + limit;
399// uint ymin = uy - limit;
400// uint ymax = uy + limit;
401// // World map boundary checks
402// if (xmin < 0 || xmin > ux)
403// xmin = 0;
404// if (xmax > int.MaxValue || xmax < ux)
405// xmax = int.MaxValue;
406// if (ymin < 0 || ymin > uy)
407// ymin = 0;
408// if (ymax > int.MaxValue || ymax < uy)
409// ymax = int.MaxValue;
410//
411// // Check for any regions that are within the possible teleport range to the linked region
412// List<GridRegion> regions = m_GridService.GetRegionRange(m_ScopeID, (int)xmin, (int)xmax, (int)ymin, (int)ymax);
413// if (regions.Count == 0)
414// {
415// return false;
416// }
417// else
418// {
419// // Check for regions which are not linked regions
420// List<GridRegion> hyperlinks = m_GridService.GetHyperlinks(m_ScopeID);
421// IEnumerable<GridRegion> availableRegions = regions.Except(hyperlinks);
422// if (availableRegions.Count() == 0)
423// return false;
424// }
425//
426// return true;
427// }
428
429 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
430 {
431 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
432 int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline;
433 rdata.Data["flags"] = flags.ToString();
434
435 m_Database.Store(rdata);
436 }
437
438 private void RemoveHyperlinkRegion(UUID regionID)
439 {
440 m_Database.Delete(regionID);
441 }
442
443 public UUID GetMapImage(UUID regionID, string imageURL)
444 {
445 return m_GatekeeperConnector.GetMapImage(regionID, imageURL, m_MapTileDirectory);
446 }
447 #endregion
448
449
450 #region Console Commands
451
452 public void HandleShow(string module, string[] cmd)
453 {
454 if (cmd.Length != 2)
455 {
456 MainConsole.Instance.Output("Syntax: show hyperlinks");
457 return;
458 }
459 List<RegionData> regions = m_Database.GetHyperlinks(UUID.Zero);
460 if (regions == null || regions.Count < 1)
461 {
462 MainConsole.Instance.Output("No hyperlinks");
463 return;
464 }
465
466 MainConsole.Instance.Output("Region Name");
467 MainConsole.Instance.Output("Location Region UUID");
468 MainConsole.Instance.Output(new string('-', 72));
469 foreach (RegionData r in regions)
470 {
471 MainConsole.Instance.Output(String.Format("{0}\n{2,-32} {1}\n",
472 r.RegionName, r.RegionID, String.Format("{0},{1} ({2},{3})", r.posX, r.posY,
473 r.posX / Constants.RegionSize, r.posY / Constants.RegionSize)));
474 }
475 return;
476 }
477
478 public void RunCommand(string module, string[] cmdparams)
479 {
480 List<string> args = new List<string>(cmdparams);
481 if (args.Count < 1)
482 return;
483
484 string command = args[0];
485 args.RemoveAt(0);
486
487 cmdparams = args.ToArray();
488
489 RunHGCommand(command, cmdparams);
490
491 }
492
493 private void RunLinkRegionCommand(string[] cmdparams)
494 {
495 int xloc, yloc;
496 string serverURI;
497 string remoteName = null;
498 xloc = Convert.ToInt32(cmdparams[0]) * (int)Constants.RegionSize;
499 yloc = Convert.ToInt32(cmdparams[1]) * (int)Constants.RegionSize;
500 serverURI = cmdparams[2];
501 if (cmdparams.Length > 3)
502 remoteName = string.Join(" ", cmdparams, 3, cmdparams.Length - 3);
503 string reason = string.Empty;
504 GridRegion regInfo;
505 if (TryCreateLink(UUID.Zero, xloc, yloc, remoteName, 0, null, serverURI, UUID.Zero, out regInfo, out reason))
506 MainConsole.Instance.Output("Hyperlink established");
507 else
508 MainConsole.Instance.Output("Failed to link region: " + reason);
509 }
510
511 private void RunHGCommand(string command, string[] cmdparams)
512 {
513 if (command.Equals("link-mapping"))
514 {
515 if (cmdparams.Length == 2)
516 {
517 try
518 {
519 m_autoMappingX = Convert.ToUInt32(cmdparams[0]);
520 m_autoMappingY = Convert.ToUInt32(cmdparams[1]);
521 m_enableAutoMapping = true;
522 }
523 catch (Exception)
524 {
525 m_autoMappingX = 0;
526 m_autoMappingY = 0;
527 m_enableAutoMapping = false;
528 }
529 }
530 }
531 else if (command.Equals("link-region"))
532 {
533 if (cmdparams.Length < 3)
534 {
535 if ((cmdparams.Length == 1) || (cmdparams.Length == 2))
536 {
537 LoadXmlLinkFile(cmdparams);
538 }
539 else
540 {
541 LinkRegionCmdUsage();
542 }
543 return;
544 }
545
546 //this should be the prefererred way of setting up hg links now
547 if (cmdparams[2].StartsWith("http"))
548 {
549 RunLinkRegionCommand(cmdparams);
550 }
551 else if (cmdparams[2].Contains(":"))
552 {
553 // New format
554 string[] parts = cmdparams[2].Split(':');
555 if (parts.Length > 2)
556 {
557 // Insert remote region name
558 ArrayList parameters = new ArrayList(cmdparams);
559 parameters.Insert(3, parts[2]);
560 cmdparams = (string[])parameters.ToArray(typeof(string));
561 }
562 cmdparams[2] = "http://" + parts[0] + ':' + parts[1];
563
564 RunLinkRegionCommand(cmdparams);
565 }
566 else
567 {
568 // old format
569 GridRegion regInfo;
570 int xloc, yloc;
571 uint externalPort;
572 string externalHostName;
573 try
574 {
575 xloc = Convert.ToInt32(cmdparams[0]);
576 yloc = Convert.ToInt32(cmdparams[1]);
577 externalPort = Convert.ToUInt32(cmdparams[3]);
578 externalHostName = cmdparams[2];
579 //internalPort = Convert.ToUInt32(cmdparams[4]);
580 //remotingPort = Convert.ToUInt32(cmdparams[5]);
581 }
582 catch (Exception e)
583 {
584 MainConsole.Instance.Output("[HGrid] Wrong format for link-region command: " + e.Message);
585 LinkRegionCmdUsage();
586 return;
587 }
588
589 // Convert cell coordinates given by the user to meters
590 xloc = xloc * (int)Constants.RegionSize;
591 yloc = yloc * (int)Constants.RegionSize;
592 string reason = string.Empty;
593 if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
594 {
595 // What is this? The GridRegion instance will be discarded anyway,
596 // which effectively ignores any local name given with the command.
597 //if (cmdparams.Length >= 5)
598 //{
599 // regInfo.RegionName = "";
600 // for (int i = 4; i < cmdparams.Length; i++)
601 // regInfo.RegionName += cmdparams[i] + " ";
602 //}
603 }
604 }
605 return;
606 }
607 else if (command.Equals("unlink-region"))
608 {
609 if (cmdparams.Length < 1)
610 {
611 UnlinkRegionCmdUsage();
612 return;
613 }
614 string region = string.Join(" ", cmdparams);
615 if (TryUnlinkRegion(region))
616 MainConsole.Instance.Output("Successfully unlinked " + region);
617 else
618 MainConsole.Instance.Output("Unable to unlink " + region + ", region not found.");
619 }
620 }
621
622 private void LoadXmlLinkFile(string[] cmdparams)
623 {
624 //use http://www.hgurl.com/hypergrid.xml for test
625 try
626 {
627 XmlReader r = XmlReader.Create(cmdparams[0]);
628 XmlConfigSource cs = new XmlConfigSource(r);
629 string[] excludeSections = null;
630
631 if (cmdparams.Length == 2)
632 {
633 if (cmdparams[1].ToLower().StartsWith("excludelist:"))
634 {
635 string excludeString = cmdparams[1].ToLower();
636 excludeString = excludeString.Remove(0, 12);
637 char[] splitter = { ';' };
638
639 excludeSections = excludeString.Split(splitter);
640 }
641 }
642
643 for (int i = 0; i < cs.Configs.Count; i++)
644 {
645 bool skip = false;
646 if ((excludeSections != null) && (excludeSections.Length > 0))
647 {
648 for (int n = 0; n < excludeSections.Length; n++)
649 {
650 if (excludeSections[n] == cs.Configs[i].Name.ToLower())
651 {
652 skip = true;
653 break;
654 }
655 }
656 }
657 if (!skip)
658 {
659 ReadLinkFromConfig(cs.Configs[i]);
660 }
661 }
662 }
663 catch (Exception e)
664 {
665 m_log.Error(e.ToString());
666 }
667 }
668
669
670 private void ReadLinkFromConfig(IConfig config)
671 {
672 GridRegion regInfo;
673 int xloc, yloc;
674 uint externalPort;
675 string externalHostName;
676 uint realXLoc, realYLoc;
677
678 xloc = Convert.ToInt32(config.GetString("xloc", "0"));
679 yloc = Convert.ToInt32(config.GetString("yloc", "0"));
680 externalPort = Convert.ToUInt32(config.GetString("externalPort", "0"));
681 externalHostName = config.GetString("externalHostName", "");
682 realXLoc = Convert.ToUInt32(config.GetString("real-xloc", "0"));
683 realYLoc = Convert.ToUInt32(config.GetString("real-yloc", "0"));
684
685 if (m_enableAutoMapping)
686 {
687 xloc = (int)((xloc % 100) + m_autoMappingX);
688 yloc = (int)((yloc % 100) + m_autoMappingY);
689 }
690
691 if (((realXLoc == 0) && (realYLoc == 0)) ||
692 (((realXLoc - xloc < 3896) || (xloc - realXLoc < 3896)) &&
693 ((realYLoc - yloc < 3896) || (yloc - realYLoc < 3896))))
694 {
695 xloc = xloc * (int)Constants.RegionSize;
696 yloc = yloc * (int)Constants.RegionSize;
697 string reason = string.Empty;
698 if (TryCreateLink(UUID.Zero, xloc, yloc, string.Empty, externalPort, externalHostName, UUID.Zero, out regInfo, out reason))
699 {
700 regInfo.RegionName = config.GetString("localName", "");
701 }
702 else
703 MainConsole.Instance.Output("Unable to link " + externalHostName + ": " + reason);
704 }
705 }
706
707
708 private void LinkRegionCmdUsage()
709 {
710 MainConsole.Instance.Output("Usage: link-region <Xloc> <Yloc> <ServerURI> [<RemoteRegionName>]");
711 MainConsole.Instance.Output("Usage (deprecated): link-region <Xloc> <Yloc> <HostName>:<HttpPort>[:<RemoteRegionName>]");
712 MainConsole.Instance.Output("Usage (deprecated): link-region <Xloc> <Yloc> <HostName> <HttpPort> [<LocalName>]");
713 MainConsole.Instance.Output("Usage: link-region <URI_of_xml> [<exclude>]");
714 }
715
716 private void UnlinkRegionCmdUsage()
717 {
718 MainConsole.Instance.Output("Usage: unlink-region <LocalName>");
719 }
720
721 #endregion
722
723 }
724}
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
new file mode 100644
index 0000000..5d99c79
--- /dev/null
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -0,0 +1,383 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32using System.Text.RegularExpressions;
33
34using OpenSim.Framework;
35using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37using OpenSim.Server.Base;
38using OpenSim.Services.Connectors.Hypergrid;
39
40using OpenMetaverse;
41
42using Nini.Config;
43using log4net;
44
45namespace OpenSim.Services.HypergridService
46{
47 public class GatekeeperService : IGatekeeperService
48 {
49 private static readonly ILog m_log =
50 LogManager.GetLogger(
51 MethodBase.GetCurrentMethod().DeclaringType);
52
53 private static bool m_Initialized = false;
54
55 private static IGridService m_GridService;
56 private static IPresenceService m_PresenceService;
57 private static IUserAccountService m_UserAccountService;
58 private static IUserAgentService m_UserAgentService;
59 private static ISimulationService m_SimulationService;
60
61 protected string m_AllowedClients = string.Empty;
62 protected string m_DeniedClients = string.Empty;
63
64 private static UUID m_ScopeID;
65 private static bool m_AllowTeleportsToAnyRegion;
66 private static string m_ExternalName;
67 private static GridRegion m_DefaultGatewayRegion;
68
69 public GatekeeperService(IConfigSource config, ISimulationService simService)
70 {
71 if (!m_Initialized)
72 {
73 m_Initialized = true;
74
75 IConfig serverConfig = config.Configs["GatekeeperService"];
76 if (serverConfig == null)
77 throw new Exception(String.Format("No section GatekeeperService in config file"));
78
79 string accountService = serverConfig.GetString("UserAccountService", String.Empty);
80 string homeUsersService = serverConfig.GetString("UserAgentService", string.Empty);
81 string gridService = serverConfig.GetString("GridService", String.Empty);
82 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
83 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
84
85 // These 3 are mandatory, the others aren't
86 if (gridService == string.Empty || presenceService == string.Empty)
87 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function.");
88
89 string scope = serverConfig.GetString("ScopeID", UUID.Zero.ToString());
90 UUID.TryParse(scope, out m_ScopeID);
91 //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
92 m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true);
93 m_ExternalName = serverConfig.GetString("ExternalName", string.Empty);
94 if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/"))
95 m_ExternalName = m_ExternalName + "/";
96
97 Object[] args = new Object[] { config };
98 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
99 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
100
101 if (accountService != string.Empty)
102 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
103 if (homeUsersService != string.Empty)
104 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
105
106 if (simService != null)
107 m_SimulationService = simService;
108 else if (simulationService != string.Empty)
109 m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
110
111 m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty);
112 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
113
114 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
115 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
116
117 m_log.Debug("[GATEKEEPER SERVICE]: Starting...");
118 }
119 }
120
121 public GatekeeperService(IConfigSource config)
122 : this(config, null)
123 {
124 }
125
126 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason)
127 {
128 regionID = UUID.Zero;
129 regionHandle = 0;
130 externalName = m_ExternalName + ((regionName != string.Empty) ? " " + regionName : "");
131 imageURL = string.Empty;
132 reason = string.Empty;
133 GridRegion region = null;
134
135 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName);
136 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty)
137 {
138 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
139 if (defs != null && defs.Count > 0)
140 {
141 region = defs[0];
142 m_DefaultGatewayRegion = region;
143 }
144 else
145 {
146 reason = "Grid setup problem. Try specifying a particular region here.";
147 m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to send information. Please specify a default region for this grid!");
148 return false;
149 }
150 }
151 else
152 {
153 region = m_GridService.GetRegionByName(m_ScopeID, regionName);
154 if (region == null)
155 {
156 reason = "Region not found";
157 return false;
158 }
159 }
160
161 regionID = region.RegionID;
162 regionHandle = region.RegionHandle;
163
164 string regionimage = "regionImage" + regionID.ToString();
165 regionimage = regionimage.Replace("-", "");
166 imageURL = region.ServerURI + "index.php?method=" + regionimage;
167
168 return true;
169 }
170
171 public GridRegion GetHyperlinkRegion(UUID regionID)
172 {
173 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to get hyperlink region {0}", regionID);
174
175 if (!m_AllowTeleportsToAnyRegion)
176 // Don't even check the given regionID
177 return m_DefaultGatewayRegion;
178
179 GridRegion region = m_GridService.GetRegionByUUID(m_ScopeID, regionID);
180 return region;
181 }
182
183 #region Login Agent
184 public bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason)
185 {
186 reason = string.Empty;
187
188 string authURL = string.Empty;
189 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
190 authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
191 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}",
192 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName,
193 aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0);
194
195 //
196 // Check client
197 //
198 if (m_AllowedClients != string.Empty)
199 {
200 Regex arx = new Regex(m_AllowedClients);
201 Match am = arx.Match(aCircuit.Viewer);
202
203 if (!am.Success)
204 {
205 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", aCircuit.Viewer);
206 return false;
207 }
208 }
209
210 if (m_DeniedClients != string.Empty)
211 {
212 Regex drx = new Regex(m_DeniedClients);
213 Match dm = drx.Match(aCircuit.Viewer);
214
215 if (dm.Success)
216 {
217 m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", aCircuit.Viewer);
218 return false;
219 }
220 }
221
222 //
223 // Authenticate the user
224 //
225 if (!Authenticate(aCircuit))
226 {
227 reason = "Unable to verify identity";
228 m_log.InfoFormat("[GATEKEEPER SERVICE]: Unable to verify identity of agent {0} {1}. Refusing service.", aCircuit.firstname, aCircuit.lastname);
229 return false;
230 }
231 m_log.DebugFormat("[GATEKEEPER SERVICE]: Identity verified for {0} {1} @ {2}", aCircuit.firstname, aCircuit.lastname, authURL);
232
233 //
234 // Check for impersonations
235 //
236 UserAccount account = null;
237 if (m_UserAccountService != null)
238 {
239 // Check to see if we have a local user with that UUID
240 account = m_UserAccountService.GetUserAccount(m_ScopeID, aCircuit.AgentID);
241 if (account != null)
242 {
243 // Make sure this is the user coming home, and not a foreign user with same UUID as a local user
244 if (m_UserAgentService != null)
245 {
246 if (!m_UserAgentService.IsAgentComingHome(aCircuit.SessionID, m_ExternalName))
247 {
248 // Can't do, sorry
249 reason = "Unauthorized";
250 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agent {0} {1} has same ID as local user. Refusing service.",
251 aCircuit.firstname, aCircuit.lastname);
252 return false;
253
254 }
255 }
256 }
257 }
258 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
259
260 // May want to authorize
261
262 bool isFirstLogin = false;
263 //
264 // Login the presence, if it's not there yet (by the login service)
265 //
266 PresenceInfo presence = m_PresenceService.GetAgent(aCircuit.SessionID);
267 if (presence != null) // it has been placed there by the login service
268 isFirstLogin = true;
269
270 else
271 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID))
272 {
273 reason = "Unable to login presence";
274 m_log.InfoFormat("[GATEKEEPER SERVICE]: Presence login failed for foreign agent {0} {1}. Refusing service.",
275 aCircuit.firstname, aCircuit.lastname);
276 return false;
277 }
278 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
279
280 //
281 // Get the region
282 //
283 destination = m_GridService.GetRegionByUUID(m_ScopeID, destination.RegionID);
284 if (destination == null)
285 {
286 reason = "Destination region not found";
287 return false;
288 }
289 m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName);
290
291 //
292 // Adjust the visible name
293 //
294 if (account != null)
295 {
296 aCircuit.firstname = account.FirstName;
297 aCircuit.lastname = account.LastName;
298 }
299 if (account == null && !aCircuit.lastname.StartsWith("@"))
300 {
301 aCircuit.firstname = aCircuit.firstname + "." + aCircuit.lastname;
302 try
303 {
304 Uri uri = new Uri(aCircuit.ServiceURLs["HomeURI"].ToString());
305 aCircuit.lastname = "@" + uri.Host; // + ":" + uri.Port;
306 }
307 catch
308 {
309 m_log.WarnFormat("[GATEKEEPER SERVICE]: Malformed HomeURI (this should never happen): {0}", aCircuit.ServiceURLs["HomeURI"]);
310 aCircuit.lastname = "@" + aCircuit.ServiceURLs["HomeURI"].ToString();
311 }
312 }
313
314 //
315 // Finally launch the agent at the destination
316 //
317 Constants.TeleportFlags loginFlag = isFirstLogin ? Constants.TeleportFlags.ViaLogin : Constants.TeleportFlags.ViaHGLogin;
318 m_log.DebugFormat("[GATEKEEPER SERVICE]: launching agent {0}", loginFlag);
319 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)loginFlag, out reason);
320 }
321
322 protected bool Authenticate(AgentCircuitData aCircuit)
323 {
324 if (!CheckAddress(aCircuit.ServiceSessionID))
325 return false;
326
327 string userURL = string.Empty;
328 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
329 userURL = aCircuit.ServiceURLs["HomeURI"].ToString();
330
331 if (userURL == string.Empty)
332 {
333 m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide an authentication server URL");
334 return false;
335 }
336
337 if (userURL == m_ExternalName)
338 {
339 return m_UserAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID);
340 }
341 else
342 {
343 IUserAgentService userAgentService = new UserAgentServiceConnector(userURL);
344
345 try
346 {
347 return userAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID);
348 }
349 catch
350 {
351 m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to contact authentication service at {0}", userURL);
352 return false;
353 }
354 }
355
356 return false;
357 }
358
359 // Check that the service token was generated for *this* grid.
360 // If it wasn't then that's a fake agent.
361 protected bool CheckAddress(string serviceToken)
362 {
363 string[] parts = serviceToken.Split(new char[] { ';' });
364 if (parts.Length < 2)
365 return false;
366
367 char[] trailing_slash = new char[] { '/' };
368 string addressee = parts[0].TrimEnd(trailing_slash);
369 string externalname = m_ExternalName.TrimEnd(trailing_slash);
370 m_log.DebugFormat("[GATEKEEPER SERVICE]: Verifying {0} against {1}", addressee, externalname);
371
372 return string.Equals(addressee, externalname, StringComparison.OrdinalIgnoreCase);
373 }
374
375 #endregion
376
377
378 #region Misc
379
380
381 #endregion
382 }
383}
diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs
new file mode 100644
index 0000000..e518329
--- /dev/null
+++ b/OpenSim/Services/HypergridService/HGAssetService.cs
@@ -0,0 +1,148 @@
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.IO;
30using System.Reflection;
31using System.Xml;
32
33using Nini.Config;
34using log4net;
35using OpenMetaverse;
36
37using OpenSim.Framework;
38using OpenSim.Framework.Serialization.External;
39using OpenSim.Server.Base;
40using OpenSim.Services.Interfaces;
41using OpenSim.Services.AssetService;
42
43namespace OpenSim.Services.HypergridService
44{
45 /// <summary>
46 /// Hypergrid asset service. It serves the IAssetService interface,
47 /// but implements it in ways that are appropriate for inter-grid
48 /// asset exchanges.
49 /// </summary>
50 public class HGAssetService : OpenSim.Services.AssetService.AssetService, IAssetService
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 private string m_ProfileServiceURL;
57 private IUserAccountService m_UserAccountService;
58
59 private UserAccountCache m_Cache;
60
61 public HGAssetService(IConfigSource config) : base(config)
62 {
63 m_log.Debug("[HGAsset Service]: Starting");
64 IConfig assetConfig = config.Configs["HGAssetService"];
65 if (assetConfig == null)
66 throw new Exception("No HGAssetService configuration");
67
68 string userAccountsDll = assetConfig.GetString("UserAccountsService", string.Empty);
69 if (userAccountsDll == string.Empty)
70 throw new Exception("Please specify UserAccountsService in HGAssetService configuration");
71
72 Object[] args = new Object[] { config };
73 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountsDll, args);
74 if (m_UserAccountService == null)
75 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
76
77 m_ProfileServiceURL = assetConfig.GetString("ProfileServerURI", string.Empty);
78
79 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
80 }
81
82 #region IAssetService overrides
83 public override AssetBase Get(string id)
84 {
85 AssetBase asset = base.Get(id);
86
87 if (asset == null)
88 return null;
89
90 if (asset.Metadata.Type == (sbyte)AssetType.Object)
91 asset.Data = AdjustIdentifiers(asset.Data); ;
92
93 AdjustIdentifiers(asset.Metadata);
94
95 return asset;
96 }
97
98 public override AssetMetadata GetMetadata(string id)
99 {
100 AssetMetadata meta = base.GetMetadata(id);
101
102 if (meta == null)
103 return null;
104
105 AdjustIdentifiers(meta);
106
107 return meta;
108 }
109
110 public override byte[] GetData(string id)
111 {
112 byte[] data = base.GetData(id);
113
114 if (data == null)
115 return null;
116
117 return AdjustIdentifiers(data);
118 }
119
120 //public virtual bool Get(string id, Object sender, AssetRetrieved handler)
121
122 public override bool Delete(string id)
123 {
124 // NOGO
125 return false;
126 }
127
128 #endregion
129
130 protected void AdjustIdentifiers(AssetMetadata meta)
131 {
132 if (meta == null || m_Cache == null)
133 return;
134
135 UserAccount creator = m_Cache.GetUser(meta.CreatorID);
136 if (creator != null)
137 meta.CreatorID = m_ProfileServiceURL + "/" + meta.CreatorID + ";" + creator.FirstName + " " + creator.LastName;
138 }
139
140 protected byte[] AdjustIdentifiers(byte[] data)
141 {
142 string xml = Utils.BytesToString(data);
143 return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_ProfileServiceURL, m_Cache, UUID.Zero));
144 }
145
146 }
147
148}
diff --git a/OpenSim/Services/HypergridService/HGInstantMessageService.cs b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
new file mode 100644
index 0000000..0c9cfd3
--- /dev/null
+++ b/OpenSim/Services/HypergridService/HGInstantMessageService.cs
@@ -0,0 +1,346 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using OpenSim.Services.Connectors.InstantMessage;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39using OpenSim.Server.Base;
40using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
41
42using OpenMetaverse;
43using log4net;
44using Nini.Config;
45
46namespace OpenSim.Services.HypergridService
47{
48 /// <summary>
49 /// Inter-grid IM
50 /// </summary>
51 public class HGInstantMessageService : IInstantMessage
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours
58
59 static bool m_Initialized = false;
60
61 protected static IGridService m_GridService;
62 protected static IPresenceService m_PresenceService;
63 protected static IUserAgentService m_UserAgentService;
64
65 protected static IInstantMessageSimConnector m_IMSimConnector;
66
67 protected static Dictionary<UUID, object> m_UserLocationMap = new Dictionary<UUID, object>();
68 private static ExpiringCache<UUID, GridRegion> m_RegionCache;
69
70 private static string m_RestURL;
71 private static bool m_ForwardOfflineGroupMessages;
72 private static bool m_InGatekeeper;
73
74 public HGInstantMessageService(IConfigSource config)
75 : this(config, null)
76 {
77 }
78
79 public HGInstantMessageService(IConfigSource config, IInstantMessageSimConnector imConnector)
80 {
81 if (imConnector != null)
82 m_IMSimConnector = imConnector;
83
84 if (!m_Initialized)
85 {
86 m_Initialized = true;
87
88 IConfig serverConfig = config.Configs["HGInstantMessageService"];
89 if (serverConfig == null)
90 throw new Exception(String.Format("No section HGInstantMessageService in config file"));
91
92 string gridService = serverConfig.GetString("GridService", String.Empty);
93 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
94 string userAgentService = serverConfig.GetString("UserAgentService", String.Empty);
95 m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false);
96 m_log.DebugFormat("[HG IM SERVICE]: Starting... InRobust? {0}", m_InGatekeeper);
97
98 if (gridService == string.Empty || presenceService == string.Empty)
99 throw new Exception(String.Format("Incomplete specifications, InstantMessage Service cannot function."));
100
101 Object[] args = new Object[] { config };
102 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
103 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
104 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(userAgentService, args);
105
106 m_RegionCache = new ExpiringCache<UUID, GridRegion>();
107
108 IConfig cnf = config.Configs["Messaging"];
109 if (cnf == null)
110 {
111 return;
112 }
113
114 m_RestURL = cnf.GetString("OfflineMessageURL", string.Empty);
115 m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", false);
116
117 }
118 }
119
120 public bool IncomingInstantMessage(GridInstantMessage im)
121 {
122// m_log.DebugFormat("[HG IM SERVICE]: Received message from {0} to {1}", im.fromAgentID, im.toAgentID);
123// UUID toAgentID = new UUID(im.toAgentID);
124
125 bool success = false;
126 if (m_IMSimConnector != null)
127 {
128 //m_log.DebugFormat("[XXX] SendIMToRegion local im connector");
129 success = m_IMSimConnector.SendInstantMessage(im);
130 }
131 else
132 {
133 success = TrySendInstantMessage(im, "", true, false);
134 }
135
136 if (!success && m_InGatekeeper) // we do this only in the Gatekeeper IM service
137 UndeliveredMessage(im);
138
139 return success;
140 }
141
142 public bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner)
143 {
144// m_log.DebugFormat("[HG IM SERVICE]: Sending message from {0} to {1}@{2}", im.fromAgentID, im.toAgentID, url);
145 if (url != string.Empty)
146 return TrySendInstantMessage(im, url, true, foreigner);
147 else
148 {
149 PresenceInfo upd = new PresenceInfo();
150 upd.RegionID = UUID.Zero;
151 return TrySendInstantMessage(im, upd, true, foreigner);
152 }
153
154 }
155
156 protected bool TrySendInstantMessage(GridInstantMessage im, object previousLocation, bool firstTime, bool foreigner)
157 {
158 UUID toAgentID = new UUID(im.toAgentID);
159
160 PresenceInfo upd = null;
161 string url = string.Empty;
162
163 bool lookupAgent = false;
164
165 lock (m_UserLocationMap)
166 {
167 if (m_UserLocationMap.ContainsKey(toAgentID))
168 {
169 object o = m_UserLocationMap[toAgentID];
170 if (o is PresenceInfo)
171 upd = (PresenceInfo)o;
172 else if (o is string)
173 url = (string)o;
174
175 // We need to compare the current location with the previous
176 // or the recursive loop will never end because it will never try to lookup the agent again
177 if (!firstTime)
178 {
179 lookupAgent = true;
180 upd = null;
181 }
182 }
183 else
184 {
185 lookupAgent = true;
186 }
187 }
188
189 //m_log.DebugFormat("[XXX] Neeed lookup ? {0}", (lookupAgent ? "yes" : "no"));
190
191 // Are we needing to look-up an agent?
192 if (lookupAgent)
193 {
194 // Non-cached user agent lookup.
195 PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { toAgentID.ToString() });
196 if (presences != null && presences.Length > 0)
197 {
198 foreach (PresenceInfo p in presences)
199 {
200 if (p.RegionID != UUID.Zero)
201 {
202 //m_log.DebugFormat("[XXX]: Found presence in {0}", p.RegionID);
203 upd = p;
204 break;
205 }
206 }
207 }
208
209 if (upd == null && !foreigner)
210 {
211 // Let's check with the UAS if the user is elsewhere
212 m_log.DebugFormat("[HG IM SERVICE]: User is not present. Checking location with User Agent service");
213 url = m_UserAgentService.LocateUser(toAgentID);
214 }
215
216 // check if we've tried this before..
217 // This is one way to end the recursive loop
218 //
219 if (!firstTime && ((previousLocation is PresenceInfo && upd != null && upd.RegionID == ((PresenceInfo)previousLocation).RegionID) ||
220 (previousLocation is string && upd == null && previousLocation.Equals(url))))
221 {
222 // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message");
223 m_log.DebugFormat("[HG IM SERVICE]: Fail 2 {0} {1}", previousLocation, url);
224
225 return false;
226 }
227 }
228
229 if (upd != null)
230 {
231 // ok, the user is around somewhere. Let's send back the reply with "success"
232 // even though the IM may still fail. Just don't keep the caller waiting for
233 // the entire time we're trying to deliver the IM
234 return SendIMToRegion(upd, im, toAgentID, foreigner);
235 }
236 else if (url != string.Empty)
237 {
238 // ok, the user is around somewhere. Let's send back the reply with "success"
239 // even though the IM may still fail. Just don't keep the caller waiting for
240 // the entire time we're trying to deliver the IM
241 return ForwardIMToGrid(url, im, toAgentID, foreigner);
242 }
243 else if (firstTime && previousLocation is string && (string)previousLocation != string.Empty)
244 {
245 return ForwardIMToGrid((string)previousLocation, im, toAgentID, foreigner);
246 }
247 else
248 m_log.DebugFormat("[HG IM SERVICE]: Unable to locate user {0}", toAgentID);
249 return false;
250 }
251
252 bool SendIMToRegion(PresenceInfo upd, GridInstantMessage im, UUID toAgentID, bool foreigner)
253 {
254 bool imresult = false;
255 GridRegion reginfo = null;
256 if (!m_RegionCache.TryGetValue(upd.RegionID, out reginfo))
257 {
258 reginfo = m_GridService.GetRegionByUUID(UUID.Zero /*!!!*/, upd.RegionID);
259 if (reginfo != null)
260 m_RegionCache.AddOrUpdate(upd.RegionID, reginfo, CACHE_EXPIRATION_SECONDS);
261 }
262
263 if (reginfo != null)
264 {
265 imresult = InstantMessageServiceConnector.SendInstantMessage(reginfo.ServerURI, im);
266 }
267 else
268 {
269 m_log.DebugFormat("[HG IM SERVICE]: Failed to deliver message to {0}", reginfo.ServerURI);
270 return false;
271 }
272
273 if (imresult)
274 {
275 // IM delivery successful, so store the Agent's location in our local cache.
276 lock (m_UserLocationMap)
277 {
278 if (m_UserLocationMap.ContainsKey(toAgentID))
279 {
280 m_UserLocationMap[toAgentID] = upd;
281 }
282 else
283 {
284 m_UserLocationMap.Add(toAgentID, upd);
285 }
286 }
287 return true;
288 }
289 else
290 {
291 // try again, but lookup user this time.
292 // Warning, this must call the Async version
293 // of this method or we'll be making thousands of threads
294 // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync
295 // The version that spawns the thread is SendGridInstantMessageViaXMLRPC
296
297 // This is recursive!!!!!
298 return TrySendInstantMessage(im, upd, false, foreigner);
299 }
300 }
301
302 bool ForwardIMToGrid(string url, GridInstantMessage im, UUID toAgentID, bool foreigner)
303 {
304 if (InstantMessageServiceConnector.SendInstantMessage(url, im))
305 {
306 // IM delivery successful, so store the Agent's location in our local cache.
307 lock (m_UserLocationMap)
308 {
309 if (m_UserLocationMap.ContainsKey(toAgentID))
310 {
311 m_UserLocationMap[toAgentID] = url;
312 }
313 else
314 {
315 m_UserLocationMap.Add(toAgentID, url);
316 }
317 }
318
319 return true;
320 }
321 else
322 {
323 // try again, but lookup user this time.
324
325 // This is recursive!!!!!
326 return TrySendInstantMessage(im, url, false, foreigner);
327 }
328 }
329
330 private bool UndeliveredMessage(GridInstantMessage im)
331 {
332 if (m_RestURL != string.Empty && (im.offline != 0)
333 && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages)))
334 {
335// m_log.DebugFormat("[HG IM SERVICE]: Message saved");
336
337 return SynchronousRestObjectRequester.MakeRequest<GridInstantMessage, bool>(
338 "POST", m_RestURL + "/SaveMessage/", im);
339 }
340 else
341 {
342 return false;
343 }
344 }
345 }
346} \ No newline at end of file
diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs
new file mode 100644
index 0000000..4eb61ba
--- /dev/null
+++ b/OpenSim/Services/HypergridService/HGInventoryService.cs
@@ -0,0 +1,342 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using log4net;
32using Nini.Config;
33using System.Reflection;
34using OpenSim.Services.Base;
35using OpenSim.Services.Interfaces;
36using OpenSim.Services.InventoryService;
37using OpenSim.Data;
38using OpenSim.Framework;
39using OpenSim.Server.Base;
40
41namespace OpenSim.Services.HypergridService
42{
43 /// <summary>
44 /// Hypergrid inventory service. It serves the IInventoryService interface,
45 /// but implements it in ways that are appropriate for inter-grid
46 /// inventory exchanges. Specifically, it does not performs deletions
47 /// and it responds to GetRootFolder requests with the ID of the
48 /// Suitcase folder, not the actual "My Inventory" folder.
49 /// </summary>
50 public class HGInventoryService : XInventoryService, IInventoryService
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType);
55
56 protected new IXInventoryData m_Database;
57
58 private string m_ProfileServiceURL;
59 private IUserAccountService m_UserAccountService;
60
61 private UserAccountCache m_Cache;
62
63 public HGInventoryService(IConfigSource config)
64 : base(config)
65 {
66 m_log.Debug("[HGInventory Service]: Starting");
67
68 string dllName = String.Empty;
69 string connString = String.Empty;
70 //string realm = "Inventory"; // OSG version doesn't use this
71
72 //
73 // Try reading the [DatabaseService] section, if it exists
74 //
75 IConfig dbConfig = config.Configs["DatabaseService"];
76 if (dbConfig != null)
77 {
78 if (dllName == String.Empty)
79 dllName = dbConfig.GetString("StorageProvider", String.Empty);
80 if (connString == String.Empty)
81 connString = dbConfig.GetString("ConnectionString", String.Empty);
82 }
83
84 //
85 // Try reading the [InventoryService] section, if it exists
86 //
87 IConfig invConfig = config.Configs["HGInventoryService"];
88 if (invConfig != null)
89 {
90 dllName = invConfig.GetString("StorageProvider", dllName);
91 connString = invConfig.GetString("ConnectionString", connString);
92
93 // realm = authConfig.GetString("Realm", realm);
94 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
95 if (userAccountsDll == string.Empty)
96 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
97
98 Object[] args = new Object[] { config };
99 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountsDll, args);
100 if (m_UserAccountService == null)
101 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
102
103 m_ProfileServiceURL = invConfig.GetString("ProfileServerURI", string.Empty);
104
105 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
106 }
107
108 //
109 // We tried, but this doesn't exist. We can't proceed.
110 //
111 if (dllName == String.Empty)
112 throw new Exception("No StorageProvider configured");
113
114 m_Database = LoadPlugin<IXInventoryData>(dllName,
115 new Object[] {connString, String.Empty});
116 if (m_Database == null)
117 throw new Exception("Could not find a storage interface in the given module");
118
119 m_log.Debug("[HG INVENTORY SERVICE]: Starting...");
120 }
121
122 public override bool CreateUserInventory(UUID principalID)
123 {
124 // NOGO
125 return false;
126 }
127
128
129 public override List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
130 {
131 // NOGO for this inventory service
132 return new List<InventoryFolderBase>();
133 }
134
135 public override InventoryFolderBase GetRootFolder(UUID principalID)
136 {
137 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetRootFolder for {0}", principalID);
138 // Warp! Root folder for travelers
139 XInventoryFolder[] folders = m_Database.GetFolders(
140 new string[] { "agentID", "folderName"},
141 new string[] { principalID.ToString(), "My Suitcase" });
142
143 if (folders.Length > 0)
144 return ConvertToOpenSim(folders[0]);
145
146 // make one
147 XInventoryFolder suitcase = CreateFolder(principalID, UUID.Zero, (int)AssetType.Folder, "My Suitcase");
148 return ConvertToOpenSim(suitcase);
149 }
150
151 //private bool CreateSystemFolders(UUID principalID, XInventoryFolder suitcase)
152 //{
153
154 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Animation, "Animations");
155 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Bodypart, "Body Parts");
156 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.CallingCard, "Calling Cards");
157 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Clothing, "Clothing");
158 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Gesture, "Gestures");
159 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Landmark, "Landmarks");
160 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.LostAndFoundFolder, "Lost And Found");
161 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Notecard, "Notecards");
162 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Object, "Objects");
163 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.SnapshotFolder, "Photo Album");
164 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.LSLText, "Scripts");
165 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Sound, "Sounds");
166 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.Texture, "Textures");
167 // CreateFolder(principalID, suitcase.folderID, (int)AssetType.TrashFolder, "Trash");
168
169 // return true;
170 //}
171
172
173 public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
174 {
175 //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type);
176 return GetRootFolder(principalID);
177 }
178
179 //
180 // Use the inherited methods
181 //
182 //public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
183 //{
184 //}
185
186 //public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
187 //{
188 //}
189
190 //public override bool AddFolder(InventoryFolderBase folder)
191 //{
192 // // Check if it's under the Suitcase folder
193 // List<InventoryFolderBase> skel = base.GetInventorySkeleton(folder.Owner);
194 // InventoryFolderBase suitcase = GetRootFolder(folder.Owner);
195 // List<InventoryFolderBase> suitDescendents = GetDescendents(skel, suitcase.ID);
196
197 // foreach (InventoryFolderBase f in suitDescendents)
198 // if (folder.ParentID == f.ID)
199 // {
200 // XInventoryFolder xFolder = ConvertFromOpenSim(folder);
201 // return m_Database.StoreFolder(xFolder);
202 // }
203 // return false;
204 //}
205
206 private List<InventoryFolderBase> GetDescendents(List<InventoryFolderBase> lst, UUID root)
207 {
208 List<InventoryFolderBase> direct = lst.FindAll(delegate(InventoryFolderBase f) { return f.ParentID == root; });
209 if (direct == null)
210 return new List<InventoryFolderBase>();
211
212 List<InventoryFolderBase> indirect = new List<InventoryFolderBase>();
213 foreach (InventoryFolderBase f in direct)
214 indirect.AddRange(GetDescendents(lst, f.ID));
215
216 direct.AddRange(indirect);
217 return direct;
218 }
219
220 // Use inherited method
221 //public bool UpdateFolder(InventoryFolderBase folder)
222 //{
223 //}
224
225 //public override bool MoveFolder(InventoryFolderBase folder)
226 //{
227 // XInventoryFolder[] x = m_Database.GetFolders(
228 // new string[] { "folderID" },
229 // new string[] { folder.ID.ToString() });
230
231 // if (x.Length == 0)
232 // return false;
233
234 // // Check if it's under the Suitcase folder
235 // List<InventoryFolderBase> skel = base.GetInventorySkeleton(folder.Owner);
236 // InventoryFolderBase suitcase = GetRootFolder(folder.Owner);
237 // List<InventoryFolderBase> suitDescendents = GetDescendents(skel, suitcase.ID);
238
239 // foreach (InventoryFolderBase f in suitDescendents)
240 // if (folder.ParentID == f.ID)
241 // {
242 // x[0].parentFolderID = folder.ParentID;
243 // return m_Database.StoreFolder(x[0]);
244 // }
245
246 // return false;
247 //}
248
249 public override bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
250 {
251 // NOGO
252 return false;
253 }
254
255 public override bool PurgeFolder(InventoryFolderBase folder)
256 {
257 // NOGO
258 return false;
259 }
260
261 // Unfortunately we need to use the inherited method because of how DeRez works.
262 // The viewer sends the folderID hard-wired in the derez message
263 //public override bool AddItem(InventoryItemBase item)
264 //{
265 // // Check if it's under the Suitcase folder
266 // List<InventoryFolderBase> skel = base.GetInventorySkeleton(item.Owner);
267 // InventoryFolderBase suitcase = GetRootFolder(item.Owner);
268 // List<InventoryFolderBase> suitDescendents = GetDescendents(skel, suitcase.ID);
269
270 // foreach (InventoryFolderBase f in suitDescendents)
271 // if (item.Folder == f.ID)
272 // return m_Database.StoreItem(ConvertFromOpenSim(item));
273
274 // return false;
275 //}
276
277 //public override bool UpdateItem(InventoryItemBase item)
278 //{
279 // // Check if it's under the Suitcase folder
280 // List<InventoryFolderBase> skel = base.GetInventorySkeleton(item.Owner);
281 // InventoryFolderBase suitcase = GetRootFolder(item.Owner);
282 // List<InventoryFolderBase> suitDescendents = GetDescendents(skel, suitcase.ID);
283
284 // foreach (InventoryFolderBase f in suitDescendents)
285 // if (item.Folder == f.ID)
286 // return m_Database.StoreItem(ConvertFromOpenSim(item));
287
288 // return false;
289 //}
290
291 //public override bool MoveItems(UUID principalID, List<InventoryItemBase> items)
292 //{
293 // // Principal is b0rked. *sigh*
294 // //
295 // // Let's assume they all have the same principal
296 // // Check if it's under the Suitcase folder
297 // List<InventoryFolderBase> skel = base.GetInventorySkeleton(items[0].Owner);
298 // InventoryFolderBase suitcase = GetRootFolder(items[0].Owner);
299 // List<InventoryFolderBase> suitDescendents = GetDescendents(skel, suitcase.ID);
300
301 // foreach (InventoryItemBase i in items)
302 // {
303 // foreach (InventoryFolderBase f in suitDescendents)
304 // if (i.Folder == f.ID)
305 // m_Database.MoveItem(i.ID.ToString(), i.Folder.ToString());
306 // }
307
308 // return true;
309 //}
310
311 // Let these pass. Use inherited methods.
312 //public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
313 //{
314 //}
315
316 public override InventoryItemBase GetItem(InventoryItemBase item)
317 {
318 InventoryItemBase it = base.GetItem(item);
319
320 UserAccount user = m_Cache.GetUser(it.CreatorId);
321
322 // Adjust the creator data
323 if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty))
324 it.CreatorData = m_ProfileServiceURL + "/" + it.CreatorId + ";" + user.FirstName + " " + user.LastName;
325
326 return it;
327 }
328
329 //public InventoryFolderBase GetFolder(InventoryFolderBase folder)
330 //{
331 //}
332
333 //public List<InventoryItemBase> GetActiveGestures(UUID principalID)
334 //{
335 //}
336
337 //public int GetAssetPermissions(UUID principalID, UUID assetID)
338 //{
339 //}
340
341 }
342}
diff --git a/OpenSim/Services/HypergridService/UserAccountCache.cs b/OpenSim/Services/HypergridService/UserAccountCache.cs
new file mode 100644
index 0000000..e0a3e61
--- /dev/null
+++ b/OpenSim/Services/HypergridService/UserAccountCache.cs
@@ -0,0 +1,111 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4
5using log4net;
6using OpenMetaverse;
7
8using OpenSim.Services.Interfaces;
9
10namespace OpenSim.Services.HypergridService
11{
12 public class UserAccountCache : IUserAccountService
13 {
14 private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
15
16// private static readonly ILog m_log =
17// LogManager.GetLogger(
18// MethodBase.GetCurrentMethod().DeclaringType);
19
20 private ExpiringCache<UUID, UserAccount> m_UUIDCache;
21
22 private IUserAccountService m_UserAccountService;
23
24 private static UserAccountCache m_Singleton;
25
26 public static UserAccountCache CreateUserAccountCache(IUserAccountService u)
27 {
28 if (m_Singleton == null)
29 m_Singleton = new UserAccountCache(u);
30
31 return m_Singleton;
32 }
33
34 private UserAccountCache(IUserAccountService u)
35 {
36 m_UUIDCache = new ExpiringCache<UUID, UserAccount>();
37 m_UserAccountService = u;
38 }
39
40 public void Cache(UUID userID, UserAccount account)
41 {
42 // Cache even null accounts
43 m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
44
45 //m_log.DebugFormat("[USER CACHE]: cached user {0}", userID);
46 }
47
48 public UserAccount Get(UUID userID, out bool inCache)
49 {
50 UserAccount account = null;
51 inCache = false;
52 if (m_UUIDCache.TryGetValue(userID, out account))
53 {
54 //m_log.DebugFormat("[USER CACHE]: Account {0} {1} found in cache", account.FirstName, account.LastName);
55 inCache = true;
56 return account;
57 }
58
59 return null;
60 }
61
62 public UserAccount GetUser(string id)
63 {
64 UUID uuid = UUID.Zero;
65 UUID.TryParse(id, out uuid);
66 bool inCache = false;
67 UserAccount account = Get(uuid, out inCache);
68 if (!inCache)
69 {
70 account = m_UserAccountService.GetUserAccount(UUID.Zero, uuid);
71 Cache(uuid, account);
72 }
73
74 return account;
75 }
76
77 #region IUserAccountService
78 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
79 {
80 return GetUser(userID.ToString());
81 }
82
83 public UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName)
84 {
85 return null;
86 }
87
88 public UserAccount GetUserAccount(UUID scopeID, string Email)
89 {
90 return null;
91 }
92
93 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string query)
94 {
95 return null;
96 }
97
98 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
99 {
100 return null;
101 }
102
103 public bool StoreUserAccount(UserAccount data)
104 {
105 return false;
106 }
107 #endregion
108
109 }
110
111}
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
new file mode 100644
index 0000000..398a7b7
--- /dev/null
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -0,0 +1,545 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Friends;
35using OpenSim.Services.Connectors.Hypergrid;
36using OpenSim.Services.Interfaces;
37using GridRegion = OpenSim.Services.Interfaces.GridRegion;
38using OpenSim.Server.Base;
39using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
40
41using OpenMetaverse;
42using log4net;
43using Nini.Config;
44
45namespace OpenSim.Services.HypergridService
46{
47 /// <summary>
48 /// This service is for HG1.5 only, to make up for the fact that clients don't
49 /// keep any private information in themselves, and that their 'home service'
50 /// needs to do it for them.
51 /// Once we have better clients, this shouldn't be needed.
52 /// </summary>
53 public class UserAgentService : IUserAgentService
54 {
55 private static readonly ILog m_log =
56 LogManager.GetLogger(
57 MethodBase.GetCurrentMethod().DeclaringType);
58
59 // This will need to go into a DB table
60 static Dictionary<UUID, TravelingAgentInfo> m_TravelingAgents = new Dictionary<UUID, TravelingAgentInfo>();
61
62 static bool m_Initialized = false;
63
64 protected static IGridUserService m_GridUserService;
65 protected static IGridService m_GridService;
66 protected static GatekeeperServiceConnector m_GatekeeperConnector;
67 protected static IGatekeeperService m_GatekeeperService;
68 protected static IFriendsService m_FriendsService;
69 protected static IPresenceService m_PresenceService;
70 protected static IUserAccountService m_UserAccountService;
71 protected static IFriendsSimConnector m_FriendsLocalSimConnector; // standalone, points to HGFriendsModule
72 protected static FriendsSimConnector m_FriendsSimConnector; // grid
73
74 protected static string m_GridName;
75
76 protected static bool m_BypassClientVerification;
77
78 public UserAgentService(IConfigSource config) : this(config, null)
79 {
80 }
81
82 public UserAgentService(IConfigSource config, IFriendsSimConnector friendsConnector)
83 {
84 // Let's set this always, because we don't know the sequence
85 // of instantiations
86 if (friendsConnector != null)
87 m_FriendsLocalSimConnector = friendsConnector;
88
89 if (!m_Initialized)
90 {
91 m_Initialized = true;
92
93 m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
94
95 m_FriendsSimConnector = new FriendsSimConnector();
96
97 IConfig serverConfig = config.Configs["UserAgentService"];
98 if (serverConfig == null)
99 throw new Exception(String.Format("No section UserAgentService in config file"));
100
101 string gridService = serverConfig.GetString("GridService", String.Empty);
102 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
103 string gatekeeperService = serverConfig.GetString("GatekeeperService", String.Empty);
104 string friendsService = serverConfig.GetString("FriendsService", String.Empty);
105 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
106 string userAccountService = serverConfig.GetString("UserAccountService", String.Empty);
107
108 m_BypassClientVerification = serverConfig.GetBoolean("BypassClientVerification", false);
109
110 if (gridService == string.Empty || gridUserService == string.Empty || gatekeeperService == string.Empty)
111 throw new Exception(String.Format("Incomplete specifications, UserAgent Service cannot function."));
112
113 Object[] args = new Object[] { config };
114 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
115 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
116 m_GatekeeperConnector = new GatekeeperServiceConnector();
117 m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
118 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
119 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
120 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
121
122 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
123 if (m_GridName == string.Empty)
124 {
125 serverConfig = config.Configs["GatekeeperService"];
126 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
127 }
128 if (!m_GridName.EndsWith("/"))
129 m_GridName = m_GridName + "/";
130 }
131 }
132
133 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
134 {
135 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY;
136
137 m_log.DebugFormat("[USER AGENT SERVICE]: Request to get home region of user {0}", userID);
138
139 GridRegion home = null;
140 GridUserInfo uinfo = m_GridUserService.GetGridUserInfo(userID.ToString());
141 if (uinfo != null)
142 {
143 if (uinfo.HomeRegionID != UUID.Zero)
144 {
145 home = m_GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID);
146 position = uinfo.HomePosition;
147 lookAt = uinfo.HomeLookAt;
148 }
149 if (home == null)
150 {
151 List<GridRegion> defs = m_GridService.GetDefaultRegions(UUID.Zero);
152 if (defs != null && defs.Count > 0)
153 home = defs[0];
154 }
155 }
156
157 return home;
158 }
159
160 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason)
161 {
162 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
163 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI);
164 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination
165 GridRegion region = new GridRegion(gatekeeper);
166 region.ServerURI = gatekeeper.ServerURI;
167 region.ExternalHostName = finalDestination.ExternalHostName;
168 region.InternalEndPoint = finalDestination.InternalEndPoint;
169 region.RegionName = finalDestination.RegionName;
170 region.RegionID = finalDestination.RegionID;
171 region.RegionLocX = finalDestination.RegionLocX;
172 region.RegionLocY = finalDestination.RegionLocY;
173
174 // Generate a new service session
175 agentCircuit.ServiceSessionID = region.ServerURI + ";" + UUID.Random();
176 TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region);
177
178 bool success = false;
179 string myExternalIP = string.Empty;
180 string gridName = gatekeeper.ServerURI;
181
182 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
183
184 if (m_GridName == gridName)
185 success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
186 else
187 {
188 success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out myExternalIP, out reason);
189 if (success)
190 // Report them as nowhere
191 m_PresenceService.ReportAgent(agentCircuit.SessionID, UUID.Zero);
192 }
193
194 if (!success)
195 {
196 m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}",
197 agentCircuit.firstname, agentCircuit.lastname, region.ServerURI, reason);
198
199 // restore the old travel info
200 lock (m_TravelingAgents)
201 {
202 if (old == null)
203 m_TravelingAgents.Remove(agentCircuit.SessionID);
204 else
205 m_TravelingAgents[agentCircuit.SessionID] = old;
206 }
207
208 return false;
209 }
210
211 m_log.DebugFormat("[USER AGENT SERVICE]: Gatekeeper sees me as {0}", myExternalIP);
212 // else set the IP addresses associated with this client
213 if (clientIP != null)
214 m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress = clientIP.Address.ToString();
215 m_TravelingAgents[agentCircuit.SessionID].MyIpAddress = myExternalIP;
216
217 return true;
218 }
219
220 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
221 {
222 reason = string.Empty;
223 return LoginAgentToGrid(agentCircuit, gatekeeper, finalDestination, null, out reason);
224 }
225
226 private void SetClientIP(UUID sessionID, string ip)
227 {
228 if (m_TravelingAgents.ContainsKey(sessionID))
229 {
230 m_log.DebugFormat("[USER AGENT SERVICE]: Setting IP {0} for session {1}", ip, sessionID);
231 m_TravelingAgents[sessionID].ClientIPAddress = ip;
232 }
233 }
234
235 TravelingAgentInfo UpdateTravelInfo(AgentCircuitData agentCircuit, GridRegion region)
236 {
237 TravelingAgentInfo travel = new TravelingAgentInfo();
238 TravelingAgentInfo old = null;
239 lock (m_TravelingAgents)
240 {
241 if (m_TravelingAgents.ContainsKey(agentCircuit.SessionID))
242 {
243 // Very important! Override whatever this agent comes with.
244 // UserAgentService always sets the IP for every new agent
245 // with the original IP address.
246 agentCircuit.IPAddress = m_TravelingAgents[agentCircuit.SessionID].ClientIPAddress;
247
248 old = m_TravelingAgents[agentCircuit.SessionID];
249 }
250
251 m_TravelingAgents[agentCircuit.SessionID] = travel;
252 }
253 travel.UserID = agentCircuit.AgentID;
254 travel.GridExternalName = region.ServerURI;
255 travel.ServiceToken = agentCircuit.ServiceSessionID;
256 if (old != null)
257 travel.ClientIPAddress = old.ClientIPAddress;
258
259 return old;
260 }
261
262 public void LogoutAgent(UUID userID, UUID sessionID)
263 {
264 m_log.DebugFormat("[USER AGENT SERVICE]: User {0} logged out", userID);
265
266 lock (m_TravelingAgents)
267 {
268 List<UUID> travels = new List<UUID>();
269 foreach (KeyValuePair<UUID, TravelingAgentInfo> kvp in m_TravelingAgents)
270 if (kvp.Value == null) // do some clean up
271 travels.Add(kvp.Key);
272 else if (kvp.Value.UserID == userID)
273 travels.Add(kvp.Key);
274 foreach (UUID session in travels)
275 m_TravelingAgents.Remove(session);
276 }
277
278 GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(userID.ToString());
279 if (guinfo != null)
280 m_GridUserService.LoggedOut(userID.ToString(), sessionID, guinfo.LastRegionID, guinfo.LastPosition, guinfo.LastLookAt);
281 }
282
283 // We need to prevent foreign users with the same UUID as a local user
284 public bool IsAgentComingHome(UUID sessionID, string thisGridExternalName)
285 {
286 if (!m_TravelingAgents.ContainsKey(sessionID))
287 return false;
288
289 TravelingAgentInfo travel = m_TravelingAgents[sessionID];
290
291 return travel.GridExternalName.ToLower() == thisGridExternalName.ToLower();
292 }
293
294 public bool VerifyClient(UUID sessionID, string reportedIP)
295 {
296 if (m_BypassClientVerification)
297 return true;
298
299 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying Client session {0} with reported IP {1}.",
300 sessionID, reportedIP);
301
302 if (m_TravelingAgents.ContainsKey(sessionID))
303 {
304 m_log.DebugFormat("[USER AGENT SERVICE]: Comparing with login IP {0} and MyIP {1}",
305 m_TravelingAgents[sessionID].ClientIPAddress, m_TravelingAgents[sessionID].MyIpAddress);
306
307 return m_TravelingAgents[sessionID].ClientIPAddress == reportedIP ||
308 m_TravelingAgents[sessionID].MyIpAddress == reportedIP; // NATed
309 }
310
311 return false;
312 }
313
314 public bool VerifyAgent(UUID sessionID, string token)
315 {
316 if (m_TravelingAgents.ContainsKey(sessionID))
317 {
318 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, m_TravelingAgents[sessionID].ServiceToken);
319 return m_TravelingAgents[sessionID].ServiceToken == token;
320 }
321
322 m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID);
323
324 return false;
325 }
326
327 public List<UUID> StatusNotification(List<string> friends, UUID foreignUserID, bool online)
328 {
329 if (m_FriendsService == null || m_PresenceService == null)
330 {
331 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to perform status notifications because friends or presence services are missing");
332 return new List<UUID>();
333 }
334
335 List<UUID> localFriendsOnline = new List<UUID>();
336
337 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: foreign user {0} wants to notify {1} local friends", foreignUserID, friends.Count);
338
339 // First, let's double check that the reported friends are, indeed, friends of that user
340 // And let's check that the secret matches
341 List<string> usersToBeNotified = new List<string>();
342 foreach (string uui in friends)
343 {
344 UUID localUserID;
345 string secret = string.Empty, tmp = string.Empty;
346 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
347 {
348 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
349 foreach (FriendInfo finfo in friendInfos)
350 {
351 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret))
352 {
353 // great!
354 usersToBeNotified.Add(localUserID.ToString());
355 }
356 }
357 }
358 }
359
360 // Now, let's send the notifications
361 m_log.DebugFormat("[USER AGENT SERVICE]: Status notification: user has {0} local friends", usersToBeNotified.Count);
362
363 // First, let's send notifications to local users who are online in the home grid
364 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
365 if (friendSessions != null && friendSessions.Length > 0)
366 {
367 PresenceInfo friendSession = null;
368 foreach (PresenceInfo pinfo in friendSessions)
369 if (pinfo.RegionID != UUID.Zero) // let's guard against traveling agents
370 {
371 friendSession = pinfo;
372 break;
373 }
374
375 if (friendSession != null)
376 {
377 ForwardStatusNotificationToSim(friendSession.RegionID, foreignUserID, friendSession.UserID, online);
378 usersToBeNotified.Remove(friendSession.UserID.ToString());
379 UUID id;
380 if (UUID.TryParse(friendSession.UserID, out id))
381 localFriendsOnline.Add(id);
382
383 }
384 }
385
386 // Lastly, let's notify the rest who may be online somewhere else
387 foreach (string user in usersToBeNotified)
388 {
389 UUID id = new UUID(user);
390 if (m_TravelingAgents.ContainsKey(id) && m_TravelingAgents[id].GridExternalName != m_GridName)
391 {
392 string url = m_TravelingAgents[id].GridExternalName;
393 // forward
394 m_log.WarnFormat("[USER AGENT SERVICE]: User {0} is visiting {1}. HG Status notifications still not implemented.", user, url);
395 }
396 }
397
398 // and finally, let's send the online friends
399 if (online)
400 {
401 return localFriendsOnline;
402 }
403 else
404 return new List<UUID>();
405 }
406
407 protected void ForwardStatusNotificationToSim(UUID regionID, UUID foreignUserID, string user, bool online)
408 {
409 UUID userID;
410 if (UUID.TryParse(user, out userID))
411 {
412 if (m_FriendsLocalSimConnector != null)
413 {
414 m_log.DebugFormat("[USER AGENT SERVICE]: Local Notify, user {0} is {1}", foreignUserID, (online ? "online" : "offline"));
415 m_FriendsLocalSimConnector.StatusNotify(foreignUserID, userID, online);
416 }
417 else
418 {
419 GridRegion region = m_GridService.GetRegionByUUID(UUID.Zero /* !!! */, regionID);
420 if (region != null)
421 {
422 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
423 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online);
424 }
425 }
426 }
427 }
428
429 public List<UUID> GetOnlineFriends(UUID foreignUserID, List<string> friends)
430 {
431 List<UUID> online = new List<UUID>();
432
433 if (m_FriendsService == null || m_PresenceService == null)
434 {
435 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get online friends because friends or presence services are missing");
436 return online;
437 }
438
439 m_log.DebugFormat("[USER AGENT SERVICE]: Foreign user {0} wants to know status of {1} local friends", foreignUserID, friends.Count);
440
441 // First, let's double check that the reported friends are, indeed, friends of that user
442 // And let's check that the secret matches and the rights
443 List<string> usersToBeNotified = new List<string>();
444 foreach (string uui in friends)
445 {
446 UUID localUserID;
447 string secret = string.Empty, tmp = string.Empty;
448 if (Util.ParseUniversalUserIdentifier(uui, out localUserID, out tmp, out tmp, out tmp, out secret))
449 {
450 FriendInfo[] friendInfos = m_FriendsService.GetFriends(localUserID);
451 foreach (FriendInfo finfo in friendInfos)
452 {
453 if (finfo.Friend.StartsWith(foreignUserID.ToString()) && finfo.Friend.EndsWith(secret) &&
454 (finfo.TheirFlags & (int)FriendRights.CanSeeOnline) != 0 && (finfo.TheirFlags != -1))
455 {
456 // great!
457 usersToBeNotified.Add(localUserID.ToString());
458 }
459 }
460 }
461 }
462
463 // Now, let's find out their status
464 m_log.DebugFormat("[USER AGENT SERVICE]: GetOnlineFriends: user has {0} local friends with status rights", usersToBeNotified.Count);
465
466 // First, let's send notifications to local users who are online in the home grid
467 PresenceInfo[] friendSessions = m_PresenceService.GetAgents(usersToBeNotified.ToArray());
468 if (friendSessions != null && friendSessions.Length > 0)
469 {
470 foreach (PresenceInfo pi in friendSessions)
471 {
472 UUID presenceID;
473 if (UUID.TryParse(pi.UserID, out presenceID))
474 online.Add(presenceID);
475 }
476 }
477
478 return online;
479 }
480
481 public Dictionary<string, object> GetServerURLs(UUID userID)
482 {
483 if (m_UserAccountService == null)
484 {
485 m_log.WarnFormat("[USER AGENT SERVICE]: Unable to get server URLs because user account service is missing");
486 return new Dictionary<string, object>();
487 }
488 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero /*!!!*/, userID);
489 if (account != null)
490 return account.ServiceURLs;
491
492 return new Dictionary<string, object>();
493 }
494
495 public string LocateUser(UUID userID)
496 {
497 foreach (TravelingAgentInfo t in m_TravelingAgents.Values)
498 {
499 if (t == null)
500 {
501 m_log.ErrorFormat("[USER AGENT SERVICE]: Oops! Null TravelingAgentInfo. Please report this on mantis");
502 continue;
503 }
504 if (t.UserID == userID && !m_GridName.Equals(t.GridExternalName))
505 return t.GridExternalName;
506 }
507
508 return string.Empty;
509 }
510
511 public string GetUUI(UUID userID, UUID targetUserID)
512 {
513 // Let's see if it's a local user
514 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, targetUserID);
515 if (account != null)
516 return targetUserID.ToString() + ";" + m_GridName + ";" + account.FirstName + " " + account.LastName ;
517
518 // Let's try the list of friends
519 FriendInfo[] friends = m_FriendsService.GetFriends(userID);
520 if (friends != null && friends.Length > 0)
521 {
522 foreach (FriendInfo f in friends)
523 if (f.Friend.StartsWith(targetUserID.ToString()))
524 {
525 // Let's remove the secret
526 UUID id; string tmp = string.Empty, secret = string.Empty;
527 if (Util.ParseUniversalUserIdentifier(f.Friend, out id, out tmp, out tmp, out tmp, out secret))
528 return f.Friend.Replace(secret, "0");
529 }
530 }
531
532 return string.Empty;
533 }
534 }
535
536 class TravelingAgentInfo
537 {
538 public UUID UserID;
539 public string GridExternalName = string.Empty;
540 public string ServiceToken = string.Empty;
541 public string ClientIPAddress = string.Empty; // as seen from this user agent service
542 public string MyIpAddress = string.Empty; // the user agent service's external IP, as seen from the next gatekeeper
543 }
544
545}
diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs
index 3be6815..80494f1 100644
--- a/OpenSim/Services/Interfaces/IAssetService.cs
+++ b/OpenSim/Services/Interfaces/IAssetService.cs
@@ -48,10 +48,15 @@ namespace OpenSim.Services.Interfaces
48 /// <returns></returns> 48 /// <returns></returns>
49 AssetMetadata GetMetadata(string id); 49 AssetMetadata GetMetadata(string id);
50 50
51 /// <summary>
52 /// Get an asset's data, ignoring the metadata.
53 /// </summary>
54 /// <param name="id"></param>
55 /// <returns>null if there is no such asset</returns>
51 byte[] GetData(string id); 56 byte[] GetData(string id);
52 57
53 /// <summary> 58 /// <summary>
54 /// Synchronously fetches an asset from the local cache only 59 /// Synchronously fetches an asset from the local cache only.
55 /// </summary> 60 /// </summary>
56 /// <param name="id">Asset ID</param> 61 /// <param name="id">Asset ID</param>
57 /// <returns>The fetched asset, or null if it did not exist in the local cache</returns> 62 /// <returns>The fetched asset, or null if it did not exist in the local cache</returns>
@@ -70,7 +75,9 @@ namespace OpenSim.Services.Interfaces
70 /// <summary> 75 /// <summary>
71 /// Creates a new asset 76 /// Creates a new asset
72 /// </summary> 77 /// </summary>
73 /// Returns a random ID if none is passed into it 78 /// <remarks>
79 /// Returns a random ID if none is passed via the asset argument.
80 /// </remarks>
74 /// <param name="asset"></param> 81 /// <param name="asset"></param>
75 /// <returns></returns> 82 /// <returns></returns>
76 string Store(AssetBase asset); 83 string Store(AssetBase asset);
@@ -78,7 +85,9 @@ namespace OpenSim.Services.Interfaces
78 /// <summary> 85 /// <summary>
79 /// Update an asset's content 86 /// Update an asset's content
80 /// </summary> 87 /// </summary>
88 /// <remarks>
81 /// Attachments and bare scripts need this!! 89 /// Attachments and bare scripts need this!!
90 /// </remarks>
82 /// <param name="id"> </param> 91 /// <param name="id"> </param>
83 /// <param name="data"></param> 92 /// <param name="data"></param>
84 /// <returns></returns> 93 /// <returns></returns>
diff --git a/OpenSim/Services/Interfaces/IAttachmentsService.cs b/OpenSim/Services/Interfaces/IAttachmentsService.cs
new file mode 100644
index 0000000..bdde369
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IAttachmentsService.cs
@@ -0,0 +1,17 @@
1////////////////////////////////////////////////////////////////
2//
3// (c) 2009, 2010 Careminster Limited and Melanie Thielker
4//
5// All rights reserved
6//
7using System;
8using Nini.Config;
9
10namespace OpenSim.Services.Interfaces
11{
12 public interface IAttachmentsService
13 {
14 string Get(string id);
15 void Store(string id, string data);
16 }
17}
diff --git a/OpenSim/Services/Interfaces/IAuthenticationService.cs b/OpenSim/Services/Interfaces/IAuthenticationService.cs
index 9225773..cee8bc0 100644
--- a/OpenSim/Services/Interfaces/IAuthenticationService.cs
+++ b/OpenSim/Services/Interfaces/IAuthenticationService.cs
@@ -26,10 +26,32 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using OpenMetaverse; 30using OpenMetaverse;
30 31
31namespace OpenSim.Services.Interfaces 32namespace OpenSim.Services.Interfaces
32{ 33{
34 public class AuthInfo
35 {
36 public UUID PrincipalID { get; set; }
37 public string AccountType { get; set; }
38 public string PasswordHash { get; set; }
39 public string PasswordSalt { get; set; }
40 public string WebLoginKey { get; set; }
41
42 public Dictionary<string, object> ToKeyValuePairs()
43 {
44 Dictionary<string, object> result = new Dictionary<string, object>();
45 result["PrincipalID"] = PrincipalID;
46 result["AccountType"] = AccountType;
47 result["PasswordHash"] = PasswordHash;
48 result["PasswordSalt"] = PasswordSalt;
49 result["WebLoginKey"] = WebLoginKey;
50
51 return result;
52 }
53 }
54
33 // Generic Authentication service used for identifying 55 // Generic Authentication service used for identifying
34 // and authenticating principals. 56 // and authenticating principals.
35 // Principals may be clients acting on users' behalf, 57 // Principals may be clients acting on users' behalf,
@@ -66,6 +88,21 @@ namespace OpenSim.Services.Interfaces
66 bool Release(UUID principalID, string token); 88 bool Release(UUID principalID, string token);
67 89
68 ////////////////////////////////////////////////////// 90 //////////////////////////////////////////////////////
91 // SetPassword for a principal
92 //
93 // This method exists for the service, but may or may not
94 // be served remotely. That is, the authentication
95 // handlers may not include one handler for this,
96 // because it's a bit risky. Such handlers require
97 // authentication/authorization.
98 //
99 bool SetPassword(UUID principalID, string passwd);
100
101 AuthInfo GetAuthInfo(UUID principalID);
102
103 bool SetAuthInfo(AuthInfo info);
104
105 //////////////////////////////////////////////////////
69 // Grid 106 // Grid
70 // 107 //
71 // We no longer need a shared secret between grid 108 // We no longer need a shared secret between grid
diff --git a/OpenSim/Services/Interfaces/IAuthorizationService.cs b/OpenSim/Services/Interfaces/IAuthorizationService.cs
index c5d577a..e5c68f6 100644
--- a/OpenSim/Services/Interfaces/IAuthorizationService.cs
+++ b/OpenSim/Services/Interfaces/IAuthorizationService.cs
@@ -34,14 +34,21 @@ namespace OpenSim.Services.Interfaces
34 34
35 public interface IAuthorizationService 35 public interface IAuthorizationService
36 { 36 {
37 ////////////////////////////////////////////////////// 37 /// <summary>
38 // Authorized 38 /// Check whether the user should be given access to the region.
39 // 39 /// </summary>
40 // This method returns a simple true false indicating 40 /// <remarks>
41 // whether or not a user has access to the region 41 /// We also supply user first name and last name for situations where the user does not have an account
42 // 42 /// on the region (e.g. they're a visitor via Hypergrid).
43 bool IsAuthorizedForRegion(string userID, string regionID, out string message); 43 /// </remarks>
44 44 /// <param name="userID"></param>
45 /// <param name="firstName">/param>
46 /// <param name="lastName"></param>
47 /// <param name="regionID"></param>
48 /// <param name="message"></param>
49 /// <returns></returns>
50 bool IsAuthorizedForRegion(
51 string userID, string firstName, string lastName, string regionID, out string message);
45 } 52 }
46 53
47 public class AuthorizationRequest 54 public class AuthorizationRequest
@@ -63,7 +70,8 @@ namespace OpenSim.Services.Interfaces
63 m_regionID = RegionID; 70 m_regionID = RegionID;
64 } 71 }
65 72
66 public AuthorizationRequest(string ID,string FirstName, string SurName, string Email, string RegionName, string RegionID) 73 public AuthorizationRequest(
74 string ID, string FirstName, string SurName, string Email, string RegionName, string RegionID)
67 { 75 {
68 m_userID = ID; 76 m_userID = ID;
69 m_firstname = FirstName; 77 m_firstname = FirstName;
@@ -108,9 +116,6 @@ namespace OpenSim.Services.Interfaces
108 get { return m_regionID; } 116 get { return m_regionID; }
109 set { m_regionID = value; } 117 set { m_regionID = value; }
110 } 118 }
111
112
113
114 } 119 }
115 120
116 public class AuthorizationResponse 121 public class AuthorizationResponse
@@ -126,7 +131,6 @@ namespace OpenSim.Services.Interfaces
126 { 131 {
127 m_isAuthorized = isAuthorized; 132 m_isAuthorized = isAuthorized;
128 m_message = message; 133 m_message = message;
129
130 } 134 }
131 135
132 public bool IsAuthorized 136 public bool IsAuthorized
@@ -141,4 +145,4 @@ namespace OpenSim.Services.Interfaces
141 set { m_message = value; } 145 set { m_message = value; }
142 } 146 }
143 } 147 }
144} 148} \ No newline at end of file
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
new file mode 100644
index 0000000..cda7113
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -0,0 +1,342 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31
32using OpenSim.Framework;
33
34using OpenMetaverse;
35
36namespace OpenSim.Services.Interfaces
37{
38 public interface IAvatarService
39 {
40 /// <summary>
41 /// Called by the login service
42 /// </summary>
43 /// <param name="userID"></param>
44 /// <returns></returns>
45 AvatarAppearance GetAppearance(UUID userID);
46
47 /// <summary>
48 /// Called by everyone who can change the avatar data (so, regions)
49 /// </summary>
50 /// <param name="userID"></param>
51 /// <param name="appearance"></param>
52 /// <returns></returns>
53 bool SetAppearance(UUID userID, AvatarAppearance appearance);
54
55 /// <summary>
56 /// Called by the login service
57 /// </summary>
58 /// <param name="userID"></param>
59 /// <returns></returns>
60 AvatarData GetAvatar(UUID userID);
61
62 /// <summary>
63 /// Called by everyone who can change the avatar data (so, regions)
64 /// </summary>
65 /// <param name="userID"></param>
66 /// <param name="avatar"></param>
67 /// <returns></returns>
68 bool SetAvatar(UUID userID, AvatarData avatar);
69
70 /// <summary>
71 /// Not sure if it's needed
72 /// </summary>
73 /// <param name="userID"></param>
74 /// <returns></returns>
75 bool ResetAvatar(UUID userID);
76
77 /// <summary>
78 /// These methods raison d'etre:
79 /// No need to send the entire avatar data (SetAvatar) for changing attachments
80 /// </summary>
81 /// <param name="userID"></param>
82 /// <param name="attach"></param>
83 /// <returns></returns>
84 bool SetItems(UUID userID, string[] names, string[] values);
85 bool RemoveItems(UUID userID, string[] names);
86 }
87
88 /// <summary>
89 /// Each region/client that uses avatars will have a data structure
90 /// of this type representing the avatars.
91 /// </summary>
92 public class AvatarData
93 {
94 // This pretty much determines which name/value pairs will be
95 // present below. The name/value pair describe a part of
96 // the avatar. For SL avatars, these would be "shape", "texture1",
97 // etc. For other avatars, they might be "mesh", "skin", etc.
98 // The value portion is a URL that is expected to resolve to an
99 // asset of the type required by the handler for that field.
100 // It is required that regions can access these URLs. Allowing
101 // direct access by a viewer is not required, and, if provided,
102 // may be read-only. A "naked" UUID can be used to refer to an
103 // asset int he current region's asset service, which is not
104 // portable, but allows legacy appearance to continue to
105 // function. Closed, LL-based grids will never need URLs here.
106
107 public int AvatarType;
108 public Dictionary<string,string> Data;
109
110 public AvatarData()
111 {
112 }
113
114 public AvatarData(Dictionary<string, object> kvp)
115 {
116 Data = new Dictionary<string, string>();
117
118 if (kvp.ContainsKey("AvatarType"))
119 Int32.TryParse(kvp["AvatarType"].ToString(), out AvatarType);
120
121 foreach (KeyValuePair<string, object> _kvp in kvp)
122 {
123 if (_kvp.Value != null)
124 Data[_kvp.Key] = _kvp.Value.ToString();
125 }
126 }
127
128 /// <summary>
129 /// </summary>
130 /// <returns></returns>
131 public Dictionary<string, object> ToKeyValuePairs()
132 {
133 Dictionary<string, object> result = new Dictionary<string, object>();
134
135 result["AvatarType"] = AvatarType.ToString();
136 foreach (KeyValuePair<string, string> _kvp in Data)
137 {
138 if (_kvp.Value != null)
139 result[_kvp.Key] = _kvp.Value;
140 }
141 return result;
142 }
143
144 public AvatarData(AvatarAppearance appearance)
145 {
146 AvatarType = 1; // SL avatars
147 Data = new Dictionary<string, string>();
148
149 Data["Serial"] = appearance.Serial.ToString();
150 // Wearables
151 Data["AvatarHeight"] = appearance.AvatarHeight.ToString();
152
153 for (int i = 0 ; i < AvatarWearable.MAX_WEARABLES ; i++)
154 {
155 for (int j = 0 ; j < appearance.Wearables[i].Count ; j++)
156 {
157 string fieldName = String.Format("Wearable {0}:{1}", i, j);
158 Data[fieldName] = String.Format("{0}:{1}",
159 appearance.Wearables[i][j].ItemID.ToString(),
160 appearance.Wearables[i][j].AssetID.ToString());
161 }
162 }
163
164 // Visual Params
165 string[] vps = new string[AvatarAppearance.VISUALPARAM_COUNT];
166 byte[] binary = appearance.VisualParams;
167
168 for (int i = 0 ; i < AvatarAppearance.VISUALPARAM_COUNT ; i++)
169 {
170 vps[i] = binary[i].ToString();
171 }
172
173 Data["VisualParams"] = String.Join(",", vps);
174
175 // Attachments
176 List<AvatarAttachment> attachments = appearance.GetAttachments();
177 foreach (AvatarAttachment attach in attachments)
178 {
179 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
180 }
181 }
182
183 public AvatarAppearance ToAvatarAppearance()
184 {
185 AvatarAppearance appearance = new AvatarAppearance();
186
187 if (Data.Count == 0)
188 return appearance;
189
190 appearance.ClearWearables();
191 try
192 {
193 if (Data.ContainsKey("Serial"))
194 appearance.Serial = Int32.Parse(Data["Serial"]);
195
196 if (Data.ContainsKey("AvatarHeight"))
197 appearance.AvatarHeight = float.Parse(Data["AvatarHeight"]);
198
199 // Legacy Wearables
200 if (Data.ContainsKey("BodyItem"))
201 appearance.Wearables[AvatarWearable.BODY].Wear(
202 UUID.Parse(Data["BodyItem"]),
203 UUID.Parse(Data["BodyAsset"]));
204
205 if (Data.ContainsKey("SkinItem"))
206 appearance.Wearables[AvatarWearable.SKIN].Wear(
207 UUID.Parse(Data["SkinItem"]),
208 UUID.Parse(Data["SkinAsset"]));
209
210 if (Data.ContainsKey("HairItem"))
211 appearance.Wearables[AvatarWearable.HAIR].Wear(
212 UUID.Parse(Data["HairItem"]),
213 UUID.Parse(Data["HairAsset"]));
214
215 if (Data.ContainsKey("EyesItem"))
216 appearance.Wearables[AvatarWearable.EYES].Wear(
217 UUID.Parse(Data["EyesItem"]),
218 UUID.Parse(Data["EyesAsset"]));
219
220 if (Data.ContainsKey("ShirtItem"))
221 appearance.Wearables[AvatarWearable.SHIRT].Wear(
222 UUID.Parse(Data["ShirtItem"]),
223 UUID.Parse(Data["ShirtAsset"]));
224
225 if (Data.ContainsKey("PantsItem"))
226 appearance.Wearables[AvatarWearable.PANTS].Wear(
227 UUID.Parse(Data["PantsItem"]),
228 UUID.Parse(Data["PantsAsset"]));
229
230 if (Data.ContainsKey("ShoesItem"))
231 appearance.Wearables[AvatarWearable.SHOES].Wear(
232 UUID.Parse(Data["ShoesItem"]),
233 UUID.Parse(Data["ShoesAsset"]));
234
235 if (Data.ContainsKey("SocksItem"))
236 appearance.Wearables[AvatarWearable.SOCKS].Wear(
237 UUID.Parse(Data["SocksItem"]),
238 UUID.Parse(Data["SocksAsset"]));
239
240 if (Data.ContainsKey("JacketItem"))
241 appearance.Wearables[AvatarWearable.JACKET].Wear(
242 UUID.Parse(Data["JacketItem"]),
243 UUID.Parse(Data["JacketAsset"]));
244
245 if (Data.ContainsKey("GlovesItem"))
246 appearance.Wearables[AvatarWearable.GLOVES].Wear(
247 UUID.Parse(Data["GlovesItem"]),
248 UUID.Parse(Data["GlovesAsset"]));
249
250 if (Data.ContainsKey("UnderShirtItem"))
251 appearance.Wearables[AvatarWearable.UNDERSHIRT].Wear(
252 UUID.Parse(Data["UnderShirtItem"]),
253 UUID.Parse(Data["UnderShirtAsset"]));
254
255 if (Data.ContainsKey("UnderPantsItem"))
256 appearance.Wearables[AvatarWearable.UNDERPANTS].Wear(
257 UUID.Parse(Data["UnderPantsItem"]),
258 UUID.Parse(Data["UnderPantsAsset"]));
259
260 if (Data.ContainsKey("SkirtItem"))
261 appearance.Wearables[AvatarWearable.SKIRT].Wear(
262 UUID.Parse(Data["SkirtItem"]),
263 UUID.Parse(Data["SkirtAsset"]));
264
265 if (Data.ContainsKey("VisualParams"))
266 {
267 string[] vps = Data["VisualParams"].Split(new char[] {','});
268 byte[] binary = new byte[AvatarAppearance.VISUALPARAM_COUNT];
269
270 for (int i = 0 ; i < vps.Length && i < binary.Length ; i++)
271 binary[i] = (byte)Convert.ToInt32(vps[i]);
272
273 appearance.VisualParams = binary;
274 }
275
276 // New style wearables
277 foreach (KeyValuePair<string, string> _kvp in Data)
278 {
279 if (_kvp.Key.StartsWith("Wearable "))
280 {
281 string wearIndex = _kvp.Key.Substring(9);
282 string[] wearIndices = wearIndex.Split(new char[] {':'});
283 int index = Convert.ToInt32(wearIndices[0]);
284
285 string[] ids = _kvp.Value.Split(new char[] {':'});
286 UUID itemID = new UUID(ids[0]);
287 UUID assetID = new UUID(ids[1]);
288
289 appearance.Wearables[index].Add(itemID, assetID);
290 }
291 }
292
293 // Attachments
294 Dictionary<string, string> attchs = new Dictionary<string, string>();
295 foreach (KeyValuePair<string, string> _kvp in Data)
296 if (_kvp.Key.StartsWith("_ap_"))
297 attchs[_kvp.Key] = _kvp.Value;
298
299 foreach (KeyValuePair<string, string> _kvp in attchs)
300 {
301 string pointStr = _kvp.Key.Substring(4);
302 int point = 0;
303 if (!Int32.TryParse(pointStr, out point))
304 continue;
305
306 UUID uuid = UUID.Zero;
307 UUID.TryParse(_kvp.Value, out uuid);
308
309 appearance.SetAttachment(point, uuid, UUID.Zero);
310 }
311
312 if (appearance.Wearables[AvatarWearable.BODY].Count == 0)
313 appearance.Wearables[AvatarWearable.BODY].Wear(
314 AvatarWearable.DefaultWearables[
315 AvatarWearable.BODY][0]);
316
317 if (appearance.Wearables[AvatarWearable.SKIN].Count == 0)
318 appearance.Wearables[AvatarWearable.SKIN].Wear(
319 AvatarWearable.DefaultWearables[
320 AvatarWearable.SKIN][0]);
321
322 if (appearance.Wearables[AvatarWearable.HAIR].Count == 0)
323 appearance.Wearables[AvatarWearable.HAIR].Wear(
324 AvatarWearable.DefaultWearables[
325 AvatarWearable.HAIR][0]);
326
327 if (appearance.Wearables[AvatarWearable.EYES].Count == 0)
328 appearance.Wearables[AvatarWearable.EYES].Wear(
329 AvatarWearable.DefaultWearables[
330 AvatarWearable.EYES][0]);
331 }
332 catch
333 {
334 // We really should report something here, returning null
335 // will at least break the wrapper
336 return null;
337 }
338
339 return appearance;
340 }
341 }
342}
diff --git a/OpenSim/Services/Interfaces/IFreeswitchService.cs b/OpenSim/Services/Interfaces/IFreeswitchService.cs
index d1f635b..e7941d5 100644
--- a/OpenSim/Services/Interfaces/IFreeswitchService.cs
+++ b/OpenSim/Services/Interfaces/IFreeswitchService.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using System.Collections;
30 31
31namespace OpenSim.Services.Interfaces 32namespace OpenSim.Services.Interfaces
32{ 33{
33 public interface IFreeswitchService 34 public interface IFreeswitchService
34 { 35 {
35 // Place anything the connector eeds to access here! 36 Hashtable HandleDirectoryRequest(Hashtable requestBody);
37 Hashtable HandleDialplanRequest(Hashtable requestBody);
38 string GetJsonConfig();
36 } 39 }
37} 40}
diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs
new file mode 100644
index 0000000..1664f3b
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IFriendsService.cs
@@ -0,0 +1,82 @@
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 OpenMetaverse;
30using OpenSim.Framework;
31using System.Collections.Generic;
32
33namespace OpenSim.Services.Interfaces
34{
35 public class FriendInfo
36 {
37 public UUID PrincipalID;
38 public string Friend;
39 public int MyFlags;
40 public int TheirFlags;
41
42 public FriendInfo()
43 {
44 }
45
46 public FriendInfo(Dictionary<string, object> kvp)
47 {
48 PrincipalID = UUID.Zero;
49 if (kvp.ContainsKey("PrincipalID") && kvp["PrincipalID"] != null)
50 UUID.TryParse(kvp["PrincipalID"].ToString(), out PrincipalID);
51 Friend = string.Empty;
52 if (kvp.ContainsKey("Friend") && kvp["Friend"] != null)
53 Friend = kvp["Friend"].ToString();
54 MyFlags = 0;
55 if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null)
56 Int32.TryParse(kvp["MyFlags"].ToString(), out MyFlags);
57 TheirFlags = 0;
58 if (kvp.ContainsKey("TheirFlags") && kvp["TheirFlags"] != null)
59 Int32.TryParse(kvp["TheirFlags"].ToString(), out TheirFlags);
60 }
61
62 public Dictionary<string, object> ToKeyValuePairs()
63 {
64 Dictionary<string, object> result = new Dictionary<string, object>();
65 result["PrincipalID"] = PrincipalID.ToString();
66 result["Friend"] = Friend;
67 result["MyFlags"] = MyFlags.ToString();
68 result["TheirFlags"] = TheirFlags.ToString();
69
70 return result;
71 }
72 }
73
74 public interface IFriendsService
75 {
76 FriendInfo[] GetFriends(UUID PrincipalID);
77 FriendInfo[] GetFriends(string PrincipalID);
78 bool StoreFriend(string PrincipalID, string Friend, int flags);
79 bool Delete(UUID PrincipalID, string Friend);
80 bool Delete(string PrincipalID, string Friend);
81 }
82}
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index 5135f6d..2b0b947 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -71,6 +71,12 @@ namespace OpenSim.Services.Interfaces
71 /// <returns></returns> 71 /// <returns></returns>
72 GridRegion GetRegionByPosition(UUID scopeID, int x, int y); 72 GridRegion GetRegionByPosition(UUID scopeID, int x, int y);
73 73
74 /// <summary>
75 /// Get information about a region which exactly matches the name given.
76 /// </summary>
77 /// <param name="scopeID"></param>
78 /// <param name="regionName"></param>
79 /// <returns>Returns the region information if the name matched. Null otherwise.</returns>
74 GridRegion GetRegionByName(UUID scopeID, string regionName); 80 GridRegion GetRegionByName(UUID scopeID, string regionName);
75 81
76 /// <summary> 82 /// <summary>
@@ -90,11 +96,15 @@ namespace OpenSim.Services.Interfaces
90 96
91 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax); 97 List<GridRegion> GetRegionRange(UUID scopeID, int xmin, int xmax, int ymin, int ymax);
92 98
99 List<GridRegion> GetDefaultRegions(UUID scopeID);
100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
101 List<GridRegion> GetHyperlinks(UUID scopeID);
102
103 int GetRegionFlags(UUID scopeID, UUID regionID);
93 } 104 }
94 105
95 public class GridRegion 106 public class GridRegion
96 { 107 {
97
98 /// <summary> 108 /// <summary>
99 /// The port by which http communication occurs with the region 109 /// The port by which http communication occurs with the region
100 /// </summary> 110 /// </summary>
@@ -110,8 +120,20 @@ namespace OpenSim.Services.Interfaces
110 /// </summary> 120 /// </summary>
111 public string ServerURI 121 public string ServerURI
112 { 122 {
113 get { return m_serverURI; } 123 get {
114 set { m_serverURI = value; } 124 if ( m_serverURI != string.Empty ) {
125 return m_serverURI;
126 } else {
127 return "http://" + m_externalHostName + ":" + m_httpPort + "/";
128 }
129 }
130 set {
131 if ( value.EndsWith("/") ) {
132 m_serverURI = value;
133 } else {
134 m_serverURI = value + '/';
135 }
136 }
115 } 137 }
116 protected string m_serverURI; 138 protected string m_serverURI;
117 139
@@ -126,6 +148,19 @@ namespace OpenSim.Services.Interfaces
126 148
127 protected IPEndPoint m_internalEndPoint; 149 protected IPEndPoint m_internalEndPoint;
128 150
151 /// <summary>
152 /// The co-ordinate of this region.
153 /// </summary>
154 public int RegionCoordX { get { return RegionLocX / (int)Constants.RegionSize; } }
155
156 /// <summary>
157 /// The co-ordinate of this region
158 /// </summary>
159 public int RegionCoordY { get { return RegionLocY / (int)Constants.RegionSize; } }
160
161 /// <summary>
162 /// The location of this region in meters.
163 /// </summary>
129 public int RegionLocX 164 public int RegionLocX
130 { 165 {
131 get { return m_regionLocX; } 166 get { return m_regionLocX; }
@@ -133,6 +168,9 @@ namespace OpenSim.Services.Interfaces
133 } 168 }
134 protected int m_regionLocX; 169 protected int m_regionLocX;
135 170
171 /// <summary>
172 /// The location of this region in meters.
173 /// </summary>
136 public int RegionLocY 174 public int RegionLocY
137 { 175 {
138 get { return m_regionLocY; } 176 get { return m_regionLocY; }
@@ -154,10 +192,12 @@ namespace OpenSim.Services.Interfaces
154 public UUID TerrainImage = UUID.Zero; 192 public UUID TerrainImage = UUID.Zero;
155 public byte Access; 193 public byte Access;
156 public int Maturity; 194 public int Maturity;
157 public string RegionSecret; 195 public string RegionSecret = string.Empty;
196 public string Token = string.Empty;
158 197
159 public GridRegion() 198 public GridRegion()
160 { 199 {
200 m_serverURI = string.Empty;
161 } 201 }
162 202
163 public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) 203 public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri)
@@ -200,12 +240,6 @@ namespace OpenSim.Services.Interfaces
200 Maturity = ConvertFrom.RegionSettings.Maturity; 240 Maturity = ConvertFrom.RegionSettings.Maturity;
201 RegionSecret = ConvertFrom.regionSecret; 241 RegionSecret = ConvertFrom.regionSecret;
202 EstateOwner = ConvertFrom.EstateSettings.EstateOwner; 242 EstateOwner = ConvertFrom.EstateSettings.EstateOwner;
203 if (EstateOwner == UUID.Zero)
204 {
205 EstateOwner = ConvertFrom.MasterAvatarAssignedUUID;
206 ConvertFrom.EstateSettings.EstateOwner = EstateOwner;
207 ConvertFrom.EstateSettings.Save();
208 }
209 } 243 }
210 244
211 public GridRegion(GridRegion ConvertFrom) 245 public GridRegion(GridRegion ConvertFrom)
@@ -225,6 +259,33 @@ namespace OpenSim.Services.Interfaces
225 EstateOwner = ConvertFrom.EstateOwner; 259 EstateOwner = ConvertFrom.EstateOwner;
226 } 260 }
227 261
262 # region Definition of equality
263
264 /// <summary>
265 /// Define equality as two regions having the same, non-zero UUID.
266 /// </summary>
267 public bool Equals(GridRegion region)
268 {
269 if ((object)region == null)
270 return false;
271 // Return true if the non-zero UUIDs are equal:
272 return (RegionID != UUID.Zero) && RegionID.Equals(region.RegionID);
273 }
274
275 public override bool Equals(Object obj)
276 {
277 if (obj == null)
278 return false;
279 return Equals(obj as GridRegion);
280 }
281
282 public override int GetHashCode()
283 {
284 return RegionID.GetHashCode() ^ TerrainImage.GetHashCode();
285 }
286
287 #endregion
288
228 /// <value> 289 /// <value>
229 /// This accessor can throw all the exceptions that Dns.GetHostAddresses can throw. 290 /// This accessor can throw all the exceptions that Dns.GetHostAddresses can throw.
230 /// 291 ///
@@ -260,15 +321,17 @@ namespace OpenSim.Services.Interfaces
260 } 321 }
261 catch (SocketException e) 322 catch (SocketException e)
262 { 323 {
263 throw new Exception( 324 /*throw new Exception(
264 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + 325 "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" +
265 e + "' attached to this exception", e); 326 e + "' attached to this exception", e);*/
327 // Don't throw a fatal exception here, instead, return Null and handle it in the caller.
328 // Reason is, on systems such as OSgrid it has occured that known hostnames stop
329 // resolving and thus make surrounding regions crash out with this exception.
330 return null;
266 } 331 }
267 332
268 return new IPEndPoint(ia, m_internalEndPoint.Port); 333 return new IPEndPoint(ia, m_internalEndPoint.Port);
269 } 334 }
270
271 set { m_externalHostName = value.ToString(); }
272 } 335 }
273 336
274 public string ExternalHostName 337 public string ExternalHostName
@@ -288,11 +351,6 @@ namespace OpenSim.Services.Interfaces
288 get { return Util.UIntsToLong((uint)RegionLocX, (uint)RegionLocY); } 351 get { return Util.UIntsToLong((uint)RegionLocX, (uint)RegionLocY); }
289 } 352 }
290 353
291 public int getInternalEndPointPort()
292 {
293 return m_internalEndPoint.Port;
294 }
295
296 public Dictionary<string, object> ToKeyValuePairs() 354 public Dictionary<string, object> ToKeyValuePairs()
297 { 355 {
298 Dictionary<string, object> kvp = new Dictionary<string, object>(); 356 Dictionary<string, object> kvp = new Dictionary<string, object>();
@@ -308,6 +366,7 @@ namespace OpenSim.Services.Interfaces
308 kvp["access"] = Access.ToString(); 366 kvp["access"] = Access.ToString();
309 kvp["regionSecret"] = RegionSecret; 367 kvp["regionSecret"] = RegionSecret;
310 kvp["owner_uuid"] = EstateOwner.ToString(); 368 kvp["owner_uuid"] = EstateOwner.ToString();
369 kvp["Token"] = Token.ToString();
311 // Maturity doesn't seem to exist in the DB 370 // Maturity doesn't seem to exist in the DB
312 return kvp; 371 return kvp;
313 } 372 }
@@ -326,6 +385,12 @@ namespace OpenSim.Services.Interfaces
326 if (kvp.ContainsKey("regionName")) 385 if (kvp.ContainsKey("regionName"))
327 RegionName = (string)kvp["regionName"]; 386 RegionName = (string)kvp["regionName"];
328 387
388 if (kvp.ContainsKey("access"))
389 {
390 byte access = Convert.ToByte((string)kvp["access"]);
391 Maturity = (int)Util.ConvertAccessLevelToMaturity(access);
392 }
393
329 if (kvp.ContainsKey("serverIP")) 394 if (kvp.ContainsKey("serverIP"))
330 { 395 {
331 //int port = 0; 396 //int port = 0;
@@ -365,7 +430,8 @@ namespace OpenSim.Services.Interfaces
365 if (kvp.ContainsKey("owner_uuid")) 430 if (kvp.ContainsKey("owner_uuid"))
366 EstateOwner = new UUID(kvp["owner_uuid"].ToString()); 431 EstateOwner = new UUID(kvp["owner_uuid"].ToString());
367 432
433 if (kvp.ContainsKey("Token"))
434 Token = kvp["Token"].ToString();
368 } 435 }
369 } 436 }
370
371} 437}
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
new file mode 100644
index 0000000..6613ae7
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -0,0 +1,135 @@
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 OpenMetaverse;
31
32namespace OpenSim.Services.Interfaces
33{
34 /// <summary>
35 /// Records user information specific to a grid but which is not part of a user's account.
36 /// </summary>
37 public class GridUserInfo
38 {
39 public string UserID;
40
41 public UUID HomeRegionID;
42 public Vector3 HomePosition;
43 public Vector3 HomeLookAt;
44
45 public UUID LastRegionID;
46 public Vector3 LastPosition;
47 public Vector3 LastLookAt;
48
49 public bool Online;
50 public DateTime Login;
51 public DateTime Logout;
52
53 public GridUserInfo() {}
54
55 public GridUserInfo(Dictionary<string, object> kvp)
56 {
57 if (kvp.ContainsKey("UserID"))
58 UserID = kvp["UserID"].ToString();
59
60 if (kvp.ContainsKey("HomeRegionID"))
61 UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID);
62 if (kvp.ContainsKey("HomePosition"))
63 Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition);
64 if (kvp.ContainsKey("HomeLookAt"))
65 Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt);
66
67 if (kvp.ContainsKey("LastRegionID"))
68 UUID.TryParse(kvp["LastRegionID"].ToString(), out LastRegionID);
69 if (kvp.ContainsKey("LastPosition"))
70 Vector3.TryParse(kvp["LastPosition"].ToString(), out LastPosition);
71 if (kvp.ContainsKey("LastLookAt"))
72 Vector3.TryParse(kvp["LastLookAt"].ToString(), out LastLookAt);
73
74 if (kvp.ContainsKey("Login"))
75 DateTime.TryParse(kvp["Login"].ToString(), out Login);
76 if (kvp.ContainsKey("Logout"))
77 DateTime.TryParse(kvp["Logout"].ToString(), out Logout);
78 if (kvp.ContainsKey("Online"))
79 Boolean.TryParse(kvp["Online"].ToString(), out Online);
80
81 }
82
83 public Dictionary<string, object> ToKeyValuePairs()
84 {
85 Dictionary<string, object> result = new Dictionary<string, object>();
86 result["UserID"] = UserID;
87
88 result["HomeRegionID"] = HomeRegionID.ToString();
89 result["HomePosition"] = HomePosition.ToString();
90 result["HomeLookAt"] = HomeLookAt.ToString();
91
92 result["LastRegionID"] = LastRegionID.ToString();
93 result["LastPosition"] = LastPosition.ToString();
94 result["LastLookAt"] = LastLookAt.ToString();
95
96 result["Online"] = Online.ToString();
97 result["Login"] = Login.ToString();
98 result["Logout"] = Logout.ToString();
99
100
101 return result;
102 }
103 }
104
105 public interface IGridUserService
106 {
107 GridUserInfo LoggedIn(string userID);
108
109 /// <summary>
110 /// Informs the grid that a user is logged out and to remove any session data for them
111 /// </summary>
112 /// <param name="userID">Ignore if your connector does not use userID for logouts</param>
113 /// <param name="sessionID">Ignore if your connector does not use sessionID for logouts</param>
114 /// <param name="regionID">RegionID where the user was last located</param>
115 /// <param name="lastPosition">Last region-relative position of the user</param>
116 /// <param name="lastLookAt">Last normalized look direction for the user</param>
117 /// <returns>True if the logout request was successfully processed, otherwise false</returns>
118 bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt);
119
120 bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt);
121
122 /// <summary>
123 /// Stores the last known user position at the grid level
124 /// </summary>
125 /// <param name="userID">Ignore if your connector does not use userID for position updates</param>
126 /// <param name="sessionID">Ignore if your connector does not use sessionID for position updates</param>
127 /// <param name="regionID">RegionID where the user is currently located</param>
128 /// <param name="lastPosition">Region-relative position</param>
129 /// <param name="lastLookAt">Normalized look direction</param>
130 /// <returns>True if the user's last position was successfully updated, otherwise false</returns>
131 bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt);
132
133 GridUserInfo GetGridUserInfo(string userID);
134 }
135} \ No newline at end of file
diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs
new file mode 100644
index 0000000..e86ec51
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IHypergridServices.cs
@@ -0,0 +1,87 @@
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.Net;
30using System.Collections.Generic;
31
32using OpenSim.Framework;
33using OpenMetaverse;
34
35namespace OpenSim.Services.Interfaces
36{
37 public interface IGatekeeperService
38 {
39 bool LinkRegion(string regionDescriptor, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason);
40 GridRegion GetHyperlinkRegion(UUID regionID);
41
42 bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason);
43
44 }
45
46 /// <summary>
47 /// HG1.5 only
48 /// </summary>
49 public interface IUserAgentService
50 {
51 // called by login service only
52 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, IPEndPoint clientIP, out string reason);
53 // called by simulators
54 bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason);
55 void LogoutAgent(UUID userID, UUID sessionID);
56 GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt);
57 Dictionary<string, object> GetServerURLs(UUID userID);
58
59 string LocateUser(UUID userID);
60 // Tries to get the universal user identifier for the targetUserId
61 // on behalf of the userID
62 string GetUUI(UUID userID, UUID targetUserID);
63
64 // Returns the local friends online
65 List<UUID> StatusNotification(List<string> friends, UUID userID, bool online);
66 //List<UUID> GetOnlineFriends(UUID userID, List<string> friends);
67
68 bool IsAgentComingHome(UUID sessionID, string thisGridExternalName);
69 bool VerifyAgent(UUID sessionID, string token);
70 bool VerifyClient(UUID sessionID, string reportedIP);
71 }
72
73 public interface IInstantMessage
74 {
75 bool IncomingInstantMessage(GridInstantMessage im);
76 bool OutgoingInstantMessage(GridInstantMessage im, string url, bool foreigner);
77 }
78 public interface IFriendsSimConnector
79 {
80 bool StatusNotify(UUID userID, UUID friendID, bool online);
81 }
82
83 public interface IInstantMessageSimConnector
84 {
85 bool SendInstantMessage(GridInstantMessage im);
86 }
87}
diff --git a/OpenSim/Services/Interfaces/IInventoryService.cs b/OpenSim/Services/Interfaces/IInventoryService.cs
index 1b78fb3..a8bfe47 100644
--- a/OpenSim/Services/Interfaces/IInventoryService.cs
+++ b/OpenSim/Services/Interfaces/IInventoryService.cs
@@ -141,8 +141,11 @@ namespace OpenSim.Services.Interfaces
141 /// <summary> 141 /// <summary>
142 /// Add a new item to the user's inventory 142 /// Add a new item to the user's inventory
143 /// </summary> 143 /// </summary>
144 /// <param name="item"></param> 144 /// <param name="item">
145 /// <returns>true if the item was successfully added</returns> 145 /// The item to be added. If item.FolderID == UUID.Zero then the item is added to the most suitable system
146 /// folder. If there is no suitable folder then the item is added to the user's root inventory folder.
147 /// </param>
148 /// <returns>true if the item was successfully added, false if it was not</returns>
146 bool AddItem(InventoryItemBase item); 149 bool AddItem(InventoryItemBase item);
147 150
148 /// <summary> 151 /// <summary>
@@ -166,7 +169,7 @@ namespace OpenSim.Services.Interfaces
166 /// Get an item, given by its UUID 169 /// Get an item, given by its UUID
167 /// </summary> 170 /// </summary>
168 /// <param name="item"></param> 171 /// <param name="item"></param>
169 /// <returns></returns> 172 /// <returns>null if no item was found, otherwise the found item</returns>
170 InventoryItemBase GetItem(InventoryItemBase item); 173 InventoryItemBase GetItem(InventoryItemBase item);
171 174
172 /// <summary> 175 /// <summary>
diff --git a/OpenSim/Services/Interfaces/ILandService.cs b/OpenSim/Services/Interfaces/ILandService.cs
index e2f1d1d..63d9a27 100644
--- a/OpenSim/Services/Interfaces/ILandService.cs
+++ b/OpenSim/Services/Interfaces/ILandService.cs
@@ -33,6 +33,6 @@ namespace OpenSim.Services.Interfaces
33{ 33{
34 public interface ILandService 34 public interface ILandService
35 { 35 {
36 LandData GetLandData(ulong regionHandle, uint x, uint y); 36 LandData GetLandData(UUID scopeID, ulong regionHandle, uint x, uint y, out byte regionAccess);
37 } 37 }
38} 38}
diff --git a/OpenSim/Services/Interfaces/IMapService.cs b/OpenSim/Services/Interfaces/ILibraryService.cs
index c70f484..861cf0e 100644
--- a/OpenSim/Services/Interfaces/IMapService.cs
+++ b/OpenSim/Services/Interfaces/ILibraryService.cs
@@ -25,14 +25,19 @@
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 OpenSim.Framework; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30
31using OpenSim.Framework;
30using OpenMetaverse; 32using OpenMetaverse;
31 33
32namespace OpenSim.Services.Interfaces 34namespace OpenSim.Services.Interfaces
33{ 35{
34 public interface IMapService 36 public interface ILibraryService
35 { 37 {
36 List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY); 38 InventoryFolderImpl LibraryRootFolder { get; }
39
40 Dictionary<UUID, InventoryFolderImpl> GetAllFolders();
37 } 41 }
42
38} 43}
diff --git a/OpenSim/Services/UserService/UserService.cs b/OpenSim/Services/Interfaces/ILoginService.cs
index e8b9fc3..ee9b0b1 100644
--- a/OpenSim/Services/UserService/UserService.cs
+++ b/OpenSim/Services/Interfaces/ILoginService.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -26,51 +26,31 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Collections;
30using Nini.Config;
31using OpenSim.Data;
32using OpenSim.Services.Interfaces;
33using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Net;
32
33using OpenMetaverse.StructuredData;
34using OpenMetaverse; 34using OpenMetaverse;
35 35
36namespace OpenSim.Services.UserAccountService 36namespace OpenSim.Services.Interfaces
37{ 37{
38 public class UserAccountService : UserAccountServiceBase, IUserAccountService 38 public abstract class LoginResponse
39 { 39 {
40 public UserAccountService(IConfigSource config) : base(config) 40 public abstract Hashtable ToHashtable();
41 { 41 public abstract OSD ToOSDMap();
42 } 42 }
43
44 public UserAccount GetUserAccount(UUID scopeID, string firstName,
45 string lastName)
46 {
47 return null;
48 }
49
50 public UserAccount GetUserAccount(UUID scopeID, UUID userID)
51 {
52 return null;
53 }
54 43
55 public bool SetHomePosition(UserAccount data, UUID regionID, UUID regionSecret) 44 public abstract class FailedLoginResponse : LoginResponse
56 { 45 {
57 return false; 46 }
58 }
59 47
60 public bool SetUserAccount(UserAccount data, UUID principalID, string token) 48 public interface ILoginService
61 { 49 {
62 return false; 50 LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID,
63 } 51 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP);
52 Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP);
53 }
64 54
65 public bool CreateUserAccount(UserAccount data, UUID principalID, string token)
66 {
67 return false;
68 }
69 55
70 public List<UserAccount> GetUserAccount(UUID scopeID,
71 string query)
72 {
73 return null;
74 }
75 }
76} 56}
diff --git a/OpenSim/Services/Interfaces/IHyperlink.cs b/OpenSim/Services/Interfaces/IMapImageService.cs
index ed3ff23..a7b2cf1 100644
--- a/OpenSim/Services/Interfaces/IHyperlink.cs
+++ b/OpenSim/Services/Interfaces/IMapImageService.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -26,24 +26,15 @@
26 */ 26 */
27 27
28using OpenSim.Framework; 28using OpenSim.Framework;
29using GridRegion = OpenSim.Services.Interfaces.GridRegion; 29using System.Collections.Generic;
30
31using OpenMetaverse; 30using OpenMetaverse;
32 31
33namespace OpenSim.Services.Interfaces 32namespace OpenSim.Services.Interfaces
34{ 33{
35 public interface IHyperlinkService 34 public interface IMapImageService
36 { 35 {
37 GridRegion TryLinkRegion(IClientAPI client, string regionDescriptor); 36 //List<MapBlockData> GetMapBlocks(UUID scopeID, int minX, int minY, int maxX, int maxY);
38 GridRegion GetHyperlinkRegion(ulong handle); 37 bool AddMapTile(int x, int y, byte[] imageData, out string reason);
39 ulong FindRegionHandle(ulong handle); 38 byte[] GetMapTile(string fileName, out string format);
40
41 bool SendUserInformation(GridRegion region, AgentCircuitData aCircuit);
42 void AdjustUserInformation(AgentCircuitData aCircuit);
43
44 bool CheckUserAtEntry(UUID userID, UUID sessionID, out bool comingHome);
45 void AcceptUser(ForeignUserProfileData user, GridRegion home);
46
47 bool IsLocalUser(UUID userID);
48 } 39 }
49} 40}
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs
index aa1c5bf..8d583ff 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,40 @@ 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
40 public PresenceInfo()
41 {
42 }
43
44 public PresenceInfo(Dictionary<string, object> kvp)
45 {
46 if (kvp.ContainsKey("UserID"))
47 UserID = kvp["UserID"].ToString();
48 if (kvp.ContainsKey("RegionID"))
49 UUID.TryParse(kvp["RegionID"].ToString(), out RegionID);
50 }
51
52 public Dictionary<string, object> ToKeyValuePairs()
53 {
54 Dictionary<string, object> result = new Dictionary<string, object>();
55 result["UserID"] = UserID;
56 result["RegionID"] = RegionID.ToString();
57
58 return result;
59 }
39 } 60 }
40 61
41 public interface IPresenceService 62 public interface IPresenceService
42 { 63 {
43 bool Report(PresenceInfo presence); 64 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID);
65 bool LogoutAgent(UUID sessionID);
66 bool LogoutRegionAgents(UUID regionID);
67
68 bool ReportAgent(UUID sessionID, UUID regionID);
69
70 PresenceInfo GetAgent(UUID sessionID);
71 PresenceInfo[] GetAgents(string[] userIDs);
44 } 72 }
45} 73}
diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs
index a169ab7..ae6bd72 100644
--- a/OpenSim/Services/Interfaces/ISimulationService.cs
+++ b/OpenSim/Services/Interfaces/ISimulationService.cs
@@ -29,13 +29,25 @@ using System;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using OpenMetaverse; 30using OpenMetaverse;
31 31
32using GridRegion = OpenSim.Services.Interfaces.GridRegion;
33
32namespace OpenSim.Services.Interfaces 34namespace OpenSim.Services.Interfaces
33{ 35{
34 public interface ISimulationService 36 public interface ISimulationService
35 { 37 {
38 IScene GetScene(ulong regionHandle);
39 ISimulationService GetInnerService();
40
36 #region Agents 41 #region Agents
37 42
38 bool CreateAgent(ulong regionHandle, AgentCircuitData aCircuit, out string reason); 43 /// <summary>
44 /// Ask the simulator hosting the destination to create an agent on that region.
45 /// </summary>
46 /// <param name="destination"></param>
47 /// <param name="aCircuit"></param>
48 /// <param name="flags"></param>
49 /// <param name="reason">Reason message in the event of a failure.</param>
50 bool CreateAgent(GridRegion destination, AgentCircuitData aCircuit, uint flags, out string reason);
39 51
40 /// <summary> 52 /// <summary>
41 /// Full child agent update. 53 /// Full child agent update.
@@ -43,7 +55,7 @@ namespace OpenSim.Services.Interfaces
43 /// <param name="regionHandle"></param> 55 /// <param name="regionHandle"></param>
44 /// <param name="data"></param> 56 /// <param name="data"></param>
45 /// <returns></returns> 57 /// <returns></returns>
46 bool UpdateAgent(ulong regionHandle, AgentData data); 58 bool UpdateAgent(GridRegion destination, AgentData data);
47 59
48 /// <summary> 60 /// <summary>
49 /// Short child agent update, mostly for position. 61 /// Short child agent update, mostly for position.
@@ -51,9 +63,11 @@ namespace OpenSim.Services.Interfaces
51 /// <param name="regionHandle"></param> 63 /// <param name="regionHandle"></param>
52 /// <param name="data"></param> 64 /// <param name="data"></param>
53 /// <returns></returns> 65 /// <returns></returns>
54 bool UpdateAgent(ulong regionHandle, AgentPosition data); 66 bool UpdateAgent(GridRegion destination, AgentPosition data);
55 67
56 bool RetrieveAgent(ulong regionHandle, UUID id, out IAgentData agent); 68 bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent);
69
70 bool QueryAccess(GridRegion destination, UUID id, Vector3 position, out string version, out string reason);
57 71
58 /// <summary> 72 /// <summary>
59 /// Message from receiving region to departing region, telling it got contacted by the client. 73 /// Message from receiving region to departing region, telling it got contacted by the client.
@@ -63,7 +77,15 @@ namespace OpenSim.Services.Interfaces
63 /// <param name="id"></param> 77 /// <param name="id"></param>
64 /// <param name="uri"></param> 78 /// <param name="uri"></param>
65 /// <returns></returns> 79 /// <returns></returns>
66 bool ReleaseAgent(ulong regionHandle, UUID id, string uri); 80 bool ReleaseAgent(UUID originRegion, UUID id, string uri);
81
82 /// <summary>
83 /// Close child agent.
84 /// </summary>
85 /// <param name="regionHandle"></param>
86 /// <param name="id"></param>
87 /// <returns></returns>
88 bool CloseChildAgent(GridRegion destination, UUID id);
67 89
68 /// <summary> 90 /// <summary>
69 /// Close agent. 91 /// Close agent.
@@ -71,7 +93,7 @@ namespace OpenSim.Services.Interfaces
71 /// <param name="regionHandle"></param> 93 /// <param name="regionHandle"></param>
72 /// <param name="id"></param> 94 /// <param name="id"></param>
73 /// <returns></returns> 95 /// <returns></returns>
74 bool CloseAgent(ulong regionHandle, UUID id); 96 bool CloseAgent(GridRegion destination, UUID id);
75 97
76 #endregion Agents 98 #endregion Agents
77 99
@@ -84,7 +106,7 @@ namespace OpenSim.Services.Interfaces
84 /// <param name="sog"></param> 106 /// <param name="sog"></param>
85 /// <param name="isLocalCall"></param> 107 /// <param name="isLocalCall"></param>
86 /// <returns></returns> 108 /// <returns></returns>
87 bool CreateObject(ulong regionHandle, ISceneObject sog, bool isLocalCall); 109 bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall);
88 110
89 /// <summary> 111 /// <summary>
90 /// Create an object from the user's inventory in the destination region. 112 /// Create an object from the user's inventory in the destination region.
@@ -94,15 +116,9 @@ namespace OpenSim.Services.Interfaces
94 /// <param name="userID"></param> 116 /// <param name="userID"></param>
95 /// <param name="itemID"></param> 117 /// <param name="itemID"></param>
96 /// <returns></returns> 118 /// <returns></returns>
97 bool CreateObject(ulong regionHandle, UUID userID, UUID itemID); 119 bool CreateObject(GridRegion destination, UUID userID, UUID itemID);
98 120
99 #endregion Objects 121 #endregion Objects
100 122
101 #region Regions
102
103 bool HelloNeighbour(ulong regionHandle, RegionInfo thisRegion);
104
105 #endregion Regions
106
107 } 123 }
108} 124}
diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs
new file mode 100644
index 0000000..d0fddee
--- /dev/null
+++ b/OpenSim/Services/Interfaces/IUserAccountService.cs
@@ -0,0 +1,194 @@
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 OpenMetaverse;
31
32using OpenSim.Framework;
33
34namespace OpenSim.Services.Interfaces
35{
36 public class UserAccount
37 {
38 public UserAccount()
39 {
40 }
41
42 public UserAccount(UUID principalID)
43 {
44 PrincipalID = principalID;
45 }
46
47 /// <summary>
48 /// Initializes a new instance of the <see cref="OpenSim.Services.Interfaces.UserAccount"/> class.
49 /// This method is used by externasl/3rd party management applications that need us to create a
50 /// random UUID for the new user.
51 /// </summary>
52 /// <param name='scopeID'>
53 /// Scope I.
54 /// </param>
55 /// <param name='firstName'>
56 /// First name.
57 /// </param>
58 /// <param name='lastName'>
59 /// Last name.
60 /// </param>
61 /// <param name='email'>
62 /// Email.
63 /// </param>
64 public UserAccount(UUID scopeID, string firstName, string lastName, string email)
65 {
66 PrincipalID = UUID.Random();
67 ScopeID = scopeID;
68 FirstName = firstName;
69 LastName = lastName;
70 Email = email;
71 ServiceURLs = new Dictionary<string, object>();
72 Created = Util.UnixTimeSinceEpoch();
73 }
74
75 public UserAccount(UUID scopeID, UUID principalID, string firstName, string lastName, string email)
76 {
77 PrincipalID = principalID;
78 ScopeID = scopeID;
79 FirstName = firstName;
80 LastName = lastName;
81 Email = email;
82 ServiceURLs = new Dictionary<string, object>();
83 Created = Util.UnixTimeSinceEpoch();
84 }
85
86 public string FirstName;
87 public string LastName;
88 public string Email;
89 public UUID PrincipalID;
90 public UUID ScopeID;
91 public int UserLevel;
92 public int UserFlags;
93 public string UserTitle;
94 public string UserCountry;
95
96 public Dictionary<string, object> ServiceURLs;
97
98 public int Created;
99
100 public string Name
101 {
102 get { return FirstName + " " + LastName; }
103 }
104
105 public UserAccount(Dictionary<string, object> kvp)
106 {
107 if (kvp.ContainsKey("FirstName"))
108 FirstName = kvp["FirstName"].ToString();
109 if (kvp.ContainsKey("LastName"))
110 LastName = kvp["LastName"].ToString();
111 if (kvp.ContainsKey("Email"))
112 Email = kvp["Email"].ToString();
113 if (kvp.ContainsKey("PrincipalID"))
114 UUID.TryParse(kvp["PrincipalID"].ToString(), out PrincipalID);
115 if (kvp.ContainsKey("ScopeID"))
116 UUID.TryParse(kvp["ScopeID"].ToString(), out ScopeID);
117 if (kvp.ContainsKey("UserLevel"))
118 UserLevel = Convert.ToInt32(kvp["UserLevel"].ToString());
119 if (kvp.ContainsKey("UserFlags"))
120 UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString());
121 if (kvp.ContainsKey("UserTitle"))
122 UserTitle = kvp["UserTitle"].ToString();
123 if (kvp.ContainsKey("UserCountry"))
124 UserCountry = kvp["UserCountry"].ToString();
125
126 if (kvp.ContainsKey("Created"))
127 Created = Convert.ToInt32(kvp["Created"].ToString());
128 if (kvp.ContainsKey("ServiceURLs") && kvp["ServiceURLs"] != null)
129 {
130 ServiceURLs = new Dictionary<string, object>();
131 string str = kvp["ServiceURLs"].ToString();
132 if (str != string.Empty)
133 {
134 string[] parts = str.Split(new char[] { ';' });
135// Dictionary<string, object> dic = new Dictionary<string, object>();
136 foreach (string s in parts)
137 {
138 string[] parts2 = s.Split(new char[] { '*' });
139 if (parts2.Length == 2)
140 ServiceURLs[parts2[0]] = parts2[1];
141 }
142 }
143 }
144 }
145
146 public Dictionary<string, object> ToKeyValuePairs()
147 {
148 Dictionary<string, object> result = new Dictionary<string, object>();
149 result["FirstName"] = FirstName;
150 result["LastName"] = LastName;
151 result["Email"] = Email;
152 result["PrincipalID"] = PrincipalID.ToString();
153 result["ScopeID"] = ScopeID.ToString();
154 result["Created"] = Created.ToString();
155 result["UserLevel"] = UserLevel.ToString();
156 result["UserFlags"] = UserFlags.ToString();
157 result["UserTitle"] = UserTitle;
158 result["UserCountry"] = UserCountry;
159
160 string str = string.Empty;
161 foreach (KeyValuePair<string, object> kvp in ServiceURLs)
162 {
163 str += kvp.Key + "*" + (kvp.Value == null ? "" : kvp.Value) + ";";
164 }
165 result["ServiceURLs"] = str;
166
167 return result;
168 }
169
170 };
171
172 public interface IUserAccountService
173 {
174 UserAccount GetUserAccount(UUID scopeID, UUID userID);
175 UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName);
176 UserAccount GetUserAccount(UUID scopeID, string Email);
177
178 /// <summary>
179 /// Returns the list of avatars that matches both the search criterion and the scope ID passed
180 /// </summary>
181 /// <param name="scopeID"></param>
182 /// <param name="query"></param>
183 /// <returns></returns>
184 List<UserAccount> GetUserAccounts(UUID scopeID, string query);
185 List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where);
186
187 /// <summary>
188 /// Store the data given, wich replaces the stored data, therefore must be complete.
189 /// </summary>
190 /// <param name="data"></param>
191 /// <returns></returns>
192 bool StoreUserAccount(UserAccount data);
193 }
194}
diff --git a/OpenSim/Services/Interfaces/IUserService.cs b/OpenSim/Services/Interfaces/IUserService.cs
deleted file mode 100644
index 92bd8ef..0000000
--- a/OpenSim/Services/Interfaces/IUserService.cs
+++ /dev/null
@@ -1,103 +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 System.Collections.Generic;
29using OpenMetaverse;
30
31namespace OpenSim.Services.Interfaces
32{
33 public class UserAccount
34 {
35 public UserAccount()
36 {
37 }
38
39 public UserAccount(UUID userID, UUID homeRegionID, float homePositionX,
40 float homePositionY, float homePositionZ, float homeLookAtX,
41 float homeLookAtY, float homeLookAtZ)
42 {
43 UserID = userID;
44 HomeRegionID = homeRegionID;
45 HomePositionX = homePositionX;
46 HomePositionY = homePositionY;
47 HomePositionZ = homePositionZ;
48 HomeLookAtX = homeLookAtX;
49 HomeLookAtY = homeLookAtY;
50 HomeLookAtZ = homeLookAtZ;
51 }
52
53 public string FirstName;
54 public string LastName;
55 public UUID UserID;
56 public UUID ScopeID;
57
58 // For informational purposes only!
59 //
60 public string HomeRegionName;
61
62 public UUID HomeRegionID;
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
70 // These are here because they
71 // concern the account rather than
72 // the profile. They just happen to
73 // be used in the Linden profile as well
74 //
75 public int GodLevel;
76 public int UserFlags;
77 public string AccountType;
78
79 };
80
81 public interface IUserAccountService
82 {
83 UserAccount GetUserAccount(UUID scopeID, UUID userID);
84 UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName);
85 // Returns the list of avatars that matches both the search
86 // criterion and the scope ID passed
87 //
88 List<UserAccount> GetUserAccount(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
96 // Update all updatable fields
97 //
98 bool SetUserAccount(UserAccount data, UUID PrincipalID, string token);
99
100 // Creates a user data record
101 bool CreateUserAccount(UserAccount data, UUID PrincipalID, string token);
102 }
103}
diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs
index 95007f1..73dd06a 100644
--- a/OpenSim/Services/InventoryService/InventoryService.cs
+++ b/OpenSim/Services/InventoryService/InventoryService.cs
@@ -66,6 +66,7 @@ namespace OpenSim.Services.InventoryService
66 // Agent has no inventory structure yet. 66 // Agent has no inventory structure yet.
67 if (null == rootFolder) 67 if (null == rootFolder)
68 { 68 {
69 m_log.DebugFormat("[INVENTORY SERVICE]: No root folder");
69 return null; 70 return null;
70 } 71 }
71 72
@@ -108,7 +109,7 @@ namespace OpenSim.Services.InventoryService
108 { 109 {
109 existingRootFolder = GetRootFolder(user); 110 existingRootFolder = GetRootFolder(user);
110 } 111 }
111 catch (Exception e) 112 catch /*(Exception e)*/
112 { 113 {
113 // Munch the exception, it has already been reported 114 // Munch the exception, it has already been reported
114 // 115 //
@@ -267,6 +268,8 @@ namespace OpenSim.Services.InventoryService
267 268
268 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) 269 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
269 { 270 {
271// m_log.DebugFormat("[INVENTORY SERVICE]: Looking for folder type {0} for user {1}", type, userID);
272
270 InventoryFolderBase root = m_Database.getUserRootFolder(userID); 273 InventoryFolderBase root = m_Database.getUserRootFolder(userID);
271 if (root != null) 274 if (root != null)
272 { 275 {
@@ -275,7 +278,12 @@ namespace OpenSim.Services.InventoryService
275 foreach (InventoryFolderBase folder in folders) 278 foreach (InventoryFolderBase folder in folders)
276 { 279 {
277 if (folder.Type == (short)type) 280 if (folder.Type == (short)type)
281 {
282// m_log.DebugFormat(
283// "[INVENTORY SERVICE]: Found folder {0} type {1}", folder.Name, (AssetType)folder.Type);
284
278 return folder; 285 return folder;
286 }
279 } 287 }
280 } 288 }
281 289
@@ -298,6 +306,7 @@ namespace OpenSim.Services.InventoryService
298 if ((folder.Type != (short)AssetType.Folder) && (folder.Type != (short)AssetType.Unknown)) 306 if ((folder.Type != (short)AssetType.Folder) && (folder.Type != (short)AssetType.Unknown))
299 folders[(AssetType)folder.Type] = folder; 307 folders[(AssetType)folder.Type] = folder;
300 } 308 }
309 m_log.DebugFormat("[INVENTORY SERVICE]: Got {0} system folders for {1}", folders.Count, userID);
301 return folders; 310 return folders;
302 } 311 }
303 } 312 }
@@ -331,6 +340,9 @@ namespace OpenSim.Services.InventoryService
331 List<InventoryItemBase> itemsList = new List<InventoryItemBase>(); 340 List<InventoryItemBase> itemsList = new List<InventoryItemBase>();
332 341
333 itemsList.AddRange(m_Database.getInventoryInFolder(folderID)); 342 itemsList.AddRange(m_Database.getInventoryInFolder(folderID));
343
344// m_log.DebugFormat(
345// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID);
334 346
335 return itemsList; 347 return itemsList;
336 } 348 }
@@ -376,8 +388,9 @@ namespace OpenSim.Services.InventoryService
376 // See IInventoryServices 388 // See IInventoryServices
377 public virtual bool AddItem(InventoryItemBase item) 389 public virtual bool AddItem(InventoryItemBase item)
378 { 390 {
379 m_log.DebugFormat( 391// m_log.DebugFormat(
380 "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2}", item.Name, item.ID, item.Folder); 392// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}",
393// item.Name, item.ID, item.Folder, item.Owner);
381 394
382 m_Database.addInventoryItem(item); 395 m_Database.addInventoryItem(item);
383 396
diff --git a/OpenSim/Services/InventoryService/LibraryService.cs b/OpenSim/Services/InventoryService/LibraryService.cs
new file mode 100644
index 0000000..f90895b
--- /dev/null
+++ b/OpenSim/Services/InventoryService/LibraryService.cs
@@ -0,0 +1,284 @@
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.Xml;
33
34using OpenSim.Framework;
35using OpenSim.Services.Base;
36using OpenSim.Services.Interfaces;
37
38using log4net;
39using Nini.Config;
40using OpenMetaverse;
41
42namespace OpenSim.Services.InventoryService
43{
44 /// <summary>
45 /// Basically a hack to give us a Inventory library while we don't have a inventory server
46 /// once the server is fully implemented then should read the data from that
47 /// </summary>
48 public class LibraryService : ServiceBase, ILibraryService
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 private InventoryFolderImpl m_LibraryRootFolder;
53
54 public InventoryFolderImpl LibraryRootFolder
55 {
56 get { return m_LibraryRootFolder; }
57 }
58
59 private UUID libOwner = new UUID("11111111-1111-0000-0000-000100bba000");
60
61 /// <summary>
62 /// Holds the root library folder and all its descendents. This is really only used during inventory
63 /// setup so that we don't have to repeatedly search the tree of library folders.
64 /// </summary>
65 protected Dictionary<UUID, InventoryFolderImpl> libraryFolders
66 = new Dictionary<UUID, InventoryFolderImpl>();
67
68 public LibraryService(IConfigSource config)
69 : base(config)
70 {
71 string pLibrariesLocation = Path.Combine("inventory", "Libraries.xml");
72 string pLibName = "OpenSim Library";
73
74 IConfig libConfig = config.Configs["LibraryService"];
75 if (libConfig != null)
76 {
77 pLibrariesLocation = libConfig.GetString("DefaultLibrary", pLibrariesLocation);
78 pLibName = libConfig.GetString("LibraryName", pLibName);
79 }
80
81 m_log.Debug("[LIBRARY]: Starting library service...");
82
83 m_LibraryRootFolder = new InventoryFolderImpl();
84 m_LibraryRootFolder.Owner = libOwner;
85 m_LibraryRootFolder.ID = new UUID("00000112-000f-0000-0000-000100bba000");
86 m_LibraryRootFolder.Name = pLibName;
87 m_LibraryRootFolder.ParentID = UUID.Zero;
88 m_LibraryRootFolder.Type = (short)8;
89 m_LibraryRootFolder.Version = (ushort)1;
90
91 libraryFolders.Add(m_LibraryRootFolder.ID, m_LibraryRootFolder);
92
93 LoadLibraries(pLibrariesLocation);
94 }
95
96 public InventoryItemBase CreateItem(UUID inventoryID, UUID assetID, string name, string description,
97 int assetType, int invType, UUID parentFolderID)
98 {
99 InventoryItemBase item = new InventoryItemBase();
100 item.Owner = libOwner;
101 item.CreatorId = libOwner.ToString();
102 item.ID = inventoryID;
103 item.AssetID = assetID;
104 item.Description = description;
105 item.Name = name;
106 item.AssetType = assetType;
107 item.InvType = invType;
108 item.Folder = parentFolderID;
109 item.BasePermissions = 0x7FFFFFFF;
110 item.EveryOnePermissions = 0x7FFFFFFF;
111 item.CurrentPermissions = 0x7FFFFFFF;
112 item.NextPermissions = 0x7FFFFFFF;
113 return item;
114 }
115
116 /// <summary>
117 /// Use the asset set information at path to load assets
118 /// </summary>
119 /// <param name="path"></param>
120 /// <param name="assets"></param>
121 protected void LoadLibraries(string librariesControlPath)
122 {
123 m_log.InfoFormat("[LIBRARY INVENTORY]: Loading library control file {0}", librariesControlPath);
124 LoadFromFile(librariesControlPath, "Libraries control", ReadLibraryFromConfig);
125 }
126
127 /// <summary>
128 /// Read a library set from config
129 /// </summary>
130 /// <param name="config"></param>
131 protected void ReadLibraryFromConfig(IConfig config, string path)
132 {
133 string basePath = Path.GetDirectoryName(path);
134 string foldersPath
135 = Path.Combine(
136 basePath, config.GetString("foldersFile", String.Empty));
137
138 LoadFromFile(foldersPath, "Library folders", ReadFolderFromConfig);
139
140 string itemsPath
141 = Path.Combine(
142 basePath, config.GetString("itemsFile", String.Empty));
143
144 LoadFromFile(itemsPath, "Library items", ReadItemFromConfig);
145 }
146
147 /// <summary>
148 /// Read a library inventory folder from a loaded configuration
149 /// </summary>
150 /// <param name="source"></param>
151 private void ReadFolderFromConfig(IConfig config, string path)
152 {
153 InventoryFolderImpl folderInfo = new InventoryFolderImpl();
154
155 folderInfo.ID = new UUID(config.GetString("folderID", m_LibraryRootFolder.ID.ToString()));
156 folderInfo.Name = config.GetString("name", "unknown");
157 folderInfo.ParentID = new UUID(config.GetString("parentFolderID", m_LibraryRootFolder.ID.ToString()));
158 folderInfo.Type = (short)config.GetInt("type", 8);
159
160 folderInfo.Owner = libOwner;
161 folderInfo.Version = 1;
162
163 if (libraryFolders.ContainsKey(folderInfo.ParentID))
164 {
165 InventoryFolderImpl parentFolder = libraryFolders[folderInfo.ParentID];
166
167 libraryFolders.Add(folderInfo.ID, folderInfo);
168 parentFolder.AddChildFolder(folderInfo);
169
170// m_log.InfoFormat("[LIBRARY INVENTORY]: Adding folder {0} ({1})", folderInfo.name, folderInfo.folderID);
171 }
172 else
173 {
174 m_log.WarnFormat(
175 "[LIBRARY INVENTORY]: Couldn't add folder {0} ({1}) since parent folder with ID {2} does not exist!",
176 folderInfo.Name, folderInfo.ID, folderInfo.ParentID);
177 }
178 }
179
180 /// <summary>
181 /// Read a library inventory item metadata from a loaded configuration
182 /// </summary>
183 /// <param name="source"></param>
184 private void ReadItemFromConfig(IConfig config, string path)
185 {
186 InventoryItemBase item = new InventoryItemBase();
187 item.Owner = libOwner;
188 item.CreatorId = libOwner.ToString();
189 item.ID = new UUID(config.GetString("inventoryID", m_LibraryRootFolder.ID.ToString()));
190 item.AssetID = new UUID(config.GetString("assetID", item.ID.ToString()));
191 item.Folder = new UUID(config.GetString("folderID", m_LibraryRootFolder.ID.ToString()));
192 item.Name = config.GetString("name", String.Empty);
193 item.Description = config.GetString("description", item.Name);
194 item.InvType = config.GetInt("inventoryType", 0);
195 item.AssetType = config.GetInt("assetType", item.InvType);
196 item.CurrentPermissions = (uint)config.GetLong("currentPermissions", (uint)PermissionMask.All);
197 item.NextPermissions = (uint)config.GetLong("nextPermissions", (uint)PermissionMask.All);
198 item.EveryOnePermissions
199 = (uint)config.GetLong("everyonePermissions", (uint)PermissionMask.All - (uint)PermissionMask.Modify);
200 item.BasePermissions = (uint)config.GetLong("basePermissions", (uint)PermissionMask.All);
201 item.Flags = (uint)config.GetInt("flags", 0);
202
203 if (libraryFolders.ContainsKey(item.Folder))
204 {
205 InventoryFolderImpl parentFolder = libraryFolders[item.Folder];
206 try
207 {
208 parentFolder.Items.Add(item.ID, item);
209 }
210 catch (Exception)
211 {
212 m_log.WarnFormat("[LIBRARY INVENTORY] Item {1} [{0}] not added, duplicate item", item.ID, item.Name);
213 }
214 }
215 else
216 {
217 m_log.WarnFormat(
218 "[LIBRARY INVENTORY]: Couldn't add item {0} ({1}) since parent folder with ID {2} does not exist!",
219 item.Name, item.ID, item.Folder);
220 }
221 }
222
223 private delegate void ConfigAction(IConfig config, string path);
224
225 /// <summary>
226 /// Load the given configuration at a path and perform an action on each Config contained within it
227 /// </summary>
228 /// <param name="path"></param>
229 /// <param name="fileDescription"></param>
230 /// <param name="action"></param>
231 private static void LoadFromFile(string path, string fileDescription, ConfigAction action)
232 {
233 if (File.Exists(path))
234 {
235 try
236 {
237 XmlConfigSource source = new XmlConfigSource(path);
238
239 for (int i = 0; i < source.Configs.Count; i++)
240 {
241 action(source.Configs[i], path);
242 }
243 }
244 catch (XmlException e)
245 {
246 m_log.ErrorFormat("[LIBRARY INVENTORY]: Error loading {0} : {1}", path, e);
247 }
248 }
249 else
250 {
251 m_log.ErrorFormat("[LIBRARY INVENTORY]: {0} file {1} does not exist!", fileDescription, path);
252 }
253 }
254
255 /// <summary>
256 /// Looks like a simple getter, but is written like this for some consistency with the other Request
257 /// methods in the superclass
258 /// </summary>
259 /// <returns></returns>
260 public Dictionary<UUID, InventoryFolderImpl> GetAllFolders()
261 {
262 Dictionary<UUID, InventoryFolderImpl> fs = new Dictionary<UUID, InventoryFolderImpl>();
263 fs.Add(m_LibraryRootFolder.ID, m_LibraryRootFolder);
264 List<InventoryFolderImpl> fis = TraverseFolder(m_LibraryRootFolder);
265 foreach (InventoryFolderImpl f in fis)
266 {
267 fs.Add(f.ID, f);
268 }
269 //return libraryFolders;
270 return fs;
271 }
272
273 private List<InventoryFolderImpl> TraverseFolder(InventoryFolderImpl node)
274 {
275 List<InventoryFolderImpl> folders = node.RequestListOfFolderImpls();
276 List<InventoryFolderImpl> subs = new List<InventoryFolderImpl>();
277 foreach (InventoryFolderImpl f in folders)
278 subs.AddRange(TraverseFolder(f));
279
280 folders.AddRange(subs);
281 return folders;
282 }
283 }
284}
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 2c79c77..1648b51 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -40,11 +40,12 @@ namespace OpenSim.Services.InventoryService
40{ 40{
41 public class XInventoryService : ServiceBase, IInventoryService 41 public class XInventoryService : ServiceBase, IInventoryService
42 { 42 {
43 private static readonly ILog m_log = 43// private static readonly ILog m_log =
44 LogManager.GetLogger( 44// LogManager.GetLogger(
45 MethodBase.GetCurrentMethod().DeclaringType); 45// MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 protected IXInventoryData m_Database; 47 protected IXInventoryData m_Database;
48 protected bool m_AllowDelete = true;
48 49
49 public XInventoryService(IConfigSource config) : base(config) 50 public XInventoryService(IConfigSource config) : base(config)
50 { 51 {
@@ -60,6 +61,7 @@ namespace OpenSim.Services.InventoryService
60 { 61 {
61 dllName = authConfig.GetString("StorageProvider", dllName); 62 dllName = authConfig.GetString("StorageProvider", dllName);
62 connString = authConfig.GetString("ConnectionString", connString); 63 connString = authConfig.GetString("ConnectionString", connString);
64 m_AllowDelete = authConfig.GetBoolean("AllowDelete", true);
63 // realm = authConfig.GetString("Realm", realm); 65 // realm = authConfig.GetString("Realm", realm);
64 } 66 }
65 67
@@ -87,7 +89,7 @@ namespace OpenSim.Services.InventoryService
87 throw new Exception("Could not find a storage interface in the given module"); 89 throw new Exception("Could not find a storage interface in the given module");
88 } 90 }
89 91
90 public bool CreateUserInventory(UUID principalID) 92 public virtual bool CreateUserInventory(UUID principalID)
91 { 93 {
92 // This is braindeaad. We can't ever communicate that we fixed 94 // This is braindeaad. We can't ever communicate that we fixed
93 // an existing inventory. Well, just return root folder status, 95 // an existing inventory. Well, just return root folder status,
@@ -99,7 +101,7 @@ namespace OpenSim.Services.InventoryService
99 101
100 if (rootFolder == null) 102 if (rootFolder == null)
101 { 103 {
102 rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)AssetType.Folder, "My Inventory")); 104 rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)AssetType.RootFolder, "My Inventory"));
103 result = true; 105 result = true;
104 } 106 }
105 107
@@ -137,7 +139,7 @@ namespace OpenSim.Services.InventoryService
137 return result; 139 return result;
138 } 140 }
139 141
140 private XInventoryFolder CreateFolder(UUID principalID, UUID parentID, int type, string name) 142 protected XInventoryFolder CreateFolder(UUID principalID, UUID parentID, int type, string name)
141 { 143 {
142 XInventoryFolder newFolder = new XInventoryFolder(); 144 XInventoryFolder newFolder = new XInventoryFolder();
143 145
@@ -153,8 +155,10 @@ namespace OpenSim.Services.InventoryService
153 return newFolder; 155 return newFolder;
154 } 156 }
155 157
156 private XInventoryFolder[] GetSystemFolders(UUID principalID) 158 protected virtual XInventoryFolder[] GetSystemFolders(UUID principalID)
157 { 159 {
160// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting system folders for {0}", principalID);
161
158 XInventoryFolder[] allFolders = m_Database.GetFolders( 162 XInventoryFolder[] allFolders = m_Database.GetFolders(
159 new string[] { "agentID" }, 163 new string[] { "agentID" },
160 new string[] { principalID.ToString() }); 164 new string[] { principalID.ToString() });
@@ -168,10 +172,13 @@ namespace OpenSim.Services.InventoryService
168 return false; 172 return false;
169 }); 173 });
170 174
175// m_log.DebugFormat(
176// "[XINVENTORY SERVICE]: Found {0} system folders for {1}", sysFolders.Length, principalID);
177
171 return sysFolders; 178 return sysFolders;
172 } 179 }
173 180
174 public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID) 181 public virtual List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
175 { 182 {
176 XInventoryFolder[] allFolders = m_Database.GetFolders( 183 XInventoryFolder[] allFolders = m_Database.GetFolders(
177 new string[] { "agentID" }, 184 new string[] { "agentID" },
@@ -184,14 +191,14 @@ namespace OpenSim.Services.InventoryService
184 191
185 foreach (XInventoryFolder x in allFolders) 192 foreach (XInventoryFolder x in allFolders)
186 { 193 {
187 m_log.DebugFormat("[INVENTORY]: Adding folder {0} to skeleton", x.folderName); 194 //m_log.DebugFormat("[XINVENTORY SERVICE]: Adding folder {0} to skeleton", x.folderName);
188 folders.Add(ConvertToOpenSim(x)); 195 folders.Add(ConvertToOpenSim(x));
189 } 196 }
190 197
191 return folders; 198 return folders;
192 } 199 }
193 200
194 public InventoryFolderBase GetRootFolder(UUID principalID) 201 public virtual InventoryFolderBase GetRootFolder(UUID principalID)
195 { 202 {
196 XInventoryFolder[] folders = m_Database.GetFolders( 203 XInventoryFolder[] folders = m_Database.GetFolders(
197 new string[] { "agentID", "parentFolderID"}, 204 new string[] { "agentID", "parentFolderID"},
@@ -200,28 +207,44 @@ namespace OpenSim.Services.InventoryService
200 if (folders.Length == 0) 207 if (folders.Length == 0)
201 return null; 208 return null;
202 209
203 return ConvertToOpenSim(folders[0]); 210 XInventoryFolder root = null;
211 foreach (XInventoryFolder folder in folders)
212 if (folder.folderName == "My Inventory")
213 root = folder;
214 if (folders == null) // oops
215 root = folders[0];
216
217 return ConvertToOpenSim(root);
204 } 218 }
205 219
206 public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 220 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
207 { 221 {
222// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
223
208 XInventoryFolder[] folders = m_Database.GetFolders( 224 XInventoryFolder[] folders = m_Database.GetFolders(
209 new string[] { "agentID", "type"}, 225 new string[] { "agentID", "type"},
210 new string[] { principalID.ToString(), ((int)type).ToString() }); 226 new string[] { principalID.ToString(), ((int)type).ToString() });
211 227
212 if (folders.Length == 0) 228 if (folders.Length == 0)
229 {
230// m_log.WarnFormat("[XINVENTORY SERVICE]: Found no folder for type {0} for user {1}", type, principalID);
213 return null; 231 return null;
232 }
233
234// m_log.DebugFormat(
235// "[XINVENTORY SERVICE]: Found folder {0} {1} for type {2} for user {3}",
236// folders[0].folderName, folders[0].folderID, type, principalID);
214 237
215 return ConvertToOpenSim(folders[0]); 238 return ConvertToOpenSim(folders[0]);
216 } 239 }
217 240
218 public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) 241 public virtual InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
219 { 242 {
220 // This method doesn't receive a valud principal id from the 243 // This method doesn't receive a valud principal id from the
221 // connector. So we disregard the principal and look 244 // connector. So we disregard the principal and look
222 // by ID. 245 // by ID.
223 // 246 //
224 m_log.DebugFormat("[INVENTORY]: Fetch contents for folder {0}", folderID.ToString()); 247 //m_log.DebugFormat("[XINVENTORY SERVICE]: Fetch contents for folder {0}", folderID.ToString());
225 InventoryCollection inventory = new InventoryCollection(); 248 InventoryCollection inventory = new InventoryCollection();
226 inventory.UserID = principalID; 249 inventory.UserID = principalID;
227 inventory.Folders = new List<InventoryFolderBase>(); 250 inventory.Folders = new List<InventoryFolderBase>();
@@ -233,7 +256,7 @@ namespace OpenSim.Services.InventoryService
233 256
234 foreach (XInventoryFolder x in folders) 257 foreach (XInventoryFolder x in folders)
235 { 258 {
236 m_log.DebugFormat("[INVENTORY]: Adding folder {0} to response", x.folderName); 259 //m_log.DebugFormat("[XINVENTORY]: Adding folder {0} to response", x.folderName);
237 inventory.Folders.Add(ConvertToOpenSim(x)); 260 inventory.Folders.Add(ConvertToOpenSim(x));
238 } 261 }
239 262
@@ -243,22 +266,24 @@ namespace OpenSim.Services.InventoryService
243 266
244 foreach (XInventoryItem i in items) 267 foreach (XInventoryItem i in items)
245 { 268 {
246 m_log.DebugFormat("[INVENTORY]: Adding item {0} to response", i.inventoryName); 269 //m_log.DebugFormat("[XINVENTORY]: Adding item {0} to response", i.inventoryName);
247 inventory.Items.Add(ConvertToOpenSim(i)); 270 inventory.Items.Add(ConvertToOpenSim(i));
248 } 271 }
249 272
250 return inventory; 273 return inventory;
251 } 274 }
252 275
253 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID) 276 public virtual List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
254 { 277 {
278// m_log.DebugFormat("[XINVENTORY]: Fetch items for folder {0}", folderID);
279
255 // Since we probably don't get a valid principal here, either ... 280 // Since we probably don't get a valid principal here, either ...
256 // 281 //
257 List<InventoryItemBase> invItems = new List<InventoryItemBase>(); 282 List<InventoryItemBase> invItems = new List<InventoryItemBase>();
258 283
259 XInventoryItem[] items = m_Database.GetItems( 284 XInventoryItem[] items = m_Database.GetItems(
260 new string[] { "parentFolderID"}, 285 new string[] { "parentFolderID" },
261 new string[] { UUID.Zero.ToString() }); 286 new string[] { folderID.ToString() });
262 287
263 foreach (XInventoryItem i in items) 288 foreach (XInventoryItem i in items)
264 invItems.Add(ConvertToOpenSim(i)); 289 invItems.Add(ConvertToOpenSim(i));
@@ -266,18 +291,40 @@ namespace OpenSim.Services.InventoryService
266 return invItems; 291 return invItems;
267 } 292 }
268 293
269 public bool AddFolder(InventoryFolderBase folder) 294 public virtual bool AddFolder(InventoryFolderBase folder)
270 { 295 {
296 InventoryFolderBase check = GetFolder(folder);
297 if (check != null)
298 return false;
299
271 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 300 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
272 return m_Database.StoreFolder(xFolder); 301 return m_Database.StoreFolder(xFolder);
273 } 302 }
274 303
275 public bool UpdateFolder(InventoryFolderBase folder) 304 public virtual bool UpdateFolder(InventoryFolderBase folder)
276 { 305 {
277 return AddFolder(folder); 306 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
307 InventoryFolderBase check = GetFolder(folder);
308 if (check == null)
309 return AddFolder(folder);
310
311 if (check.Type != -1 || xFolder.type != -1)
312 {
313 if (xFolder.version > check.Version)
314 return false;
315 check.Version = (ushort)xFolder.version;
316 xFolder = ConvertFromOpenSim(check);
317 return m_Database.StoreFolder(xFolder);
318 }
319
320 if (xFolder.version < check.Version)
321 xFolder.version = check.Version;
322 xFolder.folderID = check.ID;
323
324 return m_Database.StoreFolder(xFolder);
278 } 325 }
279 326
280 public bool MoveFolder(InventoryFolderBase folder) 327 public virtual bool MoveFolder(InventoryFolderBase folder)
281 { 328 {
282 XInventoryFolder[] x = m_Database.GetFolders( 329 XInventoryFolder[] x = m_Database.GetFolders(
283 new string[] { "folderID" }, 330 new string[] { "folderID" },
@@ -293,12 +340,17 @@ namespace OpenSim.Services.InventoryService
293 340
294 // We don't check the principal's ID here 341 // We don't check the principal's ID here
295 // 342 //
296 public bool DeleteFolders(UUID principalID, List<UUID> folderIDs) 343 public virtual bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
297 { 344 {
345 if (!m_AllowDelete)
346 return false;
347
298 // Ignore principal ID, it's bogus at connector level 348 // Ignore principal ID, it's bogus at connector level
299 // 349 //
300 foreach (UUID id in folderIDs) 350 foreach (UUID id in folderIDs)
301 { 351 {
352 if (!ParentIsTrash(id))
353 continue;
302 InventoryFolderBase f = new InventoryFolderBase(); 354 InventoryFolderBase f = new InventoryFolderBase();
303 f.ID = id; 355 f.ID = id;
304 PurgeFolder(f); 356 PurgeFolder(f);
@@ -308,8 +360,14 @@ namespace OpenSim.Services.InventoryService
308 return true; 360 return true;
309 } 361 }
310 362
311 public bool PurgeFolder(InventoryFolderBase folder) 363 public virtual bool PurgeFolder(InventoryFolderBase folder)
312 { 364 {
365 if (!m_AllowDelete)
366 return false;
367
368 if (!ParentIsTrash(folder.ID))
369 return false;
370
313 XInventoryFolder[] subFolders = m_Database.GetFolders( 371 XInventoryFolder[] subFolders = m_Database.GetFolders(
314 new string[] { "parentFolderID" }, 372 new string[] { "parentFolderID" },
315 new string[] { folder.ID.ToString() }); 373 new string[] { folder.ID.ToString() });
@@ -325,17 +383,28 @@ namespace OpenSim.Services.InventoryService
325 return true; 383 return true;
326 } 384 }
327 385
328 public bool AddItem(InventoryItemBase item) 386 public virtual bool AddItem(InventoryItemBase item)
329 { 387 {
388// m_log.DebugFormat(
389// "[XINVENTORY SERVICE]: Adding item {0} to folder {1} for {2}", item.ID, item.Folder, item.Owner);
390
330 return m_Database.StoreItem(ConvertFromOpenSim(item)); 391 return m_Database.StoreItem(ConvertFromOpenSim(item));
331 } 392 }
332 393
333 public bool UpdateItem(InventoryItemBase item) 394 public virtual bool UpdateItem(InventoryItemBase item)
334 { 395 {
396// throw new Exception("urrgh");
397 if (!m_AllowDelete)
398 if (item.AssetType == (sbyte)AssetType.Link || item.AssetType == (sbyte)AssetType.LinkFolder)
399 return false;
400
401// m_log.InfoFormat(
402// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
403
335 return m_Database.StoreItem(ConvertFromOpenSim(item)); 404 return m_Database.StoreItem(ConvertFromOpenSim(item));
336 } 405 }
337 406
338 public bool MoveItems(UUID principalID, List<InventoryItemBase> items) 407 public virtual bool MoveItems(UUID principalID, List<InventoryItemBase> items)
339 { 408 {
340 // Principal is b0rked. *sigh* 409 // Principal is b0rked. *sigh*
341 // 410 //
@@ -347,17 +416,38 @@ namespace OpenSim.Services.InventoryService
347 return true; 416 return true;
348 } 417 }
349 418
350 public bool DeleteItems(UUID principalID, List<UUID> itemIDs) 419 public virtual bool DeleteItems(UUID principalID, List<UUID> itemIDs)
351 { 420 {
352 // Just use the ID... *facepalms* 421 if (!m_AllowDelete)
353 // 422 {
354 foreach (UUID id in itemIDs) 423 // We must still allow links and links to folders to be deleted, otherwise they will build up
355 m_Database.DeleteItems("inventoryID", id.ToString()); 424 // in the player's inventory until they can no longer log in. Deletions of links due to code bugs or
425 // similar is inconvenient but on a par with accidental movement of items. The original item is never
426 // touched.
427 foreach (UUID id in itemIDs)
428 {
429 if (!m_Database.DeleteItems(
430 new string[] { "inventoryID", "assetType" },
431 new string[] { id.ToString(), ((sbyte)AssetType.Link).ToString() }))
432 {
433 m_Database.DeleteItems(
434 new string[] { "inventoryID", "assetType" },
435 new string[] { id.ToString(), ((sbyte)AssetType.LinkFolder).ToString() });
436 }
437 }
438 }
439 else
440 {
441 // Just use the ID... *facepalms*
442 //
443 foreach (UUID id in itemIDs)
444 m_Database.DeleteItems("inventoryID", id.ToString());
445 }
356 446
357 return true; 447 return true;
358 } 448 }
359 449
360 public InventoryItemBase GetItem(InventoryItemBase item) 450 public virtual InventoryItemBase GetItem(InventoryItemBase item)
361 { 451 {
362 XInventoryItem[] items = m_Database.GetItems( 452 XInventoryItem[] items = m_Database.GetItems(
363 new string[] { "inventoryID" }, 453 new string[] { "inventoryID" },
@@ -369,7 +459,7 @@ namespace OpenSim.Services.InventoryService
369 return ConvertToOpenSim(items[0]); 459 return ConvertToOpenSim(items[0]);
370 } 460 }
371 461
372 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 462 public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
373 { 463 {
374 XInventoryFolder[] folders = m_Database.GetFolders( 464 XInventoryFolder[] folders = m_Database.GetFolders(
375 new string[] { "folderID"}, 465 new string[] { "folderID"},
@@ -381,12 +471,12 @@ namespace OpenSim.Services.InventoryService
381 return ConvertToOpenSim(folders[0]); 471 return ConvertToOpenSim(folders[0]);
382 } 472 }
383 473
384 public List<InventoryItemBase> GetActiveGestures(UUID principalID) 474 public virtual List<InventoryItemBase> GetActiveGestures(UUID principalID)
385 { 475 {
386 XInventoryItem[] items = m_Database.GetActiveGestures(principalID); 476 XInventoryItem[] items = m_Database.GetActiveGestures(principalID);
387 477
388 if (items.Length == 0) 478 if (items.Length == 0)
389 return null; 479 return new List<InventoryItemBase>();
390 480
391 List<InventoryItemBase> ret = new List<InventoryItemBase>(); 481 List<InventoryItemBase> ret = new List<InventoryItemBase>();
392 482
@@ -396,7 +486,7 @@ namespace OpenSim.Services.InventoryService
396 return ret; 486 return ret;
397 } 487 }
398 488
399 public int GetAssetPermissions(UUID principalID, UUID assetID) 489 public virtual int GetAssetPermissions(UUID principalID, UUID assetID)
400 { 490 {
401 return m_Database.GetAssetPermissions(principalID, assetID); 491 return m_Database.GetAssetPermissions(principalID, assetID);
402 } 492 }
@@ -421,7 +511,7 @@ namespace OpenSim.Services.InventoryService
421 511
422 // CM Helpers 512 // CM Helpers
423 // 513 //
424 private InventoryFolderBase ConvertToOpenSim(XInventoryFolder folder) 514 protected InventoryFolderBase ConvertToOpenSim(XInventoryFolder folder)
425 { 515 {
426 InventoryFolderBase newFolder = new InventoryFolderBase(); 516 InventoryFolderBase newFolder = new InventoryFolderBase();
427 517
@@ -435,7 +525,7 @@ namespace OpenSim.Services.InventoryService
435 return newFolder; 525 return newFolder;
436 } 526 }
437 527
438 private XInventoryFolder ConvertFromOpenSim(InventoryFolderBase folder) 528 protected XInventoryFolder ConvertFromOpenSim(InventoryFolderBase folder)
439 { 529 {
440 XInventoryFolder newFolder = new XInventoryFolder(); 530 XInventoryFolder newFolder = new XInventoryFolder();
441 531
@@ -449,7 +539,7 @@ namespace OpenSim.Services.InventoryService
449 return newFolder; 539 return newFolder;
450 } 540 }
451 541
452 private InventoryItemBase ConvertToOpenSim(XInventoryItem item) 542 protected InventoryItemBase ConvertToOpenSim(XInventoryItem item)
453 { 543 {
454 InventoryItemBase newItem = new InventoryItemBase(); 544 InventoryItemBase newItem = new InventoryItemBase();
455 545
@@ -460,7 +550,7 @@ namespace OpenSim.Services.InventoryService
460 newItem.ID = item.inventoryID; 550 newItem.ID = item.inventoryID;
461 newItem.InvType = item.invType; 551 newItem.InvType = item.invType;
462 newItem.Folder = item.parentFolderID; 552 newItem.Folder = item.parentFolderID;
463 newItem.CreatorId = item.creatorID.ToString(); 553 newItem.CreatorIdentification = item.creatorID;
464 newItem.Description = item.inventoryDescription; 554 newItem.Description = item.inventoryDescription;
465 newItem.NextPermissions = (uint)item.inventoryNextPermissions; 555 newItem.NextPermissions = (uint)item.inventoryNextPermissions;
466 newItem.CurrentPermissions = (uint)item.inventoryCurrentPermissions; 556 newItem.CurrentPermissions = (uint)item.inventoryCurrentPermissions;
@@ -468,7 +558,10 @@ namespace OpenSim.Services.InventoryService
468 newItem.EveryOnePermissions = (uint)item.inventoryEveryOnePermissions; 558 newItem.EveryOnePermissions = (uint)item.inventoryEveryOnePermissions;
469 newItem.GroupPermissions = (uint)item.inventoryGroupPermissions; 559 newItem.GroupPermissions = (uint)item.inventoryGroupPermissions;
470 newItem.GroupID = item.groupID; 560 newItem.GroupID = item.groupID;
471 newItem.GroupOwned = item.groupOwned; 561 if (item.groupOwned == 0)
562 newItem.GroupOwned = false;
563 else
564 newItem.GroupOwned = true;
472 newItem.SalePrice = item.salePrice; 565 newItem.SalePrice = item.salePrice;
473 newItem.SaleType = (byte)item.saleType; 566 newItem.SaleType = (byte)item.saleType;
474 newItem.Flags = (uint)item.flags; 567 newItem.Flags = (uint)item.flags;
@@ -477,7 +570,7 @@ namespace OpenSim.Services.InventoryService
477 return newItem; 570 return newItem;
478 } 571 }
479 572
480 private XInventoryItem ConvertFromOpenSim(InventoryItemBase item) 573 protected XInventoryItem ConvertFromOpenSim(InventoryItemBase item)
481 { 574 {
482 XInventoryItem newItem = new XInventoryItem(); 575 XInventoryItem newItem = new XInventoryItem();
483 576
@@ -488,7 +581,7 @@ namespace OpenSim.Services.InventoryService
488 newItem.inventoryID = item.ID; 581 newItem.inventoryID = item.ID;
489 newItem.invType = item.InvType; 582 newItem.invType = item.InvType;
490 newItem.parentFolderID = item.Folder; 583 newItem.parentFolderID = item.Folder;
491 newItem.creatorID = item.CreatorIdAsUuid; 584 newItem.creatorID = item.CreatorIdentification;
492 newItem.inventoryDescription = item.Description; 585 newItem.inventoryDescription = item.Description;
493 newItem.inventoryNextPermissions = (int)item.NextPermissions; 586 newItem.inventoryNextPermissions = (int)item.NextPermissions;
494 newItem.inventoryCurrentPermissions = (int)item.CurrentPermissions; 587 newItem.inventoryCurrentPermissions = (int)item.CurrentPermissions;
@@ -496,7 +589,10 @@ namespace OpenSim.Services.InventoryService
496 newItem.inventoryEveryOnePermissions = (int)item.EveryOnePermissions; 589 newItem.inventoryEveryOnePermissions = (int)item.EveryOnePermissions;
497 newItem.inventoryGroupPermissions = (int)item.GroupPermissions; 590 newItem.inventoryGroupPermissions = (int)item.GroupPermissions;
498 newItem.groupID = item.GroupID; 591 newItem.groupID = item.GroupID;
499 newItem.groupOwned = item.GroupOwned; 592 if (item.GroupOwned)
593 newItem.groupOwned = 1;
594 else
595 newItem.groupOwned = 0;
500 newItem.salePrice = item.SalePrice; 596 newItem.salePrice = item.SalePrice;
501 newItem.saleType = (int)item.SaleType; 597 newItem.saleType = (int)item.SaleType;
502 newItem.flags = (int)item.Flags; 598 newItem.flags = (int)item.Flags;
@@ -504,5 +600,32 @@ namespace OpenSim.Services.InventoryService
504 600
505 return newItem; 601 return newItem;
506 } 602 }
603
604 private bool ParentIsTrash(UUID folderID)
605 {
606 XInventoryFolder[] folder = m_Database.GetFolders(new string[] {"folderID"}, new string[] {folderID.ToString()});
607 if (folder.Length < 1)
608 return false;
609
610 if (folder[0].type == (int)AssetType.TrashFolder)
611 return true;
612
613 UUID parentFolder = folder[0].parentFolderID;
614
615 while (parentFolder != UUID.Zero)
616 {
617 XInventoryFolder[] parent = m_Database.GetFolders(new string[] {"folderID"}, new string[] {parentFolder.ToString()});
618 if (parent.Length < 1)
619 return false;
620
621 if (parent[0].type == (int)AssetType.TrashFolder)
622 return true;
623 if (parent[0].type == (int)AssetType.RootFolder)
624 return false;
625
626 parentFolder = parent[0].parentFolderID;
627 }
628 return false;
629 }
507 } 630 }
508} 631}
diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
new file mode 100644
index 0000000..de05f28
--- /dev/null
+++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs
@@ -0,0 +1,1026 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33
34using OpenSim.Framework;
35using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
38
39using log4net;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42using OSDArray = OpenMetaverse.StructuredData.OSDArray;
43using OSDMap = OpenMetaverse.StructuredData.OSDMap;
44
45namespace OpenSim.Services.LLLoginService
46{
47 public class LLFailedLoginResponse : OpenSim.Services.Interfaces.FailedLoginResponse
48 {
49 protected string m_key;
50 protected string m_value;
51 protected string m_login;
52
53 public static LLFailedLoginResponse UserProblem;
54 public static LLFailedLoginResponse GridProblem;
55 public static LLFailedLoginResponse InventoryProblem;
56 public static LLFailedLoginResponse DeadRegionProblem;
57 public static LLFailedLoginResponse LoginBlockedProblem;
58 public static LLFailedLoginResponse UnverifiedAccountProblem;
59 public static LLFailedLoginResponse AlreadyLoggedInProblem;
60 public static LLFailedLoginResponse InternalError;
61
62 static LLFailedLoginResponse()
63 {
64 UserProblem = new LLFailedLoginResponse("key",
65 "Could not authenticate your avatar. Please check your username and password, and check the grid if problems persist.",
66 "false");
67 GridProblem = new LLFailedLoginResponse("key",
68 "Error connecting to the desired location. Try connecting to another region.",
69 "false");
70 InventoryProblem = new LLFailedLoginResponse("key",
71 "The inventory service is not responding. Please notify your login region operator.",
72 "false");
73 DeadRegionProblem = new LLFailedLoginResponse("key",
74 "The region you are attempting to log into is not responding. Please select another region and try again.",
75 "false");
76 LoginBlockedProblem = new LLFailedLoginResponse("presence",
77 "Logins are currently restricted. Please try again later.",
78 "false");
79 UnverifiedAccountProblem = new LLFailedLoginResponse("presence",
80 "Your account has not yet been verified. Please check " +
81 "your email and click the provided link.",
82 "false");
83 AlreadyLoggedInProblem = new LLFailedLoginResponse("presence",
84 "You appear to be already logged in. " +
85 "If this is not the case please wait for your session to timeout. " +
86 "If this takes longer than a few minutes please contact the grid owner. " +
87 "Please wait 5 minutes if you are going to connect to a region nearby to the region you were at previously.",
88 "false");
89 InternalError = new LLFailedLoginResponse("Internal Error", "Error generating Login Response", "false");
90 }
91
92 public LLFailedLoginResponse(string key, string value, string login)
93 {
94 m_key = key;
95 m_value = value;
96 m_login = login;
97 }
98
99 public override Hashtable ToHashtable()
100 {
101 Hashtable loginError = new Hashtable();
102 loginError["reason"] = m_key;
103 loginError["message"] = m_value;
104 loginError["login"] = m_login;
105 return loginError;
106 }
107
108 public override OSD ToOSDMap()
109 {
110 OSDMap map = new OSDMap();
111
112 map["reason"] = OSD.FromString(m_key);
113 map["message"] = OSD.FromString(m_value);
114 map["login"] = OSD.FromString(m_login);
115
116 return map;
117 }
118 }
119
120 /// <summary>
121 /// A class to handle LL login response.
122 /// </summary>
123 public class LLLoginResponse : OpenSim.Services.Interfaces.LoginResponse
124 {
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 private static Hashtable globalTexturesHash;
127 // Global Textures
128 private static string sunTexture = "cce0f112-878f-4586-a2e2-a8f104bba271";
129 private static string cloudTexture = "dc4b9f0b-d008-45c6-96a4-01dd947ac621";
130 private static string moonTexture = "ec4b9f0b-d008-45c6-96a4-01dd947ac621";
131
132 private Hashtable loginFlagsHash;
133 private Hashtable uiConfigHash;
134
135 private ArrayList loginFlags;
136 private ArrayList globalTextures;
137 private ArrayList eventCategories;
138 private ArrayList uiConfig;
139 private ArrayList classifiedCategories;
140 private ArrayList inventoryRoot;
141 private ArrayList initialOutfit;
142 private ArrayList agentInventory;
143 private ArrayList inventoryLibraryOwner;
144 private ArrayList inventoryLibRoot;
145 private ArrayList inventoryLibrary;
146 private ArrayList activeGestures;
147
148 private UserInfo userProfile;
149
150 private UUID agentID;
151 private UUID sessionID;
152 private UUID secureSessionID;
153
154 // Login Flags
155 private string dst;
156 private string stipendSinceLogin;
157 private string gendered;
158 private string everLoggedIn;
159 private string login;
160 private uint simPort;
161 private uint simHttpPort;
162 private string simAddress;
163 private string agentAccess;
164 private string agentAccessMax;
165 private Int32 circuitCode;
166 private uint regionX;
167 private uint regionY;
168
169 // Login
170 private string firstname;
171 private string lastname;
172
173 // Web map
174 private string mapTileURL;
175
176 private string searchURL;
177
178 // Error Flags
179 private string errorReason;
180 private string errorMessage;
181
182 private string welcomeMessage;
183 private string startLocation;
184 private string allowFirstLife;
185 private string home;
186 private string seedCapability;
187 private string lookAt;
188
189 private BuddyList m_buddyList = null;
190
191 private string currency;
192
193 static LLLoginResponse()
194 {
195 // This is being set, but it's not used
196 // not sure why.
197 globalTexturesHash = new Hashtable();
198 globalTexturesHash["sun_texture_id"] = sunTexture;
199 globalTexturesHash["cloud_texture_id"] = cloudTexture;
200 globalTexturesHash["moon_texture_id"] = moonTexture;
201 }
202
203 public LLLoginResponse()
204 {
205 loginFlags = new ArrayList();
206 globalTextures = new ArrayList();
207 eventCategories = new ArrayList();
208 uiConfig = new ArrayList();
209 classifiedCategories = new ArrayList();
210
211 uiConfigHash = new Hashtable();
212
213 // defaultXmlRpcResponse = new XmlRpcResponse();
214 userProfile = new UserInfo();
215 inventoryRoot = new ArrayList();
216 initialOutfit = new ArrayList();
217 agentInventory = new ArrayList();
218 inventoryLibrary = new ArrayList();
219 inventoryLibraryOwner = new ArrayList();
220 activeGestures = new ArrayList();
221
222 SetDefaultValues();
223 }
224
225 public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo,
226 GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService,
227 string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message,
228 GridRegion home, IPEndPoint clientIP, string mapTileURL, string searchURL, string currency)
229 : this()
230 {
231 FillOutInventoryData(invSkel, libService);
232
233 FillOutActiveGestures(gestures);
234
235 CircuitCode = (int)aCircuit.circuitcode;
236 Lastname = account.LastName;
237 Firstname = account.FirstName;
238 AgentID = account.PrincipalID;
239 SessionID = aCircuit.SessionID;
240 SecureSessionID = aCircuit.SecureSessionID;
241 Message = message;
242 BuddList = ConvertFriendListItem(friendsList);
243 StartLocation = where;
244 MapTileURL = mapTileURL;
245 SearchURL = searchURL;
246 Currency = currency;
247
248 FillOutHomeData(pinfo, home);
249 LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z);
250
251 FillOutRegionData(destination);
252
253 FillOutSeedCap(aCircuit, destination, clientIP);
254
255 }
256
257 private void FillOutInventoryData(List<InventoryFolderBase> invSkel, ILibraryService libService)
258 {
259 InventoryData inventData = null;
260
261 try
262 {
263 inventData = GetInventorySkeleton(invSkel);
264 }
265 catch (Exception e)
266 {
267 m_log.WarnFormat(
268 "[LLLOGIN SERVICE]: Error processing inventory skeleton of agent {0} - {1}",
269 agentID, e);
270
271 // ignore and continue
272 }
273
274 if (inventData != null)
275 {
276 ArrayList AgentInventoryArray = inventData.InventoryArray;
277
278 Hashtable InventoryRootHash = new Hashtable();
279 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
280 InventoryRoot = new ArrayList();
281 InventoryRoot.Add(InventoryRootHash);
282 InventorySkeleton = AgentInventoryArray;
283 }
284
285 // Inventory Library Section
286 if (libService != null && libService.LibraryRootFolder != null)
287 {
288 Hashtable InventoryLibRootHash = new Hashtable();
289 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
290 InventoryLibRoot = new ArrayList();
291 InventoryLibRoot.Add(InventoryLibRootHash);
292
293 InventoryLibraryOwner = GetLibraryOwner(libService.LibraryRootFolder);
294 InventoryLibrary = GetInventoryLibrary(libService);
295 }
296 }
297
298 private void FillOutActiveGestures(List<InventoryItemBase> gestures)
299 {
300 ArrayList list = new ArrayList();
301 if (gestures != null)
302 {
303 foreach (InventoryItemBase gesture in gestures)
304 {
305 Hashtable item = new Hashtable();
306 item["item_id"] = gesture.ID.ToString();
307 item["asset_id"] = gesture.AssetID.ToString();
308 list.Add(item);
309 }
310 }
311 ActiveGestures = list;
312 }
313
314 private void FillOutHomeData(GridUserInfo pinfo, GridRegion home)
315 {
316 int x = 1000 * (int)Constants.RegionSize, y = 1000 * (int)Constants.RegionSize;
317 if (home != null)
318 {
319 x = home.RegionLocX;
320 y = home.RegionLocY;
321 }
322
323 Home = string.Format(
324 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
325 x,
326 y,
327 pinfo.HomePosition.X, pinfo.HomePosition.Y, pinfo.HomePosition.Z,
328 pinfo.HomeLookAt.X, pinfo.HomeLookAt.Y, pinfo.HomeLookAt.Z);
329
330 }
331
332 private void FillOutRegionData(GridRegion destination)
333 {
334 IPEndPoint endPoint = destination.ExternalEndPoint;
335 if (endPoint == null) return;
336 SimAddress = endPoint.Address.ToString();
337 SimPort = (uint)endPoint.Port;
338 RegionX = (uint)destination.RegionLocX;
339 RegionY = (uint)destination.RegionLocY;
340 }
341
342 private void FillOutSeedCap(AgentCircuitData aCircuit, GridRegion destination, IPEndPoint ipepClient)
343 {
344 SeedCapability = destination.ServerURI + CapsUtil.GetCapsSeedPath(aCircuit.CapsPath);
345 }
346
347 private void SetDefaultValues()
348 {
349 DST = TimeZone.CurrentTimeZone.IsDaylightSavingTime(DateTime.Now) ? "Y" : "N";
350 StipendSinceLogin = "N";
351 Gendered = "Y";
352 EverLoggedIn = "Y";
353 login = "false";
354 firstname = "Test";
355 lastname = "User";
356 agentAccess = "M";
357 agentAccessMax = "A";
358 startLocation = "last";
359 allowFirstLife = "Y";
360
361 ErrorMessage = "You have entered an invalid name/password combination. Check Caps/lock.";
362 ErrorReason = "key";
363 welcomeMessage = "Welcome to OpenSim!";
364 seedCapability = String.Empty;
365 home = "{'region_handle':[r" + (1000*Constants.RegionSize).ToString() + ",r" + (1000*Constants.RegionSize).ToString() + "], 'position':[r" +
366 userProfile.homepos.X.ToString() + ",r" + userProfile.homepos.Y.ToString() + ",r" +
367 userProfile.homepos.Z.ToString() + "], 'look_at':[r" + userProfile.homelookat.X.ToString() + ",r" +
368 userProfile.homelookat.Y.ToString() + ",r" + userProfile.homelookat.Z.ToString() + "]}";
369 lookAt = "[r0.99949799999999999756,r0.03166859999999999814,r0]";
370 RegionX = (uint) 255232;
371 RegionY = (uint) 254976;
372
373 // Classifieds;
374 AddClassifiedCategory((Int32) 1, "Shopping");
375 AddClassifiedCategory((Int32) 2, "Land Rental");
376 AddClassifiedCategory((Int32) 3, "Property Rental");
377 AddClassifiedCategory((Int32) 4, "Special Attraction");
378 AddClassifiedCategory((Int32) 5, "New Products");
379 AddClassifiedCategory((Int32) 6, "Employment");
380 AddClassifiedCategory((Int32) 7, "Wanted");
381 AddClassifiedCategory((Int32) 8, "Service");
382 AddClassifiedCategory((Int32) 9, "Personal");
383
384 SessionID = UUID.Random();
385 SecureSessionID = UUID.Random();
386 AgentID = UUID.Random();
387
388 Hashtable InitialOutfitHash = new Hashtable();
389 InitialOutfitHash["folder_name"] = "Nightclub Female";
390 InitialOutfitHash["gender"] = "female";
391 initialOutfit.Add(InitialOutfitHash);
392 mapTileURL = String.Empty;
393 searchURL = String.Empty;
394
395 currency = String.Empty;
396 }
397
398
399 public override Hashtable ToHashtable()
400 {
401 try
402 {
403 Hashtable responseData = new Hashtable();
404
405 loginFlagsHash = new Hashtable();
406 loginFlagsHash["daylight_savings"] = DST;
407 loginFlagsHash["stipend_since_login"] = StipendSinceLogin;
408 loginFlagsHash["gendered"] = Gendered;
409 loginFlagsHash["ever_logged_in"] = EverLoggedIn;
410 loginFlags.Add(loginFlagsHash);
411
412 responseData["first_name"] = Firstname;
413 responseData["last_name"] = Lastname;
414 responseData["agent_access"] = agentAccess;
415 responseData["agent_access_max"] = agentAccessMax;
416
417 globalTextures.Add(globalTexturesHash);
418 // this.eventCategories.Add(this.eventCategoriesHash);
419
420 AddToUIConfig("allow_first_life", allowFirstLife);
421 uiConfig.Add(uiConfigHash);
422
423 responseData["sim_port"] = (Int32) SimPort;
424 responseData["sim_ip"] = SimAddress;
425 responseData["http_port"] = (Int32)SimHttpPort;
426
427 responseData["agent_id"] = AgentID.ToString();
428 responseData["session_id"] = SessionID.ToString();
429 responseData["secure_session_id"] = SecureSessionID.ToString();
430 responseData["circuit_code"] = CircuitCode;
431 responseData["seconds_since_epoch"] = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
432 responseData["login-flags"] = loginFlags;
433 responseData["global-textures"] = globalTextures;
434 responseData["seed_capability"] = seedCapability;
435
436 responseData["event_categories"] = eventCategories;
437 responseData["event_notifications"] = new ArrayList(); // todo
438 responseData["classified_categories"] = classifiedCategories;
439 responseData["ui-config"] = uiConfig;
440
441 if (agentInventory != null)
442 {
443 responseData["inventory-skeleton"] = agentInventory;
444 responseData["inventory-root"] = inventoryRoot;
445 }
446 responseData["inventory-skel-lib"] = inventoryLibrary;
447 responseData["inventory-lib-root"] = inventoryLibRoot;
448 responseData["gestures"] = activeGestures;
449 responseData["inventory-lib-owner"] = inventoryLibraryOwner;
450 responseData["initial-outfit"] = initialOutfit;
451 responseData["start_location"] = startLocation;
452 responseData["seed_capability"] = seedCapability;
453 responseData["home"] = home;
454 responseData["look_at"] = lookAt;
455 responseData["message"] = welcomeMessage;
456 responseData["region_x"] = (Int32)(RegionX);
457 responseData["region_y"] = (Int32)(RegionY);
458
459 if (searchURL != String.Empty)
460 responseData["search"] = searchURL;
461
462 if (mapTileURL != String.Empty)
463 responseData["map-server-url"] = mapTileURL;
464
465 if (m_buddyList != null)
466 {
467 responseData["buddy-list"] = m_buddyList.ToArray();
468 }
469
470 if (currency != String.Empty)
471 {
472 // responseData["real_currency"] = currency;
473 responseData["currency"] = currency;
474 }
475
476 responseData["login"] = "true";
477
478 return responseData;
479 }
480 catch (Exception e)
481 {
482 m_log.Warn("[CLIENT]: LoginResponse: Error creating Hashtable Response: " + e.Message);
483
484 return LLFailedLoginResponse.InternalError.ToHashtable();
485 }
486 }
487
488 public override OSD ToOSDMap()
489 {
490 try
491 {
492 OSDMap map = new OSDMap();
493
494 map["first_name"] = OSD.FromString(Firstname);
495 map["last_name"] = OSD.FromString(Lastname);
496 map["agent_access"] = OSD.FromString(agentAccess);
497 map["agent_access_max"] = OSD.FromString(agentAccessMax);
498
499 map["sim_port"] = OSD.FromInteger(SimPort);
500 map["sim_ip"] = OSD.FromString(SimAddress);
501
502 map["agent_id"] = OSD.FromUUID(AgentID);
503 map["session_id"] = OSD.FromUUID(SessionID);
504 map["secure_session_id"] = OSD.FromUUID(SecureSessionID);
505 map["circuit_code"] = OSD.FromInteger(CircuitCode);
506 map["seconds_since_epoch"] = OSD.FromInteger((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
507
508 #region Login Flags
509
510 OSDMap loginFlagsLLSD = new OSDMap();
511 loginFlagsLLSD["daylight_savings"] = OSD.FromString(DST);
512 loginFlagsLLSD["stipend_since_login"] = OSD.FromString(StipendSinceLogin);
513 loginFlagsLLSD["gendered"] = OSD.FromString(Gendered);
514 loginFlagsLLSD["ever_logged_in"] = OSD.FromString(EverLoggedIn);
515 map["login-flags"] = WrapOSDMap(loginFlagsLLSD);
516
517 #endregion Login Flags
518
519 #region Global Textures
520
521 OSDMap globalTexturesLLSD = new OSDMap();
522 globalTexturesLLSD["sun_texture_id"] = OSD.FromString(SunTexture);
523 globalTexturesLLSD["cloud_texture_id"] = OSD.FromString(CloudTexture);
524 globalTexturesLLSD["moon_texture_id"] = OSD.FromString(MoonTexture);
525
526 map["global-textures"] = WrapOSDMap(globalTexturesLLSD);
527
528 #endregion Global Textures
529
530 map["seed_capability"] = OSD.FromString(seedCapability);
531
532 map["event_categories"] = ArrayListToOSDArray(eventCategories);
533 //map["event_notifications"] = new OSDArray(); // todo
534 map["classified_categories"] = ArrayListToOSDArray(classifiedCategories);
535
536 #region UI Config
537
538 OSDMap uiConfigLLSD = new OSDMap();
539 uiConfigLLSD["allow_first_life"] = OSD.FromString(allowFirstLife);
540 map["ui-config"] = WrapOSDMap(uiConfigLLSD);
541
542 #endregion UI Config
543
544 #region Inventory
545
546 map["inventory-skeleton"] = ArrayListToOSDArray(agentInventory);
547
548 map["inventory-skel-lib"] = ArrayListToOSDArray(inventoryLibrary);
549 map["inventory-root"] = ArrayListToOSDArray(inventoryRoot); ;
550 map["inventory-lib-root"] = ArrayListToOSDArray(inventoryLibRoot);
551 map["inventory-lib-owner"] = ArrayListToOSDArray(inventoryLibraryOwner);
552
553 #endregion Inventory
554
555 map["gestures"] = ArrayListToOSDArray(activeGestures);
556
557 map["initial-outfit"] = ArrayListToOSDArray(initialOutfit);
558 map["start_location"] = OSD.FromString(startLocation);
559
560 map["seed_capability"] = OSD.FromString(seedCapability);
561 map["home"] = OSD.FromString(home);
562 map["look_at"] = OSD.FromString(lookAt);
563 map["message"] = OSD.FromString(welcomeMessage);
564 map["region_x"] = OSD.FromInteger(RegionX);
565 map["region_y"] = OSD.FromInteger(RegionY);
566
567 if (mapTileURL != String.Empty)
568 map["map-server-url"] = OSD.FromString(mapTileURL);
569
570 if (searchURL != String.Empty)
571 map["search"] = OSD.FromString(searchURL);
572
573 if (m_buddyList != null)
574 {
575 map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray());
576 }
577
578 map["login"] = OSD.FromString("true");
579
580 return map;
581 }
582 catch (Exception e)
583 {
584 m_log.Warn("[CLIENT]: LoginResponse: Error creating LLSD Response: " + e.Message);
585
586 return LLFailedLoginResponse.InternalError.ToOSDMap();
587 }
588 }
589
590 public OSDArray ArrayListToOSDArray(ArrayList arrlst)
591 {
592 OSDArray llsdBack = new OSDArray();
593 foreach (Hashtable ht in arrlst)
594 {
595 OSDMap mp = new OSDMap();
596 foreach (DictionaryEntry deHt in ht)
597 {
598 mp.Add((string)deHt.Key, OSDString.FromObject(deHt.Value));
599 }
600 llsdBack.Add(mp);
601 }
602 return llsdBack;
603 }
604
605 private static OSDArray WrapOSDMap(OSDMap wrapMe)
606 {
607 OSDArray array = new OSDArray();
608 array.Add(wrapMe);
609 return array;
610 }
611
612 public void SetEventCategories(string category, string value)
613 {
614 // this.eventCategoriesHash[category] = value;
615 //TODO
616 }
617
618 public void AddToUIConfig(string itemName, string item)
619 {
620 uiConfigHash[itemName] = item;
621 }
622
623 public void AddClassifiedCategory(Int32 ID, string categoryName)
624 {
625 Hashtable hash = new Hashtable();
626 hash["category_name"] = categoryName;
627 hash["category_id"] = ID;
628 classifiedCategories.Add(hash);
629 // this.classifiedCategoriesHash.Clear();
630 }
631
632
633 private static LLLoginResponse.BuddyList ConvertFriendListItem(FriendInfo[] friendsList)
634 {
635 LLLoginResponse.BuddyList buddylistreturn = new LLLoginResponse.BuddyList();
636 foreach (FriendInfo finfo in friendsList)
637 {
638 if (finfo.TheirFlags == -1)
639 continue;
640 LLLoginResponse.BuddyList.BuddyInfo buddyitem = new LLLoginResponse.BuddyList.BuddyInfo(finfo.Friend);
641 // finfo.Friend may not be a simple uuid
642 UUID friendID = UUID.Zero;
643 if (UUID.TryParse(finfo.Friend, out friendID))
644 buddyitem.BuddyID = finfo.Friend;
645 else
646 {
647 string tmp;
648 if (Util.ParseUniversalUserIdentifier(finfo.Friend, out friendID, out tmp, out tmp, out tmp, out tmp))
649 buddyitem.BuddyID = friendID.ToString();
650 else
651 // junk entry
652 continue;
653 }
654 buddyitem.BuddyRightsHave = (int)finfo.TheirFlags;
655 buddyitem.BuddyRightsGiven = (int)finfo.MyFlags;
656 buddylistreturn.AddNewBuddy(buddyitem);
657 }
658 return buddylistreturn;
659 }
660
661 private InventoryData GetInventorySkeleton(List<InventoryFolderBase> folders)
662 {
663 UUID rootID = UUID.Zero;
664 ArrayList AgentInventoryArray = new ArrayList();
665 Hashtable TempHash;
666 foreach (InventoryFolderBase InvFolder in folders)
667 {
668 if (InvFolder.ParentID == UUID.Zero && InvFolder.Name == "My Inventory")
669 {
670 rootID = InvFolder.ID;
671 }
672 TempHash = new Hashtable();
673 TempHash["name"] = InvFolder.Name;
674 TempHash["parent_id"] = InvFolder.ParentID.ToString();
675 TempHash["version"] = (Int32)InvFolder.Version;
676 TempHash["type_default"] = (Int32)InvFolder.Type;
677 TempHash["folder_id"] = InvFolder.ID.ToString();
678 AgentInventoryArray.Add(TempHash);
679 }
680
681 return new InventoryData(AgentInventoryArray, rootID);
682
683 }
684
685 /// <summary>
686 /// Converts the inventory library skeleton into the form required by the rpc request.
687 /// </summary>
688 /// <returns></returns>
689 protected virtual ArrayList GetInventoryLibrary(ILibraryService library)
690 {
691 Dictionary<UUID, InventoryFolderImpl> rootFolders = library.GetAllFolders();
692// m_log.DebugFormat("[LLOGIN]: Library has {0} folders", rootFolders.Count);
693 //Dictionary<UUID, InventoryFolderImpl> rootFolders = new Dictionary<UUID,InventoryFolderImpl>();
694 ArrayList folderHashes = new ArrayList();
695
696 foreach (InventoryFolderBase folder in rootFolders.Values)
697 {
698 Hashtable TempHash = new Hashtable();
699 TempHash["name"] = folder.Name;
700 TempHash["parent_id"] = folder.ParentID.ToString();
701 TempHash["version"] = (Int32)folder.Version;
702 TempHash["type_default"] = (Int32)folder.Type;
703 TempHash["folder_id"] = folder.ID.ToString();
704 folderHashes.Add(TempHash);
705 }
706
707 return folderHashes;
708 }
709
710 /// <summary>
711 ///
712 /// </summary>
713 /// <returns></returns>
714 protected virtual ArrayList GetLibraryOwner(InventoryFolderImpl libFolder)
715 {
716 //for now create random inventory library owner
717 Hashtable TempHash = new Hashtable();
718 TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000"; // libFolder.Owner
719 ArrayList inventoryLibOwner = new ArrayList();
720 inventoryLibOwner.Add(TempHash);
721 return inventoryLibOwner;
722 }
723
724 public class InventoryData
725 {
726 public ArrayList InventoryArray = null;
727 public UUID RootFolderID = UUID.Zero;
728
729 public InventoryData(ArrayList invList, UUID rootID)
730 {
731 InventoryArray = invList;
732 RootFolderID = rootID;
733 }
734 }
735
736 #region Properties
737
738 public string Login
739 {
740 get { return login; }
741 set { login = value; }
742 }
743
744 public string DST
745 {
746 get { return dst; }
747 set { dst = value; }
748 }
749
750 public string StipendSinceLogin
751 {
752 get { return stipendSinceLogin; }
753 set { stipendSinceLogin = value; }
754 }
755
756 public string Gendered
757 {
758 get { return gendered; }
759 set { gendered = value; }
760 }
761
762 public string EverLoggedIn
763 {
764 get { return everLoggedIn; }
765 set { everLoggedIn = value; }
766 }
767
768 public uint SimPort
769 {
770 get { return simPort; }
771 set { simPort = value; }
772 }
773
774 public uint SimHttpPort
775 {
776 get { return simHttpPort; }
777 set { simHttpPort = value; }
778 }
779
780 public string SimAddress
781 {
782 get { return simAddress; }
783 set { simAddress = value; }
784 }
785
786 public UUID AgentID
787 {
788 get { return agentID; }
789 set { agentID = value; }
790 }
791
792 public UUID SessionID
793 {
794 get { return sessionID; }
795 set { sessionID = value; }
796 }
797
798 public UUID SecureSessionID
799 {
800 get { return secureSessionID; }
801 set { secureSessionID = value; }
802 }
803
804 public Int32 CircuitCode
805 {
806 get { return circuitCode; }
807 set { circuitCode = value; }
808 }
809
810 public uint RegionX
811 {
812 get { return regionX; }
813 set { regionX = value; }
814 }
815
816 public uint RegionY
817 {
818 get { return regionY; }
819 set { regionY = value; }
820 }
821
822 public string SunTexture
823 {
824 get { return sunTexture; }
825 set { sunTexture = value; }
826 }
827
828 public string CloudTexture
829 {
830 get { return cloudTexture; }
831 set { cloudTexture = value; }
832 }
833
834 public string MoonTexture
835 {
836 get { return moonTexture; }
837 set { moonTexture = value; }
838 }
839
840 public string Firstname
841 {
842 get { return firstname; }
843 set { firstname = value; }
844 }
845
846 public string Lastname
847 {
848 get { return lastname; }
849 set { lastname = value; }
850 }
851
852 public string AgentAccess
853 {
854 get { return agentAccess; }
855 set { agentAccess = value; }
856 }
857
858 public string AgentAccessMax
859 {
860 get { return agentAccessMax; }
861 set { agentAccessMax = value; }
862 }
863
864 public string StartLocation
865 {
866 get { return startLocation; }
867 set { startLocation = value; }
868 }
869
870 public string LookAt
871 {
872 get { return lookAt; }
873 set { lookAt = value; }
874 }
875
876 public string SeedCapability
877 {
878 get { return seedCapability; }
879 set { seedCapability = value; }
880 }
881
882 public string ErrorReason
883 {
884 get { return errorReason; }
885 set { errorReason = value; }
886 }
887
888 public string ErrorMessage
889 {
890 get { return errorMessage; }
891 set { errorMessage = value; }
892 }
893
894 public ArrayList InventoryRoot
895 {
896 get { return inventoryRoot; }
897 set { inventoryRoot = value; }
898 }
899
900 public ArrayList InventorySkeleton
901 {
902 get { return agentInventory; }
903 set { agentInventory = value; }
904 }
905
906 public ArrayList InventoryLibrary
907 {
908 get { return inventoryLibrary; }
909 set { inventoryLibrary = value; }
910 }
911
912 public ArrayList InventoryLibraryOwner
913 {
914 get { return inventoryLibraryOwner; }
915 set { inventoryLibraryOwner = value; }
916 }
917
918 public ArrayList InventoryLibRoot
919 {
920 get { return inventoryLibRoot; }
921 set { inventoryLibRoot = value; }
922 }
923
924 public ArrayList ActiveGestures
925 {
926 get { return activeGestures; }
927 set { activeGestures = value; }
928 }
929
930 public string Home
931 {
932 get { return home; }
933 set { home = value; }
934 }
935
936 public string MapTileURL
937 {
938 get { return mapTileURL; }
939 set { mapTileURL = value; }
940 }
941
942 public string SearchURL
943 {
944 get { return searchURL; }
945 set { searchURL = value; }
946 }
947
948 public string Message
949 {
950 get { return welcomeMessage; }
951 set { welcomeMessage = value; }
952 }
953
954 public BuddyList BuddList
955 {
956 get { return m_buddyList; }
957 set { m_buddyList = value; }
958 }
959
960 public string Currency
961 {
962 get { return currency; }
963 set { currency = value; }
964 }
965
966 #endregion
967
968 public class UserInfo
969 {
970 public string firstname;
971 public string lastname;
972 public ulong homeregionhandle;
973 public Vector3 homepos;
974 public Vector3 homelookat;
975 }
976
977 public class BuddyList
978 {
979 public List<BuddyInfo> Buddies = new List<BuddyInfo>();
980
981 public void AddNewBuddy(BuddyInfo buddy)
982 {
983 if (!Buddies.Contains(buddy))
984 {
985 Buddies.Add(buddy);
986 }
987 }
988
989 public ArrayList ToArray()
990 {
991 ArrayList buddyArray = new ArrayList();
992 foreach (BuddyInfo buddy in Buddies)
993 {
994 buddyArray.Add(buddy.ToHashTable());
995 }
996 return buddyArray;
997 }
998
999 public class BuddyInfo
1000 {
1001 public int BuddyRightsHave = 1;
1002 public int BuddyRightsGiven = 1;
1003 public string BuddyID;
1004
1005 public BuddyInfo(string buddyID)
1006 {
1007 BuddyID = buddyID;
1008 }
1009
1010 public BuddyInfo(UUID buddyID)
1011 {
1012 BuddyID = buddyID.ToString();
1013 }
1014
1015 public Hashtable ToHashTable()
1016 {
1017 Hashtable hTable = new Hashtable();
1018 hTable["buddy_rights_has"] = BuddyRightsHave;
1019 hTable["buddy_rights_given"] = BuddyRightsGiven;
1020 hTable["buddy_id"] = BuddyID;
1021 return hTable;
1022 }
1023 }
1024 }
1025 }
1026}
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
new file mode 100644
index 0000000..035980d
--- /dev/null
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -0,0 +1,938 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Linq;
32using System.Net;
33using System.Reflection;
34using System.Text.RegularExpressions;
35
36using log4net;
37using Nini.Config;
38using OpenMetaverse;
39
40using OpenSim.Framework;
41using OpenSim.Framework.Console;
42using OpenSim.Server.Base;
43using OpenSim.Services.Interfaces;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
46using OpenSim.Services.Connectors.Hypergrid;
47
48namespace OpenSim.Services.LLLoginService
49{
50 public class LLLoginService : ILoginService
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private static bool Initialized = false;
54
55 protected IUserAccountService m_UserAccountService;
56 protected IGridUserService m_GridUserService;
57 protected IAuthenticationService m_AuthenticationService;
58 protected IInventoryService m_InventoryService;
59 protected IGridService m_GridService;
60 protected IPresenceService m_PresenceService;
61 protected ISimulationService m_LocalSimulationService;
62 protected ISimulationService m_RemoteSimulationService;
63 protected ILibraryService m_LibraryService;
64 protected IFriendsService m_FriendsService;
65 protected IAvatarService m_AvatarService;
66 protected IUserAgentService m_UserAgentService;
67
68 protected GatekeeperServiceConnector m_GatekeeperConnector;
69
70 protected string m_DefaultRegionName;
71 protected string m_WelcomeMessage;
72 protected bool m_RequireInventory;
73 protected int m_MinLoginLevel;
74 protected string m_GatekeeperURL;
75 protected bool m_AllowRemoteSetLoginLevel;
76 protected string m_MapTileURL;
77 protected string m_SearchURL;
78 protected string m_Currency;
79
80 protected string m_AllowedClients;
81 protected string m_DeniedClients;
82
83 IConfig m_LoginServerConfig;
84// IConfig m_ClientsConfig;
85
86 public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
87 {
88 m_LoginServerConfig = config.Configs["LoginService"];
89 if (m_LoginServerConfig == null)
90 throw new Exception(String.Format("No section LoginService in config file"));
91
92 string accountService = m_LoginServerConfig.GetString("UserAccountService", String.Empty);
93 string gridUserService = m_LoginServerConfig.GetString("GridUserService", String.Empty);
94 string agentService = m_LoginServerConfig.GetString("UserAgentService", String.Empty);
95 string authService = m_LoginServerConfig.GetString("AuthenticationService", String.Empty);
96 string invService = m_LoginServerConfig.GetString("InventoryService", String.Empty);
97 string gridService = m_LoginServerConfig.GetString("GridService", String.Empty);
98 string presenceService = m_LoginServerConfig.GetString("PresenceService", String.Empty);
99 string libService = m_LoginServerConfig.GetString("LibraryService", String.Empty);
100 string friendsService = m_LoginServerConfig.GetString("FriendsService", String.Empty);
101 string avatarService = m_LoginServerConfig.GetString("AvatarService", String.Empty);
102 string simulationService = m_LoginServerConfig.GetString("SimulationService", String.Empty);
103
104 m_DefaultRegionName = m_LoginServerConfig.GetString("DefaultRegion", String.Empty);
105 m_WelcomeMessage = m_LoginServerConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
106 m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true);
107 m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false);
108 m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0);
109 m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
110 m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty);
111 m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty);
112 m_Currency = m_LoginServerConfig.GetString("Currency", string.Empty);
113
114 m_AllowedClients = m_LoginServerConfig.GetString("AllowedClients", string.Empty);
115 m_DeniedClients = m_LoginServerConfig.GetString("DeniedClients", string.Empty);
116
117 // Clean up some of these vars
118 if (m_MapTileURL != String.Empty)
119 {
120 m_MapTileURL = m_MapTileURL.Trim();
121 if (!m_MapTileURL.EndsWith("/"))
122 m_MapTileURL = m_MapTileURL + "/";
123 }
124
125 // These are required; the others aren't
126 if (accountService == string.Empty || authService == string.Empty)
127 throw new Exception("LoginService is missing service specifications");
128
129 // replace newlines in welcome message
130 m_WelcomeMessage = m_WelcomeMessage.Replace("\\n", "\n");
131
132 Object[] args = new Object[] { config };
133 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
134 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
135 Object[] authArgs = new Object[] { config, m_UserAccountService };
136 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, authArgs);
137 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
138
139 if (gridService != string.Empty)
140 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
141 if (presenceService != string.Empty)
142 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
143 if (avatarService != string.Empty)
144 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarService, args);
145 if (friendsService != string.Empty)
146 m_FriendsService = ServerUtils.LoadPlugin<IFriendsService>(friendsService, args);
147 if (simulationService != string.Empty)
148 m_RemoteSimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
149 if (agentService != string.Empty)
150 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(agentService, args);
151
152 //
153 // deal with the services given as argument
154 //
155 m_LocalSimulationService = simService;
156 if (libraryService != null)
157 {
158 m_log.DebugFormat("[LLOGIN SERVICE]: Using LibraryService given as argument");
159 m_LibraryService = libraryService;
160 }
161 else if (libService != string.Empty)
162 {
163 m_log.DebugFormat("[LLOGIN SERVICE]: Using instantiated LibraryService");
164 m_LibraryService = ServerUtils.LoadPlugin<ILibraryService>(libService, args);
165 }
166
167 m_GatekeeperConnector = new GatekeeperServiceConnector();
168
169 if (!Initialized)
170 {
171 Initialized = true;
172 RegisterCommands();
173 }
174
175 m_log.DebugFormat("[LLOGIN SERVICE]: Starting...");
176
177 }
178
179 public LLLoginService(IConfigSource config) : this(config, null, null)
180 {
181 }
182
183 public Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP)
184 {
185 Hashtable response = new Hashtable();
186 response["success"] = "false";
187
188 if (!m_AllowRemoteSetLoginLevel)
189 return response;
190
191 try
192 {
193 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
194 if (account == null)
195 {
196 m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, user {0} {1} not found", firstName, lastName);
197 return response;
198 }
199
200 if (account.UserLevel < 200)
201 {
202 m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, reason: user level too low");
203 return response;
204 }
205
206 //
207 // Authenticate this user
208 //
209 // We don't support clear passwords here
210 //
211 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30);
212 UUID secureSession = UUID.Zero;
213 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
214 {
215 m_log.InfoFormat("[LLOGIN SERVICE]: SetLevel failed, reason: authentication failed");
216 return response;
217 }
218 }
219 catch (Exception e)
220 {
221 m_log.Error("[LLOGIN SERVICE]: SetLevel failed, exception " + e.ToString());
222 return response;
223 }
224
225 m_MinLoginLevel = level;
226 m_log.InfoFormat("[LLOGIN SERVICE]: Login level set to {0} by {1} {2}", level, firstName, lastName);
227
228 response["success"] = true;
229 return response;
230 }
231
232 public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID,
233 string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP)
234 {
235 bool success = false;
236 UUID session = UUID.Random();
237
238 m_log.InfoFormat("[LLOGIN SERVICE]: Login request for {0} {1} at {2} using viewer {3}, channel {4}, IP {5}, Mac {6}, Id0 {7}",
239 firstName, lastName, startLocation, clientVersion, channel, clientIP.Address.ToString(), mac, id0);
240 try
241 {
242 //
243 // Check client
244 //
245 if (m_AllowedClients != string.Empty)
246 {
247 Regex arx = new Regex(m_AllowedClients);
248 Match am = arx.Match(clientVersion);
249
250 if (!am.Success)
251 {
252 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is not allowed", clientVersion);
253 return LLFailedLoginResponse.LoginBlockedProblem;
254 }
255 }
256
257 if (m_DeniedClients != string.Empty)
258 {
259 Regex drx = new Regex(m_DeniedClients);
260 Match dm = drx.Match(clientVersion);
261
262 if (dm.Success)
263 {
264 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: client {0} is denied", clientVersion);
265 return LLFailedLoginResponse.LoginBlockedProblem;
266 }
267 }
268
269 //
270 // Get the account and check that it exists
271 //
272 UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName);
273 if (account == null)
274 {
275 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found");
276 return LLFailedLoginResponse.UserProblem;
277 }
278
279 if (account.UserLevel < 0)
280 {
281 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: Unverified account");
282 return LLFailedLoginResponse.UnverifiedAccountProblem;
283 }
284
285 if (account.UserLevel < m_MinLoginLevel)
286 {
287 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel);
288 return LLFailedLoginResponse.LoginBlockedProblem;
289 }
290
291 // If a scope id is requested, check that the account is in
292 // that scope, or unscoped.
293 //
294 if (scopeID != UUID.Zero)
295 {
296 if (account.ScopeID != scopeID && account.ScopeID != UUID.Zero)
297 {
298 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found");
299 return LLFailedLoginResponse.UserProblem;
300 }
301 }
302 else
303 {
304 scopeID = account.ScopeID;
305 }
306
307 //
308 // Authenticate this user
309 //
310 if (!passwd.StartsWith("$1$"))
311 passwd = "$1$" + Util.Md5Hash(passwd);
312 passwd = passwd.Remove(0, 3); //remove $1$
313 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30);
314 UUID secureSession = UUID.Zero;
315 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
316 {
317 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: authentication failed");
318 return LLFailedLoginResponse.UserProblem;
319 }
320
321 //
322 // Get the user's inventory
323 //
324 if (m_RequireInventory && m_InventoryService == null)
325 {
326 m_log.WarnFormat("[LLOGIN SERVICE]: Login failed, reason: inventory service not set up");
327 return LLFailedLoginResponse.InventoryProblem;
328 }
329 List<InventoryFolderBase> inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID);
330 if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0)))
331 {
332 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: unable to retrieve user inventory");
333 return LLFailedLoginResponse.InventoryProblem;
334 }
335
336 // Get active gestures
337 List<InventoryItemBase> gestures = m_InventoryService.GetActiveGestures(account.PrincipalID);
338// m_log.DebugFormat("[LLOGIN SERVICE]: {0} active gestures", gestures.Count);
339
340 //
341 // Login the presence
342 //
343 if (m_PresenceService != null)
344 {
345 success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession);
346 if (!success)
347 {
348 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence");
349 return LLFailedLoginResponse.GridProblem;
350 }
351 }
352
353 //
354 // Change Online status and get the home region
355 //
356 GridRegion home = null;
357 GridUserInfo guinfo = m_GridUserService.LoggedIn(account.PrincipalID.ToString());
358 if (guinfo != null && (guinfo.HomeRegionID != UUID.Zero) && m_GridService != null)
359 {
360 home = m_GridService.GetRegionByUUID(scopeID, guinfo.HomeRegionID);
361 }
362 if (guinfo == null)
363 {
364 // something went wrong, make something up, so that we don't have to test this anywhere else
365 guinfo = new GridUserInfo();
366 guinfo.LastPosition = guinfo.HomePosition = new Vector3(128, 128, 30);
367 }
368
369 //
370 // Find the destination region/grid
371 //
372 string where = string.Empty;
373 Vector3 position = Vector3.Zero;
374 Vector3 lookAt = Vector3.Zero;
375 GridRegion gatekeeper = null;
376 TeleportFlags flags;
377 GridRegion destination = FindDestination(account, scopeID, guinfo, session, startLocation, home, out gatekeeper, out where, out position, out lookAt, out flags);
378 if (destination == null)
379 {
380 m_PresenceService.LogoutAgent(session);
381 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found");
382 return LLFailedLoginResponse.GridProblem;
383 }
384
385 if (account.UserLevel >= 200)
386 flags |= TeleportFlags.Godlike;
387 //
388 // Get the avatar
389 //
390 AvatarAppearance avatar = null;
391 if (m_AvatarService != null)
392 {
393 avatar = m_AvatarService.GetAppearance(account.PrincipalID);
394 }
395
396 //
397 // Instantiate/get the simulation interface and launch an agent at the destination
398 //
399 string reason = string.Empty;
400 GridRegion dest;
401 AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where,
402 clientVersion, channel, mac, id0, clientIP, flags, out where, out reason, out dest);
403 destination = dest;
404 if (aCircuit == null)
405 {
406 m_PresenceService.LogoutAgent(session);
407 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason);
408 return new LLFailedLoginResponse("key", reason, "false");
409
410 }
411 // Get Friends list
412 FriendInfo[] friendsList = new FriendInfo[0];
413 if (m_FriendsService != null)
414 {
415 friendsList = m_FriendsService.GetFriends(account.PrincipalID);
416// m_log.DebugFormat("[LLOGIN SERVICE]: Retrieved {0} friends", friendsList.Length);
417 }
418
419 //
420 // Finally, fill out the response and return it
421 //
422 LLLoginResponse response = new LLLoginResponse(account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService,
423 where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, m_MapTileURL, m_SearchURL, m_Currency);
424
425 m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to client.");
426 return response;
427 }
428 catch (Exception e)
429 {
430 m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2} {3}", firstName, lastName, e.ToString(), e.StackTrace);
431 if (m_PresenceService != null)
432 m_PresenceService.LogoutAgent(session);
433 return LLFailedLoginResponse.InternalError;
434 }
435 }
436
437 protected GridRegion FindDestination(UserAccount account, UUID scopeID, GridUserInfo pinfo, UUID sessionID, string startLocation, GridRegion home, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt, out TeleportFlags flags)
438 {
439 flags = TeleportFlags.ViaLogin;
440
441 m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation);
442
443 gatekeeper = null;
444 where = "home";
445 position = new Vector3(128, 128, 0);
446 lookAt = new Vector3(0, 1, 0);
447
448 if (m_GridService == null)
449 return null;
450
451 if (startLocation.Equals("home"))
452 {
453 // logging into home region
454 if (pinfo == null)
455 return null;
456
457 GridRegion region = null;
458
459 bool tryDefaults = false;
460
461 if (home == null)
462 {
463 m_log.WarnFormat(
464 "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set",
465 account.FirstName, account.LastName);
466
467 tryDefaults = true;
468 }
469 else
470 {
471 region = home;
472
473 position = pinfo.HomePosition;
474 lookAt = pinfo.HomeLookAt;
475 }
476
477 if (tryDefaults)
478 {
479 List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID);
480 if (defaults != null && defaults.Count > 0)
481 {
482 region = defaults[0];
483 where = "safe";
484 }
485 else
486 {
487 m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a valid home and this grid does not have default locations. Attempting to find random region",
488 account.FirstName, account.LastName);
489 region = FindAlternativeRegion(scopeID);
490 if (region != null)
491 where = "safe";
492 }
493 }
494
495 return region;
496 }
497 else if (startLocation.Equals("last"))
498 {
499 // logging into last visited region
500 where = "last";
501
502 if (pinfo == null)
503 return null;
504
505 GridRegion region = null;
506
507 if (pinfo.LastRegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(scopeID, pinfo.LastRegionID)) == null)
508 {
509 List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID);
510 if (defaults != null && defaults.Count > 0)
511 {
512 region = defaults[0];
513 where = "safe";
514 }
515 else
516 {
517 m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region");
518 region = FindAlternativeRegion(scopeID);
519 if (region != null)
520 where = "safe";
521 }
522
523 }
524 else
525 {
526 position = pinfo.LastPosition;
527 lookAt = pinfo.LastLookAt;
528 }
529
530 return region;
531 }
532 else
533 {
534 flags |= TeleportFlags.ViaRegionID;
535
536 // free uri form
537 // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34
538 where = "url";
539 GridRegion region = null;
540 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
541 Match uriMatch = reURI.Match(startLocation);
542 if (uriMatch == null)
543 {
544 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, but can't process it", startLocation);
545 return null;
546 }
547 else
548 {
549 position = new Vector3(float.Parse(uriMatch.Groups["x"].Value, Culture.NumberFormatInfo),
550 float.Parse(uriMatch.Groups["y"].Value, Culture.NumberFormatInfo),
551 float.Parse(uriMatch.Groups["z"].Value, Culture.NumberFormatInfo));
552
553 string regionName = uriMatch.Groups["region"].ToString();
554 if (regionName != null)
555 {
556 if (!regionName.Contains("@"))
557 {
558 List<GridRegion> regions = m_GridService.GetRegionsByName(scopeID, regionName, 1);
559 if ((regions == null) || (regions != null && regions.Count == 0))
560 {
561 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}. Trying defaults.", startLocation, regionName);
562 regions = m_GridService.GetDefaultRegions(scopeID);
563 if (regions != null && regions.Count > 0)
564 {
565 where = "safe";
566 return regions[0];
567 }
568 else
569 {
570 m_log.Info("[LLOGIN SERVICE]: Last Region Not Found Attempting to find random region");
571 region = FindAlternativeRegion(scopeID);
572 if (region != null)
573 {
574 where = "safe";
575 return region;
576 }
577 else
578 {
579 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions and no alternative found.", startLocation);
580 return null;
581 }
582 }
583 }
584 return regions[0];
585 }
586 else
587 {
588 if (m_UserAgentService == null)
589 {
590 m_log.WarnFormat("[LLLOGIN SERVICE]: This llogin service is not running a user agent service, as such it can't lauch agents at foreign grids");
591 return null;
592 }
593 string[] parts = regionName.Split(new char[] { '@' });
594 if (parts.Length < 2)
595 {
596 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}", startLocation, regionName);
597 return null;
598 }
599 // Valid specification of a remote grid
600
601 regionName = parts[0];
602 string domainLocator = parts[1];
603 parts = domainLocator.Split(new char[] {':'});
604 string domainName = parts[0];
605 uint port = 0;
606 if (parts.Length > 1)
607 UInt32.TryParse(parts[1], out port);
608
609// GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper);
610 region = FindForeignRegion(domainName, port, regionName, out gatekeeper);
611 return region;
612 }
613 }
614 else
615 {
616 List<GridRegion> defaults = m_GridService.GetDefaultRegions(scopeID);
617 if (defaults != null && defaults.Count > 0)
618 {
619 where = "safe";
620 return defaults[0];
621 }
622 else
623 return null;
624 }
625 }
626 //response.LookAt = "[r0,r1,r0]";
627 //// can be: last, home, safe, url
628 //response.StartLocation = "url";
629
630 }
631
632 }
633
634 private GridRegion FindAlternativeRegion(UUID scopeID)
635 {
636 List<GridRegion> hyperlinks = null;
637 List<GridRegion> regions = m_GridService.GetFallbackRegions(scopeID, 1000 * (int)Constants.RegionSize, 1000 * (int)Constants.RegionSize);
638 if (regions != null && regions.Count > 0)
639 {
640 hyperlinks = m_GridService.GetHyperlinks(scopeID);
641 IEnumerable<GridRegion> availableRegions = regions.Except(hyperlinks);
642 if (availableRegions.Count() > 0)
643 return availableRegions.ElementAt(0);
644 }
645 // No fallbacks, try to find an arbitrary region that is not a hyperlink
646 // maxNumber is fixed for now; maybe use some search pattern with increasing maxSize here?
647 regions = m_GridService.GetRegionsByName(scopeID, "", 10);
648 if (regions != null && regions.Count > 0)
649 {
650 if (hyperlinks == null)
651 hyperlinks = m_GridService.GetHyperlinks(scopeID);
652 IEnumerable<GridRegion> availableRegions = regions.Except(hyperlinks);
653 if (availableRegions.Count() > 0)
654 return availableRegions.ElementAt(0);
655 }
656 return null;
657 }
658
659 private GridRegion FindForeignRegion(string domainName, uint port, string regionName, out GridRegion gatekeeper)
660 {
661 m_log.Debug("[LLLOGIN SERVICE]: attempting to findforeignregion " + domainName + ":" + port.ToString() + ":" + regionName);
662 gatekeeper = new GridRegion();
663 gatekeeper.ExternalHostName = domainName;
664 gatekeeper.HttpPort = port;
665 gatekeeper.RegionName = regionName;
666 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
667
668 UUID regionID;
669 ulong handle;
670 string imageURL = string.Empty, reason = string.Empty;
671 if (m_GatekeeperConnector.LinkRegion(gatekeeper, out regionID, out handle, out domainName, out imageURL, out reason))
672 {
673 GridRegion destination = m_GatekeeperConnector.GetHyperlinkRegion(gatekeeper, regionID);
674 return destination;
675 }
676
677 return null;
678 }
679
680 private string hostName = string.Empty;
681 private int port = 0;
682
683 private void SetHostAndPort(string url)
684 {
685 try
686 {
687 Uri uri = new Uri(url);
688 hostName = uri.Host;
689 port = uri.Port;
690 }
691 catch
692 {
693 m_log.WarnFormat("[LLLogin SERVICE]: Unable to parse GatekeeperURL {0}", url);
694 }
695 }
696
697 protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarAppearance avatar,
698 UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, string channel, string mac, string id0,
699 IPEndPoint clientIP, TeleportFlags flags, out string where, out string reason, out GridRegion dest)
700 {
701 where = currentWhere;
702 ISimulationService simConnector = null;
703 reason = string.Empty;
704 uint circuitCode = 0;
705 AgentCircuitData aCircuit = null;
706
707 if (m_UserAgentService == null)
708 {
709 // HG standalones have both a localSimulatonDll and a remoteSimulationDll
710 // non-HG standalones have just a localSimulationDll
711 // independent login servers have just a remoteSimulationDll
712 if (m_LocalSimulationService != null)
713 simConnector = m_LocalSimulationService;
714 else if (m_RemoteSimulationService != null)
715 simConnector = m_RemoteSimulationService;
716 }
717 else // User Agent Service is on
718 {
719 if (gatekeeper == null) // login to local grid
720 {
721 if (hostName == string.Empty)
722 SetHostAndPort(m_GatekeeperURL);
723
724 gatekeeper = new GridRegion(destination);
725 gatekeeper.ExternalHostName = hostName;
726 gatekeeper.HttpPort = (uint)port;
727 gatekeeper.ServerURI = m_GatekeeperURL;
728 }
729 m_log.Debug("[LLLOGIN SERVICE]: no gatekeeper detected..... using " + m_GatekeeperURL);
730 }
731
732 bool success = false;
733
734 if (m_UserAgentService == null && simConnector != null)
735 {
736 circuitCode = (uint)Util.RandomClass.Next(); ;
737 aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0);
738 success = LaunchAgentDirectly(simConnector, destination, aCircuit, flags, out reason);
739 if (!success && m_GridService != null)
740 {
741 // Try the fallback regions
742 List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY);
743 if (fallbacks != null)
744 {
745 foreach (GridRegion r in fallbacks)
746 {
747 success = LaunchAgentDirectly(simConnector, r, aCircuit, flags | TeleportFlags.ViaRegionID, out reason);
748 if (success)
749 {
750 where = "safe";
751 destination = r;
752 break;
753 }
754 }
755 }
756 }
757 }
758
759 if (m_UserAgentService != null)
760 {
761 circuitCode = (uint)Util.RandomClass.Next(); ;
762 aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0);
763 success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, clientIP, out reason);
764 if (!success && m_GridService != null)
765 {
766 // Try the fallback regions
767 List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY);
768 if (fallbacks != null)
769 {
770 foreach (GridRegion r in fallbacks)
771 {
772 success = LaunchAgentIndirectly(gatekeeper, r, aCircuit, clientIP, out reason);
773 if (success)
774 {
775 where = "safe";
776 destination = r;
777 break;
778 }
779 }
780 }
781 }
782 }
783 dest = destination;
784 if (success)
785 return aCircuit;
786 else
787 return null;
788 }
789
790 private AgentCircuitData MakeAgent(GridRegion region, UserAccount account,
791 AvatarAppearance avatar, UUID session, UUID secureSession, uint circuit, Vector3 position,
792 string ipaddress, string viewer, string channel, string mac, string id0)
793 {
794 AgentCircuitData aCircuit = new AgentCircuitData();
795
796 aCircuit.AgentID = account.PrincipalID;
797 if (avatar != null)
798 aCircuit.Appearance = new AvatarAppearance(avatar);
799 else
800 aCircuit.Appearance = new AvatarAppearance();
801
802 //aCircuit.BaseFolder = irrelevant
803 aCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
804 aCircuit.child = false; // the first login agent is root
805 aCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>();
806 aCircuit.circuitcode = circuit;
807 aCircuit.firstname = account.FirstName;
808 //aCircuit.InventoryFolder = irrelevant
809 aCircuit.lastname = account.LastName;
810 aCircuit.SecureSessionID = secureSession;
811 aCircuit.SessionID = session;
812 aCircuit.startpos = position;
813 aCircuit.IPAddress = ipaddress;
814 aCircuit.Viewer = viewer;
815 aCircuit.Channel = channel;
816 aCircuit.Mac = mac;
817 aCircuit.Id0 = id0;
818 SetServiceURLs(aCircuit, account);
819
820 return aCircuit;
821
822 //m_UserAgentService.LoginAgentToGrid(aCircuit, GatekeeperServiceConnector, region, out reason);
823 //if (simConnector.CreateAgent(region, aCircuit, 0, out reason))
824 // return aCircuit;
825
826 //return null;
827
828 }
829
830 private void SetServiceURLs(AgentCircuitData aCircuit, UserAccount account)
831 {
832 aCircuit.ServiceURLs = new Dictionary<string, object>();
833 if (account.ServiceURLs == null)
834 return;
835
836 // Old style: get the service keys from the DB
837 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
838 {
839 if (kvp.Value != null)
840 {
841 aCircuit.ServiceURLs[kvp.Key] = kvp.Value;
842
843 if (!aCircuit.ServiceURLs[kvp.Key].ToString().EndsWith("/"))
844 aCircuit.ServiceURLs[kvp.Key] = aCircuit.ServiceURLs[kvp.Key] + "/";
845 }
846 }
847
848 // New style: service keys start with SRV_; override the previous
849 string[] keys = m_LoginServerConfig.GetKeys();
850
851 if (keys.Length > 0)
852 {
853 bool newUrls = false;
854 IEnumerable<string> serviceKeys = keys.Where(value => value.StartsWith("SRV_"));
855 foreach (string serviceKey in serviceKeys)
856 {
857 string keyName = serviceKey.Replace("SRV_", "");
858 string keyValue = m_LoginServerConfig.GetString(serviceKey, string.Empty);
859 if (!keyValue.EndsWith("/"))
860 keyValue = keyValue + "/";
861
862 if (!account.ServiceURLs.ContainsKey(keyName) || (account.ServiceURLs.ContainsKey(keyName) && account.ServiceURLs[keyName] != keyValue))
863 {
864 account.ServiceURLs[keyName] = keyValue;
865 newUrls = true;
866 }
867 aCircuit.ServiceURLs[keyName] = keyValue;
868
869 m_log.DebugFormat("[LLLOGIN SERVICE]: found new key {0} {1}", keyName, aCircuit.ServiceURLs[keyName]);
870 }
871
872 // The grid operator decided to override the defaults in the
873 // [LoginService] configuration. Let's store the correct ones.
874 if (newUrls)
875 m_UserAccountService.StoreUserAccount(account);
876 }
877
878 }
879
880 private bool LaunchAgentDirectly(ISimulationService simConnector, GridRegion region, AgentCircuitData aCircuit, TeleportFlags flags, out string reason)
881 {
882 return simConnector.CreateAgent(region, aCircuit, (uint)flags, out reason);
883 }
884
885 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason)
886 {
887 m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName);
888 if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, clientIP, out reason))
889 return true;
890 return false;
891 }
892
893 #region Console Commands
894 private void RegisterCommands()
895 {
896 //MainConsole.Instance.Commands.AddCommand
897 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login level",
898 "login level <level>",
899 "Set the minimum user level to log in", HandleLoginCommand);
900
901 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login reset",
902 "login reset",
903 "Reset the login level to allow all users",
904 HandleLoginCommand);
905
906 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login text",
907 "login text <text>",
908 "Set the text users will see on login", HandleLoginCommand);
909
910 }
911
912 private void HandleLoginCommand(string module, string[] cmd)
913 {
914 string subcommand = cmd[1];
915
916 switch (subcommand)
917 {
918 case "level":
919 // Set the minimum level to allow login
920 // Useful to allow grid update without worrying about users.
921 // or fixing critical issues
922 //
923 if (cmd.Length > 2)
924 Int32.TryParse(cmd[2], out m_MinLoginLevel);
925 break;
926 case "reset":
927 m_MinLoginLevel = 0;
928 break;
929 case "text":
930 if (cmd.Length > 2)
931 m_WelcomeMessage = cmd[2];
932 break;
933 }
934 }
935 }
936
937 #endregion
938}
diff --git a/OpenSim/Services/MapImageService/MapImageService.cs b/OpenSim/Services/MapImageService/MapImageService.cs
new file mode 100644
index 0000000..a85ee70
--- /dev/null
+++ b/OpenSim/Services/MapImageService/MapImageService.cs
@@ -0,0 +1,300 @@
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 * The design of this map service is based on SimianGrid's PHP-based
28 * map service. See this URL for the original PHP version:
29 * https://github.com/openmetaversefoundation/simiangrid/
30 */
31
32using System;
33using System.Collections.Generic;
34using System.Drawing;
35using System.Drawing.Imaging;
36using System.IO;
37using System.Net;
38using System.Reflection;
39
40using Nini.Config;
41using log4net;
42using OpenMetaverse;
43
44using OpenSim.Framework;
45using OpenSim.Framework.Console;
46using OpenSim.Services.Interfaces;
47
48
49namespace OpenSim.Services.MapImageService
50{
51 public class MapImageService : IMapImageService
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 private const int ZOOM_LEVELS = 8;
58 private const int IMAGE_WIDTH = 256;
59 private const int HALF_WIDTH = 128;
60 private const int JPEG_QUALITY = 80;
61
62 private static string m_TilesStoragePath = "maptiles";
63
64 private static object m_Sync = new object();
65 private static bool m_Initialized = false;
66 private static string m_WaterTileFile = string.Empty;
67 private static Color m_Watercolor = Color.FromArgb(29, 71, 95);
68
69 public MapImageService(IConfigSource config)
70 {
71 if (!m_Initialized)
72 {
73 m_Initialized = true;
74 m_log.Debug("[MAP IMAGE SERVICE]: Starting MapImage service");
75
76 IConfig serviceConfig = config.Configs["MapImageService"];
77 if (serviceConfig != null)
78 {
79 m_TilesStoragePath = serviceConfig.GetString("TilesStoragePath", m_TilesStoragePath);
80 if (!Directory.Exists(m_TilesStoragePath))
81 Directory.CreateDirectory(m_TilesStoragePath);
82
83
84 m_WaterTileFile = Path.Combine(m_TilesStoragePath, "water.jpg");
85 if (!File.Exists(m_WaterTileFile))
86 {
87 Bitmap waterTile = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH);
88 FillImage(waterTile, m_Watercolor);
89 waterTile.Save(m_WaterTileFile);
90 }
91 }
92 }
93 }
94
95 #region IMapImageService
96
97 public bool AddMapTile(int x, int y, byte[] imageData, out string reason)
98 {
99 reason = string.Empty;
100 string fileName = GetFileName(1, x, y);
101
102 lock (m_Sync)
103 {
104 try
105 {
106 using (FileStream f = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write))
107 f.Write(imageData, 0, imageData.Length);
108 }
109 catch (Exception e)
110 {
111 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to save image file {0}: {1}", fileName, e);
112 reason = e.Message;
113 return false;
114 }
115
116 // Also save in png format?
117
118 // Stitch seven more aggregate tiles together
119 for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
120 {
121 // Calculate the width (in full resolution tiles) and bottom-left
122 // corner of the current zoom level
123 int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
124 int x1 = x - (x % width);
125 int y1 = y - (y % width);
126
127 if (!CreateTile(zoomLevel, x1, y1))
128 {
129 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0} at zoom level {1}", fileName, zoomLevel);
130 reason = string.Format("Map tile at zoom level {0} failed", zoomLevel);
131 return false;
132 }
133 }
134 }
135
136 return true;
137 }
138
139 public byte[] GetMapTile(string fileName, out string format)
140 {
141// m_log.DebugFormat("[MAP IMAGE SERVICE]: Getting map tile {0}", fileName);
142
143 format = ".jpg";
144 string fullName = Path.Combine(m_TilesStoragePath, fileName);
145 if (File.Exists(fullName))
146 {
147 format = Path.GetExtension(fileName).ToLower();
148 //m_log.DebugFormat("[MAP IMAGE SERVICE]: Found file {0}, extension {1}", fileName, format);
149 return File.ReadAllBytes(fullName);
150 }
151 else if (File.Exists(m_WaterTileFile))
152 {
153 return File.ReadAllBytes(m_WaterTileFile);
154 }
155 else
156 {
157 m_log.DebugFormat("[MAP IMAGE SERVICE]: unable to get file {0}", fileName);
158 return new byte[0];
159 }
160 }
161
162 #endregion
163
164
165 private string GetFileName(uint zoomLevel, int x, int y)
166 {
167 string extension = "jpg";
168 return Path.Combine(m_TilesStoragePath, string.Format("map-{0}-{1}-{2}-objects.{3}", zoomLevel, x, y, extension));
169 }
170
171 private Bitmap GetInputTileImage(string fileName)
172 {
173 try
174 {
175 if (File.Exists(fileName))
176 return new Bitmap(fileName);
177 }
178 catch (Exception e)
179 {
180 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
181 }
182
183 return null;
184 }
185
186 private Bitmap GetOutputTileImage(string fileName)
187 {
188 try
189 {
190 if (File.Exists(fileName))
191 return new Bitmap(fileName);
192
193 else
194 {
195 // Create a new output tile with a transparent background
196 Bitmap bm = new Bitmap(IMAGE_WIDTH, IMAGE_WIDTH, PixelFormat.Format24bppRgb);
197 bm.MakeTransparent();
198 return bm;
199 }
200 }
201 catch (Exception e)
202 {
203 m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to read image data from {0}: {1}", fileName, e);
204 }
205
206 return null;
207 }
208
209 private bool CreateTile(uint zoomLevel, int x, int y)
210 {
211// m_log.DebugFormat("[MAP IMAGE SERVICE]: Create tile for {0} {1}, zoom {2}", x, y, zoomLevel);
212 int prevWidth = (int)Math.Pow(2, (double)zoomLevel - 2);
213 int thisWidth = (int)Math.Pow(2, (double)zoomLevel - 1);
214
215 // Convert x and y to the bottom left tile for this zoom level
216 int xIn = x - (x % prevWidth);
217 int yIn = y - (y % prevWidth);
218
219 // Convert x and y to the bottom left tile for the next zoom level
220 int xOut = x - (x % thisWidth);
221 int yOut = y - (y % thisWidth);
222
223 // Try to open the four input tiles from the previous zoom level
224 Bitmap inputBL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn));
225 Bitmap inputBR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn));
226 Bitmap inputTL = GetInputTileImage(GetFileName(zoomLevel - 1, xIn, yIn + prevWidth));
227 Bitmap inputTR = GetInputTileImage(GetFileName(zoomLevel - 1, xIn + prevWidth, yIn + prevWidth));
228
229 // Open the output tile (current zoom level)
230 string outputFile = GetFileName(zoomLevel, xOut, yOut);
231 Bitmap output = GetOutputTileImage(outputFile);
232 if (output == null)
233 return false;
234 FillImage(output, m_Watercolor);
235
236 if (inputBL != null)
237 {
238 ImageCopyResampled(output, inputBL, 0, HALF_WIDTH, 0, 0);
239 inputBL.Dispose();
240 }
241 if (inputBR != null)
242 {
243 ImageCopyResampled(output, inputBR, HALF_WIDTH, HALF_WIDTH, 0, 0);
244 inputBR.Dispose();
245 }
246 if (inputTL != null)
247 {
248 ImageCopyResampled(output, inputTL, 0, 0, 0, 0);
249 inputTL.Dispose();
250 }
251 if (inputTR != null)
252 {
253 ImageCopyResampled(output, inputTR, HALF_WIDTH, 0, 0, 0);
254 inputTR.Dispose();
255 }
256
257 // Write the modified output
258 try
259 {
260 using (Bitmap final = new Bitmap(output))
261 {
262 output.Dispose();
263 final.Save(outputFile, ImageFormat.Jpeg);
264 }
265 }
266 catch (Exception e)
267 {
268 m_log.WarnFormat("[MAP IMAGE SERVICE]: Oops on saving {0} {1}", outputFile, e);
269 }
270
271 // Save also as png?
272
273 return true;
274 }
275
276 #region Image utilities
277
278 private void FillImage(Bitmap bm, Color c)
279 {
280 for (int x = 0; x < bm.Width; x++)
281 for (int y = 0; y < bm.Height; y++)
282 bm.SetPixel(x, y, c);
283 }
284
285 private void ImageCopyResampled(Bitmap output, Bitmap input, int destX, int destY, int srcX, int srcY)
286 {
287 int resamplingRateX = 2; // (input.Width - srcX) / (output.Width - destX);
288 int resamplingRateY = 2; // (input.Height - srcY) / (output.Height - destY);
289
290 for (int x = destX; x < destX + HALF_WIDTH; x++)
291 for (int y = destY; y < destY + HALF_WIDTH; y++)
292 {
293 Color p = input.GetPixel(srcX + (x - destX) * resamplingRateX, srcY + (y - destY) * resamplingRateY);
294 output.SetPixel(x, y, p);
295 }
296 }
297
298 #endregion
299 }
300}
diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs
index 2157462..c8ac38e 100644
--- a/OpenSim/Services/PresenceService/PresenceService.cs
+++ b/OpenSim/Services/PresenceService/PresenceService.cs
@@ -41,27 +41,121 @@ 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
48 protected bool m_allowDuplicatePresences = false;
47 49
48 public PresenceService(IConfigSource config) 50 public PresenceService(IConfigSource config)
49 : base(config) 51 : base(config)
50 { 52 {
53 m_log.Debug("[PRESENCE SERVICE]: Starting presence service");
54
55 IConfig presenceConfig = config.Configs["PresenceService"];
56 if (presenceConfig != null)
57 {
58 m_allowDuplicatePresences =
59 presenceConfig.GetBoolean("AllowDuplicatePresences",
60 m_allowDuplicatePresences);
61 }
51 } 62 }
52 63
53 public bool Report(PresenceInfo presence) 64 public bool LoginAgent(string userID, UUID sessionID,
65 UUID secureSessionID)
54 { 66 {
55 PresenceData p = new PresenceData(); 67 //PresenceData[] d = m_Database.Get("UserID", userID);
56 p.Data = new Dictionary<string, string>(); 68 //m_Database.Get("UserID", userID);
69
70 if (!m_allowDuplicatePresences)
71 m_Database.Delete("UserID", userID.ToString());
72
73 PresenceData data = new PresenceData();
57 74
58 p.UUID = presence.PrincipalID; 75 data.UserID = userID;
59 p.currentRegion = presence.RegionID; 76 data.RegionID = UUID.Zero;
77 data.SessionID = sessionID;
78 data.Data = new Dictionary<string, string>();
79 data.Data["SecureSessionID"] = secureSessionID.ToString();
80
81 m_Database.Store(data);
60 82
61 foreach (KeyValuePair<string, string> kvp in presence.Data) 83 m_log.DebugFormat("[PRESENCE SERVICE]: LoginAgent {0} with session {1} and ssession {2}",
62 p.Data[kvp.Key] = kvp.Value; 84 userID, sessionID, secureSessionID);
85 return true;
86 }
87
88 public bool LogoutAgent(UUID sessionID)
89 {
90 m_log.DebugFormat("[PRESENCE SERVICE]: Session {0} logout", sessionID);
91 return m_Database.Delete("SessionID", sessionID.ToString());
92 }
93
94 public bool LogoutRegionAgents(UUID regionID)
95 {
96 m_Database.LogoutRegionAgents(regionID);
97
98 return true;
99 }
100
101
102 public bool ReportAgent(UUID sessionID, UUID regionID)
103 {
104// m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent with session {0} in region {1}", sessionID, regionID);
105 try
106 {
107 PresenceData pdata = m_Database.Get(sessionID);
108 if (pdata == null)
109 return false;
110 if (pdata.Data == null)
111 return false;
63 112
64 return false; 113 return m_Database.ReportAgent(sessionID, regionID);
114 }
115 catch (Exception e)
116 {
117 m_log.DebugFormat("[PRESENCE SERVICE]: ReportAgent threw exception {0}", e.StackTrace);
118 return false;
119 }
65 } 120 }
121
122 public PresenceInfo GetAgent(UUID sessionID)
123 {
124 PresenceInfo ret = new PresenceInfo();
125
126 PresenceData data = m_Database.Get(sessionID);
127 if (data == null)
128 return null;
129
130 ret.UserID = data.UserID;
131 ret.RegionID = data.RegionID;
132
133 return ret;
134 }
135
136 public PresenceInfo[] GetAgents(string[] userIDs)
137 {
138 List<PresenceInfo> info = new List<PresenceInfo>();
139
140 foreach (string userIDStr in userIDs)
141 {
142 PresenceData[] data = m_Database.Get("UserID",
143 userIDStr);
144
145 foreach (PresenceData d in data)
146 {
147 PresenceInfo ret = new PresenceInfo();
148
149 ret.UserID = d.UserID;
150 ret.RegionID = d.RegionID;
151
152 info.Add(ret);
153 }
154 }
155
156 // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count);
157 return info.ToArray();
158 }
159
66 } 160 }
67} 161}
diff --git a/OpenSim/Services/PresenceService/PresenceServiceBase.cs b/OpenSim/Services/PresenceService/PresenceServiceBase.cs
index 60a246b..a4adb2f 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
@@ -77,7 +77,7 @@ namespace OpenSim.Services.PresenceService
77 77
78 m_Database = LoadPlugin<IPresenceData>(dllName, new Object[] { connString, realm }); 78 m_Database = LoadPlugin<IPresenceData>(dllName, new Object[] { connString, realm });
79 if (m_Database == null) 79 if (m_Database == null)
80 throw new Exception("Could not find a storage interface in the given module"); 80 throw new Exception("Could not find a storage interface in the given module " + dllName);
81 81
82 } 82 }
83 } 83 }
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
new file mode 100644
index 0000000..9b18915
--- /dev/null
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -0,0 +1,159 @@
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.Reflection;
31using Nini.Config;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Framework;
35using OpenSim.Framework.Console;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37
38using OpenMetaverse;
39using log4net;
40
41namespace OpenSim.Services.UserAccountService
42{
43 public class GridUserService : GridUserServiceBase, IGridUserService
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 public GridUserService(IConfigSource config) : base(config)
48 {
49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service");
50 }
51
52 public GridUserInfo GetGridUserInfo(string userID)
53 {
54 GridUserData d = m_Database.Get(userID);
55
56 if (d == null)
57 return null;
58
59 GridUserInfo info = new GridUserInfo();
60 info.UserID = d.UserID;
61 info.HomeRegionID = new UUID(d.Data["HomeRegionID"]);
62 info.HomePosition = Vector3.Parse(d.Data["HomePosition"]);
63 info.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]);
64
65 info.LastRegionID = new UUID(d.Data["LastRegionID"]);
66 info.LastPosition = Vector3.Parse(d.Data["LastPosition"]);
67 info.LastLookAt = Vector3.Parse(d.Data["LastLookAt"]);
68
69 info.Online = bool.Parse(d.Data["Online"]);
70 info.Login = Util.ToDateTime(Convert.ToInt32(d.Data["Login"]));
71 info.Logout = Util.ToDateTime(Convert.ToInt32(d.Data["Logout"]));
72
73 return info;
74 }
75
76 public GridUserInfo LoggedIn(string userID)
77 {
78 m_log.DebugFormat("[GRID USER SERVICE]: User {0} is online", userID);
79 GridUserData d = m_Database.Get(userID);
80
81 if (d == null)
82 {
83 d = new GridUserData();
84 d.UserID = userID;
85 }
86
87 d.Data["Online"] = true.ToString();
88 d.Data["Login"] = Util.UnixTimeSinceEpoch().ToString();
89
90 m_Database.Store(d);
91
92 return GetGridUserInfo(userID);
93 }
94
95 public bool LoggedOut(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
96 {
97 m_log.DebugFormat("[GRID USER SERVICE]: User {0} is offline", userID);
98 GridUserData d = m_Database.Get(userID);
99
100 if (d == null)
101 {
102 d = new GridUserData();
103 d.UserID = userID;
104 }
105
106 d.Data["Online"] = false.ToString();
107 d.Data["Logout"] = Util.UnixTimeSinceEpoch().ToString();
108 d.Data["LastRegionID"] = regionID.ToString();
109 d.Data["LastPosition"] = lastPosition.ToString();
110 d.Data["LastLookAt"] = lastLookAt.ToString();
111
112 return m_Database.Store(d);
113 }
114
115 protected bool StoreGridUserInfo(GridUserInfo info)
116 {
117 GridUserData d = new GridUserData();
118
119 d.Data["HomeRegionID"] = info.HomeRegionID.ToString();
120 d.Data["HomePosition"] = info.HomePosition.ToString();
121 d.Data["HomeLookAt"] = info.HomeLookAt.ToString();
122
123 return m_Database.Store(d);
124 }
125
126 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt)
127 {
128 GridUserData d = m_Database.Get(userID);
129 if (d == null)
130 {
131 d = new GridUserData();
132 d.UserID = userID;
133 }
134
135 d.Data["HomeRegionID"] = homeID.ToString();
136 d.Data["HomePosition"] = homePosition.ToString();
137 d.Data["HomeLookAt"] = homeLookAt.ToString();
138
139 return m_Database.Store(d);
140 }
141
142 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
143 {
144 //m_log.DebugFormat("[Grid User Service]: SetLastPosition for {0}", userID);
145 GridUserData d = m_Database.Get(userID);
146 if (d == null)
147 {
148 d = new GridUserData();
149 d.UserID = userID;
150 }
151
152 d.Data["LastRegionID"] = regionID.ToString();
153 d.Data["LastPosition"] = lastPosition.ToString();
154 d.Data["LastLookAt"] = lastLookAt.ToString();
155
156 return m_Database.Store(d);
157 }
158 }
159} \ No newline at end of file
diff --git a/OpenSim/Services/UserAccountService/GridUserServiceBase.cs b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs
new file mode 100644
index 0000000..990cb63
--- /dev/null
+++ b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs
@@ -0,0 +1,82 @@
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.Reflection;
30using Nini.Config;
31using OpenSim.Framework;
32using OpenSim.Data;
33using OpenSim.Services.Interfaces;
34using OpenSim.Services.Base;
35
36namespace OpenSim.Services.UserAccountService
37{
38 public class GridUserServiceBase : ServiceBase
39 {
40 protected IGridUserData m_Database = null;
41
42 public GridUserServiceBase(IConfigSource config) : base(config)
43 {
44 string dllName = String.Empty;
45 string connString = String.Empty;
46 string realm = "GridUser";
47
48 //
49 // Try reading the [DatabaseService] section, if it exists
50 //
51 IConfig dbConfig = config.Configs["DatabaseService"];
52 if (dbConfig != null)
53 {
54 if (dllName == String.Empty)
55 dllName = dbConfig.GetString("StorageProvider", String.Empty);
56 if (connString == String.Empty)
57 connString = dbConfig.GetString("ConnectionString", String.Empty);
58 }
59
60 //
61 // [GridUsetService] section overrides [DatabaseService], if it exists
62 //
63 IConfig presenceConfig = config.Configs["GridUserService"];
64 if (presenceConfig != null)
65 {
66 dllName = presenceConfig.GetString("StorageProvider", dllName);
67 connString = presenceConfig.GetString("ConnectionString", connString);
68 realm = presenceConfig.GetString("Realm", realm);
69 }
70
71 //
72 // We tried, but this doesn't exist. We can't proceed.
73 //
74 if (dllName.Equals(String.Empty))
75 throw new Exception("No StorageProvider configured");
76
77 m_Database = LoadPlugin<IGridUserData>(dllName, new Object[] { connString, realm });
78 if (m_Database == null)
79 throw new Exception("Could not find a storage interface in the given module " + dllName);
80 }
81 }
82} \ No newline at end of file
diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs
new file mode 100644
index 0000000..ad06300
--- /dev/null
+++ b/OpenSim/Services/UserAccountService/UserAccountService.cs
@@ -0,0 +1,687 @@
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.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Data;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37using OpenSim.Framework.Console;
38using GridRegion = OpenSim.Services.Interfaces.GridRegion;
39
40namespace OpenSim.Services.UserAccountService
41{
42 public class UserAccountService : UserAccountServiceBase, IUserAccountService
43 {
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static UserAccountService m_RootInstance;
46
47 /// <summary>
48 /// Should we create default entries (minimum body parts/clothing, avatar wearable entries) for a new avatar?
49 /// </summary>
50 private bool m_CreateDefaultAvatarEntries;
51
52 protected IGridService m_GridService;
53 protected IAuthenticationService m_AuthenticationService;
54 protected IGridUserService m_GridUserService;
55 protected IInventoryService m_InventoryService;
56 protected IAvatarService m_AvatarService;
57
58 public UserAccountService(IConfigSource config)
59 : base(config)
60 {
61 IConfig userConfig = config.Configs["UserAccountService"];
62 if (userConfig == null)
63 throw new Exception("No UserAccountService configuration");
64
65 string gridServiceDll = userConfig.GetString("GridService", string.Empty);
66 if (gridServiceDll != string.Empty)
67 m_GridService = LoadPlugin<IGridService>(gridServiceDll, new Object[] { config });
68
69 string authServiceDll = userConfig.GetString("AuthenticationService", string.Empty);
70 if (authServiceDll != string.Empty)
71 m_AuthenticationService = LoadPlugin<IAuthenticationService>(authServiceDll, new Object[] { config });
72
73 string presenceServiceDll = userConfig.GetString("GridUserService", string.Empty);
74 if (presenceServiceDll != string.Empty)
75 m_GridUserService = LoadPlugin<IGridUserService>(presenceServiceDll, new Object[] { config });
76
77 string invServiceDll = userConfig.GetString("InventoryService", string.Empty);
78 if (invServiceDll != string.Empty)
79 m_InventoryService = LoadPlugin<IInventoryService>(invServiceDll, new Object[] { config });
80
81 string avatarServiceDll = userConfig.GetString("AvatarService", string.Empty);
82 if (avatarServiceDll != string.Empty)
83 m_AvatarService = LoadPlugin<IAvatarService>(avatarServiceDll, new Object[] { config });
84
85 m_CreateDefaultAvatarEntries = userConfig.GetBoolean("CreateDefaultAvatarEntries", false);
86
87 // In case there are several instances of this class in the same process,
88 // the console commands are only registered for the root instance
89 if (m_RootInstance == null && MainConsole.Instance != null)
90 {
91 m_RootInstance = this;
92 MainConsole.Instance.Commands.AddCommand("UserService", false,
93 "create user",
94 "create user [<first> [<last> [<pass> [<email> [<user id>]]]]]",
95 "Create a new user", HandleCreateUser);
96
97 MainConsole.Instance.Commands.AddCommand("UserService", false,
98 "reset user password",
99 "reset user password [<first> [<last> [<password>]]]",
100 "Reset a user password", HandleResetUserPassword);
101
102 MainConsole.Instance.Commands.AddCommand("UserService", false,
103 "set user level",
104 "set user level [<first> [<last> [<level>]]]",
105 "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, "
106 + "this account will be treated as god-moded. "
107 + "It will also affect the 'login level' command. ",
108 HandleSetUserLevel);
109
110 MainConsole.Instance.Commands.AddCommand("UserService", false,
111 "show account",
112 "show account <first> <last>",
113 "Show account details for the given user", HandleShowAccount);
114 }
115 }
116
117 #region IUserAccountService
118
119 public UserAccount GetUserAccount(UUID scopeID, string firstName,
120 string lastName)
121 {
122// m_log.DebugFormat(
123// "[USER ACCOUNT SERVICE]: Retrieving account by username for {0} {1}, scope {2}",
124// firstName, lastName, scopeID);
125
126 UserAccountData[] d;
127
128 if (scopeID != UUID.Zero)
129 {
130 d = m_Database.Get(
131 new string[] { "ScopeID", "FirstName", "LastName" },
132 new string[] { scopeID.ToString(), firstName, lastName });
133 if (d.Length < 1)
134 {
135 d = m_Database.Get(
136 new string[] { "ScopeID", "FirstName", "LastName" },
137 new string[] { UUID.Zero.ToString(), firstName, lastName });
138 }
139 }
140 else
141 {
142 d = m_Database.Get(
143 new string[] { "FirstName", "LastName" },
144 new string[] { firstName, lastName });
145 }
146
147 if (d.Length < 1)
148 return null;
149
150 return MakeUserAccount(d[0]);
151 }
152
153 private UserAccount MakeUserAccount(UserAccountData d)
154 {
155 UserAccount u = new UserAccount();
156 u.FirstName = d.FirstName;
157 u.LastName = d.LastName;
158 u.PrincipalID = d.PrincipalID;
159 u.ScopeID = d.ScopeID;
160 if (d.Data.ContainsKey("Email") && d.Data["Email"] != null)
161 u.Email = d.Data["Email"].ToString();
162 else
163 u.Email = string.Empty;
164 u.Created = Convert.ToInt32(d.Data["Created"].ToString());
165 if (d.Data.ContainsKey("UserTitle") && d.Data["UserTitle"] != null)
166 u.UserTitle = d.Data["UserTitle"].ToString();
167 else
168 u.UserTitle = string.Empty;
169 if (d.Data.ContainsKey("UserLevel") && d.Data["UserLevel"] != null)
170 Int32.TryParse(d.Data["UserLevel"], out u.UserLevel);
171 if (d.Data.ContainsKey("UserFlags") && d.Data["UserFlags"] != null)
172 Int32.TryParse(d.Data["UserFlags"], out u.UserFlags);
173 if (d.Data.ContainsKey("UserCountry") && d.Data["UserCountry"] != null)
174 u.UserCountry = d.Data["UserCountry"].ToString();
175 else
176 u.UserTitle = string.Empty;
177
178 if (d.Data.ContainsKey("ServiceURLs") && d.Data["ServiceURLs"] != null)
179 {
180 string[] URLs = d.Data["ServiceURLs"].ToString().Split(new char[] { ' ' });
181 u.ServiceURLs = new Dictionary<string, object>();
182
183 foreach (string url in URLs)
184 {
185 string[] parts = url.Split(new char[] { '=' });
186
187 if (parts.Length != 2)
188 continue;
189
190 string name = System.Web.HttpUtility.UrlDecode(parts[0]);
191 string val = System.Web.HttpUtility.UrlDecode(parts[1]);
192
193 u.ServiceURLs[name] = val;
194 }
195 }
196 else
197 u.ServiceURLs = new Dictionary<string, object>();
198
199 return u;
200 }
201
202 public UserAccount GetUserAccount(UUID scopeID, string email)
203 {
204 UserAccountData[] d;
205
206 if (scopeID != UUID.Zero)
207 {
208 d = m_Database.Get(
209 new string[] { "ScopeID", "Email" },
210 new string[] { scopeID.ToString(), email });
211 if (d.Length < 1)
212 {
213 d = m_Database.Get(
214 new string[] { "ScopeID", "Email" },
215 new string[] { UUID.Zero.ToString(), email });
216 }
217 }
218 else
219 {
220 d = m_Database.Get(
221 new string[] { "Email" },
222 new string[] { email });
223 }
224
225 if (d.Length < 1)
226 return null;
227
228 return MakeUserAccount(d[0]);
229 }
230
231 public UserAccount GetUserAccount(UUID scopeID, UUID principalID)
232 {
233 UserAccountData[] d;
234
235 if (scopeID != UUID.Zero)
236 {
237 d = m_Database.Get(
238 new string[] { "ScopeID", "PrincipalID" },
239 new string[] { scopeID.ToString(), principalID.ToString() });
240 if (d.Length < 1)
241 {
242 d = m_Database.Get(
243 new string[] { "ScopeID", "PrincipalID" },
244 new string[] { UUID.Zero.ToString(), principalID.ToString() });
245 }
246 }
247 else
248 {
249 d = m_Database.Get(
250 new string[] { "PrincipalID" },
251 new string[] { principalID.ToString() });
252 }
253
254 if (d.Length < 1)
255 {
256 return null;
257 }
258
259 return MakeUserAccount(d[0]);
260 }
261
262 public bool StoreUserAccount(UserAccount data)
263 {
264// m_log.DebugFormat(
265// "[USER ACCOUNT SERVICE]: Storing user account for {0} {1} {2}, scope {3}",
266// data.FirstName, data.LastName, data.PrincipalID, data.ScopeID);
267
268 UserAccountData d = new UserAccountData();
269
270 d.FirstName = data.FirstName;
271 d.LastName = data.LastName;
272 d.PrincipalID = data.PrincipalID;
273 d.ScopeID = data.ScopeID;
274 d.Data = new Dictionary<string, string>();
275 d.Data["Email"] = data.Email;
276 d.Data["Created"] = data.Created.ToString();
277 d.Data["UserLevel"] = data.UserLevel.ToString();
278 d.Data["UserFlags"] = data.UserFlags.ToString();
279 if (data.UserTitle != null)
280 d.Data["UserTitle"] = data.UserTitle.ToString();
281
282 List<string> parts = new List<string>();
283
284 foreach (KeyValuePair<string, object> kvp in data.ServiceURLs)
285 {
286 string key = System.Web.HttpUtility.UrlEncode(kvp.Key);
287 string val = System.Web.HttpUtility.UrlEncode(kvp.Value.ToString());
288 parts.Add(key + "=" + val);
289 }
290
291 d.Data["ServiceURLs"] = string.Join(" ", parts.ToArray());
292
293 return m_Database.Store(d);
294 }
295
296 public List<UserAccount> GetUserAccounts(UUID scopeID, string query)
297 {
298 UserAccountData[] d = m_Database.GetUsers(scopeID, query.Trim());
299
300 if (d == null)
301 return new List<UserAccount>();
302
303 List<UserAccount> ret = new List<UserAccount>();
304
305 foreach (UserAccountData data in d)
306 ret.Add(MakeUserAccount(data));
307
308 return ret;
309 }
310
311 public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
312 {
313 UserAccountData[] d = m_Database.GetUsersWhere(scopeID, where);
314
315 if (d == null)
316 return new List<UserAccount>();
317
318 List<UserAccount> ret = new List<UserAccount>();
319
320 foreach (UserAccountData data in d)
321 ret.Add(MakeUserAccount(data));
322
323 return ret;
324 }
325
326 #endregion
327
328 #region Console commands
329
330 /// <summary>
331 /// Handle the create user command from the console.
332 /// </summary>
333 /// <param name="cmdparams">string array with parameters: firstname, lastname, password, locationX, locationY, email</param>
334 protected void HandleCreateUser(string module, string[] cmdparams)
335 {
336 string firstName;
337 string lastName;
338 string password;
339 string email;
340 string rawPrincipalId;
341
342 List<char> excluded = new List<char>(new char[]{' '});
343
344 if (cmdparams.Length < 3)
345 firstName = MainConsole.Instance.CmdPrompt("First name", "Default", excluded);
346 else firstName = cmdparams[2];
347
348 if (cmdparams.Length < 4)
349 lastName = MainConsole.Instance.CmdPrompt("Last name", "User", excluded);
350 else lastName = cmdparams[3];
351
352 if (cmdparams.Length < 5)
353 password = MainConsole.Instance.PasswdPrompt("Password");
354 else password = cmdparams[4];
355
356 if (cmdparams.Length < 6)
357 email = MainConsole.Instance.CmdPrompt("Email", "");
358 else email = cmdparams[5];
359
360 if (cmdparams.Length < 7)
361 rawPrincipalId = MainConsole.Instance.CmdPrompt("User ID", UUID.Random().ToString());
362 else
363 rawPrincipalId = cmdparams[6];
364
365 UUID principalId = UUID.Zero;
366 if (!UUID.TryParse(rawPrincipalId, out principalId))
367 throw new Exception(string.Format("ID {0} is not a valid UUID", rawPrincipalId));
368
369 CreateUser(UUID.Zero, principalId, firstName, lastName, password, email);
370 }
371
372 protected void HandleShowAccount(string module, string[] cmdparams)
373 {
374 if (cmdparams.Length != 4)
375 {
376 MainConsole.Instance.Output("Usage: show account <first-name> <last-name>");
377 return;
378 }
379
380 string firstName = cmdparams[2];
381 string lastName = cmdparams[3];
382
383 UserAccount ua = GetUserAccount(UUID.Zero, firstName, lastName);
384
385 if (ua == null)
386 {
387 MainConsole.Instance.OutputFormat("No user named {0} {1}", firstName, lastName);
388 return;
389 }
390
391 MainConsole.Instance.OutputFormat("Name: {0}", ua.Name);
392 MainConsole.Instance.OutputFormat("ID: {0}", ua.PrincipalID);
393 MainConsole.Instance.OutputFormat("Title: {0}", ua.UserTitle);
394 MainConsole.Instance.OutputFormat("E-mail: {0}", ua.Email);
395 MainConsole.Instance.OutputFormat("Created: {0}", Utils.UnixTimeToDateTime(ua.Created));
396 MainConsole.Instance.OutputFormat("Level: {0}", ua.UserLevel);
397 MainConsole.Instance.OutputFormat("Flags: {0}", ua.UserFlags);
398 foreach (KeyValuePair<string, Object> kvp in ua.ServiceURLs)
399 MainConsole.Instance.OutputFormat("{0}: {1}", kvp.Key, kvp.Value);
400 }
401
402 protected void HandleResetUserPassword(string module, string[] cmdparams)
403 {
404 string firstName;
405 string lastName;
406 string newPassword;
407
408 if (cmdparams.Length < 4)
409 firstName = MainConsole.Instance.CmdPrompt("First name");
410 else firstName = cmdparams[3];
411
412 if (cmdparams.Length < 5)
413 lastName = MainConsole.Instance.CmdPrompt("Last name");
414 else lastName = cmdparams[4];
415
416 if (cmdparams.Length < 6)
417 newPassword = MainConsole.Instance.PasswdPrompt("New password");
418 else newPassword = cmdparams[5];
419
420 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
421 if (account == null)
422 {
423 MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName);
424 return;
425 }
426
427 bool success = false;
428 if (m_AuthenticationService != null)
429 success = m_AuthenticationService.SetPassword(account.PrincipalID, newPassword);
430
431 if (!success)
432 MainConsole.Instance.OutputFormat("Unable to reset password for account {0} {1}.", firstName, lastName);
433 else
434 MainConsole.Instance.OutputFormat("Password reset for user {0} {1}", firstName, lastName);
435 }
436
437 protected void HandleSetUserLevel(string module, string[] cmdparams)
438 {
439 string firstName;
440 string lastName;
441 string rawLevel;
442 int level;
443
444 if (cmdparams.Length < 4)
445 firstName = MainConsole.Instance.CmdPrompt("First name");
446 else firstName = cmdparams[3];
447
448 if (cmdparams.Length < 5)
449 lastName = MainConsole.Instance.CmdPrompt("Last name");
450 else lastName = cmdparams[4];
451
452 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
453 if (account == null) {
454 MainConsole.Instance.OutputFormat("No such user");
455 return;
456 }
457
458 if (cmdparams.Length < 6)
459 rawLevel = MainConsole.Instance.CmdPrompt("User level");
460 else rawLevel = cmdparams[5];
461
462 if(int.TryParse(rawLevel, out level) == false) {
463 MainConsole.Instance.OutputFormat("Invalid user level");
464 return;
465 }
466
467 account.UserLevel = level;
468
469 bool success = StoreUserAccount(account);
470 if (!success)
471 MainConsole.Instance.OutputFormat("Unable to set user level for account {0} {1}.", firstName, lastName);
472 else
473 MainConsole.Instance.OutputFormat("User level set for user {0} {1} to {2}", firstName, lastName, level);
474 }
475
476 #endregion
477
478 /// <summary>
479 /// Create a user
480 /// </summary>
481 /// <param name="scopeID">Allows hosting of multiple grids in a single database. Normally left as UUID.Zero</param>
482 /// <param name="principalID">ID of the user</param>
483 /// <param name="firstName"></param>
484 /// <param name="lastName"></param>
485 /// <param name="password"></param>
486 /// <param name="email"></param>
487 public UserAccount CreateUser(UUID scopeID, UUID principalID, string firstName, string lastName, string password, string email)
488 {
489 UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
490 if (null == account)
491 {
492 account = new UserAccount(UUID.Zero, principalID, firstName, lastName, email);
493 if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0))
494 {
495 account.ServiceURLs = new Dictionary<string, object>();
496 account.ServiceURLs["HomeURI"] = string.Empty;
497 account.ServiceURLs["GatekeeperURI"] = string.Empty;
498 account.ServiceURLs["InventoryServerURI"] = string.Empty;
499 account.ServiceURLs["AssetServerURI"] = string.Empty;
500 }
501
502 if (StoreUserAccount(account))
503 {
504 bool success;
505 if (m_AuthenticationService != null)
506 {
507 success = m_AuthenticationService.SetPassword(account.PrincipalID, password);
508 if (!success)
509 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set password for account {0} {1}.",
510 firstName, lastName);
511 }
512
513 GridRegion home = null;
514 if (m_GridService != null)
515 {
516 List<GridRegion> defaultRegions = m_GridService.GetDefaultRegions(UUID.Zero);
517 if (defaultRegions != null && defaultRegions.Count >= 1)
518 home = defaultRegions[0];
519
520 if (m_GridUserService != null && home != null)
521 m_GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
522 else
523 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to set home for account {0} {1}.",
524 firstName, lastName);
525 }
526 else
527 {
528 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to retrieve home region for account {0} {1}.",
529 firstName, lastName);
530 }
531
532 if (m_InventoryService != null)
533 {
534 success = m_InventoryService.CreateUserInventory(account.PrincipalID);
535 if (!success)
536 {
537 m_log.WarnFormat("[USER ACCOUNT SERVICE]: Unable to create inventory for account {0} {1}.",
538 firstName, lastName);
539 }
540 else
541 {
542 m_log.DebugFormat(
543 "[USER ACCOUNT SERVICE]; Created user inventory for {0} {1}", firstName, lastName);
544 }
545
546 if (m_CreateDefaultAvatarEntries)
547 CreateDefaultAppearanceEntries(account.PrincipalID);
548 }
549
550 m_log.InfoFormat(
551 "[USER ACCOUNT SERVICE]: Account {0} {1} {2} created successfully",
552 firstName, lastName, account.PrincipalID);
553 }
554 else
555 {
556 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: Account creation failed for account {0} {1}", firstName, lastName);
557 }
558 }
559 else
560 {
561 m_log.ErrorFormat("[USER ACCOUNT SERVICE]: A user with the name {0} {1} already exists!", firstName, lastName);
562 }
563
564 return account;
565 }
566
567 private void CreateDefaultAppearanceEntries(UUID principalID)
568 {
569 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID);
570
571 InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Bodypart);
572
573 InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID);
574 eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
575 eyes.Name = "Default Eyes";
576 eyes.CreatorId = principalID.ToString();
577 eyes.AssetType = (int)AssetType.Bodypart;
578 eyes.InvType = (int)InventoryType.Wearable;
579 eyes.Folder = bodyPartsFolder.ID;
580 eyes.BasePermissions = (uint)PermissionMask.All;
581 eyes.CurrentPermissions = (uint)PermissionMask.All;
582 eyes.EveryOnePermissions = (uint)PermissionMask.All;
583 eyes.GroupPermissions = (uint)PermissionMask.All;
584 eyes.NextPermissions = (uint)PermissionMask.All;
585 eyes.Flags = (uint)WearableType.Eyes;
586 m_InventoryService.AddItem(eyes);
587
588 InventoryItemBase shape = new InventoryItemBase(UUID.Random(), principalID);
589 shape.AssetID = AvatarWearable.DEFAULT_BODY_ASSET;
590 shape.Name = "Default Shape";
591 shape.CreatorId = principalID.ToString();
592 shape.AssetType = (int)AssetType.Bodypart;
593 shape.InvType = (int)InventoryType.Wearable;
594 shape.Folder = bodyPartsFolder.ID;
595 shape.BasePermissions = (uint)PermissionMask.All;
596 shape.CurrentPermissions = (uint)PermissionMask.All;
597 shape.EveryOnePermissions = (uint)PermissionMask.All;
598 shape.GroupPermissions = (uint)PermissionMask.All;
599 shape.NextPermissions = (uint)PermissionMask.All;
600 shape.Flags = (uint)WearableType.Shape;
601 m_InventoryService.AddItem(shape);
602
603 InventoryItemBase skin = new InventoryItemBase(UUID.Random(), principalID);
604 skin.AssetID = AvatarWearable.DEFAULT_SKIN_ASSET;
605 skin.Name = "Default Skin";
606 skin.CreatorId = principalID.ToString();
607 skin.AssetType = (int)AssetType.Bodypart;
608 skin.InvType = (int)InventoryType.Wearable;
609 skin.Folder = bodyPartsFolder.ID;
610 skin.BasePermissions = (uint)PermissionMask.All;
611 skin.CurrentPermissions = (uint)PermissionMask.All;
612 skin.EveryOnePermissions = (uint)PermissionMask.All;
613 skin.GroupPermissions = (uint)PermissionMask.All;
614 skin.NextPermissions = (uint)PermissionMask.All;
615 skin.Flags = (uint)WearableType.Skin;
616 m_InventoryService.AddItem(skin);
617
618 InventoryItemBase hair = new InventoryItemBase(UUID.Random(), principalID);
619 hair.AssetID = AvatarWearable.DEFAULT_HAIR_ASSET;
620 hair.Name = "Default Hair";
621 hair.CreatorId = principalID.ToString();
622 hair.AssetType = (int)AssetType.Bodypart;
623 hair.InvType = (int)InventoryType.Wearable;
624 hair.Folder = bodyPartsFolder.ID;
625 hair.BasePermissions = (uint)PermissionMask.All;
626 hair.CurrentPermissions = (uint)PermissionMask.All;
627 hair.EveryOnePermissions = (uint)PermissionMask.All;
628 hair.GroupPermissions = (uint)PermissionMask.All;
629 hair.NextPermissions = (uint)PermissionMask.All;
630 hair.Flags = (uint)WearableType.Hair;
631 m_InventoryService.AddItem(hair);
632
633 InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, AssetType.Clothing);
634
635 InventoryItemBase shirt = new InventoryItemBase(UUID.Random(), principalID);
636 shirt.AssetID = AvatarWearable.DEFAULT_SHIRT_ASSET;
637 shirt.Name = "Default Shirt";
638 shirt.CreatorId = principalID.ToString();
639 shirt.AssetType = (int)AssetType.Clothing;
640 shirt.InvType = (int)InventoryType.Wearable;
641 shirt.Folder = clothingFolder.ID;
642 shirt.BasePermissions = (uint)PermissionMask.All;
643 shirt.CurrentPermissions = (uint)PermissionMask.All;
644 shirt.EveryOnePermissions = (uint)PermissionMask.All;
645 shirt.GroupPermissions = (uint)PermissionMask.All;
646 shirt.NextPermissions = (uint)PermissionMask.All;
647 shirt.Flags = (uint)WearableType.Shirt;
648 m_InventoryService.AddItem(shirt);
649
650 InventoryItemBase pants = new InventoryItemBase(UUID.Random(), principalID);
651 pants.AssetID = AvatarWearable.DEFAULT_PANTS_ASSET;
652 pants.Name = "Default Pants";
653 pants.CreatorId = principalID.ToString();
654 pants.AssetType = (int)AssetType.Clothing;
655 pants.InvType = (int)InventoryType.Wearable;
656 pants.Folder = clothingFolder.ID;
657 pants.BasePermissions = (uint)PermissionMask.All;
658 pants.CurrentPermissions = (uint)PermissionMask.All;
659 pants.EveryOnePermissions = (uint)PermissionMask.All;
660 pants.GroupPermissions = (uint)PermissionMask.All;
661 pants.NextPermissions = (uint)PermissionMask.All;
662 pants.Flags = (uint)WearableType.Pants;
663 m_InventoryService.AddItem(pants);
664
665 if (m_AvatarService != null)
666 {
667 m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default avatar entries for {0}", principalID);
668
669 AvatarWearable[] wearables = new AvatarWearable[6];
670 wearables[AvatarWearable.EYES] = new AvatarWearable(eyes.ID, eyes.AssetID);
671 wearables[AvatarWearable.BODY] = new AvatarWearable(shape.ID, shape.AssetID);
672 wearables[AvatarWearable.SKIN] = new AvatarWearable(skin.ID, skin.AssetID);
673 wearables[AvatarWearable.HAIR] = new AvatarWearable(hair.ID, hair.AssetID);
674 wearables[AvatarWearable.SHIRT] = new AvatarWearable(shirt.ID, shirt.AssetID);
675 wearables[AvatarWearable.PANTS] = new AvatarWearable(pants.ID, pants.AssetID);
676
677 AvatarAppearance ap = new AvatarAppearance();
678 for (int i = 0; i < 6; i++)
679 {
680 ap.SetWearable(i, wearables[i]);
681 }
682
683 m_AvatarService.SetAppearance(principalID, ap);
684 }
685 }
686 }
687} \ No newline at end of file
diff --git a/OpenSim/Services/UserService/UserServiceBase.cs b/OpenSim/Services/UserAccountService/UserAccountServiceBase.cs
index fea8b01..c1a7b76 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