diff -ur old/SDLnet.c new/SDLnet.c --- old/SDLnet.c 2016-01-03 02:57:09.000000000 -0500 +++ new/SDLnet.c 2016-08-02 20:06:16.681300951 -0400 @@ -134,29 +134,92 @@ } } +/* SDLNet_SocktoIP and SDLNet_IPtoSock functions are added by : Nitin Jain (nitin.j4@samsung.com) */ + +void SDLNet_SocktoIP(const struct sockaddr *sock, IPaddress *ip) +{ + if(sock->sa_family == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in *) sock; + inet_ntop(AF_INET, &(addr->sin_addr), ip->ipstr, INET_ADDRSTRLEN); + ip->f_type = AF_INET; + ip->port = addr->sin_port; + + } + else if(sock->sa_family == AF_INET6) + { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sock; + inet_ntop(AF_INET6, &(addr->sin6_addr), ip->ipstr, INET6_ADDRSTRLEN); + ip->f_type = AF_INET6; + ip->port = addr->sin6_port; + } + else + SDLNet_SetError("Wrong Family Type : SDLNet_SocktoIP \n"); +} + +void SDLNet_IPtoSock(const IPaddress *ip, struct sockaddr *sock) +{ + if(ip->f_type == AF_INET) + { + struct sockaddr_in *addr = (struct sockaddr_in *) sock; + addr->sin_family = AF_INET; + addr->sin_port = ip->port; + inet_pton(AF_INET, ip->ipstr , &(addr->sin_addr)); + } + else if(ip->f_type == AF_INET6) + { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sock; + addr->sin6_family = AF_INET6; + addr->sin6_port = ip->port; + inet_pton(AF_INET6, ip->ipstr, &(addr->sin6_addr)); + } + else + SDLNet_SetError("Wrong Family Type : SDLNet_IPtoSock \n"); +} + /* Resolve a host name and port to an IP address in network form */ int SDLNet_ResolveHost(IPaddress *address, const char *host, Uint16 port) { int retval = 0; - - /* Perform the actual host resolution */ - if ( host == NULL ) { - address->host = INADDR_ANY; - } else { - address->host = inet_addr(host); - if ( address->host == INADDR_NONE ) { - struct hostent *hp; - - hp = gethostbyname(host); - if ( hp ) { - SDL_memcpy(&address->host,hp->h_addr,hp->h_length); - } else { - retval = -1; - } + char buff[PORTLEN]; + struct addrinfo *addrinfo; + struct addrinfo hints; + SDL_memset(&hints, 0, sizeof(hints)); + snprintf(buff,PORTLEN,"%d",port); + + if( host == NULL) + { + address->sockflag = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + } + else + { + address->sockflag= 1; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = 0; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + } + retval = getaddrinfo(host, buff, &hints, &addrinfo); + + if(retval) + { + SDLNet_SetError("getnameinfo fails with Err value: %d\n", retval); } - } + else + { + if(addrinfo) + { + SDLNet_SocktoIP(addrinfo->ai_addr, address); + freeaddrinfo(addrinfo); + } + } + address->port = SDLNet_Read16(&port); - + /* Return the status */ return(retval); } @@ -172,16 +235,21 @@ */ const char *SDLNet_ResolveIP(const IPaddress *ip) { - struct hostent *hp; - struct in_addr in; - - hp = gethostbyaddr((const char *)&ip->host, sizeof(ip->host), AF_INET); - if ( hp != NULL ) { - return hp->h_name; - } - - in.s_addr = ip->host; - return inet_ntoa(in); + int error = 0; + int s_len = 0; + struct sockaddr_storage sock; + SDLNet_IPtoSock(ip, (struct sockaddr *)&sock); + s_len = sizeof(struct sockaddr_storage); + error = getnameinfo((struct sockaddr *)&sock, s_len, ip->h_name, HOSTLEN, NULL,0, 0); + if(error) + { + SDLNet_SetError("getnameinfo fails\n"); + return NULL; + } + else + { + return (const char *)ip->h_name; + } } int SDLNet_GetLocalAddresses(IPaddress *addresses, int maxcount) @@ -196,9 +264,8 @@ struct ifconf conf; char data[4096]; struct ifreq *ifr; - struct sockaddr_in *sock_addr; + sock = socket(AF_INET6, SOCK_DGRAM, 0); - sock = socket(AF_INET, SOCK_DGRAM, 0); if ( sock == INVALID_SOCKET ) { return 0; } @@ -212,14 +279,10 @@ ifr = (struct ifreq*)data; while ((char*)ifr < data+conf.ifc_len) { - if (ifr->ifr_addr.sa_family == AF_INET) { - if (count < maxcount) { - sock_addr = (struct sockaddr_in*)&ifr->ifr_addr; - addresses[count].host = sock_addr->sin_addr.s_addr; - addresses[count].port = sock_addr->sin_port; - } - ++count; + if (count < maxcount) { + SDLNet_SocktoIP(&ifr->ifr_addr , &addresses[count]); } + ++count; ifr = (struct ifreq*)((char*)ifr + _SIZEOF_ADDR_IFREQ(*ifr)); } closesocket(sock); diff -ur old/SDL_net.h new/SDL_net.h --- old/SDL_net.h 2016-01-03 02:57:09.000000000 -0500 +++ new/SDL_net.h 2016-08-02 20:04:24.620920109 -0400 @@ -42,6 +42,10 @@ #include "SDL.h" #include "SDL_endian.h" #include "SDL_version.h" +#include + +#define HOSTLEN 1024 +#define PORTLEN 6 typedef SDL_version SDLNet_version; @@ -88,7 +92,14 @@ /***********************************************************************/ typedef struct { - Uint32 host; /* 32-bit IPv4 host address */ +/* DUAL_IP macro enables both, IPv4 and IPv6 support for SDL_net + Fields under DUAL_IP added by : Nitin Jain (nitin.j4@samsung.com) +*/ + char ipstr[INET6_ADDRSTRLEN]; /* 128-bit IPv6 or 32-bit IPv4 host address in string format */ + Uint8 f_type; /* Family type - AF_INET or AF_INET6 */ + Uint8 sockflag; /* If 1 then act as a client, if 0 then act as a server */ + char h_name[HOSTLEN]; /* Host name */ + Uint16 port; /* 16-bit protocol port */ } IPaddress; @@ -170,6 +181,11 @@ extern DECLSPEC void SDLCALL SDLNet_TCP_Close(TCPsocket sock); +extern DECLSPEC void SDLCALL SDLNet_SocktoIP(const struct sockaddr *sock, IPaddress *ip); +extern DECLSPEC void SDLCALL SDLNet_IPtoSock(const IPaddress *ip, struct sockaddr *sock); + + + /***********************************************************************/ /* UDP network API */ /***********************************************************************/ @@ -211,7 +227,7 @@ internally in network (big endian) byte order, in addresses, etc. This allows other systems to send to this socket via a known port. */ -extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port); +extern DECLSPEC UDPsocket SDLCALL SDLNet_UDP_Open(Uint16 port, const char *host); /* Set the percentage of simulated packet loss for packets sent on the socket. */ diff -ur old/SDLnetsys.h new/SDLnetsys.h --- old/SDLnetsys.h 2016-01-03 02:57:09.000000000 -0500 +++ new/SDLnetsys.h 2016-08-02 20:05:03.391051909 -0400 @@ -61,6 +61,7 @@ #include #include #include +#include "SDL_net.h" #endif /* WIN32 */ /* FIXME: What platforms need this? */ @@ -78,6 +79,8 @@ #define SOCKET int #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 +//void SDLNet_SocktoIP(const struct sockaddr *sock, IPaddress *ip); +//void SDLNet_IPtoSock(const IPaddress *ip, struct sockaddr *sock); #endif /* __USE_W32_SOCKETS */ #ifdef __USE_W32_SOCKETS diff -ur old/SDLnetTCP.c new/SDLnetTCP.c --- old/SDLnetTCP.c 2016-01-03 02:57:09.000000000 -0500 +++ new/SDLnetTCP.c 2016-08-02 20:02:18.077156297 -0400 @@ -46,7 +46,7 @@ TCPsocket SDLNet_TCP_Open(IPaddress *ip) { TCPsocket sock; - struct sockaddr_in sock_addr; + struct sockaddr_in6 sock_addr; /* Allocate a TCP socket structure */ sock = (TCPsocket)SDL_malloc(sizeof(*sock)); @@ -54,104 +54,81 @@ SDLNet_SetError("Out of memory"); goto error_return; } - - /* Open the socket */ - sock->channel = socket(AF_INET, SOCK_STREAM, 0); - if ( sock->channel == INVALID_SOCKET ) { - SDLNet_SetError("Couldn't create socket"); - goto error_return; - } - - /* Connect to remote, or bind locally, as appropriate */ - if ( (ip->host != INADDR_NONE) && (ip->host != INADDR_ANY) ) { - - // ######### Connecting to remote - - SDL_memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = ip->host; - sock_addr.sin_port = ip->port; - - /* Connect to the remote host */ - if ( connect(sock->channel, (struct sockaddr *)&sock_addr, - sizeof(sock_addr)) == SOCKET_ERROR ) { - SDLNet_SetError("Couldn't connect to remote host"); - goto error_return; - } - sock->sflag = 0; - } else { - - // ########## Binding locally - - SDL_memset(&sock_addr, 0, sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = INADDR_ANY; - sock_addr.sin_port = ip->port; - -/* - * Windows gets bad mojo with SO_REUSEADDR: - * http://www.devolution.com/pipermail/sdl/2005-September/070491.html - * --ryan. - */ -#ifndef WIN32 - /* allow local address reuse */ - { int yes = 1; - setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof(yes)); - } -#endif - - /* Bind the socket for listening */ - if ( bind(sock->channel, (struct sockaddr *)&sock_addr, - sizeof(sock_addr)) == SOCKET_ERROR ) { - SDLNet_SetError("Couldn't bind to local port"); - goto error_return; - } - if ( listen(sock->channel, 5) == SOCKET_ERROR ) { - SDLNet_SetError("Couldn't listen to local port"); - goto error_return; - } - - /* Set the socket to non-blocking mode for accept() */ -#if defined(__BEOS__) && defined(SO_NONBLOCK) - /* On BeOS r5 there is O_NONBLOCK but it's for files only */ - { - long b = 1; - setsockopt(sock->channel, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); - } -#elif defined(O_NONBLOCK) - { - fcntl(sock->channel, F_SETFL, O_NONBLOCK); - } -#elif defined(WIN32) + if(ip->sockflag) + { + int retval = 0; + struct addrinfo *addrinfo , *p; + struct addrinfo hints; + SDL_memset(&hints, 0, sizeof(hints)); + char buff[PORTLEN]; + snprintf(buff,PORTLEN,"%d",SDL_SwapBE16(ip->port)); + + hints.ai_family = AF_UNSPEC; + hints.ai_flags = 0; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + + retval = getaddrinfo(ip->ipstr, buff, &hints, &addrinfo); + if(retval) + { + SDLNet_SetError("SDLNet_TCP_Open fails with Err number : %d\n", retval); + goto error_return; + + } + + sock->channel = -1; + for(p = addrinfo; p != NULL; p = p->ai_next) + { + if ((sock->channel = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) + { + continue; + } + if (connect(sock->channel, p->ai_addr, p->ai_addrlen) == -1) + { + close(sock->channel); + continue; + } + else + { + sock->sflag = 0; + SDLNet_SocktoIP(p->ai_addr, &sock->remoteAddress); + break; + } + } + + freeaddrinfo(p); + } + else { - unsigned long mode = 1; - ioctlsocket (sock->channel, FIONBIO, &mode); + int ok = 1; + sock->channel = socket(AF_INET6, SOCK_STREAM, 0); + if ( sock->channel == INVALID_SOCKET ) { + SDLNet_SetError("Couldn't create socket"); + goto error_return; + } + + setsockopt(sock->channel, SOL_SOCKET, SO_REUSEADDR, (char*)&ok, sizeof(ok)); + + + SDL_memset(&sock_addr, 0, sizeof(sock_addr)); + sock_addr.sin6_family = AF_INET6; + sock_addr.sin6_addr = in6addr_any; + sock_addr.sin6_port = ip->port; + + if ( bind(sock->channel, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't bind to local port"); + goto error_return; + } + + if ( listen(sock->channel, 5) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't listen to local port"); + goto error_return; + } + sock->sflag = 1; + SDLNet_SocktoIP((struct sockaddr *)&sock_addr, &sock->remoteAddress); } -#elif defined(__OS2__) - { - int dontblock = 1; - ioctl(sock->channel, FIONBIO, &dontblock); - } -#else -#warning How do we set non-blocking mode on other operating systems? -#endif - sock->sflag = 1; - } sock->ready = 0; -#ifdef TCP_NODELAY - /* Set the nodelay TCP option for real-time games */ - { int yes = 1; - setsockopt(sock->channel, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(yes)); - } -#else -#warning Building without TCP_NODELAY -#endif /* TCP_NODELAY */ - - /* Fill in the channel host address */ - sock->remoteAddress.host = sock_addr.sin_addr.s_addr; - sock->remoteAddress.port = sock_addr.sin_port; - /* The socket is ready */ return(sock); @@ -166,7 +143,8 @@ TCPsocket SDLNet_TCP_Accept(TCPsocket server) { TCPsocket sock; - struct sockaddr_in sock_addr; + struct sockaddr_in6 sock_addr; + socklen_t sock_alen; /* Only server sockets can accept */ @@ -203,8 +181,8 @@ fcntl(sock->channel, F_SETFL, flags & ~O_NONBLOCK); } #endif /* WIN32 */ - sock->remoteAddress.host = sock_addr.sin_addr.s_addr; - sock->remoteAddress.port = sock_addr.sin_port; + + SDLNet_SocktoIP((struct sockaddr *) &sock_addr, &sock->remoteAddress); sock->sflag = 0; sock->ready = 0; diff -ur old/SDLnetUDP.c new/SDLnetUDP.c --- old/SDLnetUDP.c 2016-01-03 02:57:09.000000000 -0500 +++ new/SDLnetUDP.c 2016-08-02 20:03:37.350759356 -0400 @@ -136,11 +136,9 @@ /* Open a UDP network socket If 'port' is non-zero, the UDP socket is bound to a fixed local port. */ -UDPsocket SDLNet_UDP_Open(Uint16 port) +UDPsocket SDLNet_UDP_Open(Uint16 port, const char *host) { UDPsocket sock; - struct sockaddr_in sock_addr; - socklen_t sock_len; /* Allocate a UDP socket structure */ sock = (UDPsocket)SDL_malloc(sizeof(*sock)); @@ -148,64 +146,68 @@ SDLNet_SetError("Out of memory"); goto error_return; } + SDL_memset(sock, 0, sizeof(*sock)); - SDL_memset(&sock_addr, 0, sizeof(sock_addr)); + if(port) + { + struct sockaddr_in6 sock_addr; + SDL_memset(&sock_addr, 0, sizeof(sock_addr)); - /* Open the socket */ - sock->channel = socket(AF_INET, SOCK_DGRAM, 0); - if ( sock->channel == INVALID_SOCKET ) - { - SDLNet_SetError("Couldn't create socket"); - goto error_return; - } + /* Open the socket */ + sock->channel = socket(AF_INET6, SOCK_DGRAM, 0); + if ( sock->channel == INVALID_SOCKET ) + { + SDLNet_SetError("Couldn't create socket"); + goto error_return; + } - /* Bind locally, if appropriate */ - sock_addr.sin_family = AF_INET; - sock_addr.sin_addr.s_addr = INADDR_ANY; - sock_addr.sin_port = SDLNet_Read16(&port); - - /* Bind the socket for listening */ - if ( bind(sock->channel, (struct sockaddr *)&sock_addr, - sizeof(sock_addr)) == SOCKET_ERROR ) { - SDLNet_SetError("Couldn't bind to local port"); - goto error_return; - } - /* Get the bound address and port */ - sock_len = sizeof(sock_addr); - if ( getsockname(sock->channel, (struct sockaddr *)&sock_addr, &sock_len) < 0 ) { - SDLNet_SetError("Couldn't get socket address"); - goto error_return; - } + sock_addr.sin6_family = AF_INET6; + sock_addr.sin6_addr = in6addr_any; + sock_addr.sin6_port = SDL_SwapBE16(port); + + /* Bind the socket for listening */ + if ( bind(sock->channel, (struct sockaddr *)&sock_addr, + sizeof(sock_addr)) == SOCKET_ERROR ) { + SDLNet_SetError("Couldn't bind to local port"); + goto error_return; + } - /* Fill in the channel host address */ - sock->address.host = sock_addr.sin_addr.s_addr; - sock->address.port = sock_addr.sin_port; + /* Fill in the channel host address */ + SDLNet_SocktoIP((struct sockaddr *)&sock_addr, &sock->address); #ifdef SO_BROADCAST - /* Allow LAN broadcasts with the socket */ - { int yes = 1; - setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); - } + /* Allow LAN broadcasts with the socket */ + { int yes = 1; + setsockopt(sock->channel, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes)); + } #endif -#ifdef IP_ADD_MEMBERSHIP - /* Receive LAN multicast packets on 224.0.0.1 - This automatically works on Mac OS X, Linux and BSD, but needs - this code on Windows. - */ - /* A good description of multicast can be found here: - http://www.docs.hp.com/en/B2355-90136/ch05s05.html - */ - /* FIXME: Add support for joining arbitrary groups to the API */ - { - struct ip_mreq g; + } + else + { + struct addrinfo *addrinfo , *p; + struct addrinfo hints; + char buff[PORTLEN]; - g.imr_multiaddr.s_addr = inet_addr("224.0.0.1"); - g.imr_interface.s_addr = INADDR_ANY; - setsockopt(sock->channel, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char*)&g, sizeof(g)); - } -#endif + SDL_memset(&hints, 0, sizeof hints); + snprintf(buff,PORTLEN,"%d",port); + + hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6 + hints.ai_socktype = SOCK_DGRAM; + + getaddrinfo(host, buff, &hints, &addrinfo); + + for(p = addrinfo; p != NULL; p = p->ai_next) + { + if( (sock->channel = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) + { + continue; + } + SDLNet_SocktoIP(p->ai_addr, &sock->address); + break; + } + freeaddrinfo(addrinfo); + } /* The socket is ready */ @@ -329,7 +331,7 @@ struct UDP_channel *binding; int status; int sock_len; - struct sockaddr_in sock_addr; + struct sockaddr_storage sock_addr; if ( sock == NULL ) { SDLNet_SetError("Passed a NULL socket"); @@ -355,9 +357,7 @@ if ( packets[i]->channel < 0 ) { - sock_addr.sin_addr.s_addr = packets[i]->address.host; - sock_addr.sin_port = packets[i]->address.port; - sock_addr.sin_family = AF_INET; + SDLNet_IPtoSock(&packets[i]->address, (struct sockaddr *)&sock_addr); status = sendto(sock->channel, packets[i]->data, packets[i]->len, 0, (struct sockaddr *)&sock_addr,sock_len); @@ -378,12 +378,11 @@ for ( j=binding->numbound-1; j>=0; --j ) { - sock_addr.sin_addr.s_addr = binding->address[j].host; - sock_addr.sin_port = binding->address[j].port; - sock_addr.sin_family = AF_INET; + SDLNet_IPtoSock(&binding->address[j], (struct sockaddr *)&sock_addr); status = sendto(sock->channel, packets[i]->data, packets[i]->len, 0, (struct sockaddr *)&sock_addr,sock_len); + if ( status >= 0 ) { packets[i]->status = status; @@ -441,7 +440,7 @@ int numrecv, i, j; struct UDP_channel *binding; socklen_t sock_len; - struct sockaddr_in sock_addr; + struct sockaddr_storage sock_addr; if ( sock == NULL ) { return(0); @@ -451,7 +450,6 @@ while ( packets[numrecv] && SocketReady(sock->channel) ) { UDPpacket *packet; - packet = packets[numrecv]; sock_len = sizeof(sock_addr); @@ -461,8 +459,7 @@ &sock_len); if ( packet->status >= 0 ) { packet->len = packet->status; - packet->address.host = sock_addr.sin_addr.s_addr; - packet->address.port = sock_addr.sin_port; + SDLNet_SocktoIP((struct sockaddr *)&sock_addr , &packet->address); packet->channel = -1; for (i=(SDLNET_MAX_UDPCHANNELS-1); i>=0; --i ) @@ -471,8 +468,8 @@ for ( j=binding->numbound-1; j>=0; --j ) { - if ( (packet->address.host == binding->address[j].host) && - (packet->address.port == binding->address[j].port) ) + if(!(strcmp(packet->address.ipstr , binding->address[j].ipstr)) && + (packet->address.port == binding->address[j].port) ) { packet->channel = i; goto foundit; /* break twice */ diff -ur old/showinterfaces.c new/showinterfaces.c --- old/showinterfaces.c 2016-01-03 02:57:09.000000000 -0500 +++ new/showinterfaces.c 2016-08-02 20:03:49.744134842 -0400 @@ -26,16 +26,11 @@ { IPaddress addresses[MAX_ADDRESSES]; int i, count; - count = SDLNet_GetLocalAddresses(addresses, MAX_ADDRESSES); + SDL_Log("Found %d local addresses", count); for ( i = 0; i < count; ++i ) { - SDL_Log("%d: %d.%d.%d.%d - %s", i+1, - (addresses[i].host >> 0) & 0xFF, - (addresses[i].host >> 8) & 0xFF, - (addresses[i].host >> 16) & 0xFF, - (addresses[i].host >> 24) & 0xFF, - SDLNet_ResolveIP(&addresses[i])); + SDL_Log("%d: %s - %s", i+1,addresses[i].ipstr,SDLNet_ResolveIP(&addresses[i])); } return 0; }