-const char jcc_rcs[] = "$Id: jcc.c,v 1.235 2009/03/18 21:01:20 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.244 2009/04/17 11:34:34 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
*
* Revisions :
* $Log: jcc.c,v $
+ * Revision 1.244 2009/04/17 11:34:34 fabiankeil
+ * Style cosmetics for the IPv6 code.
+ *
+ * Revision 1.243 2009/04/17 11:27:49 fabiankeil
+ * Petr Pisar's privoxy-3.0.12-ipv6-3.diff.
+ *
+ * Revision 1.242 2009/04/11 10:44:47 fabiankeil
+ * Update a comment. We're not in Kansas anymore.
+ *
+ * Revision 1.241 2009/04/11 10:37:23 fabiankeil
+ * When dropping connections due to ACL, don't leak csp->ip_addr_str.
+ *
+ * Revision 1.240 2009/04/09 10:12:54 fabiankeil
+ * Fix two cases in which an invalid server response would result
+ * in the client connection being closed without sending an error
+ * message first.
+ *
+ * Revision 1.239 2009/04/07 11:43:50 fabiankeil
+ * If the server rudely resets the connection directly after sending the
+ * headers, pass the mess to the client instead of sending an incorrect
+ * connect-failed message. Fixes #2698674 reported by mybugaccount.
+ *
+ * Revision 1.238 2009/03/27 14:42:30 fabiankeil
+ * Correct the status code for CONNECTION_TIMEOUT_RESPONSE.
+ *
+ * Revision 1.237 2009/03/27 14:32:04 fabiankeil
+ * If spawning a child in listen_loop() fails, send a real
+ * HTTP response to the client and continue listening for
+ * new connections without artificial delay.
+ *
+ * Revision 1.236 2009/03/25 17:30:24 fabiankeil
+ * In serve(), keep the client socket open until we marked the
+ * server socket as unused. This should increase the chances
+ * that we reuse the connection for the client's next request
+ * to the same destination.
+ *
* Revision 1.235 2009/03/18 21:01:20 fabiankeil
* Comment fix. Spotted by Roland.
*
"Connection: close\r\n\r\n"
"Bad request. Messed up with header filters.\r\n";
+static const char TOO_MANY_CONNECTIONS_RESPONSE[] =
+ "HTTP/1.0 503 Too many open connections\r\n"
+ "Proxy-Agent: Privoxy " VERSION "\r\n"
+ "Content-Type: text/plain\r\n"
+ "Connection: close\r\n\r\n"
+ "Maximum number of open connections reached.\r\n";
+
/* XXX: should be a template */
static const char CONNECTION_TIMEOUT_RESPONSE[] =
- "HTTP/1.0 502 Connection timeout\r\n"
+ "HTTP/1.0 504 Connection timeout\r\n"
"Proxy-Agent: Privoxy " VERSION "\r\n"
"Content-Type: text/plain\r\n"
"Connection: close\r\n\r\n"
if (fwd->forward_host)
{
- log_error(LOG_LEVEL_CONNECT, "via %s:%d to: %s",
+ log_error(LOG_LEVEL_CONNECT, "via [%s]:%d to: %s",
fwd->forward_host, fwd->forward_port, http->hostport);
}
else
mark_server_socket_tainted(csp);
return;
}
-
- rsp = error_response(csp, "connect-failed", errno);
- if (rsp)
- {
- send_crunch_response(csp, rsp);
- }
-
- return;
+ /*
+ * XXX: Consider handling the cases above the same.
+ */
+ mark_server_socket_tainted(csp);
+ len = 0;
}
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
* The header is incomplete and there isn't anything
* we can do about it.
*/
- log_error(LOG_LEVEL_INFO,
- "MS IIS5 hack didn't produce valid headers.");
- break;
+ log_error(LOG_LEVEL_ERROR, "Invalid server headers. "
+ "Applying the MS IIS5 hack didn't help.");
+ log_error(LOG_LEVEL_CLF,
+ "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
+ write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ mark_server_socket_tainted(csp);
+ return;
}
else
{
*/
if (ms_iis5_hack)
{
- log_error(LOG_LEVEL_INFO,
- "Closed server connection detected with MS IIS5 hack enabled.");
- break;
+ log_error(LOG_LEVEL_ERROR,
+ "Closed server connection detected. "
+ "Applying the MS IIS5 hack didn't help.");
+ log_error(LOG_LEVEL_CLF,
+ "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
+ write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
+ strlen(INVALID_SERVER_HEADERS_RESPONSE));
+ mark_server_socket_tainted(csp);
+ return;
}
}
continue;
{
struct client_state *csp = NULL;
jb_socket bfd;
- struct configuration_spec * config;
+ struct configuration_spec *config;
+ unsigned int active_threads = 0;
config = load_config();
/*
* Free data that was used by died threads
*/
- sweep();
+ active_threads = sweep();
#if defined(unix)
/*
{
/*
* Since we were listening to the "old port", we will not see
- * a "listen" param change until the next IJB request. So, at
+ * a "listen" param change until the next request. So, at
* least 1 more request must be made for us to find the new
* setting. I am simply closing the old socket and binding the
* new one.
{
log_error(LOG_LEVEL_CONNECT, "Connection from %s dropped due to ACL", csp->ip_addr_str);
close_socket(csp->cfd);
+ freez(csp->ip_addr_str);
freez(csp);
continue;
}
#endif /* def FEATURE_ACL */
+ if ((0 != config->max_client_connections)
+ && (active_threads >= config->max_client_connections))
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "Rejecting connection from %s. Maximum number of connections reached.",
+ csp->ip_addr_str);
+ write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
+ strlen(TOO_MANY_CONNECTIONS_RESPONSE));
+ close_socket(csp->cfd);
+ freez(csp->ip_addr_str);
+ freez(csp);
+ continue;
+ }
+
/* add it to the list of clients */
csp->next = clients->next;
clients->next = csp;
#undef SELECTED_ONE_OPTION
/* end of cpp switch () */
- if (child_id < 0) /* failed */
+ if (child_id < 0)
{
- char buf[BUFFER_SIZE];
-
- log_error(LOG_LEVEL_ERROR, "can't fork: %E");
-
- snprintf(buf , sizeof(buf), "Privoxy: can't fork: errno = %d", errno);
-
- write_socket(csp->cfd, buf, strlen(buf));
+ /*
+ * Spawning the child failed, assume it's because
+ * there are too many children running already.
+ * XXX: If you assume ...
+ */
+ log_error(LOG_LEVEL_ERROR,
+ "Unable to take any additional connections: %E");
+ write_socket(csp->cfd, TOO_MANY_CONNECTIONS_RESPONSE,
+ strlen(TOO_MANY_CONNECTIONS_RESPONSE));
close_socket(csp->cfd);
csp->flags &= ~CSP_FLAG_ACTIVE;
- sleep(5);
- continue;
}
}
else