1 /* GNU LGPL version 2 (or later) - see LICENSE file for details */
2 #include <ccan/io/fdpass/fdpass.h>
3 #include <ccan/fdpass/fdpass.h>
4 #include <ccan/io/io_plan.h>
5 #include <errno.h>
6 
do_fd_send(int fd,struct io_plan_arg * arg)7 static int do_fd_send(int fd, struct io_plan_arg *arg)
8 {
9 	if (!fdpass_send(fd, arg->u1.s)) {
10 		/* In case ccan/io ever gets smart with non-blocking. */
11 		if (errno == EAGAIN || errno == EWOULDBLOCK)
12 			return 0;
13 		return -1;
14 	}
15 	if (arg->u2.s)
16 		close(arg->u1.s);
17 	return 1;
18 }
19 
io_send_fd_(struct io_conn * conn,int fd,bool fdclose,struct io_plan * (* next)(struct io_conn *,void *),void * next_arg)20 struct io_plan *io_send_fd_(struct io_conn *conn,
21 			    int fd,
22 			    bool fdclose,
23 			    struct io_plan *(*next)(struct io_conn *, void *),
24 			    void *next_arg)
25 {
26 	struct io_plan_arg *arg = io_plan_arg(conn, IO_OUT);
27 
28 	arg->u1.s = fd;
29 	arg->u2.s = fdclose;
30 
31 	return io_set_plan(conn, IO_OUT, do_fd_send, next, next_arg);
32 }
33 
do_fd_recv(int fd,struct io_plan_arg * arg)34 static int do_fd_recv(int fd, struct io_plan_arg *arg)
35 {
36 	int fdin = fdpass_recv(fd);
37 
38 	if (fdin < 0) {
39 		/* In case ccan/io ever gets smart with non-blocking. */
40 		if (errno == EAGAIN || errno == EWOULDBLOCK)
41 			return 0;
42 		return -1;
43 	}
44 	*(int *)arg->u1.vp = fdin;
45 	return 1;
46 }
47 
io_recv_fd_(struct io_conn * conn,int * fd,struct io_plan * (* next)(struct io_conn *,void *),void * next_arg)48 struct io_plan *io_recv_fd_(struct io_conn *conn,
49 			    int *fd,
50 			    struct io_plan *(*next)(struct io_conn *, void *),
51 			    void *next_arg)
52 {
53 	struct io_plan_arg *arg = io_plan_arg(conn, IO_IN);
54 
55 	arg->u1.vp = fd;
56 
57 	return io_set_plan(conn, IO_IN, do_fd_recv, next, next_arg);
58 }
59