-const char jcc_rcs[] = "$Id: jcc.c,v 1.284 2009/09/06 14:07:56 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.293 2009/09/18 18:52:33 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
*********************************************************************/
static void mark_server_socket_tainted(struct client_state *csp)
{
- if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE))
+ if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
+ && !(csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED))
{
log_error(LOG_LEVEL_CONNECT,
"Marking the server socket %d tainted.", csp->sfd);
/* Skeleton for HTTP response, if we should intercept the request */
struct http_response *rsp;
struct timeval timeout;
+ int watch_client_socket = 1;
memset(buf, 0, sizeof(buf));
FD_ZERO(&rfds);
#endif
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
- if ((csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
+ if (!watch_client_socket)
{
maxfd = csp->sfd;
}
else
#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
{
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
- if (http->ssl == 0)
- {
- log_error(LOG_LEVEL_CONNECT,
- "Allowing the client to continue talking. "
- "Expecting %llu bytes.", csp->expected_client_content_length);
- }
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
FD_SET(csp->cfd, &rfds);
}
}
if (server_body && server_response_is_complete(csp, byte_count))
{
- log_error(LOG_LEVEL_CONNECT,
- "Done reading from server. Expected content length: %llu. "
- "Actual content length: %llu. Most recently received: %d.",
- csp->expected_content_length, byte_count, len);
+ if (csp->expected_content_length == byte_count)
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Done reading from server. Content length: %llu as expected. "
+ "Bytes most recently read: %d.",
+ byte_count, len);
+ }
+ else
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Done reading from server. Expected content length: %llu. "
+ "Actual content length: %llu. Bytes most recently read: %d.",
+ csp->expected_content_length, byte_count, len);
+ }
len = 0;
/*
* XXX: should not jump around,
*/
if (FD_ISSET(csp->cfd, &rfds))
{
- unsigned max_bytes_to_read = sizeof(buf) - 1;
+ int max_bytes_to_read = sizeof(buf) - 1;
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ if ((csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ))
+ {
+ if (data_is_available(csp->cfd, 0))
+ {
+ /*
+ * If the next request is already waiting, we have
+ * to stop select()ing the client socket. Otherwise
+ * we would always return right away and get nothing
+ * else done.
+ */
+ watch_client_socket = 0;
+ log_error(LOG_LEVEL_CONNECT,
+ "Stopping to watch the client socket. "
+ "There's already another request waiting.");
+ continue;
+ }
+ /*
+ * If the client socket is set, but there's no data
+ * available on the socket, the client went fishing
+ * and continuing talking to the server makes no sense.
+ */
+ log_error(LOG_LEVEL_CONNECT, "The client closed socket %d while "
+ "the server socket %d is still open.", csp->cfd, csp->sfd);
+ mark_server_socket_tainted(csp);
+ break;
+ }
if (csp->expected_client_content_length != 0)
{
if (csp->expected_client_content_length < (sizeof(buf) - 1))
{
- max_bytes_to_read = csp->expected_client_content_length;
+ max_bytes_to_read = (int)csp->expected_client_content_length;
}
log_error(LOG_LEVEL_CONNECT,
"Waiting for up to %d bytes from the client.",
if (csp->expected_client_content_length != 0)
{
assert(len <= max_bytes_to_read);
- csp->expected_client_content_length -= len;
+ csp->expected_client_content_length -= (unsigned)len;
log_error(LOG_LEVEL_CONNECT,
"Expected client content length set to %llu "
"after reading %d bytes.",
* we can parse the headers we just continue here.
*/
log_error(LOG_LEVEL_CONNECT,
- "Continuing buffering headers. Most recently received: %d",
+ "Continuing buffering headers. Bytes most recently read: %d.",
len);
continue;
}
static int monitor_thread_running = 0;
#endif /* def FEATURE_CONNECTION_SHARING */
int continue_chatting = 0;
- unsigned int latency = 0;
do
{
+ unsigned int latency;
+
chat(csp);
+ latency = (unsigned)(csp->server_connection.response_received -
+ csp->server_connection.request_sent);
+
continue_chatting = (csp->config->feature_flags
& RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
&& (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
&& (socket_is_still_usable(csp->sfd)))
{
+ time_t time_open = time(NULL) - csp->server_connection.timestamp;
+
+ if (csp->server_connection.keep_alive_timeout < time_open + latency)
+ {
+ break;
+ }
+
remember_connection(csp, forward_url(csp, csp->http));
csp->sfd = JB_INVALID_SOCKET;
close_socket(csp->cfd);
*
*********************************************************************/
#ifdef __MINGW32__
-int real_main(int argc, const char *argv[])
+int real_main(int argc, char **argv)
#else
-int main(int argc, const char *argv[])
+int main(int argc, char **argv)
#endif
{
int argc_pos = 0;