using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Reflection; using Microsoft.Owin.Hosting; using Microsoft.Owin.Hosting.Engine; using Microsoft.Owin.Hosting.Services; using Microsoft.Owin.Hosting.Tracing; using NLog; using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Core.Configuration; using NzbDrone.Host.Owin.MiddleWare; using Owin; namespace NzbDrone.Host.Owin { public interface IOwinAppFactory { IDisposable CreateApp(List urls); } public class OwinAppFactory : IOwinAppFactory { private readonly IEnumerable _owinMiddleWares; private readonly IConfigFileProvider _configFileProvider; private readonly Logger _logger; public OwinAppFactory(IEnumerable owinMiddleWares, IConfigFileProvider configFileProvider, Logger logger) { _owinMiddleWares = owinMiddleWares; _configFileProvider = configFileProvider; _logger = logger; } public IDisposable CreateApp(List urls) { var services = CreateServiceFactory(); var engine = services.GetService(); var options = new StartOptions() { ServerFactory = "Microsoft.Owin.Host.HttpListener" }; urls.ForEach(options.Urls.Add); var context = new StartContext(options) { Startup = BuildApp }; try { return engine.Start(context); } catch (TargetInvocationException ex) { if (ex.InnerException == null) { throw; } if (ex.InnerException is HttpListenerException) { throw new PortInUseException("Unable to bind to the designated IP Address/Port ({0}:{1}). Please ensure Sonarr is not already running, the bind address is correct (or is set to'*') and the port is not used", ex, _configFileProvider.BindAddress, _configFileProvider.Port); } throw ex.InnerException; } } private void BuildApp(IAppBuilder appBuilder) { appBuilder.Properties["host.AppName"] = BuildInfo.AppName; foreach (var middleWare in _owinMiddleWares.OrderBy(c => c.Order)) { _logger.Debug("Attaching {0} to host", middleWare.GetType().Name); middleWare.Attach(appBuilder); } } private IServiceProvider CreateServiceFactory() { var provider = (ServiceProvider)ServicesFactory.Create(); provider.Add(typeof(ITraceOutputFactory), typeof(OwinTraceOutputFactory)); return provider; } } }