src/sock_test.c
changeset 41 40f7aa051acb
parent 40 51678c7eae03
child 42 13cfc41f76a7
--- 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)