Luke Pulverenti 7 年之前
父节点
当前提交
0f23c7cfc1

+ 2 - 2
Emby.Server.Implementations/ApplicationHost.cs

@@ -1614,7 +1614,7 @@ namespace Emby.Server.Implementations
         {
         {
             try
             try
             {
             {
-                ServerManager.Start(GetUrlPrefixes());
+                ServerManager.Start(GetUrlPrefixes().ToArray());
                 return;
                 return;
             }
             }
             catch (Exception ex)
             catch (Exception ex)
@@ -1631,7 +1631,7 @@ namespace Emby.Server.Implementations
 
 
             try
             try
             {
             {
-                ServerManager.Start(GetUrlPrefixes());
+                ServerManager.Start(GetUrlPrefixes().ToArray());
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {

+ 33 - 34
Emby.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -10,7 +10,6 @@ using System.Reflection;
 using System.Text;
 using System.Text;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.HttpServer.SocketSharp;
 using Emby.Server.Implementations.HttpServer.SocketSharp;
 using Emby.Server.Implementations.Services;
 using Emby.Server.Implementations.Services;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net;
@@ -34,7 +33,7 @@ namespace Emby.Server.Implementations.HttpServer
         private string DefaultRedirectPath { get; set; }
         private string DefaultRedirectPath { get; set; }
 
 
         private readonly ILogger _logger;
         private readonly ILogger _logger;
-        public IEnumerable<string> UrlPrefixes { get; private set; }
+        public string[] UrlPrefixes { get; private set; }
 
 
         private readonly List<IService> _restServices = new List<IService>();
         private readonly List<IService> _restServices = new List<IService>();
 
 
@@ -62,8 +61,8 @@ namespace Emby.Server.Implementations.HttpServer
         private readonly Func<Type, Func<string, object>> _funcParseFn;
         private readonly Func<Type, Func<string, object>> _funcParseFn;
         private readonly bool _enableDualModeSockets;
         private readonly bool _enableDualModeSockets;
 
 
-        public List<Action<IRequest, IResponse, object>> RequestFilters { get; set; }
-        public List<Action<IRequest, IResponse, object>> ResponseFilters { get; set; }
+        public Action<IRequest, IResponse, object>[] RequestFilters { get; set; }
+        public Action<IRequest, IResponse, object>[] ResponseFilters { get; set; }
 
 
         private readonly Dictionary<Type, Type> ServiceOperationsMap = new Dictionary<Type, Type>();
         private readonly Dictionary<Type, Type> ServiceOperationsMap = new Dictionary<Type, Type>();
         public static HttpListenerHost Instance { get; protected set; }
         public static HttpListenerHost Instance { get; protected set; }
@@ -95,8 +94,8 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             _logger = logger;
             _logger = logger;
 
 
-            RequestFilters = new List<Action<IRequest, IResponse, object>>();
-            ResponseFilters = new List<Action<IRequest, IResponse, object>>();
+            RequestFilters = new Action<IRequest, IResponse, object>[] { };
+            ResponseFilters = new Action<IRequest, IResponse, object>[] { };
         }
         }
 
 
         public string GlobalResponse { get; set; }
         public string GlobalResponse { get; set; }
@@ -135,7 +134,9 @@ namespace Emby.Server.Implementations.HttpServer
             //Exec all RequestFilter attributes with Priority < 0
             //Exec all RequestFilter attributes with Priority < 0
             var attributes = GetRequestFilterAttributes(requestDto.GetType());
             var attributes = GetRequestFilterAttributes(requestDto.GetType());
             var i = 0;
             var i = 0;
-            for (; i < attributes.Length && attributes[i].Priority < 0; i++)
+            var count = attributes.Count;
+
+            for (; i < count && attributes[i].Priority < 0; i++)
             {
             {
                 var attribute = attributes[i];
                 var attribute = attributes[i];
                 attribute.RequestFilter(req, res, requestDto);
                 attribute.RequestFilter(req, res, requestDto);
@@ -148,7 +149,7 @@ namespace Emby.Server.Implementations.HttpServer
             }
             }
 
 
             //Exec remaining RequestFilter attributes with Priority >= 0
             //Exec remaining RequestFilter attributes with Priority >= 0
-            for (; i < attributes.Length && attributes[i].Priority >= 0; i++)
+            for (; i < count && attributes[i].Priority >= 0; i++)
             {
             {
                 var attribute = attributes[i];
                 var attribute = attributes[i];
                 attribute.RequestFilter(req, res, requestDto);
                 attribute.RequestFilter(req, res, requestDto);
@@ -167,7 +168,7 @@ namespace Emby.Server.Implementations.HttpServer
             ServiceOperationsMap[requestType] = serviceType;
             ServiceOperationsMap[requestType] = serviceType;
         }
         }
 
 
-        private IHasRequestFilter[] GetRequestFilterAttributes(Type requestDtoType)
+        private List<IHasRequestFilter> GetRequestFilterAttributes(Type requestDtoType)
         {
         {
             var attributes = requestDtoType.GetTypeInfo().GetCustomAttributes(true).OfType<IHasRequestFilter>().ToList();
             var attributes = requestDtoType.GetTypeInfo().GetCustomAttributes(true).OfType<IHasRequestFilter>().ToList();
 
 
@@ -179,24 +180,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             attributes.Sort((x, y) => x.Priority - y.Priority);
             attributes.Sort((x, y) => x.Priority - y.Priority);
 
 
-            return attributes.ToArray(attributes.Count);
-        }
-
-        /// <summary>
-        /// Starts the Web Service
-        /// </summary>
-        private void StartListener()
-        {
-            WebSocketSharpRequest.HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes.First());
-
-            _listener = GetListener();
-
-            _listener.WebSocketConnected = OnWebSocketConnected;
-            _listener.WebSocketConnecting = OnWebSocketConnecting;
-            _listener.ErrorHandler = ErrorHandler;
-            _listener.RequestHandler = RequestHandler;
-
-            _listener.Start(UrlPrefixes);
+            return attributes;
         }
         }
 
 
         public static string GetHandlerPathIfAny(string listenerUrl)
         public static string GetHandlerPathIfAny(string listenerUrl)
@@ -698,13 +682,18 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             ServiceController.Init(this, types);
             ServiceController.Init(this, types);
 
 
-            var requestFilters = _appHost.GetExports<IRequestFilter>().ToList();
-            foreach (var filter in requestFilters)
+            var list = new List<Action<IRequest, IResponse, object>>();
+            foreach (var filter in _appHost.GetExports<IRequestFilter>())
             {
             {
-                RequestFilters.Add(filter.Filter);
+                list.Add(filter.Filter);
             }
             }
 
 
-            ResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
+            RequestFilters = list.ToArray();
+
+            ResponseFilters = new Action<IRequest, IResponse, object>[]
+            {
+                new ResponseFilter(_logger).FilterResponse
+            };
         }
         }
 
 
         public RouteAttribute[] GetRouteAttributes(Type requestType)
         public RouteAttribute[] GetRouteAttributes(Type requestType)
