Index: ps/trunk/binaries/data/config/default.cfg =================================================================== --- ps/trunk/binaries/data/config/default.cfg +++ ps/trunk/binaries/data/config/default.cfg @@ -525,6 +525,7 @@ observerlimit = 8 ; Prevent further observer joins in running games if this limit is reached observermaxlag = -1 ; Make clients wait for observers if they lag more than X turns behind. -1 means "never wait for observers". autocatchup = true ; Auto-accelerate the sim rate if lagging behind (as an observer). +enetmtu = 1372 ; Lower ENet protocol MTU in case packets get further fragmented on the UDP layer which may cause drops. [overlay] fps = "false" ; Show frames per second in top right corner Index: ps/trunk/source/network/NetClient.cpp =================================================================== --- ps/trunk/source/network/NetClient.cpp +++ ps/trunk/source/network/NetClient.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include "NetClient.h" #include "NetClientTurnManager.h" +#include "NetEnet.h" #include "NetMessage.h" #include "NetSession.h" @@ -247,7 +248,7 @@ } ENetAddress hostAddr{ ENET_HOST_ANY, ENET_PORT_ANY }; - ENetHost* enetClient = enet_host_create(&hostAddr, 1, 1, 0, 0); + ENetHost* enetClient = PS::Enet::CreateHost(&hostAddr, 1, 1); if (!enetClient) { Index: ps/trunk/source/network/NetEnet.h =================================================================== --- ps/trunk/source/network/NetEnet.h +++ ps/trunk/source/network/NetEnet.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2023 Wildfire Games. + * + * Permission is hereby granted, 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 INCLUDED_NETENET +#define INCLUDED_NETENET + +#include "lib/external_libraries/enet.h" + +namespace PS +{ + +namespace Enet +{ + +/** + * Wrapper for enet_host_create setting default values and custom mtu, taking + * care of user configuration. + */ +ENetHost* CreateHost(const ENetAddress* address, size_t peerCount, size_t channelLimit); + +} // namespace Enet + +} // namespace PS + +#endif // #ifndef INCLUDED_NETENET Index: ps/trunk/source/network/NetEnet.cpp =================================================================== --- ps/trunk/source/network/NetEnet.cpp +++ ps/trunk/source/network/NetEnet.cpp @@ -0,0 +1,62 @@ +/* Copyright (C) 2023 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "NetEnet.h" + +#include "ps/ConfigDB.h" +#include "ps/containers/Span.h" + +namespace PS +{ + +namespace Enet +{ + +// ENet protocol MTU +// ENet by default uses 1400 as ENet packet fragment max size, adding ICMP and +// IPv4 headers this may exceed the MTU for some VPN solutions [1], so provide +// a lower default. +// MTU negotiation server-side needs [2], which was merged after enet-1.3.17, +// so the user configured value may be ignored on older versions. +// [1] https://github.com/lsalzman/enet/issues/132 +// [2] https://github.com/lsalzman/enet/pull/222 +constexpr enet_uint32 HOST_DEFAULT_MTU = 1372; + +ENetHost* CreateHost(const ENetAddress* address, size_t peerCount, size_t channelLimit) +{ + // TODO: Maybe allow user to set rate limits? + + ENetHost* host = enet_host_create(address, peerCount, channelLimit, 0, 0); + if (!host) + return nullptr; + + // Public ENet API doesn't offer a means to change MTU, so do it in a + // way least likely to break with ENet updates. + enet_uint32 mtu = HOST_DEFAULT_MTU; + CFG_GET_VAL("network.enetmtu", mtu); + host->mtu = mtu; + for (ENetPeer& p : PS::span{host->peers, host->peerCount}) + enet_peer_reset(&p); + + return host; +} + +} // namespace Enet + +} // namespace PS Index: ps/trunk/source/network/NetServer.cpp =================================================================== --- ps/trunk/source/network/NetServer.cpp +++ ps/trunk/source/network/NetServer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include "NetServer.h" #include "NetClient.h" +#include "NetEnet.h" #include "NetMessage.h" #include "NetSession.h" #include "NetServerTurnManager.h" @@ -223,7 +224,7 @@ addr.port = port; // Create ENet server - m_Host = enet_host_create(&addr, MAX_CLIENTS, CHANNEL_COUNT, 0, 0); + m_Host = PS::Enet::CreateHost(&addr, MAX_CLIENTS, CHANNEL_COUNT); if (!m_Host) { LOGERROR("Net server: enet_host_create failed"); Index: ps/trunk/source/network/NetSession.cpp =================================================================== --- ps/trunk/source/network/NetSession.cpp +++ ps/trunk/source/network/NetSession.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include "NetSession.h" #include "NetClient.h" +#include "NetEnet.h" #include "NetMessage.h" #include "NetServer.h" #include "NetStats.h" @@ -60,12 +61,8 @@ ENSURE(!m_Host); ENSURE(!m_Server); - // Create ENet host - ENetHost* host; - if (enetClient != nullptr) - host = enetClient; - else - host = enet_host_create(NULL, 1, CHANNEL_COUNT, 0, 0); + // Create ENet host if necessary. + ENetHost* host = enetClient != nullptr ? enetClient : PS::Enet::CreateHost(nullptr, 1, CHANNEL_COUNT); if (!host) return false;