open Alpn_lib let http1_handler = Httpun_lwt_unix.Server.SSL.create_connection_handler ?config:None ~request_handler:Http1_handler.request_handler ~error_handler:Http1_handler.error_handler let h2_handler = H2_lwt_unix.Server.SSL.create_connection_handler ~request_handler:H2_handler.request_handler ~error_handler:H2_handler.error_handler let start_http_server () = let open Lwt.Infix in let listen_address = Unix.(ADDR_INET (inet_addr_loopback, 8080)) in Lwt.async (fun () -> Lwt_io.establish_server_with_client_socket listen_address (Httpun_lwt_unix.Server.create_connection_handler ?config:None ~request_handler:Http1_handler.redirect_handler ~error_handler:Http1_handler.redirect_error_handler) >>= fun _server -> Lwt.return_unit); let forever, _ = Lwt.wait () in forever let rec first_match l1 = function | [] -> None | x :: _ when List.mem x l1 -> Some x | _ :: xs -> first_match l1 xs let start_https_server () = let open Lwt.Infix in let listen_address = Unix.(ADDR_INET (inet_addr_loopback, 9443)) in let cert = "./certificates/server.pem" in let priv_key = "./certificates/server.key" in Lwt.async (fun () -> Lwt_io.establish_server_with_client_socket listen_address (fun client_addr fd -> Lwt.catch (fun () -> let server_ctx = Ssl.create_context Ssl.TLSv1_3 Ssl.Server_context in Ssl.disable_protocols server_ctx ([ Ssl.SSLv23; Ssl.TLSv1_1 ] [@ocaml.alert "-deprecated"]); Ssl.use_certificate server_ctx cert priv_key; let protos = [ "h2"; "http/1.1" ] in Ssl.set_context_alpn_protos server_ctx protos; Ssl.set_context_alpn_select_callback server_ctx (fun client_protos -> first_match client_protos protos); Lwt_ssl.ssl_accept fd server_ctx >>= fun ssl_server -> match Lwt_ssl.ssl_socket ssl_server with | None -> assert false | Some ssl_socket -> (match Ssl.get_negotiated_alpn_protocol ssl_socket with | None -> (* Unable to negotiate a protocol *) Lwt.return_unit | Some "http/1.1" -> http1_handler client_addr ssl_server | Some "h2" -> h2_handler client_addr ssl_server | Some _ -> (* Can't really happen - would mean that TLS negotiated a * protocol that we didn't specify. *) assert false)) (fun exn -> Lwt_io.eprintlf "EXN: %s" (Printexc.to_string exn))) >>= fun _server -> Lwt.return_unit); let forever, _ = Lwt.wait () in forever let () = Sys.(set_signal sigpipe Signal_ignore); Lwt_main.run (Lwt.join [ start_http_server (); start_https_server () ])