$NetBSD$
--- sockets.c.orig	Sun Oct  3 02:27:23 1999
+++ sockets.c	Mon Oct  4 22:53:17 1999
@@ -15,6 +15,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <errno.h>
 #include <unistd.h>
@@ -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);
 }
 
 
