]> sjero.net Git - wget/blobdiff - src/http.c
[svn] Tell OpenSSL to renegotiate automatically (mode SSL_MODE_AUTO_RETRY).
[wget] / src / http.c
index 4883fb64d7ddfaa51a93a778577e43d85cd9dc08..3ef8f47b110c5174694adca4024b38848c1b82c7 100644 (file)
@@ -352,7 +352,7 @@ request_send (const struct request *req, int fd)
   write_error = fd_write (fd, request_string, size - 1, -1);
   if (write_error < 0)
     logprintf (LOG_VERBOSE, _("Failed writing HTTP request: %s.\n"),
-              strerror (errno));
+              fd_errstr (fd));
   return write_error;
 }
 
@@ -838,7 +838,7 @@ skip_short_body (int fd, wgint contlen)
          /* Don't normally report the error since this is an
             optimization that should be invisible to the user.  */
          DEBUGP (("] aborting (%s).\n",
-                  ret < 0 ? strerror (errno) : "EOF received"));
+                  ret < 0 ? fd_errstr (fd) : "EOF received"));
          return false;
        }
       contlen -= ret;
@@ -1009,11 +1009,17 @@ persistent_available_p (const char *host, int port, bool ssl,
     }
 
   /* Finally, check whether the connection is still open.  This is
-     important because most server implement a liberal (short) timeout
+     important because most servers implement liberal (short) timeout
      on persistent connections.  Wget can of course always reconnect
      if the connection doesn't work out, but it's nicer to know in
      advance.  This test is a logical followup of the first test, but
-     is "expensive" and therefore placed at the end of the list.  */
+     is "expensive" and therefore placed at the end of the list.
+
+     (Current implementation of test_socket_open has a nice side
+     effect that it treats sockets with pending data as "closed".
+     This is exactly what we want: if a broken server sends message
+     body in response to HEAD, or if it sends more than conent-length
+     data, we won't reuse the corrupted connection.)  */
 
   if (!test_socket_open (pconn.socket))
     {
@@ -1069,6 +1075,7 @@ struct http_stat
   wgint contlen;               /* expected length */
   wgint restval;               /* the restart value */
   int res;                     /* the result of last read */
+  char *rderrmsg;              /* error message from read error */
   char *newloc;                        /* new location (redirection) */
   char *remote_time;           /* remote time-stamp string */
   char *error;                 /* textual HTTP error */
@@ -1085,6 +1092,7 @@ free_hstat (struct http_stat *hs)
   xfree_null (hs->newloc);
   xfree_null (hs->remote_time);
   xfree_null (hs->error);
+  xfree_null (hs->rderrmsg);
 
   /* Guard against being called twice. */
   hs->newloc = NULL;
@@ -1206,6 +1214,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   hs->len = 0;
   hs->contlen = -1;
   hs->res = -1;
+  hs->rderrmsg = NULL;
   hs->newloc = NULL;
   hs->remote_time = NULL;
   hs->error = NULL;
@@ -1477,8 +1486,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
          request_free (connreq);
          if (write_error < 0)
            {
-             logprintf (LOG_VERBOSE, _("Failed writing to proxy: %s.\n"),
-                        strerror (errno));
              CLOSE_INVALIDATE (sock);
              return WRITEFAILED;
            }
@@ -1487,7 +1494,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
          if (!head)
            {
              logprintf (LOG_VERBOSE, _("Failed reading proxy response: %s\n"),
-                        strerror (errno));
+                        fd_errstr (sock));
              CLOSE_INVALIDATE (sock);
              return HERR;
            }
@@ -1547,8 +1554,6 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 
   if (write_error < 0)
     {
-      logprintf (LOG_VERBOSE, _("Failed writing HTTP request: %s.\n"),
-                strerror (errno));
       CLOSE_INVALIDATE (sock);
       request_free (req);
       return WRITEFAILED;
@@ -1572,7 +1577,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
       else
        {
          logprintf (LOG_NOTQUIET, _("Read error (%s) in headers.\n"),
-                    strerror (errno));
+                    fd_errstr (sock));
          CLOSE_INVALIDATE (sock);
          request_free (req);
          return HERR;
@@ -1699,7 +1704,7 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
     hs->error = xstrdup (_("(no description)"));
   else
     hs->error = xstrdup (message);
-  xfree (message);
+  xfree_null (message);
 
   type = resp_header_strdup (resp, "Content-Type");
   if (type)
@@ -1884,11 +1889,18 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
       hs->len = 0;
       hs->res = 0;
       xfree_null (type);
-      /* Pre-1.10 Wget used CLOSE_INVALIDATE here.  Now we trust the
-        servers not to send body in response to a HEAD request.  If
-        you encounter such a server (more likely a broken CGI), use
-        `--no-http-keep-alive'.  */
-      CLOSE_FINISH (sock);
+      if (head_only)
+       /* Pre-1.10 Wget used CLOSE_INVALIDATE here.  Now we trust the
+          servers not to send body in response to a HEAD request, and
+          those that do will likely be caught by test_socket_open.
+          If not, they can be worked around using
+          `--no-http-keep-alive'.  */
+       CLOSE_FINISH (sock);
+      else if (keep_alive && skip_short_body (sock, contlen))
+       /* Successfully skipped the body; also keep using the socket. */
+       CLOSE_FINISH (sock);
+      else
+       CLOSE_INVALIDATE (sock);
       return RETRFINISHED;
     }
 
@@ -1928,9 +1940,9 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   else
     fp = output_stream;
 
-  /* #### This confuses the timestamping code that checks for file
-     size.  Maybe we should save some additional information?  */
-  if (opt.save_headers)
+  /* This confuses the timestamping code that checks for file size.
+     #### The timestamping code should be smarter about file size.  */
+  if (opt.save_headers && hs->restval == 0)
     fwrite (head, 1, strlen (head), fp);
 
   /* Now we no longer need to store the response header. */
@@ -1938,7 +1950,10 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
 
   /* Download the request body.  */
   flags = 0;
-  if (keep_alive)
+  if (contlen != -1)
+    /* If content-length is present, read that much; otherwise, read
+       until EOF.  The HTTP spec doesn't require the server to
+       actually close the connection when it's done sending data. */
     flags |= rb_read_exactly;
   if (hs->restval > 0 && contrange == 0)
     /* If the server ignored our range request, instruct fd_read_body
@@ -1953,20 +1968,14 @@ gethttp (struct url *u, struct http_stat *hs, int *dt, struct url *proxy)
   if (hs->res >= 0)
     CLOSE_FINISH (sock);
   else
-    CLOSE_INVALIDATE (sock);
+    {
+      if (hs->res < 0)
+       hs->rderrmsg = xstrdup (fd_errstr (sock));
+      CLOSE_INVALIDATE (sock);
+    }
 
-  {
-    /* Close or flush the file.  We have to be careful to check for
-       error here.  Checking the result of fwrite() is not enough --
-       errors could go unnoticed!  */
-    int flush_res;
-    if (!output_stream)
-      flush_res = fclose (fp);
-    else
-      flush_res = fflush (fp);
-    if (flush_res == EOF)
-      hs->res = -2;
-  }
+  if (!output_stream)
+    fclose (fp);
   if (hs->res == -2)
     return FWRITEERR;
   return RETRFINISHED;
