From 95d082042afbbd803af77fb6c6a5fbc084195f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20K=C3=B6nig?= Date: Fri, 11 Sep 2020 15:47:36 +0200 Subject: [PATCH] Support for setting port 0 on passive tcp/ip channels --- .../MessageChannelTests.cs | 7 +++-- .../MessageCommunicator.Tests.csproj | 2 +- MessageCommunicator.Tests/Util/TestUtility.cs | 26 +++++++++++++++++++ MessageCommunicator/MessageChannel.cs | 8 ++++-- .../_Tcp/TcpPassiveByteStreamHandler.cs | 12 +++++---- 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 MessageCommunicator.Tests/Util/TestUtility.cs diff --git a/MessageCommunicator.Tests/MessageChannelTests.cs b/MessageCommunicator.Tests/MessageChannelTests.cs index ce2a9bb..7b49984 100644 --- a/MessageCommunicator.Tests/MessageChannelTests.cs +++ b/MessageCommunicator.Tests/MessageChannelTests.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using MessageCommunicator.Tests.Util; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace MessageCommunicator.Tests @@ -14,12 +15,14 @@ public class MessageChannelTests [TestMethod] public async Task Check_SimpleTcpIPConnection() { + var testingPort = TestUtility.GetFreeTcpPort(); + var receiveTaskOnPassiveChannel = new TaskCompletionSource(); var receiveTaskOnActiveChannel = new TaskCompletionSource(); // Define channels var passiveChannel = new MessageChannel( - new TcpPassiveByteStreamHandlerSettings(IPAddress.Loopback, 40000), + new TcpPassiveByteStreamHandlerSettings(IPAddress.Loopback, testingPort), new DefaultMessageRecognizerSettings(Encoding.UTF8), (msg) => { @@ -27,7 +30,7 @@ public async Task Check_SimpleTcpIPConnection() msg.ReturnToPool(); }); var activeChannel = new MessageChannel( - new TcpActiveByteStreamHandlerSettings("127.0.0.1", 40000), + new TcpActiveByteStreamHandlerSettings("127.0.0.1", testingPort), new DefaultMessageRecognizerSettings(Encoding.UTF8), (msg) => { diff --git a/MessageCommunicator.Tests/MessageCommunicator.Tests.csproj b/MessageCommunicator.Tests/MessageCommunicator.Tests.csproj index 82b45a3..33a75f8 100644 --- a/MessageCommunicator.Tests/MessageCommunicator.Tests.csproj +++ b/MessageCommunicator.Tests/MessageCommunicator.Tests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 diff --git a/MessageCommunicator.Tests/Util/TestUtility.cs b/MessageCommunicator.Tests/Util/TestUtility.cs new file mode 100644 index 0000000..2031b64 --- /dev/null +++ b/MessageCommunicator.Tests/Util/TestUtility.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Sockets; +using System.Runtime.InteropServices.ComTypes; +using System.Text; + +namespace MessageCommunicator.Tests.Util +{ + internal static class TestUtility + { + public static ushort GetFreeTcpPort() + { + // Simple method do find a free port + // see https://stackoverflow.com/questions/138043/find-the-next-tcp-port-in-net + + var dummyListener = new TcpListener(IPAddress.Loopback, 0); + + dummyListener.Start(); + var port = (ushort)((IPEndPoint)dummyListener.LocalEndpoint).Port; + dummyListener.Stop(); + + return port; + } + } +} diff --git a/MessageCommunicator/MessageChannel.cs b/MessageCommunicator/MessageChannel.cs index 89e65be..3240f10 100644 --- a/MessageCommunicator/MessageChannel.cs +++ b/MessageCommunicator/MessageChannel.cs @@ -20,12 +20,16 @@ public class MessageChannel public string RemoteEndpointDescription => _byteStreamHandler.RemoteEndpointDescription; - public IMessageReceiveHandler ReceiveHandler { get; } + public IMessageReceiveHandler? ReceiveHandler + { + get => _messageRecognizer.ReceiveHandler; + set => _messageRecognizer.ReceiveHandler = value; + } public MessageChannel( ByteStreamHandlerSettings byteStreamHandlerSettings, MessageRecognizerSettings messageRecognizerSettings, - IMessageReceiveHandler receiveHandler, + IMessageReceiveHandler? receiveHandler = null, IMessageCommunicatorLogger? logger = null) { _byteStreamHandler = byteStreamHandlerSettings.CreateByteStreamHandler(); diff --git a/MessageCommunicator/_ByteStreamHandler/_Tcp/TcpPassiveByteStreamHandler.cs b/MessageCommunicator/_ByteStreamHandler/_Tcp/TcpPassiveByteStreamHandler.cs index 1e3b848..dca5ad7 100644 --- a/MessageCommunicator/_ByteStreamHandler/_Tcp/TcpPassiveByteStreamHandler.cs +++ b/MessageCommunicator/_ByteStreamHandler/_Tcp/TcpPassiveByteStreamHandler.cs @@ -122,6 +122,7 @@ private async void RunConnectionMainLoop(int loopId) CancellationTokenSource? lastCancelTokenSource = null; TcpListener? tcpListener = null; var reconnectErrorCount = 0; + var currentListenerPort = this.ListeningPort; while(loopId == _runningLoopCounter) { if (tcpListener == null) @@ -136,6 +137,7 @@ private async void RunConnectionMainLoop(int loopId) } tcpListener = new TcpListener(this.ListeningIPAddress, this.ListeningPort); tcpListener.Start(); + currentListenerPort = (ushort)((IPEndPoint)tcpListener.LocalEndpoint).Port; reconnectErrorCount = 0; _currentListener = tcpListener; @@ -144,7 +146,7 @@ private async void RunConnectionMainLoop(int loopId) { this.Log( LoggingMessageType.Info, - StringBuffer.Format("TcpListener created for port {0}", this.ListeningPort)); + StringBuffer.Format("TcpListener created for port {0}", currentListenerPort)); } } catch (Exception ex) @@ -153,7 +155,7 @@ private async void RunConnectionMainLoop(int loopId) { this.Log( LoggingMessageType.Error, - StringBuffer.Format("Error while creating TcpListener for port {0}: {1}", this.ListeningPort, ex.Message), + StringBuffer.Format("Error while creating TcpListener for port {0}: {1}", currentListenerPort, ex.Message), exception: ex); } @@ -180,7 +182,7 @@ await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount) this.Log( LoggingMessageType.Info, StringBuffer.Format("Listening for incoming connections on port {0}...", - this.ListeningPort)); + currentListenerPort)); } actTcpClient = await tcpListener.AcceptTcpClientAsync() @@ -194,7 +196,7 @@ await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount) LoggingMessageType.Info, StringBuffer.Format( "Got new connection on listening port {0}. Connection established between {1} and {2}", - this.ListeningPort, actLocalEndPoint.ToString(), actPartnerEndPoint.ToString())); + currentListenerPort, actLocalEndPoint.ToString(), actPartnerEndPoint.ToString())); } } catch (ObjectDisposedException) @@ -210,7 +212,7 @@ await this.WaitByReconnectWaitTimeAsync(reconnectErrorCount) { this.Log( LoggingMessageType.Error, - StringBuffer.Format("Error while listening for incoming connections on port {0}: {1}", this.ListeningPort, ex.Message), + StringBuffer.Format("Error while listening for incoming connections on port {0}: {1}", currentListenerPort, ex.Message), exception: ex); }