src/sock_tcp.c
changeset 12 4147fae232d9
parent 11 14e79683c48c
child 21 0911d0b828d4
--- a/src/sock_tcp.c	Sat Feb 28 17:39:37 2009 +0200
+++ b/src/sock_tcp.c	Sat Feb 28 18:48:10 2009 +0200
@@ -18,11 +18,7 @@
     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);
+    sock_stream_invoke_callbacks(SOCK_TCP_BASE(sock), what);
 }
 
 /*
@@ -33,14 +29,26 @@
     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)
-        // errno
+    // read(), and detect non-EAGAIN or EOF
+    if ((ret = read(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
+        // unexpected error
         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_READ);
+    
+    else if (ret == 0)
+        // EOF
+        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_READ_EOF);
 
-    // bytes read
-    *len = ret;
 
+    if (ret < 0) {
+        // EAGAIN -> zero bytes
+        *len = 0;
+
+    } else {
+        // normal -> bytes read
+        *len = ret;
+    }
+
+    // ok
     return SUCCESS;
 }
 
@@ -52,13 +60,24 @@
     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)
-        // errno
+    // write(), and detect non-EAGAIN or EOF
+    if ((ret = write(sock->fd, buf, *len)) < 0 && errno != EAGAIN)
+        // unexpected error
         RETURN_SET_ERROR_ERRNO(SOCK_TCP_ERR(sock), ERR_WRITE);
+    
+    else if (ret == 0)
+        // EOF
+        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_WRITE_EOF);
 
-    // bytes read
-    *len = ret;
+
+    if (ret < 0) {
+        // EAGAIN -> zero bytes
+        *len = 0;
+
+    } else {
+        // normal -> bytes read
+        *len = ret;
+    }
 
     return SUCCESS;
 }
@@ -83,16 +102,9 @@
 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);
-
-    // just add the appropraite events
-    if (mask & EV_READ && event_add(sock->ev_read, NULL))
-        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
- 
-    if (mask & EV_WRITE && event_add(sock->ev_write, NULL))
-        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
     
-    // done
-    return SUCCESS;
+    // implemented in sock_tcp_add_event
+    return sock_tcp_add_event(sock, mask);
 }
 
 /*
@@ -149,6 +161,19 @@
     return SUCCESS;
 }
 
+err_t sock_tcp_add_event (struct sock_tcp *sock, short mask)
+{
+    // just add the appropraite events
+    if (mask & EV_READ && event_add(sock->ev_read, NULL))
+        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
+ 
+    if (mask & EV_WRITE && event_add(sock->ev_write, NULL))
+        return SET_ERROR(SOCK_TCP_ERR(sock), ERR_EVENT_ADD);
+    
+    // done
+    return SUCCESS;
+}
+
 err_t sock_tcp_init_connect (struct sock_tcp *sock, const char *hostname, const char *service)
 {
     struct addrinfo hints, *res, *r;