* 20120211.54 (2.4.19-dev) Add ap_proxy_buckets_lifetime_transform and
* ap_proxy_transfer_between_connections to
* mod_proxy.h
+ * 20120211.55 (2.4.19-dev) Add new ap_update_child_status...() methods,
+ * add protocol to worker_score in scoreboard.h,
+ * Add pre_close connection hook and
+ * ap_prep_lingering_close().
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 54 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 55 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
*/
AP_DECLARE(void) ap_lingering_close(conn_rec *c);
+AP_DECLARE(int) ap_prep_lingering_close(conn_rec *c);
+
AP_DECLARE(int) ap_start_lingering_close(conn_rec *c);
/* Hooks */
*/
AP_DECLARE_HOOK(int,process_connection,(conn_rec *c))
+/**
+ * This hook implements different protocols. Before a connection is closed,
+ * protocols might have to perform some housekeeping actions, such as
+ * sending one last goodbye packet. The connection is, unless some other
+ * error already happened before, still open and operational.
+ * All pre-close-connection hooks are run until one returns something
+ * other than ok or decline
+ * @param c The connection on which the request has been received.
+ * @return OK or DECLINED
+ */
+AP_DECLARE_HOOK(int,pre_close_connection,(conn_rec *c))
+
/** End Of Connection (EOC) bucket */
AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eoc;
char client[32]; /* Keep 'em small... */
char request[64]; /* We just want an idea... */
char vhost[32]; /* What virtual host is being accessed? */
+ char protocol[16]; /* What protocol is used on the connection? */
};
typedef struct {
AP_DECLARE(int) ap_update_child_status_from_indexes(int child_num, int thread_num,
int status, request_rec *r);
AP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status, conn_rec *c);
+AP_DECLARE(int) ap_update_child_status_from_server(ap_sb_handle_t *sbh, int status,
+ conn_rec *c, server_rec *s);
+AP_DECLARE(int) ap_update_child_status_descr(ap_sb_handle_t *sbh, int status, const char *descr);
+
AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status);
AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh);
#endif
"<th>SS</th><th>Req</th>"
"<th>Conn</th><th>Child</th><th>Slot</th>"
- "<th>Client</th><th>VHost</th>"
+ "<th>Client</th><th>Protocol</th><th>VHost</th>"
"<th>Request</th></tr>\n\n", r);
for (i = 0; i < server_limit; ++i) {
format_byte_out(r, bytes);
ap_rputs(")\n", r);
ap_rprintf(r,
- " <i>%s {%s}</i> <b>[%s]</b><br />\n\n",
+ " <i>%s {%s}</i> <i>(%s)</i> <b>[%s]</b><br />\n\n",
ap_escape_html(r->pool,
ws_record->client),
ap_escape_html(r->pool,
ap_escape_logitem(r->pool,
ws_record->request)),
+ ap_escape_html(r->pool,
+ ws_record->protocol),
ap_escape_html(r->pool,
ws_record->vhost));
}
(float)conn_bytes / KBYTE, (float) my_bytes / MBYTE,
(float)bytes / MBYTE);
- ap_rprintf(r, "</td><td>%s</td><td nowrap>%s</td>"
+ ap_rprintf(r, "</td><td>%s</td><td>%s</td><td nowrap>%s</td>"
"<td nowrap>%s</td></tr>\n\n",
ap_escape_html(r->pool,
ws_record->client),
+ ap_escape_html(r->pool,
+ ws_record->protocol),
ap_escape_html(r->pool,
ws_record->vhost),
ap_escape_html(r->pool,
#include "ssl_private.h"
#include "mod_ssl.h"
#include "util_md5.h"
+#include "scoreboard.h"
static void ssl_configure_env(request_rec *r, SSLConnRec *sslconn);
#ifdef HAVE_TLSEXT
sslcon->server = s;
sslcon->cipher_suite = sc->server->auth.cipher_suite;
+ ap_update_child_status_from_server(c->sbh, SERVER_BUSY_READ, c, s);
/*
* There is one special filter callback, which is set
* very early depending on the base_server's log level.
APR_HOOK_LINK(create_connection)
APR_HOOK_LINK(process_connection)
APR_HOOK_LINK(pre_connection)
+ APR_HOOK_LINK(pre_close_connection)
)
AP_IMPLEMENT_HOOK_RUN_FIRST(conn_rec *,create_connection,
(apr_pool_t *p, server_rec *server, apr_socket_t *csd, long conn_id, void *sbh, apr_bucket_alloc_t *alloc),
(p, server, csd, conn_id, sbh, alloc), NULL)
AP_IMPLEMENT_HOOK_RUN_FIRST(int,process_connection,(conn_rec *c),(c),DECLINED)
AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_connection,(conn_rec *c, void *csd),(c, csd),OK,DECLINED)
+AP_IMPLEMENT_HOOK_RUN_ALL(int,pre_close_connection,(conn_rec *c),(c),OK,DECLINED)
+
/*
* More machine-dependent networking gooo... on some systems,
* you've got to be *really* sure that all the packets are acknowledged
(void)ap_shutdown_conn(c, 1);
}
+AP_DECLARE(int) ap_prep_lingering_close(conn_rec *c)
+{
+ /* Give protocol handlers one last chance to raise their voice */
+ ap_run_pre_close_connection(c);
+
+ if (c->sbh) {
+ ap_update_child_status(c->sbh, SERVER_CLOSING, NULL);
+ }
+ return 0;
+}
+
/* we now proceed to read from the client until we get EOF, or until
* MAX_SECS_TO_LINGER has passed. The reasons for doing this are
* documented in a draft:
return 1;
}
- if (c->sbh) {
- ap_update_child_status(c->sbh, SERVER_CLOSING, NULL);
+ if (ap_prep_lingering_close(c)) {
+ return 1;
}
-
+
#ifdef NO_LINGCLOSE
ap_flush_conn(c); /* just close it */
apr_socket_close(csd);
conn_rec *c = cs->c;
apr_socket_t *csd = cs->pfd.desc.s;
- if (c->aborted
+ if (ap_prep_lingering_close(c)
+ || c->aborted
|| ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted
|| apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) {
apr_socket_close(csd);
#include "http_main.h"
#include "http_core.h"
#include "http_config.h"
+#include "http_protocol.h"
#include "ap_mpm.h"
#include "scoreboard.h"
int thread_num,
int status,
conn_rec *c,
- request_rec *r)
+ server_rec *s,
+ request_rec *r,
+ const char *descr)
{
int old_status;
worker_score *ws;
ws = &ap_scoreboard_image->servers[child_num][thread_num];
old_status = ws->status;
- ws->status = status;
-
- ps = &ap_scoreboard_image->parent[child_num];
-
- if (status == SERVER_READY
- && old_status == SERVER_STARTING) {
- ws->thread_num = child_num * thread_limit + thread_num;
- ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation);
- ps->generation = mpm_generation;
+ if (status >= 0) {
+ ws->status = status;
+
+ ps = &ap_scoreboard_image->parent[child_num];
+
+ if (status == SERVER_READY
+ && old_status == SERVER_STARTING) {
+ ws->thread_num = child_num * thread_limit + thread_num;
+ ap_mpm_query(AP_MPMQ_GENERATION, &mpm_generation);
+ ps->generation = mpm_generation;
+ }
}
if (ap_extended_status) {
- ws->last_used = apr_time_now();
+ const char *val;
+
if (status == SERVER_READY || status == SERVER_DEAD) {
/*
* Reset individual counters
}
ws->conn_count = 0;
ws->conn_bytes = 0;
+ ws->last_used = apr_time_now();
}
- if (r) {
- const char *client = ap_get_remote_host(c, r->per_dir_config,
- REMOTE_NOLOOKUP, NULL);
- if (!client || !strcmp(client, c->client_ip)) {
- apr_cpystrn(ws->client, r->useragent_ip, sizeof(ws->client));
+ if (status == SERVER_READY) {
+ ws->client[0]='\0';
+ ws->vhost[0]='\0';
+ ws->request[0]='\0';
+ ws->protocol[0]='\0';
+ }
+ else {
+ if (descr) {
+ apr_cpystrn(ws->request, descr, sizeof(ws->request));
}
- else {
- apr_cpystrn(ws->client, client, sizeof(ws->client));
+ else if (r) {
+ copy_request(ws->request, sizeof(ws->request), r);
}
- copy_request(ws->request, sizeof(ws->request), r);
- if (r->server) {
- apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",
- r->server->server_hostname,
- r->connection->local_addr->port);
+ if (r || c) {
+ val = ap_get_remote_host(c, r? r->per_dir_config : NULL,
+ REMOTE_NOLOOKUP, NULL);
+ if (r && (!val || !strcmp(val, c->client_ip))) {
+ apr_cpystrn(ws->client, r->useragent_ip, sizeof(ws->client));
+ }
+ else {
+ apr_cpystrn(ws->client, val, sizeof(ws->client));
+ }
+ }
+ if (s) {
+ if (c) {
+ apr_snprintf(ws->vhost, sizeof(ws->vhost), "%s:%d",
+ s->server_hostname, c->local_addr->port);
+ }
+ else {
+ apr_cpystrn(ws->vhost, s->server_hostname, sizeof(ws->vhost));
+ }
+ }
+ if (c) {
+ val = ap_get_protocol(c);
+ apr_cpystrn(ws->protocol, val, sizeof(ws->protocol));
}
- }
- else if (c) {
- apr_cpystrn(ws->client, ap_get_remote_host(c, NULL,
- REMOTE_NOLOOKUP, NULL), sizeof(ws->client));
- ws->request[0]='\0';
- ws->vhost[0]='\0';
}
}
return update_child_status_internal(child_num, thread_num, status,
r ? r->connection : NULL,
- r);
+ r ? r->server : NULL,
+ r, NULL);
}
AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status,
return update_child_status_internal(sbh->child_num, sbh->thread_num,
status,
r ? r->connection : NULL,
- r);
+ r ? r->server : NULL,
+ r, NULL);
}
AP_DECLARE(int) ap_update_child_status_from_conn(ap_sb_handle_t *sbh, int status,
- conn_rec *c)
+ conn_rec *c)
+{
+ if (!sbh || (sbh->child_num < 0))
+ return -1;
+
+ return update_child_status_internal(sbh->child_num, sbh->thread_num,
+ status, c, NULL, NULL, NULL);
+}
+
+AP_DECLARE(int) ap_update_child_status_from_server(ap_sb_handle_t *sbh, int status,
+ conn_rec *c, server_rec *s)
+{
+ if (!sbh || (sbh->child_num < 0))
+ return -1;
+
+ return update_child_status_internal(sbh->child_num, sbh->thread_num,
+ status, c, s, NULL, NULL);
+}
+
+AP_DECLARE(int) ap_update_child_status_descr(ap_sb_handle_t *sbh, int status, const char *descr)
{
if (!sbh || (sbh->child_num < 0))
return -1;
return update_child_status_internal(sbh->child_num, sbh->thread_num,
- status, c, NULL);
+ status, NULL, NULL, NULL, descr);
}
AP_DECLARE(void) ap_time_process_request(ap_sb_handle_t *sbh, int status)
ws = &ap_scoreboard_image->servers[sbh->child_num][sbh->thread_num];
if (status == START_PREQUEST) {
- ws->start_time = apr_time_now();
+ ws->start_time = ws->last_used = apr_time_now();
}
else if (status == STOP_PREQUEST) {
- ws->stop_time = apr_time_now();
+ ws->stop_time = ws->last_used = apr_time_now();
}
}
dest->client[sizeof(dest->client) - 1] = '\0';
dest->request[sizeof(dest->request) - 1] = '\0';
dest->vhost[sizeof(dest->vhost) - 1] = '\0';
+ dest->protocol[sizeof(dest->protocol) - 1] = '\0';
}
AP_DECLARE(process_score *) ap_get_scoreboard_process(int x)