2017-05-26 14:30:34 +00:00
|
|
|
(* (c) 2017 Hannes Mehnert, all rights reserved *)
|
|
|
|
|
|
|
|
open Lwt.Infix
|
|
|
|
|
2018-09-09 18:52:04 +00:00
|
|
|
let pp_sockaddr ppf = function
|
|
|
|
| Lwt_unix.ADDR_UNIX str -> Fmt.pf ppf "unix domain socket %s" str
|
|
|
|
| Lwt_unix.ADDR_INET (addr, port) -> Fmt.pf ppf "TCP %s:%d"
|
|
|
|
(Unix.string_of_inet_addr addr) port
|
|
|
|
|
2017-05-26 14:30:34 +00:00
|
|
|
let pp_process_status ppf = function
|
2017-12-20 21:29:22 +00:00
|
|
|
| Unix.WEXITED c -> Fmt.pf ppf "exited with %d" c
|
|
|
|
| Unix.WSIGNALED s -> Fmt.pf ppf "killed by signal %a" Fmt.Dump.signal s
|
|
|
|
| Unix.WSTOPPED s -> Fmt.pf ppf "stopped by signal %a" Fmt.Dump.signal s
|
2017-05-26 14:30:34 +00:00
|
|
|
|
|
|
|
let ret = function
|
|
|
|
| Unix.WEXITED c -> `Exit c
|
|
|
|
| Unix.WSIGNALED s -> `Signal s
|
|
|
|
| Unix.WSTOPPED s -> `Stop s
|
|
|
|
|
2018-03-18 13:04:44 +00:00
|
|
|
let rec waitpid pid =
|
|
|
|
Lwt.catch
|
|
|
|
(fun () -> Lwt_unix.waitpid [] pid >|= fun r -> Ok r)
|
|
|
|
(function
|
|
|
|
| Unix.(Unix_error (EINTR, _, _)) ->
|
|
|
|
Logs.debug (fun m -> m "EINTR in waitpid(), %d retrying" pid) ;
|
|
|
|
waitpid pid
|
|
|
|
| e ->
|
|
|
|
Logs.err (fun m -> m "error %s in waitpid() %d"
|
|
|
|
(Printexc.to_string e) pid) ;
|
|
|
|
Lwt.return (Error ()))
|
|
|
|
|
2017-05-26 14:30:34 +00:00
|
|
|
let wait_and_clear pid stdout =
|
2018-03-18 13:04:44 +00:00
|
|
|
Logs.debug (fun m -> m "waitpid() for pid %d" pid) ;
|
|
|
|
waitpid pid >|= fun r ->
|
2018-07-07 21:14:42 +00:00
|
|
|
Vmm_unix.close_no_err stdout ;
|
2018-03-18 13:04:44 +00:00
|
|
|
match r with
|
|
|
|
| Error () ->
|
|
|
|
Logs.err (fun m -> m "waitpid() for %d returned error" pid) ;
|
|
|
|
`Exit 23
|
|
|
|
| Ok (_, s) ->
|
|
|
|
Logs.debug (fun m -> m "pid %d exited: %a" pid pp_process_status s) ;
|
|
|
|
ret s
|
2017-05-26 14:30:34 +00:00
|
|
|
|
2018-09-09 18:52:04 +00:00
|
|
|
let read_wire s =
|
2018-10-22 21:20:00 +00:00
|
|
|
let buf = Bytes.create 4 in
|
2017-05-26 14:30:34 +00:00
|
|
|
let rec r b i l =
|
2018-03-18 17:30:43 +00:00
|
|
|
Lwt.catch (fun () ->
|
|
|
|
Lwt_unix.read s b i l >>= function
|
|
|
|
| 0 ->
|
|
|
|
Logs.err (fun m -> m "end of file while reading") ;
|
|
|
|
Lwt.return (Error `Eof)
|
|
|
|
| n when n == l -> Lwt.return (Ok ())
|
|
|
|
| n when n < l -> r b (i + n) (l - n)
|
|
|
|
| _ ->
|
|
|
|
Logs.err (fun m -> m "read too much, shouldn't happen)") ;
|
|
|
|
Lwt.return (Error `Toomuch))
|
|
|
|
(fun e ->
|
|
|
|
let err = Printexc.to_string e in
|
|
|
|
Logs.err (fun m -> m "exception %s while reading" err) ;
|
|
|
|
Lwt.return (Error `Exception))
|
2017-05-26 14:30:34 +00:00
|
|
|
in
|
2018-10-22 21:20:00 +00:00
|
|
|
r buf 0 4 >>= function
|
2018-03-18 17:30:43 +00:00
|
|
|
| Error e -> Lwt.return (Error e)
|
|
|
|
| Ok () ->
|
2018-10-22 21:20:00 +00:00
|
|
|
let len = Cstruct.BE.get_uint32 (Cstruct.of_bytes buf) 0 in
|
|
|
|
if len > 0l then
|
|
|
|
let b = Bytes.create (Int32.to_int len) in
|
|
|
|
r b 0 (Int32.to_int len) >|= function
|
|
|
|
| Error e -> Error e
|
|
|
|
| Ok () ->
|
|
|
|
(* Logs.debug (fun m -> m "read hdr %a, body %a"
|
2018-03-18 17:30:43 +00:00
|
|
|
Cstruct.hexdump_pp (Cstruct.of_bytes buf)
|
2018-09-28 20:44:38 +00:00
|
|
|
Cstruct.hexdump_pp (Cstruct.of_bytes b)) ; *)
|
2018-10-22 21:20:00 +00:00
|
|
|
match Vmm_asn.wire_of_cstruct (Cstruct.of_bytes b) with
|
|
|
|
| Ok w -> Ok w
|
|
|
|
| Error (`Msg msg) ->
|
|
|
|
Logs.err (fun m -> m "error %s while parsing data" msg) ;
|
|
|
|
Error `Exception
|
|
|
|
else
|
|
|
|
Lwt.return (Error `Eof)
|
2017-05-26 14:30:34 +00:00
|
|
|
|
2018-10-22 22:02:05 +00:00
|
|
|
let write_raw s buf =
|
2017-05-26 14:30:34 +00:00
|
|
|
let rec w off l =
|
2018-03-18 17:30:43 +00:00
|
|
|
Lwt.catch (fun () ->
|
|
|
|
Lwt_unix.send s buf off l [] >>= fun n ->
|
|
|
|
if n = l then
|
|
|
|
Lwt.return (Ok ())
|
|
|
|
else
|
|
|
|
w (off + n) (l - n))
|
|
|
|
(fun e ->
|
|
|
|
Logs.err (fun m -> m "exception %s while writing" (Printexc.to_string e)) ;
|
|
|
|
Lwt.return (Error `Exception))
|
2017-05-26 14:30:34 +00:00
|
|
|
in
|
2018-09-28 20:44:38 +00:00
|
|
|
(* Logs.debug (fun m -> m "writing %a" Cstruct.hexdump_pp (Cstruct.of_bytes buf)) ; *)
|
2017-05-26 14:30:34 +00:00
|
|
|
w 0 (Bytes.length buf)
|
2018-09-09 18:52:04 +00:00
|
|
|
|
2018-10-22 22:02:05 +00:00
|
|
|
let write_wire s wire =
|
|
|
|
let data = Vmm_asn.wire_to_cstruct wire in
|
|
|
|
let dlen = Cstruct.create 4 in
|
|
|
|
Cstruct.BE.set_uint32 dlen 0 (Int32.of_int (Cstruct.len data)) ;
|
|
|
|
let buf = Cstruct.(to_bytes (append dlen data)) in
|
|
|
|
write_raw s buf
|
|
|
|
|
2018-09-09 18:52:04 +00:00
|
|
|
let safe_close fd =
|
|
|
|
Lwt.catch
|
|
|
|
(fun () -> Lwt_unix.close fd)
|
|
|
|
(fun _ -> Lwt.return_unit)
|