- assert(conn->state == IDLE);
- conn->fd.next = next;
- conn->fd.next_arg = arg;
- backend_set_state(conn, to_ioop(NEXT));
-}
-
-static struct io_op *do_next(struct io_conn *conn)
-{
- return conn->fd.next(conn, conn->fd.next_arg);
-}
-
-struct io_op *do_ready(struct io_conn *conn)
-{
- ssize_t ret;
- bool finished;
-
- switch (conn->state) {
- case WRITE:
- ret = write(conn->fd.fd, conn->u.write.buf, conn->u.write.len);
- if (ret < 0)
- return io_close(conn, NULL);
- conn->u.write.buf += ret;
- conn->u.write.len -= ret;
- finished = (conn->u.write.len == 0);
- break;
- case WRITEPART:
- ret = write(conn->fd.fd, conn->u.writepart.buf,
- *conn->u.writepart.lenp);
- if (ret < 0)
- return io_close(conn, NULL);
- *conn->u.writepart.lenp = ret;
- finished = true;
- break;
- case READ:
- ret = read(conn->fd.fd, conn->u.read.buf, conn->u.read.len);
- if (ret <= 0)
- return io_close(conn, NULL);
- conn->u.read.buf += ret;
- conn->u.read.len -= ret;
- finished = (conn->u.read.len == 0);
- break;
- case READPART:
- ret = read(conn->fd.fd, conn->u.readpart.buf,
- *conn->u.readpart.lenp);
- if (ret <= 0)
- return io_close(conn, NULL);
- *conn->u.readpart.lenp = ret;
- finished = true;
- break;
+ assert(!conn->plan.io);
+ conn->plan = plan;
+ backend_wakeup(conn);
+}
+
+static struct io_plan do_next(struct io_conn *conn)
+{
+ if (timeout_active(conn))
+ backend_del_timeout(conn);
+ return conn->plan.next(conn, conn->plan.next_arg);
+}
+
+struct io_plan do_ready(struct io_conn *conn)
+{
+ assert(conn->plan.state == IO_IO);
+ switch (conn->plan.io(conn)) {
+ case RESULT_CLOSE:
+ return io_close(conn, NULL);
+ case RESULT_FINISHED:
+ return do_next(conn);
+ case RESULT_AGAIN:
+ return conn->plan;