Пример #1
0
static void corkable(CuTest *tc)
{
#if !APR_HAVE_CORKABLE_TCP
    CuNotImpl(tc, "TCP isn't corkable");
#else
    apr_status_t rv;
    apr_int32_t ck;

    rv = apr_socket_opt_set(sock, APR_TCP_NODELAY, 1);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 1, ck);

    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_TCP_NOPUSH, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 1, ck);

    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 0, ck);

    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 1, ck);
#endif
}
Пример #2
0
static void remove_keepalive(abts_case *tc, void *data)
{
    apr_status_t rv;
    apr_int32_t ck;

    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    ABTS_INT_EQUAL(tc, 1, ck);

    rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 0);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    ABTS_INT_EQUAL(tc, 0, ck);
}
Пример #3
0
static void remove_keepalive(CuTest *tc)
{
    apr_status_t rv;
    apr_int32_t ck;

    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 1, ck);

    rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 0);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck);
    CuAssertIntEquals(tc, APR_SUCCESS, rv);
    CuAssertIntEquals(tc, 0, ck);
}
Пример #4
0
/*! Setup the required steps to accept a connection (fully async) and
 *  install an event/callback to be called on the newly created socket.
 *
 * @param lsock        Listening socket, created by cpe_socket_server_create().
 * @param callback     Callback that will be called on the new socket.
 * @param ctx1         Callback argument.
 * @param pfd_flags    Poll flags for the new socket.
 * @param afilter_cb   Optional accept filter callback. NULL will accept
 *                     connections only from localhost.
 * @param max_peers    Max number of contemporary connections.
 * @param one_shot_cb  Callback that will be called once per newly created
 *                     socket. This allows e.g. to call cpe_queue_init with the
 *                     appropriate pfd.
 * @param one_shot_ctx Callback argument.
 * @param pool         Memory pool to use.
 */
apr_status_t
cpe_socket_after_accept(
    apr_socket_t   *lsock,
    cpe_callback_t  callback,
    void           *ctx1,
    apr_int16_t     pfd_flags,
    cpe_afilter_t   afilter_cb,
    int             max_peers,
    cpe_callback_t  one_shot_cb,
    void           *one_shot_ctx,
    apr_pool_t     *pool)
{
    apr_status_t            rv;
    cpe_event              *event;
    cpe_socket_prepare_ctx *sp_ctx;
    int                     nonblock;

    /* Enforce contract. */
    apr_socket_opt_get(lsock, APR_SO_NONBLOCK, &nonblock);
    assert(nonblock == 1);

    if (max_peers <= 0 || max_peers > CPE_MAX_PEERS) {
        cpe_log(CPE_DEB, "%s", "max_peers outside range (%d)");
        return APR_EINVAL;
    }
    /*
     * Setup event/callback for listening socket.
     */
    cpe_log(CPE_DEB, "%s", "creating event for listening socket");
    sp_ctx = apr_palloc(pool, sizeof *sp_ctx);
    if (sp_ctx == NULL) {
        return APR_EGENERAL;
    }
    event = cpe_event_fdesc_create(APR_POLL_SOCKET, APR_POLLIN,
        (apr_descriptor) lsock, 0, cpe_socket_accept_cb, sp_ctx);
    if (event == NULL) {
        return APR_EGENERAL;
    }
    sp_ctx->pc_afilter      = afilter_cb;
    sp_ctx->pc_callback     = callback;
    sp_ctx->pc_ctx1         = ctx1;
    sp_ctx->pc_reqevents    = pfd_flags;
    sp_ctx->pc_orig_socket  = lsock;
    sp_ctx->pc_event        = event;
    sp_ctx->pc_max_peers    = max_peers;
    sp_ctx->pc_num_peers    = 0;
    sp_ctx->pc_one_shot_cb  = one_shot_cb;
    sp_ctx->pc_one_shot_ctx = one_shot_ctx;

    rv = cpe_event_add(event);
    if (rv != APR_SUCCESS) {
        return rv;
    }
    return APR_SUCCESS;
}
Пример #5
0
/*! Start a connect (async) and once done install an event/callback
 * associated to the connected socket.
 *
 * @param csock        connecting socket, created by cpe_socket_client_create()
 * @param sockaddr     address infos, created by cpe_socket_client_create()
 * @param timeous_us   optional timeout in us to connect. 0 Means no timeout.
 * @param callback     callback that will be called on the connected socket
 * @param context      callback argument
 * @param pfd_flags    poll flags for the connected socket
 * @param pool         memory pool to use
 */
