You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by jo...@apache.org on 2009/10/12 23:16:58 UTC

svn commit: r824500 - in /apr/apr/trunk: include/apr_network_io.h network_io/unix/socket_util.c test/testsock.c

Author: jorton
Date: Mon Oct 12 21:16:56 2009
New Revision: 824500

URL: http://svn.apache.org/viewvc?rev=824500&view=rev
Log:
* include/apr_network_io.h,
* network_io/unix/socket_util.c (apr_socket_atreadeof): Renamed from
  apr_socket_is_connected; adjusted to return an apr_status_t error
  code, and pass an "at EOF" flag via an output parameter.

* test/testsock.c (test_atreadeof): Renamed from test_is_connected,
  adjusted for new API.

Submitted by: jorton, rpluem

Modified:
    apr/apr/trunk/include/apr_network_io.h
    apr/apr/trunk/network_io/unix/socket_util.c
    apr/apr/trunk/test/testsock.c

Modified: apr/apr/trunk/include/apr_network_io.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/apr_network_io.h?rev=824500&r1=824499&r2=824500&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_network_io.h (original)
+++ apr/apr/trunk/include/apr_network_io.h Mon Oct 12 21:16:56 2009
@@ -375,17 +375,19 @@
                                              apr_sockaddr_t *sa);
 
 /**
- * Check whether the send part of the socket is still open on the
- * peer or that there is still data in the socket's read buffer.
- * If this is false the next read on the socket will return APR_EOF.
+ * Determine whether the receive part of the socket has been closed by
+ * the peer (such that a subsequent call to apr_socket_read would
+ * return APR_EOF), if the socket's receive buffer is empty.  This
+ * function does not block waiting for I/O.
+ *
  * @param socket The socket to check
- * @remark
- * <PRE>
- * This function does not block on the socket but returns immediately in
- * any case.
- * </PRE>
+ * @param atreadeof If APR_SUCCESS is returned, *atreadeof is set to
+ *                  non-zero if a subsequent read would return APR_EOF
+ * @return an error is returned if it was not possible to determine the
+ *         status, in which case *atreadeof is not changed.
  */
-APR_DECLARE(int) apr_socket_is_connected(apr_socket_t *socket);
+APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock,
+                                               int *atreadeof);
 
 /**
  * Create apr_sockaddr_t from hostname, address family, and port.

Modified: apr/apr/trunk/network_io/unix/socket_util.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/network_io/unix/socket_util.c?rev=824500&r1=824499&r2=824500&view=diff
==============================================================================
--- apr/apr/trunk/network_io/unix/socket_util.c (original)
+++ apr/apr/trunk/network_io/unix/socket_util.c Mon Oct 12 21:16:56 2009
@@ -17,41 +17,58 @@
 #include "apr_network_io.h"
 #include "apr_poll.h"
 
-int apr_socket_is_connected(apr_socket_t *socket)
+apr_status_t apr_socket_atreadeof(apr_socket_t *sock, int *atreadeof)
 {
     apr_pollfd_t pfds[1];
-    apr_status_t status;
+    apr_status_t rv;
     apr_int32_t  nfds;
 
+    /* The purpose here is to return APR_SUCCESS only in cases in
+     * which it can be unambiguously determined whether or not the
+     * socket will return EOF on next read.  In case of an unexpected
+     * error, return that. */
+
     pfds[0].reqevents = APR_POLLIN;
     pfds[0].desc_type = APR_POLL_SOCKET;
-    pfds[0].desc.s = socket;
+    pfds[0].desc.s = sock;
 
     do {
-        status = apr_poll(&pfds[0], 1, &nfds, 0);
-    } while (APR_STATUS_IS_EINTR(status));
+        rv = apr_poll(&pfds[0], 1, &nfds, 0);
+    } while (APR_STATUS_IS_EINTR(rv));
 
