aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-02-25 23:38:21 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-02-25 23:38:21 -0500
commit13563b604756152fe2f6630a4cb8fd2994e5bb62 (patch)
tree367a886bcb57360e635da48046c87eaff243625d
parent7767580a3bff0d3a6ddc36b32784c0d49bb6b5f7 (diff)
Add upnp configuration
-rw-r--r--MediaBrowser.Api/UserService.cs22
-rw-r--r--MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs12
-rw-r--r--MediaBrowser.Common/Net/HttpRequestOptions.cs12
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs51
-rw-r--r--MediaBrowser.Dlna/MediaBrowser.Dlna.csproj55
-rw-r--r--MediaBrowser.Dlna/Properties/AssemblyInfo.cs31
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs8
-rw-r--r--MediaBrowser.Mono.sln10
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs4
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs17
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs174
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs2
-rw-r--r--MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs11
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj4
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/WebSocket/FleckServer.cs54
-rw-r--r--MediaBrowser.Server.Implementations/WebSocket/FleckWebSocket.cs47
-rw-r--r--MediaBrowser.Server.Implementations/packages.config1
-rw-r--r--MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj4
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj4
-rw-r--r--MediaBrowser.sln16
21 files changed, 383 insertions, 158 deletions
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 8e94d2c83..18c3bd096 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -189,7 +189,7 @@ namespace MediaBrowser.Api
{
throw new ArgumentNullException("xmlSerializer");
}
-
+
_xmlSerializer = xmlSerializer;
_userManager = userManager;
_dtoService = dtoService;
@@ -306,6 +306,26 @@ namespace MediaBrowser.Api
var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
+ // Login in the old way if the header is missing
+ if (string.IsNullOrEmpty(auth.Client) ||
+ string.IsNullOrEmpty(auth.Device) ||
+ string.IsNullOrEmpty(auth.DeviceId) ||
+ string.IsNullOrEmpty(auth.Version))
+ {
+ var success = await _userManager.AuthenticateUser(user, request.Password).ConfigureAwait(false);
+
+ if (!success)
+ {
+ // Unauthorized
+ throw new UnauthorizedAccessException("Invalid user or password entered.");
+ }
+
+ return new AuthenticationResult
+ {
+ User = _dtoService.GetUserDto(user)
+ };
+ }
+
var session = await _sessionMananger.AuthenticateNewSession(user, request.Password, auth.Client, auth.Version,
auth.DeviceId, auth.Device, Request.RemoteIp).ConfigureAwait(false);
diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
index 2e0035f5d..8e5cab43c 100644
--- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -114,7 +114,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
}
request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
- request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
+
+ request.CachePolicy = options.CachePolicy == Net.HttpRequestCachePolicy.None ?
+ new RequestCachePolicy(RequestCacheLevel.BypassCache) :
+ new RequestCachePolicy(RequestCacheLevel.Revalidate);
+
request.ConnectionGroupName = GetHostFromUrl(options.Url);
request.KeepAlive = true;
request.Method = method;
@@ -144,7 +148,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
}
request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
- request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
+
+ request.CachePolicy = options.CachePolicy == Net.HttpRequestCachePolicy.None ?
+ new RequestCachePolicy(RequestCacheLevel.BypassCache) :
+ new RequestCachePolicy(RequestCacheLevel.Revalidate);
+
request.ConnectionGroupName = GetHostFromUrl(options.Url);
request.KeepAlive = true;
request.Method = method;
diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs
index ebe76e62c..659d230cf 100644
--- a/MediaBrowser.Common/Net/HttpRequestOptions.cs
+++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs
@@ -71,7 +71,9 @@ namespace MediaBrowser.Common.Net
public string RequestContent { get; set; }
public bool BufferContent { get; set; }
-
+
+ public HttpRequestCachePolicy CachePolicy { get; set; }
+
private string GetHeaderValue(string name)
{
string value;
@@ -89,7 +91,15 @@ namespace MediaBrowser.Common.Net
EnableHttpCompression = true;
BufferContent = true;
+ CachePolicy = HttpRequestCachePolicy.None;
+
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
+
+ public enum HttpRequestCachePolicy
+ {
+ None = 1,
+ Validate = 2
+ }
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 954b36bf2..7ae2304c4 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -305,12 +305,6 @@ namespace MediaBrowser.Controller.Entities
return GetCachedChildren();
}
- /// <summary>
- /// Gets or sets the current validation cancellation token source.
- /// </summary>
- /// <value>The current validation cancellation token source.</value>
- private CancellationTokenSource CurrentValidationCancellationTokenSource { get; set; }
-
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken)
{
return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions());
@@ -331,48 +325,9 @@ namespace MediaBrowser.Controller.Entities
return ValidateChildrenWithCancellationSupport(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService);
}
- private async Task ValidateChildrenWithCancellationSupport(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
+ private Task ValidateChildrenWithCancellationSupport(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
- cancellationToken.ThrowIfCancellationRequested();
-
- // Cancel the current validation, if any
- if (CurrentValidationCancellationTokenSource != null)
- {
- CurrentValidationCancellationTokenSource.Cancel();
- }
-
- // Create an inner cancellation token. This can cancel all validations from this level on down,
- // but nothing above this
- var innerCancellationTokenSource = new CancellationTokenSource();
-
- try
- {
- CurrentValidationCancellationTokenSource = innerCancellationTokenSource;
-
- var linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(innerCancellationTokenSource.Token, cancellationToken);
-
- await ValidateChildrenInternal(progress, linkedCancellationTokenSource.Token, recursive, refreshChildMetadata, refreshOptions, directoryService).ConfigureAwait(false);
- }
- catch (OperationCanceledException ex)
- {
- Logger.Info("ValidateChildren cancelled for " + Name);
-
- // If the outer cancelletion token in the cause for the cancellation, throw it
- if (cancellationToken.IsCancellationRequested && ex.CancellationToken == cancellationToken)
- {
- throw;
- }
- }
- finally
- {
- // Null out the token source
- if (CurrentValidationCancellationTokenSource == innerCancellationTokenSource)
- {
- CurrentValidationCancellationTokenSource = null;
- }
-
- innerCancellationTokenSource.Dispose();
- }
+ return ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
}
private Dictionary<Guid, BaseItem> GetActualChildrenDictionary()
@@ -384,7 +339,7 @@ namespace MediaBrowser.Controller.Entities
var id = child.Id;
if (dictionary.ContainsKey(id))
{
- Logger.Error( "Found folder containing items with duplicate id. Path: {0}, Child Name: {1}",
+ Logger.Error("Found folder containing items with duplicate id. Path: {0}, Child Name: {1}",
Path ?? Name,
child.Path ?? child.Name);
}
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
new file mode 100644
index 000000000..c3ba97e9b
--- /dev/null
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MediaBrowser.Dlna</RootNamespace>
+ <AssemblyName>MediaBrowser.Dlna</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedVersion.cs">
+ <Link>Properties\SharedVersion.cs</Link>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Properties/AssemblyInfo.cs b/MediaBrowser.Dlna/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..1d9f7cd97
--- /dev/null
+++ b/MediaBrowser.Dlna/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MediaBrowser.Dlna")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MediaBrowser.Dlna")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c319ebfa-fd9d-42e4-ae74-a40039a6a688")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+// \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 21414768e..1b4a6813e 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -28,6 +28,12 @@ namespace MediaBrowser.Model.Configuration
public bool EnableHttpLevelLogging { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether [enable u pn p].
+ /// </summary>
+ /// <value><c>true</c> if [enable u pn p]; otherwise, <c>false</c>.</value>
+ public bool EnableUPnP { get; set; }
+
+ /// <summary>
/// Gets or sets the HTTP server port number.
/// </summary>
/// <value>The HTTP server port number.</value>
@@ -222,6 +228,8 @@ namespace MediaBrowser.Model.Configuration
EnableAutomaticRestart = true;
EnablePeoplePrefixSubFolders = true;
+ EnableUPnP = true;
+
MinResumePct = 5;
MaxResumePct = 90;
MinResumeDurationSeconds = Convert.ToInt32(TimeSpan.FromMinutes(5).TotalSeconds);
diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln
index c951fda72..4f6ce7a58 100644
--- a/MediaBrowser.Mono.sln
+++ b/MediaBrowser.Mono.sln
@@ -19,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Mono", "MediaBrowser.Server.Mono\MediaBrowser.Server.Mono.csproj", "{175A9388-F352-4586-A6B4-070DED62B644}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -99,6 +101,14 @@ Global
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.Build.0 = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.ActiveCfg = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.Build.0 = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.Build.0 = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(MonoDevelopProperties) = preSolution
StartupItem = MediaBrowser.Server.Mono\MediaBrowser.Server.Mono.csproj
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index c8989529b..83331ebbb 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -182,6 +182,10 @@ namespace MediaBrowser.Providers.Manager
return result;
}
+ catch (OperationCanceledException)
+ {
+ return new List<RemoteImageInfo>();
+ }
catch (Exception ex)
{
_logger.ErrorException("{0} failed in GetImageInfos for type {1}", ex, provider.GetType().Name, item.GetType().Name);
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index f4191fe8f..c620a6c33 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -36,7 +36,22 @@ namespace MediaBrowser.Providers.TV
{
foreach (var seriesGroup in series)
{
- await Run(seriesGroup, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await Run(seriesGroup, cancellationToken).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ break;
+ }
+ catch (DirectoryNotFoundException)
+ {
+ _logger.Warn("Series files missing for series id {0}", seriesGroup.Key);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in missing episode provider for series id {0}", ex, seriesGroup.Key);
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
new file mode 100644
index 000000000..43037d6ce
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -0,0 +1,174 @@
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Logging;
+using Mono.Nat;
+using System;
+using System.IO;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.EntryPoints
+{
+ public class ExternalPortForwarding : IServerEntryPoint
+ {
+ private readonly IServerApplicationHost _appHost;
+ private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
+
+ private bool _isStarted;
+
+ public ExternalPortForwarding(ILogger logger, IServerApplicationHost appHost, IServerConfigurationManager config)
+ {
+ _logger = logger;
+ _appHost = appHost;
+ _config = config;
+
+ _config.ConfigurationUpdated += _config_ConfigurationUpdated;
+ }
+
+ void _config_ConfigurationUpdated(object sender, EventArgs e)
+ {
+ var enable = _config.Configuration.EnableUPnP;
+
+ if (enable && !_isStarted)
+ {
+ Reload();
+ }
+ else if (!enable && _isStarted)
+ {
+ DisposeNat();
+ }
+ }
+
+ public void Run()
+ {
+ NatUtility.Logger = new LogWriter(_logger);
+
+ Reload();
+ }
+
+ private void Reload()
+ {
+ if (_config.Configuration.EnableUPnP)
+ {
+ _logger.Debug("Starting NAT discovery");
+
+ NatUtility.DeviceFound += NatUtility_DeviceFound;
+ NatUtility.DeviceLost += NatUtility_DeviceLost;
+ NatUtility.UnhandledException += NatUtility_UnhandledException;
+ NatUtility.StartDiscovery();
+
+ _isStarted = true;
+ }
+ }
+
+ void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ var ex = e.ExceptionObject as Exception;
+
+ if (ex == null)
+ {
+ _logger.Error("Unidentified error reported by Mono.Nat");
+ }
+ else
+ {
+ // Seeing some blank exceptions coming through here
+ _logger.ErrorException("Error reported by Mono.Nat: ", ex);
+ }
+ }
+
+ void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
+ {
+ try
+ {
+ var device = e.Device;
+ _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString());
+
+ CreateRules(device);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error creating port forwarding rules", ex);
+ }
+ }
+
+ private void CreateRules(INatDevice device)
+ {
+ var info = _appHost.GetSystemInfo();
+
+ CreatePortMap(device, info.HttpServerPortNumber);
+
+ if (info.WebSocketPortNumber != info.HttpServerPortNumber)
+ {
+ CreatePortMap(device, info.WebSocketPortNumber);
+ }
+ }
+
+ private void CreatePortMap(INatDevice device, int port)
+ {
+ _logger.Info("Creating port map on port {0}", port);
+
+ device.CreatePortMap(new Mapping(Protocol.Tcp, port, port)
+ {
+ Description = "Media Browser Server"
+ });
+ }
+
+ void NatUtility_DeviceLost(object sender, DeviceEventArgs e)
+ {
+ var device = e.Device;
+ _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString());
+ }
+
+ public void Dispose()
+ {
+ DisposeNat();
+ }
+
+ private void DisposeNat()
+ {
+ _logger.Debug("Stopping NAT discovery");
+
+ try
+ {
+ NatUtility.DeviceFound -= NatUtility_DeviceFound;
+ NatUtility.DeviceLost -= NatUtility_DeviceLost;
+ NatUtility.UnhandledException -= NatUtility_UnhandledException;
+ NatUtility.StopDiscovery();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error stopping NAT Discovery", ex);
+ }
+ finally
+ {
+ _isStarted = false;
+ }
+ }
+
+ private class LogWriter : TextWriter
+ {
+ private readonly ILogger _logger;
+
+ public LogWriter(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public override Encoding Encoding
+ {
+ get { return Encoding.UTF8; }
+ }
+
+ public override void WriteLine(string format, params object[] arg)
+ {
+ _logger.Debug(format, arg);
+ }
+
+ public override void WriteLine(string value)
+ {
+ _logger.Debug(value);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
index 9df6e7f1c..7edcf9739 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/TvFolderOrganizer.cs
@@ -170,7 +170,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
File.Delete(file.FullName);
}
- catch (IOException ex)
+ catch (Exception ex)
{
_logger.ErrorException("Error deleting file {0}", ex, file.FullName);
}
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index fa1d4b0d5..cbc4a8c24 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -39,7 +39,16 @@ namespace MediaBrowser.Server.Implementations.IO
/// <summary>
/// Any file name ending in any of these will be ignored by the watchers
/// </summary>
- private readonly IReadOnlyList<string> _alwaysIgnoreFiles = new List<string> { "thumbs.db", "small.jpg", "albumart.jpg" };
+ private readonly IReadOnlyList<string> _alwaysIgnoreFiles = new List<string>
+ {
+ "thumbs.db",
+ "small.jpg",
+ "albumart.jpg",
+
+ // WMC temp recording directories that will constantly be written to
+ "TempRec",
+ "TempSBE"
+ };
/// <summary>
/// The timer lock
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index c8e7903d1..d83f01052 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -56,6 +56,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
+ <Reference Include="Mono.Nat">
+ <HintPath>..\packages\Mono.Nat.1.1.13\lib\Net40\Mono.Nat.dll</HintPath>
+ </Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
@@ -112,6 +115,7 @@
<Compile Include="Drawing\UnplayedCountIndicator.cs" />
<Compile Include="Dto\DtoService.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
+ <Compile Include="EntryPoints\ExternalPortForwarding.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
<Compile Include="EntryPoints\LoadRegistrations.cs" />
<Compile Include="EntryPoints\Notifications\Notifier.cs" />
diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
index fecd72a39..e66b87b0c 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
@@ -154,8 +154,6 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// </summary>
private void ReloadHttpServer(IEnumerable<string> urlPrefixes, bool enableHttpLogging)
{
- DisposeHttpServer();
-
_logger.Info("Loading Http Server");
try
diff --git a/MediaBrowser.Server.Implementations/WebSocket/FleckServer.cs b/MediaBrowser.Server.Implementations/WebSocket/FleckServer.cs
deleted file mode 100644
index 2c47a366e..000000000
--- a/MediaBrowser.Server.Implementations/WebSocket/FleckServer.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using Fleck;
-using MediaBrowser.Common.Net;
-using System;
-using IWebSocketServer = MediaBrowser.Common.Net.IWebSocketServer;
-
-namespace MediaBrowser.Server.Implementations.WebSocket
-{
- public class FleckServer : IWebSocketServer
- {
- private WebSocketServer _server;
-
- public void Start(int portNumber)
- {
- var server = new WebSocketServer("ws://localhost:" + portNumber);
-
- server.Start(socket =>
- {
- socket.OnOpen = () => OnClientConnected(socket);
- });
-
- _server = server;
- }
-
- public void Stop()
- {
- _server.Dispose();
- }
-
- private void OnClientConnected(Fleck.IWebSocketConnection context)
- {
- if (WebSocketConnected != null)
- {
- var socket = new FleckWebSocket(context);
-
- WebSocketConnected(this, new WebSocketConnectEventArgs
- {
- WebSocket = socket,
- Endpoint = context.ConnectionInfo.ClientIpAddress + ":" + context.ConnectionInfo.ClientPort
- });
- }
- }
- public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- public int Port
- {
- get { return _server.Port; }
- }
-
- public void Dispose()
- {
- _server.Dispose();
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/WebSocket/FleckWebSocket.cs b/MediaBrowser.Server.Implementations/WebSocket/FleckWebSocket.cs
deleted file mode 100644
index 3667fab07..000000000
--- a/MediaBrowser.Server.Implementations/WebSocket/FleckWebSocket.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Net;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-using IWebSocketConnection = Fleck.IWebSocketConnection;
-
-namespace MediaBrowser.Server.Implementations.WebSocket
-{
- public class FleckWebSocket : IWebSocket
- {
- private readonly IWebSocketConnection _connection;
-
- public FleckWebSocket(IWebSocketConnection connection)
- {
- _connection = connection;
-
- _connection.OnMessage = OnReceiveData;
- }
-
- public WebSocketState State
- {
- get { return _connection.IsAvailable ? WebSocketState.Open : WebSocketState.Closed; }
- }
-
- private void OnReceiveData(string data)
- {
- if (OnReceive != null)
- {
- OnReceive(data);
- }
- }
-
- public Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken)
- {
- return Task.Run(() => _connection.Send(bytes));
- }
-
- public void Dispose()
- {
- _connection.Close();
- }
-
- public Action<byte[]> OnReceiveBytes { get; set; }
- public Action<string> OnReceive { get; set; }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 4b96e57f7..258e0639d 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -2,6 +2,7 @@
<packages>
<package id="Alchemy" version="2.2.1" targetFramework="net45" />
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
+ <package id="Mono.Nat" version="1.1.13" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.x86" version="1.0.90.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index 6b000435a..c8453e771 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -100,6 +100,10 @@
<Project>{442B5058-DCAF-4263-BB6A-F21E31120A1B}</Project>
<Name>MediaBrowser.Providers</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Dlna\MediaBrowser.Dlna.csproj">
+ <Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project>
+ <Name>MediaBrowser.Dlna</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
<Name>MediaBrowser.Model</Name>
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index b58899740..c3eb4fd6a 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -191,6 +191,10 @@
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Dlna\MediaBrowser.Dlna.csproj">
+ <Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project>
+ <Name>MediaBrowser.Dlna</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index a3e35f603..7ac158065 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -39,6 +39,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model.Portable
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.ServerApplication", "MediaBrowser.ServerApplication\MediaBrowser.ServerApplication.csproj", "{94ADE4D3-B7EC-45CD-A200-CC469433072B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -231,6 +233,20 @@ Global
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|Win32.ActiveCfg = Release|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|x64.ActiveCfg = Release|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|x86.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Win32.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x64.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE