From 99f6a020faba44db461c5ff92a1893bf04a63c0a Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 25 Oct 2022 10:13:49 +0100 Subject: [PATCH 01/18] unix: add Cstruct_unix.{read,write,writev,send,recv} This is useful for direct-style code to avoid copying Cstructs into temporary byte buffers. Signed-off-by: David Scott --- unix/dune | 3 + unix/read_stubs.c | 70 +++++++++++++++++++++ unix/recv_stubs.c | 63 +++++++++++++++++++ unix/send_stubs.c | 62 ++++++++++++++++++ unix/unix_cstruct.ml | 57 +++++++++++++++++ unix/unix_cstruct.mli | 21 +++++++ unix/write_stubs.c | 69 ++++++++++++++++++++ unix/writev_stubs.c | 69 ++++++++++++++++++++ unix_test/dune | 10 +++ unix_test/tests.ml | 143 ++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 567 insertions(+) create mode 100644 unix/read_stubs.c create mode 100644 unix/recv_stubs.c create mode 100644 unix/send_stubs.c create mode 100644 unix/write_stubs.c create mode 100644 unix/writev_stubs.c create mode 100644 unix_test/dune create mode 100644 unix_test/tests.ml diff --git a/unix/dune b/unix/dune index 9031788a..f483a598 100644 --- a/unix/dune +++ b/unix/dune @@ -2,4 +2,7 @@ (name cstruct_unix) (wrapped false) (public_name cstruct-unix) + (foreign_stubs + (language c) + (names read_stubs write_stubs writev_stubs send_stubs recv_stubs)) (libraries cstruct unix)) diff --git a/unix/read_stubs.c b/unix/read_stubs.c new file mode 100644 index 00000000..424a1071 --- /dev/null +++ b/unix/read_stubs.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +CAMLprim value stub_cstruct_read(value val_fd, value val_c) +{ + CAMLparam2(val_fd, val_c); + CAMLlocal3(val_buf, val_ofs, val_len); + + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + + void *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + size_t len = Long_val(val_len); + int n = 0; + +#ifdef _WIN32 + int win32err = 0; + switch (Descr_kind_val(val_fd)) + { + case KIND_SOCKET: + SOCKET s = Socket_val(val_fd); + + caml_release_runtime_system(); + n = recv(s, buf, len, 0); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + unix_error(errno, "read", Nothing); + } + break; + case KIND_HANDLE: + HANDLE h = Handle_val(val_fd); + DWORD numread; + caml_release_runtime_system(); + int ok = ReadFile(h, buf, len, &numread, NULL); + win32err = GetLastError(); + n = numread; + caml_acquire_runtime_system(); + + if (!ok) + { + win32_maperr(win32err); + unix_error(errno, "read", Nothing); + } + break; + default: + caml_failwith("unknown Descr_kind_val"); + } +#else + caml_release_runtime_system(); + n = read(Int_val(val_fd), buf, len); + caml_acquire_runtime_system(); + if (n < 0) + unix_error(errno, "read", Nothing); +#endif + CAMLreturn(Val_int(n)); +} diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c new file mode 100644 index 00000000..2031b7b3 --- /dev/null +++ b/unix/recv_stubs.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#else +#include +#include +#include +#endif + +CAMLprim value stub_cstruct_recv(value val_fd, value val_c) +{ + CAMLparam2(val_fd, val_c); + CAMLlocal3(val_buf, val_ofs, val_len); + + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + + void *buf = (void *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + size_t len = (size_t)Long_val(val_len); + int n = 0; +#ifdef WIN32 + int win32err = 0; + if (Descr_kind_val(val_fd) != KIND_SOCKET) + unix_error(EINVAL, "recv", Nothing); + + SOCKET s = Socket_val(val_fd); + + caml_release_runtime_system(); + n = recv(s, buf, len, 0); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + unix_error(errno, "recv", Nothing); + } +#else + int fd = Int_val(val_fd); + + caml_release_runtime_system(); + n = recv(fd, buf, len, 0); + caml_acquire_runtime_system(); + + if (n < 0) + unix_error(errno, "recv", Nothing); +#endif + CAMLreturn(Val_int(n)); +} diff --git a/unix/send_stubs.c b/unix/send_stubs.c new file mode 100644 index 00000000..bb8f1df1 --- /dev/null +++ b/unix/send_stubs.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#else +#include +#include +#include +#endif + +CAMLprim value stub_cstruct_send(value val_fd, value val_c) +{ + CAMLparam2(val_fd, val_c); + CAMLlocal3(val_buf, val_ofs, val_len); + + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + + const char *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + size_t len = (size_t)Long_val(val_len); + int n = 0; + +#ifdef WIN32 + int win32err = 0; + if (Descr_kind_val(val_fd) != KIND_SOCKET) + unix_error(EINVAL, "send", Nothing); + + SOCKET s = Socket_val(val_fd); + caml_release_runtime_system(); + n = send(s, buf, len, 0); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + unix_error(errno, "send", Nothing); + } +#else + int fd = Int_val(val_fd); + + caml_release_runtime_system(); + n = send(fd, buf, len, 0); + caml_acquire_runtime_system(); + if (n < 0) + unix_error(errno, "send", Nothing); +#endif + CAMLreturn(Val_int(n)); +} diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index 5ac69851..c6f0419a 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -17,3 +17,60 @@ let of_fd fd = let buffer = Bigarray.(array1_of_genarray (Unix.map_file fd char c_layout false [|-1|])) in Cstruct.of_bigarray buffer + +type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t + +(* Returns 0 if there is no writev *) +external stub_iov_max: unit -> int = "stub_cstruct_iov_max" + +external stub_write: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_write" + +external stub_writev: Unix.file_descr -> (buffer * int * int) list -> int = "stub_cstruct_writev" + +let iov_max = stub_iov_max () + +(* return the first n fragments, suitable for writev *) +let rec first n rev_acc = function +| [] -> List.rev rev_acc +| _ when n = 0 -> List.rev rev_acc +| x :: xs -> first (n - 1) (x :: rev_acc) xs + +(* shift a list of fragments along by n bytes *) +let rec shift t x = + if x = 0 then t else match t with + | [] -> invalid_arg "foo" + | y :: ys -> + let y' = Cstruct.length y in + if y' > x + then Cstruct.shift y x :: ys + else shift ys (x - y') + +let rec write fd buf = + if Cstruct.length buf > 0 then begin + let n = stub_write fd (buf.Cstruct.buffer, buf.Cstruct.off, buf.Cstruct.len) in + write fd @@ Cstruct.shift buf n + end + +let writev fd bufs = + let rec use_writev = function + | [] -> () + | remaining -> + (* write at most iov_max at a time *) + let to_send = first iov_max [] remaining in + let n = stub_writev fd (List.map (fun x -> x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) to_send) in + let rest = shift remaining n in + use_writev rest in + let use_write_fallback = List.iter (write fd) in + (if iov_max = 0 then use_write_fallback else use_writev) bufs + +external stub_send: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_send" + +external stub_recv: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_recv" + +let send fd x = stub_send fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) + +let recv fd x = stub_recv fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) + +external stub_read: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_read" + +let read fd x = stub_read fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) \ No newline at end of file diff --git a/unix/unix_cstruct.mli b/unix/unix_cstruct.mli index 361191d2..1846c9ef 100644 --- a/unix/unix_cstruct.mli +++ b/unix/unix_cstruct.mli @@ -1,5 +1,6 @@ (* * Copyright (c) 2012 Anil Madhavapeddy + * Copyright (c) 2022 David Scott * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,3 +19,23 @@ val of_fd : Unix.file_descr -> Cstruct.t (** [of_fd fd] memory maps the [fd] and returns a cstruct *) + +val read: Unix.file_descr -> Cstruct.t -> int +(** [read fd cs] reads from the file descriptor into the buffer, returning the number of bytes read. + Similar to Unix.read. *) + +val write: Unix.file_descr -> Cstruct.t -> unit +(** [write fd cs] writes the whole Cstruct to the file descriptor. + Similar to Unix.write. *) + +val writev: Unix.file_descr -> Cstruct.t list -> unit +(** [writev fd cs] writes the whole list of Cstructs to the file descriptor. + Similar to Unix.write. *) + +val send: Unix.file_descr -> Cstruct.t -> int +(** [send fd c] sends a message from a socket. This can be used to send a datagram. + If only a partial send is possible, the return argument is how many bytes were sent. *) + +val recv: Unix.file_descr -> Cstruct.t -> int +(** [recv fd c] receives a message from a socket. This can be used to receive a datagram. + If only a partial receive is possible, the return argument is now many bytes were received. *) diff --git a/unix/write_stubs.c b/unix/write_stubs.c new file mode 100644 index 00000000..655ba845 --- /dev/null +++ b/unix/write_stubs.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +CAMLprim value stub_cstruct_write(value val_fd, value val_c) +{ + CAMLparam2(val_fd, val_c); + CAMLlocal3(val_buf, val_ofs, val_len); + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + void *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + size_t len = Long_val(val_len); + int n = 0; + +#ifdef _WIN32 + int win32err = 0; + switch (Descr_kind_val(val_fd)) + { + case KIND_SOCKET: + SOCKET s = Socket_val(val_fd); + + caml_release_runtime_system(); + n = send(s, buf, len, 0); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + unix_error(errno, "writev", Nothing); + } + break; + case KIND_HANDLE: + HANDLE h = Handle_val(val_fd); + DWORD numwritten; + caml_release_runtime_system(); + int ok = WriteFile(h, buf, len, &numwritten, NULL); + win32err = GetLastError(); + + n = numwritten; + caml_acquire_runtime_system(); + + if (!ok) + { + win32_maperr(win32err); + unix_error(errno, "writev", Nothing); + } + break; + default: + caml_failwith("unknown Descr_kind_val"); + } +#else + caml_release_runtime_system(); + n = write(Int_val(val_fd), buf, len); + caml_acquire_runtime_system(); + if (n < 0) + unix_error(errno, "write", Nothing); +#endif + CAMLreturn(Val_int(n)); +} diff --git a/unix/writev_stubs.c b/unix/writev_stubs.c new file mode 100644 index 00000000..d5b4334f --- /dev/null +++ b/unix/writev_stubs.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifndef _WIN32 +#include +#include +#endif + +CAMLprim + value + stub_cstruct_iov_max(value unit) +{ + CAMLparam1(unit); +#ifdef IOV_MAX + CAMLreturn(Val_int(IOV_MAX)); +#else + CAMLreturn(Val_int(0)); +#endif +} + +CAMLprim + value + stub_cstruct_writev(value fd, value val_list) +{ + CAMLparam2(fd, val_list); + CAMLlocal5(next, head, val_buf, val_ofs, val_len); + int i; +#ifdef _WIN32 + caml_failwith("writev is not supported on Win32"); +#else + struct iovec iovec[IOV_MAX]; + int c_fd = Int_val(fd); + + next = val_list; + /* Calculate the length of the val_list */ + int length = 0; + for (next = val_list; next != Val_emptylist; next = Field(next, 1)) + length++; + /* Only copy up to the iovec array size */ + if (length > IOV_MAX) + length = IOV_MAX; + next = val_list; + for (i = 0; i < length; i++) + { + head = Field(next, 0); + val_buf = Field(head, 0); + val_ofs = Field(head, 1); + val_len = Field(head, 2); + iovec[i].iov_base = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + iovec[i].iov_len = Long_val(val_len); + next = Field(next, 1); + } + + caml_release_runtime_system(); + ssize_t n = writev(c_fd, iovec, length); + caml_acquire_runtime_system(); + if (n < 0) + unix_error(errno, "writev", Nothing); + CAMLreturn(Val_int(n)); +#endif +} diff --git a/unix_test/dune b/unix_test/dune new file mode 100644 index 00000000..45191d7c --- /dev/null +++ b/unix_test/dune @@ -0,0 +1,10 @@ +(executable + (libraries cstruct alcotest cstruct-unix threads) + (modules tests) + (name tests)) + +(rule + (alias runtest) + (package cstruct-unix) + (action + (run ./tests.exe -e))) diff --git a/unix_test/tests.ml b/unix_test/tests.ml new file mode 100644 index 00000000..28ade14c --- /dev/null +++ b/unix_test/tests.ml @@ -0,0 +1,143 @@ + +let mk_temp_dir () = + let rand_num = Random.int 1000000 |> string_of_int in + let tmp_dir = Filename.get_temp_dir_name () ^ "/test-cstruct-unix-" ^ rand_num in + try + Unix.mkdir tmp_dir 0o700; + tmp_dir + with Unix.Unix_error(Unix.EEXIST, _, _) -> + (* re-use the old one *) + tmp_dir + | e -> raise (Sys_error ("Cannot create temp dir " ^ tmp_dir ^ " " ^ (Printexc.to_string e))) + +let rmdir path = + (* non-recursive for safety *) + match Sys.is_directory path with + | true -> + Sys.readdir path |> + Array.iter (fun name -> Sys.remove (Filename.concat path name)); + Unix.rmdir path + | false -> Sys.remove path + +let finally f g = + try + let r = f () in + g (); + r + with e -> + g (); + raise e + +let with_tmp_dir f = + let dir = mk_temp_dir () in + finally (fun () -> f dir) (fun () -> rmdir dir) + +let test_message_list =[ + Cstruct.of_string "hello"; + Cstruct.of_string " "; + Cstruct.of_string "cstruct"; + Cstruct.create 0; + Cstruct.of_string " "; + Cstruct.of_string "world"; +] + +let read_and_check fd sent_message = + let expected = Cstruct.(to_string @@ concat sent_message) in + let buf = Cstruct.create 1024 in + let read = ref 0 in + while !read < (String.length expected) do + let n = Unix_cstruct.read fd (Cstruct.shift buf !read) in + if n = 0 then raise End_of_file; + read := !read + n + done; + let actual = Cstruct.(to_string @@ sub buf 0 !read) in + Alcotest.(check string) "read contents" expected actual + +let test_writev_file () = + with_tmp_dir + (fun dir -> + let test = Filename.concat dir "test" in + let fd = Unix.openfile test [ Unix.O_CREAT; Unix.O_RDWR ] 0o644 in + finally (fun () -> + Unix_cstruct.writev fd test_message_list; + let ofs = Unix.lseek fd 0 Unix.SEEK_SET in + Alcotest.(check int) "file offset" 0 ofs; + read_and_check fd test_message_list + ) (fun () -> Unix.close fd) + ) + +let with_sock_stream f = + let s = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in + finally (fun () -> f s) (fun () -> Unix.close s) + +let localhost = Unix.inet_addr_of_string "127.0.0.1" + +let bind_random_port s = + Unix.bind s (Unix.ADDR_INET(localhost, 0)); + match Unix.getsockname s with + | Unix.ADDR_INET(_, port) -> port + | _ -> assert false + +let test_writev_socket () = + with_sock_stream (fun s -> + let port = bind_random_port s in + Unix.listen s 1; + let t = Thread.create (fun () -> + let client, _ = Unix.accept s in + finally + (fun () -> + read_and_check client test_message_list + ) (fun () -> Unix.close client) + ) () in + with_sock_stream (fun c -> + Unix.connect c (Unix.ADDR_INET(localhost, port)); + Unix_cstruct.writev c test_message_list; + ); + Thread.join t + ) + +let with_sock_dgram f = + let s = Unix.socket Unix.PF_INET Unix.SOCK_DGRAM 0 in + finally (fun () -> f s) (fun () -> Unix.close s) + +let with_mutex m f = + Mutex.lock m; + finally f (fun () -> Mutex.unlock m) + +let test_send_recv () = + let test_message = Cstruct.concat test_message_list in + with_sock_dgram (fun s -> + let port = bind_random_port s in + let m = Mutex.create () in + let finished = ref false in + let t = Thread.create (fun () -> + let buf = Cstruct.create 1024 in + let n = Unix_cstruct.recv s buf in + Alcotest.(check int) "recv length" (Cstruct.length test_message) n; + let expected = Cstruct.to_string test_message in + let actual = Cstruct.(to_string @@ sub buf 0 n) in + Alcotest.(check string) "read contents" expected actual; + with_mutex m (fun () -> finished := true) + ) () in + with_sock_dgram (fun c -> + Unix.connect c (Unix.ADDR_INET(localhost, port)); + while with_mutex m (fun () -> not !finished) do + let n = Unix_cstruct.send c test_message in + Alcotest.(check int) "send length" (Cstruct.length test_message) n; + Thread.delay 0.1 + done + ); + Thread.join t + ) + +let suite = [ + "writev", [ + "test read and writev via a file", `Quick, test_writev_file; + "test read and writev via a socket", `Quick, test_writev_socket; + ]; + "send recv", [ + "test send and recv", `Quick, test_send_recv; + ] +] + +let () = Alcotest.run "cstruct.unix" suite \ No newline at end of file From 87382a1a4574e46161573469b9f27628c98ec006 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 1 Nov 2022 14:22:48 +0000 Subject: [PATCH 02/18] Update unix/writev_stubs.c Linux doesn't export IOV_MAX unless you define _XOPEN_SOURCE or _GNU_SOURCE (from @haesbaert) Co-authored-by: Christiano Haesbaert --- unix/writev_stubs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unix/writev_stubs.c b/unix/writev_stubs.c index d5b4334f..a6b5a12b 100644 --- a/unix/writev_stubs.c +++ b/unix/writev_stubs.c @@ -1,3 +1,4 @@ +#define _XOPEN_SOURCE /* IOV_MAX */ #include #include #include From 600272138e5a0e63b62a586544e389019dfe5b15 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 1 Nov 2022 14:23:09 +0000 Subject: [PATCH 03/18] Update unix/recv_stubs.c makes it easier to grep for the source of the error if we just name it after the function. (from @avsm) Co-authored-by: Anil Madhavapeddy --- unix/recv_stubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index 2031b7b3..1b670391 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -35,7 +35,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) #ifdef WIN32 int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) - unix_error(EINVAL, "recv", Nothing); + unix_error(EINVAL, "stub_cstruct_recv", Nothing); SOCKET s = Socket_val(val_fd); From 239013411dfe3c428f737398caad6fa7024a7ff0 Mon Sep 17 00:00:00 2001 From: Christiano Haesbaert Date: Fri, 28 Oct 2022 12:30:17 +0200 Subject: [PATCH 04/18] recvfrom and sendto with flags The recv/send tests looked a bit complex so I've changed mine, don't see why we would need threads since it's just one message. --- unix/dune | 3 ++- unix/recvfrom_stubs.c | 50 +++++++++++++++++++++++++++++++++++++++++++ unix/sendto_stubs.c | 45 ++++++++++++++++++++++++++++++++++++++ unix/unix_cstruct.ml | 10 ++++++++- unix/unix_cstruct.mli | 6 ++++++ unix_test/tests.ml | 33 +++++++++++++++++++++++++++- 6 files changed, 144 insertions(+), 3 deletions(-) create mode 100644 unix/recvfrom_stubs.c create mode 100644 unix/sendto_stubs.c diff --git a/unix/dune b/unix/dune index f483a598..55bddef8 100644 --- a/unix/dune +++ b/unix/dune @@ -4,5 +4,6 @@ (public_name cstruct-unix) (foreign_stubs (language c) - (names read_stubs write_stubs writev_stubs send_stubs recv_stubs)) + (names read_stubs write_stubs writev_stubs send_stubs recv_stubs + recvfrom_stubs sendto_stubs)) (libraries cstruct unix)) diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c new file mode 100644 index 00000000..ed7ab50e --- /dev/null +++ b/unix/recvfrom_stubs.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int msg_flag_table[] = { + MSG_OOB, MSG_DONTROUTE, MSG_PEEK /* XXX */ +}; + +CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) +{ + CAMLparam3(val_fd, val_c, val_flags); + CAMLlocal5(val_buf, val_ofs, val_len, val_addr, val_res); + uint8_t *buf; + size_t len; + ssize_t n; + int cv_flags; + union sock_addr_union addr; + socklen_param_type addr_len; + + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); + + buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + len = Long_val(val_len); + addr_len = sizeof(addr); + + caml_release_runtime_system(); + n = recvfrom(Int_val(val_fd), buf, len, cv_flags, &addr.s_gen, &addr_len); + caml_acquire_runtime_system(); + + if (n == -1) + caml_uerror("recvfrom", Nothing); + + val_addr = caml_unix_alloc_sockaddr(&addr, addr_len, -1); + val_res = caml_alloc_small(2, 0); + Field(val_res, 0) = Val_int(n); + Field(val_res, 1) = val_addr; + + CAMLreturn (val_res); +} diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c new file mode 100644 index 00000000..3cfde22f --- /dev/null +++ b/unix/sendto_stubs.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static int msg_flag_table[] = { /* XXX */ + MSG_OOB, MSG_DONTROUTE, MSG_PEEK +}; + +CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, value val_daddr) +{ + CAMLparam4(val_fd, val_c, val_flags, val_daddr); + CAMLlocal5(val_buf, val_ofs, val_len, val_addr, val_res); + union sock_addr_union addr; + socklen_param_type addr_len; + uint8_t *buf; + size_t len; + ssize_t n; + int cv_flags; + + val_buf = Field(val_c, 0); + val_ofs = Field(val_c, 1); + val_len = Field(val_c, 2); + + buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + len = Long_val(val_len); + caml_unix_get_sockaddr(val_daddr, &addr, &addr_len); + cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); + + caml_release_runtime_system(); + n = sendto(Int_val(val_fd), buf, len, cv_flags, &addr.s_gen, addr_len); + caml_acquire_runtime_system(); + + if (n == -1) + caml_uerror("sendto", Nothing); + + CAMLreturn (Val_int(n)); +} diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index c6f0419a..76930f1a 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -73,4 +73,12 @@ let recv fd x = stub_recv fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) external stub_read: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_read" -let read fd x = stub_read fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) \ No newline at end of file +let read fd x = stub_read fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) + +external stub_recvfrom : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr = "stub_cstruct_recvfrom" + +let recvfrom fd x fl = stub_recvfrom fd x fl + +external stub_sendto : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> Unix.sockaddr -> int = "stub_cstruct_sendto" + +let sendto fd x fl a = stub_sendto fd x fl a diff --git a/unix/unix_cstruct.mli b/unix/unix_cstruct.mli index 1846c9ef..191c975b 100644 --- a/unix/unix_cstruct.mli +++ b/unix/unix_cstruct.mli @@ -39,3 +39,9 @@ val send: Unix.file_descr -> Cstruct.t -> int val recv: Unix.file_descr -> Cstruct.t -> int (** [recv fd c] receives a message from a socket. This can be used to receive a datagram. If only a partial receive is possible, the return argument is now many bytes were received. *) + +val recvfrom: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr +(** [recvfrom fd c] Like Unix.recvfrom, but for Cstruct. *) + +val sendto: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> Unix.sockaddr -> int +(** [sendto fd c a] Like Unix.sendto, but for Cstruct. *) diff --git a/unix_test/tests.ml b/unix_test/tests.ml index 28ade14c..85093cf1 100644 --- a/unix_test/tests.ml +++ b/unix_test/tests.ml @@ -130,6 +130,34 @@ let test_send_recv () = Thread.join t ) +let test_sendto_recvfrom () = + let test_message = Cstruct.concat test_message_list in + with_sock_dgram @@ fun s -> + with_sock_dgram @@ fun c -> + let sport = bind_random_port s in + let cport = bind_random_port c in (* So we can assert the sender on receiver port *) + let server () = + let buf = Cstruct.create 1024 in + let n, (addr:Unix.sockaddr) = Unix_cstruct.recvfrom s buf [] in + let addr, port = match addr with + | ADDR_INET (a, p) -> Unix.string_of_inet_addr a, p + | _ -> Alcotest.fail "Bad AF_FAMILY" + in + Alcotest.(check string) "recvfrom inetaddr" addr "127.0.0.1"; + Alcotest.(check int) "recvfrom port" port cport; + Alcotest.(check int) "recvfrom length" (Cstruct.length test_message) n; + let expected = Cstruct.to_string test_message in + let actual = Cstruct.(to_string @@ sub buf 0 n) in + Alcotest.(check string) "read contents" expected actual + in + let client () = + let addr = Unix.ADDR_INET (Unix.inet_addr_loopback, sport) in + let n = Unix_cstruct.sendto c test_message [] addr in + Alcotest.(check int) "sendto length" (Cstruct.length test_message) n; + in + client (); + server () + let suite = [ "writev", [ "test read and writev via a file", `Quick, test_writev_file; @@ -137,7 +165,10 @@ let suite = [ ]; "send recv", [ "test send and recv", `Quick, test_send_recv; + ]; + "sendto recvfrom", [ + "test sendto and recvfrom", `Quick, test_sendto_recvfrom; ] ] -let () = Alcotest.run "cstruct.unix" suite \ No newline at end of file +let () = Alcotest.run "cstruct.unix" suite From f70b3ace242b40e14dc5b9d9501455620af7cb2c Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 1 Nov 2022 15:55:56 +0000 Subject: [PATCH 05/18] windows: ifdef for socket headers Signed-off-by: David Scott --- unix/recvfrom_stubs.c | 5 +++++ unix/sendto_stubs.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index ed7ab50e..fb1ae22e 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -8,7 +8,12 @@ #include #include +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else #include +#endif static int msg_flag_table[] = { MSG_OOB, MSG_DONTROUTE, MSG_PEEK /* XXX */ diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 3cfde22f..2b9898a7 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -8,7 +8,12 @@ #include #include +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else #include +#endif static int msg_flag_table[] = { /* XXX */ MSG_OOB, MSG_DONTROUTE, MSG_PEEK From 7d77f0a966c14deb81ef87e043ca6216f3494032 Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 1 Nov 2022 16:06:25 +0000 Subject: [PATCH 06/18] use `uerror` rather than `unix_error(errno,...)` or `caml_uerror` - `caml_uerror` is defined in ocaml/ocaml#67a4d75cfafa040099cdd322e23464362359af29 and is in 5.0+ - for backwards compat ocaml 5.0 has #define uerror caml_uerror Signed-off-by: David Scott --- unix/read_stubs.c | 6 +++--- unix/recv_stubs.c | 4 ++-- unix/recvfrom_stubs.c | 2 +- unix/send_stubs.c | 4 ++-- unix/sendto_stubs.c | 2 +- unix/write_stubs.c | 4 ++-- unix/writev_stubs.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/unix/read_stubs.c b/unix/read_stubs.c index 424a1071..6eeabbc0 100644 --- a/unix/read_stubs.c +++ b/unix/read_stubs.c @@ -38,7 +38,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) if (n == SOCKET_ERROR) { win32_maperr(win32err); - unix_error(errno, "read", Nothing); + uerror("read", Nothing); } break; case KIND_HANDLE: @@ -53,7 +53,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) if (!ok) { win32_maperr(win32err); - unix_error(errno, "read", Nothing); + uerror("read", Nothing); } break; default: @@ -64,7 +64,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) n = read(Int_val(val_fd), buf, len); caml_acquire_runtime_system(); if (n < 0) - unix_error(errno, "read", Nothing); + uerror("read", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index 1b670391..f1c06e4b 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -47,7 +47,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) if (n == SOCKET_ERROR) { win32_maperr(win32err); - unix_error(errno, "recv", Nothing); + uerror("recv", Nothing); } #else int fd = Int_val(val_fd); @@ -57,7 +57,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) caml_acquire_runtime_system(); if (n < 0) - unix_error(errno, "recv", Nothing); + uerror("recv", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index fb1ae22e..abb27f66 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -44,7 +44,7 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) caml_acquire_runtime_system(); if (n == -1) - caml_uerror("recvfrom", Nothing); + uerror("recvfrom", Nothing); val_addr = caml_unix_alloc_sockaddr(&addr, addr_len, -1); val_res = caml_alloc_small(2, 0); diff --git a/unix/send_stubs.c b/unix/send_stubs.c index bb8f1df1..2aa6a514 100644 --- a/unix/send_stubs.c +++ b/unix/send_stubs.c @@ -47,7 +47,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c) if (n == SOCKET_ERROR) { win32_maperr(win32err); - unix_error(errno, "send", Nothing); + uerror("send", Nothing); } #else int fd = Int_val(val_fd); @@ -56,7 +56,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c) n = send(fd, buf, len, 0); caml_acquire_runtime_system(); if (n < 0) - unix_error(errno, "send", Nothing); + uerror("send", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 2b9898a7..1cd0fab5 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -44,7 +44,7 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v caml_acquire_runtime_system(); if (n == -1) - caml_uerror("sendto", Nothing); + uerror("sendto", Nothing); CAMLreturn (Val_int(n)); } diff --git a/unix/write_stubs.c b/unix/write_stubs.c index 655ba845..e8b3eb67 100644 --- a/unix/write_stubs.c +++ b/unix/write_stubs.c @@ -52,7 +52,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) if (!ok) { win32_maperr(win32err); - unix_error(errno, "writev", Nothing); + uerror("writev", Nothing); } break; default: @@ -63,7 +63,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) n = write(Int_val(val_fd), buf, len); caml_acquire_runtime_system(); if (n < 0) - unix_error(errno, "write", Nothing); + uerror("write", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/writev_stubs.c b/unix/writev_stubs.c index a6b5a12b..91e3323f 100644 --- a/unix/writev_stubs.c +++ b/unix/writev_stubs.c @@ -64,7 +64,7 @@ CAMLprim ssize_t n = writev(c_fd, iovec, length); caml_acquire_runtime_system(); if (n < 0) - unix_error(errno, "writev", Nothing); + uerror("writev", Nothing); CAMLreturn(Val_int(n)); #endif } From 04e45e254ed0be97598229a21d715403037277ab Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 1 Nov 2022 16:13:53 +0000 Subject: [PATCH 07/18] Use old backwards-compat alloc_sockaddr, get_sockaddr This allows compat with OCaml 4.13 Signed-off-by: David Scott --- unix/recvfrom_stubs.c | 2 +- unix/sendto_stubs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index abb27f66..cf09218f 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -46,7 +46,7 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) if (n == -1) uerror("recvfrom", Nothing); - val_addr = caml_unix_alloc_sockaddr(&addr, addr_len, -1); + val_addr = alloc_sockaddr(&addr, addr_len, -1); val_res = caml_alloc_small(2, 0); Field(val_res, 0) = Val_int(n); Field(val_res, 1) = val_addr; diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 1cd0fab5..7e65800a 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -36,7 +36,7 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); len = Long_val(val_len); - caml_unix_get_sockaddr(val_daddr, &addr, &addr_len); + get_sockaddr(val_daddr, &addr, &addr_len); cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); caml_release_runtime_system(); From 3e6d7e47e9a2039be8b67b30c19109615fb7f2a7 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 09:35:10 +0000 Subject: [PATCH 08/18] add Windows support for Unix sendto/recvfrom Windows socket handles and error codes are managed differently. Signed-off-by: David Scott --- unix/recvfrom_stubs.c | 18 ++++++++++++++++++ unix/sendto_stubs.c | 19 ++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index cf09218f..cdc6f973 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -38,13 +38,31 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); len = Long_val(val_len); addr_len = sizeof(addr); +#ifdef WIN32 + int win32err = 0; + if (Descr_kind_val(val_fd) != KIND_SOCKET) + unix_error(EINVAL, "recvfrom", Nothing); + + SOCKET s = Socket_val(val_fd); + caml_release_runtime_system(); + n = recvfrom(s, buf, len, cv_flags, &addr.s_gen, &addr_len); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + uerror("recvfrom", Nothing); + } +#else caml_release_runtime_system(); n = recvfrom(Int_val(val_fd), buf, len, cv_flags, &addr.s_gen, &addr_len); caml_acquire_runtime_system(); if (n == -1) uerror("recvfrom", Nothing); +#endif val_addr = alloc_sockaddr(&addr, addr_len, -1); val_res = caml_alloc_small(2, 0); diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 7e65800a..2a2f15b8 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -39,12 +39,29 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v get_sockaddr(val_daddr, &addr, &addr_len); cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); +#ifdef WIN32 + int win32err = 0; + if (Descr_kind_val(val_fd) != KIND_SOCKET) + unix_error(EINVAL, "sendto", Nothing); + + SOCKET s = Socket_val(val_fd); + caml_release_runtime_system(); + n = sendto(s, buf, len, cv_flags, &addr.s_gen, addr_len); + win32err = WSAGetLastError(); + caml_acquire_runtime_system(); + + if (n == SOCKET_ERROR) + { + win32_maperr(win32err); + uerror("send", Nothing); + } +#else caml_release_runtime_system(); n = sendto(Int_val(val_fd), buf, len, cv_flags, &addr.s_gen, addr_len); caml_acquire_runtime_system(); if (n == -1) uerror("sendto", Nothing); - +#endif CAMLreturn (Val_int(n)); } From 284960a47375f2378abbea53a18bc85f93e5d37d Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 09:41:56 +0000 Subject: [PATCH 09/18] Unix_cstruct.send should take a flag list Signed-off-by: David Scott --- unix/send_stubs.c | 13 +++++++++---- unix/unix_cstruct.ml | 2 +- unix/unix_cstruct.mli | 4 ++-- unix_test/tests.ml | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/unix/send_stubs.c b/unix/send_stubs.c index 2aa6a514..41c6da44 100644 --- a/unix/send_stubs.c +++ b/unix/send_stubs.c @@ -20,9 +20,13 @@ #include #endif -CAMLprim value stub_cstruct_send(value val_fd, value val_c) +static int msg_flag_table[] = { + MSG_OOB, MSG_DONTROUTE, MSG_PEEK /* XXX */ +}; + +CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) { - CAMLparam2(val_fd, val_c); + CAMLparam3(val_fd, val_c, val_flags); CAMLlocal3(val_buf, val_ofs, val_len); val_buf = Field(val_c, 0); @@ -32,6 +36,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c) const char *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); size_t len = (size_t)Long_val(val_len); int n = 0; + int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); #ifdef WIN32 int win32err = 0; @@ -40,7 +45,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c) SOCKET s = Socket_val(val_fd); caml_release_runtime_system(); - n = send(s, buf, len, 0); + n = send(s, buf, len, cv_flags); win32err = WSAGetLastError(); caml_acquire_runtime_system(); @@ -53,7 +58,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c) int fd = Int_val(val_fd); caml_release_runtime_system(); - n = send(fd, buf, len, 0); + n = send(fd, buf, len, cv_flags); caml_acquire_runtime_system(); if (n < 0) uerror("send", Nothing); diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index 76930f1a..7b675024 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -63,7 +63,7 @@ let writev fd bufs = let use_write_fallback = List.iter (write fd) in (if iov_max = 0 then use_write_fallback else use_writev) bufs -external stub_send: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_send" +external stub_send: Unix.file_descr -> (buffer * int * int) -> Unix.msg_flag list -> int = "stub_cstruct_send" external stub_recv: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_recv" diff --git a/unix/unix_cstruct.mli b/unix/unix_cstruct.mli index 191c975b..83b4c79e 100644 --- a/unix/unix_cstruct.mli +++ b/unix/unix_cstruct.mli @@ -32,8 +32,8 @@ val writev: Unix.file_descr -> Cstruct.t list -> unit (** [writev fd cs] writes the whole list of Cstructs to the file descriptor. Similar to Unix.write. *) -val send: Unix.file_descr -> Cstruct.t -> int -(** [send fd c] sends a message from a socket. This can be used to send a datagram. +val send: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int +(** [send fd c] Like Unix.send, but for Cstruct. If only a partial send is possible, the return argument is how many bytes were sent. *) val recv: Unix.file_descr -> Cstruct.t -> int diff --git a/unix_test/tests.ml b/unix_test/tests.ml index 85093cf1..957221e6 100644 --- a/unix_test/tests.ml +++ b/unix_test/tests.ml @@ -122,7 +122,7 @@ let test_send_recv () = with_sock_dgram (fun c -> Unix.connect c (Unix.ADDR_INET(localhost, port)); while with_mutex m (fun () -> not !finished) do - let n = Unix_cstruct.send c test_message in + let n = Unix_cstruct.send c test_message [] in Alcotest.(check int) "send length" (Cstruct.length test_message) n; Thread.delay 0.1 done From ec807a7d03c71beeb4584fac11003398733161cc Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 09:44:59 +0000 Subject: [PATCH 10/18] Unix_cstruct.recv should take a flag list. Signed-off-by: David Scott --- unix/recv_stubs.c | 13 +++++++++---- unix/unix_cstruct.ml | 2 +- unix/unix_cstruct.mli | 4 ++-- unix_test/tests.ml | 2 +- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index f1c06e4b..675dd450 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -20,9 +20,13 @@ #include #endif -CAMLprim value stub_cstruct_recv(value val_fd, value val_c) +static int msg_flag_table[] = { + MSG_OOB, MSG_DONTROUTE, MSG_PEEK /* XXX */ +}; + +CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) { - CAMLparam2(val_fd, val_c); + CAMLparam3(val_fd, val_c, val_flags); CAMLlocal3(val_buf, val_ofs, val_len); val_buf = Field(val_c, 0); @@ -32,6 +36,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) void *buf = (void *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); size_t len = (size_t)Long_val(val_len); int n = 0; + int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); #ifdef WIN32 int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) @@ -40,7 +45,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) SOCKET s = Socket_val(val_fd); caml_release_runtime_system(); - n = recv(s, buf, len, 0); + n = recv(s, buf, len, cv_flags); win32err = WSAGetLastError(); caml_acquire_runtime_system(); @@ -53,7 +58,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c) int fd = Int_val(val_fd); caml_release_runtime_system(); - n = recv(fd, buf, len, 0); + n = recv(fd, buf, len, cv_flags); caml_acquire_runtime_system(); if (n < 0) diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index 7b675024..a8f68a08 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -65,7 +65,7 @@ let writev fd bufs = external stub_send: Unix.file_descr -> (buffer * int * int) -> Unix.msg_flag list -> int = "stub_cstruct_send" -external stub_recv: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_recv" +external stub_recv: Unix.file_descr -> (buffer * int * int) -> Unix.msg_flag list -> int = "stub_cstruct_recv" let send fd x = stub_send fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) diff --git a/unix/unix_cstruct.mli b/unix/unix_cstruct.mli index 83b4c79e..5b4c2e33 100644 --- a/unix/unix_cstruct.mli +++ b/unix/unix_cstruct.mli @@ -36,8 +36,8 @@ val send: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int (** [send fd c] Like Unix.send, but for Cstruct. If only a partial send is possible, the return argument is how many bytes were sent. *) -val recv: Unix.file_descr -> Cstruct.t -> int -(** [recv fd c] receives a message from a socket. This can be used to receive a datagram. +val recv: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int +(** [recv fd c] Like Unix.recv, but for Cstruct. If only a partial receive is possible, the return argument is now many bytes were received. *) val recvfrom: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr diff --git a/unix_test/tests.ml b/unix_test/tests.ml index 957221e6..96d9a3d0 100644 --- a/unix_test/tests.ml +++ b/unix_test/tests.ml @@ -112,7 +112,7 @@ let test_send_recv () = let finished = ref false in let t = Thread.create (fun () -> let buf = Cstruct.create 1024 in - let n = Unix_cstruct.recv s buf in + let n = Unix_cstruct.recv s buf [] in Alcotest.(check int) "recv length" (Cstruct.length test_message) n; let expected = Cstruct.to_string test_message in let actual = Cstruct.(to_string @@ sub buf 0 n) in From fa5ffe7d73aaf6cfac511f1b6b596c60cc541fa2 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 09:49:49 +0000 Subject: [PATCH 11/18] we can assume knowledge of Cstruct.t There's no need to repack it as a tuple for the C bindings because the definition is in this repository. Signed-off-by: David Scott --- unix/unix_cstruct.ml | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index a8f68a08..30eaa55b 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -63,22 +63,12 @@ let writev fd bufs = let use_write_fallback = List.iter (write fd) in (if iov_max = 0 then use_write_fallback else use_writev) bufs -external stub_send: Unix.file_descr -> (buffer * int * int) -> Unix.msg_flag list -> int = "stub_cstruct_send" +external send: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int = "stub_cstruct_send" -external stub_recv: Unix.file_descr -> (buffer * int * int) -> Unix.msg_flag list -> int = "stub_cstruct_recv" +external recv: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int = "stub_cstruct_recv" -let send fd x = stub_send fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) +external read: Unix.file_descr -> Cstruct.t -> int = "stub_cstruct_read" -let recv fd x = stub_recv fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) +external recvfrom : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr = "stub_cstruct_recvfrom" -external stub_read: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_read" - -let read fd x = stub_read fd (x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) - -external stub_recvfrom : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr = "stub_cstruct_recvfrom" - -let recvfrom fd x fl = stub_recvfrom fd x fl - -external stub_sendto : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> Unix.sockaddr -> int = "stub_cstruct_sendto" - -let sendto fd x fl a = stub_sendto fd x fl a +external sendto : Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> Unix.sockaddr -> int = "stub_cstruct_sendto" From 2cf81f346882de150aef6e498dbc72492816ca69 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:07:50 +0000 Subject: [PATCH 12/18] Move declarations before statements, use uint8_t* for buf Signed-off-by: David Scott --- unix/read_stubs.c | 26 ++++++++++++++++---------- unix/recv_stubs.c | 22 ++++++++++++---------- unix/recvfrom_stubs.c | 7 ++++--- unix/send_stubs.c | 20 +++++++++++--------- unix/sendto_stubs.c | 6 ++++-- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/unix/read_stubs.c b/unix/read_stubs.c index 6eeabbc0..a48b3eb5 100644 --- a/unix/read_stubs.c +++ b/unix/read_stubs.c @@ -14,21 +14,28 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) { CAMLparam2(val_fd, val_c); CAMLlocal3(val_buf, val_ofs, val_len); - + uint8_t *buf; + size_t len; + int n = 0; +#ifdef WIN32 + int win32err = 0; + SOCKET s; + HANDLE h; + DWORD numread; + int ok; +#endif val_buf = Field(val_c, 0); val_ofs = Field(val_c, 1); val_len = Field(val_c, 2); - void *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); - size_t len = Long_val(val_len); - int n = 0; + buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + len = (size_t)Long_val(val_len); -#ifdef _WIN32 - int win32err = 0; +#ifdef WIN32 switch (Descr_kind_val(val_fd)) { case KIND_SOCKET: - SOCKET s = Socket_val(val_fd); + s = Socket_val(val_fd); caml_release_runtime_system(); n = recv(s, buf, len, 0); @@ -42,10 +49,9 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) } break; case KIND_HANDLE: - HANDLE h = Handle_val(val_fd); - DWORD numread; + h = Handle_val(val_fd); caml_release_runtime_system(); - int ok = ReadFile(h, buf, len, &numread, NULL); + ok = ReadFile(h, buf, len, &numread, NULL); win32err = GetLastError(); n = numread; caml_acquire_runtime_system(); diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index 675dd450..58209ba3 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -28,22 +28,26 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) { CAMLparam3(val_fd, val_c, val_flags); CAMLlocal3(val_buf, val_ofs, val_len); + uint8_t *buf; + size_t len; + int n = 0; + int cv_flags; +#ifdef WIN32 + int win32err = 0; + SOCKET s = Socket_val(val_fd); +#endif val_buf = Field(val_c, 0); val_ofs = Field(val_c, 1); val_len = Field(val_c, 2); - void *buf = (void *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); - size_t len = (size_t)Long_val(val_len); - int n = 0; - int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); + buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + len = (size_t)Long_val(val_len); + cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); #ifdef WIN32 - int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) unix_error(EINVAL, "stub_cstruct_recv", Nothing); - SOCKET s = Socket_val(val_fd); - caml_release_runtime_system(); n = recv(s, buf, len, cv_flags); win32err = WSAGetLastError(); @@ -55,10 +59,8 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) uerror("recv", Nothing); } #else - int fd = Int_val(val_fd); - caml_release_runtime_system(); - n = recv(fd, buf, len, cv_flags); + n = recv(Int_val(val_fd), buf, len, cv_flags); caml_acquire_runtime_system(); if (n < 0) diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index cdc6f973..f9ae40d7 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -29,6 +29,10 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) int cv_flags; union sock_addr_union addr; socklen_param_type addr_len; +#ifdef WIN32 + int win32err = 0; + SOCKET s = Socket_val(val_fd); +#endif val_buf = Field(val_c, 0); val_ofs = Field(val_c, 1); @@ -39,12 +43,9 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) len = Long_val(val_len); addr_len = sizeof(addr); #ifdef WIN32 - int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) unix_error(EINVAL, "recvfrom", Nothing); - SOCKET s = Socket_val(val_fd); - caml_release_runtime_system(); n = recvfrom(s, buf, len, cv_flags, &addr.s_gen, &addr_len); win32err = WSAGetLastError(); diff --git a/unix/send_stubs.c b/unix/send_stubs.c index 41c6da44..2f002e4e 100644 --- a/unix/send_stubs.c +++ b/unix/send_stubs.c @@ -28,22 +28,26 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) { CAMLparam3(val_fd, val_c, val_flags); CAMLlocal3(val_buf, val_ofs, val_len); + uint8_t *buf; + size_t len; + int n = 0; + int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); +#ifdef WIN32 + int win32err = 0; + SOCKET s = Socket_val(val_fd); +#endif val_buf = Field(val_c, 0); val_ofs = Field(val_c, 1); val_len = Field(val_c, 2); - const char *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); - size_t len = (size_t)Long_val(val_len); - int n = 0; - int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); + buf = (uint8_t *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); + len = (size_t)Long_val(val_len); #ifdef WIN32 - int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) unix_error(EINVAL, "send", Nothing); - SOCKET s = Socket_val(val_fd); caml_release_runtime_system(); n = send(s, buf, len, cv_flags); win32err = WSAGetLastError(); @@ -55,10 +59,8 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) uerror("send", Nothing); } #else - int fd = Int_val(val_fd); - caml_release_runtime_system(); - n = send(fd, buf, len, cv_flags); + n = send(Int_val(val_fd), buf, len, cv_flags); caml_acquire_runtime_system(); if (n < 0) uerror("send", Nothing); diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 2a2f15b8..79c15d16 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -29,6 +29,10 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v size_t len; ssize_t n; int cv_flags; +#ifdef WIN32 + int win32err = 0; + SOCKET s = Socket_val(val_fd); +#endif val_buf = Field(val_c, 0); val_ofs = Field(val_c, 1); @@ -40,11 +44,9 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); #ifdef WIN32 - int win32err = 0; if (Descr_kind_val(val_fd) != KIND_SOCKET) unix_error(EINVAL, "sendto", Nothing); - SOCKET s = Socket_val(val_fd); caml_release_runtime_system(); n = sendto(s, buf, len, cv_flags, &addr.s_gen, addr_len); win32err = WSAGetLastError(); From 4a044786247312c1edf09a29e0d05c9bfaf4010f Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:11:13 +0000 Subject: [PATCH 13/18] send/recv/read/write return ssize_t Signed-off-by: David Scott --- unix/read_stubs.c | 2 +- unix/recv_stubs.c | 2 +- unix/send_stubs.c | 2 +- unix/write_stubs.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/unix/read_stubs.c b/unix/read_stubs.c index a48b3eb5..a29fc04c 100644 --- a/unix/read_stubs.c +++ b/unix/read_stubs.c @@ -16,7 +16,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) CAMLlocal3(val_buf, val_ofs, val_len); uint8_t *buf; size_t len; - int n = 0; + ssize_t n = 0; #ifdef WIN32 int win32err = 0; SOCKET s; diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index 58209ba3..54905332 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -30,7 +30,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) CAMLlocal3(val_buf, val_ofs, val_len); uint8_t *buf; size_t len; - int n = 0; + ssize_t n = 0; int cv_flags; #ifdef WIN32 int win32err = 0; diff --git a/unix/send_stubs.c b/unix/send_stubs.c index 2f002e4e..e312533d 100644 --- a/unix/send_stubs.c +++ b/unix/send_stubs.c @@ -30,7 +30,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) CAMLlocal3(val_buf, val_ofs, val_len); uint8_t *buf; size_t len; - int n = 0; + ssize_t n = 0; int cv_flags = caml_convert_flag_list(val_flags, msg_flag_table); #ifdef WIN32 int win32err = 0; diff --git a/unix/write_stubs.c b/unix/write_stubs.c index e8b3eb67..cb330920 100644 --- a/unix/write_stubs.c +++ b/unix/write_stubs.c @@ -19,7 +19,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) val_len = Field(val_c, 2); void *buf = (char *)Caml_ba_data_val(val_buf) + Long_val(val_ofs); size_t len = Long_val(val_len); - int n = 0; + ssize_t n = 0; #ifdef _WIN32 int win32err = 0; From 44ec8fc24db72df35979335e35b4901c0376aea7 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:12:08 +0000 Subject: [PATCH 14/18] Remove strange linebreak inserted by VSCode Back to vi... Signed-off-by: David Scott --- unix/writev_stubs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/unix/writev_stubs.c b/unix/writev_stubs.c index 91e3323f..dca6086d 100644 --- a/unix/writev_stubs.c +++ b/unix/writev_stubs.c @@ -27,9 +27,7 @@ CAMLprim #endif } -CAMLprim - value - stub_cstruct_writev(value fd, value val_list) +CAMLprim value stub_cstruct_writev(value fd, value val_list) { CAMLparam2(fd, val_list); CAMLlocal5(next, head, val_buf, val_ofs, val_len); From 803ba0cef3e182d728e9779bff970ae083c11d90 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:14:34 +0000 Subject: [PATCH 15/18] Remove unnecessary `type buffer` This became redundant when the re-packing of a Cstruct.t as a tuple was removed. Signed-off-by: David Scott --- unix/unix_cstruct.ml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/unix/unix_cstruct.ml b/unix/unix_cstruct.ml index 30eaa55b..27429284 100644 --- a/unix/unix_cstruct.ml +++ b/unix/unix_cstruct.ml @@ -18,14 +18,12 @@ let of_fd fd = let buffer = Bigarray.(array1_of_genarray (Unix.map_file fd char c_layout false [|-1|])) in Cstruct.of_bigarray buffer -type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t - (* Returns 0 if there is no writev *) external stub_iov_max: unit -> int = "stub_cstruct_iov_max" -external stub_write: Unix.file_descr -> (buffer * int * int) -> int = "stub_cstruct_write" +external stub_write: Unix.file_descr -> Cstruct.t -> int = "stub_cstruct_write" -external stub_writev: Unix.file_descr -> (buffer * int * int) list -> int = "stub_cstruct_writev" +external stub_writev: Unix.file_descr -> Cstruct.t list -> int = "stub_cstruct_writev" let iov_max = stub_iov_max () @@ -47,7 +45,7 @@ let rec shift t x = let rec write fd buf = if Cstruct.length buf > 0 then begin - let n = stub_write fd (buf.Cstruct.buffer, buf.Cstruct.off, buf.Cstruct.len) in + let n = stub_write fd buf in write fd @@ Cstruct.shift buf n end @@ -57,7 +55,7 @@ let writev fd bufs = | remaining -> (* write at most iov_max at a time *) let to_send = first iov_max [] remaining in - let n = stub_writev fd (List.map (fun x -> x.Cstruct.buffer, x.Cstruct.off, x.Cstruct.len) to_send) in + let n = stub_writev fd to_send in let rest = shift remaining n in use_writev rest in let use_write_fallback = List.iter (write fd) in From aeca68626144bef3275ba8871228260c8f0f8462 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:21:01 +0000 Subject: [PATCH 16/18] Improve .mli by linking to the Unix functions Signed-off-by: David Scott --- unix/unix_cstruct.mli | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/unix/unix_cstruct.mli b/unix/unix_cstruct.mli index 5b4c2e33..02061099 100644 --- a/unix/unix_cstruct.mli +++ b/unix/unix_cstruct.mli @@ -22,26 +22,27 @@ val of_fd : Unix.file_descr -> Cstruct.t val read: Unix.file_descr -> Cstruct.t -> int (** [read fd cs] reads from the file descriptor into the buffer, returning the number of bytes read. - Similar to Unix.read. *) + Like {! Unix.read}, but for Cstruct. *) val write: Unix.file_descr -> Cstruct.t -> unit -(** [write fd cs] writes the whole Cstruct to the file descriptor. - Similar to Unix.write. *) +(** [write fd cs] writes the whole Cstruct to the file descriptor. Like {! Unix.write}, but for Cstruct. *) val writev: Unix.file_descr -> Cstruct.t list -> unit (** [writev fd cs] writes the whole list of Cstructs to the file descriptor. - Similar to Unix.write. *) + Like {! Unix.write}, but for a list of Cstructs. *) val send: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int -(** [send fd c] Like Unix.send, but for Cstruct. - If only a partial send is possible, the return argument is how many bytes were sent. *) +(** [send fd c flags] sends the Cstruct to the file descriptor, returning the number of bytes written. + Like {! Unix.send}, but for Cstruct. *) val recv: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int -(** [recv fd c] Like Unix.recv, but for Cstruct. - If only a partial receive is possible, the return argument is now many bytes were received. *) +(** [recv fd c flags] receives up to a Cstruct's worth of data from the file descriptor, returning the number of bytes written. + Like {! Unix.recv}, but for Cstruct. *) val recvfrom: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> int * Unix.sockaddr -(** [recvfrom fd c] Like Unix.recvfrom, but for Cstruct. *) +(** [recvfrom fd c flags] receives up to a Cstruct's worth of data from the file descriptor, returning the number of bytes + read and the address they were sent from. Like {! Unix.recvfrom}, but for Cstruct. *) val sendto: Unix.file_descr -> Cstruct.t -> Unix.msg_flag list -> Unix.sockaddr -> int -(** [sendto fd c a] Like Unix.sendto, but for Cstruct. *) +(** [sendto fd c flags addr] sends a Cstruct's worth of data to the address via the file descriptor. + Like {! Unix.sendto}, but for Cstruct. *) From 592023519a592e837b6ff5ea0e94f04320fcf5a5 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 10:25:01 +0000 Subject: [PATCH 17/18] In Unix_error, include the C stub function name stub_cstruct_foo Signed-off-by: David Scott --- unix/read_stubs.c | 6 +++--- unix/recv_stubs.c | 4 ++-- unix/recvfrom_stubs.c | 6 +++--- unix/send_stubs.c | 6 +++--- unix/sendto_stubs.c | 6 +++--- unix/write_stubs.c | 6 +++--- unix/writev_stubs.c | 2 +- 7 files changed, 18 insertions(+), 18 deletions(-) diff --git a/unix/read_stubs.c b/unix/read_stubs.c index a29fc04c..53afb45e 100644 --- a/unix/read_stubs.c +++ b/unix/read_stubs.c @@ -45,7 +45,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) if (n == SOCKET_ERROR) { win32_maperr(win32err); - uerror("read", Nothing); + uerror("stub_cstruct_read", Nothing); } break; case KIND_HANDLE: @@ -59,7 +59,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) if (!ok) { win32_maperr(win32err); - uerror("read", Nothing); + uerror("stub_cstruct_read", Nothing); } break; default: @@ -70,7 +70,7 @@ CAMLprim value stub_cstruct_read(value val_fd, value val_c) n = read(Int_val(val_fd), buf, len); caml_acquire_runtime_system(); if (n < 0) - uerror("read", Nothing); + uerror("stub_cstruct_read", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/recv_stubs.c b/unix/recv_stubs.c index 54905332..a95dbf62 100644 --- a/unix/recv_stubs.c +++ b/unix/recv_stubs.c @@ -56,7 +56,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) if (n == SOCKET_ERROR) { win32_maperr(win32err); - uerror("recv", Nothing); + uerror("stub_cstruct_recv", Nothing); } #else caml_release_runtime_system(); @@ -64,7 +64,7 @@ CAMLprim value stub_cstruct_recv(value val_fd, value val_c, value val_flags) caml_acquire_runtime_system(); if (n < 0) - uerror("recv", Nothing); + uerror("stub_cstruct_recv", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/recvfrom_stubs.c b/unix/recvfrom_stubs.c index f9ae40d7..53c0b023 100644 --- a/unix/recvfrom_stubs.c +++ b/unix/recvfrom_stubs.c @@ -44,7 +44,7 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) addr_len = sizeof(addr); #ifdef WIN32 if (Descr_kind_val(val_fd) != KIND_SOCKET) - unix_error(EINVAL, "recvfrom", Nothing); + unix_error(EINVAL, "stub_cstruct_recvfrom", Nothing); caml_release_runtime_system(); n = recvfrom(s, buf, len, cv_flags, &addr.s_gen, &addr_len); @@ -54,7 +54,7 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) if (n == SOCKET_ERROR) { win32_maperr(win32err); - uerror("recvfrom", Nothing); + uerror("stub_cstruct_recvfrom", Nothing); } #else caml_release_runtime_system(); @@ -62,7 +62,7 @@ CAMLprim value stub_cstruct_recvfrom(value val_fd, value val_c, value val_flags) caml_acquire_runtime_system(); if (n == -1) - uerror("recvfrom", Nothing); + uerror("stub_cstruct_recvfrom", Nothing); #endif val_addr = alloc_sockaddr(&addr, addr_len, -1); diff --git a/unix/send_stubs.c b/unix/send_stubs.c index e312533d..aa330407 100644 --- a/unix/send_stubs.c +++ b/unix/send_stubs.c @@ -46,7 +46,7 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) #ifdef WIN32 if (Descr_kind_val(val_fd) != KIND_SOCKET) - unix_error(EINVAL, "send", Nothing); + unix_error(EINVAL, "stub_cstruct_send", Nothing); caml_release_runtime_system(); n = send(s, buf, len, cv_flags); @@ -56,14 +56,14 @@ CAMLprim value stub_cstruct_send(value val_fd, value val_c, value val_flags) if (n == SOCKET_ERROR) { win32_maperr(win32err); - uerror("send", Nothing); + uerror("stub_cstruct_send", Nothing); } #else caml_release_runtime_system(); n = send(Int_val(val_fd), buf, len, cv_flags); caml_acquire_runtime_system(); if (n < 0) - uerror("send", Nothing); + uerror("stub_cstruct_send", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/sendto_stubs.c b/unix/sendto_stubs.c index 79c15d16..02bb4c9c 100644 --- a/unix/sendto_stubs.c +++ b/unix/sendto_stubs.c @@ -45,7 +45,7 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v #ifdef WIN32 if (Descr_kind_val(val_fd) != KIND_SOCKET) - unix_error(EINVAL, "sendto", Nothing); + unix_error(EINVAL, "stub_cstruct_sendto", Nothing); caml_release_runtime_system(); n = sendto(s, buf, len, cv_flags, &addr.s_gen, addr_len); @@ -55,7 +55,7 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v if (n == SOCKET_ERROR) { win32_maperr(win32err); - uerror("send", Nothing); + uerror("stub_cstruct_sendto", Nothing); } #else caml_release_runtime_system(); @@ -63,7 +63,7 @@ CAMLprim value stub_cstruct_sendto(value val_fd, value val_c, value val_flags, v caml_acquire_runtime_system(); if (n == -1) - uerror("sendto", Nothing); + uerror("stub_cstruct_sendto", Nothing); #endif CAMLreturn (Val_int(n)); } diff --git a/unix/write_stubs.c b/unix/write_stubs.c index cb330920..deb7f1d5 100644 --- a/unix/write_stubs.c +++ b/unix/write_stubs.c @@ -36,7 +36,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) if (n == SOCKET_ERROR) { win32_maperr(win32err); - unix_error(errno, "writev", Nothing); + unix_error(errno, "stub_cstruct_write", Nothing); } break; case KIND_HANDLE: @@ -52,7 +52,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) if (!ok) { win32_maperr(win32err); - uerror("writev", Nothing); + uerror("stub_cstruct_write", Nothing); } break; default: @@ -63,7 +63,7 @@ CAMLprim value stub_cstruct_write(value val_fd, value val_c) n = write(Int_val(val_fd), buf, len); caml_acquire_runtime_system(); if (n < 0) - uerror("write", Nothing); + uerror("stub_cstruct_write", Nothing); #endif CAMLreturn(Val_int(n)); } diff --git a/unix/writev_stubs.c b/unix/writev_stubs.c index dca6086d..fafff451 100644 --- a/unix/writev_stubs.c +++ b/unix/writev_stubs.c @@ -62,7 +62,7 @@ CAMLprim value stub_cstruct_writev(value fd, value val_list) ssize_t n = writev(c_fd, iovec, length); caml_acquire_runtime_system(); if (n < 0) - uerror("writev", Nothing); + uerror("stub_cstruct_writev", Nothing); CAMLreturn(Val_int(n)); #endif } From 471ca03b49b3a372945fcf13c89e0447a8bd3932 Mon Sep 17 00:00:00 2001 From: David Scott Date: Wed, 2 Nov 2022 11:26:56 +0000 Subject: [PATCH 18/18] $ dune build --auto-promote @fmt Signed-off-by: David Scott --- unix/dune | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 unix/dune diff --git a/unix/dune b/unix/dune old mode 100644 new mode 100755 index 55bddef8..d48f1743 --- a/unix/dune +++ b/unix/dune @@ -5,5 +5,5 @@ (foreign_stubs (language c) (names read_stubs write_stubs writev_stubs send_stubs recv_stubs - recvfrom_stubs sendto_stubs)) + recvfrom_stubs sendto_stubs)) (libraries cstruct unix))