You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

98 regels
3.7 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 MQTTnet.Core.Diagnostics;
  7. using MQTTnet.Core.Internal;
  8. namespace MQTTnet.Core.Server
  9. {
  10. public sealed class MqttServer : IMqttServer
  11. {
  12. private readonly MqttClientSessionsManager _clientSessionsManager;
  13. private readonly ICollection<IMqttServerAdapter> _adapters;
  14. private readonly MqttServerOptions _options;
  15. private CancellationTokenSource _cancellationTokenSource;
  16. public MqttServer(MqttServerOptions options, ICollection<IMqttServerAdapter> adapters)
  17. {
  18. _options = options ?? throw new ArgumentNullException(nameof(options));
  19. _adapters = adapters ?? throw new ArgumentNullException(nameof(adapters));
  20. _clientSessionsManager = new MqttClientSessionsManager(options);
  21. _clientSessionsManager.ApplicationMessageReceived += (s, e) => ApplicationMessageReceived?.Invoke(s, e);
  22. _clientSessionsManager.ClientConnected += OnClientConnected;
  23. _clientSessionsManager.ClientDisconnected += OnClientDisconnected;
  24. }
  25. public IReadOnlyList<ConnectedMqttClient> GetConnectedClients()
  26. {
  27. return _clientSessionsManager.GetConnectedClients();
  28. }
  29. public event EventHandler<MqttClientConnectedEventArgs> ClientConnected;
  30. public event EventHandler<MqttClientDisconnectedEventArgs> ClientDisconnected;
  31. public event EventHandler<MqttApplicationMessageReceivedEventArgs> ApplicationMessageReceived;
  32. public void Publish(MqttApplicationMessage applicationMessage)
  33. {
  34. if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
  35. _clientSessionsManager.DispatchPublishPacket(null, applicationMessage.ToPublishPacket());
  36. }
  37. public async Task StartAsync()
  38. {
  39. if (_cancellationTokenSource != null) throw new InvalidOperationException("The MQTT server is already started.");
  40. _cancellationTokenSource = new CancellationTokenSource();
  41. await _clientSessionsManager.RetainedMessagesManager.LoadMessagesAsync();
  42. foreach (var adapter in _adapters)
  43. {
  44. adapter.ClientAccepted += OnClientAccepted;
  45. await adapter.StartAsync(_options);
  46. }
  47. MqttNetTrace.Information(nameof(MqttServer), "Started.");
  48. }
  49. public async Task StopAsync()
  50. {
  51. _cancellationTokenSource?.Cancel(false);
  52. _cancellationTokenSource?.Dispose();
  53. _cancellationTokenSource = null;
  54. foreach (var adapter in _adapters)
  55. {
  56. adapter.ClientAccepted -= OnClientAccepted;
  57. await adapter.StopAsync();
  58. }
  59. _clientSessionsManager.Clear();
  60. MqttNetTrace.Information(nameof(MqttServer), "Stopped.");
  61. }
  62. private void OnClientAccepted(IMqttCommunicationAdapter adapter)
  63. {
  64. Task.Run(() =>_clientSessionsManager.RunClientSessionAsync(adapter), _cancellationTokenSource.Token);
  65. }
  66. private void OnClientConnected(object sender, MqttClientConnectedEventArgs eventArgs)
  67. {
  68. MqttNetTrace.Information(nameof(MqttServer), "Client '{0}': Connected.", eventArgs.Client.ClientId);
  69. ClientConnected?.Invoke(this, eventArgs);
  70. }
  71. private void OnClientDisconnected(object sender, MqttClientDisconnectedEventArgs eventArgs)
  72. {
  73. MqttNetTrace.Information(nameof(MqttServer), "Client '{0}': Disconnected.", eventArgs.Client.ClientId);
  74. ClientDisconnected?.Invoke(this, eventArgs);
  75. }
  76. }
  77. }