From 2ea8b3da07b7f14ca8a1284763b6f6a6cc36a2f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Fri, 1 Mar 2024 08:46:17 +0100 Subject: [PATCH] update enet --- engine/joint/v4k.h | 675 +++++++++++++++++++--------------------- engine/split/3rd_enet.h | 675 +++++++++++++++++++--------------------- engine/v4k | 675 +++++++++++++++++++--------------------- 3 files changed, 957 insertions(+), 1068 deletions(-) diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 358768e..cbb9cd3 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -308681,26 +308681,10 @@ int main() { * SOFTWARE. * */ - -/* -## Disclaimer - -This is a fork of the original library [lsalzman/enet](https://github.com/lsalzman/enet). While original repo offers a stable, time-tested wonderful library, -we are trying to change some things, things, which can't be reflected on the main repo, like: - -* integrated ipv6 support -* added monotonic time -* applied project-wide code style change -* cleaned up project -* single-header style code -* NPM package distribution -* removed a lot of older methods -* and many other various changes -*/ - #ifndef ENET_INCLUDE_H #define ENET_INCLUDE_H +#include #include #include #include @@ -308708,7 +308692,7 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_VERSION_MAJOR 2 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 0 +#define ENET_VERSION_PATCH 9 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) @@ -308737,8 +308721,10 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifndef ENET_NO_PRAGMA_LINK - #pragma comment(lib, "ws2_32") //< @r-lyeh removed .lib (tcc support) - #pragma comment(lib, "winmm") //< @r-lyeh removed .lib (tcc support) + #ifndef __GNUC__ + #pragma comment(lib, "ws2_32.lib") + #pragma comment(lib, "winmm.lib") + #endif #endif #if _MSC_VER >= 1910 @@ -308749,9 +308735,9 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifdef __GNUC__ - #if (_WIN32_WINNT < 0x0501) + #if (_WIN32_WINNT < 0x0600) #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 + #define _WIN32_WINNT 0x0600 #endif #endif @@ -308761,14 +308747,14 @@ we are trying to change some things, things, which can't be reflected on the mai #include - #if defined(_MSC_VER) && _MSC_VER < 1900 //< @r-lyeh + #if defined(_WIN32) && defined(_MSC_VER) + #if _MSC_VER < 1900 typedef struct timespec { long tv_sec; long tv_nsec; }; #endif - #ifndef __MINGW32__ - #define CLOCK_MONOTONIC 0 //< @r-lyeh, tcc support + #define CLOCK_MONOTONIC 0 #endif typedef SOCKET ENetSocket; @@ -308877,12 +308863,12 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) #define ENET_IPV6 1 -const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; -const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; #define ENET_HOST_ANY in6addr_any #define ENET_HOST_BROADCAST 0xFFFFFFFFU #define ENET_PORT_ANY 0 @@ -308917,6 +308903,7 @@ extern "C" { extern void *enet_malloc(size_t); extern void enet_free(void *); extern ENetPacket* enet_packet_create(const void*,size_t,enet_uint32); + extern int enet_packet_resize(ENetPacket*, size_t); extern ENetPacket* enet_packet_copy(ENetPacket*); extern void enet_packet_destroy(ENetPacket*); @@ -309276,7 +309263,7 @@ extern "C" { ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, - ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MTU = 1392, ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, @@ -309894,16 +309881,6 @@ extern "C" { #undef AT_HAVE_ATOMICS -#else //< @r-lyeh: add __TINYC__ stubs. not going to work. - - #define ENET_ATOMIC_READ(variable) (*(int64_t *)(variable)) - #define ENET_ATOMIC_WRITE(variable, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_CAS(variable, old_value, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_INC(variable) ENET_ATOMIC_INC_BY(variable, 1) - #define ENET_ATOMIC_DEC(variable) ENET_ATOMIC_DEC_BY(variable, 1) - #define ENET_ATOMIC_INC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) + (delta)) - #define ENET_ATOMIC_DEC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) - (delta)) - #endif /* defined(_MSC_VER) */ // =======================================================================// @@ -310064,6 +310041,34 @@ extern "C" { return packet; } + /** Attempts to resize the data in the packet to length specified in the + dataLength parameter + @param packet packet to resize + @param dataLength new size for the packet data + @returns 0 on success, < 0 on failure + */ + int enet_packet_resize(ENetPacket * packet, size_t dataLength) + { + ENetPacket *newPacket = NULL; + + if (dataLength <= packet->dataLength || (packet->flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + { + packet->dataLength = dataLength; + + return 0; + } + + newPacket = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength); + if (newPacket == NULL) + return -1; + + memcpy(newPacket, packet, sizeof(ENetPacket) + packet->dataLength); + newPacket->data = (enet_uint8 *)newPacket + sizeof(ENetPacket); + enet_free(packet); + + return 0; + } + ENetPacket *enet_packet_create_offset(const void *data, size_t dataLength, size_t dataOffset, enet_uint32 flags) { ENetPacket *packet; if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { @@ -310893,18 +310898,17 @@ extern "C" { if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { return -1; } - if (peer->incomingBandwidth != 0) { --host->bandwidthLimitedPeers; } peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.incomingBandwidth); - peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); - if (peer->incomingBandwidth != 0) { ++host->bandwidthLimitedPeers; } + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); + if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) { peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) { @@ -311317,7 +311321,8 @@ extern "C" { goto commandError; } - if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { + assert(peer); + if ((command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { enet_uint16 sentTime; if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) { @@ -311809,12 +311814,12 @@ extern "C" { currentPeer->packetsLost = 0; } - host->buffers->data = headerData; + host->buffers[0].data = headerData; if (host->headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) { header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF); - host->buffers->dataLength = sizeof(ENetProtocolHeader); + host->buffers[0].dataLength = sizeof(ENetProtocolHeader); } else { - host->buffers->dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; + host->buffers[0].dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; } shouldCompress = 0; @@ -311835,9 +311840,9 @@ extern "C" { } header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags); if (host->checksum != NULL) { - enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers->dataLength]; + enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers[0].dataLength]; *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0; - host->buffers->dataLength += sizeof(enet_uint32); + host->buffers[0].dataLength += sizeof(enet_uint32); *checksum = host->checksum(host->buffers, host->bufferCount); } @@ -311852,6 +311857,9 @@ extern "C" { enet_protocol_remove_sent_unreliable_commands(currentPeer); if (sentLength < 0) { + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; return -1; } @@ -311860,6 +311868,10 @@ extern "C" { host->totalSentPackets++; } + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; + return 0; } /* enet_protocol_send_outgoing_commands */ @@ -312527,7 +312539,7 @@ extern "C" { * @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 */ void enet_peer_ping_interval(ENetPeer *peer, enet_uint32 pingInterval) { - peer->pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; + peer->pingInterval = pingInterval ? pingInterval : (enet_uint32)ENET_PEER_PING_INTERVAL; } /** Sets the timeout parameters for a peer. @@ -312548,9 +312560,9 @@ extern "C" { */ void enet_peer_timeout(ENetPeer *peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) { - peer->timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; - peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; - peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; + peer->timeoutLimit = timeoutLimit ? timeoutLimit : (enet_uint32)ENET_PEER_TIMEOUT_LIMIT; + peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : (enet_uint32)ENET_PEER_TIMEOUT_MINIMUM; + peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : (enet_uint32)ENET_PEER_TIMEOUT_MAXIMUM; } /** Force an immediate disconnection from a peer. @@ -313005,10 +313017,9 @@ extern "C" { memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32)); } - if (packet != NULL) { - ++packet->referenceCount; - peer->totalWaitingData += packet->dataLength; - } + assert(packet != NULL); + ++packet->referenceCount; + peer->totalWaitingData += packet->dataLength; enet_list_insert(enet_list_next(currentCommand), incomingCommand); @@ -313030,7 +313041,7 @@ extern "C" { goto notifyError; } - if (packet != NULL && packet->referenceCount == 0) { + if (packet != NULL && packet->referenceCount == 0) { callbacks.packet_destroy(packet); } @@ -313113,11 +313124,9 @@ extern "C" { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->randomSeed = (enet_uint32) (size_t) host; + host->randomSeed = (enet_uint32) ((uintptr_t) host % UINT32_MAX); host->randomSeed += enet_host_random_seed(); host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16); host->channelLimit = channelLimit; @@ -313366,10 +313375,7 @@ extern "C" { void enet_host_channel_limit(ENetHost *host, size_t channelLimit) { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->channelLimit = channelLimit; } @@ -313554,20 +313560,256 @@ extern "C" { // =======================================================================// // ! -// ! Compat +// ! Time // ! // =======================================================================// - #if (defined _MSC_VER && defined _WIN32 && !defined _WIN64) || \ - (defined __MINGW32__ || defined __MINGW64__) // (!defined _WIN32 && defined __MINGW32__ && defined ENET_MINGW_COMPAT) //< @r-lyeh - #define MUST_DEFINE_NTOP_PTON 1 - #else - #define MUST_DEFINE_NTOP_PTON 0 + #ifdef _WIN32 + static LARGE_INTEGER getFILETIMEoffset() { + SYSTEMTIME s; + FILETIME f; + LARGE_INTEGER t; + + s.wYear = 1970; + s.wMonth = 1; + s.wDay = 1; + s.wHour = 0; + s.wMinute = 0; + s.wSecond = 0; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + return (t); + } + int clock_gettime(int X, struct timespec *tv) { + (void)X; + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) { + LARGE_INTEGER performanceFrequency; + initialized = 1; + usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); + if (usePerformanceCounter) { + QueryPerformanceCounter(&offset); + frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; + } else { + offset = getFILETIMEoffset(); + frequencyToMicroseconds = 10.; + } + } + if (usePerformanceCounter) { + QueryPerformanceCounter(&t); + } else { + GetSystemTimeAsFileTime(&f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + } + + t.QuadPart -= offset.QuadPart; + microseconds = (double)t.QuadPart / frequencyToMicroseconds; + t.QuadPart = (LONGLONG)microseconds; + tv->tv_sec = (long)(t.QuadPart / 1000000); + tv->tv_nsec = t.QuadPart % 1000000 * 1000; + return (0); + } + #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + #define CLOCK_MONOTONIC 0 + + int clock_gettime(int X, struct timespec *ts) { + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; + + return 0; + } #endif - #if MUST_DEFINE_NTOP_PTON //< @r-lyeh + enet_uint32 enet_time_get() { + // TODO enet uses 32 bit timestamps. We should modify it to use + // 64 bit timestamps, but this is not trivial since we'd end up + // changing half the structs in enet. For now, retain 32 bits, but + // use an offset so we don't run out of bits. Basically, the first + // call of enet_time_get() will always return 1, and follow-up calls + // indicate elapsed time since the first call. + // + // Note that we don't want to return 0 from the first call, in case + // some part of enet uses 0 as a special value (meaning time not set + // for example). + static uint64_t start_time_ns = 0; - // #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) //< @r-lyeh + struct timespec ts; + #if defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + #else + clock_gettime(CLOCK_MONOTONIC, &ts); + #endif + + static const uint64_t ns_in_s = 1000 * 1000 * 1000; + static const uint64_t ns_in_ms = 1000 * 1000; + uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; + + // Most of the time we just want to atomically read the start time. We + // could just use a single CAS instruction instead of this if, but it + // would be slower in the average case. + // + // Note that statics are auto-initialized to zero, and starting a thread + // implies a memory barrier. So we know that whatever thread calls this, + // it correctly sees the start_time_ns as 0 initially. + uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); + if (offset_ns == 0) { + // We still need to CAS, since two different threads can get here + // at the same time. + // + // We assume that current_time_ns is > 1ms. + // + // Set the value of the start_time_ns, such that the first timestamp + // is at 1ms. This ensures 0 remains a special value. + uint64_t want_value = current_time_ns - 1 * ns_in_ms; + uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); + offset_ns = old_value == 0 ? want_value : old_value; + } + + uint64_t result_in_ns = current_time_ns - offset_ns; + return (enet_uint32)(result_in_ns / ns_in_ms); + } + + void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) + { + if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ + *out = enet_v6_anyaddr; + } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ + *out = enet_v6_noaddr; + } else { + *out = enet_v4_anyaddr; + out->s6_addr[10] = 0xFF; + out->s6_addr[11] = 0xFF; + out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; + out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; + out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; + out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; + } + } + void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) + { + memset(out, 0, sizeof(struct in_addr)); + ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; + ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; + ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; + ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; + } + + int enet_in6addr_lookup_host(const char *name, bool nodns, ENetAddress *out) { + struct addrinfo hints, *resultList = NULL, *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (nodns) + { + hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ + } + + if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { + freeaddrinfo(resultList); + return -1; + } + + for (result = resultList; result != NULL; result = result->ai_next) { + if (result->ai_addr != NULL) { + if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { + enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, &out->host); + out->sin6_scope_id = 0; + freeaddrinfo(resultList); + return 0; + + } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { + memcpy(&out->host, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + out->sin6_scope_id = (enet_uint16) ((struct sockaddr_in6*)result->ai_addr)->sin6_scope_id; + freeaddrinfo(resultList); + return 0; + } + } + } + freeaddrinfo(resultList); + return -1; + } + + int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, true, address); + } + + int enet_address_set_host_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, false, address); + } + + int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { + if (IN6_IS_ADDR_V4MAPPED(&address->host)) { + struct in_addr buf; + enet_inaddr_map6to4(&address->host, &buf); + + if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { + return -1; + } + } + else { + if (inet_ntop(AF_INET6, (void*)&address->host, name, nameLength) == NULL) { + return -1; + } + } + + return 0; + } /* enet_address_get_host_ip_new */ + + int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + int err; + + + 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) { + return -1; + } + + return enet_address_get_host_ip_new(address, name, nameLength); + } /* enet_address_get_host_new */ + +// =======================================================================// +// ! +// ! Platform Specific (Unix) +// ! +// =======================================================================// + + #ifndef _WIN32 + + #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) // inet_ntop/inet_pton for MinGW from http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { if (af == AF_INET) { @@ -313747,280 +313989,7 @@ extern "C" { return -1; } } - - #endif // MUST_DEFINE_NTOP_PTON //< @r-lyeh - -// =======================================================================// -// ! -// ! Time -// ! -// =======================================================================// - - #ifdef _WIN32 - static LARGE_INTEGER getFILETIMEoffset() { - SYSTEMTIME s; - FILETIME f; - LARGE_INTEGER t; - - s.wYear = 1970; - s.wMonth = 1; - s.wDay = 1; - s.wHour = 0; - s.wMinute = 0; - s.wSecond = 0; - s.wMilliseconds = 0; - SystemTimeToFileTime(&s, &f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - return (t); - } - - #ifdef __MINGW32__ - #define clock_gettime clock_gettime2 // symbol defined in pthread_time.h instead. workaround to avoid user linking against -lpthread. - #endif - -// #ifndef CLOCK_MONOTONIC_RAW -// #define CLOCK_MONOTONIC_RAW 0 // for zig-cc -// #endif - - int clock_gettime(int X, struct timespec *tv) { - LARGE_INTEGER t; - FILETIME f; - double microseconds; - static LARGE_INTEGER offset; - static double frequencyToMicroseconds; - static int initialized = 0; - static BOOL usePerformanceCounter = 0; - - if (!initialized) { - LARGE_INTEGER performanceFrequency; - initialized = 1; - usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); - if (usePerformanceCounter) { - QueryPerformanceCounter(&offset); - frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; - } else { - offset = getFILETIMEoffset(); - frequencyToMicroseconds = 10.; - } - } - if (usePerformanceCounter) { - QueryPerformanceCounter(&t); - } else { - GetSystemTimeAsFileTime(&f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - } - - t.QuadPart -= offset.QuadPart; - microseconds = (double)t.QuadPart / frequencyToMicroseconds; - t.QuadPart = (LONGLONG)microseconds; - tv->tv_sec = (long)(t.QuadPart / 1000000); - tv->tv_nsec = t.QuadPart % 1000000 * 1000; - return (0); - } - - #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #define CLOCK_MONOTONIC 0 - - int clock_gettime(int X, struct timespec *ts) { - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - ts->tv_sec = mts.tv_sec; - ts->tv_nsec = mts.tv_nsec; - - return 0; - } - #endif - - enet_uint32 enet_time_get() { - // TODO enet uses 32 bit timestamps. We should modify it to use - // 64 bit timestamps, but this is not trivial since we'd end up - // changing half the structs in enet. For now, retain 32 bits, but - // use an offset so we don't run out of bits. Basically, the first - // call of enet_time_get() will always return 1, and follow-up calls - // indicate elapsed time since the first call. - // - // Note that we don't want to return 0 from the first call, in case - // some part of enet uses 0 as a special value (meaning time not set - // for example). - static uint64_t start_time_ns = 0; - - struct timespec ts; - #if defined(CLOCK_MONOTONIC_RAW) - clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - #else - clock_gettime(CLOCK_MONOTONIC, &ts); - #endif - - static const uint64_t ns_in_s = 1000 * 1000 * 1000; - static const uint64_t ns_in_ms = 1000 * 1000; - uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; - - // Most of the time we just want to atomically read the start time. We - // could just use a single CAS instruction instead of this if, but it - // would be slower in the average case. - // - // Note that statics are auto-initialized to zero, and starting a thread - // implies a memory barrier. So we know that whatever thread calls this, - // it correctly sees the start_time_ns as 0 initially. - uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); - if (offset_ns == 0) { - // We still need to CAS, since two different threads can get here - // at the same time. - // - // We assume that current_time_ns is > 1ms. - // - // Set the value of the start_time_ns, such that the first timestamp - // is at 1ms. This ensures 0 remains a special value. - uint64_t want_value = current_time_ns - 1 * ns_in_ms; - uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); - offset_ns = old_value == 0 ? want_value : old_value; - } - - uint64_t result_in_ns = current_time_ns - offset_ns; - return (enet_uint32)(result_in_ns / ns_in_ms); - } - - void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) - { - if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ - *out = enet_v6_anyaddr; - } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ - *out = enet_v6_noaddr; - } else { - *out = enet_v4_anyaddr; - out->s6_addr[10] = 0xFF; - out->s6_addr[11] = 0xFF; - out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; - out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; - out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; - out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; - } - } - void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) - { - memset(out, 0, sizeof(struct in_addr)); - ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; - ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; - ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; - ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; - } - - int enet_in6addr_lookup_host(const char *name, bool nodns, struct in6_addr *out) { - struct addrinfo hints, *resultList = NULL, *result = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - - if (nodns) - { - hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ - } - - if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - for (result = resultList; result != NULL; result = result->ai_next) { - if (result->ai_addr != NULL) { - if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { - enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, out); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { - memcpy(out, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } - } - } - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, true, &address->host); - } - - int enet_address_set_host_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, false, &address->host); - } - - int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { - if (IN6_IS_ADDR_V4MAPPED(&address->host)) { - struct in_addr buf; - enet_inaddr_map6to4(&address->host, &buf); - - if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { - return -1; - } - } - else { - if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) { - return -1; - } - } - - return 0; - } /* enet_address_get_host_ip_new */ - - int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { - struct sockaddr_in6 sin; - memset(&sin, 0, sizeof(struct sockaddr_in6)); - - int err; - - - 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) { - return -1; - } - - return enet_address_get_host_ip_new(address, name, nameLength); - } /* enet_address_get_host_new */ - -// =======================================================================// -// ! -// ! Platform Specific (Unix) -// ! -// =======================================================================// - - #ifndef _WIN32 + #endif // __MINGW__ int enet_initialize(void) { return 0; @@ -314061,7 +314030,6 @@ extern "C" { ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr; freeaddrinfo(resultList); - return 0; } else if(result->ai_family == AF_INET6) { @@ -314071,16 +314039,11 @@ extern "C" { address->sin6_scope_id = sin->sin6_scope_id; freeaddrinfo(resultList); - return 0; } } } - - - if (resultList != NULL) { - freeaddrinfo(resultList); - } + freeaddrinfo(resultList); return enet_address_set_host_ip(address, name); } /* enet_address_set_host_old */ @@ -314152,7 +314115,7 @@ extern "C" { } ENetSocket enet_socket_create(ENetSocketType type) { - return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); + return socket(PF_INET6, (int)type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); } int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { diff --git a/engine/split/3rd_enet.h b/engine/split/3rd_enet.h index 71e5d12..2e63951 100644 --- a/engine/split/3rd_enet.h +++ b/engine/split/3rd_enet.h @@ -32,26 +32,10 @@ * SOFTWARE. * */ - -/* -## Disclaimer - -This is a fork of the original library [lsalzman/enet](https://github.com/lsalzman/enet). While original repo offers a stable, time-tested wonderful library, -we are trying to change some things, things, which can't be reflected on the main repo, like: - -* integrated ipv6 support -* added monotonic time -* applied project-wide code style change -* cleaned up project -* single-header style code -* NPM package distribution -* removed a lot of older methods -* and many other various changes -*/ - #ifndef ENET_INCLUDE_H #define ENET_INCLUDE_H +#include #include #include #include @@ -59,7 +43,7 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_VERSION_MAJOR 2 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 0 +#define ENET_VERSION_PATCH 9 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) @@ -88,8 +72,10 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifndef ENET_NO_PRAGMA_LINK - #pragma comment(lib, "ws2_32") //< @r-lyeh removed .lib (tcc support) - #pragma comment(lib, "winmm") //< @r-lyeh removed .lib (tcc support) + #ifndef __GNUC__ + #pragma comment(lib, "ws2_32.lib") + #pragma comment(lib, "winmm.lib") + #endif #endif #if _MSC_VER >= 1910 @@ -100,9 +86,9 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifdef __GNUC__ - #if (_WIN32_WINNT < 0x0501) + #if (_WIN32_WINNT < 0x0600) #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 + #define _WIN32_WINNT 0x0600 #endif #endif @@ -112,14 +98,14 @@ we are trying to change some things, things, which can't be reflected on the mai #include - #if defined(_MSC_VER) && _MSC_VER < 1900 //< @r-lyeh + #if defined(_WIN32) && defined(_MSC_VER) + #if _MSC_VER < 1900 typedef struct timespec { long tv_sec; long tv_nsec; }; #endif - #ifndef __MINGW32__ - #define CLOCK_MONOTONIC 0 //< @r-lyeh, tcc support + #define CLOCK_MONOTONIC 0 #endif typedef SOCKET ENetSocket; @@ -228,12 +214,12 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) #define ENET_IPV6 1 -const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; -const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; #define ENET_HOST_ANY in6addr_any #define ENET_HOST_BROADCAST 0xFFFFFFFFU #define ENET_PORT_ANY 0 @@ -268,6 +254,7 @@ extern "C" { extern void *enet_malloc(size_t); extern void enet_free(void *); extern ENetPacket* enet_packet_create(const void*,size_t,enet_uint32); + extern int enet_packet_resize(ENetPacket*, size_t); extern ENetPacket* enet_packet_copy(ENetPacket*); extern void enet_packet_destroy(ENetPacket*); @@ -627,7 +614,7 @@ extern "C" { ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, - ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MTU = 1392, ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, @@ -1245,16 +1232,6 @@ extern "C" { #undef AT_HAVE_ATOMICS -#else //< @r-lyeh: add __TINYC__ stubs. not going to work. - - #define ENET_ATOMIC_READ(variable) (*(int64_t *)(variable)) - #define ENET_ATOMIC_WRITE(variable, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_CAS(variable, old_value, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_INC(variable) ENET_ATOMIC_INC_BY(variable, 1) - #define ENET_ATOMIC_DEC(variable) ENET_ATOMIC_DEC_BY(variable, 1) - #define ENET_ATOMIC_INC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) + (delta)) - #define ENET_ATOMIC_DEC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) - (delta)) - #endif /* defined(_MSC_VER) */ // =======================================================================// @@ -1415,6 +1392,34 @@ extern "C" { return packet; } + /** Attempts to resize the data in the packet to length specified in the + dataLength parameter + @param packet packet to resize + @param dataLength new size for the packet data + @returns 0 on success, < 0 on failure + */ + int enet_packet_resize(ENetPacket * packet, size_t dataLength) + { + ENetPacket *newPacket = NULL; + + if (dataLength <= packet->dataLength || (packet->flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + { + packet->dataLength = dataLength; + + return 0; + } + + newPacket = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength); + if (newPacket == NULL) + return -1; + + memcpy(newPacket, packet, sizeof(ENetPacket) + packet->dataLength); + newPacket->data = (enet_uint8 *)newPacket + sizeof(ENetPacket); + enet_free(packet); + + return 0; + } + ENetPacket *enet_packet_create_offset(const void *data, size_t dataLength, size_t dataOffset, enet_uint32 flags) { ENetPacket *packet; if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { @@ -2244,18 +2249,17 @@ extern "C" { if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { return -1; } - if (peer->incomingBandwidth != 0) { --host->bandwidthLimitedPeers; } peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.incomingBandwidth); - peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); - if (peer->incomingBandwidth != 0) { ++host->bandwidthLimitedPeers; } + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); + if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) { peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) { @@ -2668,7 +2672,8 @@ extern "C" { goto commandError; } - if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { + assert(peer); + if ((command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { enet_uint16 sentTime; if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) { @@ -3160,12 +3165,12 @@ extern "C" { currentPeer->packetsLost = 0; } - host->buffers->data = headerData; + host->buffers[0].data = headerData; if (host->headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) { header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF); - host->buffers->dataLength = sizeof(ENetProtocolHeader); + host->buffers[0].dataLength = sizeof(ENetProtocolHeader); } else { - host->buffers->dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; + host->buffers[0].dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; } shouldCompress = 0; @@ -3186,9 +3191,9 @@ extern "C" { } header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags); if (host->checksum != NULL) { - enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers->dataLength]; + enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers[0].dataLength]; *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0; - host->buffers->dataLength += sizeof(enet_uint32); + host->buffers[0].dataLength += sizeof(enet_uint32); *checksum = host->checksum(host->buffers, host->bufferCount); } @@ -3203,6 +3208,9 @@ extern "C" { enet_protocol_remove_sent_unreliable_commands(currentPeer); if (sentLength < 0) { + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; return -1; } @@ -3211,6 +3219,10 @@ extern "C" { host->totalSentPackets++; } + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; + return 0; } /* enet_protocol_send_outgoing_commands */ @@ -3878,7 +3890,7 @@ extern "C" { * @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 */ void enet_peer_ping_interval(ENetPeer *peer, enet_uint32 pingInterval) { - peer->pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; + peer->pingInterval = pingInterval ? pingInterval : (enet_uint32)ENET_PEER_PING_INTERVAL; } /** Sets the timeout parameters for a peer. @@ -3899,9 +3911,9 @@ extern "C" { */ void enet_peer_timeout(ENetPeer *peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) { - peer->timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; - peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; - peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; + peer->timeoutLimit = timeoutLimit ? timeoutLimit : (enet_uint32)ENET_PEER_TIMEOUT_LIMIT; + peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : (enet_uint32)ENET_PEER_TIMEOUT_MINIMUM; + peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : (enet_uint32)ENET_PEER_TIMEOUT_MAXIMUM; } /** Force an immediate disconnection from a peer. @@ -4356,10 +4368,9 @@ extern "C" { memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32)); } - if (packet != NULL) { - ++packet->referenceCount; - peer->totalWaitingData += packet->dataLength; - } + assert(packet != NULL); + ++packet->referenceCount; + peer->totalWaitingData += packet->dataLength; enet_list_insert(enet_list_next(currentCommand), incomingCommand); @@ -4381,7 +4392,7 @@ extern "C" { goto notifyError; } - if (packet != NULL && packet->referenceCount == 0) { + if (packet != NULL && packet->referenceCount == 0) { callbacks.packet_destroy(packet); } @@ -4464,11 +4475,9 @@ extern "C" { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->randomSeed = (enet_uint32) (size_t) host; + host->randomSeed = (enet_uint32) ((uintptr_t) host % UINT32_MAX); host->randomSeed += enet_host_random_seed(); host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16); host->channelLimit = channelLimit; @@ -4717,10 +4726,7 @@ extern "C" { void enet_host_channel_limit(ENetHost *host, size_t channelLimit) { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->channelLimit = channelLimit; } @@ -4905,20 +4911,256 @@ extern "C" { // =======================================================================// // ! -// ! Compat +// ! Time // ! // =======================================================================// - #if (defined _MSC_VER && defined _WIN32 && !defined _WIN64) || \ - (defined __MINGW32__ || defined __MINGW64__) // (!defined _WIN32 && defined __MINGW32__ && defined ENET_MINGW_COMPAT) //< @r-lyeh - #define MUST_DEFINE_NTOP_PTON 1 - #else - #define MUST_DEFINE_NTOP_PTON 0 + #ifdef _WIN32 + static LARGE_INTEGER getFILETIMEoffset() { + SYSTEMTIME s; + FILETIME f; + LARGE_INTEGER t; + + s.wYear = 1970; + s.wMonth = 1; + s.wDay = 1; + s.wHour = 0; + s.wMinute = 0; + s.wSecond = 0; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + return (t); + } + int clock_gettime(int X, struct timespec *tv) { + (void)X; + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) { + LARGE_INTEGER performanceFrequency; + initialized = 1; + usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); + if (usePerformanceCounter) { + QueryPerformanceCounter(&offset); + frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; + } else { + offset = getFILETIMEoffset(); + frequencyToMicroseconds = 10.; + } + } + if (usePerformanceCounter) { + QueryPerformanceCounter(&t); + } else { + GetSystemTimeAsFileTime(&f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + } + + t.QuadPart -= offset.QuadPart; + microseconds = (double)t.QuadPart / frequencyToMicroseconds; + t.QuadPart = (LONGLONG)microseconds; + tv->tv_sec = (long)(t.QuadPart / 1000000); + tv->tv_nsec = t.QuadPart % 1000000 * 1000; + return (0); + } + #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + #define CLOCK_MONOTONIC 0 + + int clock_gettime(int X, struct timespec *ts) { + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; + + return 0; + } #endif - #if MUST_DEFINE_NTOP_PTON //< @r-lyeh + enet_uint32 enet_time_get() { + // TODO enet uses 32 bit timestamps. We should modify it to use + // 64 bit timestamps, but this is not trivial since we'd end up + // changing half the structs in enet. For now, retain 32 bits, but + // use an offset so we don't run out of bits. Basically, the first + // call of enet_time_get() will always return 1, and follow-up calls + // indicate elapsed time since the first call. + // + // Note that we don't want to return 0 from the first call, in case + // some part of enet uses 0 as a special value (meaning time not set + // for example). + static uint64_t start_time_ns = 0; - // #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) //< @r-lyeh + struct timespec ts; + #if defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + #else + clock_gettime(CLOCK_MONOTONIC, &ts); + #endif + + static const uint64_t ns_in_s = 1000 * 1000 * 1000; + static const uint64_t ns_in_ms = 1000 * 1000; + uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; + + // Most of the time we just want to atomically read the start time. We + // could just use a single CAS instruction instead of this if, but it + // would be slower in the average case. + // + // Note that statics are auto-initialized to zero, and starting a thread + // implies a memory barrier. So we know that whatever thread calls this, + // it correctly sees the start_time_ns as 0 initially. + uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); + if (offset_ns == 0) { + // We still need to CAS, since two different threads can get here + // at the same time. + // + // We assume that current_time_ns is > 1ms. + // + // Set the value of the start_time_ns, such that the first timestamp + // is at 1ms. This ensures 0 remains a special value. + uint64_t want_value = current_time_ns - 1 * ns_in_ms; + uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); + offset_ns = old_value == 0 ? want_value : old_value; + } + + uint64_t result_in_ns = current_time_ns - offset_ns; + return (enet_uint32)(result_in_ns / ns_in_ms); + } + + void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) + { + if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ + *out = enet_v6_anyaddr; + } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ + *out = enet_v6_noaddr; + } else { + *out = enet_v4_anyaddr; + out->s6_addr[10] = 0xFF; + out->s6_addr[11] = 0xFF; + out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; + out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; + out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; + out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; + } + } + void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) + { + memset(out, 0, sizeof(struct in_addr)); + ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; + ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; + ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; + ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; + } + + int enet_in6addr_lookup_host(const char *name, bool nodns, ENetAddress *out) { + struct addrinfo hints, *resultList = NULL, *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (nodns) + { + hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ + } + + if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { + freeaddrinfo(resultList); + return -1; + } + + for (result = resultList; result != NULL; result = result->ai_next) { + if (result->ai_addr != NULL) { + if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { + enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, &out->host); + out->sin6_scope_id = 0; + freeaddrinfo(resultList); + return 0; + + } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { + memcpy(&out->host, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + out->sin6_scope_id = (enet_uint16) ((struct sockaddr_in6*)result->ai_addr)->sin6_scope_id; + freeaddrinfo(resultList); + return 0; + } + } + } + freeaddrinfo(resultList); + return -1; + } + + int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, true, address); + } + + int enet_address_set_host_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, false, address); + } + + int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { + if (IN6_IS_ADDR_V4MAPPED(&address->host)) { + struct in_addr buf; + enet_inaddr_map6to4(&address->host, &buf); + + if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { + return -1; + } + } + else { + if (inet_ntop(AF_INET6, (void*)&address->host, name, nameLength) == NULL) { + return -1; + } + } + + return 0; + } /* enet_address_get_host_ip_new */ + + int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + int err; + + + 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) { + return -1; + } + + return enet_address_get_host_ip_new(address, name, nameLength); + } /* enet_address_get_host_new */ + +// =======================================================================// +// ! +// ! Platform Specific (Unix) +// ! +// =======================================================================// + + #ifndef _WIN32 + + #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) // inet_ntop/inet_pton for MinGW from http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { if (af == AF_INET) { @@ -5098,280 +5340,7 @@ extern "C" { return -1; } } - - #endif // MUST_DEFINE_NTOP_PTON //< @r-lyeh - -// =======================================================================// -// ! -// ! Time -// ! -// =======================================================================// - - #ifdef _WIN32 - static LARGE_INTEGER getFILETIMEoffset() { - SYSTEMTIME s; - FILETIME f; - LARGE_INTEGER t; - - s.wYear = 1970; - s.wMonth = 1; - s.wDay = 1; - s.wHour = 0; - s.wMinute = 0; - s.wSecond = 0; - s.wMilliseconds = 0; - SystemTimeToFileTime(&s, &f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - return (t); - } - - #ifdef __MINGW32__ - #define clock_gettime clock_gettime2 // symbol defined in pthread_time.h instead. workaround to avoid user linking against -lpthread. - #endif - -// #ifndef CLOCK_MONOTONIC_RAW -// #define CLOCK_MONOTONIC_RAW 0 // for zig-cc -// #endif - - int clock_gettime(int X, struct timespec *tv) { - LARGE_INTEGER t; - FILETIME f; - double microseconds; - static LARGE_INTEGER offset; - static double frequencyToMicroseconds; - static int initialized = 0; - static BOOL usePerformanceCounter = 0; - - if (!initialized) { - LARGE_INTEGER performanceFrequency; - initialized = 1; - usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); - if (usePerformanceCounter) { - QueryPerformanceCounter(&offset); - frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; - } else { - offset = getFILETIMEoffset(); - frequencyToMicroseconds = 10.; - } - } - if (usePerformanceCounter) { - QueryPerformanceCounter(&t); - } else { - GetSystemTimeAsFileTime(&f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - } - - t.QuadPart -= offset.QuadPart; - microseconds = (double)t.QuadPart / frequencyToMicroseconds; - t.QuadPart = (LONGLONG)microseconds; - tv->tv_sec = (long)(t.QuadPart / 1000000); - tv->tv_nsec = t.QuadPart % 1000000 * 1000; - return (0); - } - - #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #define CLOCK_MONOTONIC 0 - - int clock_gettime(int X, struct timespec *ts) { - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - ts->tv_sec = mts.tv_sec; - ts->tv_nsec = mts.tv_nsec; - - return 0; - } - #endif - - enet_uint32 enet_time_get() { - // TODO enet uses 32 bit timestamps. We should modify it to use - // 64 bit timestamps, but this is not trivial since we'd end up - // changing half the structs in enet. For now, retain 32 bits, but - // use an offset so we don't run out of bits. Basically, the first - // call of enet_time_get() will always return 1, and follow-up calls - // indicate elapsed time since the first call. - // - // Note that we don't want to return 0 from the first call, in case - // some part of enet uses 0 as a special value (meaning time not set - // for example). - static uint64_t start_time_ns = 0; - - struct timespec ts; - #if defined(CLOCK_MONOTONIC_RAW) - clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - #else - clock_gettime(CLOCK_MONOTONIC, &ts); - #endif - - static const uint64_t ns_in_s = 1000 * 1000 * 1000; - static const uint64_t ns_in_ms = 1000 * 1000; - uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; - - // Most of the time we just want to atomically read the start time. We - // could just use a single CAS instruction instead of this if, but it - // would be slower in the average case. - // - // Note that statics are auto-initialized to zero, and starting a thread - // implies a memory barrier. So we know that whatever thread calls this, - // it correctly sees the start_time_ns as 0 initially. - uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); - if (offset_ns == 0) { - // We still need to CAS, since two different threads can get here - // at the same time. - // - // We assume that current_time_ns is > 1ms. - // - // Set the value of the start_time_ns, such that the first timestamp - // is at 1ms. This ensures 0 remains a special value. - uint64_t want_value = current_time_ns - 1 * ns_in_ms; - uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); - offset_ns = old_value == 0 ? want_value : old_value; - } - - uint64_t result_in_ns = current_time_ns - offset_ns; - return (enet_uint32)(result_in_ns / ns_in_ms); - } - - void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) - { - if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ - *out = enet_v6_anyaddr; - } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ - *out = enet_v6_noaddr; - } else { - *out = enet_v4_anyaddr; - out->s6_addr[10] = 0xFF; - out->s6_addr[11] = 0xFF; - out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; - out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; - out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; - out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; - } - } - void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) - { - memset(out, 0, sizeof(struct in_addr)); - ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; - ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; - ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; - ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; - } - - int enet_in6addr_lookup_host(const char *name, bool nodns, struct in6_addr *out) { - struct addrinfo hints, *resultList = NULL, *result = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - - if (nodns) - { - hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ - } - - if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - for (result = resultList; result != NULL; result = result->ai_next) { - if (result->ai_addr != NULL) { - if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { - enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, out); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { - memcpy(out, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } - } - } - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, true, &address->host); - } - - int enet_address_set_host_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, false, &address->host); - } - - int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { - if (IN6_IS_ADDR_V4MAPPED(&address->host)) { - struct in_addr buf; - enet_inaddr_map6to4(&address->host, &buf); - - if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { - return -1; - } - } - else { - if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) { - return -1; - } - } - - return 0; - } /* enet_address_get_host_ip_new */ - - int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { - struct sockaddr_in6 sin; - memset(&sin, 0, sizeof(struct sockaddr_in6)); - - int err; - - - 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) { - return -1; - } - - return enet_address_get_host_ip_new(address, name, nameLength); - } /* enet_address_get_host_new */ - -// =======================================================================// -// ! -// ! Platform Specific (Unix) -// ! -// =======================================================================// - - #ifndef _WIN32 + #endif // __MINGW__ int enet_initialize(void) { return 0; @@ -5412,7 +5381,6 @@ extern "C" { ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr; freeaddrinfo(resultList); - return 0; } else if(result->ai_family == AF_INET6) { @@ -5422,16 +5390,11 @@ extern "C" { address->sin6_scope_id = sin->sin6_scope_id; freeaddrinfo(resultList); - return 0; } } } - - - if (resultList != NULL) { - freeaddrinfo(resultList); - } + freeaddrinfo(resultList); return enet_address_set_host_ip(address, name); } /* enet_address_set_host_old */ @@ -5503,7 +5466,7 @@ extern "C" { } ENetSocket enet_socket_create(ENetSocketType type) { - return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); + return socket(PF_INET6, (int)type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); } int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { diff --git a/engine/v4k b/engine/v4k index 2fd4bba..667b80c 100644 --- a/engine/v4k +++ b/engine/v4k @@ -289788,26 +289788,10 @@ int main() { * SOFTWARE. * */ - -/* -## Disclaimer - -This is a fork of the original library [lsalzman/enet](https://github.com/lsalzman/enet). While original repo offers a stable, time-tested wonderful library, -we are trying to change some things, things, which can't be reflected on the main repo, like: - -* integrated ipv6 support -* added monotonic time -* applied project-wide code style change -* cleaned up project -* single-header style code -* NPM package distribution -* removed a lot of older methods -* and many other various changes -*/ - #ifndef ENET_INCLUDE_H #define ENET_INCLUDE_H +#include #include #include #include @@ -289815,7 +289799,7 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_VERSION_MAJOR 2 #define ENET_VERSION_MINOR 3 -#define ENET_VERSION_PATCH 0 +#define ENET_VERSION_PATCH 9 #define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) #define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) #define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) @@ -289844,8 +289828,10 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifndef ENET_NO_PRAGMA_LINK - #pragma comment(lib, "ws2_32") //< @r-lyeh removed .lib (tcc support) - #pragma comment(lib, "winmm") //< @r-lyeh removed .lib (tcc support) + #ifndef __GNUC__ + #pragma comment(lib, "ws2_32.lib") + #pragma comment(lib, "winmm.lib") + #endif #endif #if _MSC_VER >= 1910 @@ -289856,9 +289842,9 @@ we are trying to change some things, things, which can't be reflected on the mai #endif #ifdef __GNUC__ - #if (_WIN32_WINNT < 0x0501) + #if (_WIN32_WINNT < 0x0600) #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 + #define _WIN32_WINNT 0x0600 #endif #endif @@ -289868,14 +289854,14 @@ we are trying to change some things, things, which can't be reflected on the mai #include - #if defined(_MSC_VER) && _MSC_VER < 1900 //< @r-lyeh + #if defined(_WIN32) && defined(_MSC_VER) + #if _MSC_VER < 1900 typedef struct timespec { long tv_sec; long tv_nsec; }; #endif - #ifndef __MINGW32__ - #define CLOCK_MONOTONIC 0 //< @r-lyeh, tcc support + #define CLOCK_MONOTONIC 0 #endif typedef SOCKET ENetSocket; @@ -289984,12 +289970,12 @@ we are trying to change some things, things, which can't be reflected on the mai #define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) #define ENET_IPV6 1 -const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; -const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; -const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; -const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; #define ENET_HOST_ANY in6addr_any #define ENET_HOST_BROADCAST 0xFFFFFFFFU #define ENET_PORT_ANY 0 @@ -290024,6 +290010,7 @@ extern "C" { extern void *enet_malloc(size_t); extern void enet_free(void *); extern ENetPacket* enet_packet_create(const void*,size_t,enet_uint32); + extern int enet_packet_resize(ENetPacket*, size_t); extern ENetPacket* enet_packet_copy(ENetPacket*); extern void enet_packet_destroy(ENetPacket*); @@ -290383,7 +290370,7 @@ extern "C" { ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, - ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MTU = 1392, ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, @@ -291001,16 +290988,6 @@ extern "C" { #undef AT_HAVE_ATOMICS -#else //< @r-lyeh: add __TINYC__ stubs. not going to work. - - #define ENET_ATOMIC_READ(variable) (*(int64_t *)(variable)) - #define ENET_ATOMIC_WRITE(variable, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_CAS(variable, old_value, new_val) (*(int64_t *)(variable) = (int64_t)(new_val)) - #define ENET_ATOMIC_INC(variable) ENET_ATOMIC_INC_BY(variable, 1) - #define ENET_ATOMIC_DEC(variable) ENET_ATOMIC_DEC_BY(variable, 1) - #define ENET_ATOMIC_INC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) + (delta)) - #define ENET_ATOMIC_DEC_BY(variable, delta) ( *(int64_t*)(variable) = (int64_t*)(variable) - (delta)) - #endif /* defined(_MSC_VER) */ // =======================================================================// @@ -291171,6 +291148,34 @@ extern "C" { return packet; } + /** Attempts to resize the data in the packet to length specified in the + dataLength parameter + @param packet packet to resize + @param dataLength new size for the packet data + @returns 0 on success, < 0 on failure + */ + int enet_packet_resize(ENetPacket * packet, size_t dataLength) + { + ENetPacket *newPacket = NULL; + + if (dataLength <= packet->dataLength || (packet->flags & ENET_PACKET_FLAG_NO_ALLOCATE)) + { + packet->dataLength = dataLength; + + return 0; + } + + newPacket = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength); + if (newPacket == NULL) + return -1; + + memcpy(newPacket, packet, sizeof(ENetPacket) + packet->dataLength); + newPacket->data = (enet_uint8 *)newPacket + sizeof(ENetPacket); + enet_free(packet); + + return 0; + } + ENetPacket *enet_packet_create_offset(const void *data, size_t dataLength, size_t dataOffset, enet_uint32 flags) { ENetPacket *packet; if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { @@ -292000,18 +292005,17 @@ extern "C" { if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { return -1; } - if (peer->incomingBandwidth != 0) { --host->bandwidthLimitedPeers; } peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.incomingBandwidth); - peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); - if (peer->incomingBandwidth != 0) { ++host->bandwidthLimitedPeers; } + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); + if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) { peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) { @@ -292424,7 +292428,8 @@ extern "C" { goto commandError; } - if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { + assert(peer); + if ((command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { enet_uint16 sentTime; if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) { @@ -292916,12 +292921,12 @@ extern "C" { currentPeer->packetsLost = 0; } - host->buffers->data = headerData; + host->buffers[0].data = headerData; if (host->headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) { header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF); - host->buffers->dataLength = sizeof(ENetProtocolHeader); + host->buffers[0].dataLength = sizeof(ENetProtocolHeader); } else { - host->buffers->dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; + host->buffers[0].dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; } shouldCompress = 0; @@ -292942,9 +292947,9 @@ extern "C" { } header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags); if (host->checksum != NULL) { - enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers->dataLength]; + enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers[0].dataLength]; *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0; - host->buffers->dataLength += sizeof(enet_uint32); + host->buffers[0].dataLength += sizeof(enet_uint32); *checksum = host->checksum(host->buffers, host->bufferCount); } @@ -292959,6 +292964,9 @@ extern "C" { enet_protocol_remove_sent_unreliable_commands(currentPeer); if (sentLength < 0) { + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; return -1; } @@ -292967,6 +292975,10 @@ extern "C" { host->totalSentPackets++; } + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; + return 0; } /* enet_protocol_send_outgoing_commands */ @@ -293634,7 +293646,7 @@ extern "C" { * @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 */ void enet_peer_ping_interval(ENetPeer *peer, enet_uint32 pingInterval) { - peer->pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL; + peer->pingInterval = pingInterval ? pingInterval : (enet_uint32)ENET_PEER_PING_INTERVAL; } /** Sets the timeout parameters for a peer. @@ -293655,9 +293667,9 @@ extern "C" { */ void enet_peer_timeout(ENetPeer *peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) { - peer->timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT; - peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM; - peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM; + peer->timeoutLimit = timeoutLimit ? timeoutLimit : (enet_uint32)ENET_PEER_TIMEOUT_LIMIT; + peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : (enet_uint32)ENET_PEER_TIMEOUT_MINIMUM; + peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : (enet_uint32)ENET_PEER_TIMEOUT_MAXIMUM; } /** Force an immediate disconnection from a peer. @@ -294112,10 +294124,9 @@ extern "C" { memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32)); } - if (packet != NULL) { - ++packet->referenceCount; - peer->totalWaitingData += packet->dataLength; - } + assert(packet != NULL); + ++packet->referenceCount; + peer->totalWaitingData += packet->dataLength; enet_list_insert(enet_list_next(currentCommand), incomingCommand); @@ -294137,7 +294148,7 @@ extern "C" { goto notifyError; } - if (packet != NULL && packet->referenceCount == 0) { + if (packet != NULL && packet->referenceCount == 0) { callbacks.packet_destroy(packet); } @@ -294220,11 +294231,9 @@ extern "C" { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->randomSeed = (enet_uint32) (size_t) host; + host->randomSeed = (enet_uint32) ((uintptr_t) host % UINT32_MAX); host->randomSeed += enet_host_random_seed(); host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16); host->channelLimit = channelLimit; @@ -294473,10 +294482,7 @@ extern "C" { void enet_host_channel_limit(ENetHost *host, size_t channelLimit) { if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } else if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; } - host->channelLimit = channelLimit; } @@ -294661,20 +294667,256 @@ extern "C" { // =======================================================================// // ! -// ! Compat +// ! Time // ! // =======================================================================// - #if (defined _MSC_VER && defined _WIN32 && !defined _WIN64) || \ - (defined __MINGW32__ || defined __MINGW64__) // (!defined _WIN32 && defined __MINGW32__ && defined ENET_MINGW_COMPAT) //< @r-lyeh - #define MUST_DEFINE_NTOP_PTON 1 - #else - #define MUST_DEFINE_NTOP_PTON 0 + #ifdef _WIN32 + static LARGE_INTEGER getFILETIMEoffset() { + SYSTEMTIME s; + FILETIME f; + LARGE_INTEGER t; + + s.wYear = 1970; + s.wMonth = 1; + s.wDay = 1; + s.wHour = 0; + s.wMinute = 0; + s.wSecond = 0; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + return (t); + } + int clock_gettime(int X, struct timespec *tv) { + (void)X; + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) { + LARGE_INTEGER performanceFrequency; + initialized = 1; + usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); + if (usePerformanceCounter) { + QueryPerformanceCounter(&offset); + frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; + } else { + offset = getFILETIMEoffset(); + frequencyToMicroseconds = 10.; + } + } + if (usePerformanceCounter) { + QueryPerformanceCounter(&t); + } else { + GetSystemTimeAsFileTime(&f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + } + + t.QuadPart -= offset.QuadPart; + microseconds = (double)t.QuadPart / frequencyToMicroseconds; + t.QuadPart = (LONGLONG)microseconds; + tv->tv_sec = (long)(t.QuadPart / 1000000); + tv->tv_nsec = t.QuadPart % 1000000 * 1000; + return (0); + } + #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + #define CLOCK_MONOTONIC 0 + + int clock_gettime(int X, struct timespec *ts) { + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; + + return 0; + } #endif - #if MUST_DEFINE_NTOP_PTON //< @r-lyeh + enet_uint32 enet_time_get() { + // TODO enet uses 32 bit timestamps. We should modify it to use + // 64 bit timestamps, but this is not trivial since we'd end up + // changing half the structs in enet. For now, retain 32 bits, but + // use an offset so we don't run out of bits. Basically, the first + // call of enet_time_get() will always return 1, and follow-up calls + // indicate elapsed time since the first call. + // + // Note that we don't want to return 0 from the first call, in case + // some part of enet uses 0 as a special value (meaning time not set + // for example). + static uint64_t start_time_ns = 0; - // #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) //< @r-lyeh + struct timespec ts; + #if defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + #else + clock_gettime(CLOCK_MONOTONIC, &ts); + #endif + + static const uint64_t ns_in_s = 1000 * 1000 * 1000; + static const uint64_t ns_in_ms = 1000 * 1000; + uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; + + // Most of the time we just want to atomically read the start time. We + // could just use a single CAS instruction instead of this if, but it + // would be slower in the average case. + // + // Note that statics are auto-initialized to zero, and starting a thread + // implies a memory barrier. So we know that whatever thread calls this, + // it correctly sees the start_time_ns as 0 initially. + uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); + if (offset_ns == 0) { + // We still need to CAS, since two different threads can get here + // at the same time. + // + // We assume that current_time_ns is > 1ms. + // + // Set the value of the start_time_ns, such that the first timestamp + // is at 1ms. This ensures 0 remains a special value. + uint64_t want_value = current_time_ns - 1 * ns_in_ms; + uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); + offset_ns = old_value == 0 ? want_value : old_value; + } + + uint64_t result_in_ns = current_time_ns - offset_ns; + return (enet_uint32)(result_in_ns / ns_in_ms); + } + + void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) + { + if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ + *out = enet_v6_anyaddr; + } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ + *out = enet_v6_noaddr; + } else { + *out = enet_v4_anyaddr; + out->s6_addr[10] = 0xFF; + out->s6_addr[11] = 0xFF; + out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; + out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; + out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; + out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; + } + } + void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) + { + memset(out, 0, sizeof(struct in_addr)); + ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; + ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; + ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; + ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; + } + + int enet_in6addr_lookup_host(const char *name, bool nodns, ENetAddress *out) { + struct addrinfo hints, *resultList = NULL, *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (nodns) + { + hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ + } + + if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { + freeaddrinfo(resultList); + return -1; + } + + for (result = resultList; result != NULL; result = result->ai_next) { + if (result->ai_addr != NULL) { + if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { + enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, &out->host); + out->sin6_scope_id = 0; + freeaddrinfo(resultList); + return 0; + + } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { + memcpy(&out->host, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + out->sin6_scope_id = (enet_uint16) ((struct sockaddr_in6*)result->ai_addr)->sin6_scope_id; + freeaddrinfo(resultList); + return 0; + } + } + } + freeaddrinfo(resultList); + return -1; + } + + int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, true, address); + } + + int enet_address_set_host_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, false, address); + } + + int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { + if (IN6_IS_ADDR_V4MAPPED(&address->host)) { + struct in_addr buf; + enet_inaddr_map6to4(&address->host, &buf); + + if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { + return -1; + } + } + else { + if (inet_ntop(AF_INET6, (void*)&address->host, name, nameLength) == NULL) { + return -1; + } + } + + return 0; + } /* enet_address_get_host_ip_new */ + + int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + int err; + + + 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) { + return -1; + } + + return enet_address_get_host_ip_new(address, name, nameLength); + } /* enet_address_get_host_new */ + +// =======================================================================// +// ! +// ! Platform Specific (Unix) +// ! +// =======================================================================// + + #ifndef _WIN32 + + #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) // inet_ntop/inet_pton for MinGW from http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { if (af == AF_INET) { @@ -294854,280 +295096,7 @@ extern "C" { return -1; } } - - #endif // MUST_DEFINE_NTOP_PTON //< @r-lyeh - -// =======================================================================// -// ! -// ! Time -// ! -// =======================================================================// - - #ifdef _WIN32 - static LARGE_INTEGER getFILETIMEoffset() { - SYSTEMTIME s; - FILETIME f; - LARGE_INTEGER t; - - s.wYear = 1970; - s.wMonth = 1; - s.wDay = 1; - s.wHour = 0; - s.wMinute = 0; - s.wSecond = 0; - s.wMilliseconds = 0; - SystemTimeToFileTime(&s, &f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - return (t); - } - - #ifdef __MINGW32__ - #define clock_gettime clock_gettime2 // symbol defined in pthread_time.h instead. workaround to avoid user linking against -lpthread. - #endif - -// #ifndef CLOCK_MONOTONIC_RAW -// #define CLOCK_MONOTONIC_RAW 0 // for zig-cc -// #endif - - int clock_gettime(int X, struct timespec *tv) { - LARGE_INTEGER t; - FILETIME f; - double microseconds; - static LARGE_INTEGER offset; - static double frequencyToMicroseconds; - static int initialized = 0; - static BOOL usePerformanceCounter = 0; - - if (!initialized) { - LARGE_INTEGER performanceFrequency; - initialized = 1; - usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); - if (usePerformanceCounter) { - QueryPerformanceCounter(&offset); - frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; - } else { - offset = getFILETIMEoffset(); - frequencyToMicroseconds = 10.; - } - } - if (usePerformanceCounter) { - QueryPerformanceCounter(&t); - } else { - GetSystemTimeAsFileTime(&f); - t.QuadPart = f.dwHighDateTime; - t.QuadPart <<= 32; - t.QuadPart |= f.dwLowDateTime; - } - - t.QuadPart -= offset.QuadPart; - microseconds = (double)t.QuadPart / frequencyToMicroseconds; - t.QuadPart = (LONGLONG)microseconds; - tv->tv_sec = (long)(t.QuadPart / 1000000); - tv->tv_nsec = t.QuadPart % 1000000 * 1000; - return (0); - } - - #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 - #define CLOCK_MONOTONIC 0 - - int clock_gettime(int X, struct timespec *ts) { - clock_serv_t cclock; - mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, &mts); - mach_port_deallocate(mach_task_self(), cclock); - - ts->tv_sec = mts.tv_sec; - ts->tv_nsec = mts.tv_nsec; - - return 0; - } - #endif - - enet_uint32 enet_time_get() { - // TODO enet uses 32 bit timestamps. We should modify it to use - // 64 bit timestamps, but this is not trivial since we'd end up - // changing half the structs in enet. For now, retain 32 bits, but - // use an offset so we don't run out of bits. Basically, the first - // call of enet_time_get() will always return 1, and follow-up calls - // indicate elapsed time since the first call. - // - // Note that we don't want to return 0 from the first call, in case - // some part of enet uses 0 as a special value (meaning time not set - // for example). - static uint64_t start_time_ns = 0; - - struct timespec ts; - #if defined(CLOCK_MONOTONIC_RAW) - clock_gettime(CLOCK_MONOTONIC_RAW, &ts); - #else - clock_gettime(CLOCK_MONOTONIC, &ts); - #endif - - static const uint64_t ns_in_s = 1000 * 1000 * 1000; - static const uint64_t ns_in_ms = 1000 * 1000; - uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; - - // Most of the time we just want to atomically read the start time. We - // could just use a single CAS instruction instead of this if, but it - // would be slower in the average case. - // - // Note that statics are auto-initialized to zero, and starting a thread - // implies a memory barrier. So we know that whatever thread calls this, - // it correctly sees the start_time_ns as 0 initially. - uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); - if (offset_ns == 0) { - // We still need to CAS, since two different threads can get here - // at the same time. - // - // We assume that current_time_ns is > 1ms. - // - // Set the value of the start_time_ns, such that the first timestamp - // is at 1ms. This ensures 0 remains a special value. - uint64_t want_value = current_time_ns - 1 * ns_in_ms; - uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); - offset_ns = old_value == 0 ? want_value : old_value; - } - - uint64_t result_in_ns = current_time_ns - offset_ns; - return (enet_uint32)(result_in_ns / ns_in_ms); - } - - void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) - { - if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ - *out = enet_v6_anyaddr; - } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ - *out = enet_v6_noaddr; - } else { - *out = enet_v4_anyaddr; - out->s6_addr[10] = 0xFF; - out->s6_addr[11] = 0xFF; - out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; - out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; - out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; - out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; - } - } - void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) - { - memset(out, 0, sizeof(struct in_addr)); - ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; - ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; - ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; - ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; - } - - int enet_in6addr_lookup_host(const char *name, bool nodns, struct in6_addr *out) { - struct addrinfo hints, *resultList = NULL, *result = NULL; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - - if (nodns) - { - hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ - } - - if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - for (result = resultList; result != NULL; result = result->ai_next) { - if (result->ai_addr != NULL) { - if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { - enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, out); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { - memcpy(out, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return 0; - } - } - } - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - return -1; - } - - int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, true, &address->host); - } - - int enet_address_set_host_new(ENetAddress *address, const char *name) { - return enet_in6addr_lookup_host(name, false, &address->host); - } - - int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { - if (IN6_IS_ADDR_V4MAPPED(&address->host)) { - struct in_addr buf; - enet_inaddr_map6to4(&address->host, &buf); - - if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { - return -1; - } - } - else { - if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) { - return -1; - } - } - - return 0; - } /* enet_address_get_host_ip_new */ - - int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { - struct sockaddr_in6 sin; - memset(&sin, 0, sizeof(struct sockaddr_in6)); - - int err; - - - 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) { - return -1; - } - - return enet_address_get_host_ip_new(address, name, nameLength); - } /* enet_address_get_host_new */ - -// =======================================================================// -// ! -// ! Platform Specific (Unix) -// ! -// =======================================================================// - - #ifndef _WIN32 + #endif // __MINGW__ int enet_initialize(void) { return 0; @@ -295168,7 +295137,6 @@ extern "C" { ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr; freeaddrinfo(resultList); - return 0; } else if(result->ai_family == AF_INET6) { @@ -295178,16 +295146,11 @@ extern "C" { address->sin6_scope_id = sin->sin6_scope_id; freeaddrinfo(resultList); - return 0; } } } - - - if (resultList != NULL) { - freeaddrinfo(resultList); - } + freeaddrinfo(resultList); return enet_address_set_host_ip(address, name); } /* enet_address_set_host_old */ @@ -295259,7 +295222,7 @@ extern "C" { } ENetSocket enet_socket_create(ENetSocketType type) { - return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); + return socket(PF_INET6, (int)type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); } int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) {