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 }
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); }
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); }
/*! 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; }
/*! 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; }
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 }
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); } }
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); } }
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; }
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); }
/* * 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; }
/* * 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; }
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); }