You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

138 line
4.3 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.Tasks;
  8. using Windows.Networking;
  9. using Windows.Networking.Sockets;
  10. using Windows.Security.Cryptography.Certificates;
  11. using MQTTnet.Core.Channel;
  12. using MQTTnet.Core.Client;
  13. namespace MQTTnet.Implementations
  14. {
  15. public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
  16. {
  17. private readonly MqttClientTcpOptions _options;
  18. private StreamSocket _socket;
  19. public MqttTcpChannel(MqttClientTcpOptions options)
  20. {
  21. _options = options ?? throw new ArgumentNullException(nameof(options));
  22. }
  23. public MqttTcpChannel(StreamSocket socket)
  24. {
  25. _socket = socket ?? throw new ArgumentNullException(nameof(socket));
  26. CreateStreams();
  27. }
  28. public Stream SendStream { get; private set; }
  29. public Stream ReceiveStream { get; private set; }
  30. public Stream RawReceiveStream { get; private set; }
  31. public static Func<MqttClientTcpOptions, IEnumerable<ChainValidationResult>> CustomIgnorableServerCertificateErrorsResolver { get; set; }
  32. public async Task ConnectAsync()
  33. {
  34. if (_socket == null)
  35. {
  36. _socket = new StreamSocket();
  37. }
  38. if (!_options.TlsOptions.UseTls)
  39. {
  40. await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString());
  41. }
  42. else
  43. {
  44. _socket.Control.ClientCertificate = LoadCertificate(_options);
  45. foreach (var ignorableChainValidationResult in ResolveIgnorableServerCertificateErrors())
  46. {
  47. _socket.Control.IgnorableServerCertificateErrors.Add(ignorableChainValidationResult);
  48. }
  49. await _socket.ConnectAsync(new HostName(_options.Server), _options.GetPort().ToString(), SocketProtectionLevel.Tls12);
  50. }
  51. CreateStreams();
  52. }
  53. public Task DisconnectAsync()
  54. {
  55. Dispose();
  56. return Task.FromResult(0);
  57. }
  58. public void Dispose()
  59. {
  60. RawReceiveStream?.Dispose();
  61. RawReceiveStream = null;
  62. SendStream?.Dispose();
  63. SendStream = null;
  64. ReceiveStream?.Dispose();
  65. ReceiveStream = null;
  66. _socket?.Dispose();
  67. _socket = null;
  68. }
  69. private void CreateStreams()
  70. {
  71. SendStream = _socket.OutputStream.AsStreamForWrite();
  72. ReceiveStream = _socket.InputStream.AsStreamForRead();
  73. RawReceiveStream = ReceiveStream;
  74. }
  75. private static Certificate LoadCertificate(MqttClientTcpOptions options)
  76. {
  77. if (options.TlsOptions.Certificates == null || !options.TlsOptions.Certificates.Any())
  78. {
  79. return null;
  80. }
  81. if (options.TlsOptions.Certificates.Count > 1)
  82. {
  83. throw new NotSupportedException("Only one client certificate is supported for UWP.");
  84. }
  85. return new Certificate(options.TlsOptions.Certificates.First().AsBuffer());
  86. }
  87. private IEnumerable<ChainValidationResult> ResolveIgnorableServerCertificateErrors()
  88. {
  89. if (CustomIgnorableServerCertificateErrorsResolver != null)
  90. {
  91. return CustomIgnorableServerCertificateErrorsResolver(_options);
  92. }
  93. var result = new List<ChainValidationResult>();
  94. if (_options.TlsOptions.IgnoreCertificateRevocationErrors)
  95. {
  96. result.Add(ChainValidationResult.RevocationInformationMissing);
  97. //_socket.Control.IgnorableServerCertificateErrors.Add(ChainValidationResult.Revoked); Not supported.
  98. result.Add(ChainValidationResult.RevocationFailure);
  99. }
  100. if (_options.TlsOptions.IgnoreCertificateChainErrors)
  101. {
  102. result.Add(ChainValidationResult.IncompleteChain);
  103. }
  104. if (_options.TlsOptions.AllowUntrustedCertificates)
  105. {
  106. result.Add(ChainValidationResult.Untrusted);
  107. }
  108. return result;
  109. }
  110. }
  111. }
  112. #endif