@@ -819,10 +808,20 @@ namespace Emby.Server.Implementations.HttpServer
             GC.SuppressFinalize(this);
             GC.SuppressFinalize(this);
         }
         }
 
 
-        public void StartServer(IEnumerable<string> urlPrefixes)
+        public void StartServer(string[] urlPrefixes)
         {
         {
-            UrlPrefixes = urlPrefixes.ToList();
-            StartListener();
+            UrlPrefixes = urlPrefixes;
+
+            WebSocketSharpRequest.HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]);
+
+            _listener = GetListener();
+
+            _listener.WebSocketConnected = OnWebSocketConnected;
+            _listener.WebSocketConnecting = OnWebSocketConnecting;
+            _listener.ErrorHandler = ErrorHandler;
+            _listener.RequestHandler = RequestHandler;
+
+            _listener.Start(UrlPrefixes);
         }
         }
     }
     }
 }
 }

+ 16 - 4
Emby.Server.Implementations/HttpServer/LoggerUtils.cs

@@ -1,10 +1,8 @@
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Logging;
 using System;
 using System;
 using System.Globalization;
 using System.Globalization;
-using System.Linq;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 using SocketHttpListener.Net;
 using SocketHttpListener.Net;
-using MediaBrowser.Model.Extensions;
 
 
 namespace Emby.Server.Implementations.HttpServer
 namespace Emby.Server.Implementations.HttpServer
 {
 {
@@ -30,7 +28,20 @@ namespace Emby.Server.Implementations.HttpServer
             }
             }
             else
             else
             {
             {
-                var headerText = string.Join(", ", headers.Select(i => i.Name + "=" + i.Value).ToArray(headers.Count));
+                var headerText = string.Empty;
+                var index = 0;
+
+                foreach (var i in headers)
+                {
+                    if (index > 0)
+                    {
+                        headerText += ", ";
+                    }
+
+                    headerText += i.Name + "=" + i.Value;
+
+                    index++;
+                }
 
 
                 logger.Info("HTTP {0} {1}. {2}", method, url, headerText);
                 logger.Info("HTTP {0} {1}. {2}", method, url, headerText);
             }
             }
