Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

104 linhas
3.6 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Threading.Tasks;
  5. using MQTTnet.Core.Channel;
  6. using MQTTnet.Core.Client;
  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 byte[] _readBuffer = new byte[BufferConstants.Size];
  18. private Task _sendTask = Task.FromResult(0); // this task is used to prevent overlapping write
  19. public MqttChannelCommunicationAdapter(IMqttCommunicationChannel channel, IMqttPacketSerializer serializer)
  20. {
  21. _channel = channel ?? throw new ArgumentNullException(nameof(channel));
  22. PacketSerializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
  23. }
  24. public IMqttPacketSerializer PacketSerializer { get; }
  25. public Task ConnectAsync(MqttClientOptions options, TimeSpan timeout)
  26. {
  27. return _channel.ConnectAsync(options).TimeoutAfter(timeout);
  28. }
  29. public Task DisconnectAsync()
  30. {
  31. return _channel.DisconnectAsync();
  32. }
  33. public async Task SendPacketsAsync(TimeSpan timeout, IEnumerable<MqttBasePacket> packets)
  34. {
  35. lock (_channel)
  36. {
  37. foreach (var packet in packets)
  38. {
  39. MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), "TX >>> {0} [Timeout={1}]", packet, timeout);
  40. var writeBuffer = PacketSerializer.Serialize(packet);
  41. _sendTask = _sendTask.ContinueWith(p => _channel.SendStream.WriteAsync(writeBuffer, 0, writeBuffer.Length));
  42. }
  43. }
  44. await _sendTask; // configure await false geneates stackoverflow
  45. await _channel.SendStream.FlushAsync().TimeoutAfter(timeout).ConfigureAwait(false);
  46. }
  47. public async Task<MqttBasePacket> ReceivePacketAsync(TimeSpan timeout)
  48. {
  49. Tuple<MqttPacketHeader, MemoryStream> tuple;
  50. if (timeout > TimeSpan.Zero)
  51. {
  52. tuple = await ReceiveAsync(_channel.RawStream).TimeoutAfter(timeout).ConfigureAwait(false);
  53. }
  54. else
  55. {
  56. tuple = await ReceiveAsync(_channel.ReceiveStream).ConfigureAwait(false);
  57. }
  58. var packet = PacketSerializer.Deserialize(tuple.Item1, tuple.Item2);
  59. if (packet == null)
  60. {
  61. throw new MqttProtocolViolationException("Received malformed packet.");
  62. }
  63. MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), "RX <<< {0}", packet);
  64. return packet;
  65. }
  66. private async Task<Tuple<MqttPacketHeader, MemoryStream>> ReceiveAsync(Stream stream)
  67. {
  68. var header = MqttPacketReader.ReadHeaderFromSource(stream);
  69. MemoryStream body;
  70. if (header.BodyLength > 0)
  71. {
  72. var totalRead = 0;
  73. do
  74. {
  75. var read = await stream.ReadAsync(_readBuffer, totalRead, header.BodyLength - totalRead).ConfigureAwait(false);
  76. totalRead += read;
  77. } while (totalRead < header.BodyLength);
  78. body = new MemoryStream(_readBuffer, 0, header.BodyLength);
  79. }
  80. else
  81. {
  82. body = new MemoryStream();
  83. }
  84. return Tuple.Create(header, body);
  85. }
  86. }
  87. }