src/sock_tcp.c
changeset 10 9fe218576d13
parent 8 be88e543c8ff
child 11 14e79683c48c
--- a/src/sock_tcp.c	Sun Feb 22 08:48:21 2009 +0200
+++ b/src/sock_tcp.c	Sun Feb 22 10:16:28 2009 +0200
@@ -6,53 +6,87 @@
 #include <sys/socket.h>
 #include <netdb.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include <string.h>
 #include <assert.h>
 
 /*
  * Our sock_stream_methods.read method
  */
-static err_t sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t len)
+static err_t sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t *len)
 {
     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
     int ret;
     
     // map directly to read(2)
-    if ((ret = read(sock->fd, buf, len)) < 0)
+    if ((ret = read(sock->fd, buf, *len)) < 0)
         // errno
         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_READ);
 
-    else 
-        // bytes read
-        return ret;
+    // bytes read
+    *len = ret;
+
+    return SUCCESS;
 }
 
 /*
  * Our sock_stream_methods.write method
  */
-static err_t sock_tcp_write (struct sock_stream *base_sock, const void *buf, size_t len)
+static err_t sock_tcp_write (struct sock_stream *base_sock, const void *buf, size_t *len)
 {
     struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
     int ret;
     
     // map directly to write(2)
-    if ((ret = write(sock->fd, buf, len)) < 0)
+    if ((ret = write(sock->fd, buf, *len)) < 0)
         // errno
         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_WRITE);
 
-    else
-        // bytes read
-        return ret;
+    // bytes read
+    *len = ret;
+
+    return SUCCESS;
+}
+
+static err_t sock_tcp_event_init (struct sock_stream *base_sock)
+{
+    struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
+    
+    return SUCCESS;
+}
+
+static err_t sock_tcp_event_enable (struct sock_stream *base_sock, short mask)
+{
+    struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
+    
+    return SUCCESS;
 }
 
 /*
  * Our sock_stream_type
  */
 struct sock_stream_type sock_tcp_type = {
-    .methods.read   = &sock_tcp_read,
-    .methods.write  = &sock_tcp_write,
+    .methods.read           = &sock_tcp_read,
+    .methods.write          = &sock_tcp_write,
+    .methods.event_init     = &sock_tcp_event_init,
+    .methods.event_enable   = &sock_tcp_event_enable,
 };
 
+/*
+ * Our basic socket event handler for driving our callbacks
+ */
+static void sock_tcp_event (evutil_socket_t fd, short what, void *arg) 
+{
+    struct sock_tcp *sock = arg;
+
+    // invoke appropriate callback
+    if (what & EV_READ && SOCK_TCP_BASE(sock)->cb_info->on_read)
+        SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg);
+
+    if (what & EV_WRITE && SOCK_TCP_BASE(sock)->cb_info->on_write)
+        SOCK_TCP_BASE(sock)->cb_info->on_read(SOCK_TCP_BASE(sock), SOCK_TCP_BASE(sock)->cb_arg);
+}
+
 err_t sock_tcp_alloc (struct sock_tcp **sock_ptr)
 {
     // alloc
@@ -78,6 +112,19 @@
     return SUCCESS;
 }
 
+err_t sock_tcp_init_ev (struct sock_tcp *sock, void (*ev_cb)(evutil_socket_t, short, void *), void *cb_arg)
+{
+    // require valid fd
+    assert(sock->fd >= 0);
+    
+    // create new event
+    if ((sock->ev = event_new(_sock_stream_ctx.ev_base, sock->fd, EV_READ, ev_cb, cb_arg)) == NULL)
+        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_NEW);
+
+    // ok
+    return SUCCESS;
+}
+
 err_t sock_tcp_init_connect (struct sock_tcp *sock, const char *hostname, const char *service)
 {
     struct addrinfo hints, *res, *r;
@@ -137,6 +184,26 @@
     return 0;    
 }
 
+err_t sock_tcp_set_nonblock (struct sock_tcp *sock, int nonblock)
+{
+    // fcntl it
+    // XXX: maintain old flags?
+    if (fcntl(sock->fd, F_SETFL, nonblock ? O_NONBLOCK : 0) < 0)
+        RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_FCNTL);
+
+    // ok
+    return SUCCESS;
+}
+
+void sock_tcp_release (struct sock_tcp *sock)
+{
+    // must not be connected
+    assert(sock->fd < 0);
+
+    // free
+    free(sock);
+}
+
 err_t sock_tcp_connect (struct sock_stream **sock_ptr, const char *host, const char *service, struct error_info *err_info)
 {
     struct sock_tcp *sock;
@@ -164,11 +231,4 @@
     return 0;
 }
 
-void sock_tcp_release (struct sock_tcp *sock)
-{
-    // must not be connected
-    assert(sock->fd < 0);
 
-    // free
-    free(sock);
-}