Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

112 righe
4.1 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using MQTTnet.Core.Diagnostics;
  6. using MQTTnet.Core.Internal;
  7. using MQTTnet.Core.Packets;
  8. namespace MQTTnet.Core.Server
  9. {
  10. public sealed class MqttClientRetainedMessagesManager
  11. {
  12. private readonly MqttNetTrace _trace;
  13. private readonly Dictionary<string, MqttPublishPacket> _retainedMessages = new Dictionary<string, MqttPublishPacket>();
  14. private readonly MqttServerOptions _options;
  15. public MqttClientRetainedMessagesManager(MqttServerOptions options, MqttNetTrace trace)
  16. {
  17. _trace = trace ?? throw new ArgumentNullException(nameof(trace));
  18. _options = options ?? throw new ArgumentNullException(nameof(options));
  19. }
  20. public async Task LoadMessagesAsync()
  21. {
  22. if (_options.Storage == null)
  23. {
  24. return;
  25. }
  26. try
  27. {
  28. var retainedMessages = await _options.Storage.LoadRetainedMessagesAsync();
  29. lock (_retainedMessages)
  30. {
  31. _retainedMessages.Clear();
  32. foreach (var retainedMessage in retainedMessages)
  33. {
  34. _retainedMessages[retainedMessage.Topic] = retainedMessage.ToPublishPacket();
  35. }
  36. }
  37. }
  38. catch (Exception exception)
  39. {
  40. _trace.Error(nameof(MqttClientRetainedMessagesManager), exception, "Unhandled exception while loading retained messages.");
  41. }
  42. }
  43. public async Task HandleMessageAsync(string clientId, MqttPublishPacket publishPacket)
  44. {
  45. if (publishPacket == null) throw new ArgumentNullException(nameof(publishPacket));
  46. List<MqttPublishPacket> allRetainedMessages;
  47. lock (_retainedMessages)
  48. {
  49. if (publishPacket.Payload?.Any() == false)
  50. {
  51. _retainedMessages.Remove(publishPacket.Topic);
  52. _trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' cleared retained message for topic '{1}'.", clientId, publishPacket.Topic);
  53. }
  54. else
  55. {
  56. _retainedMessages[publishPacket.Topic] = publishPacket;
  57. _trace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' updated retained message for topic '{1}'.", clientId, publishPacket.Topic);
  58. }
  59. allRetainedMessages = new List<MqttPublishPacket>(_retainedMessages.Values);
  60. }
  61. try
  62. {
  63. // ReSharper disable once UseNullPropagation
  64. if (_options.Storage != null)
  65. {
  66. await _options.Storage.SaveRetainedMessagesAsync(allRetainedMessages.Select(p => p.ToApplicationMessage()).ToList());
  67. }
  68. }
  69. catch (Exception exception)
  70. {
  71. _trace.Error(nameof(MqttClientRetainedMessagesManager), exception, "Unhandled exception while saving retained messages.");
  72. }
  73. }
  74. public List<MqttPublishPacket> GetMessages(MqttSubscribePacket subscribePacket)
  75. {
  76. var retainedMessages = new List<MqttPublishPacket>();
  77. lock (_retainedMessages)
  78. {
  79. foreach (var retainedMessage in _retainedMessages.Values)
  80. {
  81. foreach (var topicFilter in subscribePacket.TopicFilters)
  82. {
  83. if (retainedMessage.QualityOfServiceLevel < topicFilter.QualityOfServiceLevel)
  84. {
  85. continue;
  86. }
  87. if (!MqttTopicFilterComparer.IsMatch(retainedMessage.Topic, topicFilter.Topic))
  88. {
  89. continue;
  90. }
  91. retainedMessages.Add(retainedMessage);
  92. break;
  93. }
  94. }
  95. }
  96. return retainedMessages;
  97. }
  98. }
  99. }