Não pode escolher mais do que 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.
 
 
 
 

189 linhas
5.7 KiB

  1. #if WINDOWS_UWP
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Runtime.InteropServices.WindowsRuntime;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. using Windows.Networking;
  10. using Windows.Networking.Sockets;
  11. using Windows.Security.Cryptography.Certificates;
  12. using MQTTnet.Channel;
  13. using MQTTnet.Client;
  14. namespace MQTTnet.Implementations
  15. {
  16. public sealed class MqttTcpChannel : IMqttChannel
  17. {
  18. // ReSharper disable once MemberCanBePrivate.Global
  19. // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Global
  20. public static int BufferSize { get; set; } = 4096; // Can be changed for fine tuning by library user.
  21. private readonly int _bufferSize = BufferSize;
  22. private readonly MqttClientTcpOptions _options;
  23. private StreamSocket _socket;
  24. private Stream _readStream;
  25. private Stream _writeStream;
  26. public MqttTcpChannel(MqttClientTcpOptions options)
  27. {
  28. _options = options ?? throw new ArgumentNullException(nameof(options));
  29. _bufferSize = options.BufferSize;
  30. }
  31. public MqttTcpChannel(StreamSocket socket)
  32. {
  33. _socket = socket ?? throw new ArgumentNullException(nameof(socket));
  34. CreateStreams();
  35. }
  36. public static Func<MqttClientTcpOptions, IEnumerable<ChainValidationResult>> CustomIgnorableServerCertificateErrorsResolver { get; set; }
  37. public async Task ConnectAsync(CancellationToken cancellationToken)
  38. {
  39. if (_socket == null)
  40. {
  41. _socket = new StreamSocket();
  42. _socket.Control.NoDelay = true;
  43. }
  44. if (!_options.TlsOptions.UseTls)
  45. {
  46. await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString());
  47. }
  48. else
  49. {
  50. _socket.Control.ClientCertificate = LoadCertificate(_options);
  51. foreach (var ignorableChainValidationResult in ResolveIgnorableServerCertificateErrors())
  52. {
  53. _socket.Control.IgnorableServerCertificateErrors.Add(ignorableChainValidationResult);
  54. }
  55. await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), SocketProtectionLevel.Tls12);
  56. }
  57. CreateStreams();
  58. }
  59. public Task DisconnectAsync()
  60. {
  61. Dispose();
  62. return Task.FromResult(0);
  63. }
  64. public Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  65. {
  66. return _readStream.ReadAsync(buffer, offset, count, cancellationToken);
  67. }
  68. public async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  69. {
  70. await _writeStream.WriteAsync(buffer, offset, count, cancellationToken);
  71. await _writeStream.FlushAsync(cancellationToken);
  72. }
  73. public void Dispose()
  74. {
  75. try
  76. {
  77. _readStream?.Dispose();
  78. }
  79. catch (ObjectDisposedException)
  80. {
  81. }
  82. catch (NullReferenceException)
  83. {
  84. }
  85. finally
  86. {
  87. _readStream = null;
  88. }
  89. try
  90. {
  91. _writeStream?.Dispose();
  92. }
  93. catch (ObjectDisposedException)
  94. {
  95. }
  96. catch (NullReferenceException)
  97. {
  98. }
  99. finally
  100. {
  101. _writeStream = null;
  102. }
  103. try
  104. {
  105. _socket?.Dispose();
  106. }
  107. catch (ObjectDisposedException)
  108. {
  109. }
  110. catch (NullReferenceException)
  111. {
  112. }
  113. finally
  114. {
  115. _socket = null;
  116. }
  117. }
  118. private static Certificate LoadCertificate(MqttClientTcpOptions options)
  119. {
  120. if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any())
  121. {
  122. return null;
  123. }
  124. if (options.TlsOptions.Certificates.Count > 1)
  125. {
  126. throw new NotSupportedException("Only one client certificate is supported for UWP.");
  127. }
  128. return new Certificate(options.TlsOptions.Certificates.First().AsBuffer());
  129. }
  130. private IEnumerable<ChainValidationResult> ResolveIgnorableServerCertificateErrors()
  131. {
  132. if (CustomIgnorableServerCertificateErrorsResolver != null)
  133. {
  134. return CustomIgnorableServerCertificateErrorsResolver(_options);
  135. }
  136. var result = new List<ChainValidationResult>();
  137. if (_options.TlsOptions.IgnoreCertificateRevocationErrors)
  138. {
  139. result.Add(ChainValidationResult.RevocationInformationMissing);
  140. //_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked); Not supported.
  141. result.Add(ChainValidationResult.RevocationFailure);
  142. }
  143. if (_options.TlsOptions.IgnoreCertificateChainErrors)
  144. {
  145. result.Add(ChainValidationResult.IncompleteChain);
  146. }
  147. if (_options.TlsOptions.AllowUntrustedCertificates)
  148. {
  149. result.Add(ChainValidationResult.Untrusted);
  150. }
  151. return result;
  152. }
  153. private void CreateStreams()
  154. {
  155. _readStream = _socket.InputStream.AsStreamForRead(_bufferSize);
  156. _writeStream = _socket.OutputStream.AsStreamForWrite(_bufferSize);
  157. }
  158. }
  159. }
  160. #endif