1 /* Licensed under LGPLv2.1+ - see LICENSE file for details */
8 #include <sys/socket.h>
11 #include <ccan/time/time.h>
12 #include <ccan/timer/timer.h>
14 static size_t num_fds = 0, max_fds = 0, num_waiting = 0;
15 static struct pollfd *pollfds = NULL;
16 static struct fd **fds = NULL;
17 static LIST_HEAD(closing);
18 static LIST_HEAD(always);
19 static struct timemono (*nowfn)(void) = time_mono;
20 static int (*pollfn)(struct pollfd *fds, nfds_t nfds, int timeout) = poll;
22 struct timemono (*io_time_override(struct timemono (*now)(void)))(void)
24 struct timemono (*old)(void) = nowfn;
29 int (*io_poll_override(int (*poll)(struct pollfd *fds, nfds_t nfds, int timeout)))(struct pollfd *, nfds_t, int)
31 int (*old)(struct pollfd *fds, nfds_t nfds, int timeout) = pollfn;
36 static bool add_fd(struct fd *fd, short events)
40 pollfds = tal_arr(NULL, struct pollfd, 8);
43 fds = tal_arr(pollfds, struct fd *, 8);
49 if (num_fds + 1 > max_fds) {
50 size_t num = max_fds * 2;
52 if (!tal_resize(&pollfds, num))
54 if (!tal_resize(&fds, num))
59 pollfds[num_fds].events = events;
60 /* In case it's idle. */
62 pollfds[num_fds].fd = -fd->fd;
64 pollfds[num_fds].fd = fd->fd;
65 pollfds[num_fds].revents = 0; /* In case we're iterating now */
67 fd->backend_info = num_fds;
75 static void del_fd(struct fd *fd)
77 size_t n = fd->backend_info;
81 if (pollfds[n].events)
83 if (n != num_fds - 1) {
84 /* Move last one over us. */
85 pollfds[n] = pollfds[num_fds-1];
86 fds[n] = fds[num_fds-1];
87 assert(fds[n]->backend_info == num_fds-1);
88 fds[n]->backend_info = n;
89 } else if (num_fds == 1) {
90 /* Free everything when no more fds. */
91 pollfds = tal_free(pollfds);
96 fd->backend_info = -1;
99 static void destroy_listener(struct io_listener *l)
105 bool add_listener(struct io_listener *l)
107 if (!add_fd(&l->fd, POLLIN))
109 tal_add_destructor(l, destroy_listener);
113 void remove_from_always(struct io_conn *conn)
115 list_del_init(&conn->always);
118 void backend_new_always(struct io_conn *conn)
120 /* In case it's already in always list. */
121 list_del(&conn->always);
122 list_add_tail(&always, &conn->always);
125 void backend_new_plan(struct io_conn *conn)
127 struct pollfd *pfd = &pollfds[conn->fd.backend_info];
133 if (conn->plan[IO_IN].status == IO_POLLING_NOTSTARTED
134 || conn->plan[IO_IN].status == IO_POLLING_STARTED)
135 pfd->events |= POLLIN;
136 if (conn->plan[IO_OUT].status == IO_POLLING_NOTSTARTED
137 || conn->plan[IO_OUT].status == IO_POLLING_STARTED)
138 pfd->events |= POLLOUT;
142 pfd->fd = conn->fd.fd;
144 pfd->fd = -conn->fd.fd;
148 void backend_wake(const void *wait)
152 for (i = 0; i < num_fds; i++) {
155 /* Ignore listeners */
156 if (fds[i]->listener)
160 if (c->plan[IO_IN].status == IO_WAITING
161 && c->plan[IO_IN].arg.u1.const_vp == wait)
162 io_do_wakeup(c, IO_IN);
164 if (c->plan[IO_OUT].status == IO_WAITING
165 && c->plan[IO_OUT].arg.u1.const_vp == wait)
166 io_do_wakeup(c, IO_OUT);
170 static void destroy_conn(struct io_conn *conn, bool close_fd)
172 int saved_errno = errno;
177 /* In case it's on always list, remove it. */
178 list_del_init(&conn->always);
180 /* errno saved/restored by tal_free itself. */
183 conn->finish(conn, conn->finish_arg);
187 static void destroy_conn_close_fd(struct io_conn *conn)
189 destroy_conn(conn, true);
192 bool add_conn(struct io_conn *c)
194 if (!add_fd(&c->fd, 0))
196 tal_add_destructor(c, destroy_conn_close_fd);
200 void cleanup_conn_without_close(struct io_conn *conn)
202 tal_del_destructor(conn, destroy_conn_close_fd);
203 destroy_conn(conn, false);
206 static void accept_conn(struct io_listener *l)
208 int fd = accept(l->fd.fd, NULL, NULL);
210 /* FIXME: What to do here? */
214 io_new_conn(l->ctx, fd, l->init, l->arg);
217 static bool handle_always(void)
220 struct io_conn *conn;
222 while ((conn = list_pop(&always, struct io_conn, always)) != NULL) {
223 assert(conn->plan[IO_IN].status == IO_ALWAYS
224 || conn->plan[IO_OUT].status == IO_ALWAYS);
226 /* Re-initialize, for next time. */
227 list_node_init(&conn->always);
234 /* This is the main loop. */
235 void *io_loop(struct timers *timers, struct timer **expired)
239 /* if timers is NULL, expired must be. If not, not. */
240 assert(!timers == !expired);
242 /* Make sure this is NULL if we exit for some other reason. */
246 while (!io_loop_return) {
247 int i, r, ms_timeout = -1;
249 if (handle_always()) {
250 /* Could have started/finished more. */
254 /* Everything closed? */
258 /* You can't tell them all to go to sleep! */
262 struct timemono now, first;
266 /* Call functions for expired timers. */
267 *expired = timers_expire(timers, now);
271 /* Now figure out how long to wait for the next one. */
272 if (timer_earliest(timers, &first)) {
274 next = time_to_msec(timemono_between(first, now));
278 ms_timeout = INT_MAX;
282 r = pollfn(pollfds, num_fds, ms_timeout);
284 /* Signals shouldn't break us, unless they set
291 for (i = 0; i < num_fds && !io_loop_return; i++) {
292 struct io_conn *c = (void *)fds[i];
293 int events = pollfds[i].revents;
298 if (fds[i]->listener) {
299 struct io_listener *l = (void *)fds[i];
300 if (events & POLLIN) {
303 } else if (events & (POLLHUP|POLLNVAL|POLLERR)) {
306 io_close_listener(l);
308 } else if (events & (POLLIN|POLLOUT)) {
311 } else if (events & (POLLHUP|POLLNVAL|POLLERR)) {
319 ret = io_loop_return;
320 io_loop_return = NULL;