Skip to content

Commit

Permalink
feat: Add cancellation to ConnectAsync()
Browse files Browse the repository at this point in the history
  • Loading branch information
mycroes committed Jun 15, 2023
1 parent 4ff22fe commit bea5b4c
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/AdsClient/Ams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public Ams(IAmsSocket amsSocket)
/// </summary>
public ushort AmsPortSource { get; set; } = 32905;

public Task ConnectAsync()
public Task ConnectAsync(CancellationToken cancellationToken = default)
{
return AmsSocket.ConnectAsync(new MessageHandler(this));
return AmsSocket.ConnectAsync(new MessageHandler(this), cancellationToken);
}

public void Dispose()
Expand Down
19 changes: 17 additions & 2 deletions src/AdsClient/AmsSocket.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using Viscon.Communication.Ads.Internal;

Expand Down Expand Up @@ -31,11 +32,25 @@ public void Close()
connection?.Close();
}

public async Task ConnectAsync(IIncomingMessageHandler messageHandler)
public async Task ConnectAsync(IIncomingMessageHandler messageHandler, CancellationToken cancellationToken = default)
{
if (connection is not null) throw new InvalidOperationException("Connection was already established.");

await TcpClient.ConnectAsync(Host, Port).ConfigureAwait(false);
using (cancellationToken.Register(state => ((Socket)state).Close(), Socket))
{
try
{
await TcpClient.ConnectAsync(Host, Port).ConfigureAwait(false);
}
catch (Exception) when (cancellationToken.IsCancellationRequested)
{
// The exception handling is quite generic, but exceptions thrown differ across target frameworks.
// (See https://stackoverflow.com/a/66656805/1085457)
// This is probably not something to worry about, since apparently cancellation was requested anyway.
cancellationToken.ThrowIfCancellationRequested();
}
}

connection = new AmsSocketConnection(TcpClient.Client, messageHandler);
}

Expand Down
3 changes: 2 additions & 1 deletion src/AdsClient/IAmsSocket.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Viscon.Communication.Ads
Expand All @@ -9,7 +10,7 @@ public interface IAmsSocket

void Close();

Task ConnectAsync(IIncomingMessageHandler messageHandler);
Task ConnectAsync(IIncomingMessageHandler messageHandler, CancellationToken cancellationToken = default);

Task SendAsync(byte[] message);

Expand Down
14 changes: 8 additions & 6 deletions test/AdsClient/AdsCommandsAsyncTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Shouldly;
Expand All @@ -18,12 +19,13 @@ public class AdsCommandsAsyncTest : IDisposable

public AdsCommandsAsyncTest()
{
A.CallTo(() => amsSocket.ConnectAsync(A<IIncomingMessageHandler>.Ignored)).ReturnsLazily(call =>
{
messageHandler = call.GetArgument<IIncomingMessageHandler>(0);
connected = true;
return Task.CompletedTask;
});
A.CallTo(() => amsSocket.ConnectAsync(A<IIncomingMessageHandler>.Ignored, A<CancellationToken>.Ignored))
.ReturnsLazily(call =>
{
messageHandler = call.GetArgument<IIncomingMessageHandler>(0);
connected = true;
return Task.CompletedTask;
});
A.CallTo(() => amsSocket.Connected).ReturnsLazily(() => connected);

client = new AdsClient(amsNetIdSource: "10.0.0.120.1.1", amsSocket: amsSocket,
Expand Down

0 comments on commit bea5b4c

Please sign in to comment.