UdpServerEntryPoint.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using Emby.Server.Implementations.Udp;
  9. using Jellyfin.Networking.Configuration;
  10. using MediaBrowser.Common.Configuration;
  11. using MediaBrowser.Common.Net;
  12. using MediaBrowser.Controller;
  13. using MediaBrowser.Controller.Plugins;
  14. using Microsoft.Extensions.Configuration;
  15. using Microsoft.Extensions.Logging;
  16. namespace Emby.Server.Implementations.EntryPoints
  17. {
  18. /// <summary>
  19. /// Class UdpServerEntryPoint.
  20. /// </summary>
  21. public sealed class UdpServerEntryPoint : IServerEntryPoint
  22. {
  23. /// <summary>
  24. /// The port of the UDP server.
  25. /// </summary>
  26. public const int PortNumber = 7359;
  27. /// <summary>
  28. /// The logger.
  29. /// </summary>
  30. private readonly ILogger<UdpServerEntryPoint> _logger;
  31. private readonly IServerApplicationHost _appHost;
  32. private readonly IConfiguration _config;
  33. private readonly IConfigurationManager _configurationManager;
  34. private readonly INetworkManager _networkManager;
  35. private readonly bool _enableMultiSocketBinding;
  36. /// <summary>
  37. /// The UDP server.
  38. /// </summary>
  39. private List<UdpServer> _udpServers;
  40. private CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
  41. private bool _disposed = false;
  42. /// <summary>
  43. /// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
  44. /// </summary>
  45. /// <param name="logger">Instance of the <see cref="ILogger{UdpServerEntryPoint}"/> interface.</param>
  46. /// <param name="appHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
  47. /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
  48. /// <param name="configurationManager">Instance of the <see cref="IConfigurationManager"/> interface.</param>
  49. /// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param>
  50. public UdpServerEntryPoint(
  51. ILogger<UdpServerEntryPoint> logger,
  52. IServerApplicationHost appHost,
  53. IConfiguration configuration,
  54. IConfigurationManager configurationManager,
  55. INetworkManager networkManager)
  56. {
  57. _logger = logger;
  58. _appHost = appHost;
  59. _config = configuration;
  60. _configurationManager = configurationManager;
  61. _networkManager = networkManager;
  62. _udpServers = new List<UdpServer>();
  63. _enableMultiSocketBinding = OperatingSystem.IsWindows() || OperatingSystem.IsLinux();
  64. }
  65. /// <inheritdoc />
  66. public Task RunAsync()
  67. {
  68. CheckDisposed();
  69. if (!_configurationManager.GetNetworkConfiguration().AutoDiscovery)
  70. {
  71. return Task.CompletedTask;
  72. }
  73. try
  74. {
  75. if (_enableMultiSocketBinding)
  76. {
  77. // Add global broadcast socket
  78. var server = new UdpServer(_logger, _appHost, _config, IPAddress.Broadcast, PortNumber);
  79. server.Start(_cancellationTokenSource.Token);
  80. _udpServers.Add(server);
  81. // Add bind address specific broadcast sockets
  82. // IPv6 is currently unsupported
  83. var validInterfaces = _networkManager.GetInternalBindAddresses().Where(i => i.AddressFamily == AddressFamily.InterNetwork);
  84. foreach (var intf in validInterfaces)
  85. {
  86. var broadcastAddress = NetworkExtensions.GetBroadcastAddress(intf.Subnet);
  87. _logger.LogDebug("Binding UDP server to {Address} on port {PortNumber}", broadcastAddress, PortNumber);
  88. server = new UdpServer(_logger, _appHost, _config, broadcastAddress, PortNumber);
  89. server.Start(_cancellationTokenSource.Token);
  90. _udpServers.Add(server);
  91. }
  92. }
  93. else
  94. {
  95. var server = new UdpServer(_logger, _appHost, _config, IPAddress.Any, PortNumber);
  96. server.Start(_cancellationTokenSource.Token);
  97. _udpServers.Add(server);
  98. }
  99. }
  100. catch (SocketException ex)
  101. {
  102. _logger.LogWarning(ex, "Unable to start AutoDiscovery listener on UDP port {PortNumber}", PortNumber);
  103. }
  104. return Task.CompletedTask;
  105. }
  106. private void CheckDisposed()
  107. {
  108. if (_disposed)
  109. {
  110. throw new ObjectDisposedException(this.GetType().Name);
  111. }
  112. }
  113. /// <inheritdoc />
  114. public void Dispose()
  115. {
  116. if (_disposed)
  117. {
  118. return;
  119. }
  120. _cancellationTokenSource.Cancel();
  121. _cancellationTokenSource.Dispose();
  122. foreach (var server in _udpServers)
  123. {
  124. server.Dispose();
  125. }
  126. _udpServers.Clear();
  127. _disposed = true;
  128. }
  129. }
  130. }