connection.c revision 7184de27ec1d62a83c41cdeac0953ca9fd661e8c
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#include "apr.h"
e8f95a682820a599fe41b22977010636be5c2717jim#include "apr_strings.h"
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh
9d129b55f5a43abf43865c6b0eb6dd19bc22aba8ianh#include "ap_config.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "httpd.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "http_connection.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_request.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_protocol.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "ap_mpm.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_config.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_core.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "http_vhost.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "scoreboard.h"
2d71630471d1c23f0137309e3c3957c633ecbfd6rbb#include "http_log.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#include "util_filter.h"
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAPR_HOOK_STRUCT(
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_HOOK_LINK(create_connection)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_HOOK_LINK(process_connection)
51af95bb51b5084e883bad250b2afa2838e9ceebfielding APR_HOOK_LINK(pre_connection)
d4f1d9c1ff112a8ab9bee31f196973761329b236rbb)
7fae9cc4639013f3c04c085547256c68814aee8ftrawickAP_IMPLEMENT_HOOK_RUN_FIRST(conn_rec *,create_connection,
7fae9cc4639013f3c04c085547256c68814aee8ftrawick (apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc),
7fae9cc4639013f3c04c085547256c68814aee8ftrawick (p, server, csd, conn_id, sbh, alloc), NULL)
7fae9cc4639013f3c04c085547256c68814aee8ftrawickAP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/*
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * More machine-dependent networking gooo... on some systems,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * you've got to be *really* sure that all the packets are acknowledged
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * before closing the connection, since the client will not be able
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to see the last response if their TCP buffer is flushed by a RST
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * packet from us, which is what the server's TCP stack will send
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * if it receives any request data after closing the connection.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * In an ideal world, this function would be accomplished by simply
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * setting the socket option SO_LINGER and handling it within the
785be1b6298010956622771c870ab3cd8ca57a2faaron * server's TCP stack while the process continues on to the next request.
785be1b6298010956622771c870ab3cd8ca57a2faaron * Unfortunately, it seems that most (if not all) operating systems
785be1b6298010956622771c870ab3cd8ca57a2faaron * block the server process on close() when SO_LINGER is used.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * For those that don't, see USE_SO_LINGER below. For the rest,
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * we have created a home-brew lingering_close.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * Many operating systems tend to block, puke, or otherwise mishandle
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * calls to shutdown only half of the connection. You should define
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * NO_LINGCLOSE in ap_config.h if such is the case for your system.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifndef MAX_SECS_TO_LINGER
785be1b6298010956622771c870ab3cd8ca57a2faaron#define MAX_SECS_TO_LINGER 30
785be1b6298010956622771c870ab3cd8ca57a2faaron#endif
785be1b6298010956622771c870ab3cd8ca57a2faaron
785be1b6298010956622771c870ab3cd8ca57a2faaronAP_CORE_DECLARE(void) ap_flush_conn(conn_rec *c)
785be1b6298010956622771c870ab3cd8ca57a2faaron{
785be1b6298010956622771c870ab3cd8ca57a2faaron apr_bucket_brigade *bb;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_bucket *b;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
f4b96a996afbc46872f57ad1450e6ee1c8f13707jorton bb = apr_brigade_create(c->pool, c->bucket_alloc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* FLUSH bucket */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding b = apr_bucket_flush_create(c->bucket_alloc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_BRIGADE_INSERT_TAIL(bb, b);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* End Of Connection bucket */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding b = ap_bucket_eoc_create(c->bucket_alloc);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding APR_BRIGADE_INSERT_TAIL(bb, b);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_pass_brigade(c->output_filters, bb);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding}
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding/* we now proceed to read from the client until we get EOF, or until
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * MAX_SECS_TO_LINGER has passed. the reasons for doing this are
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * documented in a draft:
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-connection-00.txt
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding *
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * in a nutshell -- if we don't make this effort we risk causing
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * TCP RST packets to be sent which can tear down a connection before
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * all the response data has been sent to the client.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#define SECONDS_TO_LINGER 2
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fieldingAP_DECLARE(void) ap_lingering_close(conn_rec *c)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding{
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding char dummybuf[512];
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_size_t nbytes;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_time_t timeup = 0;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_socket_t *csd = ap_get_core_module_config(c->conn_config);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (!csd) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_update_child_status(c->sbh, SERVER_CLOSING, NULL);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#ifdef NO_LINGCLOSE
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_flush_conn(c); /* just close it */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_socket_close(csd);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding#endif
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Close the connection, being careful to send out whatever is still
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * in our buffers. If possible, try to avoid a hard close until the
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * client has ACKed our FIN and/or has stopped sending us data.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Send any leftover data to the client, but never try to again */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding ap_flush_conn(c);
45acd673a68181802b112e97e84fa3813ddd3ec1stoddard
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (c->aborted) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_socket_close(csd);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Shut down the socket for write, which will send a FIN
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding * to the peer.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding if (apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding || c->aborted) {
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_socket_close(csd);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding return;
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding }
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding /* Read available data from the client whilst it continues sending
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm * it, for a maximum time of MAX_SECS_TO_LINGER. If the client
e8f95a682820a599fe41b22977010636be5c2717jim * does not send any data within 2 seconds (a value pulled from
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * Apache 1.3 which seems to work well), give up.
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick apr_socket_timeout_set(csd, apr_time_from_sec(SECONDS_TO_LINGER));
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding apr_socket_opt_set(csd, APR_INCOMPLETE_READ, 1);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick /* The common path here is that the initial apr_socket_recv() call
58fd79b56eb624bf011772994e9761d3c2e228c1orlikowski * will return 0 bytes read; so that case must avoid the expensive
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick * apr_time_now() call and time arithmetic. */
8a261a9f7d18d1e862d63f68e93f288d3e1f0d94trawick
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding do {
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick nbytes = sizeof(dummybuf);
785be1b6298010956622771c870ab3cd8ca57a2faaron if (apr_socket_recv(csd, dummybuf, &nbytes) || nbytes == 0)
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding break;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick if (timeup == 0) {
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames /*
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * First time through;
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * calculate now + 30 seconds (MAX_SECS_TO_LINGER).
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames *
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * If some module requested a shortened waiting period, only wait for
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * 2s (SECONDS_TO_LINGER). This is useful for mitigating certain
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames * DoS attacks.
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames */
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames if (apr_table_get(c->notes, "short-lingering-close")) {
e160b861b50a3a8dcc013b8cd3ef849fe777e52fgregames timeup = apr_time_now() + apr_time_from_sec(SECONDS_TO_LINGER);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick else {
560f6ac786d611b858b2bad932713d9e971f0716trawick timeup = apr_time_now() + apr_time_from_sec(MAX_SECS_TO_LINGER);
560f6ac786d611b858b2bad932713d9e971f0716trawick }
560f6ac786d611b858b2bad932713d9e971f0716trawick continue;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick }
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick } while (apr_time_now() < timeup);
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp apr_socket_close(csd);
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp return;
7bf77d70b6830636bc36e6b76a228c301be23ff7brianp}
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawickAP_CORE_DECLARE(void) ap_process_connection(conn_rec *c, void *csd)
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick{
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick int rc;
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick ap_update_vhost_given_ip(c);
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding
09fe0b69d3d1e8c8041c9ce99ee77b8b44b5e3b1fielding rc = ap_run_pre_connection(c, csd);
eae32ab3fb398ca408bc2d45b22adf1b67a75471rbb if (rc != OK && rc != DONE) {
39b76a07959a0a332366c735a23894d9e8ed6872trawick c->aborted = 1;
de00ec7378227d05be63ecd2053ebbb01b940023jorton }
f3aa436e29aa30e29695a18b7f469dd66b39b7e4jorton
de00ec7378227d05be63ecd2053ebbb01b940023jorton if (!c->aborted) {
de00ec7378227d05be63ecd2053ebbb01b940023jorton ap_run_process_connection(c);
785be1b6298010956622771c870ab3cd8ca57a2faaron }
785be1b6298010956622771c870ab3cd8ca57a2faaron}
6b38fca3ec543a0f72efd5683e91a0b30fc752d1trawick
39b76a07959a0a332366c735a23894d9e8ed6872trawick