Merge branch 'dh/repack' (early part)
[gitweb.git] / connect.c
index 5048653639b3eea4c68eaaa4382363b2bc468e06..375739205f72062c7b51e16ca4cdecc053e1c2da 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -391,16 +391,34 @@ static enum protocol get_protocol(const char *name)
 
 #ifndef NO_IPV6
 
+static const char *ai_name(const struct addrinfo *ai)
+{
+       static char addr[INET_ADDRSTRLEN];
+       if ( AF_INET == ai->ai_family ) {
+               struct sockaddr_in *in;
+               in = (struct sockaddr_in *)ai->ai_addr;
+               inet_ntop(ai->ai_family, &in->sin_addr, addr, sizeof(addr));
+       } else if ( AF_INET6 == ai->ai_family ) {
+               struct sockaddr_in6 *in;
+               in = (struct sockaddr_in6 *)ai->ai_addr;
+               inet_ntop(ai->ai_family, &in->sin6_addr, addr, sizeof(addr));
+       } else {
+               strcpy(addr, "(unknown)");
+       }
+       return addr;
+}
+
 /*
  * Returns a connected socket() fd, or else die()s.
  */
-static int git_tcp_connect_sock(char *host)
+static int git_tcp_connect_sock(char *host, int flags)
 {
        int sockfd = -1, saved_errno = 0;
        char *colon, *end;
        const char *port = STR(DEFAULT_GIT_PORT);
        struct addrinfo hints, *ai0, *ai;
        int gai;
+       int cnt = 0;
 
        if (host[0] == '[') {
                end = strchr(host + 1, ']');
@@ -417,15 +435,23 @@ static int git_tcp_connect_sock(char *host)
        if (colon) {
                *colon = 0;
                port = colon + 1;
+               if (!*port)
+                       port = "<none>";
        }
 
        memset(&hints, 0, sizeof(hints));
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
 
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "Looking up %s ... ", host);
+
        gai = getaddrinfo(host, port, &hints, &ai);
        if (gai)
-               die("Unable to look up %s (%s)", host, gai_strerror(gai));
+               die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai));
+
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
 
        for (ai0 = ai; ai; ai = ai->ai_next) {
                sockfd = socket(ai->ai_family,
@@ -436,10 +462,18 @@ static int git_tcp_connect_sock(char *host)
                }
                if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
                        saved_errno = errno;
+                       fprintf(stderr, "%s[%d: %s]: net=%s, errno=%s\n",
+                               host,
+                               cnt,
+                               ai_name(ai),
+                               hstrerror(h_errno),
+                               strerror(saved_errno));
                        close(sockfd);
                        sockfd = -1;
                        continue;
                }
+               if (flags & CONNECT_VERBOSE)
+                       fprintf(stderr, "%s ", ai_name(ai));
                break;
        }
 
@@ -448,6 +482,9 @@ static int git_tcp_connect_sock(char *host)
        if (sockfd < 0)
                die("unable to connect a socket (%s)", strerror(saved_errno));
 
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "done.\n");
+
        return sockfd;
 }
 
@@ -456,7 +493,7 @@ static int git_tcp_connect_sock(char *host)
 /*
  * Returns a connected socket() fd, or else die()s.
  */
-static int git_tcp_connect_sock(char *host)
+static int git_tcp_connect_sock(char *host, int flags)
 {
        int sockfd = -1, saved_errno = 0;
        char *colon, *end;
@@ -465,6 +502,7 @@ static int git_tcp_connect_sock(char *host)
        struct sockaddr_in sa;
        char **ap;
        unsigned int nport;
+       int cnt;
 
        if (host[0] == '[') {
                end = strchr(host + 1, ']');
@@ -483,6 +521,9 @@ static int git_tcp_connect_sock(char *host)
                port = colon + 1;
        }
 
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "Looking up %s ... ", host);
+
        he = gethostbyname(host);
        if (!he)
                die("Unable to look up %s (%s)", host, hstrerror(h_errno));
@@ -495,7 +536,10 @@ static int git_tcp_connect_sock(char *host)
                nport = se->s_port;
        }
 
-       for (ap = he->h_addr_list; *ap; ap++) {
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "done.\nConnecting to %s (port %s) ... ", host, port);
+
+       for (cnt = 0, ap = he->h_addr_list; *ap; ap++, cnt++) {
                sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
                if (sockfd < 0) {
                        saved_errno = errno;
@@ -509,25 +553,37 @@ static int git_tcp_connect_sock(char *host)
 
                if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
                        saved_errno = errno;
+                       fprintf(stderr, "%s[%d: %s]: net=%s, errno=%s\n",
+                               host,
+                               cnt,
+                               inet_ntoa(*(struct in_addr *)&sa.sin_addr),
+                               hstrerror(h_errno),
+                               strerror(saved_errno));
                        close(sockfd);
                        sockfd = -1;
                        continue;
                }
+               if (flags & CONNECT_VERBOSE)
+                       fprintf(stderr, "%s ",
+                               inet_ntoa(*(struct in_addr *)&sa.sin_addr));
                break;
        }
 
        if (sockfd < 0)
                die("unable to connect a socket (%s)", strerror(saved_errno));
 
+       if (flags & CONNECT_VERBOSE)
+               fprintf(stderr, "done.\n");
+
        return sockfd;
 }
 
 #endif /* NO_IPV6 */
 
 
-static void git_tcp_connect(int fd[2], char *host)
+static void git_tcp_connect(int fd[2], char *host, int flags)
 {
-       int sockfd = git_tcp_connect_sock(host);
+       int sockfd = git_tcp_connect_sock(host, flags);
 
        fd[0] = sockfd;
        fd[1] = dup(sockfd);
@@ -644,7 +700,7 @@ static void git_proxy_connect(int fd[2], char *host)
  *
  * Does not return a negative value on error; it just dies.
  */
-pid_t git_connect(int fd[2], char *url, const char *prog)
+pid_t git_connect(int fd[2], char *url, const char *prog, int flags)
 {
        char *host, *path = url;
        char *end;
@@ -717,7 +773,7 @@ pid_t git_connect(int fd[2], char *url, const char *prog)
                if (git_use_proxy(host))
                        git_proxy_connect(fd, host);
                else
-                       git_tcp_connect(fd, host);
+                       git_tcp_connect(fd, host, flags);
                /*
                 * Separate original protocol components prog and path
                 * from extended components with a NUL byte.