apr_status_t
cpe_socket_after_connect(
    apr_socket_t   *csock,
    apr_sockaddr_t *sockaddr,
    apr_time_t      timeout_us,
    cpe_callback_t  callback,
    void           *context,
    apr_int16_t     pfd_flags,
    cpe_callback_t  one_shot_cb,
    void           *one_shot_ctx,
    apr_pool_t     *pool)
{
    apr_status_t            rv;
    cpe_event              *event;
    cpe_socket_prepare_ctx *ctx;
    int                     nonblock;

    /* Enforce contract. */
    apr_socket_opt_get(csock, APR_SO_NONBLOCK, &nonblock);
    assert(nonblock == 1);

    /*
     * Setup event/callback for connecting socket.
     */
    cpe_log(CPE_DEB, "%s", "creating event for connecting socket");
    ctx = apr_palloc(pool, sizeof *ctx);
    if (ctx == NULL) {
        return APR_EGENERAL;
    }
    event = cpe_event_fdesc_create(APR_POLL_SOCKET, APR_POLLOUT,
        (apr_descriptor) csock, timeout_us, cpe_socket_connect_cb, ctx);
    if (event == NULL) {
        return APR_EGENERAL;
    }
    ctx->pc_callback     = callback;
    ctx->pc_ctx1         = context;
    ctx->pc_reqevents    = pfd_flags;
    ctx->pc_orig_socket  = csock;
    ctx->pc_event        = event;
    ctx->pc_one_shot_cb  = one_shot_cb;
    ctx->pc_one_shot_ctx = one_shot_ctx;

    CHECK(cpe_event_add(event));

    rv = apr_socket_connect(csock, sockaddr);
    if (rv != APR_SUCCESS && ! APR_STATUS_IS_EINPROGRESS(rv)) {
        cpe_log(CPE_DEB, "apr_socket_connect %s", cpe_errmsg(rv));
        return rv;
    }
    return APR_SUCCESS;
}
Пример #6
0
static void corkable(abts_case *tc, void *data)
{
#if !APR_HAVE_CORKABLE_TCP
    ABTS_NOT_IMPL(tc, "TCP isn't corkable");
#else
    apr_status_t rv;
    apr_int32_t ck;

    rv = apr_socket_opt_set(sock, APR_TCP_NODELAY, 1);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    ABTS_INT_EQUAL(tc, 1, ck);

    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);

    rv = apr_socket_opt_get(sock, APR_TCP_NOPUSH, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    ABTS_INT_EQUAL(tc, 1, ck);

    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    /* TCP_NODELAY is now in an unknown state; it may be zero if
     * TCP_NOPUSH and TCP_NODELAY are mutually exclusive on this
     * platform, e.g. Linux < 2.6. */

    rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    
    rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck);
    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
    ABTS_INT_EQUAL(tc, 1, ck);
#endif
}
Пример #7
0
static void set_debug(abts_case *tc, void *data)
{
    apr_status_t rv1, rv2;
    apr_int32_t ck;
    
    /* On some platforms APR_SO_DEBUG can only be set as root; just test
     * for get/set consistency of this option. */
    rv1 = apr_socket_opt_set(sock, APR_SO_DEBUG, 1);
    rv2 = apr_socket_opt_get(sock, APR_SO_DEBUG, &ck);
    APR_ASSERT_SUCCESS(tc, "get SO_DEBUG option", rv2);
    if (rv1 == APR_SUCCESS) {
        ABTS_INT_EQUAL(tc, 1, ck);
    } else {
        ABTS_INT_EQUAL(tc, 0, ck);
    }
}
Пример #8
0
static void set_debug(CuTest *tc)
{
    apr_status_t rv1, rv2;
    apr_int32_t ck;

    /* On some platforms APR_SO_DEBUG can only be set as root; just test
     * for get/set consistency of this option. */
    rv1 = apr_socket_opt_set(sock, APR_SO_DEBUG, 1);
    rv2 = apr_socket_opt_get(sock, APR_SO_DEBUG, &ck);
    apr_assert_success(tc, "get SO_DEBUG option", rv2);
    if (APR_STATUS_IS_SUCCESS(rv1)) {
        CuAssertIntEquals(tc, 1, ck);
    } else {
        CuAssertIntEquals(tc, 0, ck);
    }
}
Пример #9
0
static int socket_opt_get(lua_State *L)
{
  apr_status_t status;
  lua_apr_socket *object;
  apr_int32_t option, value;

  object = socket_check(L, 1, 1);
  option = option_check(L, 2);
  status = apr_socket_opt_get(object->handle, option, &value);
  if (status != APR_SUCCESS)
    return push_error_status(L, status);
  else if (option == APR_SO_SNDBUF || option == APR_SO_RCVBUF)
    lua_pushinteger(L, value);
  else
    lua_pushboolean(L, value);
  return 1;
}
Пример #10
0
static APR_INLINE apr_status_t APR_THREAD_FUNC
uxp_socket_opt_get(apr_socket_t *sock, apr_int32_t opt, apr_int32_t *on)
{
    tcn_uxp_conn_t *con = (tcn_uxp_conn_t *)sock;
    return apr_socket_opt_get(con->sock, opt, on);
}
Пример #11
0
/*
 * worker_main()
 * Main entry point for the worker threads. Worker threads block in
 * win*_get_connection() awaiting a connection to service.
 */
