1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_network_io.h" 18#include "apr_poll.h" 19 20APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock, int *atreadeof) 21{ 22 apr_pollfd_t pfds[1]; 23 apr_status_t rv; 24 apr_int32_t nfds; 25 26 /* The purpose here is to return APR_SUCCESS only in cases in 27 * which it can be unambiguously determined whether or not the 28 * socket will return EOF on next read. In case of an unexpected 29 * error, return that. */ 30 31 pfds[0].reqevents = APR_POLLIN; 32 pfds[0].desc_type = APR_POLL_SOCKET; 33 pfds[0].desc.s = sock; 34 35 do { 36 rv = apr_poll(&pfds[0], 1, &nfds, 0); 37 } while (APR_STATUS_IS_EINTR(rv)); 38 39 if (APR_STATUS_IS_TIMEUP(rv)) { 40 /* Read buffer empty -> subsequent reads would block, so, 41 * definitely not at EOF. */ 42 *atreadeof = 0; 43 return APR_SUCCESS; 44 } 45 else if (rv) { 46 /* Some other error -> unexpected error. */ 47 return rv; 48 } 49 /* Many platforms return only APR_POLLIN; OS X returns APR_POLLHUP|APR_POLLIN */ 50 else if (nfds == 1 && (pfds[0].rtnevents & APR_POLLIN) == APR_POLLIN) { 51 apr_sockaddr_t unused; 52 apr_size_t len = 1; 53 char buf; 54 55 /* The socket is readable - peek to see whether it returns EOF 56 * without consuming bytes from the socket buffer. */ 57 rv = apr_socket_recvfrom(&unused, sock, MSG_PEEK, &buf, &len); 58 if (rv == APR_EOF) { 59 *atreadeof = 1; 60 return APR_SUCCESS; 61 } 62 else if (rv) { 63 /* Read error -> unexpected error. */ 64 return rv; 65 } 66 else { 67 *atreadeof = 0; 68 return APR_SUCCESS; 69 } 70 } 71 72 /* Should not fall through here. */ 73 return APR_EGENERAL; 74} 75 76