]> sjero.net Git - wget/blobdiff - src/connect.c
[svn] Allow decimal values for --timeout, --wait, and --waitretry.
[wget] / src / connect.c
index fa4a69380cf50b85469152a2e0dacc4c13e8e59c..5f927647079acfba2aacba40072182f07532eb38 100644 (file)
@@ -15,11 +15,22 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+In addition, as a special exception, the Free Software Foundation
+gives permission to link the code of its release of Wget with the
+OpenSSL project's "OpenSSL" library (or with modified versions of it
+that use the same license as the "OpenSSL" library), and distribute
+the linked executables.  You must obey the GNU General Public License
+in all respects for all of the code used other than "OpenSSL".  If you
+modify this file, you may extend this exception to your version of the
+file, but you are not obligated to do so.  If you do not wish to do
+so, delete this exception statement from your version.  */
 
 #include <config.h>
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
@@ -165,6 +176,20 @@ connect_to_one (ip_address *addr, unsigned short port, int silent)
   if (sock < 0)
     goto out;
 
+#ifdef SO_RCVBUF
+  /* For very small rate limits, set the buffer size (and hence,
+     hopefully, the size of the kernel window) to the size of the
+     limit.  */
+  if (opt.limit_rate && opt.limit_rate < 8192)
+    {
+      int bufsize = opt.limit_rate;
+      if (bufsize < 512)
+       bufsize = 512;
+      setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
+                 (char *)&bufsize, sizeof (bufsize));
+    }
+#endif
+
   resolve_bind_address ();
   if (bind_address_resolved)
     {
@@ -281,9 +306,12 @@ bindport (unsigned short *port, int family)
 
   if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
     return CONSOCKERR;
+
+#ifdef SO_REUSEADDR
   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
                  (char *)&optval, sizeof (optval)) < 0)
     return CONSOCKERR;
+#endif
 
   resolve_bind_address ();
   wget_sockaddr_set_address (&srv, ip_default_family, htons (*port),
@@ -320,27 +348,37 @@ bindport (unsigned short *port, int family)
 }
 
 #ifdef HAVE_SELECT
-/* Wait for file descriptor FD to be readable, MAXTIME being the
-   timeout in seconds.  If WRITEP is non-zero, checks for FD being
-   writable instead.
+/* Wait for file descriptor FD to be available, timing out after
+   MAXTIME seconds.  "Available" means readable if writep is 0,
+   writeable otherwise.
+
+   Returns 1 if FD is available, 0 for timeout and -1 for error.  */
 
-   Returns 1 if FD is accessible, 0 for timeout and -1 for error in
-   select().  */
 int
-select_fd (int fd, int maxtime, int writep)
+select_fd (int fd, double maxtime, int writep)
 {
-  fd_set fds, exceptfds;
-  struct timeval timeout;
+  fd_set fds;
+  fd_set *rd = NULL, *wrt = NULL;
+  struct timeval tmout;
+  int result;
 
   FD_ZERO (&fds);
   FD_SET (fd, &fds);
-  FD_ZERO (&exceptfds);
-  FD_SET (fd, &exceptfds);
-  timeout.tv_sec = maxtime;
-  timeout.tv_usec = 0;
-  /* HPUX reportedly warns here.  What is the correct incantation?  */
-  return select (fd + 1, writep ? NULL : &fds, writep ? &fds : NULL,
-                &exceptfds, &timeout);
+  *(writep ? &wrt : &rd) = &fds;
+
+  tmout.tv_sec = (long)maxtime;
+  tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
+
+  do
+    result = select (fd + 1, rd, wrt, NULL, &tmout);
+  while (result < 0 && errno == EINTR);
+
+  /* When we've timed out, set errno to ETIMEDOUT for the convenience
+     of the caller. */
+  if (result == 0)
+    errno = ETIMEDOUT;
+
+  return result;
 }
 #endif /* HAVE_SELECT */
 
@@ -392,7 +430,7 @@ conaddr (int fd, ip_address *ip)
 
   switch (mysrv.sa.sa_family)
     {
-#ifdef INET6
+#ifdef ENABLE_IPV6
     case AF_INET6:
       memcpy (ip, &mysrv.sin6.sin6_addr, 16);
       return 1;
@@ -411,43 +449,29 @@ conaddr (int fd, ip_address *ip)
    and uses select() to timeout the stale connections (a connection is
    stale if more than OPT.TIMEOUT time is spent in select() or
    read()).  */
+
 int
 iread (int fd, char *buf, int len)
 {
   int res;
 
-  do
-    {
 #ifdef HAVE_SELECT
-      if (opt.timeout)
-       {
-         do
-           {
-             res = select_fd (fd, opt.timeout, 0);
-           }
-         while (res == -1 && errno == EINTR);
-         if (res <= 0)
-           {
-             /* Set errno to ETIMEDOUT on timeout.  */
-             if (res == 0)
-               /* #### Potentially evil!  */
-               errno = ETIMEDOUT;
-             return -1;
-           }
-       }
+  if (opt.timeout)
+    if (select_fd (fd, opt.timeout, 0) <= 0)
+      return -1;
 #endif
-      res = READ (fd, buf, len);
-    }
+  do
+    res = READ (fd, buf, len);
   while (res == -1 && errno == EINTR);
 
   return res;
 }
 
 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
-   doesn't bother with select().  Unlike iread(), it makes sure that
-   all of BUF is actually written to FD, so callers needn't bother
-   with checking that the return value equals to LEN.  Instead, you
-   should simply check for -1.  */
+   unlike iread(), it makes sure that all of BUF is actually written
+   to FD, so callers needn't bother with checking that the return
+   value equals to LEN.  Instead, you should simply check for -1.  */
+
 int
 iwrite (int fd, char *buf, int len)
 {
@@ -459,27 +483,13 @@ iwrite (int fd, char *buf, int len)
      innermost loop deals with the same during select().  */
   while (len > 0)
     {
-      do
-       {
 #ifdef HAVE_SELECT
-         if (opt.timeout)
-           {
-             do
-               {
-                 res = select_fd (fd, opt.timeout, 1);
-               }
-             while (res == -1 && errno == EINTR);
-             if (res <= 0)
-               {
-                 /* Set errno to ETIMEDOUT on timeout.  */
-                 if (res == 0)
-                   errno = ETIMEDOUT;
-                 return -1;
-               }
-           }
+      if (opt.timeout)
+       if (select_fd (fd, opt.timeout, 1) <= 0)
+         return -1;
 #endif
-         res = WRITE (fd, buf, len);
-       }
+      do
+       res = WRITE (fd, buf, len);
       while (res == -1 && errno == EINTR);
       if (res <= 0)
        break;