X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=jcc.c;h=2d96ac9fdcad3a4f2341ae3d918c7de42b2ee90b;hb=f4464cf737ef3de89c27a86c20595bebc802b29a;hp=5a05d08660bcff7ec8f18a8479ce350475a8e39a;hpb=7c7592fae8bbc71e2b255289e5a1eebd752e4dfc;p=privoxy.git diff --git a/jcc.c b/jcc.c index 5a05d086..2d96ac9f 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.173 2008/05/06 15:09:00 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.186 2008/09/04 08:13:58 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -33,6 +33,56 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.173 2008/05/06 15:09:00 fabiankeil Exp $" * * Revisions : * $Log: jcc.c,v $ + * 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. + * - Hide definitions for basedir, pidfile and received_hup_signal + * from __EMX__ as they only seem to be used in case of #ifdef unix. + * + * Revision 1.183 2008/08/21 07:09:35 fabiankeil + * Accept Shoutcast responses again. Problem reported + * and fix suggested by Stefan in #2062860. + * + * Revision 1.182 2008/06/27 11:13:56 fabiankeil + * Fix possible NULL-pointer dereference reported + * by din_a4 in #2003937. Pointy hat to me. + * + * Revision 1.181 2008/05/21 15:47:15 fabiankeil + * Streamline sed()'s prototype and declare + * the header parse and add structures static. + * + * Revision 1.180 2008/05/21 15:26:32 fabiankeil + * - Mark csp as immutable for send_crunch_response(). + * - Fix comment spelling. + * + * Revision 1.179 2008/05/20 20:13:32 fabiankeil + * Factor update_server_headers() out of sed(), ditch the + * first_run hack and make server_patterns_light static. + * + * Revision 1.178 2008/05/10 13:23:38 fabiankeil + * Don't provide get_header() with the whole client state + * structure when it only needs access to csp->iob. + * + * Revision 1.177 2008/05/10 11:51:12 fabiankeil + * Make the "read the rest of the headers" loop a bit more readable. + * + * Revision 1.176 2008/05/10 11:37:57 fabiankeil + * - Instead of logging when the IIS5 hack is enabled, log when it fails. + * - Remove useless comment. + * + * Revision 1.175 2008/05/09 18:53:59 fabiankeil + * Fix comment grammar. + * + * Revision 1.174 2008/05/07 18:05:53 fabiankeil + * Remove the pointless buffer in client_protocol_is_unsupported(). + * * Revision 1.173 2008/05/06 15:09:00 fabiankeil * Least-effort fix for bug #1821930 (reported by Lee): * If the response doesn't look like HTTP, @@ -1091,7 +1141,7 @@ static int client_protocol_is_unsupported(const struct client_state *csp, char * static jb_err get_request_destination_elsewhere(struct client_state *csp, struct list *headers); static jb_err get_server_headers(struct client_state *csp); static const char *crunch_reason(const struct http_response *rsp); -static void send_crunch_response(struct client_state *csp, struct http_response *rsp); +static void send_crunch_response(const struct client_state *csp, struct http_response *rsp); /* * static int request_contains_null_bytes(const struct client_state *csp, char *buf, int len); */ @@ -1124,32 +1174,35 @@ 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; #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) || defined(__EMX__) +#if defined(unix) const char *basedir = NULL; const char *pidfile = NULL; -int received_hup_signal = 0; +static int received_hup_signal = 0; #endif /* defined unix */ /* HTTP snipplets. */ @@ -1258,6 +1311,13 @@ static const struct cruncher crunchers_light[] = { }; +/* + * XXX: Don't we really mean + * + * #if defined(unix) + * + * here? + */ #if !defined(_WIN32) && !defined(__OS2__) && !defined(AMIGA) /********************************************************************* * @@ -1291,7 +1351,9 @@ static void sig_handler(int the_signal) break; case SIGHUP: +#if defined(unix) received_hup_signal = 1; +#endif break; default: @@ -1467,7 +1529,7 @@ static jb_err get_server_headers(struct client_state *csp) int continue_hack_in_da_house = 0; char * header; - while (((header = get_header(csp)) != NULL) || continue_hack_in_da_house) + while (((header = get_header(csp->iob)) != NULL) || continue_hack_in_da_house) { if (header == NULL) { @@ -1484,7 +1546,7 @@ static jb_err get_server_headers(struct client_state *csp) { /* * It's a bodyless continue response, don't - * stop header parsing after reaching it's end. + * stop header parsing after reaching its end. * * As a result Privoxy will concatenate the * next response's head and parse and deliver @@ -1518,7 +1580,6 @@ static jb_err get_server_headers(struct client_state *csp) return JB_ERR_PARSE; } - /* Enlist header */ if (JB_ERR_MEMORY == enlist(csp->headers, header)) { /* @@ -1611,7 +1672,7 @@ static const char *crunch_reason(const struct http_response *rsp) * Returns : Nothing. * *********************************************************************/ -static void send_crunch_response(struct client_state *csp, struct http_response *rsp) +static void send_crunch_response(const struct client_state *csp, struct http_response *rsp) { const struct http_request *http = csp->http; char status_code[4]; @@ -1894,10 +1955,15 @@ static jb_err change_request_destination(struct client_state *csp) log_error(LOG_LEVEL_ERROR, "Couldn't parse rewritten request: %s.", jb_err_to_string(err)); } - http->ocmd = strdup(http->cmd); /* XXX: ocmd is a misleading name */ - if (http->ocmd == NULL) + else { - log_error(LOG_LEVEL_FATAL, "Out of memory copying rewritten HTTP request line"); + /* XXX: ocmd is a misleading name */ + http->ocmd = strdup(http->cmd); + if (http->ocmd == NULL) + { + log_error(LOG_LEVEL_FATAL, + "Out of memory copying rewritten HTTP request line"); + } } return err; @@ -1976,7 +2042,7 @@ static void chat(struct client_state *csp) return; } - req = get_header(csp); + req = get_header(csp->iob); } while ((NULL != req) && ('\0' == *req)); @@ -2064,8 +2130,20 @@ static void chat(struct client_state *csp) init_list(headers); for (;;) { - if ( ( ( p = get_header(csp) ) != NULL) && ( *p == '\0' ) ) + p = get_header(csp->iob); + + if (p == NULL) + { + /* There are no additional headers to read. */ + break; + } + + if (*p == '\0') { + /* + * We didn't receive a complete header + * line yet, get the rest of it. + */ len = read_socket(csp->cfd, buf, sizeof(buf) - 1); if (len <= 0) { @@ -2074,23 +2152,25 @@ static void chat(struct client_state *csp) return; } - /* - * If there is no memory left for buffering the - * request, there is nothing we can do but hang up - */ if (add_to_iob(csp, buf, len)) { + /* + * If there is no memory left for buffering the + * request, there is nothing we can do but hang up + */ destroy_list(headers); return; } - continue; } - - if (p == NULL) break; - - enlist(headers, p); - freez(p); - + else + { + /* + * We were able to read a complete + * header and can finaly enlist it. + */ + enlist(headers, p); + freez(p); + } } if (http->host == NULL) @@ -2145,7 +2225,7 @@ static void chat(struct client_state *csp) list_append_list_unique(csp->headers, headers); destroy_list(headers); - err = sed(client_patterns, add_client_headers, csp); + err = sed(csp, FILTER_CLIENT_HEADERS); if (JB_ERR_OK != err) { assert(err == JB_ERR_PARSE); @@ -2506,9 +2586,10 @@ static void chat(struct client_state *csp) csp->content_length = (size_t)(csp->iob->eod - csp->iob->cur); } - if (JB_ERR_OK != sed(server_patterns_light, NULL, csp)) + if (JB_ERR_OK != update_server_headers(csp)) { - log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); + log_error(LOG_LEVEL_FATAL, + "Failed to update server headers. after filtering."); } hdr = list_to_text(csp->headers); @@ -2518,12 +2599,6 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } - /* - * Shouldn't happen because this was the second sed run - * and tags are only created for the first one. - */ - assert(!crunch_response_triggered(csp, crunchers_all)); - if (write_socket(csp->cfd, hdr, strlen(hdr)) || write_socket(csp->cfd, p != NULL ? p : csp->iob->cur, csp->content_length)) { @@ -2544,9 +2619,6 @@ static void chat(struct client_state *csp) * This is NOT the body, so * Let's pretend the server just sent us a blank line. */ - log_error(LOG_LEVEL_INFO, - "Malformerd HTTP headers detected and MS IIS5 hack enabled. " - "Expect an invalid response or even no response at all."); snprintf(buf, sizeof(buf), "\r\n"); len = (int)strlen(buf); @@ -2659,6 +2731,8 @@ static void chat(struct client_state *csp) * and there isn't anything * we can do about it. */ + log_error(LOG_LEVEL_INFO, + "MS IIS5 hack didn't produce valid headers."); break; } else @@ -2684,10 +2758,11 @@ static void chat(struct client_state *csp) assert(csp->headers->first->str); assert(!http->ssl); - if (strncmpic(csp->headers->first->str, "HTTP", 4)) + if (strncmpic(csp->headers->first->str, "HTTP", 4) && + strncmpic(csp->headers->first->str, "ICY", 3)) { /* - * It doesn't look like a HTTP response: + * It doesn't look like a HTTP (or Shoutcast) response: * tell the client and log the problem. */ if (strlen(csp->headers->first->str) > 30) @@ -2705,10 +2780,11 @@ static void chat(struct client_state *csp) return; } - /* we have now received the entire header. + /* + * We have now received the entire server header, * filter it and send the result to the client */ - if (JB_ERR_OK != sed(server_patterns, add_server_headers, csp)) + if (JB_ERR_OK != sed(csp, FILTER_SERVER_HEADERS)) { log_error(LOG_LEVEL_FATAL, "Failed to parse server headers."); } @@ -2774,6 +2850,8 @@ static void chat(struct client_state *csp) */ if (ms_iis5_hack) { + log_error(LOG_LEVEL_INFO, + "Closed server connection detected with MS IIS5 hack enabled."); break; } } @@ -2884,6 +2962,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 @@ -2897,15 +3066,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); + privoxy_mutex_init(&log_mutex); - if (!err) err = pthread_mutex_init(&log_init_mutex, 0); + privoxy_mutex_init(&log_init_mutex); /* * XXX: The assumptions below are a bit naive @@ -2916,37 +3083,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 */ } @@ -3004,7 +3158,7 @@ int main(int argc, const char *argv[]) * Parse the command line arguments * * XXX: simply printing usage information in case of - * invalid arguments isn't particular user friendly. + * invalid arguments isn't particularly user friendly. */ while (++argc_pos < argc) { @@ -3162,15 +3316,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 */ @@ -3515,23 +3660,6 @@ static void listen_loop(void) } #endif -#ifdef __OS2__ -#ifdef FEATURE_COOKIE_JAR - /* - * Need a workaround here: we have to fclose() the jarfile, or we die because it's - * already open. I think unload_configfile() is not being run, which should do - * this work. Until that can get resolved, we'll use this workaround. - */ - if (csp) - if(csp->config) - if (csp->config->jar) - { - fclose(csp->config->jar); - csp->config->jar = NULL; - } -#endif /* FEATURE_COOKIE_JAR */ -#endif /* __OS2__ */ - if ( NULL == (csp = (struct client_state *) zalloc(sizeof(*csp))) ) { log_error(LOG_LEVEL_FATAL, "malloc(%d) for csp failed: %E", sizeof(*csp)); @@ -3829,13 +3957,6 @@ static void listen_loop(void) #endif freez(configfile); -#ifdef FEATURE_COOKIE_JAR - if (NULL != config->jar) - { - fclose(config->jar); - } -#endif - #if defined(_WIN32) && !defined(_WIN_CONSOLE) /* Cleanup - remove taskbar icon etc. */ TermLogWindow();