Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

139 строки
5.4 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using MQTTnet.Core.Adapter;
  6. using Microsoft.Extensions.Logging;
  7. using Microsoft.Extensions.Options;
  8. using System.Linq;
  9. namespace MQTTnet.Core.Server
  10. {
  11. public class MqttServer : IMqttServer
  12. {
  13. private readonly IMqttClientRetainedMessageManager _clientRetainedMessageManager;
  14. private readonly ILogger<MqttServer> _logger;
  15. private readonly MqttClientSessionsManager _clientSessionsManager;
  16. private readonly ICollection<IMqttServerAdapter> _adapters;
  17. private readonly MqttServerOptions _options;
  18. private CancellationTokenSource _cancellationTokenSource;
  19. public MqttServer(
  20. IOptions<MqttServerOptions> options,
  21. IEnumerable<IMqttServerAdapter> adapters,
  22. ILogger<MqttServer> logger,
  23. MqttClientSessionsManager clientSessionsManager,
  24. IMqttClientRetainedMessageManager clientRetainedMessageManager
  25. )
  26. {
  27. _options = options.Value ?? throw new ArgumentNullException(nameof(options));
  28. _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  29. _clientSessionsManager = clientSessionsManager ?? throw new ArgumentNullException(nameof(clientSessionsManager));
  30. _clientRetainedMessageManager = clientRetainedMessageManager ?? throw new ArgumentNullException(nameof(clientRetainedMessageManager));
  31. if (adapters == null)
  32. {
  33. throw new ArgumentNullException(nameof(adapters));
  34. }
  35. _adapters = adapters.ToList();
  36. _clientSessionsManager.ApplicationMessageReceived += (s, e) => ApplicationMessageReceived?.Invoke(s, e);
  37. _clientSessionsManager.ClientConnected += OnClientConnected;
  38. _clientSessionsManager.ClientDisconnected += OnClientDisconnected;
  39. }
  40. public IList<ConnectedMqttClient> GetConnectedClients()
  41. {
  42. return _clientSessionsManager.GetConnectedClients();
  43. }
  44. public event EventHandler<MqttServerStartedEventArgs> Started;
  45. public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
  46. public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
  47. public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
  48. public void Publish(IEnumerable<MqttApplicationMessage> applicationMessages)
  49. {
  50. if (applicationMessages == null) throw new ArgumentNullException(nameof(applicationMessages));
  51. if (_cancellationTokenSource == null)
  52. {
  53. throw new InvalidOperationException("The server is not started.");
  54. }
  55. foreach (var applicationMessage in applicationMessages)
  56. {
  57. var interceptorContext = new MqttApplicationMessageInterceptorContext
  58. {
  59. ApplicationMessage = applicationMessage
  60. };
  61. _options.ApplicationMessageInterceptor?.Invoke(interceptorContext);
  62. _clientSessionsManager.DispatchApplicationMessage(null, interceptorContext.ApplicationMessage);
  63. }
  64. }
  65. public Task PublishAsync(IEnumerable<MqttApplicationMessage> applicationMessages)
  66. {
  67. Publish(applicationMessages);
  68. return Task.FromResult(0);
  69. }
  70. public async Task StartAsync()
  71. {
  72. if (_cancellationTokenSource != null) throw new InvalidOperationException("The MQTT server is already started.");
  73. _cancellationTokenSource = new CancellationTokenSource();
  74. await _clientRetainedMessageManager.LoadMessagesAsync();
  75. foreach (var adapter in _adapters)
  76. {
  77. adapter.ClientAccepted += OnClientAccepted;
  78. await adapter.StartAsync(_options);
  79. }
  80. _logger.LogInformation("Started.");
  81. Started?.Invoke(this, new MqttServerStartedEventArgs());
  82. }
  83. public async Task StopAsync()
  84. {
  85. _cancellationTokenSource?.Cancel(false);
  86. _cancellationTokenSource?.Dispose();
  87. _cancellationTokenSource = null;
  88. foreach (var adapter in _adapters)
  89. {
  90. adapter.ClientAccepted -= OnClientAccepted;
  91. await adapter.StopAsync();
  92. }
  93. _clientSessionsManager.Clear();
  94. _logger.LogInformation("Stopped.");
  95. }
  96. private void OnClientAccepted(object sender, MqttServerAdapterClientAcceptedEventArgs eventArgs)
  97. {
  98. eventArgs.SessionTask = Task.Run(async () => await _clientSessionsManager.RunClientSessionAsync(eventArgs.Client, _cancellationTokenSource.Token), _cancellationTokenSource.Token);
  99. }
  100. private void OnClientConnected(object sender, MqttClientConnectedEventArgs eventArgs)
  101. {
  102. _logger.LogInformation("Client '{0}': Connected.", eventArgs.Client.ClientId);
  103. ClientConnected?.Invoke(this, eventArgs);
  104. }
  105. private void OnClientDisconnected(object sender, MqttClientDisconnectedEventArgs eventArgs)
  106. {
  107. _logger.LogInformation("Client '{0}': Disconnected.", eventArgs.Client.ClientId);
  108. ClientDisconnected?.Invoke(this, eventArgs);
  109. }
  110. }
  111. }