I'm implementing a NETransparentProxyProvider and trying to preserve the original TCP connection semantics as transparently as possible.
The current API of NEAppProxyTCPFlow appears not to provide a way to distinguish between the following situations:
- The client has performed a half-close by calling shutdown(SHUT_WR) (i.e. closed only its write side).
- The client has fully closed the socket/connection.
When readData(completionHandler:) returns empty data, indicating EOF, I cannot determine which of the two cases above has occurred.
This creates a problem when forwarding the connection to the upstream server. Upon receiving empty data from the flow, should the corresponding server-side connection:
- Perform a half-close (close only the write side / send FIN)?
- Be fully closed?
Currently, I always perform a half-close on the server-side connection. While this almost preserves the original flow semantics, it can lead to leaked connections, since the upstream connection may remain in FIN_WAIT_2 indefinitely. Is there any supported way to determine whether the originating connection was half-closed or fully closed? If not, what is the recommended approach for implementing a transparent TCP proxy that needs to accurately preserve TCP shutdown semantics? Any guidance would be appreciated.