@@ -212,23 +212,51 @@ CAMLprim value caml_eio_posix_spawn(value v_errors, value v_actions) {
212212 CAMLreturn (Val_long (child_pid ));
213213}
214214
215- CAMLprim value caml_eio_posix_send_msg (value v_fd , value v_dst_opt , value v_bufs ) {
216- CAMLparam2 (v_dst_opt , v_bufs );
215+ /* Copy [n_fds] from [v_fds] to [msg]. */
216+ static void fill_fds (struct msghdr * msg , int n_fds , value v_fds ) {
217+ if (n_fds > 0 ) {
218+ int i ;
219+ struct cmsghdr * cm ;
220+ cm = CMSG_FIRSTHDR (msg );
221+ cm -> cmsg_level = SOL_SOCKET ;
222+ cm -> cmsg_type = SCM_RIGHTS ;
223+ cm -> cmsg_len = CMSG_LEN (n_fds * sizeof (int ));
224+ for (i = 0 ; i < n_fds ; i ++ ) {
225+ int fd = -1 ;
226+ if (Is_block (v_fds )) {
227+ fd = Int_val (Field (v_fds , 0 ));
228+ v_fds = Field (v_fds , 1 );
229+ }
230+ ((int * )CMSG_DATA (cm ))[i ] = fd ;
231+ }
232+ }
233+ }
234+
235+ CAMLprim value caml_eio_posix_send_msg (value v_fd , value v_n_fds , value v_fds , value v_dst_opt , value v_bufs ) {
236+ CAMLparam3 (v_fds , v_dst_opt , v_bufs );
217237 int n_bufs = Wosize_val (v_bufs );
238+ int n_fds = Int_val (v_n_fds );
218239 struct iovec iov [n_bufs ];
219240 union sock_addr_union dst_addr ;
241+ int controllen = n_fds > 0 ? CMSG_SPACE (sizeof (int ) * n_fds ) : 0 ;
242+ char cmsg [controllen ];
220243 struct msghdr msg = {
221244 .msg_iov = iov ,
222245 .msg_iovlen = n_bufs ,
246+ .msg_control = n_fds > 0 ? cmsg : NULL ,
247+ .msg_controllen = controllen ,
223248 };
224249 ssize_t r ;
225250
251+ memset (cmsg , 0 , controllen );
252+
226253 if (Is_some (v_dst_opt )) {
227254 caml_unix_get_sockaddr (Some_val (v_dst_opt ), & dst_addr , & msg .msg_namelen );
228255 msg .msg_name = & dst_addr ;
229256 }
230257
231258 fill_iov (iov , v_bufs );
259+ fill_fds (& msg , n_fds , v_fds );
232260
233261 caml_enter_blocking_section ();
234262 r = sendmsg (Int_val (v_fd ), & msg , 0 );
@@ -238,20 +266,49 @@ CAMLprim value caml_eio_posix_send_msg(value v_fd, value v_dst_opt, value v_bufs
238266 CAMLreturn (Val_long (r ));
239267}
240268
241- CAMLprim value caml_eio_posix_recv_msg (value v_fd , value v_bufs ) {
269+ static value get_msghdr_fds (struct msghdr * msg ) {
270+ CAMLparam0 ();
271+ CAMLlocal2 (v_list , v_cons );
272+ struct cmsghdr * cm ;
273+ v_list = Val_int (0 );
274+ for (cm = CMSG_FIRSTHDR (msg ); cm ; cm = CMSG_NXTHDR (msg , cm )) {
275+ if (cm -> cmsg_level == SOL_SOCKET && cm -> cmsg_type == SCM_RIGHTS ) {
276+ int * fds = (int * ) CMSG_DATA (cm );
277+ int n_fds = (cm -> cmsg_len - CMSG_LEN (0 )) / sizeof (int );
278+ int i ;
279+ for (i = n_fds - 1 ; i >= 0 ; i -- ) {
280+ value fd = Val_int (fds [i ]);
281+ v_cons = caml_alloc_tuple (2 );
282+ Store_field (v_cons , 0 , fd );
283+ Store_field (v_cons , 1 , v_list );
284+ v_list = v_cons ;
285+ }
286+ }
287+ }
288+ CAMLreturn (v_list );
289+ }
290+
291+ CAMLprim value caml_eio_posix_recv_msg (value v_fd , value v_max_fds , value v_bufs ) {
242292 CAMLparam1 (v_bufs );
243293 CAMLlocal2 (v_result , v_addr );
294+ int max_fds = Int_val (v_max_fds );
244295 int n_bufs = Wosize_val (v_bufs );
245296 struct iovec iov [n_bufs ];
246297 union sock_addr_union source_addr ;
298+ int controllen = max_fds > 0 ? CMSG_SPACE (sizeof (int ) * max_fds ) : 0 ;
299+ char cmsg [controllen ];
247300 struct msghdr msg = {
248301 .msg_name = & source_addr ,
249302 .msg_namelen = sizeof (source_addr ),
250303 .msg_iov = iov ,
251304 .msg_iovlen = n_bufs ,
305+ .msg_control = max_fds > 0 ? cmsg : NULL ,
306+ .msg_controllen = controllen ,
252307 };
253308 ssize_t r ;
254309
310+ memset (cmsg , 0 , controllen );
311+
255312 fill_iov (iov , v_bufs );
256313
257314 caml_enter_blocking_section ();
@@ -261,9 +318,10 @@ CAMLprim value caml_eio_posix_recv_msg(value v_fd, value v_bufs) {
261318
262319 v_addr = caml_unix_alloc_sockaddr (& source_addr , msg .msg_namelen , -1 );
263320
264- v_result = caml_alloc_tuple (2 );
321+ v_result = caml_alloc_tuple (3 );
265322 Store_field (v_result , 0 , v_addr );
266323 Store_field (v_result , 1 , Val_long (r ));
324+ Store_field (v_result , 2 , get_msghdr_fds (& msg ));
267325
268326 CAMLreturn (v_result );
269327}
0 commit comments