-    if (status == APR_SUCCESS && nfds == 1 &&
-        pfds[0].rtnevents == APR_POLLIN) {
+    if (APR_STATUS_IS_TIMEUP(rv)) {
+        /* Read buffer empty -> subsequent reads would block, so,
+         * definitely not at EOF. */
+        *atreadeof = 0;
+        return APR_SUCCESS;
+    }
+    else if (rv) {
+        /* Some other error -> unexpected error. */
+        return rv;
+    }
+    else if (nfds == 1 && pfds[0].rtnevents == APR_POLLIN) {
         apr_sockaddr_t unused;
         apr_size_t len = 1;
-        char buf[1];
-        /* The socket might be closed in which case
-         * the poll will return POLLIN.
-         * If there is no data available the socket
-         * is closed.
-         */
-        status = apr_socket_recvfrom(&unused, socket, MSG_PEEK,
-                                     &buf[0], &len);
-        if (status == APR_SUCCESS && len)
-            return 1;
-        else
-            return 0;
-    }
-    else if (APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) {
-        return 1;
+        char buf;
+
+        /* The socket is readable - peek to see whether it returns EOF
+         * without consuming bytes from the socket buffer. */
+        rv = apr_socket_recvfrom(&unused, sock, MSG_PEEK, &buf, &len);
+        if (rv == APR_EOF) {
+            *atreadeof = 1;
+            return APR_SUCCESS;
+        }
+        else if (rv) {
+            /* Read error -> unexpected error. */
+            return rv;
+        }
+        else {
+            *atreadeof = 0;
+            return APR_SUCCESS;
+        }
     }
-    return 0;
 
+    /* Should not fall through here. */
+    return APR_EGENERAL;
 }
 

Modified: apr/apr/trunk/test/testsock.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testsock.c?rev=824500&r1=824499&r2=824500&view=diff
==============================================================================
--- apr/apr/trunk/test/testsock.c (original)
+++ apr/apr/trunk/test/testsock.c Mon Oct 12 21:16:56 2009
@@ -204,7 +204,7 @@
     APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
 }
 
-static void test_is_connected(abts_case *tc, void *data)
+static void test_atreadeof(abts_case *tc, void *data)
 {
     apr_status_t rv;
     apr_socket_t *sock;
@@ -212,6 +212,7 @@
     apr_proc_t proc;
     apr_size_t length = STRLEN;
     char datastr[STRLEN];
+    int atreadeof = -1;
 
     sock = setup_socket(tc);
     if (!sock) return;
@@ -222,7 +223,9 @@
     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
 
     /* Check that the remote socket is still open */
-    ABTS_INT_EQUAL(tc, 1, apr_socket_is_connected(sock2));
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #1", rv);
+    ABTS_INT_EQUAL(tc, 0, atreadeof);
 
     memset(datastr, 0, STRLEN);
     apr_socket_recv(sock2, datastr, &length);
@@ -232,7 +235,9 @@
     ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
 
     /* The child is dead, so should be the remote socket */
-    ABTS_INT_EQUAL(tc, 0, apr_socket_is_connected(sock2));
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #2", rv);
+    ABTS_INT_EQUAL(tc, 1, atreadeof);
 
     rv = apr_socket_close(sock2);
     APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
@@ -243,7 +248,9 @@
     APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
 
     /* The child closed the socket instantly */
-    ABTS_INT_EQUAL(tc, 0, apr_socket_is_connected(sock2));
+    rv = apr_socket_atreadeof(sock2, &atreadeof);
+    APR_ASSERT_SUCCESS(tc, "Determine whether at EOF, #3", rv);
+    ABTS_INT_EQUAL(tc, 1, atreadeof);
     wait_child(tc, &proc);
 
     rv = apr_socket_close(sock2);
@@ -400,7 +407,7 @@
     abts_run_test(suite, test_create_bind_listen, NULL);
     abts_run_test(suite, test_send, NULL);
     abts_run_test(suite, test_recv, NULL);
-    abts_run_test(suite, test_is_connected, NULL);
+    abts_run_test(suite, test_atreadeof, NULL);
     abts_run_test(suite, test_timeout, NULL);
     abts_run_test(suite, test_print_addr, NULL);
     abts_run_test(suite, test_get_addr, NULL);