using System; using System.IO; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Threading.Tasks; using MQTTnet.Core.Channel; using MQTTnet.Core.Client; using MQTTnet.Core.Exceptions; namespace MQTTnet { /// /// Describes an SSL channel to an MQTT server. /// public class MqttClientSslChannel : IMqttCommunicationChannel, IDisposable { private readonly Socket _socket; private SslStream _sslStream; /// /// Creates a new . /// public MqttClientSslChannel() { _socket = new Socket(SocketType.Stream, ProtocolType.Tcp); } /// /// Creates a new with a predefined . /// /// public MqttClientSslChannel(Socket socket) { _socket = socket ?? throw new ArgumentNullException(nameof(socket)); } /// /// Asynchronously connects to the host described in the . /// /// The describing the connection. public async Task ConnectAsync(MqttClientOptions options) { try { await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, options.Server, options.Port, null); NetworkStream ns = new NetworkStream(_socket, true); _sslStream = new SslStream(ns); await _sslStream.AuthenticateAsClientAsync(options.Server, null, SslProtocols.Tls12, false); } catch (SocketException exception) { throw new MqttCommunicationException(exception); } } /// /// Asynchronously disconnects the client from the server. /// public Task DisconnectAsync() { try { return Task.Factory.FromAsync(_socket.BeginDisconnect, _socket.EndDisconnect, true, null); } catch (SocketException exception) { throw new MqttCommunicationException(exception); } } /// /// Asynchronously writes a sequence of bytes to the socket. /// /// The buffer to write data from. public Task WriteAsync(byte[] buffer) { if (buffer == null) throw new ArgumentNullException(nameof(buffer)); try { return _sslStream.WriteAsync(buffer, 0, buffer.Length); } catch (Exception ex) when (ex is SocketException || ex is IOException) { throw new MqttCommunicationException(ex); } } /// /// Asynchronously reads a sequence of bytes from the socket. /// /// The buffer to write the data into. public Task ReadAsync(byte[] buffer) { try { return _sslStream.ReadAsync(buffer, 0, buffer.Length); } catch (Exception ex) when (ex is SocketException || ex is IOException) { throw new MqttCommunicationException(ex); } } /// /// Releases all resources used by the . /// public void Dispose() { _sslStream?.Dispose(); _socket?.Dispose(); } } }