UdpServerEntryPoint.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. _udpServers.Add(new UdpServer(_logger, _appHost, _config, IPAddress.Broadcast, PortNumber));
  79. // Add bind address specific broadcast sockets
  80. // IPv6 is currently unsupported
  81. var validInterfaces = _networkManager.GetInternalBindAddresses().Where(i => i.AddressFamily == AddressFamily.InterNetwork);
  82. foreach (var intf in validInterfaces)
  83. {
  84. var broadcastAddress = NetworkExtensions.GetBroadcastAddress(intf.Subnet);
  85. _logger.LogDebug("Binding UDP server to {Address} on port {PortNumber}", broadcastAddress.ToString(), PortNumber);
  86. var server = new UdpServer(_logger, _appHost, _config, broadcastAddress, PortNumber);
  87. server.Start(_cancellationTokenSource.Token);
  88. _udpServers.Add(server);
  89. }
  90. }
  91. else
  92. {
  93. var server = new UdpServer(_logger, _appHost, _config, IPAddress.Any, PortNumber);
  94. server.Start(_cancellationTokenSource.Token);
  95. _udpServers.Add(server);
  96. }
  97. }
  98. catch (SocketException ex)
  99. {
  100. _logger.LogWarning(ex, "Unable to start AutoDiscovery listener on UDP port {PortNumber}", PortNumber);
  101. }
  102. return Task.CompletedTask;
  103. }
  104. private void CheckDisposed()
  105. {
  106. if (_disposed)
  107. {
  108. throw new ObjectDisposedException(this.GetType().Name);
  109. }
  110. }
  111. /// <inheritdoc />
  112. public void Dispose()
  113. {
  114. if (_disposed)
  115. {
  116. return;
  117. }
  118. _cancellationTokenSource.Cancel();
  119. _cancellationTokenSource.Dispose();
  120. foreach (var server in _udpServers)
  121. {
  122. server.Dispose();
  123. }
  124. _udpServers.Clear();
  125. _disposed = true;
  126. }
  127. }
  128. }