anmonteiro / httpun

A high performance, memory efficient, and scalable web server written in OCaml
Other
50 stars 11 forks source link

Is there a way to have Server_connection pass the fd to the request_hander? #139

Closed aantron closed 2 months ago

aantron commented 2 months ago

This would help with https://github.com/ocaml/ocaml.org/issues/2676#issuecomment-2328280005. I don't see a way to pass the fd at the moment, and it doesn't seem to be available through Reqd.t or Request.t.

anmonteiro commented 2 months ago

it's fairly easy to do this, though it's unsafe.

here's a simplified version with eio:

let request_handler (_fd: _ Eio.Net.stream_socket) (_ : Eio.Net.Sockaddr.stream) { Gluten.reqd= _; _ } =
  assert false
;;

(* ... *)

let handler fd =
  Server.create_connection_handler
    ~request_handler:(request_handler fd)
    ~error_handler

(* ... *)

while true do
  Eio.Net.accept_fork socket ~sw ~on_error:log_connection_error (fun client_sock client_addr ->
    handler client_sock client_addr client_sock)
done;

Eio.Net.accept* (or Lwt_io.establish_server_with_client_socket) has the fd reference in the callback somewhere, all you need to do is eta-expand to use it.

aantron commented 2 months ago

Thank you. On a basic level, I have it working. However, is the expansion still safe w.r.t. side effects for SSL?

      let request_handler = wrap_handler true error_handler handler in
      let error_handler = Error_handler.httpaf error_handler in
      fun client_address unix_socket tls_endpoint ->
        Httpaf_lwt_unix.Server.SSL.create_connection_handler
          ?config:None
          ~request_handler:(request_handler unix_socket)
          ~error_handler
          client_address
          tls_endpoint

and likewise for ocaml-h2?

anmonteiro commented 2 months ago

However, is the expansion still safe w.r.t. side effects for SSL?

I believe you can rely on this, since the connection establishment happens at accept, i.e. before the callback is invoked.

aantron commented 2 months ago

Alright, thank you! This is probably the most questionable part of Dream at this point, together with the Obj.magic in https://github.com/aantron/dream/pull/345 for getting actual fd numbers, but if it works... it works :)

anmonteiro commented 2 months ago

but if it works... it works :)

I don't know if "it works". Referring to my initial response:

it's fairly easy to do this, though it's unsafe.

it depends what you do with the socket. httpun / gluten / etc guarantee the correct lifecycle for the connection (and consequently, the socket) – that's not the case if you're accessing it directly.

aantron commented 2 months ago

Dumping the fd number on Unix.

anmonteiro commented 2 months ago

I understood your intent, but I wanted to leave it written down for the next person looking for this answer.