commit 0b3d92b799ddfac0f39c30ce208ae70025e3ea4a
parent f2e724d0156a2b12ba34e04de42a3aa20cc5d45f
Author: Kris Maglione <jg@suckless.org>
Date: Thu, 5 Jul 2007 14:37:50 -0400
Resolve port names.
Diffstat:
2 files changed, 82 insertions(+), 56 deletions(-)
diff --git a/libixp/socket.c b/libixp/socket.c
@@ -20,28 +20,27 @@
* not modified.
*/
+typedef struct addrinfo addrinfo;
typedef struct sockaddr sockaddr;
typedef struct sockaddr_un sockaddr_un;
typedef struct sockaddr_in sockaddr_in;
-static int
+static char*
get_port(char *addr) {
- char *s, *end;
- int port;
+ char *s;
s = strchr(addr, '!');
if(s == nil) {
werrstr("no port provided");
- return -1;
+ return nil;
}
*s++ = '\0';
- port = strtol(s, &end, 10);
- if(*s == '\0' && *end != '\0') {
+ if(*s == '\0') {
werrstr("invalid port number");
- return -1;
+ return nil;
}
- return port;
+ return s;
}
static int
@@ -61,34 +60,6 @@ sock_unix(char *address, sockaddr_un *sa, socklen_t *salen) {
}
static int
-sock_tcp(char *host, sockaddr_in *sa) {
- struct hostent *he;
- int port, fd;
-
- /* Truncates host at '!' */
- port = get_port(host);
- if(port < 0)
- return -1;
-
- signal(SIGPIPE, SIG_IGN);
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if(fd < 0)
- return -1;
-
- memset(sa, 0, sizeof(sa));
- sa->sin_family = AF_INET;
- sa->sin_port = htons(port);
-
- if(strcmp(host, "*") == 0)
- sa->sin_addr.s_addr = htonl(INADDR_ANY);
- else if((he = gethostbyname(host)))
- memcpy(&sa->sin_addr, he->h_addr, he->h_length);
- else
- return -1;
- return fd;
-}
-
-static int
dial_unix(char *address) {
sockaddr_un sa;
socklen_t salen;
@@ -136,46 +107,100 @@ fail:
return -1;
}
+static addrinfo*
+alookup(char *host, int announce) {
+ addrinfo hints, *ret;
+ char *port;
+ int err;
+
+ /* Truncates host at '!' */
+ port = get_port(host);
+ if(port == nil)
+ return nil;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if(announce) {
+ hints.ai_flags = AI_PASSIVE;
+ if(!strcmp(host, "*"))
+ host = nil;
+ }
+
+ err = getaddrinfo(host, port, &hints, &ret);
+ if(err) {
+ werrstr("getaddrinfo: %s", gai_strerror(err));
+ return nil;
+ }
+ return ret;
+}
+
+static int
+ai_socket(addrinfo *ai) {
+ return socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+}
+
static int
dial_tcp(char *host) {
- sockaddr_in sa;
+ addrinfo *ai, *aip;
int fd;
- fd = sock_tcp(host, &sa);
- if(fd == -1)
- return fd;
+ aip = alookup(host, 0);
+ if(aip == nil)
+ return -1;
+
+ for(ai = aip; ai; ai = ai->ai_next) {
+ fd = ai_socket(ai);
+ if(fd == -1) {
+ werrstr("socket: %s", strerror(errno));
+ continue;
+ }
- if(connect(fd, (sockaddr*)&sa, sizeof(sa))) {
+ if(connect(fd, ai->ai_addr, ai->ai_addrlen) == 0)
+ break;
+
+ werrstr("connect: %s", strerror(errno));
close(fd);
- return -1;
+ fd = -1;
}
+ freeaddrinfo(aip);
return fd;
}
static int
announce_tcp(char *host) {
- sockaddr_in sa;
+ addrinfo *ai, *aip;
int fd;
- fd = sock_tcp(host, &sa);
- if(fd == -1)
- return fd;
+ aip = alookup(host, 1);
+ if(aip == nil)
+ return -1;
- if(bind(fd, (sockaddr*)&sa, sizeof(sa)) < 0)
- goto fail;
+ /* Probably don't need to loop */
+ for(ai = aip; ai; ai = ai->ai_next) {
+ fd = ai_socket(ai);
+ if(fd == -1)
+ continue;
- if(listen(fd, IXP_MAX_CACHE) < 0)
- goto fail;
+ if(bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
+ goto fail;
- return fd;
+ if(listen(fd, IXP_MAX_CACHE) < 0)
+ goto fail;
+ break;
+ fail:
+ close(fd);
+ fd = -1;
+ }
-fail:
- close(fd);
- return -1;
+ freeaddrinfo(aip);
+ return fd;
}
typedef struct addrtab addrtab;
+static
struct addrtab {
char *type;
int (*fn)(char*);
@@ -223,3 +248,4 @@ int
ixp_announce(char *address) {
return lookup(address, atab);
}
+
diff --git a/libixp_rubythread/thread_ruby.c b/libixp_rubythread/thread_ruby.c
@@ -9,8 +9,7 @@ static char RWLock[];
int
ixp_rubyinit(void) {
- if(rb_require("thread.rb") != Qtrue)
- return 1;
+ rb_require("thread.rb");
rb_eval_string(RWLock);
ixp_thread = &ixp_rthread;
return 0;
@@ -264,3 +263,4 @@ static char RWLock[] =
" Thread.critical = cr \n"
" end \n"
"end \n";
+