From: Alexander Nikolaev <55398552+alnikola@users.noreply.github.com> Date: Fri, 21 Feb 2020 18:44:22 +0000 (+0100) Subject: AllowNatTraversal is properly set for stopped socket (#32603) X-Git-Tag: submit/tizen/20210909.063632~9564 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7e398ff3a00081b5a238b282ba5e44ad42869bb7;p=platform%2Fupstream%2Fdotnet%2Fruntime.git AllowNatTraversal is properly set for stopped socket (#32603) If AllowNatTraversal is called on a stopped TcpListener when ```_serverSocket``` is null, ```allow``` value gets stored in a field. Subsequently, if a new socket is created on Start call, the saved value is read and the corresponding argument is passed to SetIPProtectionLevel call after which the value is reset to preserve the current IPProtectionLevel propagation logic. The follow-up issue is #32653 Fixes #32551 --- diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPListener.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPListener.cs index 95b5622..3220214 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPListener.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/TCPListener.cs @@ -15,6 +15,7 @@ namespace System.Net.Sockets private Socket _serverSocket; private bool _active; private bool _exclusiveAddressUse; + private bool? _allowNatTraversal; // Initializes a new instance of the TcpListener class with the specified local end point. public TcpListener(IPEndPoint localEP) @@ -118,7 +119,14 @@ namespace System.Net.Sockets throw new InvalidOperationException(SR.net_tcplistener_mustbestopped); } - _serverSocket.SetIPProtectionLevel(allowed ? IPProtectionLevel.Unrestricted : IPProtectionLevel.EdgeRestricted); + if (_serverSocket != null) + { + SetIPProtectionLevel(allowed); // Set it only for the current socket to preserve existing behavior + } + else + { + _allowNatTraversal = allowed; + } } // Starts listening to network requests. @@ -335,6 +343,9 @@ namespace System.Net.Sockets return listener; } + private void SetIPProtectionLevel(bool allowed) + => _serverSocket.SetIPProtectionLevel(allowed ? IPProtectionLevel.Unrestricted : IPProtectionLevel.EdgeRestricted); + private void CreateNewSocketIfNeeded() { _serverSocket ??= new Socket(_serverSocketEP.AddressFamily, SocketType.Stream, ProtocolType.Tcp); @@ -343,6 +354,12 @@ namespace System.Net.Sockets { _serverSocket.ExclusiveAddressUse = true; } + + if (_allowNatTraversal != null) + { + SetIPProtectionLevel(_allowNatTraversal.GetValueOrDefault()); + _allowNatTraversal = null; // Reset value to avoid affecting more sockets + } } } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/TcpListenerTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/TcpListenerTest.cs index 3bdc803..02be71a 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/TcpListenerTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/TcpListenerTest.cs @@ -45,6 +45,36 @@ namespace System.Net.Sockets.Tests } [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void AllowNatTraversal_NotStarted_SetSuccessfully() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.AllowNatTraversal(true); + listener.Start(); + listener.Stop(); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void AllowNatTraversal_Started_ThrowsException() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + Assert.Throws(() => listener.AllowNatTraversal(true)); + listener.Stop(); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void AllowNatTraversal_StartedAndStopped_SetSuccessfully() + { + var listener = new TcpListener(IPAddress.Loopback, 0); + listener.Start(); + listener.Stop(); + listener.AllowNatTraversal(true); + } + + [Fact] public void Start_InvalidArgs_Throws() { var listener = new DerivedTcpListener(IPAddress.Loopback, 0);