@@ -49,7 +60,8 @@ namespace Emby.Server.Implementations.HttpServer
             var durationMs = duration.TotalMilliseconds;
             var durationMs = duration.TotalMilliseconds;
             var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
             var logSuffix = durationMs >= 1000 && durationMs < 60000 ? "ms (slow)" : "ms";
 
 
-            var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
+            //var headerText = headers == null ? string.Empty : "Headers: " + string.Join(", ", headers.Where(i => i.Name.IndexOf("Access-", StringComparison.OrdinalIgnoreCase) == -1).Select(i => i.Name + "=" + i.Value).ToArray());
+            var headerText = string.Empty;
             logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
             logger.Info("HTTP Response {0} to {1}. Time: {2}{3}. {4} {5}", statusCode, endPoint, Convert.ToInt32(durationMs).ToString(CultureInfo.InvariantCulture), logSuffix, url, headerText);
         }
         }
     }
     }

+ 2 - 3
Emby.Server.Implementations/HttpServer/Security/AuthService.cs

@@ -7,7 +7,6 @@ using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Security;
 using MediaBrowser.Controller.Security;
 using MediaBrowser.Controller.Session;
 using MediaBrowser.Controller.Session;
 using System;
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 
 
 namespace Emby.Server.Implementations.HttpServer.Security
 namespace Emby.Server.Implementations.HttpServer.Security
@@ -78,7 +77,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
 
 
             if (!IsExemptFromRoles(auth, authAttribtues, info))
             if (!IsExemptFromRoles(auth, authAttribtues, info))
             {
             {
-                var roles = authAttribtues.GetRoles().ToList();
+                var roles = authAttribtues.GetRoles();
 
 
                 ValidateRoles(roles, user);
                 ValidateRoles(roles, user);
             }
             }
@@ -162,7 +161,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
             return false;
             return false;
         }
         }
 
 
-        private void ValidateRoles(List<string> roles, User user)
+        private void ValidateRoles(string[] roles, User user)
         {
         {
             if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
             if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
             {
             {

+ 3 - 3
Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs

@@ -3,8 +3,8 @@ using MediaBrowser.Controller.Net;
 using MediaBrowser.Controller.Security;
 using MediaBrowser.Controller.Security;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
+using System.Linq;
 
 
 namespace Emby.Server.Implementations.HttpServer.Security
 namespace Emby.Server.Implementations.HttpServer.Security
 {
 {
@@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
                     AccessToken = token
                     AccessToken = token
                 });
                 });
 
 
-                var tokenInfo = result.Items.FirstOrDefault();
+                var tokenInfo = result.Items.Length > 0 ? result.Items[0] : null;
 
 
                 if (tokenInfo != null)
                 if (tokenInfo != null)
                 {
                 {
@@ -161,7 +161,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
             // There should be at least to parts
             // There should be at least to parts
             if (parts.Length != 2) return null;
             if (parts.Length != 2) return null;
 
 
-            var acceptedNames = new[] { "MediaBrowser", "Emby"};
+            var acceptedNames = new[] { "MediaBrowser", "Emby" };
 
 
             // It has to be a digest request
             // It has to be a digest request
             if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))
             if (!acceptedNames.Contains(parts[0] ?? string.Empty, StringComparer.OrdinalIgnoreCase))

+ 2 - 2
Emby.Server.Implementations/ServerManager/ServerManager.cs

@@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.ServerManager
         /// <summary>
         /// <summary>
         /// Starts this instance.
         /// Starts this instance.
         /// </summary>
         /// </summary>
-        public void Start(IEnumerable<string> urlPrefixes)
+        public void Start(string[] urlPrefixes)
         {
         {
             ReloadHttpServer(urlPrefixes);
             ReloadHttpServer(urlPrefixes);
         }
         }
@@ -120,7 +120,7 @@ namespace Emby.Server.Implementations.ServerManager
         /// <summary>
         /// <summary>
         /// Restarts the Http Server, or starts it if not currently running
         /// Restarts the Http Server, or starts it if not currently running
         /// </summary>
         /// </summary>
-        private void ReloadHttpServer(IEnumerable<string> urlPrefixes)
+        private void ReloadHttpServer(string[] urlPrefixes)
         {
         {
             _logger.Info("Loading Http Server");
             _logger.Info("Loading Http Server");
 
 

+ 19 - 6
Emby.Server.Implementations/Services/ServiceExec.cs

@@ -24,19 +24,33 @@ namespace Emby.Server.Implementations.Services
             "POLL",  "SUBSCRIBE", "UNSUBSCRIBE"
             "POLL",  "SUBSCRIBE", "UNSUBSCRIBE"
         });
         });
 
 
