Blame test/server/test_server.c

Packit 3adb1e
/* ====================================================================
Packit 3adb1e
 *    Licensed to the Apache Software Foundation (ASF) under one
Packit 3adb1e
 *    or more contributor license agreements.  See the NOTICE file
Packit 3adb1e
 *    distributed with this work for additional information
Packit 3adb1e
 *    regarding copyright ownership.  The ASF licenses this file
Packit 3adb1e
 *    to you under the Apache License, Version 2.0 (the
Packit 3adb1e
 *    "License"); you may not use this file except in compliance
Packit 3adb1e
 *    with the License.  You may obtain a copy of the License at
Packit 3adb1e
 *
Packit 3adb1e
 *      http://www.apache.org/licenses/LICENSE-2.0
Packit 3adb1e
 *
Packit 3adb1e
 *    Unless required by applicable law or agreed to in writing,
Packit 3adb1e
 *    software distributed under the License is distributed on an
Packit 3adb1e
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
Packit 3adb1e
 *    KIND, either express or implied.  See the License for the
Packit 3adb1e
 *    specific language governing permissions and limitations
Packit 3adb1e
 *    under the License.
Packit 3adb1e
 * ====================================================================
Packit 3adb1e
 */
Packit 3adb1e
Packit 3adb1e
#include "apr.h"
Packit 3adb1e
#include "apr_pools.h"
Packit 3adb1e
#include <apr_poll.h>
Packit 3adb1e
#include <apr_version.h>
Packit 3adb1e
#include <stdlib.h>
Packit 3adb1e
Packit 3adb1e
#include "serf.h"
Packit 3adb1e
#include "serf_private.h" /* for serf__log and serf__bucket_stream_create */
Packit 3adb1e
Packit 3adb1e
#include "test_server.h"
Packit 3adb1e
Packit 3adb1e
#define BUFSIZE 8192
Packit 3adb1e
Packit 3adb1e
/* Cleanup callback for a server. */
Packit 3adb1e
static apr_status_t cleanup_server(void *baton)
Packit 3adb1e
{
Packit 3adb1e
    serv_ctx_t *servctx = baton;
Packit 3adb1e
    apr_status_t status;
Packit 3adb1e
Packit 3adb1e
    if (servctx->serv_sock)
Packit 3adb1e
      status = apr_socket_close(servctx->serv_sock);
Packit 3adb1e
    else
Packit 3adb1e
      status = APR_EGENERAL;
Packit 3adb1e
Packit 3adb1e
    if (servctx->client_sock) {
Packit 3adb1e
        apr_socket_close(servctx->client_sock);
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
    return status;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
/* Replay support functions */
Packit 3adb1e
static void next_message(serv_ctx_t *servctx)
Packit 3adb1e
{
Packit 3adb1e
    servctx->cur_message++;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
static void next_action(serv_ctx_t *servctx)
Packit 3adb1e
{
Packit 3adb1e
    servctx->cur_action++;
Packit 3adb1e
    servctx->action_buf_pos = 0;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
static apr_status_t
Packit 3adb1e
socket_write(serv_ctx_t *serv_ctx, const char *data,
Packit 3adb1e
             apr_size_t *len)
Packit 3adb1e
{
Packit 3adb1e
    return apr_socket_send(serv_ctx->client_sock, data, len);
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
static apr_status_t
Packit 3adb1e
socket_read(serv_ctx_t *serv_ctx, char *data,
Packit 3adb1e
            apr_size_t *len)
Packit 3adb1e
{
Packit 3adb1e
    return apr_socket_recv(serv_ctx->client_sock, data, len);
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
static apr_status_t
Packit 3adb1e
create_client_socket(apr_socket_t **skt,
Packit 3adb1e
                     serv_ctx_t *servctx,
Packit 3adb1e
                     const char *url)
Packit 3adb1e
{
Packit 3adb1e
    apr_sockaddr_t *address;
Packit 3adb1e
    apr_uri_t uri;
Packit 3adb1e
    apr_status_t status;
Packit 3adb1e
Packit 3adb1e
    status = apr_uri_parse(servctx->pool, url, &uri);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    status = apr_sockaddr_info_get(&address,
Packit 3adb1e
                                   uri.hostname,
Packit 3adb1e
                                   APR_UNSPEC,
Packit 3adb1e
                                   uri.port,
Packit 3adb1e
                                   0,
Packit 3adb1e
                                   servctx->pool);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    status = apr_socket_create(skt,
Packit 3adb1e
                               address->family,
Packit 3adb1e
                               SOCK_STREAM,
Packit 3adb1e
#if APR_MAJOR_VERSION > 0
Packit 3adb1e
                               APR_PROTO_TCP,
Packit 3adb1e
#endif
Packit 3adb1e
                               servctx->pool);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    /* Set the socket to be non-blocking */
Packit 3adb1e
    status = apr_socket_timeout_set(*skt, 0);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    status = apr_socket_connect(*skt, address);
Packit 3adb1e
    if (status != APR_SUCCESS && !APR_STATUS_IS_EINPROGRESS(status))
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    return APR_SUCCESS;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
Packit 3adb1e
{
Packit 3adb1e
    return APR_EAGAIN;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
/* Verify received requests and take the necessary actions
Packit 3adb1e
   (return a response, kill the connection ...) */
Packit 3adb1e
static apr_status_t replay(serv_ctx_t *servctx,
Packit 3adb1e
                           apr_int16_t rtnevents,
Packit 3adb1e
                           apr_pool_t *pool)
Packit 3adb1e
{
Packit 3adb1e
    apr_status_t status = APR_SUCCESS;
Packit 3adb1e
    test_server_action_t *action;
Packit 3adb1e
Packit 3adb1e
    if (rtnevents & APR_POLLIN) {
Packit 3adb1e
        if (servctx->message_list == NULL) {
Packit 3adb1e
            /* we're not expecting any requests to reach this server! */
Packit 3adb1e
            serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                      "Received request where none was expected.\n");
Packit 3adb1e
Packit 3adb1e
            return SERF_ERROR_ISSUE_IN_TESTSUITE;
Packit 3adb1e
        }
Packit 3adb1e
Packit 3adb1e
        if (servctx->cur_action >= servctx->action_count) {
Packit 3adb1e
            char buf[128];
Packit 3adb1e
            apr_size_t len = sizeof(buf);
Packit 3adb1e
Packit 3adb1e
            status = servctx->read(servctx, buf, &len;;
Packit 3adb1e
            if (! APR_STATUS_IS_EAGAIN(status)) {
Packit 3adb1e
                /* we're out of actions! */
Packit 3adb1e
                serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                          "Received more requests than expected.\n");
Packit 3adb1e
Packit 3adb1e
                return SERF_ERROR_ISSUE_IN_TESTSUITE;
Packit 3adb1e
            }
Packit 3adb1e
            return status;
Packit 3adb1e
        }
Packit 3adb1e
Packit 3adb1e
        action = &servctx->action_list[servctx->cur_action];
Packit 3adb1e
Packit 3adb1e
        serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                  "POLLIN while replaying action %d, kind: %d.\n",
Packit 3adb1e
                  servctx->cur_action, action->kind);
Packit 3adb1e
Packit 3adb1e
        /* Read the remaining data from the client and kill the socket. */
Packit 3adb1e
        if (action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) {
Packit 3adb1e
            char buf[128];
Packit 3adb1e
            apr_size_t len = sizeof(buf);
Packit 3adb1e
Packit 3adb1e
            status = servctx->read(servctx, buf, &len;;
Packit 3adb1e
Packit 3adb1e
            if (status == APR_EOF) {
Packit 3adb1e
                serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                          "Killing this connection.\n");
Packit 3adb1e
                apr_socket_close(servctx->client_sock);
Packit 3adb1e
                servctx->client_sock = NULL;
Packit 3adb1e
                next_action(servctx);
Packit 3adb1e
                return APR_SUCCESS;
Packit 3adb1e
            }
Packit 3adb1e
Packit 3adb1e
            return status;
Packit 3adb1e
        }
Packit 3adb1e
        else if (action->kind == SERVER_RECV ||
Packit 3adb1e
                 (action->kind == SERVER_RESPOND &&
Packit 3adb1e
                  servctx->outstanding_responses == 0)) {
Packit 3adb1e
            apr_size_t msg_len, len;
Packit 3adb1e
            char buf[128];
Packit 3adb1e
            test_server_message_t *message;
Packit 3adb1e
Packit 3adb1e
            message = &servctx->message_list[servctx->cur_message];
Packit 3adb1e
            msg_len = strlen(message->text);
Packit 3adb1e
Packit 3adb1e
            do
Packit 3adb1e
            {
Packit 3adb1e
                len = msg_len - servctx->message_buf_pos;
Packit 3adb1e
                if (len > sizeof(buf))
Packit 3adb1e
                    len = sizeof(buf);
Packit 3adb1e
Packit 3adb1e
                status = servctx->read(servctx, buf, &len;;
Packit 3adb1e
                if (SERF_BUCKET_READ_ERROR(status))
Packit 3adb1e
                    return status;
Packit 3adb1e
Packit 3adb1e
                if (status == APR_EOF) {
Packit 3adb1e
                    serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                              "Server: Client hung up the connection.\n");
Packit 3adb1e
                    break;
Packit 3adb1e
                }
Packit 3adb1e
                if (servctx->options & TEST_SERVER_DUMP)
Packit 3adb1e
                    fwrite(buf, len, 1, stdout);
Packit 3adb1e
Packit 3adb1e
                if (strncmp(buf,
Packit 3adb1e
                            message->text + servctx->message_buf_pos,
Packit 3adb1e
                            len) != 0) {
Packit 3adb1e
                    /* ## TODO: Better diagnostics. */
Packit 3adb1e
                    printf("Expected: (\n");
Packit 3adb1e
                    fwrite(message->text + servctx->message_buf_pos, len, 1,
Packit 3adb1e
                           stdout);
Packit 3adb1e
                    printf(")\n");
Packit 3adb1e
                    printf("Actual: (\n");
Packit 3adb1e
                    fwrite(buf, len, 1, stdout);
Packit 3adb1e
                    printf(")\n");
Packit 3adb1e
Packit 3adb1e
                    return SERF_ERROR_ISSUE_IN_TESTSUITE;
Packit 3adb1e
                }
Packit 3adb1e
Packit 3adb1e
                servctx->message_buf_pos += len;
Packit 3adb1e
Packit 3adb1e
                if (servctx->message_buf_pos >= msg_len) {
Packit 3adb1e
                    next_message(servctx);
Packit 3adb1e
                    servctx->message_buf_pos -= msg_len;
Packit 3adb1e
                    if (action->kind == SERVER_RESPOND)
Packit 3adb1e
                        servctx->outstanding_responses++;
Packit 3adb1e
                    if (action->kind == SERVER_RECV)
Packit 3adb1e
                        next_action(servctx);
Packit 3adb1e
                    break;
Packit 3adb1e
                }
Packit 3adb1e
            } while (!status);
Packit 3adb1e
        }
Packit 3adb1e
        else if (action->kind == PROXY_FORWARD) {
Packit 3adb1e
            apr_size_t len;
Packit 3adb1e
            char buf[BUFSIZE];
Packit 3adb1e
            serf_bucket_t *tmp;
Packit 3adb1e
Packit 3adb1e
            /* Read all incoming data from the client to forward it to the
Packit 3adb1e
               server later. */
Packit 3adb1e
            do
Packit 3adb1e
            {
Packit 3adb1e
                len = BUFSIZE;
Packit 3adb1e
Packit 3adb1e
                status = servctx->read(servctx, buf, &len;;
Packit 3adb1e
                if (SERF_BUCKET_READ_ERROR(status))
Packit 3adb1e
                    return status;
Packit 3adb1e
Packit 3adb1e
                serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                          "proxy: reading %d bytes %.*s from client with "
Packit 3adb1e
                          "status %d.\n",
Packit 3adb1e
                          len, len, buf, status);
Packit 3adb1e
Packit 3adb1e
                if (status == APR_EOF) {
Packit 3adb1e
                    serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                              "Proxy: client hung up the connection. Reset the "
Packit 3adb1e
                              "connection to the server.\n");
Packit 3adb1e
                    /* We have to stop forwarding, if a new connection opens
Packit 3adb1e
                       the CONNECT request should not be forwarded to the
Packit 3adb1e
                       server. */
Packit 3adb1e
                    next_action(servctx);
Packit 3adb1e
                }
Packit 3adb1e
                if (!servctx->servstream)
Packit 3adb1e
                    servctx->servstream = serf__bucket_stream_create(
Packit 3adb1e
                                              servctx->allocator,
Packit 3adb1e
                                              detect_eof,servctx);
Packit 3adb1e
                if (len) {
Packit 3adb1e
                    tmp = serf_bucket_simple_copy_create(buf, len,
Packit 3adb1e
                                                         servctx->allocator);
Packit 3adb1e
                    serf_bucket_aggregate_append(servctx->servstream, tmp);
Packit 3adb1e
                }
Packit 3adb1e
            } while (!status);
Packit 3adb1e
        }
Packit 3adb1e
    }
Packit 3adb1e
    if (rtnevents & APR_POLLOUT) {
Packit 3adb1e
        action = &servctx->action_list[servctx->cur_action];
Packit 3adb1e
Packit 3adb1e
        serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                  "POLLOUT when replaying action %d, kind: %d.\n", servctx->cur_action,
Packit 3adb1e
                  action->kind);
Packit 3adb1e
Packit 3adb1e
        if (action->kind == SERVER_RESPOND && servctx->outstanding_responses) {
Packit 3adb1e
            apr_size_t msg_len;
Packit 3adb1e
            apr_size_t len;
Packit 3adb1e
Packit 3adb1e
            msg_len = strlen(action->text);
Packit 3adb1e
            len = msg_len - servctx->action_buf_pos;
Packit 3adb1e
Packit 3adb1e
            status = servctx->send(servctx,
Packit 3adb1e
                                   action->text + servctx->action_buf_pos,
Packit 3adb1e
                                   &len;;
Packit 3adb1e
            if (status != APR_SUCCESS)
Packit 3adb1e
                return status;
Packit 3adb1e
Packit 3adb1e
            if (servctx->options & TEST_SERVER_DUMP)
Packit 3adb1e
                fwrite(action->text + servctx->action_buf_pos, len, 1, stdout);
Packit 3adb1e
Packit 3adb1e
            servctx->action_buf_pos += len;
Packit 3adb1e
Packit 3adb1e
            if (servctx->action_buf_pos >= msg_len) {
Packit 3adb1e
                next_action(servctx);
Packit 3adb1e
                servctx->outstanding_responses--;
Packit 3adb1e
            }
Packit 3adb1e
        }
Packit 3adb1e
        else if (action->kind == SERVER_KILL_CONNECTION ||
Packit 3adb1e
                 action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) {
Packit 3adb1e
            serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                      "Killing this connection.\n");
Packit 3adb1e
            apr_socket_close(servctx->client_sock);
Packit 3adb1e
            servctx->client_sock = NULL;
Packit 3adb1e
            next_action(servctx);
Packit 3adb1e
        }
Packit 3adb1e
        else if (action->kind == PROXY_FORWARD) {
Packit 3adb1e
            apr_size_t len;
Packit 3adb1e
            char *buf;
Packit 3adb1e
Packit 3adb1e
            if (!servctx->proxy_client_sock) {
Packit 3adb1e
                serf__log(TEST_VERBOSE, __FILE__, "Proxy: setting up connection "
Packit 3adb1e
                          "to server.\n");
Packit 3adb1e
                status = create_client_socket(&servctx->proxy_client_sock,
Packit 3adb1e
                                              servctx, action->text);
Packit 3adb1e
                if (!servctx->clientstream)
Packit 3adb1e
                    servctx->clientstream = serf__bucket_stream_create(
Packit 3adb1e
                                                servctx->allocator,
Packit 3adb1e
                                                detect_eof,servctx);
Packit 3adb1e
            }
Packit 3adb1e
Packit 3adb1e
            /* Send all data received from the server to the client. */
Packit 3adb1e
            do
Packit 3adb1e
            {
Packit 3adb1e
                apr_size_t readlen;
Packit 3adb1e
Packit 3adb1e
                readlen = BUFSIZE;
Packit 3adb1e
Packit 3adb1e
                status = serf_bucket_read(servctx->clientstream, readlen,
Packit 3adb1e
                                          &buf, &readlen);
Packit 3adb1e
                if (SERF_BUCKET_READ_ERROR(status))
Packit 3adb1e
                    return status;
Packit 3adb1e
                if (!readlen)
Packit 3adb1e
                    break;
Packit 3adb1e
Packit 3adb1e
                len = readlen;
Packit 3adb1e
Packit 3adb1e
                serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                          "proxy: sending %d bytes to client.\n", len);
Packit 3adb1e
                status = servctx->send(servctx, buf, &len;;
Packit 3adb1e
                if (status != APR_SUCCESS) {
Packit 3adb1e
                    return status;
Packit 3adb1e
                }
Packit 3adb1e
                
Packit 3adb1e
                if (len != readlen) /* abort for now, return buf to aggregate
Packit 3adb1e
                                       if not everything could be sent. */
Packit 3adb1e
                    return APR_EGENERAL;
Packit 3adb1e
            } while (!status);
Packit 3adb1e
        }
Packit 3adb1e
    }
Packit 3adb1e
    else if (rtnevents & APR_POLLIN) {
Packit 3adb1e
        /* ignore */
Packit 3adb1e
    }
Packit 3adb1e
    else {
Packit 3adb1e
        printf("Unknown rtnevents: %d\n", rtnevents);
Packit 3adb1e
        abort();
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
    return status;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
/* Exchange data between proxy and server */
Packit 3adb1e
static apr_status_t proxy_replay(serv_ctx_t *servctx,
Packit 3adb1e
                                 apr_int16_t rtnevents,
Packit 3adb1e
                                 apr_pool_t *pool)
Packit 3adb1e
{
Packit 3adb1e
    apr_status_t status;
Packit 3adb1e
Packit 3adb1e
    if (rtnevents & APR_POLLIN) {
Packit 3adb1e
        apr_size_t len;
Packit 3adb1e
        char buf[BUFSIZE];
Packit 3adb1e
        serf_bucket_t *tmp;
Packit 3adb1e
Packit 3adb1e
        serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLIN\n");
Packit 3adb1e
        /* Read all incoming data from the server to forward it to the
Packit 3adb1e
           client later. */
Packit 3adb1e
        do
Packit 3adb1e
        {
Packit 3adb1e
            len = BUFSIZE;
Packit 3adb1e
Packit 3adb1e
            status = apr_socket_recv(servctx->proxy_client_sock, buf, &len;;
Packit 3adb1e
            if (SERF_BUCKET_READ_ERROR(status))
Packit 3adb1e
                return status;
Packit 3adb1e
Packit 3adb1e
            serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                      "proxy: reading %d bytes %.*s from server.\n",
Packit 3adb1e
                      len, len, buf);
Packit 3adb1e
            tmp = serf_bucket_simple_copy_create(buf, len,
Packit 3adb1e
                                                 servctx->allocator);
Packit 3adb1e
            serf_bucket_aggregate_append(servctx->clientstream, tmp);
Packit 3adb1e
        } while (!status);
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
    if (rtnevents & APR_POLLOUT) {
Packit 3adb1e
        apr_size_t len;
Packit 3adb1e
        char *buf;
Packit 3adb1e
Packit 3adb1e
        serf__log(TEST_VERBOSE, __FILE__, "proxy_replay: POLLOUT\n");
Packit 3adb1e
        /* Send all data received from the client to the server. */
Packit 3adb1e
        do
Packit 3adb1e
        {
Packit 3adb1e
            apr_size_t readlen;
Packit 3adb1e
Packit 3adb1e
            readlen = BUFSIZE;
Packit 3adb1e
Packit 3adb1e
            if (!servctx->servstream)
Packit 3adb1e
                servctx->servstream = serf__bucket_stream_create(
Packit 3adb1e
                                          servctx->allocator,
Packit 3adb1e
                                          detect_eof,servctx);
Packit 3adb1e
            status = serf_bucket_read(servctx->servstream, BUFSIZE,
Packit 3adb1e
                                      &buf, &readlen);
Packit 3adb1e
            if (SERF_BUCKET_READ_ERROR(status))
Packit 3adb1e
                return status;
Packit 3adb1e
            if (!readlen)
Packit 3adb1e
                break;
Packit 3adb1e
Packit 3adb1e
            len = readlen;
Packit 3adb1e
Packit 3adb1e
            serf__log(TEST_VERBOSE, __FILE__,
Packit 3adb1e
                      "proxy: sending %d bytes %.*s to server.\n",
Packit 3adb1e
                      len, len, buf);
Packit 3adb1e
            status = apr_socket_send(servctx->proxy_client_sock, buf, &len;;
Packit 3adb1e
            if (status != APR_SUCCESS) {
Packit 3adb1e
                return status;
Packit 3adb1e
            }
Packit 3adb1e
Packit 3adb1e
            if (len != readlen) /* abort for now */
Packit 3adb1e
                return APR_EGENERAL;
Packit 3adb1e
        } while (!status);
Packit 3adb1e
    }
Packit 3adb1e
    else if (rtnevents & APR_POLLIN) {
Packit 3adb1e
        /* ignore */
Packit 3adb1e
    }
Packit 3adb1e
    else {
Packit 3adb1e
        printf("Unknown rtnevents: %d\n", rtnevents);
Packit 3adb1e
        abort();
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
    return status;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
apr_status_t run_test_server(serv_ctx_t *servctx,
Packit 3adb1e
                             apr_short_interval_time_t duration,
Packit 3adb1e
                             apr_pool_t *pool)
Packit 3adb1e
{
Packit 3adb1e
    apr_status_t status;
Packit 3adb1e
    apr_pollset_t *pollset;
Packit 3adb1e
    apr_int32_t num;
Packit 3adb1e
    const apr_pollfd_t *desc;
Packit 3adb1e
Packit 3adb1e
    /* create a new pollset */
Packit 3adb1e
#ifdef BROKEN_WSAPOLL
Packit 3adb1e
    status = apr_pollset_create_ex(&pollset, 32, pool, 0,
Packit 3adb1e
                                 APR_POLLSET_SELECT);
Packit 3adb1e
#else
Packit 3adb1e
    status = apr_pollset_create(&pollset, 32, pool, 0);
Packit 3adb1e
#endif
Packit 3adb1e
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    /* Don't accept new connection while processing client connection. At
Packit 3adb1e
       least for present time.*/
Packit 3adb1e
    if (servctx->client_sock) {
Packit 3adb1e
        apr_pollfd_t pfd = { 0 };
Packit 3adb1e
Packit 3adb1e
        pfd.desc_type = APR_POLL_SOCKET;
Packit 3adb1e
        pfd.desc.s = servctx->client_sock;
Packit 3adb1e
        pfd.reqevents = APR_POLLIN | APR_POLLOUT;
Packit 3adb1e
Packit 3adb1e
        status = apr_pollset_add(pollset, &pfd;;
Packit 3adb1e
        if (status != APR_SUCCESS)
Packit 3adb1e
            goto cleanup;
Packit 3adb1e
Packit 3adb1e
        if (servctx->proxy_client_sock) {
Packit 3adb1e
            apr_pollfd_t pfd = { 0 };
Packit 3adb1e
Packit 3adb1e
            pfd.desc_type = APR_POLL_SOCKET;
Packit 3adb1e
            pfd.desc.s = servctx->proxy_client_sock;
Packit 3adb1e
            pfd.reqevents = APR_POLLIN | APR_POLLOUT;
Packit 3adb1e
Packit 3adb1e
            status = apr_pollset_add(pollset, &pfd;;
Packit 3adb1e
            if (status != APR_SUCCESS)
Packit 3adb1e
                goto cleanup;
Packit 3adb1e
        }
Packit 3adb1e
    }
Packit 3adb1e
    else {
Packit 3adb1e
        apr_pollfd_t pfd = { 0 };
Packit 3adb1e
Packit 3adb1e
        pfd.desc_type = APR_POLL_SOCKET;
Packit 3adb1e
        pfd.desc.s = servctx->serv_sock;
Packit 3adb1e
        pfd.reqevents = APR_POLLIN;
Packit 3adb1e
Packit 3adb1e
        status = apr_pollset_add(pollset, &pfd;;
Packit 3adb1e
        if (status != APR_SUCCESS)
Packit 3adb1e
            goto cleanup;
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
    status = apr_pollset_poll(pollset, APR_USEC_PER_SEC >> 1, &num, &desc);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        goto cleanup;
Packit 3adb1e
Packit 3adb1e
    while (num--) {
Packit 3adb1e
        if (desc->desc.s == servctx->serv_sock) {
Packit 3adb1e
            status = apr_socket_accept(&servctx->client_sock, servctx->serv_sock,
Packit 3adb1e
                                       servctx->pool);
Packit 3adb1e
            if (status != APR_SUCCESS)
Packit 3adb1e
                goto cleanup;
Packit 3adb1e
Packit 3adb1e
            serf__log_skt(TEST_VERBOSE, __FILE__, servctx->client_sock,
Packit 3adb1e
                          "server/proxy accepted incoming connection.\n");
Packit 3adb1e
Packit 3adb1e
Packit 3adb1e
            apr_socket_opt_set(servctx->client_sock, APR_SO_NONBLOCK, 1);
Packit 3adb1e
            apr_socket_timeout_set(servctx->client_sock, 0);
Packit 3adb1e
Packit 3adb1e
            status = APR_SUCCESS;
Packit 3adb1e
            goto cleanup;
Packit 3adb1e
        }
Packit 3adb1e
Packit 3adb1e
        if (desc->desc.s == servctx->client_sock) {
Packit 3adb1e
            if (servctx->handshake) {
Packit 3adb1e
                status = servctx->handshake(servctx);
Packit 3adb1e
                if (status)
Packit 3adb1e
                    goto cleanup;
Packit 3adb1e
            }
Packit 3adb1e
Packit 3adb1e
            /* Replay data to socket. */
Packit 3adb1e
            status = replay(servctx, desc->rtnevents, pool);
Packit 3adb1e
Packit 3adb1e
            if (APR_STATUS_IS_EOF(status)) {
Packit 3adb1e
                apr_socket_close(servctx->client_sock);
Packit 3adb1e
                servctx->client_sock = NULL;
Packit 3adb1e
                if (servctx->reset)
Packit 3adb1e
                    servctx->reset(servctx);
Packit 3adb1e
Packit 3adb1e
                /* If this is a proxy and the client closed the connection, also
Packit 3adb1e
                   close the connection to the server. */
Packit 3adb1e
                if (servctx->proxy_client_sock) {
Packit 3adb1e
                    apr_socket_close(servctx->proxy_client_sock);
Packit 3adb1e
                    servctx->proxy_client_sock = NULL;
Packit 3adb1e
                    goto cleanup;
Packit 3adb1e
                }
Packit 3adb1e
            }
Packit 3adb1e
            else if (APR_STATUS_IS_EAGAIN(status)) {
Packit 3adb1e
                status = APR_SUCCESS;
Packit 3adb1e
            }
Packit 3adb1e
            else if (status != APR_SUCCESS) {
Packit 3adb1e
                /* Real error. */
Packit 3adb1e
                goto cleanup;
Packit 3adb1e
            }
Packit 3adb1e
        }
Packit 3adb1e
        if (desc->desc.s == servctx->proxy_client_sock) {
Packit 3adb1e
            /* Replay data to proxy socket. */
Packit 3adb1e
            status = proxy_replay(servctx, desc->rtnevents, pool);
Packit 3adb1e
            if (APR_STATUS_IS_EOF(status)) {
Packit 3adb1e
                apr_socket_close(servctx->proxy_client_sock);
Packit 3adb1e
                servctx->proxy_client_sock = NULL;
Packit 3adb1e
            }
Packit 3adb1e
            else if (APR_STATUS_IS_EAGAIN(status)) {
Packit 3adb1e
                status = APR_SUCCESS;
Packit 3adb1e
            }
Packit 3adb1e
            else if (status != APR_SUCCESS) {
Packit 3adb1e
                /* Real error. */
Packit 3adb1e
                goto cleanup;
Packit 3adb1e
            }
Packit 3adb1e
        }
Packit 3adb1e
Packit 3adb1e
        desc++;
Packit 3adb1e
    }
Packit 3adb1e
Packit 3adb1e
cleanup:
Packit 3adb1e
    apr_pollset_destroy(pollset);
Packit 3adb1e
Packit 3adb1e
    return status;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
Packit 3adb1e
/* Setup the context needed to start a TCP server on adress.
Packit 3adb1e
   message_list is a list of expected requests.
Packit 3adb1e
   action_list is the list of responses to be returned in order.
Packit 3adb1e
 */
Packit 3adb1e
void setup_test_server(serv_ctx_t **servctx_p,
Packit 3adb1e
                       apr_sockaddr_t *address,
Packit 3adb1e
                       test_server_message_t *message_list,
Packit 3adb1e
                       apr_size_t message_count,
Packit 3adb1e
                       test_server_action_t *action_list,
Packit 3adb1e
                       apr_size_t action_count,
Packit 3adb1e
                       apr_int32_t options,
Packit 3adb1e
                       apr_pool_t *pool)
Packit 3adb1e
{
Packit 3adb1e
    serv_ctx_t *servctx;
Packit 3adb1e
Packit 3adb1e
    servctx = apr_pcalloc(pool, sizeof(*servctx));
Packit 3adb1e
    apr_pool_cleanup_register(pool, servctx,
Packit 3adb1e
                              cleanup_server,
Packit 3adb1e
                              apr_pool_cleanup_null);
Packit 3adb1e
    *servctx_p = servctx;
Packit 3adb1e
Packit 3adb1e
    servctx->serv_addr = address;
Packit 3adb1e
    servctx->options = options;
Packit 3adb1e
    servctx->pool = pool;
Packit 3adb1e
    servctx->allocator = serf_bucket_allocator_create(pool, NULL, NULL);
Packit 3adb1e
    servctx->message_list = message_list;
Packit 3adb1e
    servctx->message_count = message_count;
Packit 3adb1e
    servctx->action_list = action_list;
Packit 3adb1e
    servctx->action_count = action_count;
Packit 3adb1e
Packit 3adb1e
    /* Start replay from first action. */
Packit 3adb1e
    servctx->cur_action = 0;
Packit 3adb1e
    servctx->action_buf_pos = 0;
Packit 3adb1e
    servctx->outstanding_responses = 0;
Packit 3adb1e
Packit 3adb1e
    servctx->read = socket_read;
Packit 3adb1e
    servctx->send = socket_write;
Packit 3adb1e
Packit 3adb1e
    *servctx_p = servctx;
Packit 3adb1e
}
Packit 3adb1e
Packit 3adb1e
apr_status_t start_test_server(serv_ctx_t *servctx)
Packit 3adb1e
{
Packit 3adb1e
    apr_status_t status;
Packit 3adb1e
    apr_socket_t *serv_sock;
Packit 3adb1e
Packit 3adb1e
    /* create server socket */
Packit 3adb1e
#if APR_VERSION_AT_LEAST(1, 0, 0)
Packit 3adb1e
    status = apr_socket_create(&serv_sock, servctx->serv_addr->family,
Packit 3adb1e
                               SOCK_STREAM, 0,
Packit 3adb1e
                               servctx->pool);
Packit 3adb1e
#else
Packit 3adb1e
    status = apr_socket_create(&serv_sock, servctx->serv_addr->family,
Packit 3adb1e
                               SOCK_STREAM,
Packit 3adb1e
                               servctx->pool);
Packit 3adb1e
#endif
Packit 3adb1e
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    apr_socket_opt_set(serv_sock, APR_SO_NONBLOCK, 1);
Packit 3adb1e
    apr_socket_timeout_set(serv_sock, 0);
Packit 3adb1e
    apr_socket_opt_set(serv_sock, APR_SO_REUSEADDR, 1);
Packit 3adb1e
Packit 3adb1e
    status = apr_socket_bind(serv_sock, servctx->serv_addr);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    /* listen for clients */
Packit 3adb1e
    status = apr_socket_listen(serv_sock, SOMAXCONN);
Packit 3adb1e
    if (status != APR_SUCCESS)
Packit 3adb1e
        return status;
Packit 3adb1e
Packit 3adb1e
    servctx->serv_sock = serv_sock;
Packit 3adb1e
    servctx->client_sock = NULL;
Packit 3adb1e
Packit 3adb1e
    return APR_SUCCESS;
Packit 3adb1e
}