diff --git a/samples/DtlsClient/Program.cs b/samples/DtlsClient/Program.cs
index c383370..a69bb91 100644
--- a/samples/DtlsClient/Program.cs
+++ b/samples/DtlsClient/Program.cs
@@ -4,7 +4,10 @@
using System.Threading.Tasks;
using CoAPNet;
using CoAPNet.Dtls.Client;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Tls;
+using Org.BouncyCastle.Tls.Crypto;
+using Org.BouncyCastle.Tls.Crypto.Impl.BC;
namespace CoAPDevices
{
@@ -16,7 +19,6 @@ static async Task Main(string[] args)
var port = Coap.PortDTLS;
var identity = new BasicTlsPskIdentity("user", Encoding.UTF8.GetBytes("password"));
-
// Create a new client using a DTLS endpoint with the remote host and Identity
var client = new CoapClient(new CoapDtlsClientEndPoint(host, port, new ExamplePskDtlsClient(identity)));
// Create a cancelation token that cancels after 1 minute
@@ -69,26 +71,18 @@ static async Task Main(string[] args)
public class ExamplePskDtlsClient : PskTlsClient
{
public ExamplePskDtlsClient(TlsPskIdentity pskIdentity)
- : base(pskIdentity)
+ : base(new BcTlsCrypto(new SecureRandom()), pskIdentity)
{
}
- public ExamplePskDtlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
- : base(cipherFactory, pskIdentity)
- {
- }
-
- public ExamplePskDtlsClient(TlsCipherFactory cipherFactory, TlsDHVerifier dhVerifier, TlsPskIdentity pskIdentity)
- : base(cipherFactory, dhVerifier, pskIdentity)
+ public override int GetHandshakeTimeoutMillis()
{
+ return 30000;
}
- public override ProtocolVersion MinimumVersion => ProtocolVersion.DTLSv10;
- public override ProtocolVersion ClientVersion => ProtocolVersion.DTLSv12;
-
- public override int GetHandshakeTimeoutMillis()
+ public override ProtocolVersion[] GetProtocolVersions()
{
- return 30000;
+ return ProtocolVersion.DTLSv12.DownTo(ProtocolVersion.DTLSv10);
}
}
}
diff --git a/samples/DtlsServer/Program.cs b/samples/DtlsServer/Program.cs
index 5e3cac3..50f6e51 100644
--- a/samples/DtlsServer/Program.cs
+++ b/samples/DtlsServer/Program.cs
@@ -7,10 +7,10 @@
using CoAPNet.Server;
using System.Threading.Tasks;
using CoAPNet.Dtls.Server;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Console;
-using Microsoft.Extensions.Options;
+using Org.BouncyCastle.Tls.Crypto.Impl.BC;
+using Org.BouncyCastle.Security;
namespace CoAPDevices
{
@@ -82,7 +82,7 @@ public class ExamplePskDtlsServer : PskTlsServer
private readonly ExamplePskIdentityManager pskIdentityManager;
public ExamplePskDtlsServer(ExamplePskIdentityManager pskIdentityManager)
- : base(pskIdentityManager)
+ : base(new BcTlsCrypto(new SecureRandom()), pskIdentityManager)
{
this.pskIdentityManager = pskIdentityManager;
}
@@ -97,8 +97,10 @@ public string GetIdentity()
return this.pskIdentityManager.GetIdentity();
}
- protected override ProtocolVersion MinimumVersion => ProtocolVersion.DTLSv10;
- protected override ProtocolVersion MaximumVersion => ProtocolVersion.DTLSv12;
+ public override ProtocolVersion[] GetProtocolVersions()
+ {
+ return ProtocolVersion.DTLSv12.DownTo(ProtocolVersion.DTLSv10);
+ }
}
public class ExamplePskIdentityManager : TlsPskIdentityManager
diff --git a/src/CoAPNet.Dtls/Client/CoapDtlsClientEndPoint.cs b/src/CoAPNet.Dtls/Client/CoapDtlsClientEndPoint.cs
index eb1e335..337df4d 100644
--- a/src/CoAPNet.Dtls/Client/CoapDtlsClientEndPoint.cs
+++ b/src/CoAPNet.Dtls/Client/CoapDtlsClientEndPoint.cs
@@ -3,7 +3,7 @@
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
using Org.BouncyCastle.Security;
namespace CoAPNet.Dtls.Client
@@ -82,7 +82,7 @@ private void EnsureConnected()
var udpClient = new UdpClient(Server, Port);
- var dtlsClientProtocol = new DtlsClientProtocol(new SecureRandom());
+ var dtlsClientProtocol = new DtlsClientProtocol();
_datagramTransport = dtlsClientProtocol.Connect(_tlsClient, new UdpDatagramTransport(udpClient, NetworkMtu));
_isConnected = true;
}
diff --git a/src/CoAPNet.Dtls/Client/UdpDatagramTransport.cs b/src/CoAPNet.Dtls/Client/UdpDatagramTransport.cs
index cc5ced3..2e79de6 100644
--- a/src/CoAPNet.Dtls/Client/UdpDatagramTransport.cs
+++ b/src/CoAPNet.Dtls/Client/UdpDatagramTransport.cs
@@ -2,7 +2,7 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Client
{
diff --git a/src/CoAPNet.Dtls/CoAPNet.Dtls.csproj b/src/CoAPNet.Dtls/CoAPNet.Dtls.csproj
index 24966f3..c3d5cef 100644
--- a/src/CoAPNet.Dtls/CoAPNet.Dtls.csproj
+++ b/src/CoAPNet.Dtls/CoAPNet.Dtls.csproj
@@ -28,7 +28,7 @@
-
+
diff --git a/src/CoAPNet.Dtls/Server/CoapDtlsConnectionInformation.cs b/src/CoAPNet.Dtls/Server/CoapDtlsConnectionInformation.cs
index de3edce..0423491 100644
--- a/src/CoAPNet.Dtls/Server/CoapDtlsConnectionInformation.cs
+++ b/src/CoAPNet.Dtls/Server/CoapDtlsConnectionInformation.cs
@@ -1,4 +1,4 @@
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Server
{
diff --git a/src/CoAPNet.Dtls/Server/CoapDtlsServerClientEndPoint.cs b/src/CoAPNet.Dtls/Server/CoapDtlsServerClientEndPoint.cs
index 140d44d..be3ed83 100644
--- a/src/CoAPNet.Dtls/Server/CoapDtlsServerClientEndPoint.cs
+++ b/src/CoAPNet.Dtls/Server/CoapDtlsServerClientEndPoint.cs
@@ -1,9 +1,10 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Server
{
@@ -29,7 +30,7 @@ public CoapDtlsServerClientEndPoint(IPEndPoint endPoint, QueueDatagramTransport
public IPEndPoint EndPoint { get; }
public Uri BaseUri { get; }
- public string ConnectionInfo { get; private set; }
+ public IReadOnlyDictionary ConnectionInfo { get; private set; }
public bool IsSecure => true;
@@ -102,8 +103,7 @@ public void Accept(DtlsServerProtocol serverProtocol, TlsServer server)
public void EnqueueDatagram(byte[] datagram)
{
- if (!IsClosed)
- _udpTransport.ReceiveQueue.Add(datagram);
+ _udpTransport.EnqueueReceived(datagram);
LastReceivedTime = DateTime.UtcNow;
}
}
diff --git a/src/CoAPNet.Dtls/Server/CoapDtlsServerTransport.cs b/src/CoAPNet.Dtls/Server/CoapDtlsServerTransport.cs
index faac3c3..475f4bf 100644
--- a/src/CoAPNet.Dtls/Server/CoapDtlsServerTransport.cs
+++ b/src/CoAPNet.Dtls/Server/CoapDtlsServerTransport.cs
@@ -8,8 +8,7 @@
using System.Threading.Tasks;
using CoAPNet.Dtls.Server.Statistics;
using Microsoft.Extensions.Logging;
-using Org.BouncyCastle.Crypto.Tls;
-using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Server
{
@@ -35,9 +34,7 @@ public CoapDtlsServerTransport(CoapDtlsServerEndPoint endPoint, ICoapHandler coa
_tlsServerFactory = tlsServerFactory ?? throw new ArgumentNullException(nameof(tlsServerFactory));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
- SecureRandom random = new SecureRandom();
-
- _serverProtocol = new DtlsServerProtocol(random);
+ _serverProtocol = new DtlsServerProtocol();
_sessions = new ConcurrentDictionary();
}
@@ -176,42 +173,37 @@ private async Task HandleSession(CoapDtlsServerClientEndPoint session)
session.Accept(_serverProtocol, server);
- if (session.ConnectionInfo != null)
- {
- _logger.LogInformation("New TLS connection from {EndPoint}, Server Info: {ServerInfo}", session.EndPoint, session.ConnectionInfo);
- }
- else
+ using (session.ConnectionInfo != null ? _logger.BeginScope(session.ConnectionInfo) : null)
{
_logger.LogInformation("New TLS connection from {EndPoint}", session.EndPoint);
- }
- var connectionInfo = new CoapDtlsConnectionInformation
- {
- LocalEndpoint = _endPoint,
- RemoteEndpoint = session,
- TlsServer = server
- };
+ var connectionInfo = new CoapDtlsConnectionInformation
+ {
+ LocalEndpoint = _endPoint,
+ RemoteEndpoint = session,
+ TlsServer = server
+ };
- while (!session.IsClosed && !_cts.IsCancellationRequested)
- {
- var packet = await session.ReceiveAsync(_cts.Token);
- _logger.LogDebug("Handling CoAP Packet from {EndPoint}", session.EndPoint);
- await _coapHandler.ProcessRequestAsync(connectionInfo, packet.Payload);
- _logger.LogDebug("CoAP request from {EndPoint} handled!", session.EndPoint);
+ while (!session.IsClosed && !_cts.IsCancellationRequested)
+ {
+ var packet = await session.ReceiveAsync(_cts.Token);
+ _logger.LogDebug("Handling CoAP Packet from {EndPoint}", session.EndPoint);
+ await _coapHandler.ProcessRequestAsync(connectionInfo, packet.Payload);
+ _logger.LogDebug("CoAP request from {EndPoint} handled!", session.EndPoint);
+ }
}
}
- catch (OperationCanceledException)
+ catch (Exception ex) when (IsCanceledException(ex))
{
+ _logger.LogDebug(ex, "Session was canceled");
}
- catch (DtlsConnectionClosedException)
+ catch (TlsTimeoutException timeoutEx)
{
+ _logger.LogWarning(timeoutEx, "Timeout while handling session");
}
catch (TlsFatalAlert tlsAlert)
{
- if (!(tlsAlert.InnerException is DtlsConnectionClosedException) && tlsAlert.AlertDescription != AlertDescription.user_canceled)
- {
- _logger.LogWarning(tlsAlert, "TLS Error");
- }
+ _logger.LogWarning(tlsAlert, "TLS Error");
}
catch (Exception ex)
{
@@ -225,6 +217,13 @@ private async Task HandleSession(CoapDtlsServerClientEndPoint session)
}
}
+ private bool IsCanceledException(Exception ex)
+ {
+ return ex is OperationCanceledException ||
+ ex is DtlsConnectionClosedException ||
+ (ex is TlsFatalAlert tlsAlert && (tlsAlert.InnerException is DtlsConnectionClosedException || tlsAlert.AlertDescription == AlertDescription.user_canceled));
+ }
+
private async Task HandleCleanup()
{
while (!_cts.IsCancellationRequested)
diff --git a/src/CoAPNet.Dtls/Server/IDtlsServerFactory.cs b/src/CoAPNet.Dtls/Server/IDtlsServerFactory.cs
index 9246834..a1afe39 100644
--- a/src/CoAPNet.Dtls/Server/IDtlsServerFactory.cs
+++ b/src/CoAPNet.Dtls/Server/IDtlsServerFactory.cs
@@ -1,4 +1,4 @@
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Server
{
diff --git a/src/CoAPNet.Dtls/Server/IDtlsServerWithConnectionInfo.cs b/src/CoAPNet.Dtls/Server/IDtlsServerWithConnectionInfo.cs
index a736225..41b7012 100644
--- a/src/CoAPNet.Dtls/Server/IDtlsServerWithConnectionInfo.cs
+++ b/src/CoAPNet.Dtls/Server/IDtlsServerWithConnectionInfo.cs
@@ -1,4 +1,5 @@
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
+using System.Collections.Generic;
namespace CoAPNet.Dtls.Server
{
@@ -12,6 +13,6 @@ public interface IDtlsServerWithConnectionInfo : TlsServer
/// Get the connection information for the connection handled by this TLS server.
///
/// Information about this connection that should be logged once the connection is established.
- string GetConnectionInfo();
+ IReadOnlyDictionary GetConnectionInfo();
}
}
diff --git a/src/CoAPNet.Dtls/Server/QueueDatagramTransport.cs b/src/CoAPNet.Dtls/Server/QueueDatagramTransport.cs
index 8ad7e48..9da11da 100644
--- a/src/CoAPNet.Dtls/Server/QueueDatagramTransport.cs
+++ b/src/CoAPNet.Dtls/Server/QueueDatagramTransport.cs
@@ -2,7 +2,7 @@
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
-using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Tls;
namespace CoAPNet.Dtls.Server
{
@@ -16,6 +16,7 @@ internal class QueueDatagramTransport : DatagramTransport
private readonly int _sendLimit;
private readonly Action _sendCallback;
private readonly CancellationTokenSource _cts;
+ private BlockingCollection _receiveQueue;
private const int MIN_IP_OVERHEAD = 20;
private const int MAX_IP_OVERHEAD = MIN_IP_OVERHEAD + 64;
@@ -27,20 +28,21 @@ public QueueDatagramTransport(int mtu, Action sendCallback)
_sendLimit = mtu - MAX_IP_OVERHEAD - UDP_OVERHEAD;
_sendCallback = sendCallback ?? throw new ArgumentNullException(nameof(sendCallback));
_cts = new CancellationTokenSource();
+ _receiveQueue = new BlockingCollection();
}
- public BlockingCollection ReceiveQueue { get; internal set; } = new BlockingCollection();
public bool IsClosed { get; private set; }
public ReaderWriterLockSlim CloseLock { get; } = new ReaderWriterLockSlim();
public void Close()
{
+ // Cancel this before locking so the lock gets released ASAP
_cts.Cancel();
CloseLock.EnterWriteLock();
IsClosed = true;
+ _receiveQueue.Dispose();
CloseLock.ExitWriteLock();
- ReceiveQueue.Dispose();
}
public int GetReceiveLimit()
@@ -53,6 +55,21 @@ public int GetSendLimit()
return _sendLimit;
}
+ public void EnqueueReceived(byte[] datagram)
+ {
+ try
+ {
+ CloseLock.EnterReadLock();
+ if (IsClosed)
+ return;
+ _receiveQueue.Add(datagram);
+ }
+ finally
+ {
+ CloseLock.ExitReadLock();
+ }
+ }
+
public int Receive(byte[] buf, int off, int len, int waitMillis)
{
try
@@ -61,7 +78,7 @@ public int Receive(byte[] buf, int off, int len, int waitMillis)
if (IsClosed)
throw new DtlsConnectionClosedException();
- var success = ReceiveQueue.TryTake(out var data, waitMillis, _cts.Token);
+ var success = _receiveQueue.TryTake(out var data, waitMillis, _cts.Token);
if (!success)
return -1; // DO NOT return 0. This will disable the wait timeout effectively for the caller and any abort logic will by bypassed!
var readLen = Math.Min(len, data.Length);
diff --git a/src/CoAPNet.Dtls/Server/Statistics/DtlsSessionStatistics.cs b/src/CoAPNet.Dtls/Server/Statistics/DtlsSessionStatistics.cs
index 2d5dfd2..1d50858 100644
--- a/src/CoAPNet.Dtls/Server/Statistics/DtlsSessionStatistics.cs
+++ b/src/CoAPNet.Dtls/Server/Statistics/DtlsSessionStatistics.cs
@@ -1,11 +1,12 @@
using System;
+using System.Collections.Generic;
namespace CoAPNet.Dtls.Server.Statistics
{
public class DtlsSessionStatistics
{
public string EndPoint { get; set; }
- public string ConnectionInfo { get; set; }
+ public IReadOnlyDictionary ConnectionInfo { get; set; }
public DateTime SessionStartTime { get; internal set; }
public DateTime LastReceivedTime { get; internal set; }
}