-        public static IEnumerable<MethodInfo> GetActions(this Type serviceType)
+        public static List<MethodInfo> GetActions(this Type serviceType)
         {
         {
-            foreach (var mi in serviceType.GetRuntimeMethods().Where(i => i.IsPublic && !i.IsStatic))
+            var list = new List<MethodInfo>();
+
+            foreach (var mi in serviceType.GetRuntimeMethods())
             {
             {
+                if (!mi.IsPublic)
+                {
+                    continue;
+                }
+
+                if (mi.IsStatic)
+                {
+                    continue;
+                }
+
                 if (mi.GetParameters().Length != 1)
                 if (mi.GetParameters().Length != 1)
                     continue;
                     continue;
 
 
                 var actionName = mi.Name;
                 var actionName = mi.Name;
-                if (!AllVerbs.Contains(actionName, StringComparer.OrdinalIgnoreCase) && !string.Equals(actionName, ServiceMethod.AnyAction, StringComparison.OrdinalIgnoreCase))
+                if (!AllVerbs.Contains(actionName, StringComparer.OrdinalIgnoreCase))
                     continue;
                     continue;
 
 
-                yield return mi;
+                list.Add(mi);
             }
             }
+
+            return list;
         }
         }
     }
     }
 
 
@@ -59,8 +73,7 @@ namespace Emby.Server.Implementations.Services
             var actionName = request.Verb ?? "POST";
             var actionName = request.Verb ?? "POST";
 
 
             ServiceMethod actionContext;
             ServiceMethod actionContext;
