]> sjero.net Git - wget/blobdiff - src/connect.c
[svn] Split passive host lookups to a separate function.
[wget] / src / connect.c
index c835fa92a2e3126038a69bfebb81d56b20acb8a6..3ed03c71b5339f640aa7ee4a32fd2c12ca45d898 100644 (file)
@@ -106,7 +106,7 @@ sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
    you're not interested in one or the other information, pass NULL as
    the pointer.  */
 
-void
+static void
 sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
 {
   switch (sa->sa_family)
@@ -166,28 +166,41 @@ sockaddr_size (const struct sockaddr *sa)
 }
 \f
 static int
-resolve_bind_address (const char *host, struct sockaddr *sa, int flags)
+resolve_bind_address (struct sockaddr *sa)
 {
   struct address_list *al;
 
-  /* #### Shouldn't we do this only once?  opt.bind_address won't
-     change during a Wget run!  */
+  /* Make sure this is called only once.  opt.bind_address doesn't
+     change during a Wget run.  */
+  static int called, should_bind;
+  static ip_address ip;
+  if (called)
+    {
+      if (should_bind)
+       sockaddr_set_data (sa, &ip, 0);
+      return should_bind;
+    }
+  called = 1;
 
-  al = lookup_host (host, flags | LH_SILENT | LH_PASSIVE);
-  if (al == NULL)
+  al = lookup_host_passive (opt.bind_address);
+  if (!al)
     {
-      /* #### We should print the error message here. */
+      /* #### We should be able to print the error message here. */
       logprintf (LOG_NOTQUIET,
                 _("%s: unable to resolve bind address `%s'; disabling bind.\n"),
                 exec_name, opt.bind_address);
+      should_bind = 0;
       return 0;
     }
 
   /* Pick the first address in the list and use it as bind address.
-     Perhaps we should try multiple addresses, but I don't think
-     that's necessary in practice.  */
-  sockaddr_set_data (sa, address_list_address_at (al, 0), 0);
+     Perhaps we should try multiple addresses in succession, but I
+     don't think that's necessary in practice.  */
+  ip = *address_list_address_at (al, 0);
   address_list_release (al);
+
+  sockaddr_set_data (sa, &ip, 0);
+  should_bind = 1;
   return 1;
 }
 \f
@@ -280,7 +293,7 @@ connect_to_ip (const ip_address *ip, int port, const char *print)
         address.  */
       struct sockaddr_storage bind_ss;
       struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
-      if (resolve_bind_address (opt.bind_address, bind_sa, 0))
+      if (resolve_bind_address (bind_sa))
        {
           if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
            goto err;
@@ -510,16 +523,28 @@ acceptport (int local_sock, int *sock)
   return ACCEPTOK;
 }
 
-/* Return the local IP address associated with the connection on FD.  */
+/* Get the IP address associated with the connection on FD and store
+   it to IP.  Return 1 on success, 0 otherwise.
+
+   If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
+   (client) side of the socket.  Else if ENDPOINT is ENDPOINT_PEER, it
+   returns the address of the remote (peer's) side of the socket.  */
 
 int
-conaddr (int fd, ip_address *ip)
+socket_ip_address (int sock, ip_address *ip, int endpoint)
 {
   struct sockaddr_storage storage;
   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
   socklen_t addrlen = sizeof (storage);
+  int ret;
 
-  if (getsockname (fd, sockaddr, &addrlen) < 0)
+  if (endpoint == ENDPOINT_LOCAL)
+    ret = getsockname (sock, sockaddr, &addrlen);
+  else if (endpoint == ENDPOINT_PEER)
+    ret = getpeername (sock, sockaddr, &addrlen);
+  else
+    abort ();
+  if (ret < 0)
     return 0;
 
   switch (sockaddr->sa_family)
@@ -628,7 +653,14 @@ void
 register_extended (int fd, xreader_t reader, xwriter_t writer,
                   xpoller_t poller, xcloser_t closer, void *ctx)
 {
-  struct extended_info *info = xnew (struct extended_info);
+  struct extended_info *info;
+
+  /* The file descriptor must be non-negative to be registered.
+     Negative values are ignored by xclose(), and -1 cannot be used as
+     hash key.  */
+  assert (fd >= 0);
+
+  info = xnew (struct extended_info);
   info->reader = reader;
   info->writer = writer;
   info->poller = poller;