78 lines
1.8 KiB
C
78 lines
1.8 KiB
C
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#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:;
|
|
}
|
|
}
|