diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs index e8e577c7ba..3d6c9b7ecd 100644 --- a/OpenSim/Capabilities/Caps.cs +++ b/OpenSim/Capabilities/Caps.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Concurrent; using System.IO; using System.Reflection; using System.Threading; @@ -51,7 +52,7 @@ namespace OpenSim.Framework.Capabilities public class Caps { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private string m_httpListenerHostName; private uint m_httpListenPort; @@ -64,8 +65,8 @@ namespace OpenSim.Framework.Capabilities private CapsHandlers m_capsHandlers; - private Dictionary m_pollServiceHandlers - = new Dictionary(); + private ConcurrentDictionary m_pollServiceHandlers + = new ConcurrentDictionary(); private Dictionary m_externalCapsHandlers = new Dictionary(); @@ -181,9 +182,15 @@ namespace OpenSim.Framework.Capabilities // "[CAPS]: Registering handler with name {0}, url {1} for {2}", // capName, pollServiceHandler.Url, m_agentID, m_regionName); - m_pollServiceHandlers.Add(capName, pollServiceHandler); + if(!m_pollServiceHandlers.TryAdd(capName, pollServiceHandler)) + { + m_log.ErrorFormat( + "[CAPS]: Handler with name {0} already registered (ulr {1}, agent {2}, region {3}", + capName, pollServiceHandler.Url, m_agentID, m_regionName); + return; + } - m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler.Url, pollServiceHandler); + m_httpListener.AddPollServiceHTTPHandler(pollServiceHandler); // uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port; // string protocol = "http"; @@ -223,7 +230,7 @@ namespace OpenSim.Framework.Capabilities foreach (PollServiceEventArgs handler in m_pollServiceHandlers.Values) { - m_httpListener.RemovePollServiceHTTPHandler("", handler.Url); + m_httpListener.RemovePollServiceHTTPHandler(handler.Url); } m_pollServiceHandlers.Clear(); } diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index 889df36fe9..406752fa04 100755 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs @@ -426,8 +426,7 @@ namespace OpenSim.Framework.Console // This call is a CAP. The URL is the authentication. string uri = "/ReadResponses/" + sessionID.ToString() + "/"; - m_Server.AddPollServiceHTTPHandler( - uri, new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, null, sessionID,25000)); // 25 secs timeout + m_Server.AddPollServiceHTTPHandler(new PollServiceEventArgs(null, uri, HasEvents, GetEvents, NoEvents, null, sessionID,25000)); // 25 secs timeout // Our reply is an XML document. // TODO: Change this to Linq.Xml diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index f2faabbcc3..57ab23d575 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Globalization; using System.IO; using System.IO.Compression; @@ -97,11 +98,11 @@ namespace OpenSim.Framework.Servers.HttpServer protected Dictionary m_rpcHandlersKeepAlive = new Dictionary(); protected DefaultLLSDMethod m_defaultLlsdHandler = null; // <-- Moving away from the monolithic.. and going to /registered/ protected Dictionary m_llsdHandlers = new Dictionary(); - protected Dictionary m_streamHandlers = new Dictionary(); + protected ConcurrentDictionary m_streamHandlers = new ConcurrentDictionary(); protected Dictionary m_HTTPHandlers = new Dictionary(); // protected Dictionary m_agentHandlers = new Dictionary(); - protected Dictionary m_pollHandlers = - new Dictionary(); + protected ConcurrentDictionary m_pollHandlers = + new ConcurrentDictionary(); protected Dictionary m_WebSocketHandlers = new Dictionary(); @@ -328,14 +329,17 @@ namespace OpenSim.Framework.Servers.HttpServer string path = handler.Path; string handlerKey = GetHandlerKey(httpMethod, path); - lock (m_streamHandlers) - { - if (!m_streamHandlers.ContainsKey(handlerKey)) - { // m_log.DebugFormat("[BASE HTTP SERVER]: Adding handler key {0}", handlerKey); - m_streamHandlers.Add(handlerKey, handler); - } - } + m_streamHandlers.TryAdd(handlerKey, handler); + } + + public void AddGenericStreamHandler(IRequestHandler handler) + { + if(String.IsNullOrWhiteSpace(handler.Path)) + return; + + // m_log.DebugFormat("[BASE HTTP SERVER]: Adding handler key {0}", handlerKey); + m_streamHandlers.TryAdd(handler.Path, handler); } public void AddWebSocketHandler(string servicepath, WebSocketRequestDelegate handler) @@ -356,8 +360,7 @@ namespace OpenSim.Framework.Servers.HttpServer public List GetStreamHandlerKeys() { - lock (m_streamHandlers) - return new List(m_streamHandlers.Keys); + return new List(m_streamHandlers.Keys); } private static string GetHandlerKey(string httpMethod, string path) @@ -456,24 +459,19 @@ namespace OpenSim.Framework.Servers.HttpServer return new List(m_HTTPHandlers.Keys); } - public bool AddPollServiceHTTPHandler(string methodName, PollServiceEventArgs args) + public bool AddPollServiceHTTPHandler(string url, PollServiceEventArgs args) { - lock (m_pollHandlers) - { - if (!m_pollHandlers.ContainsKey(methodName)) - { - m_pollHandlers.Add(methodName, args); - return true; - } - } + return m_pollHandlers.TryAdd(url, args); + } - return false; + public bool AddPollServiceHTTPHandler(PollServiceEventArgs args) + { + return m_pollHandlers.TryAdd(args.Url, args); } public List GetPollServiceHandlerKeys() { - lock (m_pollHandlers) - return new List(m_pollHandlers.Keys); + return new List(m_pollHandlers.Keys); } // // Note that the agent string is provided simply to differentiate @@ -533,7 +531,7 @@ namespace OpenSim.Framework.Servers.HttpServer IHttpClientContext context = (IHttpClientContext)source; IHttpRequest request = args.Request; - if (TryGetPollServiceHTTPHandler(request.UriPath.ToString(), out PollServiceEventArgs psEvArgs)) + if (TryGetPollServiceHTTPHandler(request.UriPath, out PollServiceEventArgs psEvArgs)) { psEvArgs.RequestsReceived++; PollServiceHttpRequest psreq = new PollServiceHttpRequest(psEvArgs, context, request); @@ -567,15 +565,7 @@ namespace OpenSim.Framework.Servers.HttpServer } OSHttpResponse resp = new OSHttpResponse(new HttpResponse(context, request)); - HandleRequest(req, resp); - - // !!!HACK ALERT!!! - // There seems to be a bug in the underlying http code that makes subsequent requests - // come up with trash in Accept headers. Until that gets fixed, we're cleaning them up here. - if (request.AcceptTypes != null) - for (int i = 0; i < request.AcceptTypes.Length; i++) - request.AcceptTypes[i] = string.Empty; } /// @@ -999,6 +989,9 @@ namespace OpenSim.Framework.Servers.HttpServer private bool TryGetPollServiceHTTPHandler(string handlerKey, out PollServiceEventArgs oServiceEventArgs) { + if(m_pollHandlers.TryGetValue(handlerKey, out oServiceEventArgs)) + return true; + string bestMatch = null; lock (m_pollHandlers) @@ -2109,12 +2102,19 @@ namespace OpenSim.Framework.Servers.HttpServer public void RemoveStreamHandler(string httpMethod, string path) { + if (m_streamHandlers.TryRemove(path, out IRequestHandler dummy)) + return; + string handlerKey = GetHandlerKey(httpMethod, path); //m_log.DebugFormat("[BASE HTTP SERVER]: Removing handler key {0}", handlerKey); - lock (m_streamHandlers) - m_streamHandlers.Remove(handlerKey); + m_streamHandlers.TryRemove(handlerKey, out dummy); + } + + public void RemoveStreamHandler(string path) + { + m_streamHandlers.TryRemove(path, out IRequestHandler dummy); } public void RemoveHTTPHandler(string httpMethod, string path) @@ -2134,25 +2134,29 @@ namespace OpenSim.Framework.Servers.HttpServer public void RemovePollServiceHTTPHandler(string httpMethod, string path) { - lock (m_pollHandlers) - m_pollHandlers.Remove(path); + m_pollHandlers.TryRemove(path, out PollServiceEventArgs dummy); } -// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) -// { -// lock (m_agentHandlers) -// { -// IHttpAgentHandler foundHandler; -// -// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) -// { -// m_agentHandlers.Remove(agent); -// return true; -// } -// } -// -// return false; -// } + public void RemovePollServiceHTTPHandler(string path) + { + m_pollHandlers.TryRemove(path, out PollServiceEventArgs dummy); + } + + // public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) + // { + // lock (m_agentHandlers) + // { + // IHttpAgentHandler foundHandler; + // + // if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) + // { + // m_agentHandlers.Remove(agent); + // return true; + // } + // } + // + // return false; + // } public void RemoveXmlRPCHandler(string method) { diff --git a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs index 01d95e916a..857705e49b 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseRequestHandler.cs @@ -62,24 +62,6 @@ namespace OpenSim.Framework.Servers.HttpServer Description = description; m_httpMethod = httpMethod; m_path = path; - - // FIXME: A very temporary measure to stop the simulator stats being overwhelmed with user CAPS info. - // Needs to be fixed properly in stats display - if (!path.StartsWith("/CAPS/")) - { - StatsManager.RegisterStat( - new Stat( - "requests", - "requests", - "Number of requests received by this service endpoint", - "requests", - "service", - string.Format("{0}:{1}", httpMethod, path), - StatType.Pull, - MeasuresOfInterest.AverageChangeOverTime, - s => s.Value = RequestsReceived, - StatVerbosity.Debug)); - } } public virtual string Path diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs index ea81d0c06a..abab47f535 100755 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetAssetsModule.cs @@ -399,7 +399,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); //args.Type = PollServiceEventArgs.EventType.Texture; - MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + MainServer.Instance.AddPollServiceHTTPHandler(args); if (handler != null) handler.RegisterExternalUserCapsHandler(agentID, caps, "GetTexture", capUrl); @@ -419,7 +419,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); //args.Type = PollServiceEventArgs.EventType.Mesh; - MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + MainServer.Instance.AddPollServiceHTTPHandler(args); if (handler != null) handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh", capUrl); @@ -437,7 +437,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); //args.Type = PollServiceEventArgs.EventType.Mesh2; - MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + MainServer.Instance.AddPollServiceHTTPHandler(args); if (handler != null) handler.RegisterExternalUserCapsHandler(agentID, caps, "GetMesh2", capUrl); @@ -456,7 +456,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceAssetEventArgs args = new PollServiceAssetEventArgs(capUrl, agentID, m_scene); //args.Type = PollServiceEventArgs.EventType.Asset; - MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); + MainServer.Instance.AddPollServiceHTTPHandler(args); if (handler != null) handler.RegisterExternalUserCapsHandler(agentID, caps, "ViewerAsset", capUrl); @@ -473,23 +473,23 @@ namespace OpenSim.Region.ClientStack.Linden string capUrl; if (m_capsDictTexture.TryGetValue(agentID, out capUrl)) { - MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); + MainServer.Instance.RemovePollServiceHTTPHandler(capUrl); m_capsDictTexture.Remove(agentID); } if (m_capsDictGetMesh.TryGetValue(agentID, out capUrl)) { - MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); + MainServer.Instance.RemovePollServiceHTTPHandler(capUrl); m_capsDictGetMesh.Remove(agentID); } if (m_capsDictGetMesh2.TryGetValue(agentID, out capUrl)) { - MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); + MainServer.Instance.RemovePollServiceHTTPHandler(capUrl); m_capsDictGetMesh2.Remove(agentID); } if (m_capsDictGetAsset.TryGetValue(agentID, out capUrl)) { - MainServer.Instance.RemovePollServiceHTTPHandler("", capUrl); + MainServer.Instance.RemovePollServiceHTTPHandler(capUrl); m_capsDictGetAsset.Remove(agentID); } } diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 91a92ceaac..ad560d0522 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -262,7 +262,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000); //args.Type = PollServiceEventArgs.EventType.LslHttp; - m_HttpServer.AddPollServiceHTTPHandler(uri, args); + m_HttpServer.AddPollServiceHTTPHandler(args); // m_log.DebugFormat( // "[URL MODULE]: Set up incoming request url {0} for {1} in {2} {3}", @@ -320,7 +320,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp PollServiceEventArgs args = new PollServiceEventArgs(HttpRequestHandler, uri, HasEvents, GetEvents, NoEvents, Drop, urlcode, 25000); //args.Type = PollServiceEventArgs.EventType.LslHttp; - m_HttpsServer.AddPollServiceHTTPHandler(uri, args); + m_HttpsServer.AddPollServiceHTTPHandler(args); // m_log.DebugFormat( // "[URL MODULE]: Set up incoming secure request url {0} for {1} in {2} {3}",