mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 00:55:13 +01:00
Add upnp configuration
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user