|
@@ -44,12 +44,15 @@
|
|
|
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
|
|
|
#endif
|
|
|
|
|
|
+ #define HAS_INET_PTON 1
|
|
|
+ #define HAS_INET_NTOP 1
|
|
|
+
|
|
|
#ifndef ENET_NO_PRAGMA_LINK
|
|
|
#pragma comment(lib, "ws2_32.lib")
|
|
|
#pragma comment(lib, "winmm.lib")
|
|
|
#endif
|
|
|
|
|
|
- #include <winsock2.h>
|
|
|
+ #include <ws2tcpip.h>
|
|
|
|
|
|
typedef SOCKET ENetSocket;
|
|
|
|
|
@@ -175,7 +178,8 @@
|
|
|
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
|
|
|
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
|
|
|
|
|
|
-#define ENET_HOST_ANY 0
|
|
|
+#define ENET_IPV6 1
|
|
|
+#define ENET_HOST_ANY in6addr_any
|
|
|
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
|
|
|
#define ENET_PORT_ANY 0
|
|
|
|
|
@@ -445,7 +449,8 @@ extern "C" {
|
|
|
ENET_SOCKOPT_RCVTIMEO = 6,
|
|
|
ENET_SOCKOPT_SNDTIMEO = 7,
|
|
|
ENET_SOCKOPT_ERROR = 8,
|
|
|
- ENET_SOCKOPT_NODELAY = 9
|
|
|
+ ENET_SOCKOPT_NODELAY = 9,
|
|
|
+ ENET_SOCKOPT_IPV6_V6ONLY = 10,
|
|
|
} ENetSocketOption;
|
|
|
|
|
|
typedef enum _ENetSocketShutdown {
|
|
@@ -465,10 +470,13 @@ extern "C" {
|
|
|
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
|
|
|
*/
|
|
|
typedef struct _ENetAddress {
|
|
|
- enet_uint32 host;
|
|
|
+ struct in6_addr host;
|
|
|
enet_uint16 port;
|
|
|
+ enet_uint16 sin6_scope_id;
|
|
|
} ENetAddress;
|
|
|
|
|
|
+ #define in6_equal(in6_addr_a, in6_addr_b) (memcmp(&in6_addr_a, &in6_addr_b, sizeof(struct in6_addr)) == 0)
|
|
|
+
|
|
|
/**
|
|
|
* Packet flag bit constants.
|
|
|
*
|
|
@@ -1469,12 +1477,12 @@ extern "C" {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- for (currentPeer = host->peers; currentPeer < &host->peers [host->peerCount]; ++currentPeer) {
|
|
|
+ for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) {
|
|
|
if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) {
|
|
|
if (peer == NULL) {
|
|
|
peer = currentPeer;
|
|
|
}
|
|
|
- } else if (currentPeer->state != ENET_PEER_STATE_CONNECTING && currentPeer->address.host == host->receivedAddress.host) {
|
|
|
+ } else if (currentPeer->state != ENET_PEER_STATE_CONNECTING && in6_equal(currentPeer->address.host, host->receivedAddress.host)) {
|
|
|
if (currentPeer->address.port == host->receivedAddress.port && currentPeer->connectID == command->connect.connectID) {
|
|
|
return NULL;
|
|
|
}
|
|
@@ -2169,9 +2177,9 @@ extern "C" {
|
|
|
|
|
|
if (peer->state == ENET_PEER_STATE_DISCONNECTED ||
|
|
|
peer->state == ENET_PEER_STATE_ZOMBIE ||
|
|
|
- ((host->receivedAddress.host != peer->address.host ||
|
|
|
+ ((!in6_equal(host->receivedAddress.host , peer->address.host) ||
|
|
|
host->receivedAddress.port != peer->address.port) &&
|
|
|
- peer->address.host != ENET_HOST_BROADCAST) ||
|
|
|
+ 1 /* no broadcast in ipv6 !in6_equal(peer->address.host , ENET_HOST_BROADCAST)*/) ||
|
|
|
(peer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
|
|
|
sessionID != peer->incomingSessionID)
|
|
|
) {
|
|
@@ -2828,7 +2836,7 @@ extern "C" {
|
|
|
host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
|
|
|
shouldCompress = compressedSize;
|
|
|
#ifdef ENET_DEBUG_COMPRESS
|
|
|
- printf("peer %u: compressed %u -> %u (%u%%)\n", currentPeer->incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
|
|
|
+ printf("peer %u: compressed %u->%u (%u%%)\n", currentPeer->incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
|
|
|
#endif
|
|
|
}
|
|
|
}
|
|
@@ -3990,6 +3998,10 @@ extern "C" {
|
|
|
memset(host->peers, 0, peerCount * sizeof(ENetPeer));
|
|
|
|
|
|
host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM);
|
|
|
+ if (host->socket != ENET_SOCKET_NULL) {
|
|
|
+ enet_socket_set_option (host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
|
|
|
+ }
|
|
|
+
|
|
|
if (host->socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind(host->socket, address) < 0)) {
|
|
|
if (host->socket != ENET_SOCKET_NULL) {
|
|
|
enet_socket_destroy(host->socket);
|
|
@@ -4005,6 +4017,7 @@ extern "C" {
|
|
|
enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1);
|
|
|
enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
|
|
|
enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
|
|
|
+ enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0);
|
|
|
|
|
|
if (address != NULL && enet_socket_get_address(host->socket, &host->address) < 0) {
|
|
|
host->address = *address;
|
|
@@ -4407,867 +4420,935 @@ extern "C" {
|
|
|
|
|
|
// =======================================================================//
|
|
|
// !
|
|
|
-// ! Platform Specific (Unix/Win)
|
|
|
+// ! Platform Specific (Win)
|
|
|
// !
|
|
|
// =======================================================================//
|
|
|
- #ifdef _WIN32
|
|
|
- static enet_uint64 timeBase = 0;
|
|
|
|
|
|
- int enet_initialize(void) {
|
|
|
- WORD versionRequested = MAKEWORD(1, 1);
|
|
|
- WSADATA wsaData;
|
|
|
+ #ifdef _WIN32
|
|
|
+ static enet_uint64 timeBase = 0;
|
|
|
|
|
|
- if (WSAStartup(versionRequested, &wsaData)) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ int enet_initialize(void) {
|
|
|
+ WORD versionRequested = MAKEWORD(1, 1);
|
|
|
+ WSADATA wsaData;
|
|
|
|
|
|
- if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
|
|
|
- WSACleanup();
|
|
|
- return -1;
|
|
|
- }
|
|
|
-
|
|
|
- timeBeginPeriod(1);
|
|
|
- return 0;
|
|
|
+ if (WSAStartup(versionRequested, &wsaData)) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- void enet_deinitialize(void) {
|
|
|
- timeEndPeriod(1);
|
|
|
+ if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
|
|
|
WSACleanup();
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- enet_uint64 enet_host_random_seed(void) {
|
|
|
- return (enet_uint64) timeGetTime();
|
|
|
- }
|
|
|
+ timeBeginPeriod(1);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- enet_uint64 enet_time_get(void) {
|
|
|
- return (enet_uint64) timeGetTime() - timeBase;
|
|
|
- }
|
|
|
+ void enet_deinitialize(void) {
|
|
|
+ timeEndPeriod(1);
|
|
|
+ WSACleanup();
|
|
|
+ }
|
|
|
|
|
|
- void enet_time_set(enet_uint64 newTimeBase) {
|
|
|
- timeBase = (enet_uint64) timeGetTime() - newTimeBase;
|
|
|
- }
|
|
|
+ enet_uint64 enet_host_random_seed(void) {
|
|
|
+ return (enet_uint64) timeGetTime();
|
|
|
+ }
|
|
|
|
|
|
- int enet_address_set_host_ip(ENetAddress *address, const char *name) {
|
|
|
- enet_uint8 vals [4] = { 0, 0, 0, 0 };
|
|
|
- int i;
|
|
|
+ enet_uint64 enet_time_get(void) {
|
|
|
+ return (enet_uint64) timeGetTime() - timeBase;
|
|
|
+ }
|
|
|
|
|
|
- for (i = 0; i < 4; ++i) {
|
|
|
- const char *next = name + 1;
|
|
|
- if (*name != '0') {
|
|
|
- long val = strtol(name, (char **) &next, 10);
|
|
|
- if (val < 0 || val > 255 || next == name || next - name > 3) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- vals [i] = (enet_uint8) val;
|
|
|
- }
|
|
|
+ void enet_time_set(enet_uint64 newTimeBase) {
|
|
|
+ timeBase = (enet_uint64) timeGetTime() - newTimeBase;
|
|
|
+ }
|
|
|
|
|
|
- if (*next != (i < 3 ? '.' : '\0')) {
|
|
|
+ int enet_address_set_host_ip(ENetAddress *address, const char *name) {
|
|
|
+ enet_uint8 vals [4] = { 0, 0, 0, 0 };
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < 4; ++i) {
|
|
|
+ const char *next = name + 1;
|
|
|
+ if (*name != '0') {
|
|
|
+ long val = strtol(name, (char **) &next, 10);
|
|
|
+ if (val < 0 || val > 255 || next == name || next - name > 3) {
|
|
|
return -1;
|
|
|
}
|
|
|
- name = next + 1;
|
|
|
+ vals [i] = (enet_uint8) val;
|
|
|
}
|
|
|
|
|
|
- memcpy(&address->host, vals, sizeof(enet_uint32));
|
|
|
- return 0;
|
|
|
+ if (*next != (i < 3 ? '.' : '\0')) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ name = next + 1;
|
|
|
}
|
|
|
|
|
|
- int enet_address_set_host(ENetAddress *address, const char *name) {
|
|
|
- struct hostent *hostEntry;
|
|
|
+ memcpy(&address->host, vals, sizeof(enet_uint32));
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- hostEntry = gethostbyname(name);
|
|
|
- if (hostEntry == NULL || hostEntry->h_addrtype != AF_INET) {
|
|
|
- return enet_address_set_host_ip(address, name);
|
|
|
- }
|
|
|
+ int enet_address_set_host(ENetAddress *address, const char *name) {
|
|
|
+ struct hostent * hostEntry = NULL;
|
|
|
+
|
|
|
+ hostEntry = gethostbyname(name);
|
|
|
|
|
|
- address->host = *(enet_uint32 *) hostEntry->h_addr_list [0];
|
|
|
+ if (hostEntry == NULL || hostEntry->h_addrtype != AF_INET) {
|
|
|
+ #ifdef HAS_INET_PTON
|
|
|
+ if (!inet_pton(AF_INET6, name, &address->host))
|
|
|
+ #elif _MSC_VER
|
|
|
+ #error "IPv6 Requires inet_pton"
|
|
|
+ // TODO FIXME
|
|
|
+ #else
|
|
|
+ if (!inet_aton(name, (struct in_addr *)&address->host))
|
|
|
+ #endif
|
|
|
+ { return -1; }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
- char *addr = inet_ntoa(*(struct in_addr *) &address->host);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
+ #ifdef HAS_INET_NTOP
|
|
|
+ if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL)
|
|
|
+ #else
|
|
|
+ char *addr = inet_ntoa(*(struct in_addr *) &address->host);
|
|
|
|
|
|
- if (addr == NULL) {
|
|
|
+ if (addr == NULL) {
|
|
|
+ return -1;
|
|
|
+ } else {
|
|
|
+ size_t addrLen = strlen(addr);
|
|
|
+ if (addrLen >= nameLength) {
|
|
|
return -1;
|
|
|
- } else {
|
|
|
- size_t addrLen = strlen(addr);
|
|
|
- if (addrLen >= nameLength) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- memcpy(name, addr, addrLen + 1);
|
|
|
}
|
|
|
- return 0;
|
|
|
+ memcpy(name, addr, addrLen + 1);
|
|
|
}
|
|
|
+ #endif
|
|
|
+ return -1;
|
|
|
|
|
|
- int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
- struct in_addr in;
|
|
|
- struct hostent *hostEntry;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- in.s_addr = address->host;
|
|
|
- hostEntry = gethostbyaddr((char *) &in, sizeof(struct in_addr), AF_INET);
|
|
|
+ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
+ struct in6_addr in;
|
|
|
+ struct hostent *hostEntry = NULL;
|
|
|
|
|
|
- if (hostEntry == NULL) {
|
|
|
- return enet_address_get_host_ip(address, name, nameLength);
|
|
|
- } else {
|
|
|
- size_t hostLen = strlen(hostEntry->h_name);
|
|
|
- if (hostLen >= nameLength) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- memcpy(name, hostEntry->h_name, hostLen + 1);
|
|
|
- }
|
|
|
+ in = address->host;
|
|
|
+ hostEntry = gethostbyaddr((char *)&in, sizeof(struct in6_addr), AF_INET6);
|
|
|
|
|
|
- return 0;
|
|
|
+ if (hostEntry == NULL) {
|
|
|
+ return enet_address_get_host_ip(address, name, nameLength);
|
|
|
+ } else {
|
|
|
+ size_t hostLen = strlen(hostEntry->h_name);
|
|
|
+ if (hostLen >= nameLength) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ memcpy(name, hostEntry->h_name, hostLen + 1);
|
|
|
}
|
|
|
|
|
|
- int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
- sin.sin_family = AF_INET;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
- } else {
|
|
|
- sin.sin_port = 0;
|
|
|
- sin.sin_addr.s_addr = INADDR_ANY;
|
|
|
- }
|
|
|
+ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
|
|
|
- return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
|
|
|
+ if (address != NULL) {
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16 (address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
+ } else {
|
|
|
+ sin.sin6_port = 0;
|
|
|
+ sin.sin6_addr = in6addr_any;
|
|
|
+ sin.sin6_scope_id = 0;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- int sinLength = sizeof(struct sockaddr_in);
|
|
|
-
|
|
|
- if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0;
|
|
|
+ }
|
|
|
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
+ int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int sinLength = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
- return 0;
|
|
|
+ if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_listen(ENetSocket socket, int backlog) {
|
|
|
- return listen(socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
|
|
|
- }
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16(sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
|
|
|
- ENetSocket enet_socket_create(ENetSocketType type) {
|
|
|
- return socket(PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
- }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
|
|
|
- int result = SOCKET_ERROR;
|
|
|
+ int enet_socket_listen(ENetSocket socket, int backlog) {
|
|
|
+ return listen(socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
|
|
|
+ }
|
|
|
|
|
|
- switch (option) {
|
|
|
- case ENET_SOCKOPT_NONBLOCK: {
|
|
|
- u_long nonBlocking = (u_long) value;
|
|
|
- result = ioctlsocket(socket, FIONBIO, &nonBlocking);
|
|
|
- break;
|
|
|
- }
|
|
|
+ ENetSocket enet_socket_create(ENetSocketType type) {
|
|
|
+ return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
+ }
|
|
|
|
|
|
- case ENET_SOCKOPT_BROADCAST:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
|
|
|
+ int result = SOCKET_ERROR;
|
|
|
|
|
|
- case ENET_SOCKOPT_REUSEADDR:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ switch (option) {
|
|
|
+ case ENET_SOCKOPT_NONBLOCK: {
|
|
|
+ u_long nonBlocking = (u_long) value;
|
|
|
+ result = ioctlsocket(socket, FIONBIO, &nonBlocking);
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- case ENET_SOCKOPT_RCVBUF:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_BROADCAST:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_SNDBUF:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_REUSEADDR:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_RCVTIMEO:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_RCVBUF:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_SNDTIMEO:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_SNDBUF:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_NODELAY:
|
|
|
- result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_RCVTIMEO:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return result == SOCKET_ERROR ? -1 : 0;
|
|
|
- } /* enet_socket_set_option */
|
|
|
+ case ENET_SOCKOPT_SNDTIMEO:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
|
|
|
- int result = SOCKET_ERROR, len;
|
|
|
+ case ENET_SOCKOPT_NODELAY:
|
|
|
+ result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- switch (option) {
|
|
|
- case ENET_SOCKOPT_ERROR:
|
|
|
- len = sizeof(int);
|
|
|
- result = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *) value, &len);
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_IPV6_V6ONLY:
|
|
|
+ result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return result == SOCKET_ERROR ? -1 : 0;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
+ return result == SOCKET_ERROR ? -1 : 0;
|
|
|
+ } /* enet_socket_set_option */
|
|
|
|
|
|
- int enet_socket_connect(ENetSocket socket, const ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- int result;
|
|
|
+ int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
|
|
|
+ int result = SOCKET_ERROR, len;
|
|
|
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
+ switch (option) {
|
|
|
+ case ENET_SOCKOPT_ERROR:
|
|
|
+ len = sizeof(int);
|
|
|
+ result = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)value, &len);
|
|
|
+ break;
|
|
|
|
|
|
- sin.sin_family = AF_INET;
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return result == SOCKET_ERROR ? -1 : 0;
|
|
|
+ }
|
|
|
|
|
|
- result = connect(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
|
|
|
- if (result == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ int enet_socket_connect(ENetSocket socket, const ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int result;
|
|
|
|
|
|
- return 0;
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
+
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
+
|
|
|
+ result = connect(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6));
|
|
|
+ if (result == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
|
|
|
- SOCKET result;
|
|
|
- struct sockaddr_in sin;
|
|
|
- int sinLength = sizeof(struct sockaddr_in);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- result = accept(socket, address != NULL ? (struct sockaddr *) &sin : NULL, address != NULL ? &sinLength : NULL);
|
|
|
+ ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
|
|
|
+ SOCKET result;
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int sinLength = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
- if (result == INVALID_SOCKET) {
|
|
|
- return ENET_SOCKET_NULL;
|
|
|
- }
|
|
|
+ result = accept(socket, address != NULL ? (struct sockaddr *)&sin : NULL, address != NULL ? &sinLength : NULL);
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
- }
|
|
|
+ if (result == INVALID_SOCKET) {
|
|
|
+ return ENET_SOCKET_NULL;
|
|
|
+ }
|
|
|
|
|
|
- return result;
|
|
|
+ if (address != NULL) {
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16(sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
|
|
|
- return shutdown(socket, (int) how) == SOCKET_ERROR ? -1 : 0;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
|
|
|
+ return shutdown(socket, (int) how) == SOCKET_ERROR ? -1 : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ void enet_socket_destroy(ENetSocket socket) {
|
|
|
+ if (socket != INVALID_SOCKET) {
|
|
|
+ closesocket(socket);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- void enet_socket_destroy(ENetSocket socket) {
|
|
|
- if (socket != INVALID_SOCKET) {
|
|
|
- closesocket(socket);
|
|
|
- }
|
|
|
+ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ DWORD sentLength;
|
|
|
+
|
|
|
+ if (address != NULL) {
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
+
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- DWORD sentLength;
|
|
|
+ if (WSASendTo(socket,
|
|
|
+ (LPWSABUF) buffers,
|
|
|
+ (DWORD) bufferCount,
|
|
|
+ &sentLength,
|
|
|
+ 0,
|
|
|
+ address != NULL ? (struct sockaddr *) &sin : NULL,
|
|
|
+ address != NULL ? sizeof(struct sockaddr_in6) : 0,
|
|
|
+ NULL,
|
|
|
+ NULL) == SOCKET_ERROR
|
|
|
+ ) {
|
|
|
+ return (WSAGetLastError() == WSAEWOULDBLOCK) ? 0 : 1;
|
|
|
+ }
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
+ return (int) sentLength;
|
|
|
+ }
|
|
|
|
|
|
- sin.sin_family = AF_INET;
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
+ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
|
|
|
+ INT sinLength = sizeof(struct sockaddr_in6);
|
|
|
+ DWORD flags = 0, recvLength;
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+
|
|
|
+ if (WSARecvFrom(socket,
|
|
|
+ (LPWSABUF) buffers,
|
|
|
+ (DWORD) bufferCount,
|
|
|
+ &recvLength,
|
|
|
+ &flags,
|
|
|
+ address != NULL ? (struct sockaddr *) &sin : NULL,
|
|
|
+ address != NULL ? &sinLength : NULL,
|
|
|
+ NULL,
|
|
|
+ NULL) == SOCKET_ERROR
|
|
|
+ ) {
|
|
|
+ switch (WSAGetLastError()) {
|
|
|
+ case WSAEWOULDBLOCK:
|
|
|
+ case WSAECONNRESET:
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- if (WSASendTo(socket,
|
|
|
- (LPWSABUF) buffers,
|
|
|
- (DWORD) bufferCount,
|
|
|
- &sentLength,
|
|
|
- 0,
|
|
|
- address != NULL ? (struct sockaddr *) &sin : NULL,
|
|
|
- address != NULL ? sizeof(struct sockaddr_in) : 0,
|
|
|
- NULL,
|
|
|
- NULL) == SOCKET_ERROR
|
|
|
- ) {
|
|
|
- return (WSAGetLastError() == WSAEWOULDBLOCK) ? 0 : 1;
|
|
|
- }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- return (int) sentLength;
|
|
|
+ if (flags & MSG_PARTIAL) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
|
|
|
- INT sinLength = sizeof(struct sockaddr_in);
|
|
|
- DWORD flags = 0, recvLength;
|
|
|
- struct sockaddr_in sin;
|
|
|
+ if (address != NULL) {
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16(sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
+ }
|
|
|
|
|
|
- if (WSARecvFrom(socket,
|
|
|
- (LPWSABUF) buffers,
|
|
|
- (DWORD) bufferCount,
|
|
|
- &recvLength,
|
|
|
- &flags,
|
|
|
- address != NULL ? (struct sockaddr *) &sin : NULL,
|
|
|
- address != NULL ? &sinLength : NULL,
|
|
|
- NULL,
|
|
|
- NULL) == SOCKET_ERROR
|
|
|
- ) {
|
|
|
- switch (WSAGetLastError()) {
|
|
|
- case WSAEWOULDBLOCK:
|
|
|
- case WSAECONNRESET:
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ return (int) recvLength;
|
|
|
+ } /* enet_socket_receive */
|
|
|
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
|
|
|
+ struct timeval timeVal;
|
|
|
|
|
|
- if (flags & MSG_PARTIAL) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ timeVal.tv_sec = timeout / 1000;
|
|
|
+ timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
- }
|
|
|
+ return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
|
|
|
+ }
|
|
|
|
|
|
- return (int) recvLength;
|
|
|
- } /* enet_socket_receive */
|
|
|
+ int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
|
|
|
+ fd_set readSet, writeSet;
|
|
|
+ struct timeval timeVal;
|
|
|
+ int selectCount;
|
|
|
|
|
|
- int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
|
|
|
- struct timeval timeVal;
|
|
|
+ timeVal.tv_sec = timeout / 1000;
|
|
|
+ timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
|
|
|
- timeVal.tv_sec = timeout / 1000;
|
|
|
- timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
+ FD_ZERO(&readSet);
|
|
|
+ FD_ZERO(&writeSet);
|
|
|
|
|
|
- return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
+ FD_SET(socket, &writeSet);
|
|
|
}
|
|
|
|
|
|
- int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
|
|
|
- fd_set readSet, writeSet;
|
|
|
- struct timeval timeVal;
|
|
|
- int selectCount;
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
+ FD_SET(socket, &readSet);
|
|
|
+ }
|
|
|
|
|
|
- timeVal.tv_sec = timeout / 1000;
|
|
|
- timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
+ selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal);
|
|
|
|
|
|
- FD_ZERO(&readSet);
|
|
|
- FD_ZERO(&writeSet);
|
|
|
+ if (selectCount < 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
- FD_SET(socket, &writeSet);
|
|
|
- }
|
|
|
+ *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
- FD_SET(socket, &readSet);
|
|
|
- }
|
|
|
+ if (selectCount == 0) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal);
|
|
|
+ if (FD_ISSET(socket, &writeSet)) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
+ }
|
|
|
|
|
|
- if (selectCount < 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ if (FD_ISSET(socket, &readSet)) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
+ }
|
|
|
|
|
|
- *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
+ return 0;
|
|
|
+ } /* enet_socket_wait */
|
|
|
|
|
|
- if (selectCount == 0) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ #endif // _WIN32
|
|
|
|
|
|
- if (FD_ISSET(socket, &writeSet)) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
- }
|
|
|
+// =======================================================================//
|
|
|
+// !
|
|
|
+// ! Platform Specific (Unix)
|
|
|
+// !
|
|
|
+// =======================================================================//
|
|
|
|
|
|
- if (FD_ISSET(socket, &readSet)) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
- }
|
|
|
+ #ifndef _WIN32
|
|
|
|
|
|
- return 0;
|
|
|
- } /* enet_socket_wait */
|
|
|
- #else
|
|
|
- static enet_uint64 timeBase = 0;
|
|
|
+ static enet_uint64 timeBase = 0;
|
|
|
|
|
|
- int enet_initialize(void) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ int enet_initialize(void) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- void enet_deinitialize(void) {}
|
|
|
+ void enet_deinitialize(void) {}
|
|
|
|
|
|
- enet_uint64 enet_host_random_seed(void) {
|
|
|
- return (enet_uint64) time(NULL);
|
|
|
- }
|
|
|
+ enet_uint64 enet_host_random_seed(void) {
|
|
|
+ return (enet_uint64) time(NULL);
|
|
|
+ }
|
|
|
|
|
|
- enet_uint64 enet_time_get(void) {
|
|
|
- struct timeval timeVal;
|
|
|
- gettimeofday(&timeVal, NULL);
|
|
|
- return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
|
|
|
- }
|
|
|
+ enet_uint64 enet_time_get(void) {
|
|
|
+ struct timeval timeVal;
|
|
|
+ gettimeofday(&timeVal, NULL);
|
|
|
+ return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
|
|
|
+ }
|
|
|
|
|
|
- void enet_time_set(enet_uint64 newTimeBase) {
|
|
|
- struct timeval timeVal;
|
|
|
- gettimeofday(&timeVal, NULL);
|
|
|
- timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
|
|
|
- }
|
|
|
+ void enet_time_set(enet_uint64 newTimeBase) {
|
|
|
+ struct timeval timeVal;
|
|
|
+ gettimeofday(&timeVal, NULL);
|
|
|
+ timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
|
|
|
+ }
|
|
|
|
|
|
- int enet_address_set_host_ip(ENetAddress *address, const char *name) {
|
|
|
- #ifdef HAS_INET_PTON
|
|
|
- if (!inet_pton(AF_INET, name, &address->host))
|
|
|
- #else
|
|
|
- if (!inet_aton(name, (struct in_addr *) &address->host))
|
|
|
- #endif
|
|
|
- { return -1; }
|
|
|
+ int enet_address_set_host_ip(ENetAddress *address, const char *name) {
|
|
|
+ #ifdef HAS_INET_PTON
|
|
|
+ if (!inet_pton(AF_INET6, name, &address->host))
|
|
|
+ #else
|
|
|
+ #error "inet_pton() is needed for IPv6 support"
|
|
|
+ if (!inet_aton(name, (struct in_addr *) &address->host))
|
|
|
+ #endif
|
|
|
+ { return -1; }
|
|
|
|
|
|
- return 0;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ int enet_address_set_host(ENetAddress *address, const char *name) {
|
|
|
+ #ifdef HAS_GETADDRINFO
|
|
|
+ struct addrinfo hints, *resultList = NULL, *result = NULL;
|
|
|
+
|
|
|
+ memset(&hints, 0, sizeof(hints));
|
|
|
+ hints.ai_family = AF_UNSPEC;
|
|
|
+
|
|
|
+ if (getaddrinfo(name, NULL, &hints, &resultList) != 0) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- int enet_address_set_host(ENetAddress *address, const char *name) {
|
|
|
- #ifdef HAS_GETADDRINFO
|
|
|
- struct addrinfo hints, *resultList = NULL, *result = NULL;
|
|
|
+ for (result = resultList; result != NULL; result = result->ai_next) {
|
|
|
+ if (result->ai_addr != NULL && result->ai_addrlen >= sizeof(struct sockaddr_in)) {
|
|
|
+ if (result->ai_family == AF_INET) {
|
|
|
+ struct sockaddr_in * sin = (struct sockaddr_in *) result->ai_addr;
|
|
|
|
|
|
- memset(&hints, 0, sizeof(hints));
|
|
|
- hints.ai_family = AF_INET;
|
|
|
+ ((uint32_t *) & address->host.s6_addr)[0] = 0;
|
|
|
+ ((uint32_t *) & address->host.s6_addr)[1] = 0;
|
|
|
+ ((uint32_t *) & address->host.s6_addr)[2] = htonl(0xffff);
|
|
|
+ ((uint32_t *) & address->host.s6_addr)[3] = sin->sin_addr.s_addr;
|
|
|
|
|
|
- if (getaddrinfo(name, NULL, NULL, &resultList) != 0) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ freeaddrinfo(resultList);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ else if(result->ai_family == AF_INET6) {
|
|
|
+ struct sockaddr_in6 * sin = (struct sockaddr_in6 *)result->ai_addr;
|
|
|
+
|
|
|
+ address->host = sin->sin6_addr;
|
|
|
+ address->sin6_scope_id = sin->sin6_scope_id;
|
|
|
|
|
|
- for (result = resultList; result != NULL; result = result->ai_next) {
|
|
|
- if (result->ai_family == AF_INET && result->ai_addr != NULL && result->ai_addrlen >= sizeof(struct sockaddr_in)) {
|
|
|
- struct sockaddr_in *sin = (struct sockaddr_in *) result->ai_addr;
|
|
|
- address->host = sin->sin_addr.s_addr;
|
|
|
freeaddrinfo(resultList);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (resultList != NULL) {
|
|
|
- freeaddrinfo(resultList);
|
|
|
- }
|
|
|
- #else /* ifdef HAS_GETADDRINFO */
|
|
|
- struct hostent *hostEntry = NULL;
|
|
|
- #ifdef HAS_GETHOSTBYNAME_R
|
|
|
+
|
|
|
+ if (resultList != NULL) {
|
|
|
+ freeaddrinfo(resultList);
|
|
|
+ }
|
|
|
+ #else /* ifdef HAS_GETADDRINFO */
|
|
|
+ #warning "Really use gethostbyname() with IPv6? Not all platforms support it."
|
|
|
+ struct hostent *hostEntry = NULL;
|
|
|
+
|
|
|
+ #ifdef HAS_GETHOSTBYNAME_R
|
|
|
struct hostent hostData;
|
|
|
char buffer [2048];
|
|
|
int errnum;
|
|
|
|
|
|
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || \
|
|
|
+ #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || \
|
|
|
defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__)
|
|
|
gethostbyname_r(name, &hostData, buffer, sizeof(buffer), &hostEntry, &errnum);
|
|
|
- #else
|
|
|
+ #else
|
|
|
hostEntry = gethostbyname_r(name, &hostData, buffer, sizeof(buffer), &errnum);
|
|
|
- #endif
|
|
|
- #else
|
|
|
+ #endif
|
|
|
+ #else
|
|
|
hostEntry = gethostbyname(name);
|
|
|
- #endif /* ifdef HAS_GETHOSTBYNAME_R */
|
|
|
+ #endif /* ifdef HAS_GETHOSTBYNAME_R */
|
|
|
|
|
|
- if (hostEntry != NULL && hostEntry->h_addrtype == AF_INET) {
|
|
|
- address->host = *(enet_uint32 *) hostEntry->h_addr_list [0];
|
|
|
+ if (hostEntry != NULL && hostEntry->h_addrtype == AF_INET6) {
|
|
|
+ address->host = *(struct in6_addr *)hostEntry->h_addr_list [0];
|
|
|
return 0;
|
|
|
}
|
|
|
- #endif /* ifdef HAS_GETADDRINFO */
|
|
|
+ #endif /* ifdef HAS_GETADDRINFO */
|
|
|
|
|
|
- return enet_address_set_host_ip(address, name);
|
|
|
- } /* enet_address_set_host */
|
|
|
+ return enet_address_set_host_ip(address, name);
|
|
|
+ } /* enet_address_set_host */
|
|
|
|
|
|
- int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
- #ifdef HAS_INET_NTOP
|
|
|
- if (inet_ntop(AF_INET, &address->host, name, nameLength) == NULL)
|
|
|
- #else
|
|
|
- char *addr = inet_ntoa(*(struct in_addr *) &address->host);
|
|
|
- if (addr != NULL) {
|
|
|
- size_t addrLen = strlen(addr);
|
|
|
- if (addrLen >= nameLength) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- memcpy(name, addr, addrLen + 1);
|
|
|
- } else
|
|
|
- #endif
|
|
|
- { return -1; }
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
+ #ifdef HAS_INET_NTOP
|
|
|
+ if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL)
|
|
|
+ #else
|
|
|
+ #error "inet_ntop() is needed for IPv6 support"
|
|
|
+ char *addr = inet_ntoa(*(struct in_addr *) &address->host);
|
|
|
+ if (addr != NULL) {
|
|
|
+ size_t addrLen = strlen(addr);
|
|
|
+ if (addrLen >= nameLength) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ memcpy(name, addr, addrLen + 1);
|
|
|
+ } else
|
|
|
+ #endif
|
|
|
+ { return -1; }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
- #ifdef HAS_GETNAMEINFO
|
|
|
- struct sockaddr_in sin;
|
|
|
- int err;
|
|
|
+ int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) {
|
|
|
+ #ifdef HAS_GETNAMEINFO
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int err;
|
|
|
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
|
|
|
- sin.sin_family = AF_INET;
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16 (address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
|
|
|
- err = getnameinfo((struct sockaddr *) &sin, sizeof(sin), name, nameLength, NULL, 0, NI_NAMEREQD);
|
|
|
- if (!err) {
|
|
|
- if (name != NULL && nameLength > 0 && !memchr(name, '\0', nameLength)) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (err != EAI_NONAME) {
|
|
|
+ err = getnameinfo((struct sockaddr *) &sin, sizeof(sin), name, nameLength, NULL, 0, NI_NAMEREQD);
|
|
|
+ if (!err) {
|
|
|
+ if (name != NULL && nameLength > 0 && !memchr(name, '\0', nameLength)) {
|
|
|
return -1;
|
|
|
}
|
|
|
- #else /* ifdef HAS_GETNAMEINFO */
|
|
|
- struct in_addr in;
|
|
|
- struct hostent *hostEntry = NULL;
|
|
|
- #ifdef HAS_GETHOSTBYADDR_R
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if (err != EAI_NONAME) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ #else /* ifdef HAS_GETNAMEINFO */
|
|
|
+ #warning "Really use gethostbyaddr() with IPv6? Not all platforms support it."
|
|
|
+ struct in6_addr in;
|
|
|
+ struct hostent *hostEntry = NULL;
|
|
|
+ #ifdef HAS_GETHOSTBYADDR_R
|
|
|
struct hostent hostData;
|
|
|
char buffer [2048];
|
|
|
int errnum;
|
|
|
|
|
|
- in.s_addr = address->host;
|
|
|
+ in = address->host;
|
|
|
|
|
|
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__EMSCRIPTEN__)
|
|
|
- gethostbyaddr_r((char *) &in, sizeof(struct in_addr), AF_INET, &hostData, buffer, sizeof(buffer), &hostEntry, &errnum);
|
|
|
+ gethostbyaddr_r((char *)&in, sizeof(struct in6_addr), AF_INET6, &hostData, buffer, sizeof(buffer), &hostEntry, &errnum);
|
|
|
#else
|
|
|
- hostEntry = gethostbyaddr_r((char *) &in, sizeof(struct in_addr), AF_INET, &hostData, buffer, sizeof(buffer), &errnum);
|
|
|
+ hostEntry = gethostbyaddr_r((char *)&in, sizeof(struct in6_addr), AF_INET6, &hostData, buffer, sizeof(buffer), &errnum);
|
|
|
#endif
|
|
|
- #else /* ifdef HAS_GETHOSTBYADDR_R */
|
|
|
- in.s_addr = address->host;
|
|
|
-
|
|
|
- hostEntry = gethostbyaddr((char *) &in, sizeof(struct in_addr), AF_INET);
|
|
|
- #endif /* ifdef HAS_GETHOSTBYADDR_R */
|
|
|
+ #else /* ifdef HAS_GETHOSTBYADDR_R */
|
|
|
+ in = address->host;
|
|
|
|
|
|
- if (hostEntry != NULL) {
|
|
|
- size_t hostLen = strlen(hostEntry->h_name);
|
|
|
- if (hostLen >= nameLength) { return -1; }
|
|
|
- memcpy(name, hostEntry->h_name, hostLen + 1);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- #endif /* ifdef HAS_GETNAMEINFO */
|
|
|
+ hostEntry = gethostbyaddr((char *)&in, sizeof(struct in6_addr), AF_INET6);
|
|
|
+ #endif /* ifdef HAS_GETHOSTBYADDR_R */
|
|
|
|
|
|
- return enet_address_get_host_ip(address, name, nameLength);
|
|
|
- } /* enet_address_get_host */
|
|
|
+ if (hostEntry != NULL) {
|
|
|
+ size_t hostLen = strlen(hostEntry->h_name);
|
|
|
+ if (hostLen >= nameLength) { return -1; }
|
|
|
+ memcpy(name, hostEntry->h_name, hostLen + 1);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ #endif /* ifdef HAS_GETNAMEINFO */
|
|
|
|
|
|
- int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
- sin.sin_family = AF_INET;
|
|
|
+ return enet_address_get_host_ip(address, name, nameLength);
|
|
|
+ } /* enet_address_get_host */
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
- } else {
|
|
|
- sin.sin_port = 0;
|
|
|
- sin.sin_addr.s_addr = INADDR_ANY;
|
|
|
- }
|
|
|
+ int enet_socket_bind(ENetSocket socket, const ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
|
|
|
- return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
|
|
|
+ if (address != NULL) {
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
+ } else {
|
|
|
+ sin.sin6_port = 0;
|
|
|
+ sin.sin6_addr = ENET_HOST_ANY;
|
|
|
+ sin.sin6_scope_id = 0;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- socklen_t sinLength = sizeof(struct sockaddr_in);
|
|
|
-
|
|
|
- if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ return bind(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6));
|
|
|
+ }
|
|
|
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
+ int enet_socket_get_address(ENetSocket socket, ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ socklen_t sinLength = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
- return 0;
|
|
|
+ if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) {
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_listen(ENetSocket socket, int backlog) {
|
|
|
- return listen(socket, backlog < 0 ? SOMAXCONN : backlog);
|
|
|
- }
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16(sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
|
|
|
- ENetSocket enet_socket_create(ENetSocketType type) {
|
|
|
- return socket(PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
- }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
|
|
|
- int result = -1;
|
|
|
+ int enet_socket_listen(ENetSocket socket, int backlog) {
|
|
|
+ return listen(socket, backlog < 0 ? SOMAXCONN : backlog);
|
|
|
+ }
|
|
|
|
|
|
- switch (option) {
|
|
|
- case ENET_SOCKOPT_NONBLOCK:
|
|
|
- #ifdef HAS_FCNTL
|
|
|
- result = fcntl(socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl(socket, F_GETFL) & ~O_NONBLOCK));
|
|
|
- #else
|
|
|
- result = ioctl(socket, FIONBIO, &value);
|
|
|
- #endif
|
|
|
- break;
|
|
|
+ ENetSocket enet_socket_create(ENetSocketType type) {
|
|
|
+ return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
+ }
|
|
|
|
|
|
- case ENET_SOCKOPT_BROADCAST:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {
|
|
|
+ int result = -1;
|
|
|
|
|
|
- case ENET_SOCKOPT_REUSEADDR:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ switch (option) {
|
|
|
+ case ENET_SOCKOPT_NONBLOCK:
|
|
|
+ #ifdef HAS_FCNTL
|
|
|
+ result = fcntl(socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl(socket, F_GETFL) & ~O_NONBLOCK));
|
|
|
+ #else
|
|
|
+ result = ioctl(socket, FIONBIO, &value);
|
|
|
+ #endif
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_RCVBUF:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_BROADCAST:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_SNDBUF:
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_REUSEADDR:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_RCVTIMEO: {
|
|
|
- struct timeval timeVal;
|
|
|
- timeVal.tv_sec = value / 1000;
|
|
|
- timeVal.tv_usec = (value % 1000) * 1000;
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeVal, sizeof(struct timeval));
|
|
|
- break;
|
|
|
- }
|
|
|
+ case ENET_SOCKOPT_RCVBUF:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_SNDTIMEO: {
|
|
|
- struct timeval timeVal;
|
|
|
- timeVal.tv_sec = value / 1000;
|
|
|
- timeVal.tv_usec = (value % 1000) * 1000;
|
|
|
- result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeVal, sizeof(struct timeval));
|
|
|
- break;
|
|
|
- }
|
|
|
+ case ENET_SOCKOPT_SNDBUF:
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- case ENET_SOCKOPT_NODELAY:
|
|
|
- result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *) &value, sizeof(int));
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_RCVTIMEO: {
|
|
|
+ struct timeval timeVal;
|
|
|
+ timeVal.tv_sec = value / 1000;
|
|
|
+ timeVal.tv_usec = (value % 1000) * 1000;
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeVal, sizeof(struct timeval));
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- default:
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_SNDTIMEO: {
|
|
|
+ struct timeval timeVal;
|
|
|
+ timeVal.tv_sec = value / 1000;
|
|
|
+ timeVal.tv_usec = (value % 1000) * 1000;
|
|
|
+ result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeVal, sizeof(struct timeval));
|
|
|
+ break;
|
|
|
}
|
|
|
- return result == -1 ? -1 : 0;
|
|
|
- } /* enet_socket_set_option */
|
|
|
|
|
|
- int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
|
|
|
- int result = -1;
|
|
|
- socklen_t len;
|
|
|
+ case ENET_SOCKOPT_NODELAY:
|
|
|
+ result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- switch (option) {
|
|
|
- case ENET_SOCKOPT_ERROR:
|
|
|
- len = sizeof(int);
|
|
|
- result = getsockopt(socket, SOL_SOCKET, SO_ERROR, value, &len);
|
|
|
- break;
|
|
|
+ case ENET_SOCKOPT_IPV6_V6ONLY:
|
|
|
+ result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int));
|
|
|
+ break;
|
|
|
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- return result == -1 ? -1 : 0;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
+ return result == -1 ? -1 : 0;
|
|
|
+ } /* enet_socket_set_option */
|
|
|
|
|
|
- int enet_socket_connect(ENetSocket socket, const ENetAddress *address) {
|
|
|
- struct sockaddr_in sin;
|
|
|
- int result;
|
|
|
+ int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) {
|
|
|
+ int result = -1;
|
|
|
+ socklen_t len;
|
|
|
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
+ switch (option) {
|
|
|
+ case ENET_SOCKOPT_ERROR:
|
|
|
+ len = sizeof(int);
|
|
|
+ result = getsockopt(socket, SOL_SOCKET, SO_ERROR, value, &len);
|
|
|
+ break;
|
|
|
|
|
|
- sin.sin_family = AF_INET;
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return result == -1 ? -1 : 0;
|
|
|
+ }
|
|
|
|
|
|
- result = connect(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in));
|
|
|
- if (result == -1 && errno == EINPROGRESS) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ int enet_socket_connect(ENetSocket socket, const ENetAddress *address) {
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int result;
|
|
|
|
|
|
- return result;
|
|
|
- }
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
|
|
|
- ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
|
|
|
- int result;
|
|
|
- struct sockaddr_in sin;
|
|
|
- socklen_t sinLength = sizeof(struct sockaddr_in);
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
|
|
|
- result = accept(socket,
|
|
|
- address != NULL ? (struct sockaddr *) &sin : NULL,
|
|
|
- address != NULL ? &sinLength : NULL);
|
|
|
+ result = connect(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6));
|
|
|
+ if (result == -1 && errno == EINPROGRESS) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- if (result == -1) {
|
|
|
- return ENET_SOCKET_NULL;
|
|
|
- }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
- }
|
|
|
+ ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) {
|
|
|
+ int result;
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ socklen_t sinLength = sizeof(struct sockaddr_in6);
|
|
|
|
|
|
- return result;
|
|
|
- }
|
|
|
+ result = accept(socket,address != NULL ? (struct sockaddr *) &sin : NULL, address != NULL ? &sinLength : NULL);
|
|
|
|
|
|
- int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
|
|
|
- return shutdown(socket, (int) how);
|
|
|
+ if (result == -1) {
|
|
|
+ return ENET_SOCKET_NULL;
|
|
|
}
|
|
|
|
|
|
- void enet_socket_destroy(ENetSocket socket) {
|
|
|
- if (socket != -1) {
|
|
|
- close(socket);
|
|
|
- }
|
|
|
+ if (address != NULL) {
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16 (sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_send(ENetSocket socket,
|
|
|
- const ENetAddress * address,
|
|
|
- const ENetBuffer * buffers,
|
|
|
- size_t bufferCount) {
|
|
|
- struct msghdr msgHdr;
|
|
|
- struct sockaddr_in sin;
|
|
|
- int sentLength;
|
|
|
+ return result;
|
|
|
+ }
|
|
|
|
|
|
- memset(&msgHdr, 0, sizeof(struct msghdr));
|
|
|
+ int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) {
|
|
|
+ return shutdown(socket, (int) how);
|
|
|
+ }
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- memset(&sin, 0, sizeof(struct sockaddr_in));
|
|
|
+ void enet_socket_destroy(ENetSocket socket) {
|
|
|
+ if (socket != -1) {
|
|
|
+ close(socket);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- sin.sin_family = AF_INET;
|
|
|
- sin.sin_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
- sin.sin_addr.s_addr = address->host;
|
|
|
+ int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) {
|
|
|
+ struct msghdr msgHdr;
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int sentLength;
|
|
|
|
|
|
- msgHdr.msg_name = &sin;
|
|
|
- msgHdr.msg_namelen = sizeof(struct sockaddr_in);
|
|
|
- }
|
|
|
+ memset(&msgHdr, 0, sizeof(struct msghdr));
|
|
|
|
|
|
- msgHdr.msg_iov = (struct iovec *) buffers;
|
|
|
- msgHdr.msg_iovlen = bufferCount;
|
|
|
+ if (address != NULL) {
|
|
|
+ memset(&sin, 0, sizeof(struct sockaddr_in6));
|
|
|
|
|
|
- sentLength = sendmsg(socket, &msgHdr, MSG_NOSIGNAL);
|
|
|
+ sin.sin6_family = AF_INET6;
|
|
|
+ sin.sin6_port = ENET_HOST_TO_NET_16(address->port);
|
|
|
+ sin.sin6_addr = address->host;
|
|
|
+ sin.sin6_scope_id = address->sin6_scope_id;
|
|
|
|
|
|
- if (sentLength == -1) {
|
|
|
- if (errno == EWOULDBLOCK) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ msgHdr.msg_name = &sin;
|
|
|
+ msgHdr.msg_namelen = sizeof(struct sockaddr_in6);
|
|
|
+ }
|
|
|
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ msgHdr.msg_iov = (struct iovec *) buffers;
|
|
|
+ msgHdr.msg_iovlen = bufferCount;
|
|
|
|
|
|
- return sentLength;
|
|
|
- } /* enet_socket_send */
|
|
|
+ sentLength = sendmsg(socket, &msgHdr, MSG_NOSIGNAL);
|
|
|
|
|
|
- int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
|
|
|
- struct msghdr msgHdr;
|
|
|
- struct sockaddr_in sin;
|
|
|
- int recvLength;
|
|
|
+ if (sentLength == -1) {
|
|
|
+ if (errno == EWOULDBLOCK) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
- memset(&msgHdr, 0, sizeof(struct msghdr));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- msgHdr.msg_name = &sin;
|
|
|
- msgHdr.msg_namelen = sizeof(struct sockaddr_in);
|
|
|
- }
|
|
|
+ return sentLength;
|
|
|
+ } /* enet_socket_send */
|
|
|
|
|
|
- msgHdr.msg_iov = (struct iovec *) buffers;
|
|
|
- msgHdr.msg_iovlen = bufferCount;
|
|
|
+ int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) {
|
|
|
+ struct msghdr msgHdr;
|
|
|
+ struct sockaddr_in6 sin;
|
|
|
+ int recvLength;
|
|
|
|
|
|
- recvLength = recvmsg(socket, &msgHdr, MSG_NOSIGNAL);
|
|
|
+ memset(&msgHdr, 0, sizeof(struct msghdr));
|
|
|
|
|
|
- if (recvLength == -1) {
|
|
|
- if (errno == EWOULDBLOCK) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (address != NULL) {
|
|
|
+ msgHdr.msg_name = &sin;
|
|
|
+ msgHdr.msg_namelen = sizeof(struct sockaddr_in6);
|
|
|
+ }
|
|
|
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ msgHdr.msg_iov = (struct iovec *) buffers;
|
|
|
+ msgHdr.msg_iovlen = bufferCount;
|
|
|
|
|
|
- #ifdef HAS_MSGHDR_FLAGS
|
|
|
- if (msgHdr.msg_flags & MSG_TRUNC) {
|
|
|
- return -1;
|
|
|
- }
|
|
|
- #endif
|
|
|
+ recvLength = recvmsg(socket, &msgHdr, MSG_NOSIGNAL);
|
|
|
|
|
|
- if (address != NULL) {
|
|
|
- address->host = (enet_uint32) sin.sin_addr.s_addr;
|
|
|
- address->port = ENET_NET_TO_HOST_16(sin.sin_port);
|
|
|
+ if (recvLength == -1) {
|
|
|
+ if (errno == EWOULDBLOCK) {
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
- return recvLength;
|
|
|
- } /* enet_socket_receive */
|
|
|
-
|
|
|
- int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
|
|
|
- struct timeval timeVal;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- timeVal.tv_sec = timeout / 1000;
|
|
|
- timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
+ #ifdef HAS_MSGHDR_FLAGS
|
|
|
+ if (msgHdr.msg_flags & MSG_TRUNC) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ #endif
|
|
|
|
|
|
- return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
|
|
|
+ if (address != NULL) {
|
|
|
+ address->host = sin.sin6_addr;
|
|
|
+ address->port = ENET_NET_TO_HOST_16(sin.sin6_port);
|
|
|
+ address->sin6_scope_id = sin.sin6_scope_id;
|
|
|
}
|
|
|
|
|
|
- int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
|
|
|
- #ifdef HAS_POLL
|
|
|
- struct pollfd pollSocket;
|
|
|
- int pollCount;
|
|
|
+ return recvLength;
|
|
|
+ } /* enet_socket_receive */
|
|
|
|
|
|
- pollSocket.fd = socket;
|
|
|
- pollSocket.events = 0;
|
|
|
+ int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) {
|
|
|
+ struct timeval timeVal;
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
- pollSocket.events |= POLLOUT;
|
|
|
- }
|
|
|
+ timeVal.tv_sec = timeout / 1000;
|
|
|
+ timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
- pollSocket.events |= POLLIN;
|
|
|
- }
|
|
|
+ return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal);
|
|
|
+ }
|
|
|
|
|
|
- pollCount = poll(&pollSocket, 1, timeout);
|
|
|
+ int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) {
|
|
|
+ #ifdef HAS_POLL
|
|
|
+ struct pollfd pollSocket;
|
|
|
+ int pollCount;
|
|
|
|
|
|
- if (pollCount < 0) {
|
|
|
- if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) {
|
|
|
- *condition = ENET_SOCKET_WAIT_INTERRUPT;
|
|
|
+ pollSocket.fd = socket;
|
|
|
+ pollSocket.events = 0;
|
|
|
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
+ pollSocket.events |= POLLOUT;
|
|
|
+ }
|
|
|
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
+ pollSocket.events |= POLLIN;
|
|
|
+ }
|
|
|
+
|
|
|
+ pollCount = poll(&pollSocket, 1, timeout);
|
|
|
|
|
|
- *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
+ if (pollCount < 0) {
|
|
|
+ if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) {
|
|
|
+ *condition = ENET_SOCKET_WAIT_INTERRUPT;
|
|
|
|
|
|
- if (pollCount == 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (pollSocket.revents & POLLOUT) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
- }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (pollSocket.revents & POLLIN) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
- }
|
|
|
+ *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
|
|
|
+ if (pollCount == 0) {
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
- #else /* ifdef HAS_POLL */
|
|
|
- fd_set readSet, writeSet;
|
|
|
- struct timeval timeVal;
|
|
|
- int selectCount;
|
|
|
+ if (pollSocket.revents & POLLOUT) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
+ }
|
|
|
|
|
|
- timeVal.tv_sec = timeout / 1000;
|
|
|
- timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
+ if (pollSocket.revents & POLLIN) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
+ }
|
|
|
|
|
|
- FD_ZERO(&readSet);
|
|
|
- FD_ZERO(&writeSet);
|
|
|
+ return 0;
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
- FD_SET(socket, &writeSet);
|
|
|
- }
|
|
|
+ #else /* ifdef HAS_POLL */
|
|
|
+ fd_set readSet, writeSet;
|
|
|
+ struct timeval timeVal;
|
|
|
+ int selectCount;
|
|
|
|
|
|
- if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
- FD_SET(socket, &readSet);
|
|
|
- }
|
|
|
+ timeVal.tv_sec = timeout / 1000;
|
|
|
+ timeVal.tv_usec = (timeout % 1000) * 1000;
|
|
|
|
|
|
- selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal);
|
|
|
+ FD_ZERO(&readSet);
|
|
|
+ FD_ZERO(&writeSet);
|
|
|
|
|
|
- if (selectCount < 0) {
|
|
|
- if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) {
|
|
|
- *condition = ENET_SOCKET_WAIT_INTERRUPT;
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_SEND) {
|
|
|
+ FD_SET(socket, &writeSet);
|
|
|
+ }
|
|
|
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (*condition & ENET_SOCKET_WAIT_RECEIVE) {
|
|
|
+ FD_SET(socket, &readSet);
|
|
|
+ }
|
|
|
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal);
|
|
|
|
|
|
- *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
+ if (selectCount < 0) {
|
|
|
+ if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) {
|
|
|
+ *condition = ENET_SOCKET_WAIT_INTERRUPT;
|
|
|
|
|
|
- if (selectCount == 0) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- if (FD_ISSET(socket, &writeSet)) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
- }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
|
|
|
- if (FD_ISSET(socket, &readSet)) {
|
|
|
- *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
- }
|
|
|
+ *condition = ENET_SOCKET_WAIT_NONE;
|
|
|
|
|
|
+ if (selectCount == 0) {
|
|
|
return 0;
|
|
|
+ }
|
|
|
|
|
|
- #endif /* ifdef HAS_POLL */
|
|
|
- } /* enet_socket_wait */
|
|
|
- #endif
|
|
|
+ if (FD_ISSET(socket, &writeSet)) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_SEND;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (FD_ISSET(socket, &readSet)) {
|
|
|
+ *condition |= ENET_SOCKET_WAIT_RECEIVE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ #endif /* ifdef HAS_POLL */
|
|
|
+ } /* enet_socket_wait */
|
|
|
|
|
|
+ #endif // !_WIN32
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
}
|