s@higlight@highlight@
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index eb407a9..6641465 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.190 2008/10/11 14:58:00 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.199 2008/10/26 15:36:10 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -33,6 +33,41 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.190 2008/10/11 14:58:00 fabiankeil Exp $"
  *
  * Revisions   :
  *    $Log: jcc.c,v $
+ *    Revision 1.199  2008/10/26 15:36:10  fabiankeil
+ *    Remove two debug messages with LOG_LEVEL_INFO.
+ *
+ *    Revision 1.198  2008/10/22 15:19:55  fabiankeil
+ *    Once More, With Feeling: if there is no logfile
+ *    because the user didn't specify one, we shouldn't
+ *    call init_error_log() after receiving SIGHUP either.
+ *
+ *    Revision 1.197  2008/10/20 17:02:40  fabiankeil
+ *    If SIGHUP is received while we aren't running in daemon
+ *    mode, calling init_error_log() would be a mistake.
+ *
+ *    Revision 1.196  2008/10/16 09:16:41  fabiankeil
+ *    - Fix two gcc44 conversion warnings.
+ *    - Don't bother logging the last five bytes
+ *      of the 0-chunk.
+ *
+ *    Revision 1.195  2008/10/13 16:04:37  fabiankeil
+ *    Make sure we don't try to reuse tainted server sockets.
+ *
+ *    Revision 1.194  2008/10/12 18:35:18  fabiankeil
+ *    The last commit was a bit too ambitious, apparently the content
+ *    length adjustment is only necessary if we aren't buffering.
+ *
+ *    Revision 1.193  2008/10/12 15:57:35  fabiankeil
+ *    Fix content length calculation if we read headers
+ *    and the start of the body at once. Now that we have
+ *    FEATURE_CONNECTION_KEEP_ALIVE, it actually matters.
+ *
+ *    Revision 1.192  2008/10/11 18:19:14  fabiankeil
+ *    Even more chat() cosmetics.
+ *
+ *    Revision 1.191  2008/10/11 18:00:14  fabiankeil
+ *    Reformat some comments in chat().
+ *
  *    Revision 1.190  2008/10/11 14:58:00  fabiankeil
  *    In case of chunk-encoded content, stop reading if
  *    the buffer looks like it ends with the last chunk.
@@ -2012,7 +2047,6 @@ static int server_response_is_complete(struct client_state *csp, size_t content_
        * "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;
    }
@@ -2022,7 +2056,6 @@ static int server_response_is_complete(struct client_state *csp, size_t content_
       /*
        * 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;
    }
@@ -2466,12 +2499,11 @@ static void chat(struct client_state *csp)
       if (write_socket(csp->sfd, hdr, strlen(hdr))
        || (flush_socket(csp->sfd, csp->iob) <  0))
       {
-         log_error(LOG_LEVEL_CONNECT, "write header to: %s failed: %E",
-                    http->hostport);
+         log_error(LOG_LEVEL_CONNECT,
+            "write header to: %s failed: %E", http->hostport);
 
          rsp = error_response(csp, "connect-failed", errno);
-
-         if(rsp)
+         if (rsp)
          {
             send_crunch_response(csp, rsp);
          }
@@ -2500,7 +2532,7 @@ static void chat(struct client_state *csp)
    /* we're finished with the client's header */
    freez(hdr);
 
-   maxfd = ( csp->cfd > csp->sfd ) ? csp->cfd : csp->sfd;
+   maxfd = (csp->cfd > csp->sfd) ? csp->cfd : csp->sfd;
 
    /* pass data between the client and server
     * until one or the other shuts down the connection.
@@ -2543,7 +2575,7 @@ static void chat(struct client_state *csp)
       if (n < 0)
       {
          log_error(LOG_LEVEL_ERROR, "select() failed!: %E");
-         return;
+         break;
       }
 
       /*
@@ -2562,7 +2594,7 @@ static void chat(struct client_state *csp)
          if (write_socket(csp->sfd, buf, (size_t)len))
          {
             log_error(LOG_LEVEL_ERROR, "write to: %s failed: %E", http->host);
-            return;
+            break;
          }
          continue;
       }
@@ -2574,7 +2606,7 @@ static void chat(struct client_state *csp)
        */
       if (FD_ISSET(csp->sfd, &rfds))
       {
-         fflush( 0 );
+         fflush(0);
          len = read_socket(csp->sfd, buf, sizeof(buf) - 1);
 
          if (len < 0)
@@ -2603,11 +2635,10 @@ static void chat(struct client_state *csp)
                 */
                log_error(LOG_LEVEL_ERROR, "Already forwarded the original headers. "
                   "Unable to tell the client about the problem.");
-               return;
+               break;
             }
 
             rsp = error_response(csp, "connect-failed", errno);
-
             if (rsp)
             {
                send_crunch_response(csp, rsp);
@@ -2623,10 +2654,9 @@ static void chat(struct client_state *csp)
             {
                /* XXX: this is a temporary hack */
                log_error(LOG_LEVEL_CONNECT,
-                  "Looks like we reached the end of the last chunk: "
-                  "%d %d %d %d %d. We better stop reading.",
-                  buf[len-5], buf[len-4], buf[len-3], buf[len-2], buf[len-1]);
-               csp->expected_content_length = byte_count + len;
+                  "Looks like we reached the end of the last chunk. "
+                  "We better stop reading.");
+               csp->expected_content_length = byte_count + (size_t)len;
                csp->flags |= CSP_FLAG_CONTENT_LENGTH_SET;
             }
          }
