You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by rp...@apache.org on 2009/10/16 23:08:15 UTC
svn commit: r826089 - in /apr/apr/branches/1.4.x: CHANGES
include/apr_network_io.h libapr.dsp network_io/beos/socketcommon.c
network_io/os2/socket_util.c network_io/unix/socket_util.c test/sockchild.c
test/testsock.c
Author: rpluem
Date: Fri Oct 16 21:08:15 2009
New Revision: 826089
URL: http://svn.apache.org/viewvc?rev=826089&view=rev
Log:
Merge r821524, r822431, r822892, r824500 from trunk:
* Add apr_socket_is_connected to detect whether the remote side of a socket
is still open. The origin of apr_socket_is_connected is r473278 from
http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c
in httpd.
* Improve the documentation
Suggested by: jorton
* Improve the documentation even further
Reviewed by: jim
* 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.
Reviewed by: jorton, rpluem
Added:
apr/apr/branches/1.4.x/network_io/os2/socket_util.c
- copied unchanged from r821524, apr/apr/trunk/network_io/os2/socket_util.c
apr/apr/branches/1.4.x/network_io/unix/socket_util.c
- copied, changed from r821524, apr/apr/trunk/network_io/unix/socket_util.c
Modified:
apr/apr/branches/1.4.x/CHANGES
apr/apr/branches/1.4.x/include/apr_network_io.h
apr/apr/branches/1.4.x/libapr.dsp
apr/apr/branches/1.4.x/network_io/beos/socketcommon.c
apr/apr/branches/1.4.x/test/sockchild.c
apr/apr/branches/1.4.x/test/testsock.c
Modified: apr/apr/branches/1.4.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/CHANGES?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.4.x/CHANGES [utf-8] Fri Oct 16 21:08:15 2009
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes for APR 1.4.0
+ *) Add apr_socket_atreadeof to determine whether the receive part of the
+ socket has been closed by the peer.
+ [Ruediger Pluem, Mladen Turk, Joe Orton]
+
*) Make apr_pollset and apr_pollcb implementations using providers.
Added apr_pollset_create_ex and apr_pollcb_create_ex that allows
choosing non-default providers.
Modified: apr/apr/branches/1.4.x/include/apr_network_io.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/include/apr_network_io.h?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/include/apr_network_io.h (original)
+++ apr/apr/branches/1.4.x/include/apr_network_io.h Fri Oct 16 21:08:15 2009
@@ -348,6 +348,21 @@
apr_sockaddr_t *sa);
/**
+ * 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
+ * @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(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock,
+ int *atreadeof);
+
+/**
* Create apr_sockaddr_t from hostname, address family, and port.
* @param sa The new apr_sockaddr_t.
* @param hostname The hostname or numeric address string to resolve/parse, or
Modified: apr/apr/branches/1.4.x/libapr.dsp
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/libapr.dsp?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/libapr.dsp (original)
+++ apr/apr/branches/1.4.x/libapr.dsp Fri Oct 16 21:08:15 2009
@@ -436,6 +436,10 @@
# End Source File
# Begin Source File
+SOURCE=.\network_io\unix\socket_util.c
+# End Source File
+# Begin Source File
+
SOURCE=.\network_io\win32\sendrecv.c
# End Source File
# Begin Source File
Modified: apr/apr/branches/1.4.x/network_io/beos/socketcommon.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/network_io/beos/socketcommon.c?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/network_io/beos/socketcommon.c (original)
+++ apr/apr/branches/1.4.x/network_io/beos/socketcommon.c Fri Oct 16 21:08:15 2009
@@ -3,3 +3,4 @@
#include "../unix/sockets.c"
#include "../unix/sockaddr.c"
#include "../unix/sockopt.c"
+#include "../unix/socket_util.c"
Copied: apr/apr/branches/1.4.x/network_io/unix/socket_util.c (from r821524, apr/apr/trunk/network_io/unix/socket_util.c)
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/network_io/unix/socket_util.c?p2=apr/apr/branches/1.4.x/network_io/unix/socket_util.c&p1=apr/apr/trunk/network_io/unix/socket_util.c&r1=821524&r2=826089&rev=826089&view=diff
==============================================================================
--- apr/apr/trunk/network_io/unix/socket_util.c (original)
+++ apr/apr/branches/1.4.x/network_io/unix/socket_util.c Fri Oct 16 21:08:15 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/branches/1.4.x/test/sockchild.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/test/sockchild.c?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/test/sockchild.c (original)
+++ apr/apr/branches/1.4.x/test/sockchild.c Fri Oct 16 21:08:15 2009
@@ -76,5 +76,9 @@
apr_socket_close(sock);
exit((int)length);
}
+ else if (!strcmp("close", argv[1])) {
+ apr_socket_close(sock);
+ exit(0);
+ }
exit(-1);
}
Modified: apr/apr/branches/1.4.x/test/testsock.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.4.x/test/testsock.c?rev=826089&r1=826088&r2=826089&view=diff
==============================================================================
--- apr/apr/branches/1.4.x/test/testsock.c (original)
+++ apr/apr/branches/1.4.x/test/testsock.c Fri Oct 16 21:08:15 2009
@@ -198,6 +198,62 @@
APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
}
+static void test_atreadeof(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+ apr_socket_t *sock;
+ apr_socket_t *sock2;
+ apr_proc_t proc;
+ apr_size_t length = STRLEN;
+ char datastr[STRLEN];
+ int atreadeof = -1;
+
+ sock = setup_socket(tc);
+ if (!sock) return;
+
+ launch_child(tc, &proc, "write", p);
+
+ rv = apr_socket_accept(&sock2, sock, p);
+ APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+ /* Check that the remote socket is still open */
+ 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);
+
+ /* Make sure that the server received the data we sent */
+ ABTS_STR_EQUAL(tc, DATASTR, datastr);
+ ABTS_SIZE_EQUAL(tc, strlen(datastr), wait_child(tc, &proc));
+
+ /* The child is dead, so should be the remote socket */
+ 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);
+
+ launch_child(tc, &proc, "close", p);
+
+ rv = apr_socket_accept(&sock2, sock, p);
+ APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv);
+
+ /* The child closed the socket instantly */
+ 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);
+ APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv);
+
+ rv = apr_socket_close(sock);
+ APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv);
+}
+
static void test_timeout(abts_case *tc, void *data)
{
apr_status_t rv;
@@ -345,6 +401,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_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);