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.
 
 
 
 

109 rivejä
3.3 KiB

  1. using System;
  2. using System.Net.Security;
  3. using System.Net.Sockets;
  4. using System.Security.Authentication;
  5. using System.Security.Cryptography.X509Certificates;
  6. using System.Threading.Tasks;
  7. using MQTTnet.Core.Channel;
  8. using MQTTnet.Core.Client;
  9. using MQTTnet.Core.Exceptions;
  10. using System.IO;
  11. namespace MQTTnet.Implementations
  12. {
  13. public sealed class MqttTcpChannel : IMqttCommunicationChannel, IDisposable
  14. {
  15. private Socket _socket;
  16. private SslStream _sslStream;
  17. public Stream ReceiveStream { get; private set; }
  18. public Stream RawStream => ReceiveStream;
  19. public Stream SendStream => ReceiveStream;
  20. /// <summary>
  21. /// called on client sockets are created in connect
  22. /// </summary>
  23. public MqttTcpChannel()
  24. {
  25. }
  26. /// <summary>
  27. /// called on server, sockets are passed in
  28. /// connect will not be called
  29. /// </summary>
  30. public MqttTcpChannel(Socket socket, SslStream sslStream)
  31. {
  32. _socket = socket ?? throw new ArgumentNullException(nameof(socket));
  33. _sslStream = sslStream;
  34. ReceiveStream = (Stream)sslStream ?? new NetworkStream(socket);
  35. }
  36. public async Task ConnectAsync(MqttClientOptions options)
  37. {
  38. if (options == null) throw new ArgumentNullException(nameof(options));
  39. try
  40. {
  41. if (_socket == null)
  42. {
  43. _socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
  44. }
  45. await _socket.ConnectAsync(options.Server, options.GetPort()).ConfigureAwait(false);
  46. if (options.TlsOptions.UseTls)
  47. {
  48. _sslStream = new SslStream(new NetworkStream(_socket, true));
  49. ReceiveStream = _sslStream;
  50. await _sslStream.AuthenticateAsClientAsync(options.Server, LoadCertificates(options), SslProtocols.Tls12, options.TlsOptions.CheckCertificateRevocation).ConfigureAwait(false);
  51. }
  52. else
  53. {
  54. ReceiveStream = new NetworkStream(_socket);
  55. }
  56. }
  57. catch (SocketException exception)
  58. {
  59. throw new MqttCommunicationException(exception);
  60. }
  61. }
  62. public Task DisconnectAsync()
  63. {
  64. try
  65. {
  66. Dispose();
  67. return Task.FromResult(0);
  68. }
  69. catch (SocketException exception)
  70. {
  71. throw new MqttCommunicationException(exception);
  72. }
  73. }
  74. public void Dispose()
  75. {
  76. _socket?.Dispose();
  77. _sslStream?.Dispose();
  78. _socket = null;
  79. _sslStream = null;
  80. }
  81. private static X509CertificateCollection LoadCertificates(MqttClientOptions options)
  82. {
  83. var certificates = new X509CertificateCollection();
  84. if (options.TlsOptions.Certificates == null)
  85. {
  86. return certificates;
  87. }
  88. foreach (var certificate in options.TlsOptions.Certificates)
  89. {
  90. certificates.Add(new X509Certificate(certificate));
  91. }
  92. return certificates;
  93. }
  94. }
  95. }