open H2 module Client = H2_eio.Client let response_handler ~on_eof response response_body = Format.eprintf "Response: %a@." Response.pp_hum response; let rec read_response () = Body.Reader.schedule_read response_body ~on_eof ~on_read:(fun bigstring ~off ~len -> Format.eprintf "heh nice %d@." len; let response_fragment = Bytes.create len in Bigstringaf.blit_to_bytes bigstring ~src_off:off response_fragment ~dst_off:0 ~len; print_string (Bytes.to_string response_fragment); read_response ()) in read_response () let error_handler u err = (match err with | `Exn exn -> Format.eprintf "wut %S@." (Printexc.to_string exn) | `Invalid_response_body_length res -> Format.eprintf "invalid res: %a@." Response.pp_hum res | `Malformed_response str -> Format.eprintf "malformed %S@." str | `Protocol_error (err, s) -> Format.eprintf "wut %a %S@." H2.Error_code.pp_hum err s); Eio.Promise.resolve u () let[@ocaml.alert "-deprecated"] () = Ssl_threads.init (); Ssl.init ~thread_safe:true (); let host = ref None in let port = ref 443 in Arg.parse [ "-p", Set_int port, " Port number (443 by default)" ] (fun host_argument -> host := Some host_argument) "eio_get.exe [-p N] HOST"; let host = match !host with | None -> failwith "No hostname provided" | Some host -> host in Eio_main.run (fun env -> let network = Eio.Stdenv.net env in Eio.Switch.run (fun sw -> let addrs = let addrs = Eio_unix.run_in_systhread (fun () -> Unix.getaddrinfo host (string_of_int !port) [ Unix.(AI_FAMILY PF_INET) ]) in List.filter_map (fun (addr : Unix.addr_info) -> match addr.ai_addr with | Unix.ADDR_UNIX _ -> None | ADDR_INET (addr, port) -> Some (addr, port)) addrs in let addr = let inet, port = List.hd addrs in `Tcp (Eio_unix.Net.Ipaddr.of_unix inet, port) in let socket = Eio.Net.connect ~sw network addr in let request = Request.create `GET "/" ~scheme:"https" ~headers: Headers.( add_list empty [ "user-agent", "carl/0.0.0-experimental"; ":authority", host ]) in let ctx = Ssl.create_context Ssl.SSLv23 Ssl.Client_context in (* Ssl.disable_protocols ctx [ Ssl.SSLv23 ]; *) Ssl.honor_cipher_order ctx; Ssl.set_context_alpn_protos ctx [ "h2" ]; Ssl.set_min_protocol_version ctx TLSv1_3; Ssl.set_max_protocol_version ctx TLSv1_3; let ssl_ctx = Eio_ssl.Context.create ~ctx socket in let ssl_sock = Eio_ssl.Context.ssl_socket ssl_ctx in Ssl.set_client_SNI_hostname ssl_sock host; Ssl.set_hostflags ssl_sock [ No_partial_wildcards ]; Ssl.set_host ssl_sock host; let ssl_sock = Eio_ssl.connect ssl_ctx in let shut_p, shut_u = Eio.Promise.create () in let error_handler = error_handler shut_u in let connection = Client.create_connection ~sw ~error_handler ssl_sock in let response_handler = response_handler ~on_eof:(fun () -> Format.eprintf "eof@."; Eio.Promise.resolve shut_u ()) in let request_body = Client.request connection request ~error_handler ~response_handler ~flush_headers_immediately:true in Body.Writer.close request_body; Eio.Promise.await shut_p; Eio.Promise.await (Client.shutdown connection)))