@@ -2700,7 +2730,7 @@ static void chat(struct client_state *csp)
                      log_error(LOG_LEVEL_ERROR, "write modified content to client failed: %E");
                      freez(hdr);
                      freez(p);
-                     return;
+                     break;
                   }
 
                   freez(hdr);
@@ -2744,7 +2774,8 @@ static void chat(struct client_state *csp)
                   size_t hdrlen;
                   int flushed;
 
-                  log_error(LOG_LEVEL_INFO, "Flushing header and buffers. Stepping back from filtering.");
+                  log_error(LOG_LEVEL_INFO,
+                     "Flushing header and buffers. Stepping back from filtering.");
 
                   hdr = list_to_text(csp->headers);
                   if (hdr == NULL)
@@ -2756,8 +2787,7 @@ static void chat(struct client_state *csp)
                      log_error(LOG_LEVEL_ERROR, "Out of memory while trying to flush.");
                      rsp = cgi_error_memory();
                      send_crunch_response(csp, rsp);
-
-                     return;
+                     break;
                   }
                   hdrlen = strlen(hdr);
 
@@ -2765,10 +2795,10 @@ static void chat(struct client_state *csp)
                    || ((flushed = flush_socket(csp->cfd, csp->iob)) < 0)
                    || (write_socket(csp->cfd, buf, (size_t)len)))
                   {
-                     log_error(LOG_LEVEL_CONNECT, "Flush header and buffers to client failed: %E");
-
+                     log_error(LOG_LEVEL_CONNECT,
+                        "Flush header and buffers to client failed: %E");
                      freez(hdr);
-                     return;
+                     break;
                   }
 
                   /*
@@ -2787,7 +2817,7 @@ static void chat(struct client_state *csp)
                if (write_socket(csp->cfd, buf, (size_t)len))
                {
                   log_error(LOG_LEVEL_ERROR, "write to client failed: %E");
-                  return;
+                  break;
                }
             }
             byte_count += (size_t)len;
@@ -2795,6 +2825,7 @@ static void chat(struct client_state *csp)
          }
          else
          {
+            const char *header_start;
             /*
              * We're still looking for the end of the server's header.
              * Buffer up the data we just read.  If that fails, there's
@@ -2805,10 +2836,11 @@ static void chat(struct client_state *csp)
                log_error(LOG_LEVEL_ERROR, "Out of memory while looking for end of server headers.");
                rsp = cgi_error_memory();
                send_crunch_response(csp, rsp);               
-
-               return;
+               break;
             }
 
+            header_start = csp->iob->cur;
+
             /* Convert iob into something sed() can digest */
             if (JB_ERR_PARSE == get_server_headers(csp))
             {
@@ -2840,7 +2872,7 @@ static void chat(struct client_state *csp)
                log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd);
                write_socket(csp->cfd, NO_SERVER_DATA_RESPONSE, strlen(NO_SERVER_DATA_RESPONSE));
                free_http_request(http);
-               return;
+               break;
             }
 
             assert(csp->headers->first->str);
@@ -2864,7 +2896,7 @@ static void chat(struct client_state *csp)
                write_socket(csp->cfd, INVALID_SERVER_HEADERS_RESPONSE,
                   strlen(INVALID_SERVER_HEADERS_RESPONSE));
                free_http_request(http);
-               return;
+               break;
             }
 
             /*
@@ -2891,7 +2923,7 @@ static void chat(struct client_state *csp)
                 * and are done here after cleaning up.
                 */
                 freez(hdr);
-                return;
+                break;
             }
             /* Buffer and pcrs filter this if appropriate. */
 
@@ -2920,11 +2952,21 @@ static void chat(struct client_state *csp)
                    * to the client... it probably can't hear us anyway.
                    */
                   freez(hdr);
-                  return;
+                  break;
                }
 
                byte_count += (size_t)len;
             }
+            else
+            {
+               /*
+                * XXX: the header lenght should probably
+                * be calculated by get_server_headers().
+                */
+               int header_length = csp->iob->cur - header_start;
+               assert(csp->iob->cur > header_start);
+               byte_count += (size_t)(len - header_length);
+            }
 
             /* we're finished with the server's header */
 
@@ -2945,8 +2987,17 @@ static void chat(struct client_state *csp)
          }
          continue;
       }
-
-      return; /* huh? we should never get here */
+      /*
+       * If we reach this point, the server socket is tainted
+       * (most likely because we didn't read everything the
+       * server sent us) and reusing it would lead to garbage.
+       */
+      if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE))
+      {
+         log_error(LOG_LEVEL_CONNECT, "Unsetting keep-alive flag.");
+         csp->flags &= ~CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE;
+      }
+      return;
    }
 
    if (csp->content_length == 0)
@@ -3762,7 +3813,10 @@ static void listen_loop(void)
        */
       if (received_hup_signal)
       {
-         init_error_log(Argv[0], config->logfile);
+         if (NULL != config->logfile)
+         {
+            init_error_log(Argv[0], config->logfile);
+         }
          received_hup_signal = 0;
       }
 #endif