From 0036402be853761dab6b2e9295925cdcc0b57767 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 3 Aug 2020 20:01:08 +0200 Subject: [PATCH] - removed most of the network code in Blood. Mainly to expose the parts that still get used in single player because there's some problems here that need addressing. ENet is also gone now. --- source/CMakeLists.txt | 1 - source/blood/src/blood.cpp | 7 +- source/blood/src/controls.cpp | 6 +- source/blood/src/messages.cpp | 2 +- source/blood/src/network.cpp | 1005 +---- source/blood/src/network.h | 6 +- source/blood/src/player.cpp | 20 - source/core/gamecontrol.cpp | 4 - source/thirdparty/include/enet.h | 5907 ------------------------------ source/thirdparty/src/enet.cpp | 18 - 10 files changed, 13 insertions(+), 6963 deletions(-) delete mode 100644 source/thirdparty/include/enet.h delete mode 100644 source/thirdparty/src/enet.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index f21850b7e..60a39b67d 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -766,7 +766,6 @@ set (PCH_SOURCES thirdparty/src/base64.cpp thirdparty/src/fix16.cpp thirdparty/src/md4.cpp - thirdparty/src/enet.cpp # Todo: Split out the license-safe code from this. build/src/animvpx.cpp diff --git a/source/blood/src/blood.cpp b/source/blood/src/blood.cpp index 1019dd406..dd103c65a 100644 --- a/source/blood/src/blood.cpp +++ b/source/blood/src/blood.cpp @@ -525,7 +525,7 @@ void StartLevel(GAMEOPTIONS *gameOptions) if (!bVanilla && !gMe->packSlots[1].isActive) // if diving suit is not active, turn off reverb sound effect sfxSetReverb(0); ambInit(); - sub_79760(); + netReset(); gFrame = 0; gChokeCounter = 0; M_ClearMenus(); @@ -557,12 +557,14 @@ void ProcessFrame(void) gPlayer[i].input.q16mlook = gFifoInput[gNetFifoTail&255][i].q16mlook; } gNetFifoTail++; +#if 0 if (!(gFrame&7)) { CalcGameChecksum(); memcpy(gCheckFifo[gCheckHead[myconnectindex]&255][myconnectindex], gChecksum, sizeof(gChecksum)); gCheckHead[myconnectindex]++; } +#endif for (int i = connecthead; i >= 0; i = connectpoint2[i]) { if (gPlayer[i].input.keyFlags.quit) @@ -797,7 +799,7 @@ static void app_init() static void gameInit() { //RESTART: - sub_79760(); + netReset(); gViewIndex = myconnectindex; gMe = gView = &gPlayer[myconnectindex]; netBroadcastPlayerInfo(myconnectindex); @@ -848,7 +850,6 @@ static void gameTicker() break; if (i >= 0) break; - //faketimerhandler(); ProcessFrame(); gameUpdate = true; } diff --git a/source/blood/src/controls.cpp b/source/blood/src/controls.cpp index d1a0797f4..cc832666e 100644 --- a/source/blood/src/controls.cpp +++ b/source/blood/src/controls.cpp @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "view.h" #include "d_event.h" #include "gamestate.h" +#include "sound.h" BEGIN_BLD_NS @@ -119,7 +120,8 @@ void LocalKeys(void) char fk = key - sc_F1; if (alt) { - netBroadcastTaunt(myconnectindex, fk); + sndStartSample(4400 + fk, 128, 1, 0); + //netBroadcastTaunt(myconnectindex, fk); } else { @@ -129,7 +131,7 @@ void LocalKeys(void) buttonMap.ClearButton(gamefunc_Third_Person_View); return; } - } + } } diff --git a/source/blood/src/messages.cpp b/source/blood/src/messages.cpp index 765f3dd0c..34e1a0399 100644 --- a/source/blood/src/messages.cpp +++ b/source/blood/src/messages.cpp @@ -331,7 +331,7 @@ void CPlayerMsg::Send(void) { if (VanillaMode() || !IsWhitespaceOnly(text)) { - netBroadcastMessage(myconnectindex, text); + //netBroadcastMessage(myconnectindex, text); if (!VanillaMode()) { char *myName = gProfile[myconnectindex].name; diff --git a/source/blood/src/network.cpp b/source/blood/src/network.cpp index e57c990a3..81f733d60 100644 --- a/source/blood/src/network.cpp +++ b/source/blood/src/network.cpp @@ -21,9 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- #include "ns.h" // Must come before everything else! -#ifndef NETCODE_DISABLE -#include "enet.h" -#endif #include "build.h" #include "mmulti.h" @@ -77,90 +74,6 @@ const short word_1328AC = 0x214; PKT_STARTGAME gPacketStartGame; -#ifndef NETCODE_DISABLE -ENetAddress gNetENetAddress; -ENetHost *gNetENetServer; -ENetHost *gNetENetClient; -ENetPeer *gNetENetPeer; -ENetPeer *gNetPlayerPeer[kMaxPlayers]; -bool gNetENetInit = false; - -#define kENetFifoSize 2048 - -//ENetPacket *gNetServerPacketFifo[kENetFifoSize]; -//int gNetServerPacketHead, gNetServerPacketTail; -ENetPacket *gNetPacketFifo[kENetFifoSize]; -int gNetPacketHead, gNetPacketTail; - -enum BLOOD_ENET_CHANNEL { - BLOOD_ENET_SERVICE = 0, - BLOOD_ENET_GAME, - BLOOD_ENET_CHANNEL_MAX -}; - -enum BLOOD_SERVICE { - BLOOD_SERVICE_CONNECTINFO = 0, - BLOOD_SERVICE_CONNECTID, - BLOOD_SERVICE_SENDTOID, -}; - -struct PKT_CONNECTINFO { - short numplayers; - short connecthead; - short connectpoint2[kMaxPlayers]; -}; - -void netServerDisconnect(void) -{ - ENetEvent event; - if (gNetMode != NETWORK_SERVER) - return; - for (int p = 0; p < kMaxPlayers; p++) - if (gNetPlayerPeer[p]) - { - bool bDisconnectStatus = false; - enet_peer_disconnect_later(gNetPlayerPeer[p], 0); - if (enet_host_service(gNetENetServer, &event, 3000) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_DISCONNECT: - bDisconnectStatus = true; - break; - default: - break; - } - } - if (!bDisconnectStatus) - enet_peer_reset(gNetPlayerPeer[p]); - gNetPlayerPeer[p] = NULL; - } -} - -void netClientDisconnect(void) -{ - ENetEvent event; - if (gNetMode != NETWORK_CLIENT || gNetENetPeer == NULL) - return; - enet_peer_disconnect_later(gNetENetPeer, 0); - bool bDisconnectStatus = false; - if (enet_host_service(gNetENetClient, &event, 3000) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_DISCONNECT: - bDisconnectStatus = true; - break; - default: - break; - } - } - if (!bDisconnectStatus) - enet_peer_reset(gNetENetPeer); - gNetENetPeer = NULL; -} -#endif - void netResetToSinglePlayer(void) { myconnectindex = connecthead = 0; @@ -173,58 +86,13 @@ void netResetToSinglePlayer(void) void netSendPacket(int nDest, char *pBuffer, int nSize) { -#ifndef NETCODE_DISABLE - if (gNetMode == NETWORK_NONE) - return; - netUpdate(); - - if (gNetMode == NETWORK_SERVER) - { - if (gNetPlayerPeer[nDest] != NULL) - { - ENetPacket *pNetPacket = enet_packet_create(NULL, nSize + 1, ENET_PACKET_FLAG_RELIABLE); - char *pPBuffer = (char*)pNetPacket->data; - PutPacketByte(pPBuffer, myconnectindex); - PutPacketBuffer(pPBuffer, pBuffer, nSize); - enet_peer_send(gNetPlayerPeer[nDest], BLOOD_ENET_GAME, pNetPacket); - enet_host_service(gNetENetServer, NULL, 0); - } - } - else - { - if (nDest == 0) - { - ENetPacket *pNetPacket = enet_packet_create(NULL, nSize + 1, ENET_PACKET_FLAG_RELIABLE); - char *pPBuffer = (char*)pNetPacket->data; - PutPacketByte(pPBuffer, myconnectindex); - PutPacketBuffer(pPBuffer, pBuffer, nSize); - enet_peer_send(gNetENetPeer, BLOOD_ENET_GAME, pNetPacket); - } - else - { - ENetPacket *pNetPacket = enet_packet_create(NULL, nSize + 3, ENET_PACKET_FLAG_RELIABLE); - char *pPBuffer = (char*)pNetPacket->data; - PutPacketByte(pPBuffer, BLOOD_SERVICE_SENDTOID); - PutPacketByte(pPBuffer, nDest); - PutPacketByte(pPBuffer, myconnectindex); - PutPacketBuffer(pPBuffer, pBuffer, nSize); - enet_peer_send(gNetENetPeer, BLOOD_ENET_SERVICE, pNetPacket); - } - enet_host_service(gNetENetClient, NULL, 0); - } - - netUpdate(); -#endif } void netSendPacketAll(char *pBuffer, int nSize) { - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - if (p != myconnectindex) - netSendPacket(p, pBuffer, nSize); } -void sub_79760(void) +void netReset(void) { gNetFifoClock = gFrameClock = totalclock = 0; gNetFifoMasterTail = 0; @@ -244,311 +112,27 @@ void sub_79760(void) void CalcGameChecksum(void) { - memset(gChecksum, 0, sizeof(gChecksum)); - gChecksum[0] = wrand(); - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - int *pBuffer = &gPlayer[p].used1; - int sum = 0; - int length = ((char*)&gPlayer[p+1]-(char*)pBuffer)/4; - while (length--) - { - sum += *pBuffer++; - } - gChecksum[1] ^= sum; - pBuffer = (int*)gPlayer[p].pSprite; - sum = 0; - length = sizeof(spritetype)/4; - while (length--) - { - sum += *pBuffer++; - } - gChecksum[2] ^= sum; - pBuffer = (int*)gPlayer[p].pXSprite; - sum = 0; - length = sizeof(XSPRITE)/4; - while (length--) - { - sum += *pBuffer++; - } - gChecksum[3] ^= sum; - } } void netCheckSync(void) { - char buffer[80]; - if (gGameOptions.nGameType == 0) - return; - if (numplayers == 1) - return; - if (bOutOfSync) - return; - while (1) - { - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (gCheckTail >= gCheckHead[p]) - return; - } - - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (p != myconnectindex) - { - int status = memcmp(gCheckFifo[gCheckTail&255][p], gCheckFifo[gCheckTail&255][connecthead], 16); - if (status) - { - sprintf(buffer, "OUT OF SYNC (%d)", p); - char *pBuffer = buffer + strlen(buffer); - for (unsigned int i = 0; i < 4; i++) - { - if (gCheckFifo[gCheckTail&255][p][i] != gCheckFifo[gCheckTail&255][connecthead][i]) - pBuffer += sprintf(pBuffer, " %d", i); - } - viewSetErrorMessage(buffer); - bOutOfSync = 1; - } - } - } - gCheckTail++; - } } short netGetPacket(short *pSource, char *pMessage) { -#ifndef NETCODE_DISABLE - if (gNetMode == NETWORK_NONE) - return 0; - netUpdate(); - if (gNetPacketTail != gNetPacketHead) - { - ENetPacket *pEPacket = gNetPacketFifo[gNetPacketTail]; - gNetPacketTail = (gNetPacketTail+1)%kENetFifoSize; - char *pPacket = (char*)pEPacket->data; - *pSource = GetPacketByte(pPacket); - int nSize = pEPacket->dataLength-1; - memcpy(pMessage, pPacket, nSize); - enet_packet_destroy(pEPacket); - netUpdate(); - return nSize; - } - netUpdate(); -#endif return 0; } void netGetPackets(void) { - short nPlayer; - short nSize; - char buffer[128]; - while ((nSize = netGetPacket(&nPlayer, packet)) > 0) - { - char *pPacket = packet; - switch (GetPacketByte(pPacket)) - { - case 0: // From master - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (p != myconnectindex) - { - GINPUT *pInput = &gFifoInput[gNetFifoHead[p]&255][p]; - memset(pInput, 0, sizeof(GINPUT)); - pInput->syncFlags.byte = GetPacketByte(pPacket); - pInput->forward = GetPacketWord(pPacket); - pInput->q16turn = GetPacketDWord(pPacket); - pInput->strafe = GetPacketWord(pPacket); - if (pInput->syncFlags.buttonChange) - pInput->buttonFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.keyChange) - pInput->keyFlags.word = GetPacketWord(pPacket); - if (pInput->syncFlags.useChange) - pInput->useFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.weaponChange) - pInput->newWeapon = GetPacketByte(pPacket); - if (pInput->syncFlags.mlookChange) - pInput->q16mlook = GetPacketDWord(pPacket); - gNetFifoHead[p]++; - } - else - { - SYNCFLAGS syncFlags; - syncFlags.byte = GetPacketByte(pPacket); - pPacket += 2+4+2; - if (syncFlags.buttonChange) - pPacket++; - if (syncFlags.keyChange) - pPacket+=2; - if (syncFlags.useChange) - pPacket++; - if (syncFlags.weaponChange) - pPacket++; - if (syncFlags.mlookChange) - pPacket+=4; - } - } - if (((gNetFifoHead[connecthead]-1)&15)==0) - { - for (int p = connectpoint2[connecthead]; p >= 0; p = connectpoint2[p]) - { - int nLag = (signed char)GetPacketByte(pPacket); - if (p == myconnectindex) - otherMinLag = nLag; - } - } - while (pPacket < packet+nSize) - { - int checkSum[4]; - GetPacketBuffer(pPacket, checkSum, sizeof(checkSum)); - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (p != myconnectindex) - { - memcpy(gCheckFifo[gCheckHead[p]&255][p], checkSum, sizeof(checkSum)); - gCheckHead[p]++; - } - } - } - break; - case 1: // From slave - { - GINPUT *pInput = &gFifoInput[gNetFifoHead[nPlayer]&255][nPlayer]; - memset(pInput, 0, sizeof(GINPUT)); - pInput->syncFlags.byte = GetPacketByte(pPacket); - pInput->forward = GetPacketWord(pPacket); - pInput->q16turn = GetPacketDWord(pPacket); - pInput->strafe = GetPacketWord(pPacket); - if (pInput->syncFlags.buttonChange) - pInput->buttonFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.keyChange) - pInput->keyFlags.word = GetPacketWord(pPacket); - if (pInput->syncFlags.useChange) - pInput->useFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.weaponChange) - pInput->newWeapon = GetPacketByte(pPacket); - if (pInput->syncFlags.mlookChange) - pInput->q16mlook = GetPacketDWord(pPacket); - gNetFifoHead[nPlayer]++; - while (pPacket < packet+nSize) - { - int checkSum[4]; - GetPacketBuffer(pPacket, checkSum, sizeof(checkSum)); - memcpy(gCheckFifo[gCheckHead[nPlayer]&255][nPlayer], checkSum, sizeof(checkSum)); - gCheckHead[nPlayer]++; - } - break; - } - case 2: - { - if (nPlayer == connecthead && (gNetFifoHead[nPlayer]&15) == 0) - { - for (int p = connectpoint2[connecthead]; p >= 0; p = connectpoint2[p]) - { - int nLag = (signed char)GetPacketByte(pPacket); - if (p == myconnectindex) - otherMinLag = nLag; - } - } - GINPUT *pInput = &gFifoInput[gNetFifoHead[nPlayer]&255][nPlayer]; - memset(pInput, 0, sizeof(GINPUT)); - pInput->syncFlags.byte = GetPacketByte(pPacket); - pInput->forward = GetPacketWord(pPacket); - pInput->q16turn = GetPacketDWord(pPacket); - pInput->strafe = GetPacketWord(pPacket); - if (pInput->syncFlags.buttonChange) - pInput->buttonFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.keyChange) - pInput->keyFlags.word = GetPacketWord(pPacket); - if (pInput->syncFlags.useChange) - pInput->useFlags.byte = GetPacketByte(pPacket); - if (pInput->syncFlags.weaponChange) - pInput->newWeapon = GetPacketByte(pPacket); - if (pInput->syncFlags.mlookChange) - pInput->q16mlook = GetPacketDWord(pPacket); - gNetFifoHead[nPlayer]++; - while (pPacket < packet+nSize) - { - int checkSum[4]; - GetPacketBuffer(pPacket, checkSum, sizeof(checkSum)); - memcpy(gCheckFifo[gCheckHead[nPlayer]&255][nPlayer], checkSum, sizeof(checkSum)); - gCheckHead[nPlayer]++; - } - break; - } - case 3: - pPacket += 4; - if (*pPacket != '/' || (*pPacket == 0 && *(pPacket+1) == 0) || (*(pPacket+1) >= '1' && *(pPacket+1) <= '8' && *(pPacket+1)-'1' == myconnectindex)) - { - sprintf(buffer, VanillaMode() ? "%s : %s" : "%s: %s", gProfile[nPlayer].name, pPacket); - viewSetMessage(buffer, VanillaMode() ? 0 : 10); // 10: dark blue - sndStartSample("DMRADIO", 128, -1); - } - break; - case 4: - sndStartSample(4400+GetPacketByte(pPacket), 128, 1, 0); - break; - case 7: - nPlayer = GetPacketDWord(pPacket); - dassert(nPlayer != myconnectindex); - netWaitForEveryone(0); - netPlayerQuit(nPlayer); - netWaitForEveryone(0); - break; - case 249: - nPlayer = GetPacketDWord(pPacket); - dassert(nPlayer != myconnectindex); - netPlayerQuit(nPlayer); - netWaitForEveryone(0); - break; - case 250: - gPlayerReady[nPlayer]++; - break; - case 251: - memcpy(&gProfile[nPlayer], pPacket, sizeof(PROFILE)); - break; - case 252: - pPacket += 4; - memcpy(&gPacketStartGame, pPacket, sizeof(PKT_STARTGAME)); - if (gPacketStartGame.version != word_1328AC) - ThrowError("\nThese versions of Blood cannot play together.\n"); - gStartNewGame = 1; - break; - case 255: - // What are we trying to do here? Opening the menu, maybe? - //inputState.SetKeyStatus(sc_Escape); - M_StartControlPanel(false); - M_SetMenu(NAME_Mainmenu); - break; - } - } } void netBroadcastPlayerLogoff(int nPlayer) { - if (numplayers < 2) - return; - netWaitForEveryone(0); - netPlayerQuit(nPlayer); - if (nPlayer != myconnectindex) - netWaitForEveryone(0); } void netBroadcastMyLogoff(bool bRestart) { - if (numplayers < 2) - return; - char *pPacket = packet; - PutPacketByte(pPacket, 7); - PutPacketDWord(pPacket, myconnectindex); - netSendPacketAll(packet, pPacket - packet); - netWaitForEveryone(0); - ready2send = 0; - gQuitGame = true; - if (bRestart) - gRestartGame = true; - netDeinitialize(); - netResetToSinglePlayer(); } void netBroadcastPlayerInfo(int nPlayer) @@ -560,103 +144,14 @@ void netBroadcastPlayerInfo(int nPlayer) pProfile->nWeaponSwitch = cl_weaponswitch; if (numplayers < 2) return; - char *pPacket = packet; - PutPacketByte(pPacket, 251); - PutPacketBuffer(pPacket, pProfile, sizeof(PROFILE)); - netSendPacketAll(packet, pPacket-packet); } void netBroadcastNewGame(void) { - if (numplayers < 2) - return; - gPacketStartGame.version = word_1328AC; - char *pPacket = packet; - PutPacketByte(pPacket, 252); - PutPacketDWord(pPacket, myconnectindex); - PutPacketBuffer(pPacket, &gPacketStartGame, sizeof(PKT_STARTGAME)); - netSendPacketAll(packet, pPacket-packet); -} - -void netBroadcastTaunt(int nPlayer, int nTaunt) -{ - UNREFERENCED_PARAMETER(nPlayer); - if (numplayers > 1) - { - char *pPacket = packet; - PutPacketByte(pPacket, 4); - PutPacketByte(pPacket, nTaunt); - netSendPacketAll(packet, pPacket-packet); - } - sndStartSample(4400+nTaunt, 128, 1, 0); -} - -void netBroadcastMessage(int nPlayer, const char *pzMessage) -{ - if (numplayers > 1) - { - int nSize = strlen(pzMessage); - char *pPacket = packet; - PutPacketByte(pPacket, 3); - PutPacketDWord(pPacket, nPlayer); - PutPacketBuffer(pPacket, pzMessage, nSize+1); - netSendPacketAll(packet, pPacket-packet); - } } void netWaitForEveryone(char a1) { - if (numplayers < 2) - return; - char *pPacket = packet; - PutPacketByte(pPacket, 250); - netSendPacketAll(packet, pPacket-packet); - gPlayerReady[myconnectindex]++; - int p; - do - { - if (inputState.EscapePressed() && a1) - Bexit(0); - gameHandleEvents(); - //faketimerhandler(); - for (p = connecthead; p >= 0; p = connectpoint2[p]) - if (gPlayerReady[p] < gPlayerReady[myconnectindex]) - break; - if (gRestartGame || gNetPlayers <= 1) - break; - } while (p >= 0); -} - -void sub_7AC28(const char *pzString) -{ - if (numplayers < 2) - return; - if (pzString) - { - int nLength = strlen(pzString); - if (nLength > 0) - { - char *pPacket = packet; - PutPacketByte(pPacket, 5); - PutPacketBuffer(pPacket, pzString, nLength+1); - netSendPacketAll(packet, pPacket-packet); - } - } -} - -void netSendEmptyPackets(void) -{ - ClockTicks nClock = totalclock; - char *pPacket = packet; - PutPacketByte(pPacket, 254); - for (int i = 0; i < 8; i++) - { - if (nClock <= totalclock) - { - nClock = totalclock+4; - netSendPacketAll(packet, pPacket-packet); - } - } } void netMasterUpdate(void) @@ -768,71 +263,6 @@ void netGetInput(void) else if (t < 0) gBufferJitter -= (1-t)>>2; } - if (gPacketMode == PACKETMODE_2) - { - char *pPacket = packet; - PutPacketByte(pPacket, 2); - if (((gNetFifoHead[myconnectindex]-1)&15) == 0) - { - if (myconnectindex == connecthead) - { - for (int p = connectpoint2[connecthead]; p >= 0; p = connectpoint2[p]) - PutPacketByte(pPacket, ClipRange(myMinLag[p], -128, 127)); - } - else - { - int t = myMinLag[connecthead]-otherMinLag; - if (klabs(t) > 2) - { - if (klabs(t) > 8) - { - if (t < 0) - t++; - t >>= 1; - } - else - t = ksgn(t); - totalclock -= t<<2; - otherMinLag += t; - myMinLag[connecthead] -= t; - } - } - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - myMinLag[p] = 0x7fffffff; - } - if (input.buttonFlags.byte) - input.syncFlags.buttonChange = 1; - if (input.keyFlags.word) - input.syncFlags.keyChange = 1; - if (input.useFlags.byte) - input.syncFlags.useChange = 1; - if (input.newWeapon) - input.syncFlags.weaponChange = 1; - if (input.q16mlook) - input.syncFlags.mlookChange = 1; - PutPacketByte(pPacket, input.syncFlags.byte); - PutPacketWord(pPacket, input.forward); - PutPacketDWord(pPacket, input.q16turn); - PutPacketWord(pPacket, input.strafe); - if (gInput.syncFlags.buttonChange) - PutPacketByte(pPacket, input.buttonFlags.byte); - if (gInput.syncFlags.keyChange) - PutPacketWord(pPacket, input.keyFlags.word); - if (gInput.syncFlags.useChange) - PutPacketByte(pPacket, input.useFlags.byte); - if (gInput.syncFlags.weaponChange) - PutPacketByte(pPacket, input.newWeapon); - if (gInput.syncFlags.mlookChange) - PutPacketDWord(pPacket, input.q16mlook); - while (gSendCheckTail != gCheckHead[myconnectindex]) - { - unsigned int *checkSum = gCheckFifo[gSendCheckTail&255][myconnectindex]; - PutPacketBuffer(pPacket, checkSum, 16); - gSendCheckTail++; - } - netSendPacketAll(packet, pPacket-packet); - return; - } if (myconnectindex != connecthead) { char *pPacket = packet; @@ -894,446 +324,17 @@ void netGetInput(void) void netInitialize(bool bConsole) { - netDeinitialize(); memset(gPlayerReady, 0, sizeof(gPlayerReady)); - sub_79760(); -#ifndef NETCODE_DISABLE - char buffer[128]; - gNetENetServer = gNetENetClient = NULL; - //gNetServerPacketHead = gNetServerPacketTail = 0; - gNetPacketHead = gNetPacketTail = 0; - if (gNetMode == NETWORK_NONE) - { - netResetToSinglePlayer(); - return; - } - if (!gHaveNetworking) - { - Printf("An error occurred while initializing ENet.\n"); - netResetToSinglePlayer(); - return; - } - if (gNetMode == NETWORK_SERVER) - { - memset(gNetPlayerPeer, 0, sizeof(gNetPlayerPeer)); - ENetEvent event; - gNetENetAddress.host = ENET_HOST_ANY; - gNetENetAddress.port = gNetPort; - gNetENetServer = enet_host_create(&gNetENetAddress, 8, BLOOD_ENET_CHANNEL_MAX, 0, 0); - if (!gNetENetServer) - { - Printf("An error occurred while trying to create an ENet server host.\n"); - netDeinitialize(); - netResetToSinglePlayer(); - return; - } - - numplayers = 1; - // Wait for clients - while (numplayers < gNetPlayers) - { - handleevents(); -#if 0 - if (quitevent) - { - netServerDisconnect(); - QuitGame(); - } -#endif - if (!bConsole && inputState.GetKeyStatus(sc_Escape)) - { - netServerDisconnect(); - netDeinitialize(); - netResetToSinglePlayer(); - return; - } - enet_host_service(gNetENetServer, NULL, 0); - if (enet_host_check_events(gNetENetServer, &event) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_CONNECT: - { - char ipaddr[32]; - - enet_address_get_host_ip(&event.peer->address, ipaddr, sizeof(ipaddr)); - Printf("Client connected: %s:%u\n", ipaddr, event.peer->address.port); - numplayers++; - for (int i = 1; i < kMaxPlayers; i++) - { - if (gNetPlayerPeer[i] == NULL) - { - gNetPlayerPeer[i] = event.peer; - break; - } - } - break; - } - case ENET_EVENT_TYPE_DISCONNECT: - { - char ipaddr[32]; - - enet_address_get_host_ip(&event.peer->address, ipaddr, sizeof(ipaddr)); - Printf("Client disconnected: %s:%u\n", ipaddr, event.peer->address.port); - numplayers--; - for (int i = 1; i < kMaxPlayers; i++) - { - if (gNetPlayerPeer[i] == event.peer) - { - gNetPlayerPeer[i] = NULL; - for (int j = kMaxPlayers-1; j > i; j--) - { - if (gNetPlayerPeer[j]) - { - gNetPlayerPeer[i] = gNetPlayerPeer[j]; - gNetPlayerPeer[j] = NULL; - break; - } - } - } - } - break; - } - default: - break; - } - } - enet_host_service(gNetENetServer, NULL, 0); - } - Printf("All clients connected\n"); - - dassert(numplayers >= 1); - - gInitialNetPlayers = gNetPlayers = numplayers; - connecthead = 0; - for (int i = 0; i < numplayers-1; i++) - connectpoint2[i] = i+1; - connectpoint2[numplayers-1] = -1; - - enet_host_service(gNetENetServer, NULL, 0); - - // Send connect info - char *pPacket = packet; - PutPacketByte(pPacket, BLOOD_SERVICE_CONNECTINFO); - PKT_CONNECTINFO connectinfo; - connectinfo.numplayers = numplayers; - connectinfo.connecthead = connecthead; - for (int i = 0; i < numplayers; i++) - connectinfo.connectpoint2[i] = connectpoint2[i]; - PutPacketBuffer(pPacket, &connectinfo, sizeof(connectinfo)); - ENetPacket *pEPacket = enet_packet_create(packet, pPacket-packet, ENET_PACKET_FLAG_RELIABLE); - enet_host_broadcast(gNetENetServer, BLOOD_ENET_SERVICE, pEPacket); - //enet_packet_destroy(pEPacket); - - enet_host_service(gNetENetServer, NULL, 0); - - // Send id - myconnectindex = 0; - for (int i = 1; i < numplayers; i++) - { - if (!gNetPlayerPeer[i]) - continue; - char *pPacket = packet; - PutPacketByte(pPacket, BLOOD_SERVICE_CONNECTID); - PutPacketByte(pPacket, i); - ENetPacket *pEPacket = enet_packet_create(packet, pPacket-packet, ENET_PACKET_FLAG_RELIABLE); - enet_peer_send(gNetPlayerPeer[i], BLOOD_ENET_SERVICE, pEPacket); - - enet_host_service(gNetENetServer, NULL, 0); - } - - enet_host_service(gNetENetServer, NULL, 0); - } - else if (gNetMode == NETWORK_CLIENT) - { - ENetEvent event; - sprintf(buffer, "Connecting to %s:%u", gNetAddress, gNetPort); - Printf("%s\n", buffer); - gNetENetClient = enet_host_create(NULL, 1, BLOOD_ENET_CHANNEL_MAX, 0, 0); - enet_address_set_host(&gNetENetAddress, gNetAddress); - gNetENetAddress.port = gNetPort; - gNetENetPeer = enet_host_connect(gNetENetClient, &gNetENetAddress, BLOOD_ENET_CHANNEL_MAX, 0); - if (!gNetENetPeer) - { - Printf("No available peers for initiating an ENet connection.\n"); - netDeinitialize(); - netResetToSinglePlayer(); - return; - } - if (enet_host_service(gNetENetClient, &event, 5000) > 0 && event.type == ENET_EVENT_TYPE_CONNECT) - Printf("Connected to %s:%i\n", gNetAddress, gNetPort); - else - { - Printf("Could not connect to %s:%i\n", gNetAddress, gNetPort); - netDeinitialize(); - return; - } - bool bWaitServer = true; - while (bWaitServer) - { - handleevents(); -#if 0 - if (quitevent) - { - netClientDisconnect(); - QuitGame(); - } -#endif - if (!bConsole && inputState.GetKeyStatus(sc_Escape)) - { - netClientDisconnect(); - netDeinitialize(); - netResetToSinglePlayer(); - return; - } - enet_host_service(gNetENetClient, NULL, 0); - if (enet_host_check_events(gNetENetClient, &event) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_DISCONNECT: - Printf("Lost connection to server\n"); - netDeinitialize(); - netResetToSinglePlayer(); - return; - case ENET_EVENT_TYPE_RECEIVE: - //Printf("NETEVENT\n"); - if (event.channelID == BLOOD_ENET_SERVICE) - { - char *pPacket = (char*)event.packet->data; - switch (GetPacketByte(pPacket)) - { - case BLOOD_SERVICE_CONNECTINFO: - { - PKT_CONNECTINFO *connectinfo = (PKT_CONNECTINFO*)pPacket; - gInitialNetPlayers = gNetPlayers = numplayers = connectinfo->numplayers; - connecthead = connectinfo->connecthead; - for (int i = 0; i < numplayers; i++) - connectpoint2[i] = connectinfo->connectpoint2[i]; - //Printf("BLOOD_SERVICE_CONNECTINFO\n"); - break; - } - case BLOOD_SERVICE_CONNECTID: - dassert(numplayers > 1); - myconnectindex = GetPacketByte(pPacket); - bWaitServer = false; - //Printf("BLOOD_SERVICE_CONNECTID\n"); - break; - } - } - enet_packet_destroy(event.packet); - break; - default: - break; - } - } - } - enet_host_service(gNetENetClient, NULL, 0); - Printf("Successfully connected to server\n"); - } - gNetENetInit = true; - gGameOptions.nGameType = 2; -#endif + netReset(); + netResetToSinglePlayer(); } void netDeinitialize(void) { -#ifndef NETCODE_DISABLE - if (!gNetENetInit) - return; - gNetENetInit = false; - if (gNetMode != NETWORK_NONE) - { - if (gNetENetServer) - { - netServerDisconnect(); - enet_host_destroy(gNetENetServer); - } - else if (gNetENetClient) - { - netClientDisconnect(); - enet_host_destroy(gNetENetClient); - } - enet_deinitialize(); - } - gNetENetServer = gNetENetClient = NULL; -#endif -} - -#ifndef NETCODE_DISABLE -void netPostEPacket(ENetPacket *pEPacket) -{ - //static int number; - //Printf("netPostEPacket %i\n", number++); - gNetPacketFifo[gNetPacketHead] = pEPacket; - gNetPacketHead = (gNetPacketHead+1)%kENetFifoSize; -} -#endif - -void netUpdate(void) -{ -#ifndef NETCODE_DISABLE - ENetEvent event; - if (gNetMode == NETWORK_NONE) - return; - - if (gNetENetServer) - { - enet_host_service(gNetENetServer, NULL, 0); - while (enet_host_check_events(gNetENetServer, &event) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_DISCONNECT: - { - int nPlayer; - for (nPlayer = connectpoint2[connecthead]; nPlayer >= 0; nPlayer = connectpoint2[nPlayer]) - if (gNetPlayerPeer[nPlayer] == event.peer) - break; - - for (int p = 0; p < kMaxPlayers; p++) - if (gNetPlayerPeer[p] == event.peer) - gNetPlayerPeer[p] = NULL; - if (nPlayer >= 0) - { - // TODO: Game most likely will go out of sync here... - char *pPacket = packet; - PutPacketByte(pPacket, 249); - PutPacketDWord(pPacket, nPlayer); - netSendPacketAll(packet, pPacket - packet); - netPlayerQuit(nPlayer); - netWaitForEveryone(0); - } - if (gNetPlayers <= 1) - { - netDeinitialize(); - netResetToSinglePlayer(); - return; - } - break; - } - case ENET_EVENT_TYPE_RECEIVE: - switch (event.channelID) - { - case BLOOD_ENET_SERVICE: - { - char *pPacket = (char*)event.packet->data; - if (GetPacketByte(pPacket) != BLOOD_SERVICE_SENDTOID) - ThrowError("Packet error\n"); - int nDest = GetPacketByte(pPacket); - int nSource = GetPacketByte(pPacket); - int nSize = event.packet->dataLength-3; - if (gNetPlayerPeer[nDest] != NULL) - { - ENetPacket *pNetPacket = enet_packet_create(NULL, nSize + 1, ENET_PACKET_FLAG_RELIABLE); - char *pPBuffer = (char*)pNetPacket->data; - PutPacketByte(pPBuffer, nSource); - PutPacketBuffer(pPBuffer, pPacket, nSize); - enet_peer_send(gNetPlayerPeer[nDest], BLOOD_ENET_GAME, pNetPacket); - enet_host_service(gNetENetServer, NULL, 0); - } - enet_packet_destroy(event.packet); - break; - } - case BLOOD_ENET_GAME: - netPostEPacket(event.packet); - break; - } - default: - break; - } - enet_host_service(gNetENetServer, NULL, 0); - } - enet_host_service(gNetENetServer, NULL, 0); - } - else if (gNetENetClient) - { - enet_host_service(gNetENetClient, NULL, 0); - while (enet_host_check_events(gNetENetClient, &event) > 0) - { - switch (event.type) - { - case ENET_EVENT_TYPE_DISCONNECT: - Printf("Lost connection to server\n"); - netDeinitialize(); - netResetToSinglePlayer(); - gQuitGame = gRestartGame = true; - return; - case ENET_EVENT_TYPE_RECEIVE: - switch (event.channelID) - { - case BLOOD_ENET_SERVICE: - { - ThrowError("Packet error\n"); - break; - } - case BLOOD_ENET_GAME: - netPostEPacket(event.packet); - break; - } - default: - break; - } - enet_host_service(gNetENetClient, NULL, 0); - } - enet_host_service(gNetENetClient, NULL, 0); - } -#endif -} - -void faketimerhandler(void) -{ -#ifndef NETCODE_DISABLE - if (gNetMode != NETWORK_NONE && gNetENetInit) - netUpdate(); -#endif - //if (gNetMode != NETWORK_NONE && gNetENetInit) - // enet_host_service(gNetMode == NETWORK_SERVER ? gNetENetServer : gNetENetClient, NULL, 0); } void netPlayerQuit(int nPlayer) { - char buffer[128]; - sprintf(buffer, "%s left the game with %d frags.", gProfile[nPlayer].name, gPlayer[nPlayer].fragCount); - viewSetMessage(buffer); - if (gamestate == GS_LEVEL) - { - seqKill(3, gPlayer[nPlayer].pSprite->extra); - actPostSprite(gPlayer[nPlayer].nSprite, kStatFree); - if (nPlayer == gViewIndex) - gViewIndex = myconnectindex; - gView = &gPlayer[gViewIndex]; - } - if (nPlayer == connecthead) - { - connecthead = connectpoint2[connecthead]; - //if (gPacketMode == PACKETMODE_1) - { - //byte_27B2CC = 1; - gQuitGame = true; - gRestartGame = true; - gNetPlayers = 1; - //gQuitRequest = 1; - } - } - else - { - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (connectpoint2[p] == nPlayer) - connectpoint2[p] = connectpoint2[nPlayer]; - } -#ifndef NETCODE_DISABLE - gNetPlayerPeer[nPlayer] = NULL; -#endif - } - gNetPlayers--; - numplayers = ClipLow(numplayers-1, 1); - if (gNetPlayers <= 1) - { - netDeinitialize(); - netResetToSinglePlayer(); - } } END_BLD_NS diff --git a/source/blood/src/network.h b/source/blood/src/network.h index b86284e65..57304c5f7 100644 --- a/source/blood/src/network.h +++ b/source/blood/src/network.h @@ -138,13 +138,10 @@ inline void GetPacketBuffer(char *&p, void *pBuffer, int size) p += size; } -void sub_79760(void); +void netReset(void); void netResetToSinglePlayer(void); -void netBroadcastMessage(int nPlayer, const char *pzMessage); void netWaitForEveryone(char a1); -void sub_7AC28(const char *pzString); void netGetPackets(void); -void netBroadcastTaunt(int nPlayer, int nTaunt); void CalcGameChecksum(void); void netBroadcastPlayerLogoff(int nPlayer); void netBroadcastMyLogoff(bool bRestart); @@ -154,7 +151,6 @@ void netCheckSync(void); void netMasterUpdate(void); void netGetInput(void); void netPlayerQuit(int nPlayer); -void netUpdate(void); void netDeinitialize(void); void netBroadcastNewGame(void); diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 3eba3e4f2..f39e65df4 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -957,13 +957,6 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { sprintf(buffer, "%s captured Red Flag!", gProfile[pPlayer->nPlayer].name); sndStartSample(8001, 255, 2, 0); viewSetMessage(buffer); -#if 0 - if (dword_28E3D4 == 3 && myconnectindex == connecthead) - { - sprintf(buffer, "frag A killed B\n"); - sub_7AC28(buffer); - } -#endif } } @@ -1001,13 +994,6 @@ char PickupItem(PLAYER *pPlayer, spritetype *pItem) { sprintf(buffer, "%s captured Blue Flag!", gProfile[pPlayer->nPlayer].name); sndStartSample(8000, 255, 2, 0); viewSetMessage(buffer); -#if 0 - if (dword_28E3D4 == 3 && myconnectindex == connecthead) - { - sprintf(buffer, "frag B killed A\n"); - sub_7AC28(buffer); - } -#endif } } } @@ -1842,12 +1828,6 @@ void playerFrag(PLAYER *pKiller, PLAYER *pVictim) dassert(nKiller >= 0 && nKiller < kMaxPlayers); int nVictim = pVictim->pSprite->type-kDudePlayer1; dassert(nVictim >= 0 && nVictim < kMaxPlayers); - if (myconnectindex == connecthead) - { - sprintf(buffer, "frag %d killed %d\n", pKiller->nPlayer+1, pVictim->nPlayer+1); - sub_7AC28(buffer); - buffer[0] = 0; - } if (nKiller == nVictim) { pVictim->fraggerId = -1; diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 2a2c8eb61..a30016b04 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -113,8 +113,6 @@ int ShowStartupWindow(TArray &); FString GetGameFronUserFiles(); void InitFileSystem(TArray&); void I_SetWindowTitle(const char* caption); -void InitENet(); -void ShutdownENet(); void S_ParseSndInfo(); void I_DetectOS(void); void LoadScripts(); @@ -548,7 +546,6 @@ int GameMain() delete gi; gi = nullptr; } - InitENet(); DeleteStartupScreen(); PClass::StaticShutdown(); if (Args) delete Args; @@ -763,7 +760,6 @@ int RunGame() I_DetectOS(); userConfig.ProcessOptions(); G_LoadConfig(); - ShutdownENet(); auto usedgroups = SetupGame(); diff --git a/source/thirdparty/include/enet.h b/source/thirdparty/include/enet.h deleted file mode 100644 index 3a6bc3e93..000000000 --- a/source/thirdparty/include/enet.h +++ /dev/null @@ -1,5907 +0,0 @@ -/** - * include/enet.h - a Single-Header auto-generated variant of enet.h library. - * - * Usage: - * #define ENET_IMPLEMENTATION exactly in ONE source file right BEFORE including the library, like: - * - * #define ENET_IMPLEMENTATION - * #include - * - * License: - * The MIT License (MIT) - * - * Copyright (c) 2002-2016 Lee Salzman - * Copyright (c) 2017-2018 Vladyslav Hrytsenko, Dominik Madarász - * - * Permission is hereby granted, e_free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#ifndef ENET_INCLUDE_H -#define ENET_INCLUDE_H - -#include -#include -#include -#include - -#define ENET_VERSION_MAJOR 2 -#define ENET_VERSION_MINOR 2 -#define ENET_VERSION_PATCH 0 -#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) -#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) -#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) - -#define ENET_TIME_OVERFLOW 86400000 -#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) -#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) -#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) -#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) -#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) - -// =======================================================================// -// ! -// ! System differences -// ! -// =======================================================================// - -#if defined(_WIN32) - #if defined(_MSC_VER) && defined(ENET_IMPLEMENTATION) - #pragma warning (disable: 4267) // size_t to int conversion - #pragma warning (disable: 4244) // 64bit to 32bit int - #pragma warning (disable: 4018) // signed/unsigned mismatch - #pragma warning (disable: 4146) // unary minus operator applied to unsigned type - #endif - - #ifndef ENET_NO_PRAGMA_LINK - #pragma comment(lib, "ws2_32.lib") - #pragma comment(lib, "winmm.lib") - #endif - - #if _MSC_VER >= 1910 - /* It looks like there were changes as of Visual Studio 2017 and there are no 32/64 bit - versions of _InterlockedExchange[operation], only InterlockedExchange[operation] - (without leading underscore), so we have to distinguish between compiler versions */ - #define NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - #endif - - #ifdef __GNUC__ - #if (_WIN32_WINNT < 0x0501) - #undef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 - #endif - #endif - - #include - #include - #include - - #include - - #if defined(_WIN32) && defined(_MSC_VER) - #if _MSC_VER < 1900 - typedef struct timespec { - long tv_sec; - long tv_nsec; - }; - #endif - #define CLOCK_MONOTONIC 0 - #endif - - typedef SOCKET ENetSocket; - #define ENET_SOCKET_NULL INVALID_SOCKET - - #define ENET_HOST_TO_NET_16(value) (htons(value)) - #define ENET_HOST_TO_NET_32(value) (htonl(value)) - - #define ENET_NET_TO_HOST_16(value) (ntohs(value)) - #define ENET_NET_TO_HOST_32(value) (ntohl(value)) - - typedef struct { - size_t dataLength; - void * data; - } ENetBuffer; - - #define ENET_CALLBACK __cdecl - - #ifdef ENET_DLL - #ifdef ENET_IMPLEMENTATION - #define ENET_API __declspec( dllexport ) - #else - #define ENET_API __declspec( dllimport ) - #endif // ENET_IMPLEMENTATION - #else - #define ENET_API extern - #endif // ENET_DLL - - typedef fd_set ENetSocketSet; - - #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO(&(sockset)) - #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET(socket, &(sockset)) - #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset)) - #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET(socket, &(sockset)) -#else - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - - #ifdef __APPLE__ - #include - #include - #include - #endif - - #ifndef MSG_NOSIGNAL - #define MSG_NOSIGNAL 0 - #endif - - #ifdef MSG_MAXIOVLEN - #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN - #endif - - typedef int ENetSocket; - - #define ENET_SOCKET_NULL -1 - - #define ENET_HOST_TO_NET_16(value) (htons(value)) /**< macro that converts host to net byte-order of a 16-bit value */ - #define ENET_HOST_TO_NET_32(value) (htonl(value)) /**< macro that converts host to net byte-order of a 32-bit value */ - - #define ENET_NET_TO_HOST_16(value) (ntohs(value)) /**< macro that converts net to host byte-order of a 16-bit value */ - #define ENET_NET_TO_HOST_32(value) (ntohl(value)) /**< macro that converts net to host byte-order of a 32-bit value */ - - typedef struct { - void * data; - size_t dataLength; - } ENetBuffer; - - #define ENET_CALLBACK - #define ENET_API extern - - typedef fd_set ENetSocketSet; - - #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO(&(sockset)) - #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET(socket, &(sockset)) - #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset)) - #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET(socket, &(sockset)) -#endif - -#ifndef ENET_BUFFER_MAXIMUM -#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS) -#endif - -#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) -#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) - -#define ENET_IPV6 1 -#define ENET_HOST_ANY in6addr_any -#define ENET_HOST_BROADCAST 0xFFFFFFFFU -#define ENET_PORT_ANY 0 - -#ifdef __cplusplus -extern "C" { -#endif - -// =======================================================================// -// ! -// ! Basic stuff -// ! -// =======================================================================// - - typedef uint8_t enet_uint8; /**< unsigned 8-bit type */ - typedef uint16_t enet_uint16; /**< unsigned 16-bit type */ - typedef uint32_t enet_uint32; /**< unsigned 32-bit type */ - typedef uint64_t enet_uint64; /**< unsigned 64-bit type */ - - typedef enet_uint32 ENetVersion; - - - typedef struct _ENetCallbacks { - void *(ENET_CALLBACK *e_malloc) (size_t size); - void (ENET_CALLBACK *e_free) (void *memory); - void (ENET_CALLBACK *no_memory) (void); - } ENetCallbacks; - - extern void *enet_malloc(size_t); - extern void enet_free(void *); - -// =======================================================================// -// ! -// ! List -// ! -// =======================================================================// - - typedef struct _ENetListNode { - struct _ENetListNode *next; - struct _ENetListNode *previous; - } ENetListNode; - - typedef ENetListNode *ENetListIterator; - - typedef struct _ENetList { - ENetListNode sentinel; - } ENetList; - - extern ENetListIterator enet_list_insert(ENetListIterator, void *); - extern ENetListIterator enet_list_move(ENetListIterator, void *, void *); - - extern void *enet_list_remove(ENetListIterator); - extern void enet_list_clear(ENetList *); - extern size_t enet_list_size(ENetList *); - - #define enet_list_begin(list) ((list)->sentinel.next) - #define enet_list_end(list) (&(list)->sentinel) - #define enet_list_empty(list) (enet_list_begin(list) == enet_list_end(list)) - #define enet_list_next(iterator) ((iterator)->next) - #define enet_list_previous(iterator) ((iterator)->previous) - #define enet_list_front(list) ((void *)(list)->sentinel.next) - #define enet_list_back(list) ((void *)(list)->sentinel.previous) - - -// =======================================================================// -// ! -// ! Protocol -// ! -// =======================================================================// - - enum { - ENET_PROTOCOL_MINIMUM_MTU = 576, - ENET_PROTOCOL_MAXIMUM_MTU = 4096, - ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, - ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, - ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, - ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, - ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, - ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, - ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 - }; - - typedef enum _ENetProtocolCommand { - ENET_PROTOCOL_COMMAND_NONE = 0, - ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1, - ENET_PROTOCOL_COMMAND_CONNECT = 2, - ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3, - ENET_PROTOCOL_COMMAND_DISCONNECT = 4, - ENET_PROTOCOL_COMMAND_PING = 5, - ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, - ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, - ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, - ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, - ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, - ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, - ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12, - ENET_PROTOCOL_COMMAND_COUNT = 13, - - ENET_PROTOCOL_COMMAND_MASK = 0x0F - } ENetProtocolCommand; - - typedef enum _ENetProtocolFlag { - ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), - ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), - - ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14), - ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), - ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME, - - ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12), - ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 - } ENetProtocolFlag; - - #ifdef _MSC_VER - #pragma pack(push, 1) - #define ENET_PACKED - #elif defined(__GNUC__) || defined(__clang__) - #define ENET_PACKED __attribute__ ((packed)) - #else - #define ENET_PACKED - #endif - - typedef struct _ENetProtocolHeader { - enet_uint16 peerID; - enet_uint16 sentTime; - } ENET_PACKED ENetProtocolHeader; - - typedef struct _ENetProtocolCommandHeader { - enet_uint8 command; - enet_uint8 channelID; - enet_uint16 reliableSequenceNumber; - } ENET_PACKED ENetProtocolCommandHeader; - - typedef struct _ENetProtocolAcknowledge { - ENetProtocolCommandHeader header; - enet_uint16 receivedReliableSequenceNumber; - enet_uint16 receivedSentTime; - } ENET_PACKED ENetProtocolAcknowledge; - - typedef struct _ENetProtocolConnect { - ENetProtocolCommandHeader header; - enet_uint16 outgoingPeerID; - enet_uint8 incomingSessionID; - enet_uint8 outgoingSessionID; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 channelCount; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 connectID; - enet_uint32 data; - } ENET_PACKED ENetProtocolConnect; - - typedef struct _ENetProtocolVerifyConnect { - ENetProtocolCommandHeader header; - enet_uint16 outgoingPeerID; - enet_uint8 incomingSessionID; - enet_uint8 outgoingSessionID; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 channelCount; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 connectID; - } ENET_PACKED ENetProtocolVerifyConnect; - - typedef struct _ENetProtocolBandwidthLimit { - ENetProtocolCommandHeader header; - enet_uint32 incomingBandwidth; - enet_uint32 outgoingBandwidth; - } ENET_PACKED ENetProtocolBandwidthLimit; - - typedef struct _ENetProtocolThrottleConfigure { - ENetProtocolCommandHeader header; - enet_uint32 packetThrottleInterval; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - } ENET_PACKED ENetProtocolThrottleConfigure; - - typedef struct _ENetProtocolDisconnect { - ENetProtocolCommandHeader header; - enet_uint32 data; - } ENET_PACKED ENetProtocolDisconnect; - - typedef struct _ENetProtocolPing { - ENetProtocolCommandHeader header; - } ENET_PACKED ENetProtocolPing; - - typedef struct _ENetProtocolSendReliable { - ENetProtocolCommandHeader header; - enet_uint16 dataLength; - } ENET_PACKED ENetProtocolSendReliable; - - typedef struct _ENetProtocolSendUnreliable { - ENetProtocolCommandHeader header; - enet_uint16 unreliableSequenceNumber; - enet_uint16 dataLength; - } ENET_PACKED ENetProtocolSendUnreliable; - - typedef struct _ENetProtocolSendUnsequenced { - ENetProtocolCommandHeader header; - enet_uint16 unsequencedGroup; - enet_uint16 dataLength; - } ENET_PACKED ENetProtocolSendUnsequenced; - - typedef struct _ENetProtocolSendFragment { - ENetProtocolCommandHeader header; - enet_uint16 startSequenceNumber; - enet_uint16 dataLength; - enet_uint32 fragmentCount; - enet_uint32 fragmentNumber; - enet_uint32 totalLength; - enet_uint32 fragmentOffset; - } ENET_PACKED ENetProtocolSendFragment; - - typedef union _ENetProtocol { - ENetProtocolCommandHeader header; - ENetProtocolAcknowledge acknowledge; - ENetProtocolConnect connect; - ENetProtocolVerifyConnect verifyConnect; - ENetProtocolDisconnect disconnect; - ENetProtocolPing ping; - ENetProtocolSendReliable sendReliable; - ENetProtocolSendUnreliable sendUnreliable; - ENetProtocolSendUnsequenced sendUnsequenced; - ENetProtocolSendFragment sendFragment; - ENetProtocolBandwidthLimit bandwidthLimit; - ENetProtocolThrottleConfigure throttleConfigure; - } ENET_PACKED ENetProtocol; - - #ifdef _MSC_VER - #pragma pack(pop) - #endif - -// =======================================================================// -// ! -// ! General ENet structs/enums -// ! -// =======================================================================// - - typedef enum _ENetSocketType { - ENET_SOCKET_TYPE_STREAM = 1, - ENET_SOCKET_TYPE_DATAGRAM = 2 - } ENetSocketType; - - typedef enum _ENetSocketWait { - ENET_SOCKET_WAIT_NONE = 0, - ENET_SOCKET_WAIT_SEND = (1 << 0), - ENET_SOCKET_WAIT_RECEIVE = (1 << 1), - ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) - } ENetSocketWait; - - typedef enum _ENetSocketOption { - ENET_SOCKOPT_NONBLOCK = 1, - ENET_SOCKOPT_BROADCAST = 2, - ENET_SOCKOPT_RCVBUF = 3, - ENET_SOCKOPT_SNDBUF = 4, - ENET_SOCKOPT_REUSEADDR = 5, - ENET_SOCKOPT_RCVTIMEO = 6, - ENET_SOCKOPT_SNDTIMEO = 7, - ENET_SOCKOPT_ERROR = 8, - ENET_SOCKOPT_NODELAY = 9, - ENET_SOCKOPT_IPV6_V6ONLY = 10, - } ENetSocketOption; - - typedef enum _ENetSocketShutdown { - ENET_SOCKET_SHUTDOWN_READ = 0, - ENET_SOCKET_SHUTDOWN_WRITE = 1, - ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 - } ENetSocketShutdown; - - /** - * Portable internet address structure. - * - * The host must be specified in network byte-order, and the port must be in host - * byte-order. The constant ENET_HOST_ANY may be used to specify the default - * server host. The constant ENET_HOST_BROADCAST may be used to specify the - * broadcast address (255.255.255.255). This makes sense for enet_host_connect, - * but not for enet_host_create. Once a server responds to a broadcast, the - * address is updated from ENET_HOST_BROADCAST to the server's actual IP address. - */ - struct ENetAddress { - struct in6_addr host; - enet_uint16 port; - enet_uint16 sin6_scope_id; - }; - - #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. - * - * The host must be specified in network byte-order, and the port must be in - * host byte-order. The constant ENET_HOST_ANY may be used to specify the - * default server host. - * - * @sa ENetPacket - */ - typedef enum _ENetPacketFlag { - ENET_PACKET_FLAG_RELIABLE = (1 << 0), /** packet must be received by the target peer and resend attempts should be made until the packet is delivered */ - ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), /** packet will not be sequenced with other packets not supported for reliable packets */ - ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), /** packet will not allocate data, and user must supply it instead */ - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), /** packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU */ - ENET_PACKET_FLAG_SENT = (1 << 8), /** whether the packet has been sent from all queues it has been entered into */ - } ENetPacketFlag; - - typedef void (ENET_CALLBACK *ENetPacketFreeCallback)(void *); - - /** - * ENet packet structure. - * - * An ENet data packet that may be sent to or received from a peer. The shown - * fields should only be read and never modified. The data field contains the - * allocated data for the packet. The dataLength fields specifies the length - * of the allocated data. The flags field is either 0 (specifying no flags), - * or a bitwise-or of any combination of the following flags: - * - * ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer and resend attempts should be made until the packet is delivered - * ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets (not supported for reliable packets) - * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead - * ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU - * ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into - * @sa ENetPacketFlag - */ - struct ENetPacket { - size_t referenceCount; /**< internal use only */ - enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */ - enet_uint8 * data; /**< allocated data for packet */ - size_t dataLength; /**< length of data */ - ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ - void * userData; /**< application private data, may be freely modified */ - }; - - typedef struct _ENetAcknowledgement { - ENetListNode acknowledgementList; - enet_uint32 sentTime; - ENetProtocol command; - } ENetAcknowledgement; - - typedef struct _ENetOutgoingCommand { - ENetListNode outgoingCommandList; - enet_uint16 reliableSequenceNumber; - enet_uint16 unreliableSequenceNumber; - enet_uint32 sentTime; - enet_uint32 roundTripTimeout; - enet_uint32 roundTripTimeoutLimit; - enet_uint32 fragmentOffset; - enet_uint16 fragmentLength; - enet_uint16 sendAttempts; - ENetProtocol command; - ENetPacket * packet; - } ENetOutgoingCommand; - - typedef struct _ENetIncomingCommand { - ENetListNode incomingCommandList; - enet_uint16 reliableSequenceNumber; - enet_uint16 unreliableSequenceNumber; - ENetProtocol command; - enet_uint32 fragmentCount; - enet_uint32 fragmentsRemaining; - enet_uint32 *fragments; - ENetPacket * packet; - } ENetIncomingCommand; - - typedef enum _ENetPeerState { - ENET_PEER_STATE_DISCONNECTED = 0, - ENET_PEER_STATE_CONNECTING = 1, - ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, - ENET_PEER_STATE_CONNECTION_PENDING = 3, - ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, - ENET_PEER_STATE_CONNECTED = 5, - ENET_PEER_STATE_DISCONNECT_LATER = 6, - ENET_PEER_STATE_DISCONNECTING = 7, - ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, - ENET_PEER_STATE_ZOMBIE = 9 - } ENetPeerState; - - enum { - 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_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, - ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, - - ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, - ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, - ENET_PEER_PACKET_THROTTLE_SCALE = 32, - ENET_PEER_PACKET_THROTTLE_COUNTER = 7, - ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2, - ENET_PEER_PACKET_THROTTLE_DECELERATION = 2, - ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000, - ENET_PEER_PACKET_LOSS_SCALE = (1 << 16), - ENET_PEER_PACKET_LOSS_INTERVAL = 10000, - ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024, - ENET_PEER_TIMEOUT_LIMIT = 32, - ENET_PEER_TIMEOUT_MINIMUM = 5000, - ENET_PEER_TIMEOUT_MAXIMUM = 30000, - ENET_PEER_PING_INTERVAL = 500, - ENET_PEER_UNSEQUENCED_WINDOWS = 64, - ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024, - ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32, - ENET_PEER_RELIABLE_WINDOWS = 16, - ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000, - ENET_PEER_FREE_RELIABLE_WINDOWS = 8 - }; - - typedef struct _ENetChannel { - enet_uint16 outgoingReliableSequenceNumber; - enet_uint16 outgoingUnreliableSequenceNumber; - enet_uint16 usedReliableWindows; - enet_uint16 reliableWindows[ENET_PEER_RELIABLE_WINDOWS]; - enet_uint16 incomingReliableSequenceNumber; - enet_uint16 incomingUnreliableSequenceNumber; - ENetList incomingReliableCommands; - ENetList incomingUnreliableCommands; - } ENetChannel; - - /** - * An ENet peer which data packets may be sent or received from. - * - * No fields should be modified unless otherwise specified. - */ - struct ENetPeer { - ENetListNode dispatchList; - struct ENetHost *host; - enet_uint16 outgoingPeerID; - enet_uint16 incomingPeerID; - enet_uint32 connectID; - enet_uint8 outgoingSessionID; - enet_uint8 incomingSessionID; - ENetAddress address; /**< Internet address of the peer */ - void * data; /**< Application private data, may be freely modified */ - ENetPeerState state; - ENetChannel * channels; - size_t channelCount; /**< Number of channels allocated for communication with peer */ - enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */ - enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */ - enet_uint32 incomingBandwidthThrottleEpoch; - enet_uint32 outgoingBandwidthThrottleEpoch; - enet_uint32 incomingDataTotal; - enet_uint64 totalDataReceived; - enet_uint32 outgoingDataTotal; - enet_uint64 totalDataSent; - enet_uint32 lastSendTime; - enet_uint32 lastReceiveTime; - enet_uint32 nextTimeout; - enet_uint32 earliestTimeout; - enet_uint32 packetLossEpoch; - enet_uint32 packetsSent; - enet_uint64 totalPacketsSent; /**< total number of packets sent during a session */ - enet_uint32 packetsLost; - enet_uint32 totalPacketsLost; /**< total number of packets lost during a session */ - enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */ - enet_uint32 packetLossVariance; - enet_uint32 packetThrottle; - enet_uint32 packetThrottleLimit; - enet_uint32 packetThrottleCounter; - enet_uint32 packetThrottleEpoch; - enet_uint32 packetThrottleAcceleration; - enet_uint32 packetThrottleDeceleration; - enet_uint32 packetThrottleInterval; - enet_uint32 pingInterval; - enet_uint32 timeoutLimit; - enet_uint32 timeoutMinimum; - enet_uint32 timeoutMaximum; - enet_uint32 lastRoundTripTime; - enet_uint32 lowestRoundTripTime; - enet_uint32 lastRoundTripTimeVariance; - enet_uint32 highestRoundTripTimeVariance; - enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */ - enet_uint32 roundTripTimeVariance; - enet_uint32 mtu; - enet_uint32 windowSize; - enet_uint32 reliableDataInTransit; - enet_uint16 outgoingReliableSequenceNumber; - ENetList acknowledgements; - ENetList sentReliableCommands; - ENetList sentUnreliableCommands; - ENetList outgoingReliableCommands; - ENetList outgoingUnreliableCommands; - ENetList dispatchedCommands; - int needsDispatch; - enet_uint16 incomingUnsequencedGroup; - enet_uint16 outgoingUnsequencedGroup; - enet_uint32 unsequencedWindow[ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; - enet_uint32 eventData; - size_t totalWaitingData; - }; - - /** An ENet packet compressor for compressing UDP packets before socket sends or receives. */ - typedef struct _ENetCompressor { - /** Context data for the compressor. Must be non-NULL. */ - void *context; - - /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ - size_t(ENET_CALLBACK * compress) (void *context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit); - - /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ - size_t(ENET_CALLBACK * decompress) (void *context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit); - - /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */ - void (ENET_CALLBACK * destroy)(void *context); - } ENetCompressor; - - /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ - typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback)(const ENetBuffer *buffers, size_t bufferCount); - - /** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ - typedef int (ENET_CALLBACK * ENetInterceptCallback)(struct ENetHost *host, void *event); - - /** An ENet host for communicating with peers. - * - * No fields should be modified unless otherwise stated. - * - * @sa enet_host_create() - * @sa enet_host_destroy() - * @sa enet_host_connect() - * @sa enet_host_service() - * @sa enet_host_flush() - * @sa enet_host_broadcast() - * @sa enet_host_compress() - * @sa enet_host_channel_limit() - * @sa enet_host_bandwidth_limit() - * @sa enet_host_bandwidth_throttle() - */ - struct ENetHost { - ENetSocket socket; - ENetAddress address; /**< Internet address of the host */ - enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */ - enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */ - enet_uint32 bandwidthThrottleEpoch; - enet_uint32 mtu; - enet_uint32 randomSeed; - int recalculateBandwidthLimits; - ENetPeer * peers; /**< array of peers allocated for this host */ - size_t peerCount; /**< number of peers allocated for this host */ - size_t channelLimit; /**< maximum number of channels allowed for connected peers */ - enet_uint32 serviceTime; - ENetList dispatchQueue; - int continueSending; - size_t packetSize; - enet_uint16 headerFlags; - ENetProtocol commands[ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; - size_t commandCount; - ENetBuffer buffers[ENET_BUFFER_MAXIMUM]; - size_t bufferCount; - ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */ - ENetCompressor compressor; - enet_uint8 packetData[2][ENET_PROTOCOL_MAXIMUM_MTU]; - ENetAddress receivedAddress; - enet_uint8 * receivedData; - size_t receivedDataLength; - enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ - enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ - ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ - size_t connectedPeers; - size_t bandwidthLimitedPeers; - size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ - size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ - size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ - }; - - /** - * An ENet event type, as specified in @ref ENetEvent. - */ - typedef enum _ENetEventType { - /** no event occurred within the specified time limit */ - ENET_EVENT_TYPE_NONE = 0, - - /** a connection request initiated by enet_host_connect has completed. - * The peer field contains the peer which successfully connected. - */ - ENET_EVENT_TYPE_CONNECT = 1, - - /** a peer has disconnected. This event is generated on a successful - * completion of a disconnect initiated by enet_peer_disconnect, if - * a peer has timed out. The peer field contains the peer - * which disconnected. The data field contains user supplied data - * describing the disconnection, or 0, if none is available. - */ - ENET_EVENT_TYPE_DISCONNECT = 2, - - /** a packet has been received from a peer. The peer field specifies the - * peer which sent the packet. The channelID field specifies the channel - * number upon which the packet was received. The packet field contains - * the packet that was received; this packet must be destroyed with - * enet_packet_destroy after use. - */ - ENET_EVENT_TYPE_RECEIVE = 3, - - /** a peer is disconnected because the host didn't receive the acknowledgment - * packet within certain maximum time out. The reason could be because of bad - * network connection or host crashed. - */ - ENET_EVENT_TYPE_DISCONNECT_TIMEOUT = 4, - } ENetEventType; - - /** - * An ENet event as returned by enet_host_service(). - * - * @sa enet_host_service - */ - struct ENetEvent { - ENetEventType type; /**< type of the event */ - ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */ - enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */ - enet_uint32 data; /**< data associated with the event, if appropriate */ - ENetPacket * packet; /**< packet associated with the event, if appropriate */ - }; - -// =======================================================================// -// ! -// ! Public API -// ! -// =======================================================================// - - /** - * Initializes ENet globally. Must be called prior to using any functions in ENet. - * @returns 0 on success, < 0 on failure - */ - ENET_API int enet_initialize(void); - - /** - * Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. - * - * @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use - * @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults - * @returns 0 on success, < 0 on failure - */ - ENET_API int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks * inits); - - /** - * Shuts down ENet globally. Should be called when a program that has initialized ENet exits. - */ - ENET_API void enet_deinitialize(void); - - /** - * Gives the linked version of the ENet library. - * @returns the version number - */ - ENET_API ENetVersion enet_linked_version(void); - - /** Returns the monotonic time in milliseconds. Its initial value is unspecified unless otherwise set. */ - ENET_API enet_uint32 enet_time_get(void); - - /** ENet socket functions */ - ENET_API ENetSocket enet_socket_create(ENetSocketType); - ENET_API int enet_socket_bind(ENetSocket, const ENetAddress *); - ENET_API int enet_socket_get_address(ENetSocket, ENetAddress *); - ENET_API int enet_socket_listen(ENetSocket, int); - ENET_API ENetSocket enet_socket_accept(ENetSocket, ENetAddress *); - ENET_API int enet_socket_connect(ENetSocket, const ENetAddress *); - ENET_API int enet_socket_send(ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); - ENET_API int enet_socket_receive(ENetSocket, ENetAddress *, ENetBuffer *, size_t); - ENET_API int enet_socket_wait(ENetSocket, enet_uint32 *, enet_uint64); - ENET_API int enet_socket_set_option(ENetSocket, ENetSocketOption, int); - ENET_API int enet_socket_get_option(ENetSocket, ENetSocketOption, int *); - ENET_API int enet_socket_shutdown(ENetSocket, ENetSocketShutdown); - ENET_API void enet_socket_destroy(ENetSocket); - ENET_API int enet_socketset_select(ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); - - /** Attempts to parse the printable form of the IP address in the parameter hostName - and sets the host field in the address parameter if successful. - @param address destination to store the parsed IP address - @param hostName IP address to parse - @retval 0 on success - @retval < 0 on failure - @returns the address of the given hostName in address on success - */ - ENET_API int enet_address_set_host_ip(ENetAddress * address, const char * hostName); - - /** Attempts to resolve the host named by the parameter hostName and sets - the host field in the address parameter if successful. - @param address destination to store resolved address - @param hostName host name to lookup - @retval 0 on success - @retval < 0 on failure - @returns the address of the given hostName in address on success - */ - ENET_API int enet_address_set_host(ENetAddress * address, const char * hostName); - - /** Gives the printable form of the IP address specified in the address parameter. - @param address address printed - @param hostName destination for name, must not be NULL - @param nameLength maximum length of hostName. - @returns the null-terminated name of the host in hostName on success - @retval 0 on success - @retval < 0 on failure - */ - ENET_API int enet_address_get_host_ip(const ENetAddress * address, char * hostName, size_t nameLength); - - /** Attempts to do a reverse lookup of the host field in the address parameter. - @param address address used for reverse lookup - @param hostName destination for name, must not be NULL - @param nameLength maximum length of hostName. - @returns the null-terminated name of the host in hostName on success - @retval 0 on success - @retval < 0 on failure - */ - ENET_API int enet_address_get_host(const ENetAddress * address, char * hostName, size_t nameLength); - - ENET_API enet_uint32 enet_host_get_peers_count(ENetHost *); - ENET_API enet_uint32 enet_host_get_packets_sent(ENetHost *); - ENET_API enet_uint32 enet_host_get_packets_received(ENetHost *); - ENET_API enet_uint32 enet_host_get_bytes_sent(ENetHost *); - ENET_API enet_uint32 enet_host_get_bytes_received(ENetHost *); - ENET_API enet_uint32 enet_host_get_received_data(ENetHost *, enet_uint8** data); - ENET_API enet_uint32 enet_host_get_mtu(ENetHost *); - - ENET_API enet_uint32 enet_peer_get_id(ENetPeer *); - ENET_API enet_uint32 enet_peer_get_ip(ENetPeer *, char * ip, size_t ipLength); - ENET_API enet_uint16 enet_peer_get_port(ENetPeer *); - ENET_API enet_uint32 enet_peer_get_rtt(ENetPeer *); - ENET_API enet_uint64 enet_peer_get_packets_sent(ENetPeer *); - ENET_API enet_uint32 enet_peer_get_packets_lost(ENetPeer *); - ENET_API enet_uint64 enet_peer_get_bytes_sent(ENetPeer *); - ENET_API enet_uint64 enet_peer_get_bytes_received(ENetPeer *); - - ENET_API ENetPeerState enet_peer_get_state(ENetPeer *); - - ENET_API void * enet_peer_get_data(ENetPeer *); - ENET_API void enet_peer_set_data(ENetPeer *, const void *); - - ENET_API void * enet_packet_get_data(ENetPacket *); - ENET_API enet_uint32 enet_packet_get_length(ENetPacket *); - ENET_API void enet_packet_set_free_callback(ENetPacket *, void *); - - ENET_API ENetPacket * enet_packet_create(const void *, size_t, enet_uint32); - ENET_API ENetPacket * enet_packet_create_offset(const void *, size_t, size_t, enet_uint32); - ENET_API void enet_packet_destroy(ENetPacket *); - ENET_API enet_uint32 enet_crc32(const ENetBuffer *, size_t); - - ENET_API ENetHost * enet_host_create(const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); - ENET_API void enet_host_destroy(ENetHost *); - ENET_API ENetPeer * enet_host_connect(ENetHost *, const ENetAddress *, size_t, enet_uint32); - ENET_API int enet_host_check_events(ENetHost *, ENetEvent *); - ENET_API int enet_host_service(ENetHost *, ENetEvent *, enet_uint32); - ENET_API int enet_host_send_raw(ENetHost *, const ENetAddress *, enet_uint8 *, size_t); - ENET_API int enet_host_send_raw_ex(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend); - ENET_API void enet_host_set_intercept(ENetHost *, const ENetInterceptCallback); - ENET_API void enet_host_flush(ENetHost *); - ENET_API void enet_host_broadcast(ENetHost *, enet_uint8, ENetPacket *); - ENET_API void enet_host_compress(ENetHost *, const ENetCompressor *); - ENET_API void enet_host_channel_limit(ENetHost *, size_t); - ENET_API void enet_host_bandwidth_limit(ENetHost *, enet_uint32, enet_uint32); - extern void enet_host_bandwidth_throttle(ENetHost *); - extern enet_uint64 enet_host_random_seed(void); - - ENET_API int enet_peer_send(ENetPeer *, enet_uint8, ENetPacket *); - ENET_API ENetPacket * enet_peer_receive(ENetPeer *, enet_uint8 * channelID); - ENET_API void enet_peer_ping(ENetPeer *); - ENET_API void enet_peer_ping_interval(ENetPeer *, enet_uint32); - ENET_API void enet_peer_timeout(ENetPeer *, enet_uint32, enet_uint32, enet_uint32); - ENET_API void enet_peer_reset(ENetPeer *); - ENET_API void enet_peer_disconnect(ENetPeer *, enet_uint32); - ENET_API void enet_peer_disconnect_now(ENetPeer *, enet_uint32); - ENET_API void enet_peer_disconnect_later(ENetPeer *, enet_uint32); - ENET_API void enet_peer_throttle_configure(ENetPeer *, enet_uint32, enet_uint32, enet_uint32); - extern int enet_peer_throttle(ENetPeer *, enet_uint32); - extern void enet_peer_reset_queues(ENetPeer *); - extern void enet_peer_setup_outgoing_command(ENetPeer *, ENetOutgoingCommand *); - extern ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); - extern ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); - extern ENetAcknowledgement * enet_peer_queue_acknowledgement(ENetPeer *, const ENetProtocol *, enet_uint16); - extern void enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *, ENetChannel *); - extern void enet_peer_dispatch_incoming_reliable_commands(ENetPeer *, ENetChannel *); - extern void enet_peer_on_connect(ENetPeer *); - extern void enet_peer_on_disconnect(ENetPeer *); - - extern size_t enet_protocol_command_size (enet_uint8); - -#ifdef __cplusplus -} -#endif - -#if defined(ENET_IMPLEMENTATION) && !defined(ENET_IMPLEMENTATION_DONE) -#define ENET_IMPLEMENTATION_DONE 1 - -#ifdef __cplusplus -extern "C" { -#endif - -// =======================================================================// -// ! -// ! Atomics -// ! -// =======================================================================// - -#if defined(_MSC_VER) - - #define ENET_AT_CASSERT_PRED(predicate) sizeof(char[2 * !!(predicate)-1]) - #define ENET_IS_SUPPORTED_ATOMIC(size) ENET_AT_CASSERT_PRED(size == 1 || size == 2 || size == 4 || size == 8) - #define ENET_ATOMIC_SIZEOF(variable) (ENET_IS_SUPPORTED_ATOMIC(sizeof(*(variable))), sizeof(*(variable))) - - __inline int64_t enet_at_atomic_read(char *ptr, size_t size) - { - switch (size) { - case 1: - return _InterlockedExchangeAdd8((volatile char *)ptr, 0); - case 2: - return _InterlockedExchangeAdd16((volatile SHORT *)ptr, 0); - case 4: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchangeAdd((volatile LONG *)ptr, 0); - #else - return _InterlockedExchangeAdd((volatile LONG *)ptr, 0); - #endif - case 8: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0); - #else - return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0); - #endif - default: - return 0xbad13bad; /* never reached */ - } - } - - __inline int64_t enet_at_atomic_write(char *ptr, int64_t value, size_t size) - { - switch (size) { - case 1: - return _InterlockedExchange8((volatile char *)ptr, (char)value); - case 2: - return _InterlockedExchange16((volatile SHORT *)ptr, (SHORT)value); - case 4: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchange((volatile LONG *)ptr, (LONG)value); - #else - return _InterlockedExchange((volatile LONG *)ptr, (LONG)value); - #endif - case 8: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value); - #else - return _InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value); - #endif - default: - return 0xbad13bad; /* never reached */ - } - } - - __inline int64_t enet_at_atomic_cas(char *ptr, int64_t new_val, int64_t old_val, size_t size) - { - switch (size) { - case 1: - return _InterlockedCompareExchange8((volatile char *)ptr, (char)new_val, (char)old_val); - case 2: - return _InterlockedCompareExchange16((volatile SHORT *)ptr, (SHORT)new_val, - (SHORT)old_val); - case 4: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val); - #else - return _InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val); - #endif - case 8: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val, - (LONGLONG)old_val); - #else - return _InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val, - (LONGLONG)old_val); - #endif - default: - return 0xbad13bad; /* never reached */ - } - } - - __inline int64_t enet_at_atomic_inc(char *ptr, int64_t delta, size_t data_size) - { - switch (data_size) { - case 1: - return _InterlockedExchangeAdd8((volatile char *)ptr, (char)delta); - case 2: - return _InterlockedExchangeAdd16((volatile SHORT *)ptr, (SHORT)delta); - case 4: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta); - #else - return _InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta); - #endif - case 8: - #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE - return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta); - #else - return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta); - #endif - default: - return 0xbad13bad; /* never reached */ - } - } - - #define ENET_ATOMIC_READ(variable) enet_at_atomic_read((char *)(variable), ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_WRITE(variable, new_val) \ - enet_at_atomic_write((char *)(variable), (int64_t)(new_val), ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_CAS(variable, old_value, new_val) \ - enet_at_atomic_cas((char *)(variable), (int64_t)(new_val), (int64_t)(old_value), \ - ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_INC(variable) enet_at_atomic_inc((char *)(variable), 1, ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_DEC(variable) enet_at_atomic_inc((char *)(variable), -1, ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_INC_BY(variable, delta) \ - enet_at_atomic_inc((char *)(variable), (delta), ENET_ATOMIC_SIZEOF(variable)) - #define ENET_ATOMIC_DEC_BY(variable, delta) \ - enet_at_atomic_inc((char *)(variable), -(delta), ENET_ATOMIC_SIZEOF(variable)) - -#elif defined(__GNUC__) || defined(__clang__) - - #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) - #define AT_HAVE_ATOMICS - #endif - - /* We want to use __atomic built-ins if possible because the __sync primitives are - deprecated, because the __atomic build-ins allow us to use ENET_ATOMIC_WRITE on - uninitialized memory without running into undefined behavior, and because the - __atomic versions generate more efficient code since we don't need to rely on - CAS when we don't actually want it. - - Note that we use acquire-release memory order (like mutexes do). We could use - sequentially consistent memory order but that has lower performance and is - almost always unneeded. */ - #ifdef AT_HAVE_ATOMICS - #define ENET_ATOMIC_READ(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE) - #define ENET_ATOMIC_WRITE(ptr, value) __atomic_store_n((ptr), (value), __ATOMIC_RELEASE) - - #ifndef typeof - #define typeof __typeof__ - #endif - - /* clang_analyzer doesn't know that CAS writes to memory so it complains about - potentially lost data. Replace the code with the equivalent non-sync code. */ - #ifdef __clang_analyzer__ - - #define ENET_ATOMIC_CAS(ptr, old_value, new_value) \ - ({ \ - typeof(*(ptr)) ENET_ATOMIC_CAS_old_actual_ = (*(ptr)); \ - if (ATOMIC_CAS_old_actual_ == (old_value)) { \ - *(ptr) = new_value; \ - } \ - ENET_ATOMIC_CAS_old_actual_; \ - }) - - #else - - /* Could use __auto_type instead of typeof but that shouldn't work in C++. - The ({ }) syntax is a GCC extension called statement expression. It lets - us return a value out of the macro. - - TODO We should return bool here instead of the old value to avoid the ABA - problem. */ - #define ENET_ATOMIC_CAS(ptr, old_value, new_value) \ - ({ \ - typeof(*(ptr)) ENET_ATOMIC_CAS_expected_ = (old_value); \ - __atomic_compare_exchange_n((ptr), &ENET_ATOMIC_CAS_expected_, (new_value), false, \ - __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); \ - ENET_ATOMIC_CAS_expected_; \ - }) - - #endif /* __clang_analyzer__ */ - - #define ENET_ATOMIC_INC(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_ACQ_REL) - #define ENET_ATOMIC_DEC(ptr) __atomic_fetch_sub((ptr), 1, __ATOMIC_ACQ_REL) - #define ENET_ATOMIC_INC_BY(ptr, delta) __atomic_fetch_add((ptr), (delta), __ATOMIC_ACQ_REL) - #define ENET_ATOMIC_DEC_BY(ptr, delta) __atomic_fetch_sub((ptr), (delta), __ATOMIC_ACQ_REL) - - #else - - #define ENET_ATOMIC_READ(variable) __sync_fetch_and_add(variable, 0) - #define ENET_ATOMIC_WRITE(variable, new_val) \ - (void) __sync_val_compare_and_swap((variable), *(variable), (new_val)) - #define ENET_ATOMIC_CAS(variable, old_value, new_val) \ - __sync_val_compare_and_swap((variable), (old_value), (new_val)) - #define ENET_ATOMIC_INC(variable) __sync_fetch_and_add((variable), 1) - #define ENET_ATOMIC_DEC(variable) __sync_fetch_and_sub((variable), 1) - #define ENET_ATOMIC_INC_BY(variable, delta) __sync_fetch_and_add((variable), (delta), 1) - #define ENET_ATOMIC_DEC_BY(variable, delta) __sync_fetch_and_sub((variable), (delta), 1) - - #endif /* AT_HAVE_ATOMICS */ - - #undef AT_HAVE_ATOMICS - -#endif /* defined(_MSC_VER) */ - - -// =======================================================================// -// ! -// ! Callbacks -// ! -// =======================================================================// - - static ENetCallbacks callbacks = { malloc, free, abort }; - - int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks *inits) { - if (version < ENET_VERSION_CREATE(1, 3, 0)) { - return -1; - } - - if (inits->e_malloc != NULL || inits->e_free != NULL) { - if (inits->e_malloc == NULL || inits->e_free == NULL) { - return -1; - } - - callbacks.e_malloc = inits->e_malloc; - callbacks.e_free = inits->e_free; - } - - if (inits->no_memory != NULL) { - callbacks.no_memory = inits->no_memory; - } - - return enet_initialize(); - } - - ENetVersion enet_linked_version(void) { - return ENET_VERSION; - } - - void * enet_malloc(size_t size) { - void *memory = callbacks.e_malloc(size); - - if (memory == NULL) { - callbacks.no_memory(); - } - - return memory; - } - - void enet_free(void *memory) { - callbacks.e_free(memory); - } - -// =======================================================================// -// ! -// ! List -// ! -// =======================================================================// - - void enet_list_clear(ENetList *list) { - list->sentinel.next = &list->sentinel; - list->sentinel.previous = &list->sentinel; - } - - ENetListIterator enet_list_insert(ENetListIterator position, void *data) { - ENetListIterator result = (ENetListIterator)data; - - result->previous = position->previous; - result->next = position; - - result->previous->next = result; - position->previous = result; - - return result; - } - - void *enet_list_remove(ENetListIterator position) { - position->previous->next = position->next; - position->next->previous = position->previous; - - return position; - } - - ENetListIterator enet_list_move(ENetListIterator position, void *dataFirst, void *dataLast) { - ENetListIterator first = (ENetListIterator)dataFirst; - ENetListIterator last = (ENetListIterator)dataLast; - - first->previous->next = last->next; - last->next->previous = first->previous; - - first->previous = position->previous; - last->next = position; - - first->previous->next = first; - position->previous = last; - - return first; - } - - size_t enet_list_size(ENetList *list) { - size_t size = 0; - ENetListIterator position; - - for (position = enet_list_begin(list); position != enet_list_end(list); position = enet_list_next(position)) { - ++size; - } - - return size; - } - -// =======================================================================// -// ! -// ! Packet -// ! -// =======================================================================// - - /** - * Creates a packet that may be sent to a peer. - * @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. - * @param dataLength size of the data allocated for this packet - * @param flags flags for this packet as described for the ENetPacket structure. - * @returns the packet on success, NULL on failure - */ - ENetPacket *enet_packet_create(const void *data, size_t dataLength, enet_uint32 flags) { - ENetPacket *packet; - if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { - packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket)); - if (packet == NULL) { - return NULL; - } - - packet->data = (enet_uint8 *)data; - } - else { - packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength); - if (packet == NULL) { - return NULL; - } - - packet->data = (enet_uint8 *)packet + sizeof(ENetPacket); - - if (data != NULL) { - memcpy(packet->data, data, dataLength); - } - } - - packet->referenceCount = 0; - packet->flags = flags; - packet->dataLength = dataLength; - packet->freeCallback = NULL; - packet->userData = NULL; - - return packet; - } - - 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) { - packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket)); - if (packet == NULL) { - return NULL; - } - - packet->data = (enet_uint8 *)data; - } - else { - packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength + dataOffset); - if (packet == NULL) { - return NULL; - } - - packet->data = (enet_uint8 *)packet + sizeof(ENetPacket); - - if (data != NULL) { - memcpy(packet->data + dataOffset, data, dataLength); - } - } - - packet->referenceCount = 0; - packet->flags = flags; - packet->dataLength = dataLength + dataOffset; - packet->freeCallback = NULL; - packet->userData = NULL; - - return packet; - } - - /** - * Destroys the packet and deallocates its data. - * @param packet packet to be destroyed - */ - void enet_packet_destroy(ENetPacket *packet) { - if (packet == NULL) { - return; - } - - if (packet->freeCallback != NULL) { - (*packet->freeCallback)((void *)packet); - } - - enet_free(packet); - } - - static int initializedCRC32 = 0; - static enet_uint32 crcTable[256]; - - static enet_uint32 reflect_crc(int val, int bits) { - int result = 0, bit; - - for (bit = 0; bit < bits; bit++) { - if (val & 1) { result |= 1 << (bits - 1 - bit); } - val >>= 1; - } - - return result; - } - - static void initialize_crc32(void) { - int byte; - - for (byte = 0; byte < 256; ++byte) { - enet_uint32 crc = reflect_crc(byte, 8) << 24; - int offset; - - for (offset = 0; offset < 8; ++offset) { - if (crc & 0x80000000) { - crc = (crc << 1) ^ 0x04c11db7; - } else { - crc <<= 1; - } - } - - crcTable[byte] = reflect_crc(crc, 32); - } - - initializedCRC32 = 1; - } - - enet_uint32 enet_crc32(const ENetBuffer *buffers, size_t bufferCount) { - enet_uint32 crc = 0xFFFFFFFF; - - if (!initializedCRC32) { initialize_crc32(); } - - while (bufferCount-- > 0) { - const enet_uint8 *data = (const enet_uint8 *)buffers->data; - const enet_uint8 *dataEnd = &data[buffers->dataLength]; - - while (data < dataEnd) { - crc = (crc >> 8) ^ crcTable[(crc & 0xFF) ^ *data++]; - } - - ++buffers; - } - - return ENET_HOST_TO_NET_32(~crc); - } - -// =======================================================================// -// ! -// ! Protocol -// ! -// =======================================================================// - - static size_t commandSizes[ENET_PROTOCOL_COMMAND_COUNT] = { - 0, - sizeof(ENetProtocolAcknowledge), - sizeof(ENetProtocolConnect), - sizeof(ENetProtocolVerifyConnect), - sizeof(ENetProtocolDisconnect), - sizeof(ENetProtocolPing), - sizeof(ENetProtocolSendReliable), - sizeof(ENetProtocolSendUnreliable), - sizeof(ENetProtocolSendFragment), - sizeof(ENetProtocolSendUnsequenced), - sizeof(ENetProtocolBandwidthLimit), - sizeof(ENetProtocolThrottleConfigure), - sizeof(ENetProtocolSendFragment) - }; - - size_t enet_protocol_command_size(enet_uint8 commandNumber) { - return commandSizes[commandNumber & ENET_PROTOCOL_COMMAND_MASK]; - } - - static void enet_protocol_change_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) { - if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) { - enet_peer_on_connect(peer); - } else { - enet_peer_on_disconnect(peer); - } - - peer->state = state; - } - - static void enet_protocol_dispatch_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) { - enet_protocol_change_state(host, peer, state); - - if (!peer->needsDispatch) { - enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList); - peer->needsDispatch = 1; - } - } - - static int enet_protocol_dispatch_incoming_commands(ENetHost *host, ENetEvent *event) { - while (!enet_list_empty(&host->dispatchQueue)) { - ENetPeer *peer = (ENetPeer *) enet_list_remove(enet_list_begin(&host->dispatchQueue)); - peer->needsDispatch = 0; - - switch (peer->state) { - case ENET_PEER_STATE_CONNECTION_PENDING: - case ENET_PEER_STATE_CONNECTION_SUCCEEDED: - enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED); - - event->type = ENET_EVENT_TYPE_CONNECT; - event->peer = peer; - event->data = peer->eventData; - - return 1; - - case ENET_PEER_STATE_ZOMBIE: - host->recalculateBandwidthLimits = 1; - - event->type = ENET_EVENT_TYPE_DISCONNECT; - event->peer = peer; - event->data = peer->eventData; - - enet_peer_reset(peer); - - return 1; - - case ENET_PEER_STATE_CONNECTED: - if (enet_list_empty(&peer->dispatchedCommands)) { - continue; - } - - event->packet = enet_peer_receive(peer, &event->channelID); - if (event->packet == NULL) { - continue; - } - - event->type = ENET_EVENT_TYPE_RECEIVE; - event->peer = peer; - - if (!enet_list_empty(&peer->dispatchedCommands)) { - peer->needsDispatch = 1; - enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList); - } - - return 1; - - default: - break; - } - } - - return 0; - } /* enet_protocol_dispatch_incoming_commands */ - - static void enet_protocol_notify_connect(ENetHost *host, ENetPeer *peer, ENetEvent *event) { - host->recalculateBandwidthLimits = 1; - - if (event != NULL) { - enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED); - - peer->totalDataSent = 0; - peer->totalDataReceived = 0; - peer->totalPacketsSent = 0; - peer->totalPacketsLost = 0; - - event->type = ENET_EVENT_TYPE_CONNECT; - event->peer = peer; - event->data = peer->eventData; - } else { - enet_protocol_dispatch_state(host, peer, peer->state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING); - } - } - - static void enet_protocol_notify_disconnect(ENetHost *host, ENetPeer *peer, ENetEvent *event) { - if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) { - host->recalculateBandwidthLimits = 1; - } - - if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) { - enet_peer_reset(peer); - } else if (event != NULL) { - event->type = ENET_EVENT_TYPE_DISCONNECT; - event->peer = peer; - event->data = 0; - - enet_peer_reset(peer); - } else { - peer->eventData = 0; - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - } - } - - static void enet_protocol_notify_disconnect_timeout (ENetHost * host, ENetPeer * peer, ENetEvent * event) { - if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) { - host->recalculateBandwidthLimits = 1; - } - - if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) { - enet_peer_reset (peer); - } - else if (event != NULL) { - event->type = ENET_EVENT_TYPE_DISCONNECT_TIMEOUT; - event->peer = peer; - event->data = 0; - - enet_peer_reset(peer); - } - else { - peer->eventData = 0; - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - } - } - - static void enet_protocol_remove_sent_unreliable_commands(ENetPeer *peer) { - ENetOutgoingCommand *outgoingCommand; - - while (!enet_list_empty(&peer->sentUnreliableCommands)) { - outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentUnreliableCommands); - enet_list_remove(&outgoingCommand->outgoingCommandList); - - if (outgoingCommand->packet != NULL) { - --outgoingCommand->packet->referenceCount; - - if (outgoingCommand->packet->referenceCount == 0) { - outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT; - enet_packet_destroy(outgoingCommand->packet); - } - } - - enet_free(outgoingCommand); - } - } - - static ENetProtocolCommand enet_protocol_remove_sent_reliable_command(ENetPeer *peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) { - ENetOutgoingCommand *outgoingCommand = NULL; - ENetListIterator currentCommand; - ENetProtocolCommand commandNumber; - int wasSent = 1; - - for (currentCommand = enet_list_begin(&peer->sentReliableCommands); - currentCommand != enet_list_end(&peer->sentReliableCommands); - currentCommand = enet_list_next(currentCommand) - ) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - - if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) { - break; - } - } - - if (currentCommand == enet_list_end(&peer->sentReliableCommands)) { - for (currentCommand = enet_list_begin(&peer->outgoingReliableCommands); - currentCommand != enet_list_end(&peer->outgoingReliableCommands); - currentCommand = enet_list_next(currentCommand) - ) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - - if (outgoingCommand->sendAttempts < 1) { return ENET_PROTOCOL_COMMAND_NONE; } - if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) { - break; - } - } - - if (currentCommand == enet_list_end(&peer->outgoingReliableCommands)) { - return ENET_PROTOCOL_COMMAND_NONE; - } - - wasSent = 0; - } - - if (outgoingCommand == NULL) { - return ENET_PROTOCOL_COMMAND_NONE; - } - - if (channelID < peer->channelCount) { - ENetChannel *channel = &peer->channels[channelID]; - enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - if (channel->reliableWindows[reliableWindow] > 0) { - --channel->reliableWindows[reliableWindow]; - if (!channel->reliableWindows[reliableWindow]) { - channel->usedReliableWindows &= ~(1 << reliableWindow); - } - } - } - - commandNumber = (ENetProtocolCommand) (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK); - enet_list_remove(&outgoingCommand->outgoingCommandList); - - if (outgoingCommand->packet != NULL) { - if (wasSent) { - peer->reliableDataInTransit -= outgoingCommand->fragmentLength; - } - - --outgoingCommand->packet->referenceCount; - - if (outgoingCommand->packet->referenceCount == 0) { - outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT; - enet_packet_destroy(outgoingCommand->packet); - } - } - - enet_free(outgoingCommand); - - if (enet_list_empty(&peer->sentReliableCommands)) { - return commandNumber; - } - - outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentReliableCommands); - peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; - - return commandNumber; - } /* enet_protocol_remove_sent_reliable_command */ - - static ENetPeer * enet_protocol_handle_connect(ENetHost *host, ENetProtocolHeader *header, ENetProtocol *command) { - enet_uint8 incomingSessionID, outgoingSessionID; - enet_uint32 mtu, windowSize; - ENetChannel *channel; - size_t channelCount, duplicatePeers = 0; - ENetPeer *currentPeer, *peer = NULL; - ENetProtocol verifyCommand; - - channelCount = ENET_NET_TO_HOST_32(command->connect.channelCount); - - if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { - return NULL; - } - - 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 && in6_equal(currentPeer->address.host, host->receivedAddress.host)) { - if (currentPeer->address.port == host->receivedAddress.port && currentPeer->connectID == command->connect.connectID) { - return NULL; - } - - ++duplicatePeers; - } - } - - if (peer == NULL || duplicatePeers >= host->duplicatePeers) { - return NULL; - } - - if (channelCount > host->channelLimit) { - channelCount = host->channelLimit; - } - peer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel)); - if (peer->channels == NULL) { - return NULL; - } - peer->channelCount = channelCount; - peer->state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; - peer->connectID = command->connect.connectID; - peer->address = host->receivedAddress; - peer->outgoingPeerID = ENET_NET_TO_HOST_16(command->connect.outgoingPeerID); - peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->connect.incomingBandwidth); - peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->connect.outgoingBandwidth); - peer->packetThrottleInterval = ENET_NET_TO_HOST_32(command->connect.packetThrottleInterval); - peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleAcceleration); - peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleDeceleration); - peer->eventData = ENET_NET_TO_HOST_32(command->connect.data); - - incomingSessionID = command->connect.incomingSessionID == 0xFF ? peer->outgoingSessionID : command->connect.incomingSessionID; - incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (incomingSessionID == peer->outgoingSessionID) { - incomingSessionID = (incomingSessionID + 1) - & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - } - peer->outgoingSessionID = incomingSessionID; - - outgoingSessionID = command->connect.outgoingSessionID == 0xFF ? peer->incomingSessionID : command->connect.outgoingSessionID; - outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - if (outgoingSessionID == peer->incomingSessionID) { - outgoingSessionID = (outgoingSessionID + 1) - & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); - } - peer->incomingSessionID = outgoingSessionID; - - for (channel = peer->channels; channel < &peer->channels[channelCount]; ++channel) { - channel->outgoingReliableSequenceNumber = 0; - channel->outgoingUnreliableSequenceNumber = 0; - channel->incomingReliableSequenceNumber = 0; - channel->incomingUnreliableSequenceNumber = 0; - - enet_list_clear(&channel->incomingReliableCommands); - enet_list_clear(&channel->incomingUnreliableCommands); - - channel->usedReliableWindows = 0; - memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows)); - } - - mtu = ENET_NET_TO_HOST_32(command->connect.mtu); - - if (mtu < ENET_PROTOCOL_MINIMUM_MTU) { - mtu = ENET_PROTOCOL_MINIMUM_MTU; - } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) { - mtu = ENET_PROTOCOL_MAXIMUM_MTU; - } - - peer->mtu = mtu; - - if (host->outgoingBandwidth == 0 && peer->incomingBandwidth == 0) { - peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } else if (host->outgoingBandwidth == 0 || peer->incomingBandwidth == 0) { - peer->windowSize = (ENET_MAX(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else { - peer->windowSize = (ENET_MIN(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } - - if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { - peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { - peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } - - if (host->incomingBandwidth == 0) { - windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } else { - windowSize = (host->incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } - - if (windowSize > ENET_NET_TO_HOST_32(command->connect.windowSize)) { - windowSize = ENET_NET_TO_HOST_32(command->connect.windowSize); - } - - if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { - windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { - windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } - - verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - verifyCommand.header.channelID = 0xFF; - verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16(peer->incomingPeerID); - verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; - verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; - verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32(peer->mtu); - verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32(windowSize); - verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32(channelCount); - verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32(host->incomingBandwidth); - verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); - verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32(peer->packetThrottleInterval); - verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(peer->packetThrottleAcceleration); - verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(peer->packetThrottleDeceleration); - verifyCommand.verifyConnect.connectID = peer->connectID; - - enet_peer_queue_outgoing_command(peer, &verifyCommand, NULL, 0, 0); - return peer; - } /* enet_protocol_handle_connect */ - - static int enet_protocol_handle_send_reliable(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { - size_t dataLength; - - if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { - return -1; - } - - dataLength = ENET_NET_TO_HOST_16(command->sendReliable.dataLength); - *currentData += dataLength; - - if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { - return -1; - } - - if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) { - return -1; - } - - return 0; - } - - static int enet_protocol_handle_send_unsequenced(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { - enet_uint32 unsequencedGroup, index; - size_t dataLength; - - if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { - return -1; - } - - dataLength = ENET_NET_TO_HOST_16(command->sendUnsequenced.dataLength); - *currentData += dataLength; - if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { - return -1; - } - - unsequencedGroup = ENET_NET_TO_HOST_16(command->sendUnsequenced.unsequencedGroup); - index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE; - - if (unsequencedGroup < peer->incomingUnsequencedGroup) { - unsequencedGroup += 0x10000; - } - - if (unsequencedGroup >= (enet_uint32) peer->incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE) { - return 0; - } - - unsequencedGroup &= 0xFFFF; - - if (unsequencedGroup - index != peer->incomingUnsequencedGroup) { - peer->incomingUnsequencedGroup = unsequencedGroup - index; - memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow)); - } else if (peer->unsequencedWindow[index / 32] & (1 << (index % 32))) { - return 0; - } - - if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED,0) == NULL) { - return -1; - } - - peer->unsequencedWindow[index / 32] |= 1 << (index % 32); - - return 0; - } /* enet_protocol_handle_send_unsequenced */ - - static int enet_protocol_handle_send_unreliable(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, - enet_uint8 **currentData) { - size_t dataLength; - - if (command->header.channelID >= peer->channelCount || - (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) - { - return -1; - } - - dataLength = ENET_NET_TO_HOST_16(command->sendUnreliable.dataLength); - *currentData += dataLength; - if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { - return -1; - } - - if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) { - return -1; - } - - return 0; - } - - static int enet_protocol_handle_send_fragment(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { - enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, startSequenceNumber, totalLength; - ENetChannel *channel; - enet_uint16 startWindow, currentWindow; - ENetListIterator currentCommand; - ENetIncomingCommand *startCommand = NULL; - - if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { - return -1; - } - - fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength); - *currentData += fragmentLength; - if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { - return -1; - } - - channel = &peer->channels[command->header.channelID]; - startSequenceNumber = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber); - startWindow = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - - if (startSequenceNumber < channel->incomingReliableSequenceNumber) { - startWindow += ENET_PEER_RELIABLE_WINDOWS; - } - - if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { - return 0; - } - - fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber); - fragmentCount = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount); - fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset); - totalLength = ENET_NET_TO_HOST_32(command->sendFragment.totalLength); - - if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || - fragmentNumber >= fragmentCount || - totalLength > host->maximumPacketSize || - fragmentOffset >= totalLength || - fragmentLength > totalLength - fragmentOffset - ) { - return -1; - } - - for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands)); - currentCommand != enet_list_end(&channel->incomingReliableCommands); - currentCommand = enet_list_previous(currentCommand) - ) { - ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; - - if (startSequenceNumber >= channel->incomingReliableSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - continue; - } - } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber <= startSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < startSequenceNumber) { - break; - } - - if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) != - ENET_PROTOCOL_COMMAND_SEND_FRAGMENT || - totalLength != incomingCommand->packet->dataLength || - fragmentCount != incomingCommand->fragmentCount - ) { - return -1; - } - - startCommand = incomingCommand; - break; - } - } - - if (startCommand == NULL) { - ENetProtocol hostCommand = *command; - hostCommand.header.reliableSequenceNumber = startSequenceNumber; - startCommand = enet_peer_queue_incoming_command(peer, &hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount); - if (startCommand == NULL) { - return -1; - } - } - - if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) { - --startCommand->fragmentsRemaining; - startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32)); - - if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) { - fragmentLength = startCommand->packet->dataLength - fragmentOffset; - } - - memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength); - - if (startCommand->fragmentsRemaining <= 0) { - enet_peer_dispatch_incoming_reliable_commands(peer, channel); - } - } - - return 0; - } /* enet_protocol_handle_send_fragment */ - - static int enet_protocol_handle_send_unreliable_fragment(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { - enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, reliableSequenceNumber, startSequenceNumber, totalLength; - enet_uint16 reliableWindow, currentWindow; - ENetChannel *channel; - ENetListIterator currentCommand; - ENetIncomingCommand *startCommand = NULL; - - if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { - return -1; - } - - fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength); - *currentData += fragmentLength; - if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { - return -1; - } - - channel = &peer->channels[command->header.channelID]; - reliableSequenceNumber = command->header.reliableSequenceNumber; - startSequenceNumber = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber); - - reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - - if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - reliableWindow += ENET_PEER_RELIABLE_WINDOWS; - } - - if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { - return 0; - } - - if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && startSequenceNumber <= channel->incomingUnreliableSequenceNumber) { - return 0; - } - - fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber); - fragmentCount = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount); - fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset); - totalLength = ENET_NET_TO_HOST_32(command->sendFragment.totalLength); - - if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || - fragmentNumber >= fragmentCount || - totalLength > host->maximumPacketSize || - fragmentOffset >= totalLength || - fragmentLength > totalLength - fragmentOffset - ) { - return -1; - } - - for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands)); - currentCommand != enet_list_end(&channel->incomingUnreliableCommands); - currentCommand = enet_list_previous(currentCommand) - ) { - ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; - - if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - continue; - } - } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) { - continue; - } - - if (incomingCommand->unreliableSequenceNumber <= startSequenceNumber) { - if (incomingCommand->unreliableSequenceNumber < startSequenceNumber) { - break; - } - - if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) != - ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT || - totalLength != incomingCommand->packet->dataLength || - fragmentCount != incomingCommand->fragmentCount - ) { - return -1; - } - - startCommand = incomingCommand; - break; - } - } - - if (startCommand == NULL) { - startCommand = enet_peer_queue_incoming_command(peer, command, NULL, totalLength, - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount); - if (startCommand == NULL) { - return -1; - } - } - - if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) { - --startCommand->fragmentsRemaining; - startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32)); - - if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) { - fragmentLength = startCommand->packet->dataLength - fragmentOffset; - } - - memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength); - - if (startCommand->fragmentsRemaining <= 0) { - enet_peer_dispatch_incoming_unreliable_commands(peer, channel); - } - } - - return 0; - } /* enet_protocol_handle_send_unreliable_fragment */ - - static int enet_protocol_handle_ping(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { - if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - return -1; - } - - return 0; - } - - static int enet_protocol_handle_bandwidth_limit(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { - 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; - } - - if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) { - peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) { - peer->windowSize = (ENET_MAX(peer->incomingBandwidth, host->outgoingBandwidth) - / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else { - peer->windowSize = (ENET_MIN(peer->incomingBandwidth, host->outgoingBandwidth) - / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } - - if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { - peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { - peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } - - return 0; - } /* enet_protocol_handle_bandwidth_limit */ - - static int enet_protocol_handle_throttle_configure(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { - if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - return -1; - } - - peer->packetThrottleInterval = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleInterval); - peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleAcceleration); - peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleDeceleration); - - return 0; - } - - static int enet_protocol_handle_disconnect(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { - if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE || - peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT - ) { - return 0; - } - - enet_peer_reset_queues(peer); - - if (peer->state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer->state == ENET_PEER_STATE_DISCONNECTING || peer->state == ENET_PEER_STATE_CONNECTING) { - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - } - else if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - if (peer->state == ENET_PEER_STATE_CONNECTION_PENDING) { host->recalculateBandwidthLimits = 1; } - enet_peer_reset(peer); - } - else if (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - enet_protocol_change_state(host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT); - } - else { - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - } - - if (peer->state != ENET_PEER_STATE_DISCONNECTED) { - peer->eventData = ENET_NET_TO_HOST_32(command->disconnect.data); - } - - return 0; - } - - static int enet_protocol_handle_acknowledge(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) { - enet_uint32 roundTripTime, receivedSentTime, receivedReliableSequenceNumber; - ENetProtocolCommand commandNumber; - - if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE) { - return 0; - } - - receivedSentTime = ENET_NET_TO_HOST_16(command->acknowledge.receivedSentTime); - receivedSentTime |= host->serviceTime & 0xFFFF0000; - if ((receivedSentTime & 0x8000) > (host->serviceTime & 0x8000)) { - receivedSentTime -= 0x10000; - } - - if (ENET_TIME_LESS(host->serviceTime, receivedSentTime)) { - return 0; - } - - peer->lastReceiveTime = host->serviceTime; - peer->earliestTimeout = 0; - roundTripTime = ENET_TIME_DIFFERENCE(host->serviceTime, receivedSentTime); - - enet_peer_throttle(peer, roundTripTime); - peer->roundTripTimeVariance -= peer->roundTripTimeVariance / 4; - - if (roundTripTime >= peer->roundTripTime) { - peer->roundTripTime += (roundTripTime - peer->roundTripTime) / 8; - peer->roundTripTimeVariance += (roundTripTime - peer->roundTripTime) / 4; - } else { - peer->roundTripTime -= (peer->roundTripTime - roundTripTime) / 8; - peer->roundTripTimeVariance += (peer->roundTripTime - roundTripTime) / 4; - } - - if (peer->roundTripTime < peer->lowestRoundTripTime) { - peer->lowestRoundTripTime = peer->roundTripTime; - } - - if (peer->roundTripTimeVariance > peer->highestRoundTripTimeVariance) { - peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance; - } - - if (peer->packetThrottleEpoch == 0 || - ENET_TIME_DIFFERENCE(host->serviceTime, peer->packetThrottleEpoch) >= peer->packetThrottleInterval - ) { - peer->lastRoundTripTime = peer->lowestRoundTripTime; - peer->lastRoundTripTimeVariance = peer->highestRoundTripTimeVariance; - peer->lowestRoundTripTime = peer->roundTripTime; - peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance; - peer->packetThrottleEpoch = host->serviceTime; - } - - receivedReliableSequenceNumber = ENET_NET_TO_HOST_16(command->acknowledge.receivedReliableSequenceNumber); - commandNumber = enet_protocol_remove_sent_reliable_command(peer, receivedReliableSequenceNumber, command->header.channelID); - - switch (peer->state) { - case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: - if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT) { - return -1; - } - - enet_protocol_notify_connect(host, peer, event); - break; - - case ENET_PEER_STATE_DISCONNECTING: - if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT) { - return -1; - } - - enet_protocol_notify_disconnect(host, peer, event); - break; - - case ENET_PEER_STATE_DISCONNECT_LATER: - if (enet_list_empty(&peer->outgoingReliableCommands) && - enet_list_empty(&peer->outgoingUnreliableCommands) && - enet_list_empty(&peer->sentReliableCommands)) - { - enet_peer_disconnect(peer, peer->eventData); - } - break; - - default: - break; - } - - return 0; - } /* enet_protocol_handle_acknowledge */ - - static int enet_protocol_handle_verify_connect(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) { - enet_uint32 mtu, windowSize; - size_t channelCount; - - if (peer->state != ENET_PEER_STATE_CONNECTING) { - return 0; - } - - channelCount = ENET_NET_TO_HOST_32(command->verifyConnect.channelCount); - - if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT || - ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleInterval) != peer->packetThrottleInterval || - ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleAcceleration) != peer->packetThrottleAcceleration || - ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleDeceleration) != peer->packetThrottleDeceleration || - command->verifyConnect.connectID != peer->connectID - ) { - peer->eventData = 0; - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - return -1; - } - - enet_protocol_remove_sent_reliable_command(peer, 1, 0xFF); - - if (channelCount < peer->channelCount) { - peer->channelCount = channelCount; - } - - peer->outgoingPeerID = ENET_NET_TO_HOST_16(command->verifyConnect.outgoingPeerID); - peer->incomingSessionID = command->verifyConnect.incomingSessionID; - peer->outgoingSessionID = command->verifyConnect.outgoingSessionID; - - mtu = ENET_NET_TO_HOST_32(command->verifyConnect.mtu); - - if (mtu < ENET_PROTOCOL_MINIMUM_MTU) { - mtu = ENET_PROTOCOL_MINIMUM_MTU; - } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) { - mtu = ENET_PROTOCOL_MAXIMUM_MTU; - } - - if (mtu < peer->mtu) { - peer->mtu = mtu; - } - - windowSize = ENET_NET_TO_HOST_32(command->verifyConnect.windowSize); - if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { - windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } - - if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { - windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } - - if (windowSize < peer->windowSize) { - peer->windowSize = windowSize; - } - - peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.incomingBandwidth); - peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.outgoingBandwidth); - - enet_protocol_notify_connect(host, peer, event); - return 0; - } /* enet_protocol_handle_verify_connect */ - - static int enet_protocol_handle_incoming_commands(ENetHost *host, ENetEvent *event) { - ENetProtocolHeader *header; - ENetProtocol *command; - ENetPeer *peer; - enet_uint8 *currentData; - size_t headerSize; - enet_uint16 peerID, flags; - enet_uint8 sessionID; - - if (host->receivedDataLength < (size_t) &((ENetProtocolHeader *) 0)->sentTime) { - return 0; - } - - header = (ENetProtocolHeader *) host->receivedData; - - peerID = ENET_NET_TO_HOST_16(header->peerID); - sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT; - flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK; - peerID &= ~(ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK); - - headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof(ENetProtocolHeader) : (size_t) &((ENetProtocolHeader *) 0)->sentTime); - if (host->checksum != NULL) { - headerSize += sizeof(enet_uint32); - } - - if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID) { - peer = NULL; - } else if (peerID >= host->peerCount) { - return 0; - } else { - peer = &host->peers[peerID]; - - if (peer->state == ENET_PEER_STATE_DISCONNECTED || - peer->state == ENET_PEER_STATE_ZOMBIE || - ((!in6_equal(host->receivedAddress.host , peer->address.host) || - host->receivedAddress.port != peer->address.port) && - 1 /* no broadcast in ipv6 !in6_equal(peer->address.host , ENET_HOST_BROADCAST)*/) || - (peer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID && - sessionID != peer->incomingSessionID) - ) { - return 0; - } - } - - if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED) { - size_t originalSize; - if (host->compressor.context == NULL || host->compressor.decompress == NULL) { - return 0; - } - - originalSize = host->compressor.decompress(host->compressor.context, - host->receivedData + headerSize, - host->receivedDataLength - headerSize, - host->packetData[1] + headerSize, - sizeof(host->packetData[1]) - headerSize - ); - - if (originalSize <= 0 || originalSize > sizeof(host->packetData[1]) - headerSize) { - return 0; - } - - memcpy(host->packetData[1], header, headerSize); - host->receivedData = host->packetData[1]; - host->receivedDataLength = headerSize + originalSize; - } - - if (host->checksum != NULL) { - enet_uint32 *checksum = (enet_uint32 *) &host->receivedData[headerSize - sizeof(enet_uint32)]; - enet_uint32 desiredChecksum = *checksum; - ENetBuffer buffer; - - *checksum = peer != NULL ? peer->connectID : 0; - - buffer.data = host->receivedData; - buffer.dataLength = host->receivedDataLength; - - if (host->checksum(&buffer, 1) != desiredChecksum) { - return 0; - } - } - - if (peer != NULL) { - peer->address.host = host->receivedAddress.host; - peer->address.port = host->receivedAddress.port; - peer->incomingDataTotal += host->receivedDataLength; - peer->totalDataReceived += host->receivedDataLength; - } - - currentData = host->receivedData + headerSize; - - while (currentData < &host->receivedData[host->receivedDataLength]) { - enet_uint8 commandNumber; - size_t commandSize; - - command = (ENetProtocol *) currentData; - - if (currentData + sizeof(ENetProtocolCommandHeader) > &host->receivedData[host->receivedDataLength]) { - break; - } - - commandNumber = command->header.command & ENET_PROTOCOL_COMMAND_MASK; - if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) { - break; - } - - commandSize = commandSizes[commandNumber]; - if (commandSize == 0 || currentData + commandSize > &host->receivedData[host->receivedDataLength]) { - break; - } - - currentData += commandSize; - - if (peer == NULL && (commandNumber != ENET_PROTOCOL_COMMAND_CONNECT || currentData < &host->receivedData[host->receivedDataLength])) { - break; - } - - command->header.reliableSequenceNumber = ENET_NET_TO_HOST_16(command->header.reliableSequenceNumber); - - switch (commandNumber) { - case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: - if (enet_protocol_handle_acknowledge(host, event, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_CONNECT: - if (peer != NULL) { - goto commandError; - } - peer = enet_protocol_handle_connect(host, header, command); - if (peer == NULL) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT: - if (enet_protocol_handle_verify_connect(host, event, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_DISCONNECT: - if (enet_protocol_handle_disconnect(host, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_PING: - if (enet_protocol_handle_ping(host, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - if (enet_protocol_handle_send_reliable(host, peer, command, ¤tData)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: - if (enet_protocol_handle_send_unreliable(host, peer, command, ¤tData)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: - if (enet_protocol_handle_send_unsequenced(host, peer, command, ¤tData)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: - if (enet_protocol_handle_send_fragment(host, peer, command, ¤tData)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT: - if (enet_protocol_handle_bandwidth_limit(host, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE: - if (enet_protocol_handle_throttle_configure(host, peer, command)) { - goto commandError; - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: - if (enet_protocol_handle_send_unreliable_fragment(host, peer, command, ¤tData)) { - goto commandError; - } - break; - - default: - goto commandError; - } - - if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { - enet_uint16 sentTime; - - if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) { - break; - } - - sentTime = ENET_NET_TO_HOST_16(header->sentTime); - - switch (peer->state) { - case ENET_PEER_STATE_DISCONNECTING: - case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: - case ENET_PEER_STATE_DISCONNECTED: - case ENET_PEER_STATE_ZOMBIE: - break; - - case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: - if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) { - enet_peer_queue_acknowledgement(peer, command, sentTime); - } - break; - - default: - enet_peer_queue_acknowledgement(peer, command, sentTime); - break; - } - } - } - - commandError: - if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { - return 1; - } - - return 0; - } /* enet_protocol_handle_incoming_commands */ - - static int enet_protocol_receive_incoming_commands(ENetHost *host, ENetEvent *event) { - int packets; - - for (packets = 0; packets < 256; ++packets) { - int receivedLength; - ENetBuffer buffer; - - buffer.data = host->packetData[0]; - // buffer.dataLength = sizeof (host->packetData[0]); - buffer.dataLength = host->mtu; - - receivedLength = enet_socket_receive(host->socket, &host->receivedAddress, &buffer, 1); - - if (receivedLength == -2) - continue; - - if (receivedLength < 0) { - return -1; - } - - if (receivedLength == 0) { - return 0; - } - - host->receivedData = host->packetData[0]; - host->receivedDataLength = receivedLength; - - host->totalReceivedData += receivedLength; - host->totalReceivedPackets++; - - if (host->intercept != NULL) { - switch (host->intercept(host, (void *)event)) { - case 1: - if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { - return 1; - } - - continue; - - case -1: - return -1; - - default: - break; - } - } - - switch (enet_protocol_handle_incoming_commands(host, event)) { - case 1: - return 1; - - case -1: - return -1; - - default: - break; - } - } - - return -1; - } /* enet_protocol_receive_incoming_commands */ - - static void enet_protocol_send_acknowledgements(ENetHost *host, ENetPeer *peer) { - ENetProtocol *command = &host->commands[host->commandCount]; - ENetBuffer *buffer = &host->buffers[host->bufferCount]; - ENetAcknowledgement *acknowledgement; - ENetListIterator currentAcknowledgement; - enet_uint16 reliableSequenceNumber; - - currentAcknowledgement = enet_list_begin(&peer->acknowledgements); - - while (currentAcknowledgement != enet_list_end(&peer->acknowledgements)) { - if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || - buffer >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || - peer->mtu - host->packetSize < sizeof(ENetProtocolAcknowledge) - ) { - host->continueSending = 1; - break; - } - - acknowledgement = (ENetAcknowledgement *) currentAcknowledgement; - currentAcknowledgement = enet_list_next(currentAcknowledgement); - - buffer->data = command; - buffer->dataLength = sizeof(ENetProtocolAcknowledge); - host->packetSize += buffer->dataLength; - - reliableSequenceNumber = ENET_HOST_TO_NET_16(acknowledgement->command.header.reliableSequenceNumber); - - command->header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; - command->header.channelID = acknowledgement->command.header.channelID; - command->header.reliableSequenceNumber = reliableSequenceNumber; - command->acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber; - command->acknowledge.receivedSentTime = ENET_HOST_TO_NET_16(acknowledgement->sentTime); - - if ((acknowledgement->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) { - enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); - } - - enet_list_remove(&acknowledgement->acknowledgementList); - enet_free(acknowledgement); - - ++command; - ++buffer; - } - - host->commandCount = command - host->commands; - host->bufferCount = buffer - host->buffers; - } /* enet_protocol_send_acknowledgements */ - - static void enet_protocol_send_unreliable_outgoing_commands(ENetHost *host, ENetPeer *peer) { - ENetProtocol *command = &host->commands[host->commandCount]; - ENetBuffer *buffer = &host->buffers[host->bufferCount]; - ENetOutgoingCommand *outgoingCommand; - ENetListIterator currentCommand; - - currentCommand = enet_list_begin(&peer->outgoingUnreliableCommands); - while (currentCommand != enet_list_end(&peer->outgoingUnreliableCommands)) { - size_t commandSize; - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - commandSize = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK]; - - if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || - buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || - peer->mtu - host->packetSize < commandSize || - (outgoingCommand->packet != NULL && - peer->mtu - host->packetSize < commandSize + outgoingCommand->fragmentLength) - ) { - host->continueSending = 1; - break; - } - - currentCommand = enet_list_next(currentCommand); - - if (outgoingCommand->packet != NULL && outgoingCommand->fragmentOffset == 0) { - peer->packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; - peer->packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; - - if (peer->packetThrottleCounter > peer->packetThrottle) { - enet_uint16 reliableSequenceNumber = outgoingCommand->reliableSequenceNumber; - enet_uint16 unreliableSequenceNumber = outgoingCommand->unreliableSequenceNumber; - for (;;) { - --outgoingCommand->packet->referenceCount; - - if (outgoingCommand->packet->referenceCount == 0) { - enet_packet_destroy(outgoingCommand->packet); - } - - enet_list_remove(&outgoingCommand->outgoingCommandList); - enet_free(outgoingCommand); - - if (currentCommand == enet_list_end(&peer->outgoingUnreliableCommands)) { - break; - } - - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - if (outgoingCommand->reliableSequenceNumber != reliableSequenceNumber || outgoingCommand->unreliableSequenceNumber != unreliableSequenceNumber) { - break; - } - - currentCommand = enet_list_next(currentCommand); - } - - continue; - } - } - - buffer->data = command; - buffer->dataLength = commandSize; - host->packetSize += buffer->dataLength; - *command = outgoingCommand->command; - enet_list_remove(&outgoingCommand->outgoingCommandList); - - if (outgoingCommand->packet != NULL) { - ++buffer; - - buffer->data = outgoingCommand->packet->data + outgoingCommand->fragmentOffset; - buffer->dataLength = outgoingCommand->fragmentLength; - - host->packetSize += buffer->dataLength; - - enet_list_insert(enet_list_end(&peer->sentUnreliableCommands), outgoingCommand); - } else { - enet_free(outgoingCommand); - } - - ++command; - ++buffer; - } - - host->commandCount = command - host->commands; - host->bufferCount = buffer - host->buffers; - - if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER && - enet_list_empty(&peer->outgoingReliableCommands) && - enet_list_empty(&peer->outgoingUnreliableCommands) && - enet_list_empty(&peer->sentReliableCommands)) - { - enet_peer_disconnect(peer, peer->eventData); - } - } /* enet_protocol_send_unreliable_outgoing_commands */ - - static int enet_protocol_check_timeouts(ENetHost *host, ENetPeer *peer, ENetEvent *event) { - ENetOutgoingCommand *outgoingCommand; - ENetListIterator currentCommand, insertPosition; - - currentCommand = enet_list_begin(&peer->sentReliableCommands); - insertPosition = enet_list_begin(&peer->outgoingReliableCommands); - - while (currentCommand != enet_list_end(&peer->sentReliableCommands)) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - - currentCommand = enet_list_next(currentCommand); - - if (ENET_TIME_DIFFERENCE(host->serviceTime, outgoingCommand->sentTime) < outgoingCommand->roundTripTimeout) { - continue; - } - - if (peer->earliestTimeout == 0 || ENET_TIME_LESS(outgoingCommand->sentTime, peer->earliestTimeout)) { - peer->earliestTimeout = outgoingCommand->sentTime; - } - - if (peer->earliestTimeout != 0 && - (ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMaximum || - (outgoingCommand->roundTripTimeout >= outgoingCommand->roundTripTimeoutLimit && - ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMinimum)) - ) { - enet_protocol_notify_disconnect_timeout(host, peer, event); - return 1; - } - - if (outgoingCommand->packet != NULL) { - peer->reliableDataInTransit -= outgoingCommand->fragmentLength; - } - - ++peer->packetsLost; - ++peer->totalPacketsLost; - - /* Replaced exponential backoff time with something more linear */ - /* Source: http://lists.cubik.org/pipermail/enet-discuss/2014-May/002308.html */ - outgoingCommand->roundTripTimeout = peer->roundTripTime + 4 * peer->roundTripTimeVariance; - outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout; - - enet_list_insert(insertPosition, enet_list_remove(&outgoingCommand->outgoingCommandList)); - - if (currentCommand == enet_list_begin(&peer->sentReliableCommands) && !enet_list_empty(&peer->sentReliableCommands)) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; - } - } - - return 0; - } /* enet_protocol_check_timeouts */ - - static int enet_protocol_send_reliable_outgoing_commands(ENetHost *host, ENetPeer *peer) { - ENetProtocol *command = &host->commands[host->commandCount]; - ENetBuffer *buffer = &host->buffers[host->bufferCount]; - ENetOutgoingCommand *outgoingCommand; - ENetListIterator currentCommand; - ENetChannel *channel; - enet_uint16 reliableWindow; - size_t commandSize; - int windowExceeded = 0, windowWrap = 0, canPing = 1; - - currentCommand = enet_list_begin(&peer->outgoingReliableCommands); - - while (currentCommand != enet_list_end(&peer->outgoingReliableCommands)) { - outgoingCommand = (ENetOutgoingCommand *) currentCommand; - - channel = outgoingCommand->command.header.channelID < peer->channelCount ? &peer->channels[outgoingCommand->command.header.channelID] : NULL; - reliableWindow = outgoingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - if (channel != NULL) { - if (!windowWrap && - outgoingCommand->sendAttempts < 1 && - !(outgoingCommand->reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && - (channel->reliableWindows[(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) - % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || - channel->usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) - | (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))) - ) { - windowWrap = 1; - } - - if (windowWrap) { - currentCommand = enet_list_next(currentCommand); - continue; - } - } - - if (outgoingCommand->packet != NULL) { - if (!windowExceeded) { - enet_uint32 windowSize = (peer->packetThrottle * peer->windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; - - if (peer->reliableDataInTransit + outgoingCommand->fragmentLength > ENET_MAX(windowSize, peer->mtu)) { - windowExceeded = 1; - } - } - if (windowExceeded) { - currentCommand = enet_list_next(currentCommand); - - continue; - } - } - - canPing = 0; - - commandSize = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK]; - if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || - buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || - peer->mtu - host->packetSize < commandSize || - (outgoingCommand->packet != NULL && - (enet_uint16) (peer->mtu - host->packetSize) < (enet_uint16) (commandSize + outgoingCommand->fragmentLength)) - ) { - host->continueSending = 1; - break; - } - - currentCommand = enet_list_next(currentCommand); - - if (channel != NULL && outgoingCommand->sendAttempts < 1) { - channel->usedReliableWindows |= 1 << reliableWindow; - ++channel->reliableWindows[reliableWindow]; - } - - ++outgoingCommand->sendAttempts; - - if (outgoingCommand->roundTripTimeout == 0) { - outgoingCommand->roundTripTimeout = peer->roundTripTime + 4 * peer->roundTripTimeVariance; - outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout; - } - - if (enet_list_empty(&peer->sentReliableCommands)) { - peer->nextTimeout = host->serviceTime + outgoingCommand->roundTripTimeout; - } - - enet_list_insert(enet_list_end(&peer->sentReliableCommands), enet_list_remove(&outgoingCommand->outgoingCommandList)); - - outgoingCommand->sentTime = host->serviceTime; - - buffer->data = command; - buffer->dataLength = commandSize; - - host->packetSize += buffer->dataLength; - host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; - - *command = outgoingCommand->command; - - if (outgoingCommand->packet != NULL) { - ++buffer; - buffer->data = outgoingCommand->packet->data + outgoingCommand->fragmentOffset; - buffer->dataLength = outgoingCommand->fragmentLength; - host->packetSize += outgoingCommand->fragmentLength; - peer->reliableDataInTransit += outgoingCommand->fragmentLength; - } - - ++peer->packetsSent; - ++peer->totalPacketsSent; - - ++command; - ++buffer; - } - - host->commandCount = command - host->commands; - host->bufferCount = buffer - host->buffers; - - return canPing; - } /* enet_protocol_send_reliable_outgoing_commands */ - - static int enet_protocol_send_outgoing_commands(ENetHost *host, ENetEvent *event, int checkForTimeouts) { - enet_uint8 headerData[sizeof(ENetProtocolHeader) + sizeof(enet_uint32)]; - ENetProtocolHeader *header = (ENetProtocolHeader *) headerData; - ENetPeer *currentPeer; - int sentLength; - size_t shouldCompress = 0; - host->continueSending = 1; - - while (host->continueSending) - for (host->continueSending = 0, currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED || currentPeer->state == ENET_PEER_STATE_ZOMBIE) { - continue; - } - - host->headerFlags = 0; - host->commandCount = 0; - host->bufferCount = 1; - host->packetSize = sizeof(ENetProtocolHeader); - - if (!enet_list_empty(¤tPeer->acknowledgements)) { - enet_protocol_send_acknowledgements(host, currentPeer); - } - - if (checkForTimeouts != 0 && - !enet_list_empty(¤tPeer->sentReliableCommands) && - ENET_TIME_GREATER_EQUAL(host->serviceTime, currentPeer->nextTimeout) && - enet_protocol_check_timeouts(host, currentPeer, event) == 1 - ) { - if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { - return 1; - } else { - continue; - } - } - - if ((enet_list_empty(¤tPeer->outgoingReliableCommands) || - enet_protocol_send_reliable_outgoing_commands(host, currentPeer)) && - enet_list_empty(¤tPeer->sentReliableCommands) && - ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->lastReceiveTime) >= currentPeer->pingInterval && - currentPeer->mtu - host->packetSize >= sizeof(ENetProtocolPing) - ) { - enet_peer_ping(currentPeer); - enet_protocol_send_reliable_outgoing_commands(host, currentPeer); - } - - if (!enet_list_empty(¤tPeer->outgoingUnreliableCommands)) { - enet_protocol_send_unreliable_outgoing_commands(host, currentPeer); - } - - if (host->commandCount == 0) { - continue; - } - - if (currentPeer->packetLossEpoch == 0) { - currentPeer->packetLossEpoch = host->serviceTime; - } else if (ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL && currentPeer->packetsSent > 0) { - enet_uint32 packetLoss = currentPeer->packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer->packetsSent; - - #ifdef ENET_DEBUG - printf( - "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer->incomingPeerID, - currentPeer->packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, - currentPeer->packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer->roundTripTime, currentPeer->roundTripTimeVariance, - currentPeer->packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, - enet_list_size(¤tPeer->outgoingReliableCommands), - enet_list_size(¤tPeer->outgoingUnreliableCommands), - currentPeer->channels != NULL ? enet_list_size( ¤tPeer->channels->incomingReliableCommands) : 0, - currentPeer->channels != NULL ? enet_list_size(¤tPeer->channels->incomingUnreliableCommands) : 0 - ); - #endif - - currentPeer->packetLossVariance -= currentPeer->packetLossVariance / 4; - - if (packetLoss >= currentPeer->packetLoss) { - currentPeer->packetLoss += (packetLoss - currentPeer->packetLoss) / 8; - currentPeer->packetLossVariance += (packetLoss - currentPeer->packetLoss) / 4; - } else { - currentPeer->packetLoss -= (currentPeer->packetLoss - packetLoss) / 8; - currentPeer->packetLossVariance += (currentPeer->packetLoss - packetLoss) / 4; - } - - currentPeer->packetLossEpoch = host->serviceTime; - currentPeer->packetsSent = 0; - currentPeer->packetsLost = 0; - } - - host->buffers->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); - } else { - host->buffers->dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; - } - - shouldCompress = 0; - if (host->compressor.context != NULL && host->compressor.compress != NULL) { - size_t originalSize = host->packetSize - sizeof(ENetProtocolHeader), - compressedSize = host->compressor.compress(host->compressor.context, &host->buffers[1], host->bufferCount - 1, originalSize, host->packetData[1], originalSize); - if (compressedSize > 0 && compressedSize < originalSize) { - 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); - #endif - } - } - - if (currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID) { - host->headerFlags |= currentPeer->outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT; - } - header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags); - if (host->checksum != NULL) { - enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers->dataLength]; - *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0; - host->buffers->dataLength += sizeof(enet_uint32); - *checksum = host->checksum(host->buffers, host->bufferCount); - } - - if (shouldCompress > 0) { - host->buffers[1].data = host->packetData[1]; - host->buffers[1].dataLength = shouldCompress; - host->bufferCount = 2; - } - - currentPeer->lastSendTime = host->serviceTime; - sentLength = enet_socket_send(host->socket, ¤tPeer->address, host->buffers, host->bufferCount); - enet_protocol_remove_sent_unreliable_commands(currentPeer); - - if (sentLength < 0) { - return -1; - } - - host->totalSentData += sentLength; - currentPeer->totalDataSent += sentLength; - host->totalSentPackets++; - } - - return 0; - } /* enet_protocol_send_outgoing_commands */ - - /** Sends any queued packets on the host specified to its designated peers. - * - * @param host host to flush - * @remarks this function need only be used in circumstances where one wishes to send queued packets earlier than in a call to enet_host_service(). - * @ingroup host - */ - void enet_host_flush(ENetHost *host) { - host->serviceTime = enet_time_get(); - enet_protocol_send_outgoing_commands(host, NULL, 0); - } - - /** Checks for any queued events on the host and dispatches one if available. - * - * @param host host to check for events - * @param event an event structure where event details will be placed if available - * @retval > 0 if an event was dispatched - * @retval 0 if no events are available - * @retval < 0 on failure - * @ingroup host - */ - int enet_host_check_events(ENetHost *host, ENetEvent *event) { - if (event == NULL) { return -1; } - - event->type = ENET_EVENT_TYPE_NONE; - event->peer = NULL; - event->packet = NULL; - - return enet_protocol_dispatch_incoming_commands(host, event); - } - - /** Waits for events on the host specified and shuttles packets between - * the host and its peers. - * - * @param host host to service - * @param event an event structure where event details will be placed if one occurs - * if event == NULL then no events will be delivered - * @param timeout number of milliseconds that ENet should wait for events - * @retval > 0 if an event occurred within the specified time limit - * @retval 0 if no event occurred - * @retval < 0 on failure - * @remarks enet_host_service should be called fairly regularly for adequate performance - * @ingroup host - */ - int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) { - enet_uint32 waitCondition; - - if (event != NULL) { - event->type = ENET_EVENT_TYPE_NONE; - event->peer = NULL; - event->packet = NULL; - - switch (enet_protocol_dispatch_incoming_commands(host, event)) { - case 1: - return 1; - - case -1: - #ifdef ENET_DEBUG - perror("Error dispatching incoming packets"); - #endif - - return -1; - - default: - break; - } - } - - host->serviceTime = enet_time_get(); - timeout += host->serviceTime; - - do { - if (ENET_TIME_DIFFERENCE(host->serviceTime, host->bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) { - enet_host_bandwidth_throttle(host); - } - - switch (enet_protocol_send_outgoing_commands(host, event, 1)) { - case 1: - return 1; - - case -1: - #ifdef ENET_DEBUG - perror("Error sending outgoing packets"); - #endif - - return -1; - - default: - break; - } - - switch (enet_protocol_receive_incoming_commands(host, event)) { - case 1: - return 1; - - case -1: - #ifdef ENET_DEBUG - perror("Error receiving incoming packets"); - #endif - - return -1; - - default: - break; - } - - switch (enet_protocol_send_outgoing_commands(host, event, 1)) { - case 1: - return 1; - - case -1: - #ifdef ENET_DEBUG - perror("Error sending outgoing packets"); - #endif - - return -1; - - default: - break; - } - - if (event != NULL) { - switch (enet_protocol_dispatch_incoming_commands(host, event)) { - case 1: - return 1; - - case -1: - #ifdef ENET_DEBUG - perror("Error dispatching incoming packets"); - #endif - - return -1; - - default: - break; - } - } - - if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) { - return 0; - } - - do { - host->serviceTime = enet_time_get(); - - if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) { - return 0; - } - - waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; - if (enet_socket_wait(host->socket, &waitCondition, ENET_TIME_DIFFERENCE(timeout, host->serviceTime)) != 0) { - return -1; - } - } while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); - - host->serviceTime = enet_time_get(); - } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE); - - return 0; - } /* enet_host_service */ - - -// =======================================================================// -// ! -// ! Peer -// ! -// =======================================================================// - - /** Configures throttle parameter for a peer. - * - * Unreliable packets are dropped by ENet in response to the varying conditions - * of the Internet connection to the peer. The throttle represents a probability - * that an unreliable packet should not be dropped and thus sent by ENet to the peer. - * The lowest mean round trip time from the sending of a reliable packet to the - * receipt of its acknowledgement is measured over an amount of time specified by - * the interval parameter in milliseconds. If a measured round trip time happens to - * be significantly less than the mean round trip time measured over the interval, - * then the throttle probability is increased to allow more traffic by an amount - * specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE - * constant. If a measured round trip time happens to be significantly greater than - * the mean round trip time measured over the interval, then the throttle probability - * is decreased to limit traffic by an amount specified in the deceleration parameter, which - * is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has - * a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by - * ENet, and so 100% of all unreliable packets will be sent. When the throttle has a - * value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable - * packets will be sent. Intermediate values for the throttle represent intermediate - * probabilities between 0% and 100% of unreliable packets being sent. The bandwidth - * limits of the local and foreign hosts are taken into account to determine a - * sensible limit for the throttle probability above which it should not raise even in - * the best of conditions. - * - * @param peer peer to configure - * @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL. - * @param acceleration rate at which to increase the throttle probability as mean RTT declines - * @param deceleration rate at which to decrease the throttle probability as mean RTT increases - */ - void enet_peer_throttle_configure(ENetPeer *peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration) { - ENetProtocol command; - - peer->packetThrottleInterval = interval; - peer->packetThrottleAcceleration = acceleration; - peer->packetThrottleDeceleration = deceleration; - - command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - command.header.channelID = 0xFF; - - command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32(interval); - command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32(acceleration); - command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32(deceleration); - - enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); - } - - int enet_peer_throttle(ENetPeer *peer, enet_uint32 rtt) { - if (peer->lastRoundTripTime <= peer->lastRoundTripTimeVariance) { - peer->packetThrottle = peer->packetThrottleLimit; - } - else if (rtt < peer->lastRoundTripTime) { - peer->packetThrottle += peer->packetThrottleAcceleration; - - if (peer->packetThrottle > peer->packetThrottleLimit) { - peer->packetThrottle = peer->packetThrottleLimit; - } - - return 1; - } - else if (rtt > peer->lastRoundTripTime + 2 * peer->lastRoundTripTimeVariance) { - if (peer->packetThrottle > peer->packetThrottleDeceleration) { - peer->packetThrottle -= peer->packetThrottleDeceleration; - } else { - peer->packetThrottle = 0; - } - - return -1; - } - - return 0; - } - - /* Extended functionality for easier binding in other programming languages */ - enet_uint32 enet_host_get_peers_count(ENetHost *host) { - return host->connectedPeers; - } - - enet_uint32 enet_host_get_packets_sent(ENetHost *host) { - return host->totalSentPackets; - } - - enet_uint32 enet_host_get_packets_received(ENetHost *host) { - return host->totalReceivedPackets; - } - - enet_uint32 enet_host_get_bytes_sent(ENetHost *host) { - return host->totalSentData; - } - - enet_uint32 enet_host_get_bytes_received(ENetHost *host) { - return host->totalReceivedData; - } - - /** Gets received data buffer. Returns buffer length. - * @param host host to access recevie buffer - * @param data ouput parameter for recevied data - * @retval buffer length - */ - enet_uint32 enet_host_get_received_data(ENetHost *host, /*out*/ enet_uint8** data) { - *data = host->receivedData; - return host->receivedDataLength; - } - - enet_uint32 enet_host_get_mtu(ENetHost *host) { - return host->mtu; - } - - enet_uint32 enet_peer_get_id(ENetPeer *peer) { - return peer->connectID; - } - - enet_uint32 enet_peer_get_ip(ENetPeer *peer, char *ip, size_t ipLength) { - return enet_address_get_host_ip(&peer->address, ip, ipLength); - } - - enet_uint16 enet_peer_get_port(ENetPeer *peer) { - return peer->address.port; - } - - ENetPeerState enet_peer_get_state(ENetPeer *peer) { - return peer->state; - } - - enet_uint32 enet_peer_get_rtt(ENetPeer *peer) { - return peer->roundTripTime; - } - - enet_uint64 enet_peer_get_packets_sent(ENetPeer *peer) { - return peer->totalPacketsSent; - } - - enet_uint32 enet_peer_get_packets_lost(ENetPeer *peer) { - return peer->totalPacketsLost; - } - - enet_uint64 enet_peer_get_bytes_sent(ENetPeer *peer) { - return peer->totalDataSent; - } - - enet_uint64 enet_peer_get_bytes_received(ENetPeer *peer) { - return peer->totalDataReceived; - } - - void * enet_peer_get_data(ENetPeer *peer) { - return (void *) peer->data; - } - - void enet_peer_set_data(ENetPeer *peer, const void *data) { - peer->data = (enet_uint32 *) data; - } - - void * enet_packet_get_data(ENetPacket *packet) { - return (void *) packet->data; - } - - enet_uint32 enet_packet_get_length(ENetPacket *packet) { - return packet->dataLength; - } - - void enet_packet_set_free_callback(ENetPacket *packet, void *callback) { - packet->freeCallback = (ENetPacketFreeCallback)callback; - } - - /** Queues a packet to be sent. - * @param peer destination for the packet - * @param channelID channel on which to send - * @param packet packet to send - * @retval 0 on success - * @retval < 0 on failure - */ - int enet_peer_send(ENetPeer *peer, enet_uint8 channelID, ENetPacket *packet) { - ENetChannel *channel = &peer->channels[channelID]; - ENetProtocol command; - size_t fragmentLength; - - if (peer->state != ENET_PEER_STATE_CONNECTED || channelID >= peer->channelCount || packet->dataLength > peer->host->maximumPacketSize) { - return -1; - } - - fragmentLength = peer->mtu - sizeof(ENetProtocolHeader) - sizeof(ENetProtocolSendFragment); - if (peer->host->checksum != NULL) { - fragmentLength -= sizeof(enet_uint32); - } - - if (packet->dataLength > fragmentLength) { - enet_uint32 fragmentCount = (packet->dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; - enet_uint8 commandNumber; - enet_uint16 startSequenceNumber; - ENetList fragments; - ENetOutgoingCommand *fragment; - - if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) { - return -1; - } - - if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == - ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && - channel->outgoingUnreliableSequenceNumber < 0xFFFF) - { - commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT; - startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingUnreliableSequenceNumber + 1); - } else { - commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingReliableSequenceNumber + 1); - } - - enet_list_clear(&fragments); - - for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet->dataLength; ++fragmentNumber, fragmentOffset += fragmentLength) { - if (packet->dataLength - fragmentOffset < fragmentLength) { - fragmentLength = packet->dataLength - fragmentOffset; - } - - fragment = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand)); - - if (fragment == NULL) { - while (!enet_list_empty(&fragments)) { - fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments)); - - enet_free(fragment); - } - - return -1; - } - - fragment->fragmentOffset = fragmentOffset; - fragment->fragmentLength = fragmentLength; - fragment->packet = packet; - fragment->command.header.command = commandNumber; - fragment->command.header.channelID = channelID; - - fragment->command.sendFragment.startSequenceNumber = startSequenceNumber; - - fragment->command.sendFragment.dataLength = ENET_HOST_TO_NET_16(fragmentLength); - fragment->command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32(fragmentCount); - fragment->command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32(fragmentNumber); - fragment->command.sendFragment.totalLength = ENET_HOST_TO_NET_32(packet->dataLength); - fragment->command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32(fragmentOffset); - - enet_list_insert(enet_list_end(&fragments), fragment); - } - - packet->referenceCount += fragmentNumber; - - while (!enet_list_empty(&fragments)) { - fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments)); - enet_peer_setup_outgoing_command(peer, fragment); - } - - return 0; - } - - command.header.channelID = channelID; - - if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED) { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; - command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); - } - else if (packet->flags & ENET_PACKET_FLAG_RELIABLE || channel->outgoingUnreliableSequenceNumber >= 0xFFFF) { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - command.sendReliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); - } - else { - command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; - command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); - } - - if (enet_peer_queue_outgoing_command(peer, &command, packet, 0, packet->dataLength) == NULL) { - return -1; - } - - return 0; - } // enet_peer_send - - /** Attempts to dequeue any incoming queued packet. - * @param peer peer to dequeue packets from - * @param channelID holds the channel ID of the channel the packet was received on success - * @returns a pointer to the packet, or NULL if there are no available incoming queued packets - */ - ENetPacket * enet_peer_receive(ENetPeer *peer, enet_uint8 *channelID) { - ENetIncomingCommand *incomingCommand; - ENetPacket *packet; - - if (enet_list_empty(&peer->dispatchedCommands)) { - return NULL; - } - - incomingCommand = (ENetIncomingCommand *) enet_list_remove(enet_list_begin(&peer->dispatchedCommands)); - - if (channelID != NULL) { - *channelID = incomingCommand->command.header.channelID; - } - - packet = incomingCommand->packet; - --packet->referenceCount; - - if (incomingCommand->fragments != NULL) { - enet_free(incomingCommand->fragments); - } - - enet_free(incomingCommand); - peer->totalWaitingData -= packet->dataLength; - - return packet; - } - - static void enet_peer_reset_outgoing_commands(ENetList *queue) { - ENetOutgoingCommand *outgoingCommand; - - while (!enet_list_empty(queue)) { - outgoingCommand = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(queue)); - - if (outgoingCommand->packet != NULL) { - --outgoingCommand->packet->referenceCount; - - if (outgoingCommand->packet->referenceCount == 0) { - enet_packet_destroy(outgoingCommand->packet); - } - } - - enet_free(outgoingCommand); - } - } - - static void enet_peer_remove_incoming_commands(ENetList *queue, ENetListIterator startCommand, ENetListIterator endCommand) { - ENetListIterator currentCommand; - - for (currentCommand = startCommand; currentCommand != endCommand;) { - ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; - - currentCommand = enet_list_next(currentCommand); - enet_list_remove(&incomingCommand->incomingCommandList); - - if (incomingCommand->packet != NULL) { - --incomingCommand->packet->referenceCount; - - if (incomingCommand->packet->referenceCount == 0) { - enet_packet_destroy(incomingCommand->packet); - } - } - - if (incomingCommand->fragments != NULL) { - enet_free(incomingCommand->fragments); - } - - enet_free(incomingCommand); - } - } - - static void enet_peer_reset_incoming_commands(ENetList *queue) { - enet_peer_remove_incoming_commands(queue, enet_list_begin(queue), enet_list_end(queue)); - } - - void enet_peer_reset_queues(ENetPeer *peer) { - ENetChannel *channel; - - if (peer->needsDispatch) { - enet_list_remove(&peer->dispatchList); - peer->needsDispatch = 0; - } - - while (!enet_list_empty(&peer->acknowledgements)) { - enet_free(enet_list_remove(enet_list_begin(&peer->acknowledgements))); - } - - enet_peer_reset_outgoing_commands(&peer->sentReliableCommands); - enet_peer_reset_outgoing_commands(&peer->sentUnreliableCommands); - enet_peer_reset_outgoing_commands(&peer->outgoingReliableCommands); - enet_peer_reset_outgoing_commands(&peer->outgoingUnreliableCommands); - enet_peer_reset_incoming_commands(&peer->dispatchedCommands); - - if (peer->channels != NULL && peer->channelCount > 0) { - for (channel = peer->channels; channel < &peer->channels[peer->channelCount]; ++channel) { - enet_peer_reset_incoming_commands(&channel->incomingReliableCommands); - enet_peer_reset_incoming_commands(&channel->incomingUnreliableCommands); - } - - enet_free(peer->channels); - } - - peer->channels = NULL; - peer->channelCount = 0; - } - - void enet_peer_on_connect(ENetPeer *peer) { - if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - if (peer->incomingBandwidth != 0) { - ++peer->host->bandwidthLimitedPeers; - } - - ++peer->host->connectedPeers; - } - } - - void enet_peer_on_disconnect(ENetPeer *peer) { - if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { - if (peer->incomingBandwidth != 0) { - --peer->host->bandwidthLimitedPeers; - } - - --peer->host->connectedPeers; - } - } - - /** Forcefully disconnects a peer. - * @param peer peer to forcefully disconnect - * @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout - * on its connection to the local host. - */ - void enet_peer_reset(ENetPeer *peer) { - enet_peer_on_disconnect(peer); - - // We don't want to reset connectID here, otherwise, we can't get it in the Disconnect event - // peer->connectID = 0; - peer->outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; - peer->state = ENET_PEER_STATE_DISCONNECTED; - peer->incomingBandwidth = 0; - peer->outgoingBandwidth = 0; - peer->incomingBandwidthThrottleEpoch = 0; - peer->outgoingBandwidthThrottleEpoch = 0; - peer->incomingDataTotal = 0; - peer->totalDataReceived = 0; - peer->outgoingDataTotal = 0; - peer->totalDataSent = 0; - peer->lastSendTime = 0; - peer->lastReceiveTime = 0; - peer->nextTimeout = 0; - peer->earliestTimeout = 0; - peer->packetLossEpoch = 0; - peer->packetsSent = 0; - peer->totalPacketsSent = 0; - peer->packetsLost = 0; - peer->totalPacketsLost = 0; - peer->packetLoss = 0; - peer->packetLossVariance = 0; - peer->packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE; - peer->packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE; - peer->packetThrottleCounter = 0; - peer->packetThrottleEpoch = 0; - peer->packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; - peer->packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; - peer->packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; - peer->pingInterval = ENET_PEER_PING_INTERVAL; - peer->timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; - peer->timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; - peer->timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; - peer->lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; - peer->lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; - peer->lastRoundTripTimeVariance = 0; - peer->highestRoundTripTimeVariance = 0; - peer->roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; - peer->roundTripTimeVariance = 0; - peer->mtu = peer->host->mtu; - peer->reliableDataInTransit = 0; - peer->outgoingReliableSequenceNumber = 0; - peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - peer->incomingUnsequencedGroup = 0; - peer->outgoingUnsequencedGroup = 0; - peer->eventData = 0; - peer->totalWaitingData = 0; - - memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow)); - enet_peer_reset_queues(peer); - } - - /** Sends a ping request to a peer. - * @param peer destination for the ping request - * @remarks ping requests factor into the mean round trip time as designated by the - * roundTripTime field in the ENetPeer structure. ENet automatically pings all connected - * peers at regular intervals, however, this function may be called to ensure more - * frequent ping requests. - */ - void enet_peer_ping(ENetPeer *peer) { - ENetProtocol command; - - if (peer->state != ENET_PEER_STATE_CONNECTED) { - return; - } - - command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - command.header.channelID = 0xFF; - - enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); - } - - /** Sets the interval at which pings will be sent to a peer. - * - * Pings are used both to monitor the liveness of the connection and also to dynamically - * adjust the throttle during periods of low traffic so that the throttle has reasonable - * responsiveness during traffic spikes. - * - * @param peer the peer to adjust - * @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; - } - - /** Sets the timeout parameters for a peer. - * - * The timeout parameter control how and when a peer will timeout from a failure to acknowledge - * reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable - * packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, - * the timeout will be doubled until it reaches a set limit. If the timeout is thus at this - * limit and reliable packets have been sent but not acknowledged within a certain minimum time - * period, the peer will be disconnected. Alternatively, if reliable packets have been sent - * but not acknowledged for a certain maximum time period, the peer will be disconnected regardless - * of the current timeout limit value. - * - * @param peer the peer to adjust - * @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 - * @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 - * @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 - */ - - 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; - } - - /** Force an immediate disconnection from a peer. - * @param peer peer to disconnect - * @param data data describing the disconnection - * @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not - * guaranteed to receive the disconnect notification, and is reset immediately upon - * return from this function. - */ - void enet_peer_disconnect_now(ENetPeer *peer, enet_uint32 data) { - ENetProtocol command; - - if (peer->state == ENET_PEER_STATE_DISCONNECTED) { - return; - } - - if (peer->state != ENET_PEER_STATE_ZOMBIE && peer->state != ENET_PEER_STATE_DISCONNECTING) { - enet_peer_reset_queues(peer); - - command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; - command.header.channelID = 0xFF; - command.disconnect.data = ENET_HOST_TO_NET_32(data); - - enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); - enet_host_flush(peer->host); - } - - enet_peer_reset(peer); - } - - /** Request a disconnection from a peer. - * @param peer peer to request a disconnection - * @param data data describing the disconnection - * @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() - * once the disconnection is complete. - */ - void enet_peer_disconnect(ENetPeer *peer, enet_uint32 data) { - ENetProtocol command; - - if (peer->state == ENET_PEER_STATE_DISCONNECTING || - peer->state == ENET_PEER_STATE_DISCONNECTED || - peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT || - peer->state == ENET_PEER_STATE_ZOMBIE - ) { - return; - } - - enet_peer_reset_queues(peer); - - command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT; - command.header.channelID = 0xFF; - command.disconnect.data = ENET_HOST_TO_NET_32(data); - - if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { - command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - } else { - command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; - } - - enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); - - if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { - enet_peer_on_disconnect(peer); - - peer->state = ENET_PEER_STATE_DISCONNECTING; - } else { - enet_host_flush(peer->host); - enet_peer_reset(peer); - } - } - - /** Request a disconnection from a peer, but only after all queued outgoing packets are sent. - * @param peer peer to request a disconnection - * @param data data describing the disconnection - * @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() - * once the disconnection is complete. - */ - void enet_peer_disconnect_later(ENetPeer *peer, enet_uint32 data) { - if ((peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) && - !(enet_list_empty(&peer->outgoingReliableCommands) && - enet_list_empty(&peer->outgoingUnreliableCommands) && - enet_list_empty(&peer->sentReliableCommands)) - ) { - peer->state = ENET_PEER_STATE_DISCONNECT_LATER; - peer->eventData = data; - } else { - enet_peer_disconnect(peer, data); - } - } - - ENetAcknowledgement *enet_peer_queue_acknowledgement(ENetPeer *peer, const ENetProtocol *command, enet_uint16 sentTime) { - ENetAcknowledgement *acknowledgement; - - if (command->header.channelID < peer->channelCount) { - ENetChannel *channel = &peer->channels[command->header.channelID]; - enet_uint16 reliableWindow = command->header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - enet_uint16 currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - - if (command->header.reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - reliableWindow += ENET_PEER_RELIABLE_WINDOWS; - } - - if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS) { - return NULL; - } - } - - acknowledgement = (ENetAcknowledgement *) enet_malloc(sizeof(ENetAcknowledgement)); - if (acknowledgement == NULL) { - return NULL; - } - - peer->outgoingDataTotal += sizeof(ENetProtocolAcknowledge); - - acknowledgement->sentTime = sentTime; - acknowledgement->command = *command; - - enet_list_insert(enet_list_end(&peer->acknowledgements), acknowledgement); - return acknowledgement; - } - - void enet_peer_setup_outgoing_command(ENetPeer *peer, ENetOutgoingCommand *outgoingCommand) { - ENetChannel *channel = &peer->channels[outgoingCommand->command.header.channelID]; - peer->outgoingDataTotal += enet_protocol_command_size(outgoingCommand->command.header.command) + outgoingCommand->fragmentLength; - - if (outgoingCommand->command.header.channelID == 0xFF) { - ++peer->outgoingReliableSequenceNumber; - - outgoingCommand->reliableSequenceNumber = peer->outgoingReliableSequenceNumber; - outgoingCommand->unreliableSequenceNumber = 0; - } - else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - ++channel->outgoingReliableSequenceNumber; - channel->outgoingUnreliableSequenceNumber = 0; - - outgoingCommand->reliableSequenceNumber = channel->outgoingReliableSequenceNumber; - outgoingCommand->unreliableSequenceNumber = 0; - } - else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) { - ++peer->outgoingUnsequencedGroup; - - outgoingCommand->reliableSequenceNumber = 0; - outgoingCommand->unreliableSequenceNumber = 0; - } - else { - if (outgoingCommand->fragmentOffset == 0) { - ++channel->outgoingUnreliableSequenceNumber; - } - - outgoingCommand->reliableSequenceNumber = channel->outgoingReliableSequenceNumber; - outgoingCommand->unreliableSequenceNumber = channel->outgoingUnreliableSequenceNumber; - } - - outgoingCommand->sendAttempts = 0; - outgoingCommand->sentTime = 0; - outgoingCommand->roundTripTimeout = 0; - outgoingCommand->roundTripTimeoutLimit = 0; - outgoingCommand->command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->reliableSequenceNumber); - - switch (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) { - case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: - outgoingCommand->command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->unreliableSequenceNumber); - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: - outgoingCommand->command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16(peer->outgoingUnsequencedGroup); - break; - - default: - break; - } - - if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { - enet_list_insert(enet_list_end(&peer->outgoingReliableCommands), outgoingCommand); - } else { - enet_list_insert(enet_list_end(&peer->outgoingUnreliableCommands), outgoingCommand); - } - } - - ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *peer, const ENetProtocol *command, ENetPacket *packet, enet_uint32 offset, enet_uint16 length) { - ENetOutgoingCommand *outgoingCommand = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand)); - - if (outgoingCommand == NULL) { - return NULL; - } - - outgoingCommand->command = *command; - outgoingCommand->fragmentOffset = offset; - outgoingCommand->fragmentLength = length; - outgoingCommand->packet = packet; - if (packet != NULL) { - ++packet->referenceCount; - } - - enet_peer_setup_outgoing_command(peer, outgoingCommand); - return outgoingCommand; - } - - void enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *peer, ENetChannel *channel) { - ENetListIterator droppedCommand, startCommand, currentCommand; - - for (droppedCommand = startCommand = currentCommand = enet_list_begin(&channel->incomingUnreliableCommands); - currentCommand != enet_list_end(&channel->incomingUnreliableCommands); - currentCommand = enet_list_next(currentCommand) - ) { - ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; - - if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { - continue; - } - - if (incomingCommand->reliableSequenceNumber == channel->incomingReliableSequenceNumber) { - if (incomingCommand->fragmentsRemaining <= 0) { - channel->incomingUnreliableSequenceNumber = incomingCommand->unreliableSequenceNumber; - continue; - } - - if (startCommand != currentCommand) { - enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); - - if (!peer->needsDispatch) { - enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); - peer->needsDispatch = 1; - } - - droppedCommand = currentCommand; - } else if (droppedCommand != currentCommand) { - droppedCommand = enet_list_previous(currentCommand); - } - } else { - enet_uint16 reliableWindow = incomingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - enet_uint16 currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - - if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - reliableWindow += ENET_PEER_RELIABLE_WINDOWS; - } - - if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { - break; - } - - droppedCommand = enet_list_next(currentCommand); - - if (startCommand != currentCommand) { - enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); - - if (!peer->needsDispatch) { - enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); - peer->needsDispatch = 1; - } - } - } - - startCommand = enet_list_next(currentCommand); - } - - if (startCommand != currentCommand) { - enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); - - if (!peer->needsDispatch) { - enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); - peer->needsDispatch = 1; - } - - droppedCommand = currentCommand; - } - - enet_peer_remove_incoming_commands(&channel->incomingUnreliableCommands,enet_list_begin(&channel->incomingUnreliableCommands), droppedCommand); - } - - void enet_peer_dispatch_incoming_reliable_commands(ENetPeer *peer, ENetChannel *channel) { - ENetListIterator currentCommand; - - for (currentCommand = enet_list_begin(&channel->incomingReliableCommands); - currentCommand != enet_list_end(&channel->incomingReliableCommands); - currentCommand = enet_list_next(currentCommand) - ) { - ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; - - if (incomingCommand->fragmentsRemaining > 0 || incomingCommand->reliableSequenceNumber != (enet_uint16) (channel->incomingReliableSequenceNumber + 1)) { - break; - } - - channel->incomingReliableSequenceNumber = incomingCommand->reliableSequenceNumber; - - if (incomingCommand->fragmentCount > 0) { - channel->incomingReliableSequenceNumber += incomingCommand->fragmentCount - 1; - } - } - - if (currentCommand == enet_list_begin(&channel->incomingReliableCommands)) { - return; - } - - channel->incomingUnreliableSequenceNumber = 0; - enet_list_move(enet_list_end(&peer->dispatchedCommands), enet_list_begin(&channel->incomingReliableCommands), enet_list_previous(currentCommand)); - - if (!peer->needsDispatch) { - enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); - peer->needsDispatch = 1; - } - - if (!enet_list_empty(&channel->incomingUnreliableCommands)) { - enet_peer_dispatch_incoming_unreliable_commands(peer, channel); - } - } - - ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *peer, const ENetProtocol *command, const void *data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) { - static ENetIncomingCommand dummyCommand; - - ENetChannel *channel = &peer->channels[command->header.channelID]; - enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0; - enet_uint16 reliableWindow, currentWindow; - ENetIncomingCommand *incomingCommand; - ENetListIterator currentCommand; - ENetPacket *packet = NULL; - - if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { - goto discardCommand; - } - - if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { - reliableSequenceNumber = command->header.reliableSequenceNumber; - reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; - - if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - reliableWindow += ENET_PEER_RELIABLE_WINDOWS; - } - - if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { - goto discardCommand; - } - } - - switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) { - case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: - case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - if (reliableSequenceNumber == channel->incomingReliableSequenceNumber) { - goto discardCommand; - } - - for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands)); - currentCommand != enet_list_end(&channel->incomingReliableCommands); - currentCommand = enet_list_previous(currentCommand) - ) { - incomingCommand = (ENetIncomingCommand *) currentCommand; - - if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - continue; - } - } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber <= reliableSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { - break; - } - - goto discardCommand; - } - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: - case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: - unreliableSequenceNumber = ENET_NET_TO_HOST_16(command->sendUnreliable.unreliableSequenceNumber); - - if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && unreliableSequenceNumber <= channel->incomingUnreliableSequenceNumber) { - goto discardCommand; - } - - for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands)); - currentCommand != enet_list_end(&channel->incomingUnreliableCommands); - currentCommand = enet_list_previous(currentCommand) - ) { - incomingCommand = (ENetIncomingCommand *) currentCommand; - - if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { - continue; - } - - if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { - continue; - } - } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { - break; - } - - if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) { - continue; - } - - if (incomingCommand->unreliableSequenceNumber <= unreliableSequenceNumber) { - if (incomingCommand->unreliableSequenceNumber < unreliableSequenceNumber) { - break; - } - - goto discardCommand; - } - } - break; - - case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: - currentCommand = enet_list_end(&channel->incomingUnreliableCommands); - break; - - default: - goto discardCommand; - } - - if (peer->totalWaitingData >= peer->host->maximumWaitingData) { - goto notifyError; - } - - packet = enet_packet_create(data, dataLength, flags); - if (packet == NULL) { - goto notifyError; - } - - incomingCommand = (ENetIncomingCommand *) enet_malloc(sizeof(ENetIncomingCommand)); - if (incomingCommand == NULL) { - goto notifyError; - } - - incomingCommand->reliableSequenceNumber = command->header.reliableSequenceNumber; - incomingCommand->unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF; - incomingCommand->command = *command; - incomingCommand->fragmentCount = fragmentCount; - incomingCommand->fragmentsRemaining = fragmentCount; - incomingCommand->packet = packet; - incomingCommand->fragments = NULL; - - if (fragmentCount > 0) { - if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) { - incomingCommand->fragments = (enet_uint32 *) enet_malloc((fragmentCount + 31) / 32 * sizeof(enet_uint32)); - } - - if (incomingCommand->fragments == NULL) { - enet_free(incomingCommand); - - goto notifyError; - } - - memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32)); - } - - if (packet != NULL) { - ++packet->referenceCount; - peer->totalWaitingData += packet->dataLength; - } - - enet_list_insert(enet_list_next(currentCommand), incomingCommand); - - switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) { - case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: - case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: - enet_peer_dispatch_incoming_reliable_commands(peer, channel); - break; - - default: - enet_peer_dispatch_incoming_unreliable_commands(peer, channel); - break; - } - - return incomingCommand; - - discardCommand: - if (fragmentCount > 0) { - goto notifyError; - } - - if (packet != NULL && packet->referenceCount == 0) { - enet_packet_destroy(packet); - } - - return &dummyCommand; - - notifyError: - if (packet != NULL && packet->referenceCount == 0) { - enet_packet_destroy(packet); - } - - return NULL; - } /* enet_peer_queue_incoming_command */ - -// =======================================================================// -// ! -// ! Host -// ! -// =======================================================================// - - /** Creates a host for communicating to peers. - * - * @param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host. - * @param peerCount the maximum number of peers that should be allocated for the host. - * @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT - * @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. - * @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. - * - * @returns the host on success and NULL on failure - * - * @remarks ENet will strategically drop packets on specific sides of a connection between hosts - * to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine - * the window size of a connection which limits the amount of reliable packets that may be in transit - * at any given time. - */ - ENetHost * enet_host_create(const ENetAddress *address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { - ENetHost *host; - ENetPeer *currentPeer; - - if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) { - return NULL; - } - - host = (ENetHost *) enet_malloc(sizeof(ENetHost)); - if (host == NULL) { return NULL; } - memset(host, 0, sizeof(ENetHost)); - - host->peers = (ENetPeer *) enet_malloc(peerCount * sizeof(ENetPeer)); - if (host->peers == NULL) { - enet_free(host); - return NULL; - } - - 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); - } - - enet_free(host->peers); - enet_free(host); - - return NULL; - } - - enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1); - 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; - } - - 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_host_random_seed(); - host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16); - host->channelLimit = channelLimit; - host->incomingBandwidth = incomingBandwidth; - host->outgoingBandwidth = outgoingBandwidth; - host->bandwidthThrottleEpoch = 0; - host->recalculateBandwidthLimits = 0; - host->mtu = ENET_HOST_DEFAULT_MTU; - host->peerCount = peerCount; - host->commandCount = 0; - host->bufferCount = 0; - host->checksum = NULL; - host->receivedAddress.host = ENET_HOST_ANY; - host->receivedAddress.port = 0; - host->receivedData = NULL; - host->receivedDataLength = 0; - host->totalSentData = 0; - host->totalSentPackets = 0; - host->totalReceivedData = 0; - host->totalReceivedPackets = 0; - host->connectedPeers = 0; - host->bandwidthLimitedPeers = 0; - host->duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; - host->maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; - host->maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; - host->compressor.context = NULL; - host->compressor.compress = NULL; - host->compressor.decompress = NULL; - host->compressor.destroy = NULL; - host->intercept = NULL; - - enet_list_clear(&host->dispatchQueue); - - for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - currentPeer->host = host; - currentPeer->incomingPeerID = currentPeer - host->peers; - currentPeer->outgoingSessionID = currentPeer->incomingSessionID = 0xFF; - currentPeer->data = NULL; - - enet_list_clear(¤tPeer->acknowledgements); - enet_list_clear(¤tPeer->sentReliableCommands); - enet_list_clear(¤tPeer->sentUnreliableCommands); - enet_list_clear(¤tPeer->outgoingReliableCommands); - enet_list_clear(¤tPeer->outgoingUnreliableCommands); - enet_list_clear(¤tPeer->dispatchedCommands); - - enet_peer_reset(currentPeer); - } - - return host; - } /* enet_host_create */ - - /** Destroys the host and all resources associated with it. - * @param host pointer to the host to destroy - */ - void enet_host_destroy(ENetHost *host) { - ENetPeer *currentPeer; - - if (host == NULL) { - return; - } - - enet_socket_destroy(host->socket); - - for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - enet_peer_reset(currentPeer); - } - - if (host->compressor.context != NULL && host->compressor.destroy) { - (*host->compressor.destroy)(host->compressor.context); - } - - enet_free(host->peers); - enet_free(host); - } - - /** Initiates a connection to a foreign host. - * @param host host seeking the connection - * @param address destination for the connection - * @param channelCount number of channels to allocate - * @param data user data supplied to the receiving host - * @returns a peer representing the foreign host on success, NULL on failure - * @remarks The peer returned will have not completed the connection until enet_host_service() - * notifies of an ENET_EVENT_TYPE_CONNECT event for the peer. - */ - ENetPeer * enet_host_connect(ENetHost *host, const ENetAddress *address, size_t channelCount, enet_uint32 data) { - ENetPeer *currentPeer; - ENetChannel *channel; - ENetProtocol command; - - if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { - channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; - } else if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { - channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; - } - - for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) { - break; - } - } - - if (currentPeer >= &host->peers[host->peerCount]) { - return NULL; - } - - currentPeer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel)); - if (currentPeer->channels == NULL) { - return NULL; - } - - currentPeer->channelCount = channelCount; - currentPeer->state = ENET_PEER_STATE_CONNECTING; - currentPeer->address = *address; - currentPeer->connectID = ++host->randomSeed; - - if (host->outgoingBandwidth == 0) { - currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } else { - currentPeer->windowSize = (host->outgoingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } - - if (currentPeer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { - currentPeer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; - } else if (currentPeer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { - currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; - } - - for (channel = currentPeer->channels; channel < ¤tPeer->channels[channelCount]; ++channel) { - channel->outgoingReliableSequenceNumber = 0; - channel->outgoingUnreliableSequenceNumber = 0; - channel->incomingReliableSequenceNumber = 0; - channel->incomingUnreliableSequenceNumber = 0; - - enet_list_clear(&channel->incomingReliableCommands); - enet_list_clear(&channel->incomingUnreliableCommands); - - channel->usedReliableWindows = 0; - memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows)); - } - - command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - command.header.channelID = 0xFF; - command.connect.outgoingPeerID = ENET_HOST_TO_NET_16(currentPeer->incomingPeerID); - command.connect.incomingSessionID = currentPeer->incomingSessionID; - command.connect.outgoingSessionID = currentPeer->outgoingSessionID; - command.connect.mtu = ENET_HOST_TO_NET_32(currentPeer->mtu); - command.connect.windowSize = ENET_HOST_TO_NET_32(currentPeer->windowSize); - command.connect.channelCount = ENET_HOST_TO_NET_32(channelCount); - command.connect.incomingBandwidth = ENET_HOST_TO_NET_32(host->incomingBandwidth); - command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); - command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32(currentPeer->packetThrottleInterval); - command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleAcceleration); - command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleDeceleration); - command.connect.connectID = currentPeer->connectID; - command.connect.data = ENET_HOST_TO_NET_32(data); - - enet_peer_queue_outgoing_command(currentPeer, &command, NULL, 0, 0); - - return currentPeer; - } /* enet_host_connect */ - - /** Queues a packet to be sent to all peers associated with the host. - * @param host host on which to broadcast the packet - * @param channelID channel on which to broadcast - * @param packet packet to broadcast - */ - void enet_host_broadcast(ENetHost *host, enet_uint8 channelID, ENetPacket *packet) { - ENetPeer *currentPeer; - - for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { - if (currentPeer->state != ENET_PEER_STATE_CONNECTED) { - continue; - } - - enet_peer_send(currentPeer, channelID, packet); - } - - if (packet->referenceCount == 0) { - enet_packet_destroy(packet); - } - } - - /** Sends raw data to specified address. Useful when you want to send unconnected data using host's socket. - * @param host host sending data - * @param address destination address - * @param data data pointer - * @param dataLength length of data to send - * @retval >=0 bytes sent - * @retval <0 error - * @sa enet_socket_send - */ - int enet_host_send_raw(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t dataLength) { - ENetBuffer buffer; - buffer.data = data; - buffer.dataLength = dataLength; - return enet_socket_send(host->socket, address, &buffer, 1); - } - - /** Sends raw data to specified address with extended arguments. Allows to send only part of data, handy for other programming languages. - * I.e. if you have data =- { 0, 1, 2, 3 } and call function as enet_host_send_raw_ex(data, 1, 2) then it will skip 1 byte and send 2 bytes { 1, 2 }. - * @param host host sending data - * @param address destination address - * @param data data pointer - * @param skipBytes number of bytes to skip from start of data - * @param bytesToSend number of bytes to send - * @retval >=0 bytes sent - * @retval <0 error - * @sa enet_socket_send - */ - int enet_host_send_raw_ex(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend) { - ENetBuffer buffer; - buffer.data = data + skipBytes; - buffer.dataLength = bytesToSend; - return enet_socket_send(host->socket, address, &buffer, 1); - } - - /** Sets intercept callback for the host. - * @param host host to set a callback - * @param callback intercept callback - */ - void enet_host_set_intercept(ENetHost *host, const ENetInterceptCallback callback) { - host->intercept = callback; - } - - /** Sets the packet compressor the host should use to compress and decompress packets. - * @param host host to enable or disable compression for - * @param compressor callbacks for for the packet compressor; if NULL, then compression is disabled - */ - void enet_host_compress(ENetHost *host, const ENetCompressor *compressor) { - if (host->compressor.context != NULL && host->compressor.destroy) { - (*host->compressor.destroy)(host->compressor.context); - } - - if (compressor) { - host->compressor = *compressor; - } else { - host->compressor.context = NULL; - } - } - - /** Limits the maximum allowed channels of future incoming connections. - * @param host host to limit - * @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT - */ - 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; - } - - /** Adjusts the bandwidth limits of a host. - * @param host host to adjust - * @param incomingBandwidth new incoming bandwidth - * @param outgoingBandwidth new outgoing bandwidth - * @remarks the incoming and outgoing bandwidth parameters are identical in function to those - * specified in enet_host_create(). - */ - void enet_host_bandwidth_limit(ENetHost *host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { - host->incomingBandwidth = incomingBandwidth; - host->outgoingBandwidth = outgoingBandwidth; - host->recalculateBandwidthLimits = 1; - } - - void enet_host_bandwidth_throttle(ENetHost *host) { - enet_uint32 timeCurrent = enet_time_get(); - enet_uint32 elapsedTime = timeCurrent - host->bandwidthThrottleEpoch; - enet_uint32 peersRemaining = (enet_uint32) host->connectedPeers; - enet_uint32 dataTotal = ~0; - enet_uint32 bandwidth = ~0; - enet_uint32 throttle = 0; - enet_uint32 bandwidthLimit = 0; - - int needsAdjustment = host->bandwidthLimitedPeers > 0 ? 1 : 0; - ENetPeer *peer; - ENetProtocol command; - - if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) { - return; - } - - if (host->outgoingBandwidth == 0 && host->incomingBandwidth == 0) { - return; - } - - host->bandwidthThrottleEpoch = timeCurrent; - - if (peersRemaining == 0) { - return; - } - - if (host->outgoingBandwidth != 0) { - dataTotal = 0; - bandwidth = (host->outgoingBandwidth * elapsedTime) / 1000; - - for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { - if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - continue; - } - - dataTotal += peer->outgoingDataTotal; - } - } - - while (peersRemaining > 0 && needsAdjustment != 0) { - needsAdjustment = 0; - - if (dataTotal <= bandwidth) { - throttle = ENET_PEER_PACKET_THROTTLE_SCALE; - } else { - throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; - } - - for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { - enet_uint32 peerBandwidth; - - if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || - peer->incomingBandwidth == 0 || - peer->outgoingBandwidthThrottleEpoch == timeCurrent - ) { - continue; - } - - peerBandwidth = (peer->incomingBandwidth * elapsedTime) / 1000; - if ((throttle * peer->outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth) { - continue; - } - - peer->packetThrottleLimit = (peerBandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / peer->outgoingDataTotal; - - if (peer->packetThrottleLimit == 0) { - peer->packetThrottleLimit = 1; - } - - if (peer->packetThrottle > peer->packetThrottleLimit) { - peer->packetThrottle = peer->packetThrottleLimit; - } - - peer->outgoingBandwidthThrottleEpoch = timeCurrent; - - peer->incomingDataTotal = 0; - peer->outgoingDataTotal = 0; - - needsAdjustment = 1; - --peersRemaining; - bandwidth -= peerBandwidth; - dataTotal -= peerBandwidth; - } - } - - if (peersRemaining > 0) { - if (dataTotal <= bandwidth) { - throttle = ENET_PEER_PACKET_THROTTLE_SCALE; - } else { - throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; - } - - for (peer = host->peers; - peer < &host->peers[host->peerCount]; - ++peer) - { - if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || peer->outgoingBandwidthThrottleEpoch == timeCurrent) { - continue; - } - - peer->packetThrottleLimit = throttle; - - if (peer->packetThrottle > peer->packetThrottleLimit) { - peer->packetThrottle = peer->packetThrottleLimit; - } - - peer->incomingDataTotal = 0; - peer->outgoingDataTotal = 0; - } - } - - if (host->recalculateBandwidthLimits) { - host->recalculateBandwidthLimits = 0; - - peersRemaining = (enet_uint32) host->connectedPeers; - bandwidth = host->incomingBandwidth; - needsAdjustment = 1; - - if (bandwidth == 0) { - bandwidthLimit = 0; - } else { - while (peersRemaining > 0 && needsAdjustment != 0) { - needsAdjustment = 0; - bandwidthLimit = bandwidth / peersRemaining; - - for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { - if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || - peer->incomingBandwidthThrottleEpoch == timeCurrent - ) { - continue; - } - - if (peer->outgoingBandwidth > 0 && peer->outgoingBandwidth >= bandwidthLimit) { - continue; - } - - peer->incomingBandwidthThrottleEpoch = timeCurrent; - - needsAdjustment = 1; - --peersRemaining; - bandwidth -= peer->outgoingBandwidth; - } - } - } - - for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { - if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { - continue; - } - - command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; - command.header.channelID = 0xFF; - command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); - - if (peer->incomingBandwidthThrottleEpoch == timeCurrent) { - command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(peer->outgoingBandwidth); - } else { - command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(bandwidthLimit); - } - - enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); - } - } - } /* enet_host_bandwidth_throttle */ - -// =======================================================================// -// ! -// ! 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); - } - - 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 && !defined CLOCK_MONOTONIC - #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); - } - -// =======================================================================// -// ! -// ! Platform Specific (Unix) -// ! -// =======================================================================// - - #ifndef _WIN32 - - int enet_initialize(void) { - return 0; - } - - void enet_deinitialize(void) {} - - enet_uint64 enet_host_random_seed(void) { - return (enet_uint64) time(NULL); - } - - int enet_address_set_host_ip(ENetAddress *address, const char *name) { - if (!inet_pton(AF_INET6, name, &address->host)) { - return -1; - } - - return 0; - } - - int enet_address_set_host(ENetAddress *address, const char *name) { - 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; - } - - 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; - - ((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; - - 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; - - freeaddrinfo(resultList); - - return 0; - } - } - } - - - if (resultList != NULL) { - freeaddrinfo(resultList); - } - - 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) { - if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) { - return -1; - } - - return 0; - } - - int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) { - struct sockaddr_in6 sin; - int err; - - 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; - - 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(address, name, nameLength); - } /* enet_address_get_host */ - - 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; - - 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; - } - - return bind(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6)); - } - - int enet_socket_get_address(ENetSocket socket, ENetAddress *address) { - struct sockaddr_in6 sin; - socklen_t sinLength = sizeof(struct sockaddr_in6); - - if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) { - return -1; - } - - address->host = sin.sin6_addr; - address->port = ENET_NET_TO_HOST_16(sin.sin6_port); - address->sin6_scope_id = sin.sin6_scope_id; - - return 0; - } - - int enet_socket_listen(ENetSocket socket, int backlog) { - return listen(socket, backlog < 0 ? SOMAXCONN : backlog); - } - - ENetSocket enet_socket_create(ENetSocketType type) { - return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); - } - - int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { - int result = -1; - - switch (option) { - case ENET_SOCKOPT_NONBLOCK: - result = fcntl(socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl(socket, F_GETFL) & ~O_NONBLOCK)); - break; - - case ENET_SOCKOPT_BROADCAST: - result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_REUSEADDR: - result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_RCVBUF: - result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_SNDBUF: - result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (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_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_NODELAY: - result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int)); - 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; - } /* enet_socket_set_option */ - - int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) { - int result = -1; - socklen_t len; - - switch (option) { - case ENET_SOCKOPT_ERROR: - len = sizeof(int); - result = getsockopt(socket, SOL_SOCKET, SO_ERROR, value, &len); - break; - - default: - break; - } - return result == -1 ? -1 : 0; - } - - int enet_socket_connect(ENetSocket socket, const ENetAddress *address) { - struct sockaddr_in6 sin; - int result; - - 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 == -1 && errno == EINPROGRESS) { - return 0; - } - - return result; - } - - ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) { - int result; - struct sockaddr_in6 sin; - socklen_t sinLength = sizeof(struct sockaddr_in6); - - result = accept(socket,address != NULL ? (struct sockaddr *) &sin : NULL, address != NULL ? &sinLength : NULL); - - if (result == -1) { - return ENET_SOCKET_NULL; - } - - 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; - } - - return result; - } - - int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) { - return shutdown(socket, (int) how); - } - - void enet_socket_destroy(ENetSocket socket) { - if (socket != -1) { - close(socket); - } - } - - int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) { - struct msghdr msgHdr; - struct sockaddr_in6 sin; - int sentLength; - - memset(&msgHdr, 0, sizeof(struct msghdr)); - - 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; - - msgHdr.msg_name = &sin; - msgHdr.msg_namelen = sizeof(struct sockaddr_in6); - } - - msgHdr.msg_iov = (struct iovec *) buffers; - msgHdr.msg_iovlen = bufferCount; - - sentLength = sendmsg(socket, &msgHdr, MSG_NOSIGNAL); - - if (sentLength == -1) { - if (errno == EWOULDBLOCK) { - return 0; - } - - return -1; - } - - return sentLength; - } /* enet_socket_send */ - - int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) { - struct msghdr msgHdr; - struct sockaddr_in6 sin; - int recvLength; - - memset(&msgHdr, 0, sizeof(struct msghdr)); - - if (address != NULL) { - msgHdr.msg_name = &sin; - msgHdr.msg_namelen = sizeof(struct sockaddr_in6); - } - - msgHdr.msg_iov = (struct iovec *) buffers; - msgHdr.msg_iovlen = bufferCount; - - recvLength = recvmsg(socket, &msgHdr, MSG_NOSIGNAL); - - if (recvLength == -1) { - if (errno == EWOULDBLOCK) { - return 0; - } - - return -1; - } - - if (msgHdr.msg_flags & MSG_TRUNC) { - return -1; - } - - 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; - } - - return recvLength; - } /* enet_socket_receive */ - - 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; - - return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal); - } - - int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) { - struct pollfd pollSocket; - int pollCount; - - pollSocket.fd = socket; - pollSocket.events = 0; - - if (*condition & ENET_SOCKET_WAIT_SEND) { - pollSocket.events |= POLLOUT; - } - - if (*condition & ENET_SOCKET_WAIT_RECEIVE) { - pollSocket.events |= POLLIN; - } - - pollCount = poll(&pollSocket, 1, timeout); - - if (pollCount < 0) { - if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) { - *condition = ENET_SOCKET_WAIT_INTERRUPT; - - return 0; - } - - return -1; - } - - *condition = ENET_SOCKET_WAIT_NONE; - - if (pollCount == 0) { - return 0; - } - - if (pollSocket.revents & POLLOUT) { - *condition |= ENET_SOCKET_WAIT_SEND; - } - - if (pollSocket.revents & POLLIN) { - *condition |= ENET_SOCKET_WAIT_RECEIVE; - } - - return 0; - } /* enet_socket_wait */ - - #endif // !_WIN32 - - -// =======================================================================// -// ! -// ! Platform Specific (Win) -// ! -// =======================================================================// - - #ifdef _WIN32 - - #ifdef __MINGW32__ - // 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) { - struct sockaddr_in in; - memset(&in, 0, sizeof(in)); - in.sin_family = AF_INET; - memcpy(&in.sin_addr, src, sizeof(struct in_addr)); - getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - else if (af == AF_INET6) { - struct sockaddr_in6 in; - memset(&in, 0, sizeof(in)); - in.sin6_family = AF_INET6; - memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); - getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); - return dst; - } - - return NULL; - } - - #define NS_INADDRSZ 4 - #define NS_IN6ADDRSZ 16 - #define NS_INT16SZ 2 - - int inet_pton4(const char *src, char *dst) { - uint8_t tmp[NS_INADDRSZ], *tp; - - int saw_digit = 0; - int octets = 0; - *(tp = tmp) = 0; - - int ch; - while ((ch = *src++) != '\0') - { - if (ch >= '0' && ch <= '9') - { - uint32_t n = *tp * 10 + (ch - '0'); - - if (saw_digit && *tp == 0) - return 0; - - if (n > 255) - return 0; - - *tp = n; - if (!saw_digit) - { - if (++octets > 4) - return 0; - saw_digit = 1; - } - } - else if (ch == '.' && saw_digit) - { - if (octets == 4) - return 0; - *++tp = 0; - saw_digit = 0; - } - else - return 0; - } - if (octets < 4) - return 0; - - memcpy(dst, tmp, NS_INADDRSZ); - - return 1; - } - - int inet_pton6(const char *src, char *dst) { - static const char xdigits[] = "0123456789abcdef"; - uint8_t tmp[NS_IN6ADDRSZ]; - - uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); - uint8_t *endp = tp + NS_IN6ADDRSZ; - uint8_t *colonp = NULL; - - /* Leading :: requires some special handling. */ - if (*src == ':') - { - if (*++src != ':') - return 0; - } - - const char *curtok = src; - int saw_xdigit = 0; - uint32_t val = 0; - int ch; - while ((ch = tolower(*src++)) != '\0') - { - const char *pch = strchr(xdigits, ch); - if (pch != NULL) - { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return 0; - saw_xdigit = 1; - continue; - } - if (ch == ':') - { - curtok = src; - if (!saw_xdigit) - { - if (colonp) - return 0; - colonp = tp; - continue; - } - else if (*src == '\0') - { - return 0; - } - if (tp + NS_INT16SZ > endp) - return 0; - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && - inet_pton4(curtok, (char*) tp) > 0) - { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return 0; - } - if (saw_xdigit) - { - if (tp + NS_INT16SZ > endp) - return 0; - *tp++ = (uint8_t) (val >> 8) & 0xff; - *tp++ = (uint8_t) val & 0xff; - } - if (colonp != NULL) - { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - - if (tp == endp) - return 0; - - for (int i = 1; i <= n; i++) - { - endp[-i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return 0; - - memcpy(dst, tmp, NS_IN6ADDRSZ); - - return 1; - } - - - int inet_pton(int af, const char *src, struct in6_addr *dst) { - switch (af) - { - case AF_INET: - return inet_pton4(src, (char *)dst); - case AF_INET6: - return inet_pton6(src, (char *)dst); - default: - return -1; - } - } - #endif // __MINGW__ - - int enet_initialize(void) { - WORD versionRequested = MAKEWORD(1, 1); - WSADATA wsaData; - - if (WSAStartup(versionRequested, &wsaData)) { - return -1; - } - - if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { - WSACleanup(); - return -1; - } - - timeBeginPeriod(1); - return 0; - } - - void enet_deinitialize(void) { - timeEndPeriod(1); - WSACleanup(); - } - - 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; - - 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; - } - - if (*next != (i < 3 ? '.' : '\0')) { - return -1; - } - name = next + 1; - } - - memcpy(&address->host, vals, sizeof(enet_uint32)); - return 0; - } - - int enet_address_set_host(ENetAddress *address, const char *name) { - struct hostent *hostEntry = NULL; - hostEntry = gethostbyname(name); - - if (hostEntry == NULL || hostEntry->h_addrtype != AF_INET) { - if (!inet_pton(AF_INET6, name, &address->host)) { - return -1; - } - - return 0; - } - - ((enet_uint32 *)&address->host.s6_addr)[0] = 0; - ((enet_uint32 *)&address->host.s6_addr)[1] = 0; - ((enet_uint32 *)&address->host.s6_addr)[2] = htonl(0xffff); - ((enet_uint32 *)&address->host.s6_addr)[3] = *(enet_uint32 *)hostEntry->h_addr_list[0]; - - return 0; - } - - int enet_address_get_host_ip(const ENetAddress *address, char *name, size_t nameLength) { - if (inet_ntop(AF_INET6, (PVOID)&address->host, name, nameLength) == NULL) { - return -1; - } - - return 0; - } - - int enet_address_get_host(const ENetAddress *address, char *name, size_t nameLength) { - struct in6_addr in; - struct hostent *hostEntry = NULL; - - in = address->host; - hostEntry = gethostbyaddr((char *)&in, sizeof(struct in6_addr), AF_INET6); - - 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); - } - - return 0; - } - - 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; - - 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; - } - - return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0; - } - - int enet_socket_get_address(ENetSocket socket, ENetAddress *address) { - struct sockaddr_in6 sin; - int sinLength = sizeof(struct sockaddr_in6); - - if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) { - return -1; - } - - address->host = sin.sin6_addr; - address->port = ENET_NET_TO_HOST_16(sin.sin6_port); - address->sin6_scope_id = sin.sin6_scope_id; - - return 0; - } - - int enet_socket_listen(ENetSocket socket, int backlog) { - return listen(socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; - } - - ENetSocket enet_socket_create(ENetSocketType type) { - return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); - } - - int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { - int result = SOCKET_ERROR; - - switch (option) { - case ENET_SOCKOPT_NONBLOCK: { - u_long nonBlocking = (u_long) value; - result = ioctlsocket(socket, FIONBIO, &nonBlocking); - break; - } - - case ENET_SOCKOPT_BROADCAST: - result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_REUSEADDR: - result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_RCVBUF: - result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_SNDBUF: - result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_RCVTIMEO: - result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_SNDTIMEO: - result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&value, sizeof(int)); - break; - - case ENET_SOCKOPT_NODELAY: - result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int)); - 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; - } /* enet_socket_set_option */ - - int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) { - int result = SOCKET_ERROR, len; - - switch (option) { - case ENET_SOCKOPT_ERROR: - len = sizeof(int); - result = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)value, &len); - break; - - default: - break; - } - return result == SOCKET_ERROR ? -1 : 0; - } - - int enet_socket_connect(ENetSocket socket, const ENetAddress *address) { - struct sockaddr_in6 sin; - int result; - - 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; - } - - return 0; - } - - ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) { - SOCKET result; - struct sockaddr_in6 sin; - int sinLength = sizeof(struct sockaddr_in6); - - result = accept(socket, address != NULL ? (struct sockaddr *)&sin : NULL, address != NULL ? &sinLength : NULL); - - if (result == INVALID_SOCKET) { - return ENET_SOCKET_NULL; - } - - 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; - } - - 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); - } - } - - 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; - } - - 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; - } - - return (int) sentLength; - } - - 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; - } - - return -1; - } - - if (flags & MSG_PARTIAL) { - return -1; - } - - 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; - } - - return (int) recvLength; - } /* enet_socket_receive */ - - 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; - - return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal); - } - - int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) { - fd_set readSet, writeSet; - struct timeval timeVal; - int selectCount; - - timeVal.tv_sec = timeout / 1000; - timeVal.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&readSet); - FD_ZERO(&writeSet); - - if (*condition & ENET_SOCKET_WAIT_SEND) { - FD_SET(socket, &writeSet); - } - - if (*condition & ENET_SOCKET_WAIT_RECEIVE) { - FD_SET(socket, &readSet); - } - - selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal); - - if (selectCount < 0) { - return -1; - } - - *condition = ENET_SOCKET_WAIT_NONE; - - if (selectCount == 0) { - return 0; - } - - if (FD_ISSET(socket, &writeSet)) { - *condition |= ENET_SOCKET_WAIT_SEND; - } - - if (FD_ISSET(socket, &readSet)) { - *condition |= ENET_SOCKET_WAIT_RECEIVE; - } - - return 0; - } /* enet_socket_wait */ - - #endif // _WIN32 - - -#ifdef __cplusplus -} -#endif - -#endif // ENET_IMPLEMENTATION -#endif // ENET_INCLUDE_H diff --git a/source/thirdparty/src/enet.cpp b/source/thirdparty/src/enet.cpp deleted file mode 100644 index d3bac0a81..000000000 --- a/source/thirdparty/src/enet.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#define ENET_IMPLEMENTATION -#include "enet.h" -#include "printf.h" - -bool gHaveNetworking; - -void ShutdownENet() -{ - if (gHaveNetworking) enet_deinitialize(); -} - -void InitENet() -{ - gHaveNetworking = !enet_initialize(); - if (!gHaveNetworking) - Printf("An error occurred while initializing ENet.\n"); -} -