@@ -2346,9 +2355,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
       if ((tmr != (time_t) (-1))
          && !opt.spider
          && ((hstat.len == hstat.contlen) ||
-             ((hstat.res == 0) &&
-              ((hstat.contlen == -1) ||
-               (hstat.len >= hstat.contlen && !opt.kill_longer)))))
+             ((hstat.res == 0) && (hstat.contlen == -1))))
        {
          /* #### This code repeats in http.c and ftp.c.  Move it to a
              function!  */
@@ -2444,43 +2451,10 @@ The sizes do not match (local %s) -- retrieving.\n"),
              free_hstat (&hstat);
              continue;
            }
-         else if (!opt.kill_longer) /* meaning we got more than expected */
-           {
-             logprintf (LOG_VERBOSE,
-                        _("%s (%s) - `%s' saved [%s/%s]\n\n"),
-                        tms, tmrate, locf,
-                        number_to_static_string (hstat.len),
-                        number_to_static_string (hstat.contlen));
-             logprintf (LOG_NONVERBOSE,
-                        "%s URL:%s [%s/%s] -> \"%s\" [%d]\n",
-                        tms, u->url,
-                        number_to_static_string (hstat.len),
-                        number_to_static_string (hstat.contlen),
-                        locf, count);
-             ++opt.numurls;
-             total_downloaded_bytes += hstat.len;
-
-             /* Remember that we downloaded the file for later ".orig" code. */
-             if (*dt & ADDED_HTML_EXTENSION)
-               downloaded_file(FILE_DOWNLOADED_AND_HTML_EXTENSION_ADDED, locf);
-             else
-               downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
-             
-             free_hstat (&hstat);
-             xfree_null (dummy);
-             return RETROK;
-           }
-         else                  /* the same, but not accepted */
-           {
-             logprintf (LOG_VERBOSE,
-                        _("%s (%s) - Connection closed at byte %s/%s. "),
-                        tms, tmrate,
-                        number_to_static_string (hstat.len),
-                        number_to_static_string (hstat.contlen));
-             printwhat (count, opt.ntry);
-             free_hstat (&hstat);
-             continue;
-           }
+         else
+           /* Getting here would mean reading more data than
+              requested with content-length, which we never do.  */
+           abort ();
        }
       else                     /* now hstat.res can only be -1 */
        {
@@ -2489,7 +2463,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
              logprintf (LOG_VERBOSE,
                         _("%s (%s) - Read error at byte %s (%s)."),
                         tms, tmrate, number_to_static_string (hstat.len),
-                        strerror (errno));
+                        hstat.rderrmsg);
              printwhat (count, opt.ntry);
              free_hstat (&hstat);
              continue;
@@ -2501,7 +2475,7 @@ The sizes do not match (local %s) -- retrieving.\n"),
                         tms, tmrate,
                         number_to_static_string (hstat.len),
                         number_to_static_string (hstat.contlen),
-                        strerror (errno));
+                        hstat.rderrmsg);
              printwhat (count, opt.ntry);
              free_hstat (&hstat);
              continue;