NWListener ignores value of allowLocalEndpointReuse (macOS and iOS)

Originator:thibault.ml
Number:rdar://FB8658821 Date Originated:09/09/2020
Status:Open Resolved:
Product:Network Framework Product Version:
Classification: Reproducible:Always
 
DESCRIPTION
Both on macOS and iOS, NWListener ignores the value of NWParameters.allowLocalEndpointReuse and behave as it it were false, whatever value was set.
When running on an iOS simulator, NWListener always behaves as it were true, whatever value was set.


STEP-BY-STEP
- Download the attached proof of concept (PoC) TestAllowLocalEndpointReuse.zip
- Run the attached PoC on macOS (e.g. macOS 10.15.6)
- Run the attached PoC on an iOS device (e.g. iOS 13.6.1)
- Run the attached PoC on an iOS simulator (e.g. iOS 13.6.1 simulator)

The test in the PoC creates a listener, and waits for it to be ready. Once it is ready, it tries to create another listener on the exact same IP+port, and will consider success or failure depending on whether allowLocalEndpointReuse was true or false.
On each run, the test is run twice, once with allowLocalEndpointReuse=false, and once with allowLocalEndpointReuse=true.

When allowLocalEndpointReuse=false, the test will:
- *succeed* if the second listener fails to listen ("Address already in use", which is expected); or
- *fail* if the second listener succeeds (if reuse is forbidden, the second listener should actually fail)

When allowLocalEndpointReuse=true, the test will:
- *fail* if the second listener fails to listen (the second listener shouldn't fail since reuse was requested); or
- *succeed* if the second listener succeeds (which is what is expected)


EXPECTED RESULTS

Both test runs succeed on each platform


ACTUAL RESULTS

Only one test succeeds on each platform.
On macOS & iOS, allowLocalEndpointReuse always behaves as if it were false, even when set to true
On iOS Simulator or iOS Playground, allowLocalEndpointReuse always behaves as if it were true, even when set to false

ADDITIONAL NOTES

The issue reproduces whether NWParameters.tcp or NWParameters.udp is used
The issue also reproduces when using an external listener (e.g. with Python) as the first or second listener. 

OUTPUT

On macOS:
Running test with allowLocalEndpointReuse=false
[OK] Listener #2 not started. Did not allow endpoint reuse, as expected: POSIXErrorCode: Address already in use
Running test with allowLocalEndpointReuse=true
[FAIL] Failed to allow endpoint reuse despite being requested: POSIXErrorCode: Address already in use

On iOS:
Running test with allowLocalEndpointReuse=false
[OK] Listener #2 not started. Did not allow endpoint reuse, as expected: POSIXErrorCode: Address already in use
Running test with allowLocalEndpointReuse=true
[FAIL] Failed to allow endpoint reuse despite being requested: POSIXErrorCode: Address already in use

On iOS Simulator:
Running test with allowLocalEndpointReuse=false
[FAIL] Allowed endpoint reuse, despite asking to deny it
Running test with allowLocalEndpointReuse=true
[OK] Listener #2 started. Did allow endpoint reuse, as expected

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!