/* Establishing and handling network connections.
- Copyright (C) 1996-2005 Free Software Foundation, Inc.
+ Copyright (C) 1996-2006 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
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.,
-51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+along with Wget. If not, see <http://www.gnu.org/licenses/>.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
static void
sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
{
- switch (ip->type)
+ switch (ip->family)
{
- case IPV4_ADDRESS:
+ case AF_INET:
{
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);
+ sin->sin_addr = ip->data.d4;
break;
}
#ifdef ENABLE_IPV6
- case IPV6_ADDRESS:
+ case AF_INET6:
{
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);
+ sin6->sin6_addr = ip->data.d6;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
- sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
+ sin6->sin6_scope_id = ip->ipv6_scope;
#endif
break;
}
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
if (ip)
{
- ip->type = IPV4_ADDRESS;
- ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
+ ip->family = AF_INET;
+ ip->data.d4 = sin->sin_addr;
}
if (port)
*port = ntohs (sin->sin_port);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (ip)
{
- ip->type = IPV6_ADDRESS;
- ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
+ ip->family = AF_INET6;
+ ip->data.d6 = sin6->sin6_addr;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
- ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
+ ip->ipv6_scope = sin6->sin6_scope_id;
#endif
}
if (port)
bind_local (const ip_address *bind_address, int *port)
{
int sock;
- int family = AF_INET;
struct sockaddr_storage ss;
struct sockaddr *sa = (struct sockaddr *)&ss;
void *setopt_ptr = (void *)&setopt_val;
socklen_t setopt_size = sizeof (setopt_val);
-#ifdef ENABLE_IPV6
- if (bind_address->type == IPV6_ADDRESS)
- family = AF_INET6;
-#endif
-
- sock = socket (family, SOCK_STREAM, 0);
+ sock = socket (bind_address->family, SOCK_STREAM, 0);
if (sock < 0)
return -1;
if (ret < 0)
return false;
+ ip->family = sockaddr->sa_family;
switch (sockaddr->sa_family)
{
#ifdef ENABLE_IPV6
case AF_INET6:
{
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
- ip->type = IPV6_ADDRESS;
- ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
+ ip->data.d6 = sa6->sin6_addr;
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
- ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
+ ip->ipv6_scope = sa6->sin6_scope_id;
#endif
DEBUGP (("conaddr is: %s\n", print_address (ip)));
return true;
case AF_INET:
{
struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
- ip->type = IPV4_ADDRESS;
- ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
+ ip->data.d4 = sa->sin_addr;
DEBUGP (("conaddr is: %s\n", print_address (ip)));
return true;
}
to.tv_sec = 0;
to.tv_usec = 1;
- /* If we get a timeout, then that means still connected */
if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
- /* Connection is valid (not EOF), so continue */
+ /* We got a timeout, it means we're still connected. */
return true;
else
+ /* Read now would not wait, it means we have either pending data
+ or EOF/error. */
return false;
}
\f
info->ctx = ctx;
if (!transport_map)
transport_map = hash_table_new (0, NULL, NULL);
- hash_table_put (transport_map, (void *) fd, info);
+ hash_table_put (transport_map, (void *)(intptr_t) fd, info);
++transport_map_modified_tick;
}
void *
fd_transport_context (int fd)
{
- struct transport_info *info = hash_table_get (transport_map, (void *) fd);
+ struct transport_info *info = hash_table_get (transport_map, (void *)(intptr_t) fd);
return info->ctx;
}
#define LAZY_RETRIEVE_INFO(info) do { \
static struct transport_info *last_info; \
- static int last_fd = -1, last_tick; \
+ static int last_fd = -1; \
+ static unsigned int last_tick; \
if (!transport_map) \
info = NULL; \
else if (last_fd == fd && last_tick == transport_map_modified_tick) \
info = last_info; \
else \
{ \
- info = hash_table_get (transport_map, (void *) fd); \
+ info = hash_table_get (transport_map, (void *)(intptr_t) fd); \
last_fd = fd; \
last_info = info; \
last_tick = transport_map_modified_tick; \
used.
If the transport doesn't support error messages or doesn't supply
- one, strerror(errno) is returned. */
+ one, strerror(errno) is returned. The returned error message
+ should not be used after fd_close has been called. */
const char *
fd_errstr (int fd)
in case of error, never in a tight loop. */
struct transport_info *info = NULL;
if (transport_map)
- info = hash_table_get (transport_map, (void *) fd);
+ info = hash_table_get (transport_map, (void *)(intptr_t) fd);
if (info && info->imp->errstr)
{
per socket, so that particular optimization wouldn't work. */
info = NULL;
if (transport_map)
- info = hash_table_get (transport_map, (void *) fd);
+ info = hash_table_get (transport_map, (void *)(intptr_t) fd);
if (info && info->imp->closer)
info->imp->closer (fd, info->ctx);
if (info)
{
- hash_table_remove (transport_map, (void *) fd);
+ hash_table_remove (transport_map, (void *)(intptr_t) fd);
xfree (info);
++transport_map_modified_tick;
}