-const char jcc_rcs[] = "$Id: jcc.c,v 1.448 2016/12/24 15:58:49 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.456 2017/05/25 11:16:56 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/jcc.c,v $
* Purpose : Main file. Contains main() method, main loop, and
* the main connection-handling function.
*
- * Copyright : Written by and Copyright (C) 2001-2016 the
+ * Copyright : Written by and Copyright (C) 2001-2017 the
* Privoxy team. http://www.privoxy.org/
*
* Based on the Internet Junkbuster originally written
# ifdef __OS2__
#define INCL_DOS
# include <os2.h>
-#define bzero(B,N) memset(B,0x00,n)
# endif
+#ifdef HAVE_POLL
+#ifdef __GLIBC__
+#include <sys/poll.h>
+#else
+#include <poll.h>
+#endif /* def __GLIBC__ */
+#else
# ifndef FD_ZERO
# include <select.h>
# endif
+#endif /* HAVE_POLL */
#endif
privoxy_mutex_t localtime_mutex;
#endif /* ndef HAVE_GMTIME_R */
-#ifndef HAVE_RANDOM
+#if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
privoxy_mutex_t rand_mutex;
-#endif /* ndef HAVE_RANDOM */
+#endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
#endif /* def MUTEX_LOCKS_AVAILABLE */
enum chunk_status status;
while (CHUNK_STATUS_MISSING_DATA ==
- (status = chunked_body_is_complete(csp->client_iob,&body_length)))
+ (status = chunked_body_is_complete(csp->client_iob, &body_length)))
{
char buf[BUFFER_SIZE];
int len;
}
+/*********************************************************************
+ *
+ * Function : send_http_request
+ *
+ * Description : Sends the HTTP headers from the client request
+ * and all the body data that has already been received.
+ *
+ * Parameters :
+ * 1 : csp = Current client state (buffers, headers, etc...)
+ *
+ * Returns : 0 on success, anything else is na error.
+ *
+ *********************************************************************/
+static int send_http_request(struct client_state *csp)
+{
+ char *hdr;
+ int write_failure;
+
+ hdr = list_to_text(csp->headers);
+ if (hdr == NULL)
+ {
+ /* FIXME Should handle error properly */
+ log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
+ }
+ list_remove_all(csp->headers);
+
+ /*
+ * Write the client's (modified) header to the server
+ * (along with anything else that may be in the buffer)
+ */
+ write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
+ freez(hdr);
+
+ if (write_failure)
+ {
+ log_error(LOG_LEVEL_CONNECT, "Failed sending request headers to: %s: %E",
+ csp->http->hostport);
+ }
+ else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
+ && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
+ {
+ write_failure = 1;
+ log_error(LOG_LEVEL_CONNECT, "Failed sending request body to: %s: %E",
+ csp->http->hostport);
+ }
+
+ return write_failure;
+
+}
+
+
/*********************************************************************
*
* Function : handle_established_connection
char buf[BUFFER_SIZE];
char *hdr;
char *p;
- fd_set rfds;
int n;
+#ifdef HAVE_POLL
+ struct pollfd poll_fds[2];
+#else
+ fd_set rfds;
jb_socket maxfd;
+ struct timeval timeout;
+#endif
int server_body;
int ms_iis5_hack = 0;
unsigned long long byte_count = 0;
/* Skeleton for HTTP response, if we should intercept the request */
struct http_response *rsp;
- struct timeval timeout;
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
int watch_client_socket;
#endif
http = csp->http;
+#ifndef HAVE_POLL
maxfd = (csp->cfd > csp->server_connection.sfd) ?
csp->cfd : csp->server_connection.sfd;
+#endif
/* pass data between the client and server
* until one or the other shuts down the connection.
for (;;)
{
+#ifndef HAVE_POLL
#ifdef __OS2__
/*
* FD_ZERO here seems to point to an errant macro which crashes.
}
FD_SET(csp->server_connection.sfd, &rfds);
+#endif /* ndef HAVE_POLL */
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
if ((csp->flags & CSP_FLAG_CHUNKED)
}
#endif /* FEATURE_CONNECTION_KEEP_ALIVE */
+#ifdef HAVE_POLL
+ poll_fds[0].fd = csp->cfd;
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+ if (!watch_client_socket)
+ {
+ /*
+ * Ignore incoming data, but still watch out
+ * for disconnects etc. These flags are always
+ * implied anyway but explicitly setting them
+ * doesn't hurt.
+ */
+ poll_fds[0].events = POLLERR|POLLHUP;
+ }
+ else
+#endif
+ {
+ poll_fds[0].events = POLLIN;
+ }
+ poll_fds[1].fd = csp->server_connection.sfd;
+ poll_fds[1].events = POLLIN;
+ n = poll(poll_fds, 2, csp->config->socket_timeout * 1000);
+#else
timeout.tv_sec = csp->config->socket_timeout;
timeout.tv_usec = 0;
n = select((int)maxfd+1, &rfds, NULL, NULL, &timeout);
+#endif /* def HAVE_POLL */
if (n == 0)
{
}
else if (n < 0)
{
+#ifdef HAVE_POLL
+ log_error(LOG_LEVEL_ERROR, "poll() failed!: %E");
+#else
log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
+#endif
mark_server_socket_tainted(csp);
return;
}
* XXX: Make sure the client doesn't use pipelining
* behind Privoxy's back.
*/
+#ifdef HAVE_POLL
+ if ((poll_fds[0].revents & (POLLERR|POLLHUP|POLLNVAL)) != 0)
+ {
+ log_error(LOG_LEVEL_CONNECT,
+ "The client socket %d has become unusable while "
+ "the server socket %d is still open.",
+ csp->cfd, csp->server_connection.sfd);
+ mark_server_socket_tainted(csp);
+ break;
+ }
+
+ if (poll_fds[0].revents != 0)
+#else
if (FD_ISSET(csp->cfd, &rfds))
+#endif /* def HAVE_POLL*/
{
int max_bytes_to_read = sizeof(buf) - 1;
* If `hdr' is null, then it's the header otherwise it's the body.
* FIXME: Does `hdr' really mean `host'? No.
*/
+#ifdef HAVE_POLL
+ if (poll_fds[1].revents != 0)
+#else
if (FD_ISSET(csp->server_connection.sfd, &rfds))
+#endif /* HAVE_POLL */
{
#ifdef FEATURE_CONNECTION_KEEP_ALIVE
/*
*********************************************************************/
static void chat(struct client_state *csp)
{
- char buf[BUFFER_SIZE];
- char *hdr;
const struct forward_spec *fwd;
struct http_request *http;
/* Skeleton for HTTP response, if we should intercept the request */
struct http_response *rsp;
- memset(buf, 0, sizeof(buf));
-
http = csp->http;
if (receive_client_request(csp) != JB_ERR_OK)
}
else if (fwd->forward_host || (http->ssl == 0))
{
- int write_failure;
- hdr = list_to_text(csp->headers);
- if (hdr == NULL)
- {
- /* FIXME Should handle error properly */
- log_error(LOG_LEVEL_FATAL, "Out of memory parsing client header");
- }
- list_remove_all(csp->headers);
-
- /*
- * Write the client's (modified) header to the server
- * (along with anything else that may be in the buffer)
- */
- write_failure = 0 != write_socket(csp->server_connection.sfd, hdr, strlen(hdr));
- freez(hdr);
-
- if (write_failure)
- {
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request headers to: %s: %E", http->hostport);
- }
- else if (((csp->flags & CSP_FLAG_PIPELINED_REQUEST_WAITING) == 0)
- && (flush_socket(csp->server_connection.sfd, csp->client_iob) < 0))
- {
- write_failure = 1;
- log_error(LOG_LEVEL_CONNECT,
- "Failed sending request body to: %s: %E", http->hostport);
- }
-
- if (write_failure)
+ if (send_http_request(csp))
{
rsp = error_response(csp, "connect-failed");
if (rsp)
privoxy_mutex_init(&localtime_mutex);
#endif /* ndef HAVE_GMTIME_R */
-#ifndef HAVE_RANDOM
+#if !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM)
privoxy_mutex_init(&rand_mutex);
-#endif /* ndef HAVE_RANDOM */
+#endif /* !defined(HAVE_ARC4RANDOM) && !defined(HAVE_RANDOM) */
#endif /* def MUTEX_LOCKS_AVAILABLE */
}
{
int argc_pos = 0;
int do_config_test = 0;
+#ifndef HAVE_ARC4RANDOM
unsigned int random_seed;
+#endif
#ifdef unix
struct passwd *pw = NULL;
struct group *grp = NULL;
InitWin32();
#endif
+#ifndef HAVE_ARC4RANDOM
random_seed = (unsigned int)time(NULL);
#ifdef HAVE_RANDOM
srandom(random_seed);
#else
srand(random_seed);
#endif /* ifdef HAVE_RANDOM */
+#endif /* ifndef HAVE_ARC4RANDOM */
/*
* Unix signal handling
*
* Catch the abort, interrupt and terminate signals for a graceful exit
* Catch the hangup signal so the errlog can be reopened.
- * Ignore the broken pipe signals (FIXME: Why?)
+ *
+ * Ignore the broken pipe signal as connection failures
+ * are handled when and where they occur without relying
+ * on a signal.
*/
#if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA)
{
return JB_INVALID_SOCKET;
}
+#ifndef HAVE_POLL
#ifndef _WIN32
if (bfd >= FD_SETSIZE)
{
"Bind socket number too high to use select(): %d >= %d",
bfd, FD_SETSIZE);
}
+#endif
#endif
if (haddr == NULL)