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

112 行
4.1 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading.Tasks;
  5. using MQTTnet.Core.Packets;
  6. using Microsoft.Extensions.Logging;
  7. using Microsoft.Extensions.Options;
  8. namespace MQTTnet.Core.Server
  9. {
  10. public sealed class MqttClientRetainedMessagesManager
  11. {
  12. private readonly Dictionary<string, MqttApplicationMessage> _retainedMessages = new Dictionary<string, MqttApplicationMessage>();
  13. private readonly ILogger<MqttClientRetainedMessagesManager> _logger;
  14. private readonly MqttServerOptions _options;
  15. public MqttClientRetainedMessagesManager(IOptions<MqttServerOptions> options, ILogger<MqttClientRetainedMessagesManager> logger)
  16. {
  17. _logger = logger ?? throw new ArgumentNullException(nameof(logger));
  18. _options = options.Value ?? 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;
  35. }
  36. }
  37. }
  38. catch (Exception exception)
  39. {
  40. _logger.LogError(new EventId(), exception, "Unhandled exception while loading retained messages.");
  41. }
  42. }
  43. public async Task HandleMessageAsync(string clientId, MqttApplicationMessage applicationMessage)
  44. {
  45. if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage));
  46. List<MqttApplicationMessage> allRetainedMessages;
  47. lock (_retainedMessages)
  48. {
  49. if (applicationMessage.Payload?.Any() == false)
  50. {
  51. _retainedMessages.Remove(applicationMessage.Topic);
  52. _logger.LogInformation("Client '{0}' cleared retained message for topic '{1}'.", clientId, applicationMessage.Topic);
  53. }
  54. else
  55. {
  56. _retainedMessages[applicationMessage.Topic] = applicationMessage;
  57. _logger.LogInformation("Client '{0}' updated retained message for topic '{1}'.", clientId, applicationMessage.Topic);
  58. }
  59. allRetainedMessages = new List<MqttApplicationMessage>(_retainedMessages.Values);
  60. }
  61. try
  62. {
  63. // ReSharper disable once UseNullPropagation
  64. if (_options.Storage != null)
  65. {
  66. await _options.Storage.SaveRetainedMessagesAsync(allRetainedMessages);
  67. }
  68. }
  69. catch (Exception exception)
  70. {
  71. _logger.LogError(new EventId(), exception, "Unhandled exception while saving retained messages.");
  72. }
  73. }
  74. public List<MqttApplicationMessage> GetMessages(MqttSubscribePacket subscribePacket)
  75. {
  76. var retainedMessages = new List<MqttApplicationMessage>();
  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. }