X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Fconnect.c;h=436258c3f0d2a07fef5082e627e6051901f2573a;hb=277e840a0f8e3ec8800cfe7407fe3c16000bc622;hp=e2bacf40e41f2d24aa7cf2d6da8cd06303b326ca;hpb=f496a0ea078552622938a4ddc429278b1264c0ca;p=wget diff --git a/src/connect.c b/src/connect.c index e2bacf40..436258c3 100644 --- a/src/connect.c +++ b/src/connect.c @@ -31,7 +31,6 @@ so, delete this exception statement from your version. */ #include #include -#include #ifdef HAVE_UNISTD_H # include #endif @@ -47,11 +46,7 @@ so, delete this exception statement from your version. */ #endif /* not WINDOWS */ #include -#ifdef HAVE_STRING_H -# include -#else -# include -#endif /* HAVE_STRING_H */ +#include #ifdef HAVE_SYS_SELECT_H # include #endif /* HAVE_SYS_SELECT_H */ @@ -62,10 +57,6 @@ so, delete this exception statement from your version. */ #include "connect.h" #include "hash.h" -#ifndef errno -extern int errno; -#endif - /* Define sockaddr_storage where unavailable (presumably on IPv4-only hosts). */ @@ -87,6 +78,7 @@ sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port) case IPV4_ADDRESS: { struct sockaddr_in *sin = (struct sockaddr_in *)sa; + xzero (*sin); sin->sin_family = AF_INET; sin->sin_port = htons (port); sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip); @@ -96,6 +88,7 @@ sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port) case IPV6_ADDRESS: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; + xzero (*sin6); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons (port); sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip); @@ -169,7 +162,6 @@ sockaddr_size (const struct sockaddr *sa) #endif default: abort (); - return 0; /* so the compiler shuts up. */ } } @@ -259,7 +251,7 @@ connect_to_ip (const ip_address *ip, int port, const char *print) { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *)&ss; - int sock = -1; + int sock; /* If PRINT is non-NULL, print the "Connecting to..." line, with PRINT being the host name we're connecting to. */ @@ -267,8 +259,8 @@ connect_to_ip (const ip_address *ip, int port, const char *print) { const char *txt_addr = pretty_print_address (ip); if (print && 0 != strcmp (print, txt_addr)) - logprintf (LOG_VERBOSE, - _("Connecting to %s|%s|:%d... "), print, txt_addr, port); + logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "), + escnonprint (print), txt_addr, port); else logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port); } @@ -281,6 +273,18 @@ connect_to_ip (const ip_address *ip, int port, const char *print) if (sock < 0) goto err; +#if defined(ENABLE_IPV6) && defined(IPV6_V6ONLY) + if (opt.ipv6_only) { + int on = 1; + /* In case of error, we will go on anyway... */ + int err = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)); +#ifdef ENABLE_DEBUG + if (err < 0) + DEBUGP (("Failed setting IPV6_V6ONLY: %s", strerror (errno))); +#endif + } +#endif + /* For very small rate limits, set the buffer size (and hence, hopefully, the kernel's TCP window size) to the per-second limit. That way we should never have to sleep for more than 1s between @@ -331,7 +335,7 @@ connect_to_ip (const ip_address *ip, int port, const char *print) if (sock >= 0) fd_close (sock); if (print) - logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno)); + logprintf (LOG_VERBOSE, _("failed: %s.\n"), strerror (errno)); errno = save_errno; return -1; } @@ -428,13 +432,6 @@ bind_local (const ip_address *bind_address, int *port) setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, setopt_ptr, setopt_size); #endif -#ifdef ENABLE_IPV6 -# ifdef HAVE_IPV6_V6ONLY - if (family == AF_INET6) - setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, setopt_ptr, setopt_size); -# endif -#endif - xzero (ss); sockaddr_set_data (sa, bind_address, *port); if (bind (sock, sa, sockaddr_size (sa)) < 0) @@ -553,8 +550,6 @@ socket_ip_address (int sock, ip_address *ip, int endpoint) default: abort (); } - - return 0; } /* Return non-zero if the error from the connect code can be @@ -590,43 +585,20 @@ retryable_socket_connect_error (int err) ) return 0; - if (err == ECONNREFUSED && !opt.retry_connrefused) - return 0; + if (!opt.retry_connrefused) + if (err == ECONNREFUSED +#ifdef ENETUNREACH + || err == ENETUNREACH /* network is unreachable */ +#endif +#ifdef EHOSTUNREACH + || err == EHOSTUNREACH /* host is unreachable */ +#endif + ) + return 0; return 1; } -#ifdef ENABLE_IPV6 -# ifndef HAVE_GETADDRINFO_AI_ADDRCONFIG - -/* Return non-zero if the INET6 socket family is supported on the - system. - - This doesn't guarantee that we're able to connect to IPv6 hosts, - but it's better than nothing. It is only used on systems where - getaddrinfo doesn't support AI_ADDRCONFIG. (See lookup_host.) */ - -int -socket_has_inet6 (void) -{ - static int supported = -1; - if (supported == -1) - { - int sock = socket (AF_INET6, SOCK_STREAM, 0); - if (sock < 0) - supported = 0; - else - { - fd_close (sock); - supported = 1; - } - } - return supported; -} - -# endif/* not HAVE_GETADDRINFO_AI_ADDRCONFIG */ -#endif /* ENABLE_IPV6 */ - /* Wait for a single descriptor to become available, timing out after MAXTIME seconds. Returns 1 if FD is available, 0 for timeout and -1 for error. The argument WAIT_FOR can be a combination of @@ -653,7 +625,7 @@ select_fd (int fd, double maxtime, int wait_for) wr = &fdset; tmout.tv_sec = (long) maxtime; - tmout.tv_usec = 1000000L * (maxtime - (long) maxtime); + tmout.tv_usec = 1000000 * (maxtime - (long) maxtime); do result = select (fd + 1, rd, wr, NULL, &tmout); @@ -815,6 +787,17 @@ fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer, ++transport_map_modified_tick; } +/* Return context of the transport registered with + fd_register_transport. This assumes fd_register_transport was + previously called on FD. */ + +void * +fd_transport_context (int fd) +{ + struct transport_info *info = hash_table_get (transport_map, (void *) fd); + return info->ctx; +} + /* When fd_read/fd_write are called multiple times in a loop, they should remember the INFO pointer instead of fetching it every time. It is not enough to compare FD to LAST_FD because FD might have been @@ -878,8 +861,17 @@ fd_read (int fd, char *buf, int bufsize, double timeout) return sock_read (fd, buf, bufsize); } -/* The same as xread, but don't actually read the data, just copy it - instead. */ +/* Like fd_read, except it provides a "preview" of the data that will + be read by subsequent calls to fd_read. Specifically, it copies no + more than BUFSIZE bytes of the currently available data to BUF and + returns the number of bytes copied. Return values and timeout + semantics are the same as those of fd_read. + + CAVEAT: Do not assume that the first subsequent call to fd_read + will retrieve the same amount of data. Reading can return more or + less data, depending on the TCP implementation and other + circumstances. However, barring an error, it can be expected that + all the peeked data will eventually be read by fd_read. */ int fd_peek (int fd, char *buf, int bufsize, double timeout)