Merge branch 'master' into fix-resharper-warnings

# Conflicts:
#	Emby.Server.Implementations/Net/SocketFactory.cs
#	RSSDP/SsdpCommunicationsServer.cs
#	RSSDP/SsdpDeviceLocator.cs
#	RSSDP/SsdpDevicePublisher.cs
This commit is contained in:
Stepan Goremykin
2023-10-12 20:11:16 +02:00
83 changed files with 1484 additions and 2131 deletions

View File

@@ -101,7 +101,6 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Prometheus.DotNetRuntime;
using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
@@ -133,7 +132,7 @@ namespace Emby.Server.Implementations
/// <value>All concrete types.</value>
private Type[] _allConcreteTypes;
private bool _disposed = false;
private bool _disposed;
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
@@ -184,26 +183,16 @@ namespace Emby.Server.Implementations
public bool CoreStartupHasCompleted { get; private set; }
public virtual bool CanLaunchWebBrowser => Environment.UserInteractive
&& !_startupOptions.IsService
&& (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS());
/// <summary>
/// Gets the <see cref="INetworkManager"/> singleton instance.
/// </summary>
public INetworkManager NetManager { get; private set; }
/// <summary>
/// Gets a value indicating whether this instance has changes that require the entire application to restart.
/// </summary>
/// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
/// <inheritdoc />
public bool HasPendingRestart { get; private set; }
/// <inheritdoc />
public bool IsShuttingDown { get; private set; }
/// <inheritdoc />
public bool ShouldRestart { get; private set; }
public bool ShouldRestart { get; set; }
/// <summary>
/// Gets the logger.
@@ -461,7 +450,7 @@ namespace Emby.Server.Implementations
ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
NetManager = new NetworkManager(ConfigurationManager, LoggerFactory.CreateLogger<NetworkManager>());
NetManager = new NetworkManager(ConfigurationManager, _startupConfig, LoggerFactory.CreateLogger<NetworkManager>());
// Initialize runtime stat collection
if (ConfigurationManager.Configuration.EnableMetrics)
@@ -507,6 +496,8 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IFileSystem, ManagedFileSystem>();
serviceCollection.AddSingleton<IShortcutHandler, MbLinkShortcutHandler>();
serviceCollection.AddScoped<ISystemManager, SystemManager>();
serviceCollection.AddSingleton<TmdbClientManager>();
serviceCollection.AddSingleton(NetManager);
@@ -850,24 +841,6 @@ namespace Emby.Server.Implementations
}
}
/// <inheritdoc />
public void Restart()
{
ShouldRestart = true;
Shutdown();
}
/// <inheritdoc />
public void Shutdown()
{
Task.Run(async () =>
{
await Task.Delay(100).ConfigureAwait(false);
IsShuttingDown = true;
Resolve<IHostApplicationLifetime>().StopApplication();
});
}
/// <summary>
/// Gets the composable part assemblies.
/// </summary>
@@ -923,49 +896,6 @@ namespace Emby.Server.Implementations
protected abstract IEnumerable<Assembly> GetAssembliesWithPartsInternal();
/// <summary>
/// Gets the system status.
/// </summary>
/// <param name="request">Where this request originated.</param>
/// <returns>SystemInfo.</returns>
public SystemInfo GetSystemInfo(HttpRequest request)
{
return new SystemInfo
{
HasPendingRestart = HasPendingRestart,
IsShuttingDown = IsShuttingDown,
Version = ApplicationVersionString,
WebSocketPortNumber = HttpPort,
CompletedInstallations = Resolve<IInstallationManager>().CompletedInstallations.ToArray(),
Id = SystemId,
ProgramDataPath = ApplicationPaths.ProgramDataPath,
WebPath = ApplicationPaths.WebPath,
LogPath = ApplicationPaths.LogDirectoryPath,
ItemsByNamePath = ApplicationPaths.InternalMetadataPath,
InternalMetadataPath = ApplicationPaths.InternalMetadataPath,
CachePath = ApplicationPaths.CachePath,
CanLaunchWebBrowser = CanLaunchWebBrowser,
TranscodingTempPath = ConfigurationManager.GetTranscodePath(),
ServerName = FriendlyName,
LocalAddress = GetSmartApiUrl(request),
SupportsLibraryMonitor = true,
PackageName = _startupOptions.PackageName
};
}
public PublicSystemInfo GetPublicSystemInfo(HttpRequest request)
{
return new PublicSystemInfo
{
Version = ApplicationVersionString,
ProductName = ApplicationProductName,
Id = SystemId,
ServerName = FriendlyName,
LocalAddress = GetSmartApiUrl(request),
StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted
};
}
/// <inheritdoc/>
public string GetSmartApiUrl(IPAddress remoteAddr)
{
@@ -983,7 +913,7 @@ namespace Emby.Server.Implementations
/// <inheritdoc/>
public string GetSmartApiUrl(HttpRequest request)
{
// Return the host in the HTTP request as the API url
// Return the host in the HTTP request as the API URL if not configured otherwise
if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest)
{
int? requestPort = request.Host.Port;
@@ -1018,7 +948,7 @@ namespace Emby.Server.Implementations
public string GetApiUrlForLocalAccess(IPAddress ipAddress = null, bool allowHttps = true)
{
// With an empty source, the port will be null
var smart = NetManager.GetBindAddress(ipAddress, out _, true);
var smart = NetManager.GetBindAddress(ipAddress, out _, false);
var scheme = !allowHttps ? Uri.UriSchemeHttp : null;
int? port = !allowHttps ? HttpPort : null;
return GetLocalApiUrl(smart, scheme, port);

View File

@@ -18,7 +18,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class UdpServerEntryPoint.
/// Class responsible for registering all UDP broadcast endpoints and their handlers.
/// </summary>
public sealed class UdpServerEntryPoint : IServerEntryPoint
{
@@ -35,7 +35,6 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly IConfiguration _config;
private readonly IConfigurationManager _configurationManager;
private readonly INetworkManager _networkManager;
private readonly bool _enableMultiSocketBinding;
/// <summary>
/// The UDP server.
@@ -65,7 +64,6 @@ namespace Emby.Server.Implementations.EntryPoints
_configurationManager = configurationManager;
_networkManager = networkManager;
_udpServers = new List<UdpServer>();
_enableMultiSocketBinding = OperatingSystem.IsWindows() || OperatingSystem.IsLinux();
}
/// <inheritdoc />
@@ -80,14 +78,16 @@ namespace Emby.Server.Implementations.EntryPoints
try
{
if (_enableMultiSocketBinding)
// Linux needs to bind to the broadcast addresses to get broadcast traffic
// Windows receives broadcast fine when binding to just the interface, it is unable to bind to broadcast addresses
if (OperatingSystem.IsLinux())
{
// Add global broadcast socket
// Add global broadcast listener
var server = new UdpServer(_logger, _appHost, _config, IPAddress.Broadcast, PortNumber);
server.Start(_cancellationTokenSource.Token);
_udpServers.Add(server);
// Add bind address specific broadcast sockets
// Add bind address specific broadcast listeners
// IPv6 is currently unsupported
var validInterfaces = _networkManager.GetInternalBindAddresses().Where(i => i.AddressFamily == AddressFamily.InterNetwork);
foreach (var intf in validInterfaces)
@@ -102,9 +102,18 @@ namespace Emby.Server.Implementations.EntryPoints
}
else
{
var server = new UdpServer(_logger, _appHost, _config, IPAddress.Any, PortNumber);
server.Start(_cancellationTokenSource.Token);
_udpServers.Add(server);
// Add bind address specific broadcast listeners
// IPv6 is currently unsupported
var validInterfaces = _networkManager.GetInternalBindAddresses().Where(i => i.AddressFamily == AddressFamily.InterNetwork);
foreach (var intf in validInterfaces)
{
var intfAddress = intf.Address;
_logger.LogDebug("Binding UDP server to {Address} on port {PortNumber}", intfAddress, PortNumber);
var server = new UdpServer(_logger, _appHost, _config, intfAddress, PortNumber);
server.Start(_cancellationTokenSource.Token);
_udpServers.Add(server);
}
}
}
catch (SocketException ex)
@@ -119,7 +128,7 @@ namespace Emby.Server.Implementations.EntryPoints
{
if (_disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
throw new ObjectDisposedException(GetType().Name);
}
}

View File

@@ -103,15 +103,17 @@ namespace Emby.Server.Implementations.IO
return filePath;
}
var filePathSpan = filePath.AsSpan();
// relative path
if (firstChar == '\\')
{
filePath = filePath.Substring(1);
filePathSpan = filePathSpan.Slice(1);
}
try
{
return Path.GetFullPath(Path.Combine(folderPath, filePath));
return Path.GetFullPath(Path.Join(folderPath, filePathSpan));
}
catch (ArgumentException)
{

View File

@@ -838,19 +838,12 @@ namespace Emby.Server.Implementations.Library
{
var path = Person.GetPath(name);
var id = GetItemByNameId<Person>(path);
if (GetItemById(id) is not Person item)
if (GetItemById(id) is Person item)
{
item = new Person
{
Name = name,
Id = id,
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow,
Path = path
};
return item;
}
return item;
return null;
}
/// <summary>
@@ -1161,7 +1154,7 @@ namespace Emby.Server.Implementations.Library
Name = Path.GetFileName(dir),
Locations = _fileSystem.GetFilePaths(dir, false)
.Where(i => string.Equals(ShortcutFileExtension, Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
.Where(i => Path.GetExtension(i.AsSpan()).Equals(ShortcutFileExtension, StringComparison.OrdinalIgnoreCase))
.Select(i =>
{
try
@@ -2899,9 +2892,18 @@ namespace Emby.Server.Implementations.Library
var saveEntity = false;
var personEntity = GetPerson(person.Name);
// if PresentationUniqueKey is empty it's likely a new item.
if (string.IsNullOrEmpty(personEntity.PresentationUniqueKey))
if (personEntity is null)
{
var path = Person.GetPath(person.Name);
personEntity = new Person()
{
Name = person.Name,
Id = GetItemByNameId<Person>(path),
DateCreated = DateTime.UtcNow,
DateModified = DateTime.UtcNow,
Path = path
};
personEntity.PresentationUniqueKey = personEntity.CreatePresentationUniqueKey();
saveEntity = true;
}
@@ -3134,7 +3136,7 @@ namespace Emby.Server.Implementations.Library
}
var shortcut = _fileSystem.GetFilePaths(virtualFolderPath, true)
.Where(i => string.Equals(ShortcutFileExtension, Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
.Where(i => Path.GetExtension(i.AsSpan()).Equals(ShortcutFileExtension, StringComparison.OrdinalIgnoreCase))
.FirstOrDefault(f => _appHost.ExpandVirtualPath(_fileSystem.ResolveShortcut(f)).Equals(mediaPath, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(shortcut))

View File

@@ -94,9 +94,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
if (AudioFileParser.IsAudioFile(args.Path, _namingOptions))
{
var extension = Path.GetExtension(args.Path);
var extension = Path.GetExtension(args.Path.AsSpan());
if (string.Equals(extension, ".cue", StringComparison.OrdinalIgnoreCase))
if (extension.Equals(".cue", StringComparison.OrdinalIgnoreCase))
{
// if audio file exists of same name, return null
return null;
@@ -128,7 +128,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
if (item is not null)
{
item.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase);
item.IsShortcut = extension.Equals(".strm", StringComparison.OrdinalIgnoreCase);
item.IsInMixedFolder = true;
}

View File

@@ -263,7 +263,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
return false;
}
return directoryService.GetFilePaths(fullPath).Any(i => string.Equals(Path.GetExtension(i), ".vob", StringComparison.OrdinalIgnoreCase));
return directoryService.GetFilePaths(fullPath).Any(i => Path.GetExtension(i.AsSpan()).Equals(".vob", StringComparison.OrdinalIgnoreCase));
}
/// <summary>

View File

@@ -32,9 +32,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
return GetBook(args);
}
var extension = Path.GetExtension(args.Path);
var extension = Path.GetExtension(args.Path.AsSpan());
if (extension is not null && _validExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
if (_validExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase))
{
// It's a book
return new Book
@@ -51,12 +51,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
{
var bookFiles = args.FileSystemChildren.Where(f =>
{
var fileExtension = Path.GetExtension(f.FullName)
?? string.Empty;
var fileExtension = Path.GetExtension(f.FullName.AsSpan());
return _validExtensions.Contains(
fileExtension,
StringComparer.OrdinalIgnoreCase);
StringComparison.OrdinalIgnoreCase);
}).ToList();
// Don't return a Book if there is more (or less) than one document in the directory

View File

@@ -121,5 +121,7 @@
"TaskOptimizeDatabaseDescription": "ഡാറ്റാബേസ് ചുരുക്കുകയും സ്വതന്ത്ര ഇടം വെട്ടിച്ചുരുക്കുകയും ചെയ്യുന്നു. ലൈബ്രറി സ്‌കാൻ ചെയ്‌തതിനുശേഷം അല്ലെങ്കിൽ ഡാറ്റാബേസ് പരിഷ്‌ക്കരണങ്ങളെ സൂചിപ്പിക്കുന്ന മറ്റ് മാറ്റങ്ങൾ ചെയ്‌തതിന് ശേഷം ഈ ടാസ്‌ക് പ്രവർത്തിപ്പിക്കുന്നത് പ്രകടനം മെച്ചപ്പെടുത്തും.",
"TaskOptimizeDatabase": "ഡാറ്റാബേസ് ഒപ്റ്റിമൈസ് ചെയ്യുക",
"HearingImpaired": "കേൾവി തകരാറുകൾ",
"External": "പുറമേയുള്ള"
"External": "പുറമേയുള്ള",
"TaskKeyframeExtractorDescription": "കൂടുതൽ കൃത്യമായ HLS പ്ലേലിസ്റ്റുകൾ സൃഷ്‌ടിക്കുന്നതിന് വീഡിയോ ഫയലുകളിൽ നിന്ന് കീഫ്രെയിമുകൾ എക്‌സ്‌ട്രാക്‌റ്റ് ചെയ്യുന്നു. ഈ പ്രവർത്തനം പൂർത്തിയാവാൻ കുറച്ചധികം സമയം എടുത്തേക്കാം.",
"TaskKeyframeExtractor": "കീഫ്രെയിം എക്സ്ട്രാക്റ്റർ"
}

View File

@@ -124,5 +124,5 @@
"TaskKeyframeExtractorDescription": "Extrahuje kľúčové snímky z video súborov na vytvorenie presnejších HLS playlistov. Táto úloha môže trvať dlhšiu dobu.",
"TaskKeyframeExtractor": "Extraktor kľúčových snímkov",
"External": "Externé",
"HearingImpaired": "Sluchovo Postihnutý"
"HearingImpaired": "Sluchovo postihnutí"
}

View File

@@ -222,7 +222,7 @@ namespace Emby.Server.Implementations.MediaEncoder
{
var deadImages = images
.Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase)
.Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparison.OrdinalIgnoreCase))
.Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i.AsSpan()), StringComparison.OrdinalIgnoreCase))
.ToList();
foreach (var image in deadImages)

View File

@@ -1,12 +1,15 @@
#pragma warning disable CS1591
using System;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.Net
{
/// <summary>
/// Factory class to create different kinds of sockets.
/// </summary>
public class SocketFactory : ISocketFactory
{
/// <inheritdoc />
@@ -38,7 +41,8 @@ namespace Emby.Server.Implementations.Net
/// <inheritdoc />
public Socket CreateSsdpUdpSocket(IPData bindInterface, int localPort)
{
ArgumentNullException.ThrowIfNull(bindInterface.Address);
var interfaceAddress = bindInterface.Address;
ArgumentNullException.ThrowIfNull(interfaceAddress);
if (localPort < 0)
{
@@ -49,7 +53,7 @@ namespace Emby.Server.Implementations.Net
try
{
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.Bind(new IPEndPoint(bindInterface.Address, localPort));
socket.Bind(new IPEndPoint(interfaceAddress, localPort));
return socket;
}
@@ -82,16 +86,25 @@ namespace Emby.Server.Implementations.Net
try
{
var interfaceIndex = bindInterface.Index;
var interfaceIndexSwapped = IPAddress.HostToNetworkOrder(interfaceIndex);
socket.MulticastLoopback = false;
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.PacketInformation, true);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, multicastTimeToLive);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, interfaceIndexSwapped);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, interfaceIndex));
socket.Bind(new IPEndPoint(multicastAddress, localPort));
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress));
socket.Bind(new IPEndPoint(multicastAddress, localPort));
}
else
{
// Only create socket if interface supports multicast
var interfaceIndex = bindInterface.Index;
var interfaceIndexSwapped = IPAddress.HostToNetworkOrder(interfaceIndex);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, interfaceIndex));
socket.Bind(new IPEndPoint(bindIPAddress, localPort));
}
return socket;
}

