From: Alan Webb <alan_webb@us.ibm.com>
cleanups and assorted fixes to REST inventory, asset, and appearance services.0.6.0-stable
parent
1fc6872f20
commit
12042cdc2b
|
@ -42,11 +42,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path);
|
public delegate RequestData RestMethodAllocator(OSHttpRequest request, OSHttpResponse response, string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This interface represents the boundary between the general purpose
|
/// This interface exports the generic plugin-handling services
|
||||||
/// REST plugin handling, and the functionally specific handlers. The
|
/// available to each loaded REST services module (IRest implementation)
|
||||||
/// handler knows only to initialize and terminate all such handlers
|
|
||||||
/// that it finds. Implementing this interface identifies the class as
|
|
||||||
/// a REST handler implementation.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
internal interface IRestHandler
|
internal interface IRestHandler
|
||||||
|
|
|
@ -167,7 +167,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
//
|
//
|
||||||
|
|
||||||
internal bool authenticated = false;
|
internal bool authenticated = false;
|
||||||
internal string scheme = null;
|
internal string scheme = Rest.Scheme;
|
||||||
internal string realm = Rest.Realm;
|
internal string realm = Rest.Realm;
|
||||||
internal string domain = null;
|
internal string domain = null;
|
||||||
internal string nonce = null;
|
internal string nonce = null;
|
||||||
|
@ -292,6 +292,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
sbuilder.Length = 0;
|
sbuilder.Length = 0;
|
||||||
|
|
||||||
encoding = request.ContentEncoding;
|
encoding = request.ContentEncoding;
|
||||||
|
|
||||||
if (encoding == null)
|
if (encoding == null)
|
||||||
{
|
{
|
||||||
encoding = Rest.Encoding;
|
encoding = Rest.Encoding;
|
||||||
|
@ -448,9 +449,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
if (realm != null)
|
if (realm != null)
|
||||||
{
|
{
|
||||||
sbuilder.Append(" realm=\"");
|
sbuilder.Append(" realm=");
|
||||||
|
sbuilder.Append(Rest.CS_DQUOTE);
|
||||||
sbuilder.Append(realm);
|
sbuilder.Append(realm);
|
||||||
sbuilder.Append("\"");
|
sbuilder.Append(Rest.CS_DQUOTE);
|
||||||
}
|
}
|
||||||
AddHeader(Rest.HttpHeaderWWWAuthenticate,sbuilder.ToString());
|
AddHeader(Rest.HttpHeaderWWWAuthenticate,sbuilder.ToString());
|
||||||
}
|
}
|
||||||
|
@ -677,7 +679,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
UserProfileData udata = Rest.UserServices.GetUserProfile(first, last);
|
UserProfileData udata = Rest.UserServices.GetUserProfile(first, last);
|
||||||
|
|
||||||
// If we don;t recognize the user id, perhaps it is god?
|
// If we don't recognize the user id, perhaps it is god?
|
||||||
|
|
||||||
if (udata == null)
|
if (udata == null)
|
||||||
return pass == Rest.GodKey;
|
return pass == Rest.GodKey;
|
||||||
|
@ -800,6 +802,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
if (!authparms.ContainsKey("cnonce"))
|
if (!authparms.ContainsKey("cnonce"))
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId);
|
Rest.Log.WarnFormat("{0} Authentication failed: cnonce missing", MsgId);
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,6 +811,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
if (!authparms.TryGetValue("nc", out nck) || nck == null)
|
if (!authparms.TryGetValue("nc", out nck) || nck == null)
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId);
|
Rest.Log.WarnFormat("{0} Authentication failed: cnonce counter missing", MsgId);
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,6 +824,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck))
|
if (Rest.Hex2Int(ncl) >= Rest.Hex2Int(nck))
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId);
|
Rest.Log.WarnFormat("{0} Authentication failed: bad cnonce counter", MsgId);
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cntable[nonce] = nck;
|
cntable[nonce] = nck;
|
||||||
|
@ -840,11 +845,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
if (authparms.ContainsKey("cnonce"))
|
if (authparms.ContainsKey("cnonce"))
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId);
|
Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce", MsgId);
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (authparms.ContainsKey("nc"))
|
if (authparms.ContainsKey("nc"))
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId);
|
Rest.Log.WarnFormat("{0} Authentication failed: invalid cnonce counter[2]", MsgId);
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -857,6 +864,8 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
while (false);
|
while (false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Fail(Rest.HttpStatusCodeBadRequest);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,21 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
internal static bool DEBUG = Log.IsDebugEnabled;
|
internal static bool DEBUG = Log.IsDebugEnabled;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supported authentication schemes
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
public const string AS_BASIC = "Basic"; // simple user/password verification
|
||||||
|
public const string AS_DIGEST = "Digest"; // password safe authentication
|
||||||
|
|
||||||
|
/// Supported Digest algorithms
|
||||||
|
|
||||||
|
public const string Digest_MD5 = "MD5"; // assumed default if omitted
|
||||||
|
public const string Digest_MD5Sess = "MD5-sess"; // session-span - not good for REST?
|
||||||
|
|
||||||
|
public const string Qop_Auth = "auth"; // authentication only
|
||||||
|
public const string Qop_Int = "auth-int"; // TODO
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// These values have a single value for the whole
|
/// These values have a single value for the whole
|
||||||
/// domain and lifetime of the plugin handler. We
|
/// domain and lifetime of the plugin handler. We
|
||||||
|
@ -67,9 +82,10 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
internal static bool Secure = true;
|
internal static bool Secure = true;
|
||||||
internal static bool ExtendedEscape = true;
|
internal static bool ExtendedEscape = true;
|
||||||
internal static bool DumpAsset = false;
|
internal static bool DumpAsset = false;
|
||||||
internal static bool Fill = true;
|
internal static bool Fill = false;
|
||||||
internal static bool FlushEnabled = true;
|
internal static bool FlushEnabled = true;
|
||||||
internal static string Realm = "REST";
|
internal static string Realm = "OpenSim REST";
|
||||||
|
internal static string Scheme = AS_BASIC;
|
||||||
internal static int DumpLineSize = 32; // Should be a multiple of 16 or (possibly) 4
|
internal static int DumpLineSize = 32; // Should be a multiple of 16 or (possibly) 4
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -383,21 +399,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
public const string HttpHeaderWarning = "Warning";
|
public const string HttpHeaderWarning = "Warning";
|
||||||
public const string HttpHeaderWWWAuthenticate = "WWW-Authenticate";
|
public const string HttpHeaderWWWAuthenticate = "WWW-Authenticate";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Supported authentication schemes
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
public const string AS_BASIC = "Basic";
|
|
||||||
public const string AS_DIGEST = "Digest";
|
|
||||||
|
|
||||||
/// Supported Digest algorithms
|
|
||||||
|
|
||||||
public const string Digest_MD5 = "MD5"; // assumed default if omitted
|
|
||||||
public const string Digest_MD5Sess = "MD5-sess";
|
|
||||||
|
|
||||||
public const string Qop_Auth = "auth";
|
|
||||||
public const string Qop_Int = "auth-int";
|
|
||||||
|
|
||||||
/// Utility routines
|
/// Utility routines
|
||||||
|
|
||||||
public static string StringToBase64(string str)
|
public static string StringToBase64(string str)
|
||||||
|
|
|
@ -63,6 +63,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId);
|
Rest.Log.InfoFormat("{0} User appearance services initializing", MsgId);
|
||||||
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
||||||
|
|
||||||
|
// This is better than a null reference.
|
||||||
|
|
||||||
|
if (Rest.AvatarServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim inventory services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
|
if (Rest.UserServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim user profile services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
// If a relative path was specified for the handler's domain,
|
// If a relative path was specified for the handler's domain,
|
||||||
// add the standard prefix to make it absolute, e.g. /admin
|
// add the standard prefix to make it absolute, e.g. /admin
|
||||||
|
|
||||||
|
@ -170,9 +180,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// digest scheme seems borked: disable it for the time
|
|
||||||
// being
|
|
||||||
rdata.scheme = Rest.AS_BASIC;
|
|
||||||
if (!rdata.IsAuthenticated)
|
if (!rdata.IsAuthenticated)
|
||||||
{
|
{
|
||||||
rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
|
rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
|
||||||
|
@ -731,7 +738,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
if (asset != UUID.Zero)
|
if (asset != UUID.Zero)
|
||||||
{
|
{
|
||||||
rdata.writer.WriteAttributeString("Item",asset.ToString());
|
rdata.writer.WriteAttributeString("Asset",asset.ToString());
|
||||||
}
|
}
|
||||||
rdata.writer.WriteEndElement();
|
rdata.writer.WriteEndElement();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,12 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
Rest.Log.InfoFormat("{0} Asset services initializing", MsgId);
|
Rest.Log.InfoFormat("{0} Asset services initializing", MsgId);
|
||||||
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
||||||
|
|
||||||
|
// This is better than a null reference.
|
||||||
|
|
||||||
|
if (Rest.AssetServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim asset services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
// If the handler specifies a relative path for its domain
|
// If the handler specifies a relative path for its domain
|
||||||
// then we must add the standard absolute prefix, e.g. /admin
|
// then we must add the standard absolute prefix, e.g. /admin
|
||||||
|
|
||||||
|
@ -130,9 +136,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// digest scheme seems borked: disable it for the time
|
|
||||||
// being
|
|
||||||
rdata.scheme = Rest.AS_BASIC;
|
|
||||||
if (!rdata.IsAuthenticated)
|
if (!rdata.IsAuthenticated)
|
||||||
{
|
{
|
||||||
rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
|
rdata.Fail(Rest.HttpStatusCodeNotAuthorized, String.Format("user \"{0}\" could not be authenticated"));
|
||||||
|
|
|
@ -239,14 +239,17 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
Rest.Prefix = Prefix;
|
Rest.Prefix = Prefix;
|
||||||
Rest.GodKey = GodKey;
|
Rest.GodKey = GodKey;
|
||||||
|
|
||||||
Rest.Authenticate = Rest.Config.GetBoolean("authenticate",true);
|
Rest.Authenticate = Rest.Config.GetBoolean("authenticate", Rest.Authenticate);
|
||||||
Rest.Secure = Rest.Config.GetBoolean("secured",true);
|
Rest.Scheme = Rest.Config.GetString("auth-scheme", Rest.Scheme);
|
||||||
Rest.ExtendedEscape = Rest.Config.GetBoolean("extended-escape",true);
|
Rest.Secure = Rest.Config.GetBoolean("secured", Rest.Secure);
|
||||||
Rest.Realm = Rest.Config.GetString("realm","OpenSim REST");
|
Rest.ExtendedEscape = Rest.Config.GetBoolean("extended-escape", Rest.ExtendedEscape);
|
||||||
Rest.DumpAsset = Rest.Config.GetBoolean("dump-asset",false);
|
Rest.Realm = Rest.Config.GetString("realm", Rest.Realm);
|
||||||
Rest.Fill = Rest.Config.GetBoolean("path-fill",true);
|
Rest.DumpAsset = Rest.Config.GetBoolean("dump-asset", Rest.DumpAsset);
|
||||||
Rest.DumpLineSize = Rest.Config.GetInt("dump-line-size",32);
|
Rest.Fill = Rest.Config.GetBoolean("path-fill", Rest.Fill);
|
||||||
Rest.FlushEnabled = Rest.Config.GetBoolean("flush-on-error",true);
|
Rest.DumpLineSize = Rest.Config.GetInt("dump-line-size", Rest.DumpLineSize);
|
||||||
|
Rest.FlushEnabled = Rest.Config.GetBoolean("flush-on-error", Rest.FlushEnabled);
|
||||||
|
|
||||||
|
// Note: Odd spacing is required in the following strings
|
||||||
|
|
||||||
Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId,
|
Rest.Log.InfoFormat("{0} Authentication is {1}required", MsgId,
|
||||||
(Rest.Authenticate ? "" : "not "));
|
(Rest.Authenticate ? "" : "not "));
|
||||||
|
@ -374,13 +377,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
string path = request.RawUrl.ToLower();
|
string path = request.RawUrl.ToLower();
|
||||||
|
|
||||||
Rest.Log.DebugFormat("{0} Match ENTRY", MsgId);
|
// Rest.Log.DebugFormat("{0} Match ENTRY", MsgId);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (string key in pathHandlers.Keys)
|
foreach (string key in pathHandlers.Keys)
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key);
|
// Rest.Log.DebugFormat("{0} Match testing {1} against agent prefix <{2}>", MsgId, path, key);
|
||||||
|
|
||||||
// Note that Match will not necessarily find the handler that will
|
// Note that Match will not necessarily find the handler that will
|
||||||
// actually be used - it does no test for the "closest" fit. It
|
// actually be used - it does no test for the "closest" fit. It
|
||||||
|
@ -388,7 +391,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
if (path.StartsWith(key))
|
if (path.StartsWith(key))
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
|
// Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
|
||||||
|
|
||||||
// This apparently odd evaluation is needed to prevent a match
|
// This apparently odd evaluation is needed to prevent a match
|
||||||
// on anything other than a URI token boundary. Otherwise we
|
// on anything other than a URI token boundary. Otherwise we
|
||||||
|
@ -404,7 +407,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
foreach (string key in streamHandlers.Keys)
|
foreach (string key in streamHandlers.Keys)
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key);
|
// Rest.Log.DebugFormat("{0} Match testing {1} against stream prefix <{2}>", MsgId, path, key);
|
||||||
|
|
||||||
// Note that Match will not necessarily find the handler that will
|
// Note that Match will not necessarily find the handler that will
|
||||||
// actually be used - it does no test for the "closest" fit. It
|
// actually be used - it does no test for the "closest" fit. It
|
||||||
|
@ -412,7 +415,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
if (path.StartsWith(key))
|
if (path.StartsWith(key))
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
|
// Rest.Log.DebugFormat("{0} Matched prefix <{1}>", MsgId, key);
|
||||||
|
|
||||||
// This apparently odd evaluation is needed to prevent a match
|
// This apparently odd evaluation is needed to prevent a match
|
||||||
// on anything other than a URI token boundary. Otherwise we
|
// on anything other than a URI token boundary. Otherwise we
|
||||||
|
@ -434,7 +437,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is called by the HTTP server once the handler has indicated
|
/// This is called by the HTTP server once the handler has indicated
|
||||||
/// that t is able to handle the request.
|
/// that it is able to handle the request.
|
||||||
/// Preconditions:
|
/// Preconditions:
|
||||||
/// [1] request != null and is a valid request object
|
/// [1] request != null and is a valid request object
|
||||||
/// [2] response != null and is a valid response object
|
/// [2] response != null and is a valid response object
|
||||||
|
@ -474,7 +477,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
{
|
{
|
||||||
// A raw exception indicates that something we weren't expecting has
|
// A raw exception indicates that something we weren't expecting has
|
||||||
// happened. This should always reflect a shortcoming in the plugin,
|
// happened. This should always reflect a shortcoming in the plugin,
|
||||||
// or a failure to satisfy the preconditions.
|
// or a failure to satisfy the preconditions. It should not reflect
|
||||||
|
// an error in the request itself. Under such circumstances the state
|
||||||
|
// of the request cannot be determined and we are obliged to mark it
|
||||||
|
// as 'handled'.
|
||||||
|
|
||||||
Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message);
|
Rest.Log.ErrorFormat("{0} Plugin error: {1}", MsgId, e.Message);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
@ -497,7 +504,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
{
|
{
|
||||||
RequestData rdata = new RequestData(request, response, String.Empty);
|
RequestData rdata = new RequestData(request, response, String.Empty);
|
||||||
|
|
||||||
string bestMatch = null;
|
string bestMatch = String.Empty;
|
||||||
string path = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower();
|
string path = String.Format("{0}:{1}", rdata.method, rdata.path).ToLower();
|
||||||
|
|
||||||
Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path);
|
Rest.Log.DebugFormat("{0} Checking for stream handler for <{1}>", MsgId, path);
|
||||||
|
@ -511,7 +518,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
{
|
{
|
||||||
if (path.StartsWith(pattern))
|
if (path.StartsWith(pattern))
|
||||||
{
|
{
|
||||||
if (String.IsNullOrEmpty(bestMatch) || pattern.Length > bestMatch.Length)
|
if (pattern.Length > bestMatch.Length)
|
||||||
{
|
{
|
||||||
bestMatch = pattern;
|
bestMatch = pattern;
|
||||||
}
|
}
|
||||||
|
@ -520,7 +527,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
// Handle using the best match available
|
// Handle using the best match available
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(bestMatch))
|
if (bestMatch.Length > 0)
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch);
|
Rest.Log.DebugFormat("{0} Stream-based handler matched with <{1}>", MsgId, bestMatch);
|
||||||
RestStreamHandler handler = streamHandlers[bestMatch];
|
RestStreamHandler handler = streamHandlers[bestMatch];
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
using System.Timers;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Framework.Servers;
|
using OpenSim.Framework.Servers;
|
||||||
using OpenSim.Framework.Communications;
|
using OpenSim.Framework.Communications;
|
||||||
|
@ -61,6 +62,20 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId);
|
Rest.Log.InfoFormat("{0} Inventory services initializing", MsgId);
|
||||||
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
Rest.Log.InfoFormat("{0} Using REST Implementation Version {1}", MsgId, Rest.Version);
|
||||||
|
|
||||||
|
// This is better than a null reference.
|
||||||
|
|
||||||
|
if (Rest.InventoryServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim inventory services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
|
if (Rest.UserServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim user services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
|
if (Rest.AssetServices == null)
|
||||||
|
throw new Exception(String.Format("{0} OpenSim asset services are not available",
|
||||||
|
MsgId));
|
||||||
|
|
||||||
// If a relative path was specified for the handler's domain,
|
// If a relative path was specified for the handler's domain,
|
||||||
// add the standard prefix to make it absolute, e.g. /admin
|
// add the standard prefix to make it absolute, e.g. /admin
|
||||||
|
|
||||||
|
@ -167,9 +182,6 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// digest scheme seems borked: disable it for the time
|
|
||||||
// being
|
|
||||||
rdata.scheme = Rest.AS_BASIC;
|
|
||||||
if (!rdata.IsAuthenticated)
|
if (!rdata.IsAuthenticated)
|
||||||
{
|
{
|
||||||
rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
|
rdata.Fail(Rest.HttpStatusCodeNotAuthorized,String.Format("user \"{0}\" could not be authenticated", rdata.userName));
|
||||||
|
@ -283,14 +295,24 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}",
|
Rest.Log.DebugFormat("{0} Inventory catalog requested for {1} {2}",
|
||||||
MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
|
MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
|
||||||
|
|
||||||
|
|
||||||
lock (rdata)
|
lock (rdata)
|
||||||
{
|
{
|
||||||
if (!rdata.HaveInventory)
|
if (!rdata.HaveInventory)
|
||||||
{
|
{
|
||||||
|
rdata.startWD(1000);
|
||||||
|
rdata.timeout = false;
|
||||||
Monitor.Wait(rdata);
|
Monitor.Wait(rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rdata.timeout)
|
||||||
|
{
|
||||||
|
Rest.Log.WarnFormat("{0} Inventory not available for {1} {2}. No response from service.",
|
||||||
|
MsgId, rdata.userProfile.FirstName, rdata.userProfile.SurName);
|
||||||
|
rdata.Fail(Rest.HttpStatusCodeServerError, "inventory server not responding");
|
||||||
|
}
|
||||||
|
|
||||||
if (rdata.root == null)
|
if (rdata.root == null)
|
||||||
{
|
{
|
||||||
Rest.Log.WarnFormat("{0} Inventory is not available [1] for agent {1} {2}",
|
Rest.Log.WarnFormat("{0} Inventory is not available [1] for agent {1} {2}",
|
||||||
|
@ -2145,12 +2167,50 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
internal ICollection<InventoryItemBase> items = null;
|
internal ICollection<InventoryItemBase> items = null;
|
||||||
internal UserProfileData userProfile = null;
|
internal UserProfileData userProfile = null;
|
||||||
internal InventoryFolderBase root = null;
|
internal InventoryFolderBase root = null;
|
||||||
|
internal bool timeout = false;
|
||||||
|
internal System.Timers.Timer watchDog = new System.Timers.Timer();
|
||||||
|
|
||||||
internal InventoryRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
|
internal InventoryRequestData(OSHttpRequest request, OSHttpResponse response, string prefix)
|
||||||
: base(request, response, prefix)
|
: base(request, response, prefix)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void startWD(double interval)
|
||||||
|
{
|
||||||
|
Rest.Log.DebugFormat("{0} Setting watchdog", MsgId);
|
||||||
|
watchDog.Elapsed += new ElapsedEventHandler(OnTimeOut);
|
||||||
|
watchDog.Interval = interval;
|
||||||
|
watchDog.AutoReset = false;
|
||||||
|
watchDog.Enabled = true;
|
||||||
|
watchDog.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void stopWD()
|
||||||
|
{
|
||||||
|
Rest.Log.DebugFormat("{0} Reset watchdog", MsgId);
|
||||||
|
watchDog.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the callback method required by the inventory watchdog. The
|
||||||
|
/// requestor issues an inventory request and then blocks until the
|
||||||
|
/// request completes, or this method signals the monitor.
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
private void OnTimeOut(object sender, ElapsedEventArgs args)
|
||||||
|
{
|
||||||
|
Rest.Log.DebugFormat("{0} Asynchronous inventory update timed-out", MsgId);
|
||||||
|
// InventoryRequestData rdata = (InventoryRequestData) sender;
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
this.folders = null;
|
||||||
|
this.items = null;
|
||||||
|
this.HaveInventory = false;
|
||||||
|
this.timeout = true;
|
||||||
|
Monitor.Pulse(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is the callback method required by inventory services. The
|
/// This is the callback method required by inventory services. The
|
||||||
/// requestor issues an inventory request and then blocks until this
|
/// requestor issues an inventory request and then blocks until this
|
||||||
|
@ -2160,11 +2220,16 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
|
||||||
internal void GetUserInventory(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items)
|
internal void GetUserInventory(ICollection<InventoryFolderImpl> folders, ICollection<InventoryItemBase> items)
|
||||||
{
|
{
|
||||||
Rest.Log.DebugFormat("{0} Asynchronously updating inventory data", MsgId);
|
Rest.Log.DebugFormat("{0} Asynchronously updating inventory data", MsgId);
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (watchDog.Enabled)
|
||||||
|
{
|
||||||
|
this.stopWD();
|
||||||
|
}
|
||||||
this.folders = folders;
|
this.folders = folders;
|
||||||
this.items = items;
|
this.items = items;
|
||||||
this.HaveInventory = true;
|
this.HaveInventory = true;
|
||||||
lock (this)
|
this.timeout = false;
|
||||||
{
|
|
||||||
Monitor.Pulse(this);
|
Monitor.Pulse(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,9 +178,15 @@ namespace OpenSim.Framework.Communications.Cache
|
||||||
if (libraryFolders.ContainsKey(item.Folder))
|
if (libraryFolders.ContainsKey(item.Folder))
|
||||||
{
|
{
|
||||||
InventoryFolderImpl parentFolder = libraryFolders[item.Folder];
|
InventoryFolderImpl parentFolder = libraryFolders[item.Folder];
|
||||||
|
try
|
||||||
|
{
|
||||||
parentFolder.Items.Add(item.ID, item);
|
parentFolder.Items.Add(item.ID, item);
|
||||||
}
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
m_log.WarnFormat("[LIBRARY INVENTORY] Item {1} [{0}] not added, duplicate item", item.ID, item.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
|
|
Loading…
Reference in New Issue