Skip to content

Commit

Permalink
Merge pull request #61 from emcifuntik/master
Browse files Browse the repository at this point in the history
Support for up to 65k peers
  • Loading branch information
zpl-zak authored Jan 7, 2025
2 parents e8a7dfa + 57a5d42 commit 17cc8a0
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 16 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ jobs:
run: cmake --build build
- name: Run unit tests
run: cd build ; .\Debug\enet_test.exe
- name: Run unit tests with extra peers
run: cd build ; .\Debug\enet_test_extra_peers.exe

build-lin:
name: Test Linux
Expand All @@ -54,6 +56,8 @@ jobs:
run: cmake --build build
- name: Test build on Linux
run: build/enet_test
- name: Test build on Linux with extra peers
run: build/enet_test_extra_peers

build-mac:
name: Test macOS
Expand All @@ -67,6 +71,8 @@ jobs:
run: cmake --build build
- name: Test build on macOS
run: build/enet_test
- name: Test build on macOS with extra peers
run: build/enet_test_extra_peers

done:
name: Notify about status
Expand Down
32 changes: 25 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ project(enet C)
option(ENET_STATIC "Build enet as a static library" ON)
option(ENET_SHARED "Build enet as a shared library" OFF)
option(ENET_TEST "Build enet tests" ON)
option(ENET_USE_MORE_PEERS "Build enet with up to 65k peers support" OFF)

if (ENET_USE_MORE_PEERS)
add_definitions(-DENET_USE_MORE_PEERS)
endif()

# -----------------------------
# 2) Static library
Expand Down Expand Up @@ -59,18 +64,31 @@ endif()
# 4) Tests (optional)
# -----------------------------
if(ENET_TEST)
add_executable(enet_test test/build.c)
target_include_directories(enet_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(enet_test_interface INTERFACE)

if(WIN32)
target_link_libraries(enet_test PUBLIC winmm ws2_32)
endif()
target_include_directories(enet_test_interface INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
)

if(TARGET enet_static)
target_link_libraries(enet_test PRIVATE enet_static)
target_link_libraries(enet_test_interface INTERFACE enet_static)
elseif(TARGET enet_shared)
target_link_libraries(enet_test PRIVATE enet_shared)
target_link_libraries(enet_test_interface INTERFACE enet_shared)
endif()

if(WIN32)
target_link_libraries(enet_test_interface INTERFACE winmm ws2_32)
endif()

# Default test
add_executable(enet_test test/build.c)
target_link_libraries(enet_test PRIVATE enet_test_interface)

# Test with more peers
add_executable(enet_test_extra_peers test/build.c)
target_link_libraries(enet_test_extra_peers PRIVATE enet_test_interface)
target_compile_definitions(enet_test_extra_peers PRIVATE ENET_USE_MORE_PEERS)

endif()

# -----------------------------
Expand Down
76 changes: 72 additions & 4 deletions include/enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,11 @@ extern "C" {
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
#ifdef ENET_USE_MORE_PEERS
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFFF,
#else
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
#endif
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
};

Expand All @@ -332,12 +336,22 @@ extern "C" {
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),

#ifdef ENET_USE_MORE_PEERS
ENET_PROTOCOL_HEADER_FLAG_PEER_EXTRA = (1 << 13),
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_PEER_EXTRA | ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,

ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 11),
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 11
#else
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
#endif
} ENetProtocolFlag;

#ifdef _MSC_VER
Expand All @@ -354,6 +368,10 @@ extern "C" {
enet_uint16 sentTime;
} ENET_PACKED ENetProtocolHeader;

typedef struct _ENetProtocolHeaderMinimal {
enet_uint16 peerID;
} ENET_PACKED ENetProtocolHeaderMinimal;

