--- a/src/sock_test.c Thu Mar 12 20:00:48 2009 +0200
+++ b/src/sock_test.c Thu Mar 12 21:12:48 2009 +0200
@@ -4,23 +4,63 @@
#include <string.h>
#include <assert.h>
+/**
+ * Grow buf->vecs as needed, to ensure that buf->write_vec is valid
+ */
+static err_t sock_test_grow_buf (struct io_buf *buf)
+{
+ size_t read_vec_offset = buf->read_vec ? (buf->read_vec - buf->vecs) : 0;
+ size_t write_vec_offset = buf->write_vec ? (buf->write_vec - buf->vecs) : 0;
+ struct io_vec *v;
+ struct io_vec *vecs_tmp = buf->vecs;
+
+ // don't grow if not full
+ if (buf->vecs && buf->write_vec < buf->vecs + buf->count)
+ return SUCCESS;
+
+ // new size
+ buf->count = buf->count * 2 + 1;
+
+ // grow
+ if ((buf->vecs = realloc(buf->vecs, buf->count * sizeof(struct io_vec))) == NULL) {
+ // restore old value
+ buf->vecs = vecs_tmp;
+
+ return ERR_CALLOC;
+ }
+
+ // set vec
+ buf->write_vec = buf->vecs + write_vec_offset;
+ buf->read_vec = buf->vecs + read_vec_offset;
+
+ // zero new vecs
+ for (v = buf->write_vec; v < buf->vecs + buf->count; v++) {
+ v->buf = NULL;
+ v->len = 0;
+ }
+
+ // ok
+ return SUCCESS;
+}
+
static err_t sock_test_read (struct sock_stream *base_sock, void *buf_ptr, size_t *len)
{
struct sock_test *sock = SOCK_FROM_BASE(base_sock, struct sock_test);
struct io_buf *buf = &sock->recv_buf;
- struct io_vec *vec = buf->vec;
-
- // no current vector -> EOF
- if (!vec)
- return ERR_READ_EOF;
+ struct io_vec *vec = buf->read_vec;
+
+ // EOF/nonblock if we're past the end of the last vector
+ if (!vec || vec == buf->vecs + buf->count || buf->off >= vec->len) {
+ if (sock->nonblocking && !sock->eof) {
+ // wait for more to be fed in
+ *len = 0;
+ return SUCCESS;
- // vector past the end -> EOF
- if (vec == &buf->vecs[buf->count])
- return ERR_READ_EOF;
-
- // no data left in current vector -> EOF
- if (buf->off >= vec->len)
- return ERR_READ_EOF;
+ } else {
+ // EOF!
+ return SET_ERROR(SOCK_TEST_ERR(sock), ERR_READ_EOF);
+ }
+ }
// amount of data available in this iovec
size_t available = vec->len - buf->off;
@@ -42,7 +82,7 @@
} else {
// next vector
- buf->vec++;
+ buf->read_vec++;
}
// update len
@@ -56,28 +96,12 @@
{
struct sock_test *sock = SOCK_FROM_BASE(base_sock, struct sock_test);
struct io_buf *buf = &sock->send_buf;
- struct io_vec *vec = buf->vec;
- // vectors full?
- if (buf->vecs == NULL || vec == &buf->vecs[buf->count]) {
- size_t vec_offset = vec ? (vec - buf->vecs) : 0;
- struct io_vec *v;
-
- // new size
- buf->count = buf->count * 2 + 1;
-
- // grow
- assert((buf->vecs = realloc(buf->vecs, buf->count * sizeof(struct io_vec))));
-
- // set vec
- vec = buf->vec = buf->vecs + vec_offset;
-
- // zero
- for (v = vec; v < &buf->vecs[buf->count]; v++) {
- v->buf = NULL;
- v->len = 0;
- }
- }
+ // ensure there's room
+ assert(sock_test_grow_buf(buf) == SUCCESS);
+
+ // the next buffer
+ struct io_vec *vec = buf->write_vec;
// store
vec->len = *len;
@@ -85,7 +109,7 @@
memcpy(vec->buf, buf_ptr, vec->len);
// move vec onwards
- buf->vec++;
+ buf->write_vec++;
// ok
return SUCCESS;
@@ -93,19 +117,26 @@
static err_t sock_test_event_init (struct sock_stream *base_sock)
{
-
+ struct sock_test *sock = SOCK_FROM_BASE(base_sock, struct sock_test);
+
+ // set the nonblocking flag
+ sock->nonblocking = true;
+
return SUCCESS;
}
static err_t sock_test_event_enable (struct sock_stream *base_sock, short mask)
{
-
+ struct sock_test *sock = SOCK_FROM_BASE(base_sock, struct sock_test);
+
return SUCCESS;
}
static void sock_test_release (struct sock_stream *base_sock)
{
+ struct sock_test *sock = SOCK_FROM_BASE(base_sock, struct sock_test);
+ sock_test_destroy(sock);
}
/*
@@ -135,12 +166,52 @@
return sock;
}
-void sock_test_set_recv_buffer (struct sock_test *sock, struct io_vec *vecs, size_t count)
+void sock_test_destroy (struct sock_test *sock)
{
- sock->recv_buf.vecs = vecs;
- sock->recv_buf.count = count;
- sock->recv_buf.vec = vecs;
- sock->recv_buf.off = 0;
+ size_t i;
+ struct io_buf *sbuf = &sock->send_buf, *rbuf = &sock->recv_buf;
+
+ // free the send buffer
+ for (i = 0; i < sbuf->count; i++) {
+ free(sbuf->vecs[i].buf);
+ }
+
+ // free the buffer vector lists
+ free(sbuf->vecs);
+ free(rbuf->vecs);
+
+ // free the sock itself
+ free(sock);
+}
+
+void sock_test_set_recv_buffer (struct sock_test *sock, struct io_vec *vecs, size_t count, bool eof)
+{
+ struct io_buf *buf = &sock->recv_buf;
+
+ // allocate + copy
+ assert((buf->vecs = calloc(count, sizeof(struct io_vec))));
+ memcpy(buf->vecs, vecs, count * sizeof(struct io_vec));
+
+ // set
+ buf->count = count;
+ buf->read_vec = buf->vecs;
+ buf->write_vec = buf->vecs + count;
+ buf->off = 0;
+
+ // set EOF flag?
+ if (eof)
+ sock->eof = true;
+}
+
+void sock_test_add_recv_vec (struct sock_test *sock, struct io_vec new_vec)
+{
+ struct io_buf *buf = &sock->recv_buf;
+
+ // ensure there's room
+ assert(sock_test_grow_buf(buf) == SUCCESS);
+
+ // copy
+ *(buf->write_vec++) = new_vec;
}
void sock_test_get_send_data (struct sock_test *sock, char **buf_ptr, size_t *len_ptr)