+ if (err == 0) {
+ return 1;
+ } else if (err == EINPROGRESS)
+ return 0;
+
+ errno = err;
+ return -1;
+}
+
+struct io_plan *io_connect_(struct io_conn *conn, const struct addrinfo *addr,
+ struct io_plan *(*next)(struct io_conn *, void *),
+ void *next_arg)
+{
+ int fd = io_conn_fd(conn);
+
+ /* We don't actually need the arg, but we need it polling. */
+ io_plan_arg(conn, IO_OUT);
+
+ /* Note that io_new_conn() will make fd O_NONBLOCK */
+
+ /* Immediate connect can happen. */
+ if (connect(fd, addr->ai_addr, addr->ai_addrlen) == 0)
+ return set_always(conn, IO_OUT, next, next_arg);
+
+ if (errno != EINPROGRESS)
+ return io_close(conn);
+
+ return io_set_plan(conn, IO_OUT, do_connect, next, next_arg);
+}
+
+static struct io_plan *io_wait_dir(struct io_conn *conn,
+ const void *wait,
+ enum io_direction dir,
+ struct io_plan *(*next)(struct io_conn *,
+ void *),
+ void *next_arg)
+{
+ struct io_plan_arg *arg = io_plan_arg(conn, dir);
+ arg->u1.const_vp = wait;
+
+ conn->plan[dir].status = IO_WAITING;
+
+ return io_set_plan(conn, dir, NULL, next, next_arg);