$NetBSD: patch-bd,v 1.3 1999/11/26 06:09:01 itohy Exp $ --- sockets.c.orig Tue Jul 6 03:46:16 1999 +++ sockets.c Thu Nov 25 20:00:36 1999 @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -47,93 +48,133 @@ int OpenClientSocket(char* host, int port,int timeout) { - int s; - int retval; - struct sockaddr_in server; - struct hostent* hp; + int s = -1; + int connected, err; + struct addrinfo hints, *r, *res = NULL; int noblock,flags; + char *aport = NULL; - server.sin_family=AF_INET; - server.sin_port=htons((unsigned short)port); - - hp=gethostbyname(host); - if(!hp) - { - unsigned long int addr=inet_addr(host); - if(addr!=-1) - hp=gethostbyaddr((char*)addr,sizeof(addr),AF_INET); - - if(!hp) - {errno=-1;PrintMessage(Warning,"Unknown host '%s' for server [%!s].",host);return(-1);} - } - memcpy((char*)&server.sin_addr,(char*)hp->h_addr,sizeof(server.sin_addr)); - - s=socket(PF_INET,SOCK_STREAM,0); - if(s==-1) - {PrintMessage(Warning,"Cannot create client socket [%!s].");return(-1);} - + err = asprintf(&aport, "%d", port); + if (err < 0) { + errno=-1; + PrintMessage(Warning,"Memory Alloc Fails [%!s]."); + return(-1); + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype= SOCK_STREAM; + err = getaddrinfo(host, aport, &hints, &res); + if (res) { + freeaddrinfo(res); + res = NULL; + } + + if (!err) { + /*numeric*/ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + err = getaddrinfo(host, aport, &hints, &res); + } else { + /*non-numeric*/ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + err = getaddrinfo(host, aport, &hints, &res); + } + + if (err) { + s = -1; errno=-1; + PrintMessage(Warning,"%s '%s', server [%!s].", gai_strerror(err), host); + } + else { + err = 0; s = -1; + connected = 0; + for (r = res; r && !connected; r = r->ai_next) { + s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if (s < 0) { + PrintMessage(Warning,"Cannot create client socket [%!s]."); + continue; + } #ifdef O_NONBLOCK - flags=fcntl(s,F_GETFL,0); - if(flags!=-1) - noblock=fcntl(s,F_SETFL,flags|O_NONBLOCK); - else - noblock=-1; + flags=fcntl(s,F_GETFL,0); + if(flags!=-1) + noblock=fcntl(s,F_SETFL,flags|O_NONBLOCK); + else + noblock=-1; #else - flags=1; - noblock=ioctl(s,FIONBIO,&flags); + flags=1; + noblock=ioctl(s,FIONBIO,&flags); #endif - retval=connect(s,(struct sockaddr *)&server,sizeof(server)); - - if(retval==-1 && noblock!=-1 && errno==EINPROGRESS) - { - fd_set writefd; - struct timeval tv; - - FD_ZERO(&writefd); - FD_SET(s,&writefd); - - tv.tv_sec=timeout; - tv.tv_usec=0; - - retval=select(s+1,NULL,&writefd,NULL,&tv); - - if(retval>0) - { - int arglen=sizeof(int); - - if(getsockopt(s,SOL_SOCKET,SO_ERROR,&retval,&arglen)<0) - retval=errno; - - if(retval!=0) - errno=retval,retval=-1; - if(errno==EINPROGRESS) - errno=ETIMEDOUT; - } - else if(retval==0) - errno=ETIMEDOUT,retval=-1; - } - - if(retval<0) - { - close(s); - s=-1; - - PrintMessage(Warning,"Connect fail [%!s]."); - } - else - { + err = connect(s, r->ai_addr, r->ai_addrlen); + if(err==-1 && noblock!=-1 && errno==EINPROGRESS) + { + fd_set writefd; + struct timeval tv; + + FD_ZERO(&writefd); + FD_SET(s,&writefd); + + tv.tv_sec=timeout; + tv.tv_usec=0; + + err=select(s+1,NULL,&writefd,NULL,&tv); + + if(err>0) + { + int arglen=sizeof(int); + + if(getsockopt(s,SOL_SOCKET,SO_ERROR,&err,&arglen)<0) + err=errno; + + if(err!=0) + errno=err,err=-1; + if(errno==EINPROGRESS) + errno=ETIMEDOUT; + } + else if(err==0) + errno=ETIMEDOUT,err=-1; + } + + if(err<0) + { + close(s); + s=-1; + + PrintMessage(Warning,"Connect fail [%!s]."); + continue; + } + else + { #ifdef O_NONBLOCK - flags=fcntl(s,F_GETFL,0); - if(flags!=-1) - fcntl(s,F_SETFL,flags&~O_NONBLOCK); + flags=fcntl(s,F_GETFL,0); + if(flags!=-1) + fcntl(s,F_SETFL,flags&~O_NONBLOCK); #else - flags=0; - ioctl(s,FIONBIO,&flags); + flags=0; + ioctl(s,FIONBIO,&flags); #endif - } - - return(s); + } + + PrintMessage(Inform,"Connected ok to client [%!s]."); + connected++; + break; + } + if (!connected) s = -1; + } + if (res) freeaddrinfo(res); + if (aport) free(aport); + + if (s < 0) + PrintMessage(Warning,"OSC Connect fail [%!s]."); + + return (s); } @@ -145,30 +186,75 @@ int port The port number to use. ++++++++++++++++++++++++++++++++++++++*/ -int OpenServerSocket(int port) +int *OpenServerSockets(int port) { - int s; - int retval; - struct sockaddr_in server; - int reuse_addr=1; - - s=socket(PF_INET,SOCK_STREAM,0); - if(s==-1) - {PrintMessage(Warning,"Cannot create server socket [%!s].");return(-1);} - - setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&reuse_addr,sizeof(reuse_addr)); - - server.sin_family=AF_INET; - server.sin_addr.s_addr=INADDR_ANY; - server.sin_port=htons((unsigned int)port); + int *s = NULL, *slist = NULL, maxs, error; + int reuse_addr = 1; + struct addrinfo hints, *r = NULL, *res; + char *aport = NULL; + + error = asprintf(&aport, "%d", port); + if (error < 0) + PrintMessage(Warning,"Memory Alloc Fails [%!s]."); + else { + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(NULL, aport, &hints, &res); + if (error) + PrintMessage(Warning,"%s [%!s].",gai_strerror(error)); + if (aport) + free (aport); + + if (!error) { + for (maxs = 0, r = res; r; r = r->ai_next, maxs++); + slist = malloc ((maxs+1) * sizeof(int)); + if (!slist) + PrintMessage(Warning,"Memory Alloc Fails [%!s]."); + else { + slist[0] = 0; /* counting number of sockets */ + + s = slist+1; + for (r = res; r; r = r->ai_next) { + *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if (*s < 0) { + PrintMessage(Warning,"Cannot create server socket [%!s]."); + continue; + } + setsockopt(*s,SOL_SOCKET,SO_REUSEADDR,&reuse_addr,sizeof(reuse_addr)); + + if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) { + PrintMessage(Warning,"Failed to bind server socket [%!s]."); + close (*s); + continue; + } + if (listen(*s, 4) < 0) { + close (*s); + continue; + } + slist[0] = slist[0] + 1; + s++; + } + } + } else + slist = NULL; + } + + + if (res) freeaddrinfo(res); + + if (slist && !slist[0]) { + PrintMessage(Warning,"Failed to bind server socket [%!s]."); + free (slist); + slist = NULL; + } - retval=bind(s,(struct sockaddr*)&server,sizeof(server)); - if(retval==-1) - {PrintMessage(Warning,"Failed to bind server socket [%!s].");return(-1);} + if (!slist) + errno = -1; - listen(s,4); - - return(s); + return (slist); } @@ -209,35 +295,43 @@ int SocketRemoteName(int socket,char **name,char **ipname,int *port) { - struct sockaddr_in server; - int length=sizeof(server),retval; - static char host[MAXHOSTNAMELEN],ip[16]; - struct hostent* hp=NULL; - - retval=getpeername(socket,(struct sockaddr*)&server,&length); - if(retval==-1) - PrintMessage(Warning,"Failed to get socket peername [%!s]."); - else - { - hp=gethostbyaddr((char*)&server.sin_addr,sizeof(server.sin_addr),AF_INET); - if(hp) - strcpy(host,hp->h_name); - else - strcpy(host,inet_ntoa(server.sin_addr)); - - strcpy(ip,inet_ntoa(server.sin_addr)); + struct sockaddr_storage server; + int length=sizeof(server),retval,error; + static char host[NI_MAXHOST],ip[NI_MAXHOST],portstr[NI_MAXSERV]; + + error = getpeername(socket,(struct sockaddr*)&server,&length); + if(error) { + PrintMessage(Warning,"Failed to get socket peername [%!s]."); + retval = error; + } else { + error = getnameinfo((struct sockaddr*)&server, length, host, + NI_MAXHOST, NULL, 0, 0); + retval = getnameinfo((struct sockaddr*)&server, length, ip, + NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (error) + retval = error; + + error = getnameinfo((struct sockaddr*)&server, length, NULL, 0, + portstr, NI_MAXSERV, 0); + + if (error) + retval = getnameinfo((struct sockaddr*)&server, length, ip, + NI_MAXHOST, portstr, NI_MAXSERV, + NI_NUMERICSERV); + if (retval) + PrintMessage(Warning,"Failed Name Lookup [%!s]: %s.", gai_strerror(retval)); - if(name) - *name=host; + if(name) + *name=host; #ifdef __CYGWIN__ - if(!strcmp(ip,"127.0.0.1")) - *name="localhost"; + if(!strcmp(ip,"127.0.0.1")) + *name="localhost"; #endif - if(ipname) - *ipname=ip; - if(port) - *port=ntohs(server.sin_port); - } + if(ipname) + *ipname=ip; + if(port) + *port=atoi(portstr); + } return(retval); } @@ -259,37 +353,35 @@ int SocketLocalName(int socket,char **name,char **ipname,int *port) { - struct sockaddr_in server; - int length=sizeof(server),retval; - static char host[MAXHOSTNAMELEN],ip[16]; - struct hostent* hp=NULL; - - retval=getsockname(socket,(struct sockaddr*)&server,&length); - if(retval==-1) - PrintMessage(Warning,"Failed to get socket name [%!s]."); - else - { - hp=gethostbyaddr((char*)&server.sin_addr,sizeof(server.sin_addr),AF_INET); - if(hp) - strcpy(host,hp->h_name); - else - strcpy(host,inet_ntoa(server.sin_addr)); - - strcpy(ip,inet_ntoa(server.sin_addr)); - + struct sockaddr_storage server; + int length=sizeof(server), retval, error; + static char host[NI_MAXHOST],ip[NI_MAXHOST],portstr[NI_MAXSERV]; + + error = getsockname(socket,(struct sockaddr*)&server,&length); + if(error) { + retval = error; + PrintMessage(Warning,"Failed to get socket name [%!s]."); + } + else { + error = name ? getnameinfo((struct sockaddr*)&server, length, host, + NI_MAXHOST, NULL, 0, 0) : 0; + retval = ipname ? getnameinfo((struct sockaddr*)&server, length, ip, + NI_MAXHOST, NULL, NI_MAXSERV, NI_NUMERICHOST) : 0; + if (error) + retval = error; + + retval = port ? getnameinfo((struct sockaddr*)&server, length, NULL, 0, + portstr, NI_MAXSERV, NI_NUMERICSERV) : 0; + } + if(name) - *name=host; -#ifdef __CYGWIN__ - if(!strcmp(ip,"127.0.0.1")) - *name="localhost"; -#endif + *name=host; if(ipname) - *ipname=ip; + *ipname=ip; if(port) - *port=ntohs(server.sin_port); - } - - return(retval); + *port=atoi(portstr); + + return(retval); }