-const char parsers_rcs[] = "$Id: parsers.c,v 1.152 2009/03/01 18:43:48 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.155 2009/05/10 10:12:30 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/parsers.c,v $
*
* Revisions :
* $Log: parsers.c,v $
+ * Revision 1.155 2009/05/10 10:12:30 fabiankeil
+ * Initial keep-alive support for the client socket.
+ * Temporarily disable the server-side-only keep-alive code.
+ *
+ * Revision 1.154 2009/03/13 14:10:07 fabiankeil
+ * Fix some more harmless warnings on amd64.
+ *
+ * Revision 1.153 2009/03/07 13:09:17 fabiankeil
+ * Change csp->expected_content and_csp->expected_content_length from
+ * size_t to unsigned long long to reduce the likelihood of integer
+ * overflows that would let us close the connection prematurely.
+ * Bug found while investigating #2669131, reported by cyberpatrol.
+ *
* Revision 1.152 2009/03/01 18:43:48 fabiankeil
* Help clang understand that we aren't dereferencing
* NULL pointers here.
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
static jb_err server_save_content_length(struct client_state *csp, char **header);
+static jb_err server_keep_alive(struct client_state *csp, char **header);
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
static jb_err client_host_adder (struct client_state *csp);
static jb_err client_xtra_adder (struct client_state *csp);
static jb_err client_x_forwarded_for_adder(struct client_state *csp);
static jb_err client_connection_header_adder(struct client_state *csp);
-static jb_err server_connection_close_adder(struct client_state *csp);
+static jb_err server_connection_adder(struct client_state *csp);
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+static jb_err server_proxy_connection_adder(struct client_state *csp);
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
static jb_err create_forged_referrer(char **header, const char *hostport);
static jb_err create_fake_referrer(char **header, const char *fake_referrer);
{ "TE:", 3, client_te },
{ "Host:", 5, client_host },
{ "if-modified-since:", 18, client_if_modified_since },
+#ifndef FEATURE_CONNECTION_KEEP_ALIVE
{ "Keep-Alive:", 11, crumble },
+#endif
{ "connection:", 11, client_connection },
{ "proxy-connection:", 17, crumble },
{ "max-forwards:", 13, client_max_forwards },
{ "Content-Encoding:", 17, server_content_encoding },
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
{ "Content-Length:", 15, server_save_content_length },
+ { "Keep-Alive:", 11, server_keep_alive },
+#else
+ { "Keep-Alive:", 11, crumble },
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
{ "Transfer-Encoding:", 18, server_transfer_coding },
- { "Keep-Alive:", 11, crumble },
{ "content-disposition:", 20, server_content_disposition },
{ "Last-Modified:", 14, server_last_modified },
{ "*", 0, crunch_server_header },
};
static const add_header_func_ptr add_server_headers[] = {
- server_connection_close_adder,
+ server_connection_adder,
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ server_proxy_connection_adder,
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
NULL
};
* file, the results are not portable.
*
*********************************************************************/
-int flush_socket(jb_socket fd, struct iob *iob)
+long flush_socket(jb_socket fd, struct iob *iob)
{
- int len = iob->eod - iob->cur;
+ long len = iob->eod - iob->cur;
if (len <= 0)
{
* or buffer limit reached.
*
*********************************************************************/
-jb_err add_to_iob(struct client_state *csp, char *buf, int n)
+jb_err add_to_iob(struct client_state *csp, char *buf, long n)
{
struct iob *iob = csp->iob;
size_t used, offset, need, want;
*
* Function : server_connection
*
- * Description : Makes sure that the value of the Connection: header
- * is "close" and signals server_connection_close_adder
- * to do nothing.
+ * Description : Makes sure a proper "Connection:" header is
+ * set and signals connection_header_adder to
+ * do nothing.
*
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*********************************************************************/
static jb_err server_connection(struct client_state *csp, char **header)
{
- char *old_header = *header;
-
/* Do we have a 'Connection: close' header? */
if (strcmpic(*header, "Connection: close"))
{
/* Remember to keep the connection alive. */
csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
}
-#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
+ log_error(LOG_LEVEL_HEADER,
+ "Keeping the server header '%s' around.", *header);
+#else
+ char *old_header = *header;
*header = strdup("Connection: close");
if (header == NULL)
}
log_error(LOG_LEVEL_HEADER, "Replaced: \'%s\' with \'%s\'", old_header, *header);
freez(old_header);
+#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
}
- /* Signal server_connection_close_adder() to return early. */
- csp->flags |= CSP_FLAG_SERVER_CONNECTION_CLOSE_SET;
+ /* Signal server_connection_adder() to return early. */
+ csp->flags |= CSP_FLAG_SERVER_CONNECTION_HEADER_SET;
return JB_ERR_OK;
}
+
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+/*********************************************************************
+ *
+ * Function : server_keep_alive
+ *
+ * Description : Stores the servers keep alive timeout.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ * 2 : header = On input, pointer to header to modify.
+ * On output, pointer to the modified header, or NULL
+ * to remove the header. This function frees the
+ * original string if necessary.
+ *
+ * Returns : JB_ERR_OK.
+ *
+ *********************************************************************/
+static jb_err server_keep_alive(struct client_state *csp, char **header)
+{
+ unsigned int keep_alive_timeout;
+ const char *timeout_position = strstr(*header, "timeout=");
+
+ if ((NULL != timeout_position)
+ && (1 != sscanf(timeout_position, "timeout=%u", &keep_alive_timeout)))
+ {
+ log_error(LOG_LEVEL_ERROR, "Couldn't parse: %s", *header);
+ }
+ else
+ {
+ if (keep_alive_timeout < csp->server_connection.keep_alive_timeout)
+ {
+ log_error(LOG_LEVEL_HEADER,
+ "Reducing keep-alive timeout from %u to %u.",
+ csp->server_connection.keep_alive_timeout, keep_alive_timeout);
+ csp->server_connection.keep_alive_timeout = keep_alive_timeout;
+ }
+ else
+ {
+ /* XXX: Is this log worthy? */
+ log_error(LOG_LEVEL_HEADER,
+ "Server keep-alive timeout is %u. Sticking with %u.",
+ keep_alive_timeout, csp->server_connection.keep_alive_timeout);
+ }
+ }
+
+ return JB_ERR_OK;
+}
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+
+
+
/*********************************************************************
*
* Function : client_connection
*********************************************************************/
static jb_err client_connection(struct client_state *csp, char **header)
{
- char *old_header = *header;
const char *wanted_header = get_appropiate_connection_header(csp);
if (strcmpic(*header, wanted_header))
{
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ log_error(LOG_LEVEL_HEADER,
+ "Keeping the client header '%s' around. "
+ "The connection will not be kept alive.",
+ *header);
+#else
+ char *old_header = *header;
+
*header = strdup(wanted_header);
if (header == NULL)
{
log_error(LOG_LEVEL_HEADER,
"Replaced: \'%s\' with \'%s\'", old_header, *header);
freez(old_header);
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+ }
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ else
+ {
+ log_error(LOG_LEVEL_HEADER,
+ "Keeping the client header '%s' around. "
+ "The server connection will be kept alive if possible.",
+ *header);
+ csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE;
}
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
- /* Signal client_connection_close_adder() to return early. */
+ /* Signal client_connection_adder() to return early. */
csp->flags |= CSP_FLAG_CLIENT_CONNECTION_HEADER_SET;
return JB_ERR_OK;
/*********************************************************************
*
- * Function : server_connection_close_adder
+ * Function : server_connection_adder
*
- * Description : "Temporary" fix for the needed but missing HTTP/1.1
- * support. Adds a "Connection: close" header to csp->headers
+ * Description : Adds an appropiate "Connection:" header to csp->headers
* unless the header was already present. Called from `sed'.
*
- * FIXME: This whole function shouldn't be neccessary!
- *
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*
* JB_ERR_MEMORY on out-of-memory error.
*
*********************************************************************/
-static jb_err server_connection_close_adder(struct client_state *csp)
+static jb_err server_connection_adder(struct client_state *csp)
{
const unsigned int flags = csp->flags;
const char *response_status_line = csp->headers->first->str;
+ const char *wanted_header = get_appropiate_connection_header(csp);
if ((flags & CSP_FLAG_CLIENT_HEADER_PARSING_DONE)
- && (flags & CSP_FLAG_SERVER_CONNECTION_CLOSE_SET))
+ && (flags & CSP_FLAG_SERVER_CONNECTION_HEADER_SET))
{
return JB_ERR_OK;
}
csp->flags |= CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
}
- log_error(LOG_LEVEL_HEADER, "Adding: Connection: close");
+ log_error(LOG_LEVEL_HEADER, "Adding: %s", wanted_header);
- return enlist(csp->headers, "Connection: close");
+ return enlist(csp->headers, wanted_header);
}
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+/*********************************************************************
+ *
+ * Function : server_proxy_connection_adder
+ *
+ * Description : Adds a "Proxy-Connection: keep-alive" header to
+ * csp->headers. XXX: We should reuse existant ones.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : JB_ERR_OK on success, or
+ * JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+static jb_err server_proxy_connection_adder(struct client_state *csp)
+{
+ static const char proxy_connection_header[] = "Proxy-Connection: keep-alive";
+ log_error(LOG_LEVEL_HEADER, "Adding: %s", proxy_connection_header);
+ return enlist(csp->headers, proxy_connection_header);
+}
+#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
+
+
/*********************************************************************
*
* Function : client_connection_header_adder