typedef struct _ENetProtocolCommandHeader {
enet_uint8 command;
enet_uint8 channelID;
Expand Down Expand Up @@ -2483,7 +2501,7 @@ extern "C" {
enet_uint16 peerID, flags;
enet_uint8 sessionID;

if (host->receivedDataLength < (size_t) &((ENetProtocolHeader *) 0)->sentTime) {
if (host->receivedDataLength < sizeof(ENetProtocolHeaderMinimal)) {
return 0;
}

Expand All @@ -2494,8 +2512,27 @@ extern "C" {
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);
headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof(ENetProtocolHeader) : sizeof(ENetProtocolHeaderMinimal));

#ifdef ENET_USE_MORE_PEERS
if (flags & ENET_PROTOCOL_HEADER_FLAG_PEER_EXTRA) {
if (host->receivedDataLength < headerSize + sizeof(enet_uint8)) {
return 0;
}

enet_uint8 * headerExtraPeerID = (enet_uint8 *) & host -> receivedData [headerSize];
enet_uint8 peerIDExtra = *headerExtraPeerID;
peerID = (peerID & 0x07FF) | ((enet_uint16)peerIDExtra << 11);

headerSize += sizeof (enet_uint8);
}
#endif

if (host->checksum != NULL) {
if (host->receivedDataLength < headerSize + sizeof(enet_uint32)) {
return 0;
}

headerSize += sizeof(enet_uint32);
}

Expand Down Expand Up @@ -3081,7 +3118,13 @@ extern "C" {
} /* 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)];
enet_uint8 headerData[
sizeof(ENetProtocolHeader)
#ifdef ENET_USE_MORE_PEERS
+ sizeof(enet_uint8) // additional peer id byte
#endif
+ sizeof(enet_uint32)
];
ENetProtocolHeader *header = (ENetProtocolHeader *) headerData;
ENetPeer *currentPeer;
int sentLength;
Expand Down Expand Up @@ -3171,7 +3214,7 @@ extern "C" {
header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF);
host->buffers[0].dataLength = sizeof(ENetProtocolHeader);
} else {
host->buffers[0].dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime;
host->buffers[0].dataLength = sizeof(ENetProtocolHeaderMinimal);
}

shouldCompress = 0;
Expand All @@ -3190,7 +3233,32 @@ extern "C" {
if (currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID) {
host->headerFlags |= currentPeer->outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
}

#ifdef ENET_USE_MORE_PEERS
{
enet_uint16 basePeerID = (enet_uint16)(currentPeer->outgoingPeerID & 0x07FF);
enet_uint16 flagsAndSession = (enet_uint16)(host->headerFlags & 0xF800); /* top bits only */

if (currentPeer->outgoingPeerID > 0x07FF)
{
flagsAndSession |= ENET_PROTOCOL_HEADER_FLAG_PEER_EXTRA;
header->peerID = ENET_HOST_TO_NET_16(basePeerID | flagsAndSession);
{
enet_uint8 overflowByte = (enet_uint8)((currentPeer->outgoingPeerID >> 11) & 0xFF);
enet_uint8 *extraPeerIDByte = &headerData[host->buffers[0].dataLength];
*extraPeerIDByte = overflowByte;
host->buffers[0].dataLength += sizeof(enet_uint8);
}
}
else
{
header->peerID = ENET_HOST_TO_NET_16(basePeerID | flagsAndSession);
}
}
#else
header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags);
#endif

if (host->checksum != NULL) {
enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers[0].dataLength];
*checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0;
Expand Down
21 changes: 16 additions & 5 deletions test/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@ typedef struct {
ENetPeer *peer;
} Client;

#ifdef ENET_USE_MORE_PEERS
#define MAX_CLIENTS 5000
#else
#define MAX_CLIENTS 32
#endif

unsigned long long counter = 0;

void host_server(ENetHost *server) {
ENetEvent event;
while (enet_host_service(server, &event, 2) > 0) {
switch (event.type) {
case ENET_EVENT_TYPE_CONNECT:
printf("A new client connected from ::1:%u.\n", event.peer->address.port);
printf("A new peer with ID %u connected from ::1:%u.\n", event.peer->incomingPeerID , event.peer->address.port);
/* Store any relevant client information here. */
event.peer->data = "Client information";
event.peer->data = (void*)(counter++);
break;
case ENET_EVENT_TYPE_RECEIVE:
printf("A packet of length %zu containing %s was received from %s on channel %u.\n",
Expand All @@ -30,7 +38,7 @@ void host_server(ENetHost *server) {
break;

case ENET_EVENT_TYPE_DISCONNECT:
printf ("%s disconnected.\n", (char *)event.peer->data);
printf ("Peer with ID %u disconnected.\n", event.peer->incomingPeerID);
/* Reset the peer's client information. */
event.peer->data = NULL;
break;
Expand All @@ -51,8 +59,6 @@ int main() {
return 1;
}

#define MAX_CLIENTS 32

int i = 0;
ENetHost *server;
Client clients[MAX_CLIENTS];
Expand Down Expand Up @@ -81,6 +87,8 @@ int main() {
}
}

printf("running server...\n");

// program will make N iterations, and then exit
static int counter = 1000;

Expand All @@ -95,9 +103,12 @@ int main() {
counter--;
} while (counter > 0);

printf("stopping clients...\n");

for (i = 0; i < MAX_CLIENTS; ++i) {
enet_peer_disconnect_now(clients[i].peer, 0);
enet_host_destroy(clients[i].host);
host_server(server);
}

host_server(server);
Expand Down

0 comments on commit 17cc8a0

Please sign in to comment.