third_party/serf/instaweb_outgoing.c
/* process all events on the connection */
process all events on the connection
process all events on the connection
apr_status_t serf__process_connection(serf_connection_t *conn,
                                      apr_int16_t events)
{
    apr_status_t status;
    if ((events & APR_POLLIN) != 0) {
        if ((status = read_from_connection(conn)) != APR_SUCCESS)
            return status;
        if ((conn->seen_in_pollset & APR_POLLHUP) != 0) {
            return APR_SUCCESS;
        }
    }
    if ((events & APR_POLLHUP) != 0) {
        if (conn->completed_responses) {
            return reset_connection(conn, 1);
        }
        return SERF_ERROR_ABORTED_CONNECTION;
    }
    if ((events & APR_POLLERR) != 0) {
        if (conn->completed_requests && !conn->probable_keepalive_limit) {
            return reset_connection(conn, 1);
        }
#ifdef SO_ERROR
        {
            apr_os_sock_t osskt;
            if (!apr_os_sock_get(&osskt, conn->skt)) {
                int error;
                apr_socklen_t l = sizeof(error);
                if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error,
                                &l)) {
                    status = APR_FROM_OS_ERROR(error);
                    if (conn->completed_requests == 0
                        && conn->address->next != NULL
                        && (APR_STATUS_IS_ECONNREFUSED(status)
                            || APR_STATUS_IS_TIMEUP(status)
                            || APR_STATUS_IS_ENETUNREACH(status))) {
                        conn->address = conn->address->next;
                        return reset_connection(conn, 1);
                    }
                    return status;
                  }
            }
        }
#endif
        return APR_EGENERAL;
    }
    if ((events & APR_POLLOUT) != 0) {
        if ((status = write_to_connection(conn)) != APR_SUCCESS)
            return status;
    }
    return APR_SUCCESS;
}
apr_status_t serf__process_connection ( serf_connection_t * conn , apr_int16_t events ) { apr_status_t status ; if ( ( events & APR_POLLIN ) != 0 ) { if ( ( status = read_from_connection ( conn ) ) != APR_SUCCESS ) return status ; if ( ( conn -> seen_in_pollset & APR_POLLHUP ) != 0 ) { return APR_SUCCESS ; } } if ( ( events & APR_POLLHUP ) != 0 ) { if ( conn -> completed_responses ) { return reset_connection ( conn , 1 ) ; } return SERF_ERROR_ABORTED_CONNECTION ; } if ( ( events & APR_POLLERR ) != 0 ) { if ( conn -> completed_requests && ! conn -> probable_keepalive_limit ) { return reset_connection ( conn , 1 ) ; } #ifdef SO_ERROR { apr_os_sock_t osskt ; if ( ! apr_os_sock_get ( & osskt , conn -> skt ) ) { int error ; apr_socklen_t l = sizeof ( error ) ; if ( ! getsockopt ( osskt , SOL_SOCKET , SO_ERROR , ( char * ) & error , & l ) ) { status = APR_FROM_OS_ERROR ( error ) ; if ( conn -> completed_requests == 0 && conn -> address -> next != NULL && ( APR_STATUS_IS_ECONNREFUSED ( status ) || APR_STATUS_IS_TIMEUP ( status ) || APR_STATUS_IS_ENETUNREACH ( status ) ) ) { conn -> address = conn -> address -> next ; return reset_connection ( conn , 1 ) ; } return status ; } } } #endif return APR_EGENERAL ; } if ( ( events & APR_POLLOUT ) != 0 ) { if ( ( status = write_to_connection ( conn ) ) != APR_SUCCESS ) return status ; } return APR_SUCCESS ; }
process all events on the connection
process all events on the connection
/* POLLHUP/ERR should come after POLLIN so if there's an error message or
     * the like sitting on the connection, we give the app a chance to read
     * it before we trigger a reset condition.
     */ /* If we decided to reset our connection, return now as we don't
         * want to write.
         */ /* The connection got reset by the server. On Windows this can happen
           when all data is read, so just cleanup the connection and open
           a new one.
           If we haven't had any successful responses on this connection,
           then error out as it is likely a server issue. */ /* We might be talking to a buggy HTTP server that doesn't
         * do lingering-close.  (httpd < 2.1.8 does this.)
         *
         * See:
         *
         * http://issues.apache.org/bugzilla/show_bug.cgi?id=35292
         */ /* If possible, get the error from the platform's socket layer and
           convert it to an APR status code. */ /* Handle fallback for multi-homed servers.

                       ### Improve algorithm to find better than just 'next'?

                       Current Windows versions already handle re-ordering for
                       api users by using statistics on the recently failed
                       connections to order the list of addresses. */