選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

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