View File

@@ -327,9 +327,9 @@ namespace Emby.Server.Implementations.Playlists
// this is probably best done as a metadata provider
// saving a file over itself will require some work to prevent this from happening when not needed
var playlistPath = item.Path;
var extension = Path.GetExtension(playlistPath);
var extension = Path.GetExtension(playlistPath.AsSpan());
if (string.Equals(".wpl", extension, StringComparison.OrdinalIgnoreCase))
if (extension.Equals(".wpl", StringComparison.OrdinalIgnoreCase))
{
var playlist = new WplPlaylist();
foreach (var child in item.GetLinkedChildren())
@@ -362,8 +362,7 @@ namespace Emby.Server.Implementations.Playlists
string text = new WplContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase))
else if (extension.Equals(".zpl", StringComparison.OrdinalIgnoreCase))
{
var playlist = new ZplPlaylist();
foreach (var child in item.GetLinkedChildren())
@@ -396,8 +395,7 @@ namespace Emby.Server.Implementations.Playlists
string text = new ZplContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase))
else if (extension.Equals(".m3u", StringComparison.OrdinalIgnoreCase))
{
var playlist = new M3uPlaylist
{
@@ -428,8 +426,7 @@ namespace Emby.Server.Implementations.Playlists
string text = new M3uContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase))
else if (extension.Equals(".m3u8", StringComparison.OrdinalIgnoreCase))
{
var playlist = new M3uPlaylist();
playlist.IsExtended = true;
@@ -458,8 +455,7 @@ namespace Emby.Server.Implementations.Playlists
string text = new M3uContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase))
else if (extension.Equals(".pls", StringComparison.OrdinalIgnoreCase))
{
var playlist = new PlsPlaylist();
foreach (var child in item.GetLinkedChildren())

View File

@@ -0,0 +1,103 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
namespace Emby.Server.Implementations;
/// <inheritdoc />
public class SystemManager : ISystemManager
{
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly IServerApplicationHost _applicationHost;
private readonly IServerApplicationPaths _applicationPaths;
private readonly IServerConfigurationManager _configurationManager;
private readonly IStartupOptions _startupOptions;
private readonly IInstallationManager _installationManager;
/// <summary>
/// Initializes a new instance of the <see cref="SystemManager"/> class.
/// </summary>
/// <param name="applicationLifetime">Instance of <see cref="IHostApplicationLifetime"/>.</param>
/// <param name="applicationHost">Instance of <see cref="IServerApplicationHost"/>.</param>
/// <param name="applicationPaths">Instance of <see cref="IServerApplicationPaths"/>.</param>
/// <param name="configurationManager">Instance of <see cref="IServerConfigurationManager"/>.</param>
/// <param name="startupOptions">Instance of <see cref="IStartupOptions"/>.</param>
/// <param name="installationManager">Instance of <see cref="IInstallationManager"/>.</param>
public SystemManager(
IHostApplicationLifetime applicationLifetime,
IServerApplicationHost applicationHost,
IServerApplicationPaths applicationPaths,
IServerConfigurationManager configurationManager,
IStartupOptions startupOptions,
IInstallationManager installationManager)
{
_applicationLifetime = applicationLifetime;
_applicationHost = applicationHost;
_applicationPaths = applicationPaths;
_configurationManager = configurationManager;
_startupOptions = startupOptions;
_installationManager = installationManager;
}
/// <inheritdoc />
public SystemInfo GetSystemInfo(HttpRequest request)
{
return new SystemInfo
{
HasPendingRestart = _applicationHost.HasPendingRestart,
IsShuttingDown = _applicationLifetime.ApplicationStopping.IsCancellationRequested,
Version = _applicationHost.ApplicationVersionString,
WebSocketPortNumber = _applicationHost.HttpPort,
CompletedInstallations = _installationManager.CompletedInstallations.ToArray(),
Id = _applicationHost.SystemId,
ProgramDataPath = _applicationPaths.ProgramDataPath,
WebPath = _applicationPaths.WebPath,
LogPath = _applicationPaths.LogDirectoryPath,
ItemsByNamePath = _applicationPaths.InternalMetadataPath,
InternalMetadataPath = _applicationPaths.InternalMetadataPath,
CachePath = _applicationPaths.CachePath,
TranscodingTempPath = _configurationManager.GetTranscodePath(),
ServerName = _applicationHost.FriendlyName,
LocalAddress = _applicationHost.GetSmartApiUrl(request),
SupportsLibraryMonitor = true,
PackageName = _startupOptions.PackageName
};
}
/// <inheritdoc />
public PublicSystemInfo GetPublicSystemInfo(HttpRequest request)
{
return new PublicSystemInfo
{
Version = _applicationHost.ApplicationVersionString,
ProductName = _applicationHost.Name,
Id = _applicationHost.SystemId,
ServerName = _applicationHost.FriendlyName,
LocalAddress = _applicationHost.GetSmartApiUrl(request),
StartupWizardCompleted = _configurationManager.CommonConfiguration.IsStartupWizardCompleted
};
}
/// <inheritdoc />
public void Restart() => ShutdownInternal(true);
/// <inheritdoc />
public void Shutdown() => ShutdownInternal(false);
private void ShutdownInternal(bool restart)
{
Task.Run(async () =>
{
await Task.Delay(100).ConfigureAwait(false);
_applicationHost.ShouldRestart = restart;
_applicationLifetime.StopApplication();
});
}
}

View File

@@ -52,7 +52,10 @@ namespace Emby.Server.Implementations.Udp
_endpoint = new IPEndPoint(bindAddress, port);
_udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp)
{
MulticastLoopback = false,
};
_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
@@ -74,6 +77,7 @@ namespace Emby.Server.Implementations.Udp
try
{
_logger.LogDebug("Sending AutoDiscovery response");
await _udpSocket.SendToAsync(JsonSerializer.SerializeToUtf8Bytes(response), SocketFlags.None, endpoint, cancellationToken).ConfigureAwait(false);
}
catch (SocketException ex)
@@ -99,7 +103,8 @@ namespace Emby.Server.Implementations.Udp
{
try
{
var result = await _udpSocket.ReceiveFromAsync(_receiveBuffer, SocketFlags.None, _endpoint, cancellationToken).ConfigureAwait(false);
var endpoint = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
var result = await _udpSocket.ReceiveFromAsync(_receiveBuffer, endpoint, cancellationToken).ConfigureAwait(false);
var text = Encoding.UTF8.GetString(_receiveBuffer, 0, result.ReceivedBytes);
if (text.Contains("who is JellyfinServer?", StringComparison.OrdinalIgnoreCase))
{
@@ -112,7 +117,7 @@ namespace Emby.Server.Implementations.Udp
}
catch (OperationCanceledException)
{
// Don't throw
_logger.LogDebug("Broadcast socket operation cancelled");
}
}
}

View File

@@ -504,8 +504,7 @@ namespace Emby.Server.Implementations.Updates
private async Task PerformPackageInstallation(InstallationInfo package, PluginStatus status, CancellationToken cancellationToken)
{
var extension = Path.GetExtension(package.SourceUrl);
if (!string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase))
if (!Path.GetExtension(package.SourceUrl.AsSpan()).Equals(".zip", StringComparison.OrdinalIgnoreCase))
{
_logger.LogError("Only zip packages are supported. {SourceUrl} is not a zip archive.", package.SourceUrl);
return;