Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Eio.Resource.Close #489

Merged
merged 2 commits into from
Mar 26, 2024
Merged

Implement Eio.Resource.Close #489

merged 2 commits into from
Mar 26, 2024

Conversation

paurkedal
Copy link
Contributor

After shutting down the TLS flow, I would like to close the underlying TCP socket. This is of course handled by the switch, but since I'm using resource pooling, I would like to do this before leaving the scope of the switch. I could pass around the TCP flow along with the TLS flow, but this breaks the flow-abstraction which is very useful when dealing with TLS.

My proposal here is the the TLS flow implements the close interface but falls back to no-op if the underlying flow does not implement it. We could consider making close a requirement for the underlying flow, since it should be possible to amend a no-op close operation to an existing flow in the (unlikely?) event that a non-TCP flow is used.

(I made a hack around the issue, but I prefer a more proper solution.)

@hannesm
Copy link
Member

hannesm commented Feb 27, 2024

First of all thanks for your contribution :). As I don't understand eio and its desired semantics, I'd be happy if someone with more clue @talex5 @bikallem would review this PR.

@talex5
Copy link
Contributor

talex5 commented Feb 27, 2024

It's up to tls-eio to decide whether closing a TLS flow also closes the underlying flow.

For tls-lwt, we have:

(** [of_t t] is [ic, oc], the input and output channel.  [close]
    defaults to [!Unix.close]. *)
val of_t : ?close:(unit -> unit Lwt.t) -> Unix.t -> ic * oc

So, tls-lwt closes by default but you can override it.

tls-mirage closes in all cases.

I find it a bit ugly that this PR uses runtime introspection to find out whether it can close the underlying flow. Since it's probably only useful in rare cases, we could just default to not closing.

@paurkedal
Copy link
Contributor Author

@talex5 Thanks for the input, I'm new to EIO and still learning, as well.

I agree the runtime introspection is ugly, and I changed my mind about the PR in the current form. I think that the best solution is to require that the underlying flow implements the close operation. I would expect close to be present for TCP flows, or any flows where TLS is relevant for protecting the data. But if I'm wrong, there could be code out there which breaks after the change, and which will need a noop close amended.

Would it not also be best to close by default in consistency with tls-lwt? I can't think of cases where it would be relevant to re-use the underlying flow after the TLS session is complete. Of course, when using switches either way works, but releasing resources as soon as possible is a good thing.

@talex5
Copy link
Contributor

talex5 commented Mar 5, 2024

I think that the best solution is to require that the underlying flow implements the close operation.

Sounds good to me!

(it would also be possible to use a polymorphic type to remember whether the underlying flow is closable, but I suspect that would be more trouble than it's worth and would certainly break existing code)

@paurkedal
Copy link
Contributor Author

I've updated the PR to require close from the socket. If we want to make it optional, I could add either a boolean parameter or a function like for tls-lwt.

Copy link
Contributor

@talex5 talex5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. CI is failing for an unrelated reason:

File "lwt/examples/resume_echo_server.ml", line 55, characters 35-61:
55 |     obfuscation = Randomconv.int32 Mirage_crypto_rng.generate ;
                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type int -> HT.key
       but an expression was expected of type int -> string
       Type HT.key is not compatible with type string

@hannesm
Copy link
Member

hannesm commented Mar 26, 2024

Ooops sorry, I forgot about this PR. If you could rebase to the main branch, and @talex5 approval still stands, I can merge and cut a release for tls-eio.

@paurkedal
Copy link
Contributor Author

No problem, I pushed a branch rebased on main. Let me know if you prefer it squashed too.

@hannesm hannesm merged commit fc2c7f8 into mirleft:main Mar 26, 2024
1 check passed
hannesm added a commit to hannesm/opam-repository that referenced this pull request Mar 26, 2024
CHANGES:

* tls: handle half-closed connection properly: a received CLOSE_NOTIFY does not
  lead to a CLOSE_NOTIFY to be sent (a `send_close_notify` sends it explicitly)
  (mirleft/ocaml-tls#488 @hannesm)
* tls: modify return type of `handle_tls` - the Alert is now in the right hand
  side, and `` `Eof `` is explicit in the second part of the tuple
  (mirleft/ocaml-tls#488 @hannesm)
* tls: remove `can_handle_appdata`, the function `handshake_in_progress` is
  available (mirleft/ocaml-tls#488 @hannesm)
* tls-mirage: avoid exceptions in reneg and rekey (mirleft/ocaml-tls#487 @hannesm)
* tls: remove HEARTBEAT decoding - HEARTBEAT was never supported in this
  library, the decoder was superfluous (mirleft/ocaml-tls#487 @hannesm)
* tls-mirage: provide `underlying : flow -> FLOW.flow` (mirleft/ocaml-tls#487 @hannesm,
  fixes mirleft/ocaml-tls#425 @dinosaure)
* tls-mirage: implement mirage-flow 4 API (`val shutdown`) (mirleft/ocaml-tls#488 @hannesm)
* tls-eio: adapt to half-closed connections (mirleft/ocaml-tls#488 @talex5)
* tls-eio: implement Eio.Resource.Close (mirleft/ocaml-tls#489 @paurkedal, reviewed by @talex5)
@hannesm
Copy link
Member

hannesm commented Mar 26, 2024

thanks @paurkedal, merged and I re-did the 0.17.4 release to include this PR. ocaml/opam-repository#25587

hannesm added a commit to hannesm/opam-repository that referenced this pull request Mar 27, 2024
CHANGES:

* tls: handle half-closed connection properly: a received CLOSE_NOTIFY does not
  lead to a CLOSE_NOTIFY to be sent (a `send_close_notify` sends it explicitly)
  (mirleft/ocaml-tls#488 @hannesm)
* tls: modify return type of `handle_tls` - the Alert is now in the right hand
  side, and `` `Eof `` is explicit in the second part of the tuple
  (mirleft/ocaml-tls#488 @hannesm)
* tls: remove `can_handle_appdata`, the function `handshake_in_progress` is
  available (mirleft/ocaml-tls#488 @hannesm)
* tls-mirage: avoid exceptions in reneg and rekey (mirleft/ocaml-tls#487 @hannesm)
* tls: remove HEARTBEAT decoding - HEARTBEAT was never supported in this
  library, the decoder was superfluous (mirleft/ocaml-tls#487 @hannesm)
* tls-mirage: provide `underlying : flow -> FLOW.flow` (mirleft/ocaml-tls#487 @hannesm,
  fixes mirleft/ocaml-tls#425 @dinosaure)
* tls-mirage: implement mirage-flow 4 API (`val shutdown`) (mirleft/ocaml-tls#488 @hannesm)
* tls-eio: adapt to half-closed connections (mirleft/ocaml-tls#488 @talex5)
* tls-eio: implement Eio.Resource.Close (mirleft/ocaml-tls#489 @paurkedal, reviewed by @talex5)
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants