X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jcc.c;h=4b3e4ebaa3985096254740dc8aa6fb7beb8ff95c;hb=c1106aa0f9d5e26d68c852bc1ef02beb088562d9;hp=e76358ba447e03080ea2a928b12b0dff00c2bc8d;hpb=8ef1cce0e3dfe6b68730d19d68cbb628219ebf39;p=privoxy.git diff --git a/jcc.c b/jcc.c index e76358ba..4b3e4eba 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.184 2008/08/22 15:34:45 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.187 2008/09/07 12:35:05 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,16 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.184 2008/08/22 15:34:45 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * Revision 1.187 2008/09/07 12:35:05 fabiankeil + * Add mutex lock support for _WIN32. + * + * Revision 1.186 2008/09/04 08:13:58 fabiankeil + * Prepare for critical sections on Windows by adding a + * layer of indirection before the pthread mutex functions. + * + * Revision 1.185 2008/08/30 12:03:07 fabiankeil + * Remove FEATURE_COOKIE_JAR. + * * Revision 1.184 2008/08/22 15:34:45 fabiankeil * - Silence LLVM/Clang complaint. * - Make received_hup_signal static. @@ -1167,27 +1177,31 @@ static int32 server_thread(void *data); #define sleep(N) DosSleep(((N) * 100)) #endif -#ifdef FEATURE_PTHREAD -pthread_mutex_t log_mutex; -pthread_mutex_t log_init_mutex; +#ifdef MUTEX_LOCKS_AVAILABLE +/* + * XXX: Does the locking stuff really belong in this file? + */ +privoxy_mutex_t log_mutex; +privoxy_mutex_t log_init_mutex; +privoxy_mutex_t connection_reuse_mutex; #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) -pthread_mutex_t resolver_mutex; +privoxy_mutex_t resolver_mutex; #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */ #ifndef HAVE_GMTIME_R -pthread_mutex_t gmtime_mutex; +privoxy_mutex_t gmtime_mutex; #endif /* ndef HAVE_GMTIME_R */ #ifndef HAVE_LOCALTIME_R -pthread_mutex_t localtime_mutex; +privoxy_mutex_t localtime_mutex; #endif /* ndef HAVE_GMTIME_R */ #ifndef HAVE_RANDOM -pthread_mutex_t rand_mutex; +privoxy_mutex_t rand_mutex; #endif /* ndef HAVE_RANDOM */ -#endif /* FEATURE_PTHREAD */ +#endif /* def MUTEX_LOCKS_AVAILABLE */ #if defined(unix) const char *basedir = NULL; @@ -1960,6 +1974,52 @@ static jb_err change_request_destination(struct client_state *csp) } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE +/********************************************************************* + * + * Function : server_response_is_complete + * + * Description : Determines whether we should stop reading + * from the server socket. + * + * Parameters : + * 1 : csp = Current client state (buffers, headers, etc...) + * + * Returns : TRUE if the response is complete, + * FALSE otherwise. + * + *********************************************************************/ +static int server_response_is_complete(struct client_state *csp) +{ + int content_length_known = (csp->flags & CSP_FLAG_CONTENT_LENGTH_SET); + + if (!strcmpic(csp->http->gpc, "HEAD")) + { + /* + * "HEAD" implies no body, we are thus expecting + * no content. XXX: incomplete "list" of methods? + */ + log_error(LOG_LEVEL_INFO, "Method %s implies no body.", csp->http->gpc); + csp->expected_content_length = 0; + content_length_known = TRUE; + } + + if (csp->http->status == 304) + { + /* + * Expect no body. XXX: incomplete "list" of status codes? + */ + log_error(LOG_LEVEL_INFO, "Status code %d implies no body.", csp->http->status); + csp->expected_content_length = 0; + content_length_known = TRUE; + } + + return (content_length_known && ((0 == csp->expected_content_length) + || (csp->expected_content_length <= (csp->iob->eod - csp->iob->cur)))); +} +#endif /* FEATURE_CONNECTION_KEEP_ALIVE */ + + /********************************************************************* * * Function : chat @@ -2450,6 +2510,22 @@ static void chat(struct client_state *csp) FD_SET(csp->cfd, &rfds); FD_SET(csp->sfd, &rfds); +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (server_body && server_response_is_complete(csp)) + { + log_error(LOG_LEVEL_CONNECT, + "Stopped reading from server. Expected content length: %d. " + "Actual content length: %d. Most recently received: %d.", + csp->expected_content_length, (csp->iob->eod - csp->iob->cur), len); + len = 0; + /* + * XXX: should not jump around, + * chat() is complicated enough already. + */ + goto reading_done; + } +#endif /* FEATURE_CONNECTION_KEEP_ALIVE */ + n = select((int)maxfd+1, &rfds, NULL, NULL, NULL); if (n < 0) @@ -2530,6 +2606,10 @@ static void chat(struct client_state *csp) return; } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + reading_done: +#endif /* FEATURE_CONNECTION_KEEP_ALIVE */ + /* Add a trailing zero. This lets filter_popups * use string operations. */ @@ -2890,7 +2970,19 @@ static void serve(struct client_state *csp) if (csp->sfd != JB_INVALID_SOCKET) { +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)) + { + remember_connection(csp->sfd, csp->http, forward_url(csp, csp->http)); + } + else + { + forget_connection(csp->sfd); + close_socket(csp->sfd); + } +#else close_socket(csp->sfd); +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ } csp->flags &= ~CSP_FLAG_ACTIVE; @@ -2952,6 +3044,97 @@ static void usage(const char *myname) #endif /* #if !defined(_WIN32) || defined(_WIN_CONSOLE) */ +#ifdef MUTEX_LOCKS_AVAILABLE +/********************************************************************* + * + * Function : privoxy_mutex_lock + * + * Description : Locks a mutex. + * + * Parameters : + * 1 : mutex = The mutex to lock. + * + * Returns : Void. May exit in case of errors. + * + *********************************************************************/ +void privoxy_mutex_lock(privoxy_mutex_t *mutex) +{ +#ifdef FEATURE_PTHREAD + int err = pthread_mutex_lock(mutex); + if (err) + { + if (mutex != &log_mutex) + { + log_error(LOG_LEVEL_FATAL, + "Mutex locking failed: %s.\n", strerror(err)); + } + exit(1); + } +#else + EnterCriticalSection(mutex); +#endif /* def FEATURE_PTHREAD */ +} + + +/********************************************************************* + * + * Function : privoxy_mutex_unlock + * + * Description : Unlocks a mutex. + * + * Parameters : + * 1 : mutex = The mutex to unlock. + * + * Returns : Void. May exit in case of errors. + * + *********************************************************************/ +void privoxy_mutex_unlock(privoxy_mutex_t *mutex) +{ +#ifdef FEATURE_PTHREAD + int err = pthread_mutex_unlock(mutex); + if (err) + { + if (mutex != &log_mutex) + { + log_error(LOG_LEVEL_FATAL, + "Mutex unlocking failed: %s.\n", strerror(err)); + } + exit(1); + } +#else + LeaveCriticalSection(mutex); +#endif /* def FEATURE_PTHREAD */ +} + + +/********************************************************************* + * + * Function : privoxy_mutex_init + * + * Description : Prepares a mutex. + * + * Parameters : + * 1 : mutex = The mutex to initialize. + * + * Returns : Void. May exit in case of errors. + * + *********************************************************************/ +static void privoxy_mutex_init(privoxy_mutex_t *mutex) +{ +#ifdef FEATURE_PTHREAD + int err = pthread_mutex_init(mutex, 0); + if (err) + { + printf("Fatal error. Mutex initialization failed: %s.\n", + strerror(err)); + exit(1); + } +#else + InitializeCriticalSection(mutex); +#endif /* def FEATURE_PTHREAD */ +} +#endif /* def MUTEX_LOCKS_AVAILABLE */ + /********************************************************************* * * Function : initialize_mutexes @@ -2965,15 +3148,13 @@ static void usage(const char *myname) *********************************************************************/ static void initialize_mutexes(void) { - int err = 0; - -#ifdef FEATURE_PTHREAD +#ifdef MUTEX_LOCKS_AVAILABLE /* * Prepare global mutex semaphores */ - err = pthread_mutex_init(&log_mutex, 0); - - if (!err) err = pthread_mutex_init(&log_init_mutex, 0); + privoxy_mutex_init(&log_mutex); + privoxy_mutex_init(&log_init_mutex); + privoxy_mutex_init(&connection_reuse_mutex); /* * XXX: The assumptions below are a bit naive @@ -2984,37 +3165,24 @@ static void initialize_mutexes(void) * thread safe. */ #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) - if (!err) err = pthread_mutex_init(&resolver_mutex, 0); + privoxy_mutex_init(&resolver_mutex); #endif /* !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_GETHOSTBYNAME_R) */ /* * XXX: should we use a single mutex for * localtime() and gmtime() as well? */ #ifndef HAVE_GMTIME_R - if (!err) err = pthread_mutex_init(&gmtime_mutex, 0); + privoxy_mutex_init(&gmtime_mutex); #endif /* ndef HAVE_GMTIME_R */ #ifndef HAVE_LOCALTIME_R - if (!err) err = pthread_mutex_init(&localtime_mutex, 0); + privoxy_mutex_init(&localtime_mutex); #endif /* ndef HAVE_GMTIME_R */ #ifndef HAVE_RANDOM - if (!err) err = pthread_mutex_init(&rand_mutex, 0); + privoxy_mutex_init(&rand_mutex); #endif /* ndef HAVE_RANDOM */ -#endif /* FEATURE_PTHREAD */ - - /* - * TODO: mutex support for mingw32 would be swell. - */ - - if (err) - { - printf("Fatal error. Mutex initialization failed: %s.\n", - strerror(err)); - exit(1); - } - - return; +#endif /* def MUTEX_LOCKS_AVAILABLE */ } @@ -3230,15 +3398,6 @@ int main(int argc, const char *argv[]) random_seed = (unsigned int)time(NULL); #ifdef HAVE_RANDOM srandom(random_seed); -#elif defined (_WIN32) - /* - * See pick_from_range() in miscutil.c for details. - */ - log_error(LOG_LEVEL_INFO, - "No thread-safe PRNG implemented for your platform. " - "Using weak \'randomization\' factor which will " - "limit the already questionable usefulness of " - "header-time-randomizing actions (disabled by default)."); #else srand(random_seed); #endif /* ifdef HAVE_RANDOM */ @@ -3552,6 +3711,14 @@ static void listen_loop(void) config = load_config(); +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + /* + * XXX: Should be relocated once it no + * longer needs to emit log messages. + */ + initialize_reusable_connections(); +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + bfd = bind_port_helper(config); #ifdef FEATURE_GRACEFUL_TERMINATION