Skip to content

Commit

Permalink
AllowNatTraversal is properly set for stopped socket (dotnet#32603)
Browse files Browse the repository at this point in the history
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 dotnet#32653 
Fixes dotnet#32551
  • Loading branch information
alnikola committed Feb 21, 2020
1 parent 857529d commit 7e398ff
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class TcpListener
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)
Expand Down Expand Up @@ -118,7 +119,14 @@ public void AllowNatTraversal(bool allowed)
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.
Expand Down Expand Up @@ -335,6 +343,9 @@ public static TcpListener Create(int port)
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);
Expand All @@ -343,6 +354,12 @@ private void CreateNewSocketIfNeeded()
{
_serverSocket.ExclusiveAddressUse = true;
}

if (_allowNatTraversal != null)
{
SetIPProtectionLevel(_allowNatTraversal.GetValueOrDefault());
_allowNatTraversal = null; // Reset value to avoid affecting more sockets
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,36 @@ public void Active_TrueWhileRunning(int ctor)
Assert.False(listener.Active);
}

[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<InvalidOperationException>(() => 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()
{
Expand Down

0 comments on commit 7e398ff

Please sign in to comment.