static unsigned int __stdcall worker_main(void *thread_num_val)
{
    static int requests_this_child = 0;
    PCOMP_CONTEXT context = NULL;
    int thread_num = (int)thread_num_val;
    ap_sb_handle_t *sbh;

    while (1) {
        conn_rec *c;
        apr_int32_t disconnected;

        ap_update_child_status_from_indexes(0, thread_num, SERVER_READY, NULL);

        /* Grab a connection off the network */
        if (use_acceptex) {
            context = winnt_get_connection(context);
        }
        else {
            context = win9x_get_connection(context);
        }

        if (!context) {
            /* Time for the thread to exit */
            break;
        }

        /* Have we hit MaxRequestPerChild connections? */
        if (ap_max_requests_per_child) {
            requests_this_child++;
            if (requests_this_child > ap_max_requests_per_child) {
                SetEvent(max_requests_per_child_event);
            }
        }

        ap_create_sb_handle(&sbh, context->ptrans, 0, thread_num);
        c = ap_run_create_connection(context->ptrans, ap_server_conf,
                                     context->sock, thread_num, sbh,
                                     context->ba);

        if (c) {
            ap_process_connection(c, context->sock);
            apr_socket_opt_get(context->sock, APR_SO_DISCONNECTED,
                               &disconnected);
            if (!disconnected) {
                context->accept_socket = INVALID_SOCKET;
                ap_lingering_close(c);
            }
            else if (!use_acceptex) {
                /* If the socket is disconnected but we are not using acceptex,
                 * we cannot reuse the socket. Disconnected sockets are removed
                 * from the apr_socket_t struct by apr_sendfile() to prevent the
                 * socket descriptor from being inadvertently closed by a call
                 * to apr_socket_close(), so close it directly.
                 */
                closesocket(context->accept_socket);
                context->accept_socket = INVALID_SOCKET;
            }
        }
        else {
            /* ap_run_create_connection closes the socket on failure */
            context->accept_socket = INVALID_SOCKET;
        }
    }

    ap_update_child_status_from_indexes(0, thread_num, SERVER_DEAD,
                                        (request_rec *) NULL);

    return 0;
}
Пример #12
0
/*
 * worker_main()
 * Main entry point for the worker threads. Worker threads block in
 * win*_get_connection() awaiting a connection to service.
 */
static DWORD __stdcall worker_main(void *thread_num_val)
{
    apr_thread_t *thd;
    apr_os_thread_t osthd;
    static int requests_this_child = 0;
    winnt_conn_ctx_t *context = NULL;
    int thread_num = (int)thread_num_val;
    ap_sb_handle_t *sbh;
    apr_bucket *e;
    int rc;
    conn_rec *c;
    apr_int32_t disconnected;

    osthd = apr_os_thread_current();

    while (1) {

        ap_update_child_status_from_indexes(0, thread_num, SERVER_READY, NULL);

        /* Grab a connection off the network */
        context = winnt_get_connection(context);

        if (!context) {
            /* Time for the thread to exit */
            break;
        }

        /* Have we hit MaxConnectionsPerChild connections? */
        if (ap_max_requests_per_child) {
            requests_this_child++;
            if (requests_this_child > ap_max_requests_per_child) {
                SetEvent(max_requests_per_child_event);
            }
        }

        e = context->overlapped.Pointer;

        ap_create_sb_handle(&sbh, context->ptrans, 0, thread_num);
        c = ap_run_create_connection(context->ptrans, ap_server_conf,
                                     context->sock, thread_num, sbh,
                                     context->ba);

        if (!c)
        {
            /* ap_run_create_connection closes the socket on failure */
            context->accept_socket = INVALID_SOCKET;
            if (e)
                apr_bucket_free(e);
            continue;
        }

        thd = NULL;
        apr_os_thread_put(&thd, &osthd, context->ptrans);
        c->current_thread = thd;

        /* follow ap_process_connection(c, context->sock) logic
         * as it left us no chance to reinject our first data bucket.
         */
        ap_update_vhost_given_ip(c);

        rc = ap_run_pre_connection(c, context->sock);
        if (rc != OK && rc != DONE) {
            c->aborted = 1;
        }

        if (e && c->aborted)
        {
            apr_bucket_free(e);
        }
        else
        {
            ap_set_module_config(c->conn_config, &mpm_winnt_module, context);
        }

        if (!c->aborted)
        {
            ap_run_process_connection(c);

            apr_socket_opt_get(context->sock, APR_SO_DISCONNECTED,
                               &disconnected);

            if (!disconnected) {
                context->accept_socket = INVALID_SOCKET;
                ap_lingering_close(c);
            }
        }
    }

    ap_update_child_status_from_indexes(0, thread_num, SERVER_DEAD,
                                        (request_rec *) NULL);

    return 0;
}
Пример #13
0
apr_status_t apr_getsocketopt(apr_socket_t *sock,
                              apr_int32_t opt, apr_int32_t *on)
{
    return apr_socket_opt_get(sock, opt, on);
}