Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 

210 řádky
6.6 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using MQTTnet.Core.Channel;
  7. using MQTTnet.Core.Diagnostics;
  8. using MQTTnet.Core.Exceptions;
  9. using MQTTnet.Core.Internal;
  10. using MQTTnet.Core.Packets;
  11. using MQTTnet.Core.Serializer;
  12. namespace MQTTnet.Core.Adapter
  13. {
  14. public class MqttChannelCommunicationAdapter : IMqttCommunicationAdapter
  15. {
  16. private readonly IMqttCommunicationChannel _channel;
  17. private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
  18. public MqttChannelCommunicationAdapter(IMqttCommunicationChannel channel, IMqttPacketSerializer serializer)
  19. {
  20. _channel = channel ?? throw new ArgumentNullException(nameof(channel));
  21. PacketSerializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
  22. }
  23. public IMqttPacketSerializer PacketSerializer { get; }
  24. public async Task ConnectAsync(TimeSpan timeout)
  25. {
  26. try
  27. {
  28. await _channel.ConnectAsync().TimeoutAfter(timeout).ConfigureAwait(false);
  29. }
  30. catch (TaskCanceledException)
  31. {
  32. throw;
  33. }
  34. catch (OperationCanceledException)
  35. {
  36. throw;
  37. }
  38. catch (MqttCommunicationTimedOutException)
  39. {
  40. throw;
  41. }
  42. catch (MqttCommunicationException)
  43. {
  44. throw;
  45. }
  46. catch (Exception exception)
  47. {
  48. throw new MqttCommunicationException(exception);
  49. }
  50. }
  51. public async Task DisconnectAsync(TimeSpan timeout)
  52. {
  53. try
  54. {
  55. await _channel.DisconnectAsync().TimeoutAfter(timeout).ConfigureAwait(false);
  56. }
  57. catch (TaskCanceledException)
  58. {
  59. throw;
  60. }
  61. catch (OperationCanceledException)
  62. {
  63. throw;
  64. }
  65. catch (MqttCommunicationTimedOutException)
  66. {
  67. throw;
  68. }
  69. catch (MqttCommunicationException)
  70. {
  71. throw;
  72. }
  73. catch (Exception exception)
  74. {
  75. throw new MqttCommunicationException(exception);
  76. }
  77. }
  78. public async Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable<MqttBasePacket> packets)
  79. {
  80. await _semaphore.WaitAsync(cancellationToken);
  81. try
  82. {
  83. foreach (var packet in packets)
  84. {
  85. if (packet == null)
  86. {
  87. continue;
  88. }
  89. MqttNetTrace.Information(nameof(MqttChannelCommunicationAdapter), "TX >>> {0} [Timeout={1}]", packet, timeout);
  90. var writeBuffer = PacketSerializer.Serialize(packet);
  91. await _channel.SendStream.WriteAsync(writeBuffer, 0, writeBuffer.Length, cancellationToken).ConfigureAwait(false);
  92. }
  93. if (timeout > TimeSpan.Zero)
  94. {
  95. await _channel.SendStream.FlushAsync(cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false);
  96. }
  97. else
  98. {
  99. await _channel.SendStream.FlushAsync(cancellationToken).ConfigureAwait(false);
  100. }
  101. }
  102. catch (TaskCanceledException)
  103. {
  104. throw;
  105. }
  106. catch (OperationCanceledException)
  107. {
  108. throw;
  109. }
  110. catch (MqttCommunicationTimedOutException)
  111. {
  112. throw;
  113. }
  114. catch (MqttCommunicationException)
  115. {
  116. throw;
  117. }
  118. catch (Exception exception)
  119. {
  120. throw new MqttCommunicationException(exception);
  121. }
  122. finally
  123. {
  124. _semaphore.Release();
  125. }
  126. }
  127. public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken)
  128. {
  129. try
  130. {
  131. ReceivedMqttPacket receivedMqttPacket;
  132. if (timeout > TimeSpan.Zero)
  133. {
  134. receivedMqttPacket = await ReceiveAsync(_channel.RawReceiveStream, cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false);
  135. }
  136. else
  137. {
  138. receivedMqttPacket = await ReceiveAsync(_channel.ReceiveStream, cancellationToken).ConfigureAwait(false);
  139. }
  140. if (cancellationToken.IsCancellationRequested)
  141. {
  142. throw new TaskCanceledException();
  143. }
  144. var packet = PacketSerializer.Deserialize(receivedMqttPacket);
  145. if (packet == null)
  146. {
  147. throw new MqttProtocolViolationException("Received malformed packet.");
  148. }
  149. MqttNetTrace.Information(nameof(MqttChannelCommunicationAdapter), "RX <<< {0}", packet);
  150. return packet;
  151. }
  152. catch (TaskCanceledException)
  153. {
  154. throw;
  155. }
  156. catch (OperationCanceledException)
  157. {
  158. throw;
  159. }
  160. catch (MqttCommunicationTimedOutException)
  161. {
  162. throw;
  163. }
  164. catch (MqttCommunicationException)
  165. {
  166. throw;
  167. }
  168. catch (Exception exception)
  169. {
  170. throw new MqttCommunicationException(exception);
  171. }
  172. }
  173. private static async Task<ReceivedMqttPacket> ReceiveAsync(Stream stream, CancellationToken cancellationToken)
  174. {
  175. var header = MqttPacketReader.ReadHeaderFromSource(stream, cancellationToken);
  176. if (header.BodyLength == 0)
  177. {
  178. return new ReceivedMqttPacket(header, new MemoryStream(0));
  179. }
  180. var body = new byte[header.BodyLength];
  181. var offset = 0;
  182. do
  183. {
  184. var readBytesCount = await stream.ReadAsync(body, offset, body.Length - offset, cancellationToken).ConfigureAwait(false);
  185. offset += readBytesCount;
  186. } while (offset < header.BodyLength);
  187. return new ReceivedMqttPacket(header, new MemoryStream(body, 0, body.Length));
  188. }
  189. }
  190. }