-            if (ServiceExecGeneral.execMap.TryGetValue(ServiceMethod.Key(serviceType, actionName, requestName), out actionContext)
-                || ServiceExecGeneral.execMap.TryGetValue(ServiceMethod.AnyKey(serviceType, requestName), out actionContext))
+            if (ServiceExecGeneral.execMap.TryGetValue(ServiceMethod.Key(serviceType, actionName, requestName), out actionContext))
             {
             {
                 if (actionContext.RequestFilters != null)
                 if (actionContext.RequestFilters != null)
                 {
                 {

+ 0 - 7
Emby.Server.Implementations/Services/ServiceMethod.cs

@@ -4,8 +4,6 @@ namespace Emby.Server.Implementations.Services
 {
 {
     public class ServiceMethod
     public class ServiceMethod
     {
     {
-        public const string AnyAction = "ANY";
-
         public string Id { get; set; }
         public string Id { get; set; }
 
 
         public ActionInvokerFn ServiceAction { get; set; }
         public ActionInvokerFn ServiceAction { get; set; }
@@ -15,10 +13,5 @@ namespace Emby.Server.Implementations.Services
         {
         {
             return serviceType.FullName + " " + method.ToUpper() + " " + requestDtoName;
             return serviceType.FullName + " " + method.ToUpper() + " " + requestDtoName;
         }
         }
-
-        public static string AnyKey(Type serviceType, string requestDtoName)
-        {
-            return Key(serviceType, AnyAction, requestDtoName);
-        }
     }
     }
 }
 }

+ 7 - 3
Emby.Server.Implementations/Services/StringMapTypeDeserializer.cs

@@ -1,6 +1,5 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Linq;
 using System.Reflection;
 using System.Reflection;
 
 
 namespace Emby.Server.Implementations.Services
 namespace Emby.Server.Implementations.Services
@@ -64,11 +63,16 @@ namespace Emby.Server.Implementations.Services
             if (instance == null)
             if (instance == null)
                 instance = _CreateInstanceFn(type);
                 instance = _CreateInstanceFn(type);
 
 
-            foreach (var pair in keyValuePairs.Where(x => !string.IsNullOrEmpty(x.Value)))
+            foreach (var pair in keyValuePairs)
             {
             {
                 propertyName = pair.Key;
                 propertyName = pair.Key;
                 propertyTextValue = pair.Value;
                 propertyTextValue = pair.Value;
 
 
+                if (string.IsNullOrEmpty(propertyTextValue))
+                {
+                    continue;
+                }
+
                 if (!propertySetterMap.TryGetValue(propertyName, out propertySerializerEntry))
                 if (!propertySetterMap.TryGetValue(propertyName, out propertySerializerEntry))
                 {
                 {
                     if (propertyName == "v")
                     if (propertyName == "v")
@@ -115,7 +119,7 @@ namespace Emby.Server.Implementations.Services
     {
     {
         public static Action<object, object> GetSetPropertyMethod(Type type, PropertyInfo propertyInfo)
         public static Action<object, object> GetSetPropertyMethod(Type type, PropertyInfo propertyInfo)
         {
         {
-            if (!propertyInfo.CanWrite || propertyInfo.GetIndexParameters().Any()) return null;
+            if (!propertyInfo.CanWrite || propertyInfo.GetIndexParameters().Length > 0) return null;
 
 
             var setMethodInfo = propertyInfo.SetMethod;
             var setMethodInfo = propertyInfo.SetMethod;
             return (instance, value) => setMethodInfo.Invoke(instance, new[] { value });
             return (instance, value) => setMethodInfo.Invoke(instance, new[] { value });

+ 27 - 9
MediaBrowser.Api/Dlna/DlnaServerService.cs

@@ -70,24 +70,27 @@ namespace MediaBrowser.Api.Dlna
         public Stream RequestStream { get; set; }
         public Stream RequestStream { get; set; }
     }
     }
 
 
-    [Route("/Dlna/{UuId}/mediareceiverregistrar/events", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/mediareceiverregistrar/events", "SUBSCRIBE", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/mediareceiverregistrar/events", "UNSUBSCRIBE", Summary = "Processes an event subscription request")]
     public class ProcessMediaReceiverRegistrarEventRequest
     public class ProcessMediaReceiverRegistrarEventRequest
     {
     {
-        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,POST")]
+        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,UNSUBSCRIBE")]
         public string UuId { get; set; }
         public string UuId { get; set; }
     }
     }
 
 
-    [Route("/Dlna/{UuId}/contentdirectory/events", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/contentdirectory/events", "SUBSCRIBE", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/contentdirectory/events", "UNSUBSCRIBE", Summary = "Processes an event subscription request")]
     public class ProcessContentDirectoryEventRequest
     public class ProcessContentDirectoryEventRequest
     {
     {
-        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,POST")]
+        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,UNSUBSCRIBE")]
         public string UuId { get; set; }
         public string UuId { get; set; }
     }
     }
 
 
-    [Route("/Dlna/{UuId}/connectionmanager/events", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/connectionmanager/events", "SUBSCRIBE", Summary = "Processes an event subscription request")]
+    [Route("/Dlna/{UuId}/connectionmanager/events", "UNSUBSCRIBE", Summary = "Processes an event subscription request")]
     public class ProcessConnectionManagerEventRequest
     public class ProcessConnectionManagerEventRequest
     {
     {
-        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,POST")]
+        [ApiMember(Name = "UuId", Description = "Server UuId", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "SUBSCRIBE,UNSUBSCRIBE")]
         public string UuId { get; set; }
         public string UuId { get; set; }
     }
     }
 
 
@@ -200,17 +203,32 @@ namespace MediaBrowser.Api.Dlna
             }
             }
         }
         }
 
 
-        public object Any(ProcessContentDirectoryEventRequest request)
+        public object Subscribe(ProcessContentDirectoryEventRequest request)
         {
         {
             return ProcessEventRequest(_contentDirectory);
             return ProcessEventRequest(_contentDirectory);
         }
         }
 
 
-        public object Any(ProcessConnectionManagerEventRequest request)
+        public object Subscribe(ProcessConnectionManagerEventRequest request)
         {
         {
             return ProcessEventRequest(_connectionManager);
             return ProcessEventRequest(_connectionManager);
         }
         }
 
 
-        public object Any(ProcessMediaReceiverRegistrarEventRequest request)
+        public object Subscribe(ProcessMediaReceiverRegistrarEventRequest request)
+        {
+            return ProcessEventRequest(_mediaReceiverRegistrar);
+        }
+
+        public object Unsubscribe(ProcessContentDirectoryEventRequest request)
+        {
+            return ProcessEventRequest(_contentDirectory);
+        }
+
+        public object Unsubscribe(ProcessConnectionManagerEventRequest request)
+        {
+            return ProcessEventRequest(_connectionManager);
+        }
+
+        public object Unsubscribe(ProcessMediaReceiverRegistrarEventRequest request)
         {
         {
             return ProcessEventRequest(_mediaReceiverRegistrar);
             return ProcessEventRequest(_mediaReceiverRegistrar);
         }
         }

+ 2 - 3
MediaBrowser.Controller/Net/AuthenticatedAttribute.cs

@@ -1,5 +1,4 @@
 using System;
 using System;
-using System.Collections.Generic;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 
 
 namespace MediaBrowser.Controller.Net
 namespace MediaBrowser.Controller.Net
@@ -50,7 +49,7 @@ namespace MediaBrowser.Controller.Net
             get { return 0; }
             get { return 0; }
         }
         }
 
 
-        public IEnumerable<string> GetRoles()
+        public string[] GetRoles()
         {
         {
             return (Roles ?? string.Empty).Split(new []{ ',' }, StringSplitOptions.RemoveEmptyEntries);
             return (Roles ?? string.Empty).Split(new []{ ',' }, StringSplitOptions.RemoveEmptyEntries);
         }
         }
@@ -61,6 +60,6 @@ namespace MediaBrowser.Controller.Net
         bool EscapeParentalControl { get; }
         bool EscapeParentalControl { get; }
         bool AllowBeforeStartupWizard { get; }
         bool AllowBeforeStartupWizard { get; }
 
 
-        IEnumerable<string> GetRoles();
+        string[] GetRoles();
     }
     }
 }
 }

+ 2 - 2
MediaBrowser.Controller/Net/IHttpServer.cs

@@ -13,13 +13,13 @@ namespace MediaBrowser.Controller.Net
         /// Gets the URL prefix.
         /// Gets the URL prefix.
         /// </summary>
         /// </summary>
         /// <value>The URL prefix.</value>
         /// <value>The URL prefix.</value>
-        IEnumerable<string> UrlPrefixes { get; }
+        string[] UrlPrefixes { get; }
 
 
         /// <summary>
         /// <summary>
         /// Starts the specified server name.
         /// Starts the specified server name.
         /// </summary>
         /// </summary>
         /// <param name="urlPrefixes">The URL prefixes.</param>
         /// <param name="urlPrefixes">The URL prefixes.</param>
-        void StartServer(IEnumerable<string> urlPrefixes);
+        void StartServer(string[] urlPrefixes);
 
 
         /// <summary>
         /// <summary>
         /// Stops this instance.
         /// Stops this instance.

+ 1 - 1
MediaBrowser.Controller/Net/IServerManager.cs

@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Net
         /// Starts this instance.
         /// Starts this instance.
         /// </summary>
         /// </summary>
         /// <param name="urlPrefixes">The URL prefixes.</param>
         /// <param name="urlPrefixes">The URL prefixes.</param>
-        void Start(IEnumerable<string> urlPrefixes);
+        void Start(string[] urlPrefixes);
 
 
         /// <summary>
         /// <summary>
         /// Sends a message to all clients currently connected via a web socket
         /// Sends a message to all clients currently connected via a web socket

+ 1 - 1
SharedVersion.cs

@@ -1,3 +1,3 @@
 using System.Reflection;
 using System.Reflection;
 
 
-[assembly: AssemblyVersion("3.2.30.2")]
+[assembly: AssemblyVersion("3.2.30.3")]