src/sock_test.c
changeset 40 51678c7eae03
child 41 40f7aa051acb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sock_test.c	Thu Mar 12 20:00:48 2009 +0200
@@ -0,0 +1,170 @@
+#include "sock_test.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+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;
+
+    // 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;
+    
+    // amount of data available in this iovec
+    size_t available = vec->len - buf->off;
+
+    // amount to read
+    size_t to_read = *len;
+    
+    // trim down?
+    if (to_read > available)
+        to_read = available;
+
+    // copy
+    memcpy(buf_ptr, vec->buf + buf->off, to_read);
+    
+    // consumed the whole vec?
+    if (to_read < available) {
+        // move offset
+        buf->off += to_read;
+
+    } else {
+        // next vector
+        buf->vec++;
+    }
+
+    // update len
+    *len = to_read;
+
+    // ok
+    return SUCCESS;
+}
+
+static err_t sock_test_write (struct sock_stream *base_sock, const void *buf_ptr, size_t *len)
+{
+    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;
+        }
+    }
+
+    // store
+    vec->len = *len;
+    assert((vec->buf = malloc(vec->len)));
+    memcpy(vec->buf, buf_ptr, vec->len);
+
+    // move vec onwards
+    buf->vec++;
+
+    // ok
+    return SUCCESS;
+}
+
+static err_t sock_test_event_init (struct sock_stream *base_sock)
+{
+    
+    return SUCCESS;
+}
+
+static err_t sock_test_event_enable (struct sock_stream *base_sock, short mask)
+{
+    
+    return SUCCESS;
+}
+
+static void sock_test_release (struct sock_stream *base_sock)
+{
+
+}
+
+/*
+ * Our sock_stream_type
+ */
+static struct sock_stream_type sock_test_type = {
+    .methods                = {
+        .read               = &sock_test_read,
+        .write              = &sock_test_write,
+        .event_init         = &sock_test_event_init,
+        .event_enable       = &sock_test_event_enable,
+        .release            = &sock_test_release,
+    },
+};
+
+struct sock_test* sock_test_create (void)
+{
+    struct sock_test *sock;
+
+    // allocate
+    assert((sock = calloc(1, sizeof(*sock))));
+    
+    // initialize base with our sock_stream_type
+    sock_stream_init(SOCK_TEST_BASE(sock), &sock_test_type);
+
+    // ok
+    return sock;
+}
+
+void sock_test_set_recv_buffer (struct sock_test *sock, struct io_vec *vecs, size_t count)
+{
+    sock->recv_buf.vecs = vecs;
+    sock->recv_buf.count = count;
+    sock->recv_buf.vec = vecs;
+    sock->recv_buf.off = 0;
+}
+
+void sock_test_get_send_data (struct sock_test *sock, char **buf_ptr, size_t *len_ptr)
+{
+    struct io_buf *buf = &sock->send_buf;
+    size_t len = 0, i, off = 0;
+    char *out;
+    
+    // calculate total size
+    for (i = 0; i < buf->count; i++) {
+        len += buf->vecs[i].len;
+    }
+
+    // alloc
+    assert((out = malloc(len)));
+
+    // copy
+    for (i = 0; i < buf->count; i++) {
+        memcpy(out + off, buf->vecs[i].buf, buf->vecs[i].len);
+        off += buf->vecs[i].len;
+    }
+    
+    // update return
+    *buf_ptr = out;
+    *len_ptr = len;
+}
+