threads / patch / 1285

patch, 2 partsGIT: Try all addresses for given remote name

Subject: [PATCH 1/2] GIT: Try all addresses for given remote name

## tl;dr

5 messages between Jul 21, 2005 and Jul 23, 2005. Diffs are folded; open one to read it.

replies: 4people: 3as markdown or json

YOSHIFUJI Hideaki / 吉藤英明· Jul 21, 2005, 13:10 UTC · lore
Hello.

Try all addresses for given remote name until it succeeds. Also supports IPv6.

Signed-of-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
Show changes to connect.c +42 −27
diff --git a/connect.c b/connect.c
--- a/connect.c
+++ b/connect.c
@@ -96,42 +96,57 @@ static enum protocol get_protocol(const 
 	die("I don't handle protocol '%s'", name);
 }
 
-static void lookup_host(const char *host, struct sockaddr *in)
-{
-	struct addrinfo *res;
-	int ret;
-
-	ret = getaddrinfo(host, NULL, NULL, &res);
-	if (ret)
-		die("Unable to look up %s (%s)", host, gai_strerror(ret));
-	*in = *res->ai_addr;
-	freeaddrinfo(res);
-}
+#define STR_(s)	# s
+#define STR(s)	STR_(s)
 
 static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
 {
-	struct sockaddr addr;
-	int port = DEFAULT_GIT_PORT, sockfd;
-	char *colon;
-
-	colon = strchr(host, ':');
-	if (colon) {
-		char *end;
-		unsigned long n = strtoul(colon+1, &end, 0);
-		if (colon[1] && !*end) {
-			*colon = 0;
-			port = n;
+	int sockfd = -1;
+	char *colon, *end;
+	char *port = STR(DEFAULT_GIT_PORT);
+	struct addrinfo hints, *ai0, *ai;
+	int gai;
+
+	if (host[0] == '[') {
+		end = strchr(host + 1, ']');
+		if (end) {
+			*end = 0;
+			end++;
+			host++;
+		} else
+			end = host;
+	} else
+		end = host;
+	colon = strchr(end, ':');
+
+	if (colon)
+		port = colon + 1;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+
+	gai = getaddrinfo(host, port, &hints, &ai);
+	if (gai)
+		die("Unable to look up %s (%s)", host, gai_strerror(gai));
+
+	for (ai0 = ai; ai; ai = ai->ai_next) {
+		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+		if (sockfd < 0)
+			continue;
+		if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
+			close(sockfd);
+			sockfd = -1;
+			continue;
 		}
+		break;
 	}
 
-	lookup_host(host, &addr);
-	((struct sockaddr_in *)&addr)->sin_port = htons(port);
+	freeaddrinfo(ai0);
 
-	sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
 	if (sockfd < 0)
 		die("unable to create socket (%s)", strerror(errno));
-	if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
-		die("unable to connect (%s)", strerror(errno));
+
 	fd[0] = sockfd;
 	fd[1] = sockfd;
 	packet_write(sockfd, "%s %s\n", prog, path);
-- 
YOSHIFUJI Hideaki @ USAGI Project  <yoshfuji@linux-ipv6.org>
GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
Petr Baudis· Jul 22, 2005, 21:09 UTC · re: YOSHIFUJI Hideaki / 吉藤英明 · lore

Re: [PATCH 1/2] GIT: Try all addresses for given remote name

Dear diary, on Thu, Jul 21, 2005 at 03:10:36PM CEST, I got a letter where "YOSHIFUJI Hideaki / ?$B5HF#1QL@" <yoshfuji@linux-ipv6.org> told me that...

> Hello.
Hello,
Show 25 quoted lines
> Try all addresses for given remote name until it succeeds.
> Also supports IPv6.
> 
> Signed-of-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
> 
> diff --git a/connect.c b/connect.c
> --- a/connect.c
> +++ b/connect.c
> @@ -96,42 +96,57 @@ static enum protocol get_protocol(const 
>  	die("I don't handle protocol '%s'", name);
>  }
>  
> -static void lookup_host(const char *host, struct sockaddr *in)
> -{
> -	struct addrinfo *res;
> -	int ret;
> -
> -	ret = getaddrinfo(host, NULL, NULL, &res);
> -	if (ret)
> -		die("Unable to look up %s (%s)", host, gai_strerror(ret));
> -	*in = *res->ai_addr;
> -	freeaddrinfo(res);
> -}
> +#define STR_(s)	# s
> +#define STR(s)	STR_(s)
Uh-huh? Why two macros? Well, why any macros at all?
Show 67 quoted lines
>  static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
>  {
> -	struct sockaddr addr;
> -	int port = DEFAULT_GIT_PORT, sockfd;
> -	char *colon;
> -
> -	colon = strchr(host, ':');
> -	if (colon) {
> -		char *end;
> -		unsigned long n = strtoul(colon+1, &end, 0);
> -		if (colon[1] && !*end) {
> -			*colon = 0;
> -			port = n;
> +	int sockfd = -1;
> +	char *colon, *end;
> +	char *port = STR(DEFAULT_GIT_PORT);
> +	struct addrinfo hints, *ai0, *ai;
> +	int gai;
> +
> +	if (host[0] == '[') {
> +		end = strchr(host + 1, ']');
> +		if (end) {
> +			*end = 0;
> +			end++;
> +			host++;
> +		} else
> +			end = host;
> +	} else
> +		end = host;
> +	colon = strchr(end, ':');
> +
> +	if (colon)
> +		port = colon + 1;
> +
> +	memset(&hints, 0, sizeof(hints));
> +	hints.ai_socktype = SOCK_STREAM;
> +	hints.ai_protocol = IPPROTO_TCP;
> +
> +	gai = getaddrinfo(host, port, &hints, &ai);
> +	if (gai)
> +		die("Unable to look up %s (%s)", host, gai_strerror(gai));
> +
> +	for (ai0 = ai; ai; ai = ai->ai_next) {
> +		sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
> +		if (sockfd < 0)
> +			continue;
> +		if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
> +			close(sockfd);
> +			sockfd = -1;
> +			continue;
>  		}
> +		break;
>  	}
>  
> -	lookup_host(host, &addr);
> -	((struct sockaddr_in *)&addr)->sin_port = htons(port);
> +	freeaddrinfo(ai0);
>  
> -	sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
>  	if (sockfd < 0)
>  		die("unable to create socket (%s)", strerror(errno));
> -	if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
> -		die("unable to connect (%s)", strerror(errno));
> +
>  	fd[0] = sockfd;
>  	fd[1] = sockfd;
>  	packet_write(sockfd, "%s %s\n", prog, path);

You are saying that you were unable to create socket while you just were unable to connect. Not any biggie, but it saves the user the trouble of one strace after being confused by an error message. :-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
If you want the holes in your knowledge showing up try teaching
someone.  -- Alan Cox
YOSHIFUJI Hideaki / 吉藤英明· Jul 22, 2005, 21:26 UTC · re: Petr Baudis · lore

Re: [PATCH 1/2] GIT: Try all addresses for given remote name

In article <20050722210913.GH11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:09:13 +0200), Petr Baudis <pasky@suse.cz> says:
Show 6 quoted lines
> > -}
> > +#define STR_(s)	# s
> > +#define STR(s)	STR_(s)
> 
> Uh-huh? Why two macros? Well, why any macros at all?
> 
:
> > +	char *colon, *end;
> > +	char *port = STR(DEFAULT_GIT_PORT);
> > +	struct addrinfo hints, *ai0, *ai;

The macro is used here. This is trick.

After preprocess,

/* --- cut here --- */ #define TEST 12345 #define STR_(s) # s #define STR(s) STR_(s)

test(STR(TEST)); test(STR_(TEST)); test(# TEST); /* --- cut here --- */

becomes

test("12345"); test("TEST"); test(# 12345);

> >  	if (sockfd < 0)
> >  		die("unable to create socket (%s)", strerror(errno));
> > -	if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
> > -		die("unable to connect (%s)", strerror(errno));
:
> You are saying that you were unable to create socket while you just were
> unable to connect.  Not any biggie, but it saves the user the trouble of
> one strace after being confused by an error message. :-)

In fact, I don't think it is really worng, because it says that it could not create (connected) socket or endpoint of connection.

Anyway, I agree that it would be confusing. Better ideas / wordings?

--yoshfuji
Petr Baudis· Jul 22, 2005, 21:37 UTC · re: YOSHIFUJI Hideaki / 吉藤英明 · lore

Re: [PATCH 1/2] GIT: Try all addresses for given remote name

Dear diary, on Fri, Jul 22, 2005 at 11:26:29PM CEST, I got a letter where "YOSHIFUJI Hideaki / ?$B5HF#1QL@" <yoshfuji@linux-ipv6.org> told me that...

Show 33 quoted lines
> In article <20050722210913.GH11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:09:13 +0200), Petr Baudis <pasky@suse.cz> says:
> 
> > > -}
> > > +#define STR_(s)	# s
> > > +#define STR(s)	STR_(s)
> > 
> > Uh-huh? Why two macros? Well, why any macros at all?
> > 
> :
> > > +	char *colon, *end;
> > > +	char *port = STR(DEFAULT_GIT_PORT);
> > > +	struct addrinfo hints, *ai0, *ai;
> 
> The macro is used here.
> This is trick.
> 
> After preprocess,
> 
> /* --- cut here --- */
> #define TEST 12345
> #define STR_(s) # s
> #define STR(s) STR_(s)
> 
> test(STR(TEST));
> test(STR_(TEST));
> test(# TEST);
> /* --- cut here --- */
> 
> becomes
> 
> test("12345");
> test("TEST");
> test(# 12345);

I see, I didn't know about this. Well, I didn't actually use the # stringificator many times. Perhaps a short comment would be due.

Show 11 quoted lines
> > >  	if (sockfd < 0)
> > >  		die("unable to create socket (%s)", strerror(errno));
> > > -	if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
> > > -		die("unable to connect (%s)", strerror(errno));
> :
> > You are saying that you were unable to create socket while you just were
> > unable to connect.  Not any biggie, but it saves the user the trouble of
> > one strace after being confused by an error message. :-)
> 
> In fact, I don't think it is really worng, because it says that
> it could not create (connected) socket or endpoint of connection.
It uses only two words ("create socket") from that, though. ;-)
> Anyway, I agree that it would be confusing.
> Better ideas / wordings?
	if (connect() < 0) sockfd = -2;
	...
	if (sockfd == -1) die("unable to create socket");
	else die("unable to connect")

or I'd prefer the second error message "unable to connect", which is perhaps more descriptive regarding what effectively happened.

BTW, could the close() on the socket ever fail (read as "modify errno") here?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
If you want the holes in your knowledge showing up try teaching
someone.  -- Alan Cox
Sam Ravnborg· Jul 23, 2005, 00:15 UTC · re: YOSHIFUJI Hideaki / 吉藤英明 · lore

Re: [PATCH 1/2] GIT: Try all addresses for given remote name

On Fri, Jul 22, 2005 at 05:26:29PM -0400, YOSHIFUJI Hideaki / ?$B5HF#1QL@ wrote:
Show 14 quoted lines
> In article <20050722210913.GH11916@pasky.ji.cz> (at Fri, 22 Jul 2005 23:09:13 +0200), Petr Baudis <pasky@suse.cz> says:
> 
> > > -}
> > > +#define STR_(s)	# s
> > > +#define STR(s)	STR_(s)
> > 
> > Uh-huh? Why two macros? Well, why any macros at all?
> > 
> :
> > > +	char *colon, *end;
> > > +	char *port = STR(DEFAULT_GIT_PORT);
> > > +	struct addrinfo hints, *ai0, *ai;
> 
> The macro is used here.

You could copy the include/linux/stingify.h file from the kernel also. That makes it available for other users also.

	Sam

← back to recent threads