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();
}
}
}