63c46223691311f7db2eade98c961face21d4b34
[ccan] / ccan / io / fdpass / fdpass.c
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
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
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
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
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 }