#include #include #include #include "lnm/loop.h" #include "lnm/loop_internal.h" void lnm_loop_conn_io_req(lnm_loop *l, lnm_loop_conn *conn) { do { // Move remaining data to front of buffer memmove(conn->r.buf, &conn->r.buf[conn->r.read], conn->r.size - conn->r.read); conn->r.size -= conn->r.read; conn->r.read = 0; ssize_t res; size_t cap = LNM_LOOP_BUF_SIZE - conn->r.size; do { res = read(conn->fd, &conn->r.buf[conn->r.size], cap); } while (res < 0 && errno == EINTR); // Read can't be performed without blocking; we come back later if (res < 0 && errno == EAGAIN) { return; } if (res <= 0) { conn->state = lnm_loop_state_end; return; } conn->r.size += res; l->data_read(conn); } while (conn->state == lnm_loop_state_req); } void lnm_loop_conn_io_res(lnm_loop *l, lnm_loop_conn *conn) { do { l->data_write(conn); ssize_t res; do { res = write(conn->fd, conn->w.buf, conn->w.size); } while (res < 0 && errno == EINTR); // Write can't be performed without blocking; we come back later if (res < 0 && errno == EAGAIN) { return; } if (res < 0) { conn->state = lnm_loop_state_end; return; } // Move remaining data to front of buffer. Doing this here gives the data // writer function more space to work with memmove(conn->w.buf, &conn->w.buf[res], conn->w.size - res); conn->w.size -= res; } while (conn->state == lnm_loop_state_res); } void lnm_loop_conn_io(lnm_loop *l, lnm_loop_conn *conn) { switch (conn->state) { case lnm_loop_state_req: lnm_loop_conn_io_req(l, conn); break; case lnm_loop_state_res: lnm_loop_conn_io_res(l, conn); break; default:; } }