*/
AP_CORE_DECLARE(conn_rec *)ap_new_connection(apr_pool_t *ptrans, server_rec *server,
apr_socket_t *csd, long id, void *sbh);
+
/**
* This is the protocol module driver. This calls all of the
* pre-connection and connection hooks for all protocol modules.
* @param c The connection on which the request is read
* @deffunc void ap_process_connection(conn_rec *)
*/
-AP_CORE_DECLARE(void) ap_process_connection(conn_rec *);
+AP_CORE_DECLARE(void) ap_process_connection(conn_rec *, apr_socket_t *csd);
AP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c);
#endif
/* Hooks */
+/**
+ * This hook is used to install the bottom most input and output
+ * filters (e.g., CORE_IN and CORE_OUT) used to interface to the
+ * network. This filter is a RUN_FIRST hook that runs right before
+ * the pre_connection filter. This filter hook can use vhost
+ * configuration to influence its operation.
+ * @param c The socket to the client
+ * @param csd Pointer to the client apr_socket_t struct.
+ * @return OK or DECLINED
+ * @deffunc int ap_run_install_transport_filters(conn_rec *c, apr_socket_t *csd)
+ */
+AP_DECLARE_HOOK(int, install_transport_filters, (conn_rec *c, apr_socket_t *csd))
+
/**
* This hook gives protocol modules an opportunity to set everything up
* before calling the protocol handler. All pre-connection hooks are
void *vhost_lookup_data;
/* Information about the connection itself */
-
- /** Connection to the client */
- apr_socket_t *client_socket;
-
/** local address */
apr_sockaddr_t *local_addr;
/** remote address */
typedef struct core_filter_ctx {
apr_bucket_brigade *b;
} core_ctx_t;
+
+typedef struct core_net_rec {
+ /** Connection to the client */
+ apr_socket_t *client_socket;
+
+ /** connection record */
+ conn_rec *c;
+
+ core_output_filter_ctx_t *out_ctx;
+ core_ctx_t *in_ctx;
+} core_net_rec;
/**
* Examine a field value (such as a media-/content-type) string and return
static apr_port_t http_port(const request_rec *r)
{ return DEFAULT_HTTP_PORT; }
-static int ap_pre_http_connection(conn_rec *c)
-{
- ap_add_input_filter_handle(ap_core_input_filter_handle, NULL, NULL, c);
- ap_add_output_filter_handle(ap_core_output_filter_handle, NULL, NULL, c);
- return OK;
-}
+
static int ap_process_http_connection(conn_rec *c)
{
request_rec *r;
static void register_hooks(apr_pool_t *p)
{
- ap_hook_pre_connection(ap_pre_http_connection,NULL,NULL,
- APR_HOOK_REALLY_LAST);
ap_hook_process_connection(ap_process_http_connection,NULL,NULL,
APR_HOOK_REALLY_LAST);
ap_hook_map_to_storage(ap_send_http_trace,NULL,NULL,APR_HOOK_MIDDLE);
APR_HOOK_STRUCT(
APR_HOOK_LINK(pre_connection)
APR_HOOK_LINK(process_connection)
+ APR_HOOK_LINK(install_transport_filters)
)
AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c),(c),OK,DECLINED)
AP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED)
+AP_IMPLEMENT_HOOK_RUN_FIRST(int, install_transport_filters,
+ (conn_rec *c, apr_socket_t *csd),(c, csd), DECLINED)
/*
* More machine-dependent networking gooo... on some systems,
apr_status_t rc;
apr_int32_t timeout;
apr_int32_t total_linger_time = 0;
- apr_socket_t *csd = c->client_socket;
+ apr_socket_t *csd = ap_get_module_config(c->conn_config, &core_module);
if (!csd) {
return;
return;
}
-AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c)
+AP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, apr_socket_t *csd)
{
ap_update_vhost_given_ip(c);
+ ap_run_install_transport_filters(c, csd);
+
ap_run_pre_connection(c);
if (!c->aborted) {
c->sbh = sbh;
(void) ap_update_child_status(c->sbh, SERVER_BUSY_READ, (request_rec *) NULL);
-#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
- /* BillS says perhaps this should be moved to the MPMs. Some OSes
- * allow listening socket attributes to be inherited by the
- * accept sockets which means this call only needs to be made
- * once on the listener
- */
- ap_sock_disable_nagle(csd);
-#endif
-
/* Got a connection structure, so initialize what fields we can
* (the rest are zeroed out by pcalloc).
*/
}
apr_sockaddr_ip_get(&c->remote_ip, c->remote_addr);
c->base_server = server;
- c->client_socket = csd;
c->id = id;
-
return c;
}
*/
#if APR_HAS_SENDFILE
-static apr_status_t sendfile_it_all(conn_rec *c,
+static apr_status_t sendfile_it_all(core_net_rec *c,
apr_file_t *fd,
apr_hdtr_t *hdtr,
apr_off_t file_offset,
* to the network. emulate_sendfile will return only when all the bytes have been
* sent (i.e., it handles partial writes) or on a network error condition.
*/
-static apr_status_t emulate_sendfile(conn_rec *c, apr_file_t *fd,
+static apr_status_t emulate_sendfile(core_net_rec *c, apr_file_t *fd,
apr_hdtr_t *hdtr, apr_off_t offset,
apr_size_t length, apr_size_t *nbytes)
{
apr_off_t readbytes)
{
int keptalive = f->c->keepalive == 1;
- apr_socket_t *csd = f->c->client_socket;
+ apr_socket_t *csd = ap_get_module_config(f->c->conn_config, &core_module);
int *first_line = f->ctx;
if (!f->ctx) {
{
apr_bucket *e;
apr_status_t rv;
- core_ctx_t *ctx = f->ctx;
+ core_net_rec *net = f->ctx;
+ core_ctx_t *ctx = net->in_ctx;
const char *str;
apr_size_t len;
if (!ctx)
{
- f->ctx = ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
+ ctx = apr_pcalloc(f->c->pool, sizeof(*ctx));
ctx->b = apr_brigade_create(f->c->pool);
/* seed the brigade with the client socket. */
- e = apr_bucket_socket_create(f->c->client_socket);
+ e = apr_bucket_socket_create(net->client_socket);
APR_BRIGADE_INSERT_TAIL(ctx->b, e);
+ net->in_ctx = ctx;
}
else if (APR_BRIGADE_EMPTY(ctx->b)) {
/* hit EOF on socket already */
{
apr_status_t rv;
conn_rec *c = f->c;
- core_output_filter_ctx_t *ctx = f->ctx;
+ core_net_rec *net = f->ctx;
+ core_output_filter_ctx_t *ctx = net->out_ctx;
if (ctx == NULL) {
- f->ctx = ctx = apr_pcalloc(c->pool, sizeof(*ctx));
+ ctx = apr_pcalloc(net->c->pool, sizeof(*ctx));
+ net->out_ctx = ctx;
}
/* If we have a saved brigade, concatenate the new brigade to it */
* after the request_pool is cleared.
*/
if (ctx->b == NULL) {
- ctx->b = apr_brigade_create(c->pool);
+ ctx->b = apr_brigade_create(net->c->pool);
}
APR_BRIGADE_FOREACH(bucket, b) {
/* Prepare the socket to be reused */
flags |= APR_SENDFILE_DISCONNECT_SOCKET;
}
- rv = sendfile_it_all(c, /* the network information */
+ rv = sendfile_it_all(net, /* the network information */
fd, /* the file to send */
&hdtr, /* header and trailer iovecs */
foffset, /* offset in the file to begin
#endif
{
apr_size_t unused_bytes_sent;
- rv = emulate_sendfile(c, fd, &hdtr, foffset, flen,
+ rv = emulate_sendfile(net, fd, &hdtr, foffset, flen,
&unused_bytes_sent);
}
fd = NULL;
else {
apr_size_t unused_bytes_sent;
- rv = writev_it_all(c->client_socket,
+ rv = writev_it_all(net->client_socket,
vec, nvec,
nbytes, &unused_bytes_sent);
}
return core_create_req(pr);
}
+static int core_install_transport_filters(conn_rec *c, apr_socket_t *csd)
+{
+ core_net_rec *net = apr_palloc(c->pool, sizeof(*net));
+
+#ifdef AP_MPM_DISABLE_NAGLE_ACCEPTED_SOCK
+ /* BillS says perhaps this should be moved to the MPMs. Some OSes
+ * allow listening socket attributes to be inherited by the
+ * accept sockets which means this call only needs to be made
+ * once on the listener
+ */
+ ap_sock_disable_nagle(csd);
+#endif
+ net->c = c;
+ net->in_ctx = NULL;
+ net->out_ctx = NULL;
+ net->client_socket = csd;
+
+ ap_set_module_config(net->c->conn_config, &core_module, csd);
+ ap_add_input_filter("CORE_IN", net, NULL, net->c);
+ ap_add_output_filter("CORE", net, NULL, net->c);
+ return OK;
+}
+
static void register_hooks(apr_pool_t *p)
{
+ ap_hook_install_transport_filters(core_install_transport_filters, NULL,
+ NULL, APR_HOOK_REALLY_LAST);
ap_hook_post_config(core_post_config,NULL,NULL,APR_HOOK_REALLY_FIRST);
ap_hook_translate_name(ap_core_translate,NULL,NULL,APR_HOOK_REALLY_LAST);
ap_hook_map_to_storage(core_map_to_storage,NULL,NULL,APR_HOOK_REALLY_LAST);
current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, sock);
ap_lingering_close(current_conn);
}
}
ap_create_sb_handle(&sbh, p, conn_id / thread_limit, thread_num);
current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, sock);
ap_lingering_close(current_conn);
}
}
current_conn = ap_new_connection(pconn, ap_server_conf, worker_args->conn_sd, conn_id, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, worker_args->conn_sd);
ap_lingering_close(current_conn);
}
current_conn = ap_new_connection(ptrans, ap_server_conf, csd,
my_worker_num, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, csd);
ap_lingering_close(current_conn);
}
request_count++;
ap_create_sb_handle(&sbh, p, conn_id / thread_limit, thread_num);
current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, sock);
ap_lingering_close(current_conn);
}
}
thread_num, sbh);
if (c) {
- ap_process_connection(c);
+ ap_process_connection(c, context->sock);
apr_getsocketopt(context->sock, APR_SO_DISCONNECTED, &disconnected);
if (!disconnected) {
context->accept_socket = INVALID_SOCKET;
current_conn = ap_new_connection(p, ap_server_conf, sock, conn_id, sbh);
if (current_conn) {
- ap_process_connection(current_conn);
+ ap_process_connection(current_conn, sock);
ap_lingering_close(current_conn);
}
}