From 25636f8db7a86445a390b1b935d3eae30e850923 Mon Sep 17 00:00:00 2001 From: Jordan Schidlowsky Date: Mon, 27 Sep 2021 09:36:57 +0200 Subject: [PATCH 1/2] [Net] ENet now sends fragmented packets unreliably too. It used to always send them reliably when transfer mode was unreliable or ordered if the packet size was more then the enet host MTU (1400 bytes by default). This commit also adds a warning when debug is enabled to explain the effects of sending fragmented packets unreliably. --- modules/enet/networked_multiplayer_enet.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index a249d7037866..cf6148e91854 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -546,9 +546,10 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer packet_flags = ENET_PACKET_FLAG_UNSEQUENCED; } channel = SYSCH_UNRELIABLE; + packet_flags |= ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT; } break; case TRANSFER_MODE_UNRELIABLE_ORDERED: { - packet_flags = 0; + packet_flags = ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT; channel = SYSCH_UNRELIABLE; } break; case TRANSFER_MODE_RELIABLE: { @@ -561,6 +562,12 @@ Error NetworkedMultiplayerENet::put_packet(const uint8_t *p_buffer, int p_buffer channel = transfer_channel; } +#ifdef DEBUG_ENABLED + if ((packet_flags & ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT) && p_buffer_size + 8 > ENET_HOST_DEFAULT_MTU) { + WARN_PRINT_ONCE(vformat("Sending %d bytes unrealiably which is above the MTU (%d), this will result in higher packet loss", p_buffer_size + 8, host->mtu)); + } +#endif + Map::Element *E = nullptr; if (target_peer != 0) { From 3b43dfee11fe6db9a3c1fc99be1e4b0295166534 Mon Sep 17 00:00:00 2001 From: Jordan Schidlowsky Date: Mon, 27 Sep 2021 09:39:31 +0200 Subject: [PATCH 2/2] [Net] ENet poll now only service the connection once. It used to call `enet_host_service` until all events were consumed, but that also meant constantly polling the connection leading to potentially unbounded processing time. It now only service the connection once, and instead consumes all the retrieved events via `enet_host_check_events`. --- modules/enet/networked_multiplayer_enet.cpp | 27 ++++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp index cf6148e91854..a3944b53dedd 100644 --- a/modules/enet/networked_multiplayer_enet.cpp +++ b/modules/enet/networked_multiplayer_enet.cpp @@ -217,20 +217,23 @@ void NetworkedMultiplayerENet::poll() { _pop_current_packet(); + if (!host || !active) { // Might be disconnected + return; + } + ENetEvent event; - /* Keep servicing until there are no available events left in queue. */ - while (true) { - if (!host || !active) { // Might have been disconnected while emitting a notification - return; - } + int ret = enet_host_service(host, &event, 0); - int ret = enet_host_service(host, &event, 0); + if (ret < 0) { + ERR_FAIL_MSG("Enet host service error"); + } else if (ret == 0) { + return; // No events + } - if (ret < 0) { - // Error, do something? - break; - } else if (ret == 0) { - break; + /* Keep servicing until there are no available events left in the queue. */ + do { + if (!host || !active) { // Check again after every event + return; } switch (event.type) { @@ -436,7 +439,7 @@ void NetworkedMultiplayerENet::poll() { // Do nothing } break; } - } + } while (enet_host_check_events(host, &event) > 0); } bool NetworkedMultiplayerENet::is_server() const {