From 93248e1cd75da47980e0d69428747ff6471be1ed Mon Sep 17 00:00:00 2001 From: Adrian Friedli Date: Thu, 9 Sep 2010 16:02:21 +0200 Subject: [PATCH 5/5] IPv6 for Windows --- include/enet/enet.h | 6 +- include/enet/win32.h | 1 + win32.c | 237 ++++++++++++++++++++++++++++++++------------------ 3 files changed, 160 insertions(+), 84 deletions(-) diff --git a/include/enet/enet.h b/include/enet/enet.h index 616fe7f..54e3b3b 100644 --- a/include/enet/enet.h +++ b/include/enet/enet.h @@ -77,7 +77,11 @@ extern const ENetHostAddress ENET_HOST_BROADCAST; /**< specifies a IPv4 subne typedef struct _ENetAddress { ENetHostAddress host; - enet_uint32 scopeID; //FIXME: this is of different size on Windows +#ifdef WIN32 + u_long scopeID; +#else + uint32_t scopeID; +#endif enet_uint16 port; } ENetAddress; diff --git a/include/enet/win32.h b/include/enet/win32.h index 0e1cf0c..9f3f6e5 100644 --- a/include/enet/win32.h +++ b/include/enet/win32.h @@ -14,6 +14,7 @@ #include #include +#include typedef SOCKET ENetSocket; diff --git a/win32.c b/win32.c index e1fae23..dbbe85a 100644 --- a/win32.c +++ b/win32.c @@ -52,77 +52,139 @@ enet_time_set (enet_uint32 newTimeBase) timeBase = (enet_uint32) timeGetTime () - newTimeBase; } -int -enet_address_set_host (ENetAddress * address, const char * name) +static enet_uint16 +enet_af (ENetAddressFamily family) { - struct hostent * hostEntry; + if (family == ENET_IPV4) + return AF_INET; + if (family == ENET_IPV6) + return AF_INET6; + return 0; +} + +static socklen_t +enet_sa_size (ENetAddressFamily family) +{ + if (family == ENET_IPV4) + return sizeof (SOCKADDR_IN); + if (family == ENET_IPV6) + return sizeof (SOCKADDR_IN6); + return 0; +} - hostEntry = gethostbyname (name); - if (hostEntry == NULL || - hostEntry -> h_addrtype != AF_INET) +static ENetAddressFamily +enet_address_set_address (ENetAddress * address, const SOCKADDR * sin) +{ + memset (address, 0, sizeof (ENetAddress)); + if (sin -> sa_family == AF_INET) { - unsigned long host = inet_addr (name); - if (host == INADDR_NONE) - return -1; - address -> host = host; - return 0; + address -> host = enet_address_map4 ((((SOCKADDR_IN *) sin) -> sin_addr.s_addr)); + //address -> scopeID = 0; + address -> port = ENET_NET_TO_HOST_16 (((SOCKADDR_IN *) sin) -> sin_port); + return ENET_IPV4; } + if (sin -> sa_family == AF_INET6) + { + address -> host = * (ENetHostAddress *) & ((SOCKADDR_IN6 *) sin) -> sin6_addr; + address -> scopeID = ((SOCKADDR_IN6 *) sin) -> sin6_scope_id; + address -> port = ENET_NET_TO_HOST_16 (((SOCKADDR_IN6 *) sin) -> sin6_port); + return ENET_IPV6; + } + return ENET_NO_ADDRESS_FAMILY; +} - address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0]; - - return 0; +static int +enet_address_set_sin (SOCKADDR * sin, const ENetAddress * address, ENetAddressFamily family) +{ + memset (sin, 0, enet_sa_size(family)); + if (family == ENET_IPV4 && + (enet_get_address_family (address) == ENET_IPV4 || + !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress)))) + { + ((SOCKADDR_IN *) sin) -> sin_family = AF_INET; + ((SOCKADDR_IN *) sin) -> sin_addr = * (IN_ADDR *) & address -> host.addr[12]; + ((SOCKADDR_IN *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port); + return 0; + } + else if (family == ENET_IPV6) + { + ((SOCKADDR_IN6 *) sin) -> sin6_family = AF_INET6; + ((SOCKADDR_IN6 *) sin) -> sin6_addr = * (IN6_ADDR *) & address -> host; + ((SOCKADDR_IN6 *) sin) -> sin6_scope_id = address -> scopeID; + ((SOCKADDR_IN6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port); + return 0; + } + return -1; } int -enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) +enet_address_set_host (ENetAddress * address, const char * name) { - char * addr = inet_ntoa (* (struct in_addr *) & address -> host); - if (addr == NULL) + enet_uint16 port = address -> port; + ADDRINFO hints; + ADDRINFO * result; + ADDRINFO * res; + + memset(& hints, 0, sizeof (hints)); + hints.ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG; + hints.ai_family = AF_UNSPEC; + + if ( getaddrinfo(name, NULL, &hints, &result) ) return -1; - strncpy (name, addr, nameLength); + + for (res = result; res != NULL; res = res -> ai_next) + { + if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY ) + break; + } + + address -> port = port; + freeaddrinfo(result); + if (res == NULL) return -1; + return 0; } -int -enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) +static int +enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags) { - struct in_addr in; - struct hostent * hostEntry; - - in.s_addr = address -> host; - - hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET); - if (hostEntry == NULL) - return enet_address_get_host_ip (address, name, nameLength); + SOCKADDR_STORAGE sin; + enet_address_set_sin((SOCKADDR *) & sin, address, ENET_IPV6); - strncpy (name, hostEntry -> h_name, nameLength); + if ( getnameinfo((SOCKADDR *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags)) + return -1; return 0; } int -enet_socket_bind (ENetSocket socket, const ENetAddress * address) +enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength) { - struct sockaddr_in sin; + return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST); +} - memset (& sin, 0, sizeof (struct sockaddr_in)); +int +enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength) +{ + return enet_address_get_host_x(address, name, nameLength, 0); +} - sin.sin_family = AF_INET; +int +enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family) +{ + SOCKADDR_STORAGE sin; if (address != NULL) { - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; + enet_address_set_sin((SOCKADDR *) & sin, address, family); } else { - sin.sin_port = 0; - sin.sin_addr.s_addr = INADDR_ANY; + ENetAddress address_ = { ENET_HOST_ANY, 0, 0 }; + enet_address_set_sin((SOCKADDR *) & sin, & address_, family); } - return bind (socket, - (struct sockaddr *) & sin, - sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; + return bind (socket, (SOCKADDR *) & sin, enet_sa_size(family)) == SOCKET_ERROR ? -1 : 0; } int @@ -132,7 +194,7 @@ enet_socket_listen (ENetSocket socket, int backlog) } ENetSocket -enet_socket_create (ENetSocketType type) +enet_socket_create (ENetSocketType type, ENetAddressFamily family) { return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); } @@ -173,28 +235,23 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value) } int -enet_socket_connect (ENetSocket socket, const ENetAddress * address) +enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family) { - struct sockaddr_in sin; - - memset (& sin, 0, sizeof (struct sockaddr_in)); + SOCKADDR_STORAGE sin; + enet_address_set_sin((SOCKADDR *) & sin, address, family); - sin.sin_family = AF_INET; - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; - - return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0; + return connect (socket, (SOCKADDR *) & sin, enet_sa_size(family)) == SOCKET_ERROR ? -1 : 0; } ENetSocket -enet_socket_accept (ENetSocket socket, ENetAddress * address) +enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family) { SOCKET result; - struct sockaddr_in sin; - int sinLength = sizeof (struct sockaddr_in); + SOCKADDR_STORAGE sin; + int sinLength = enet_sa_size (family); result = accept (socket, - address != NULL ? (struct sockaddr *) & sin : NULL, + address != NULL ? (SOCKADDR *) & sin : NULL, address != NULL ? & sinLength : NULL); if (result == INVALID_SOCKET) @@ -202,8 +259,7 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address) if (address != NULL) { - address -> host = (enet_uint32) sin.sin_addr.s_addr; - address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + enet_address_set_address(address, (SOCKADDR *) & sin); } return result; @@ -219,18 +275,15 @@ int enet_socket_send (ENetSocket socket, const ENetAddress * address, const ENetBuffer * buffers, - size_t bufferCount) + size_t bufferCount, + ENetAddressFamily family) { - struct sockaddr_in sin; + SOCKADDR_STORAGE sin; DWORD sentLength; if (address != NULL) { - memset (& sin, 0, sizeof (struct sockaddr_in)); - - sin.sin_family = AF_INET; - sin.sin_port = ENET_HOST_TO_NET_16 (address -> port); - sin.sin_addr.s_addr = address -> host; + enet_address_set_sin((SOCKADDR *) & sin, address, family); } if (WSASendTo (socket, @@ -238,8 +291,8 @@ enet_socket_send (ENetSocket socket, (DWORD) bufferCount, & sentLength, 0, - address != NULL ? (struct sockaddr *) & sin : 0, - address != NULL ? sizeof (struct sockaddr_in) : 0, + address != NULL ? (SOCKADDR *) & sin : 0, + address != NULL ? enet_sa_size (family) : 0, NULL, NULL) == SOCKET_ERROR) { @@ -256,19 +309,20 @@ int enet_socket_receive (ENetSocket socket, ENetAddress * address, ENetBuffer * buffers, - size_t bufferCount) + size_t bufferCount, + ENetAddressFamily family) { - INT sinLength = sizeof (struct sockaddr_in); + INT sinLength = enet_sa_size (family); DWORD flags = 0, recvLength; - struct sockaddr_in sin; + SOCKADDR_STORAGE sin; if (WSARecvFrom (socket, (LPWSABUF) buffers, (DWORD) bufferCount, & recvLength, & flags, - address != NULL ? (struct sockaddr *) & sin : NULL, + address != NULL ? (SOCKADDR *) & sin : NULL, address != NULL ? & sinLength : NULL, NULL, NULL) == SOCKET_ERROR) @@ -288,8 +342,7 @@ enet_socket_receive (ENetSocket socket, if (address != NULL) { - address -> host = (enet_uint32) sin.sin_addr.s_addr; - address -> port = ENET_NET_TO_HOST_16 (sin.sin_port); + enet_address_set_address(address, (SOCKADDR *) & sin); } return (int) recvLength; @@ -307,25 +360,41 @@ enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocket } int -enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout) +enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout) { fd_set readSet, writeSet; struct timeval timeVal; int selectCount; - + timeVal.tv_sec = timeout / 1000; timeVal.tv_usec = (timeout % 1000) * 1000; - + FD_ZERO (& readSet); FD_ZERO (& writeSet); if (* condition & ENET_SOCKET_WAIT_SEND) - FD_SET (socket, & writeSet); + { + if (socket4 != ENET_SOCKET_NULL) + FD_SET (socket4, & writeSet); + if (socket6 != ENET_SOCKET_NULL) + FD_SET (socket6, & writeSet); + } if (* condition & ENET_SOCKET_WAIT_RECEIVE) - FD_SET (socket, & readSet); + { + if (socket4 != ENET_SOCKET_NULL) + FD_SET (socket4, & readSet); + if (socket6 != ENET_SOCKET_NULL) + FD_SET (socket6, & readSet); + } - selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal); + ENetSocket maxSocket = 0; + if (socket4 != ENET_SOCKET_NULL) + maxSocket = socket4; + if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket) + maxSocket = socket6; + + selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal); if (selectCount < 0) return -1; @@ -335,14 +404,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou if (selectCount == 0) return 0; - if (FD_ISSET (socket, & writeSet)) - * condition |= ENET_SOCKET_WAIT_SEND; - - if (FD_ISSET (socket, & readSet)) - * condition |= ENET_SOCKET_WAIT_RECEIVE; + if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) || + (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) ) + * condition |= ENET_SOCKET_WAIT_SEND; + + if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) || + (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) ) + * condition |= ENET_SOCKET_WAIT_RECEIVE; return 0; -} +} #endif -- 1.7.1