Closed kazu-yamamoto closed 4 months ago
Sorry, I'm not sure I understand. Let me try to explain:
When I introduced runTCPServerWithSocket
in #3, the point was exactly to, as you say, "pass a socket to the run function": if you want to have control over how that socket is initialized, then instead of calling runTCPServer
, you can call runTCPServerWithSocket
, passing in your own function to initialize the socket. By exposing openServerSocket
, you can then use openServerSocket
as defined in http2
for the "default" setup, and perhaps do some additional things, if you wish. You can of course also just use your own replacement and not use openServerSocket
at all.
Perhaps put another way: openServerSocket
is exactly the "resource acquire mechanism" and runTCPServerWithSocket
is exactly the "protocol run function".
The new function runTCPServerWithListenSocket
from this PR (#7), as far as I can tell, does not really change this picture. Instead of passing a function to initialize the socket (AddrInfo -> IO Socket
), for which you then could use openServerSocket
if you wish, you must now pass the actual socket itself (Socket
), which you could initialize with openServerSocket
, if you wish. It seems to me that that doesn't really change anything (but perhaps I'm missing something)?
One downside of runTCPServerWithListenSocket
is the caller is now responsible for doing the appropriate bracketing, which runTCPServerWithSocket
does on behalf of the caller.
The point of #6 is two-fold:
a. Generalize openServerSocket
to openServerSocketWithOptions
, which takes additional flags; this is necessary for flags that must be set before we call bind
on the socket, such as TCP_NODELAY
. This way code that wants to use whatever defaults openServerSocket
uses, we can still reuse it (rather than having to reimplement it), but also pass some additional flags.
b. Generalize the client API in the same way as we did in #3, to provide runTCPClientWithSocket
alongside runTCPServerWithSocket
, and openClientSocketWithOptions
alongside openClientSocket
.
As far as I can tell, this PR (#7) is therefore entirely orthogonal to #6: it is still not possible to reuse openServerSocket
to create a socket for which, say, TCP_NODELAY
is set, nor is it possible to run the client with a socket initialized in a user-specified manner.
Personally I don't have a strong preference for runTCPServerWithSocket
versus runTCPServerWithListenSocket
; they are mostly equivalent as far as I can see, with the other minor proviso that with runTCPServerWithListenSocket
the user is more likely to forget to bracket
the call to openServerSocket
.
Perhaps one aspect of #6 that muddled the waters a bit was that we also added runTCPServerWithSocketOptions
and runTCPClientWithSocketOptions
; that might have confused matters and suggested that in fact we do not separate a "resource acquire mechanism" from a "protocol run function"; but that's not really the case, those functions were added for a more convenient API only. They could easily be removed (and arguably should be removed), leaving only runTCPServerWithSocket
and runTCPClientWithSocket
(the protocol run function), and then open{Server,Client}Socket{,WithOptions}
as the ways to construct the socket (acquire the resource).
This is a lot of text, sorry. Perhaps the following helps:
runTCPServer runTCPClient
runTCPServerWithSocket (#3) runTCPClientWithSocket (#6)
runTCPServerWithListenSocket (#7) ------
openServerSocket openClientSocket
openServerSocketWithOptions (#6) openClientSocketWithOptions (#6)
-- OPTIONAL, for convenience only --
runTCPServerWithSocketOptions (#6) runTCPClientWithSocketOptions (#6)
I think that the essential issue of #6 is there is no way to pass a socket to the run function. With a recent discussion with @khibino, I realized that a resource acquire mechanism and a protocol run function should be separated.
@edsko @FinleyMcIlwaine I believe that this is a smarter approach than #6. What do you think?