#use "topfind";; #require "equeue,nettls-gnutls";; (* This example connects stdin/stdout with a remote SSL service. To test * replace the following IP address and port with real numbers, e.g. * with an HTTPS server. Then start with * * ocaml ssl_client.ml * * Then enter something like: * * GET / HTTP/1.0 * * (+ double new lines). *) let remote_name = "www.google.com" ;; let remote_ip_addr = (Uq_resolver.get_host_by_name remote_name).Unix.h_addr_list.(0) let remote_port = 443 ;; let maybe_error err_opt = match err_opt with | None -> () | Some err -> raise err ;; let communicate tls_mplex = prerr_endline "* TLS handshake done"; let esys = tls_mplex # event_system in let shutdown_in = ref (fun _ _ _ -> ()) in let shutdown_out = ref (fun _ _ _ -> ()) in let in_ch = new Uq_transfer.input_async_mplex ~onshutdown:(`Action (fun ch m s -> !shutdown_in ch m s)) ~buffer_size:10 tls_mplex in let _sender = new Uq_transfer.sender ~src:in_ch ~dst:Unix.stdout ~close_dst:false esys in let out_ch = new Uq_transfer.output_async_mplex ~onshutdown:(`Action (fun ch m s -> !shutdown_out ch m s)) ~buffer_size:10 tls_mplex in let _receiver = new Uq_transfer.receiver ~src:Unix.stdin ~dst:out_ch ~close_src:false esys in (* Shutdown actions: Because we have two channels attached to a * single multiplexer, we must synchronize the shutdown. *) shutdown_in := ( fun ch m s -> (* The SSL connection is terminated. If the out_ch * is already finished, we shut down the multiplexer. * Else we simply abort the output channel. *) match out_ch # state with | `Working _ -> out_ch # abort() | _ -> m # start_shutting_down ~when_done:(fun _ -> ()) () ); shutdown_out := (fun ch m s -> (* The terminal connection is terminated. Now we * have to check whether in_ch is still alive. *) match in_ch # state with | `Working _ -> in_ch # abort() | _ -> m # start_shutting_down ~when_done:(fun _ -> ()) () ); () let main() = Nettls_gnutls.init(); let esys = Unixqueue.create_unix_event_system() in let cl = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in prerr_endline "* TCP connected"; Unix.connect cl (Unix.ADDR_INET (remote_ip_addr, remote_port)); let tls_config = Netsys_tls.create_x509_config ~system_trust:true ~peer_auth:`Required (module Nettls_gnutls.TLS) in let cl_mplex = Uq_multiplex.create_multiplex_controller_for_connected_socket cl esys in let _tls_mplex = Uq_multiplex.tls_multiplex_controller ~on_handshake:communicate ~role:`Client ~peer_name:(Some remote_name) tls_config cl_mplex in esys# run() ;; (* Unixqueue.set_debug_mode true;*) main();; prerr_endline "DONE";