summaryrefslogtreecommitdiff
path: root/network_io/unix/socket_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'network_io/unix/socket_util.c')
-rw-r--r--network_io/unix/socket_util.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/network_io/unix/socket_util.c b/network_io/unix/socket_util.c
index bf98f100c..b23aed6b2 100644
--- a/network_io/unix/socket_util.c
+++ b/network_io/unix/socket_util.c
@@ -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;
}