switched network reader from select() to poll()

This commit is contained in:
Eric 2023-06-15 12:10:01 -07:00
parent d725cf79da
commit fdfe0ffd3a
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
14 changed files with 289 additions and 196 deletions

56
.efrocachemap generated
View File

@ -4072,26 +4072,26 @@
"build/assets/workspace/ninjafightplug.py": "https://files.ballistica.net/cache/ba1/18/4b/787a9267e17be3c49966072581a5",
"build/assets/workspace/onslaughtplug.py": "https://files.ballistica.net/cache/ba1/20/f6/4ce9bc3c1f3732f6adf8237fbe9b",
"build/assets/workspace/runaroundplug.py": "https://files.ballistica.net/cache/ba1/a5/30/9058181df0b1255bf6950cbc7813",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/1e/dc/97e852e2bd553825887ae9852756",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/54/0c/cf1fc5786cd44bf50ef116e053c2",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/15/b2/0fd773bb3bf55249e87360edcb61",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/19/43/2aa331c03048ce000662de5713f1",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/1a/bc/48fb516727c8774640794b5c345c",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/de/da/6b4057aa7f583ef6a1f79bbdbdd6",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/13/6d/0d13fe395db109730e9f48c84e53",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/7a/b4/98a5e5ed423107e3aca585cea6a9",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/36/f2/6127c27e229de21395fbe6ca3dbe",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/fe/bb/67e0a6b2b9b5f65b1521df2e977b",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/2a/62/a298f381499bbb60131db027c0bd",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/a8/ed/6ac901d41db9709042e0e1ec0c31",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/93/c5/dc0b4a2031435986ddf853e1f36f",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/1b/39/6acfd7fcd05139612ea277ce315e",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/53/b3/d8df1a3269ea4c7a9254b3f6d5e7",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/bc/46/d6c92388b06f42c7df1e20df72d9",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/4f/0f/6344b046dfee6ed0ba404fd102bd",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/88/a9/b49c302ced5e4d7463597a4bddab",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/0e/be/e62bb97312b709ba28e1a3017e20",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/91/3f/5594522e68d039e3113ebd61e458",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/fb/2b/e9b87e05c1b8021e897421b33c0f",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/fe/88/d586906b71912924f6b5be68417f",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/b7/e5/6b2a939582e0fa0e5453f1b30379",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/dd/d0/7b8dfb5b436c0f7fa90397acbded",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/9f/6d/a996b63727ca2552cf2abc7a1770",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/75/37/09a2c4b1cd721c62c81df5d13864",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/59/3f/b32b06bc31e0622175c69bebc51d",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/0c/8d/ca80f75886f8e872b6cdb409aeac",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/60/77/a59b63bacdded8410a5a20f0edb7",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/67/f2/55962dc83849e412d4205813c572",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/9f/d7/da3f63ac008515d3c8b5b101cde7",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/d1/ec/b23825d099644ba8497a548369f2",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "https://files.ballistica.net/cache/ba1/02/ce/6eaea9df32a8a2d83993342b216e",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "https://files.ballistica.net/cache/ba1/20/8a/958c0db70b01b8e8011b3b696cc4",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/6b/aa/8695595c3ae00f2201fae34d6fcc",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "https://files.ballistica.net/cache/ba1/33/14/c5e32d098f60c0255d3a8b73fab2",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/eb/84/0ec9699d6658f46ac84dd0dce984",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "https://files.ballistica.net/cache/ba1/1c/a2/8171dc09551a84b5d219e6edd49e",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/0f/4b/9df8e37c59530603c8c613126195",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "https://files.ballistica.net/cache/ba1/8e/3c/624bac9b4856fa5cc537f8ec28f4",
"build/prefab/lib/linux_arm64_gui/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/d9/56/b0a16db98621500b473844ec39d6",
"build/prefab/lib/linux_arm64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/57/f9/f304c67d9958574b6b35de2ad13d",
"build/prefab/lib/linux_arm64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/04/55/a41ad832c081ff421039827d16c1",
@ -4108,14 +4108,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/88/1a/1ea680450c3c9bc97147df4bf99d",
"build/prefab/lib/mac_x86_64_server/debug/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/91/b3/31b980ca2a000871408cbc7923e3",
"build/prefab/lib/mac_x86_64_server/release/libballistica_plus.a": "https://files.ballistica.net/cache/ba1/67/d1/8b98ad3d0d67bf6bc23c2c9167cf",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/bf/a7/927941d5af60608348087bb7ecd2",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/c6/5d/da70d2fa77eae532b1561c2c8115",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/27/fe/52a04ab3e85736e41a545262121d",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/8f/5d/c3eceee36e50f5344d5308c443eb",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/37/66/0b7542b46e953e9f7261a59a1ec8",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/07/7c/488129817dede65aec11d0240144",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/ff/99/be91e7ce7f8755aa1cbcc1b40df5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/8b/2d/8bb91aa1677da94c21573e2bf43a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/42/ca/e8c47da7bab3ec0bddd17b5d9d36",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/13/0c/f422781a8977146f4cfeb8f80747",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/09/0a/f480d906922d9961c10adc00e380",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/5e/ac/790ed8a49f55ab7e61ece370e99d",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "https://files.ballistica.net/cache/ba1/17/cf/d35c4d5cb692903b1f67705f9c43",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "https://files.ballistica.net/cache/ba1/4e/a7/93fad7afb34dee1924f92b58451f",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "https://files.ballistica.net/cache/ba1/cb/02/fc48ae8cac41433539acd048e9ed",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "https://files.ballistica.net/cache/ba1/6a/39/f3d0300f87aadf8bf64313b0d69e",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "https://files.ballistica.net/cache/ba1/52/c6/c11130af7b10d6c0321add5518fa",
"src/assets/ba_data/python/babase/_mgen/enums.py": "https://files.ballistica.net/cache/ba1/38/c3/1dedd5e74f2508efc5974c8815a1",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "https://files.ballistica.net/cache/ba1/ea/6a/6a4721b144e5e297b542d2a0eea2",

View File

@ -2363,6 +2363,7 @@
<w>rcvs</w>
<w>rdict</w>
<w>rdir</w>
<w>rdynamic</w>
<w>readexactly</w>
<w>readline</w>
<w>readlines</w>

View File

@ -1,4 +1,4 @@
### 1.7.20 (build 21112, api 8, 2023-06-14)
### 1.7.20 (build 21114, api 8, 2023-06-15)
- This seems like a good time for a `refactoring` release in anticipation of
changes coming in 1.8. Basically this means that a lot of things will be
@ -329,6 +329,9 @@
Please holler if not.
- (build 21111) Fixed a server crash when an individual client player leaves the
game but doesn't disconnect from the server.
- (build 21113) Linux builds now use the '-rdynamic' flag which means stack
traces we capture in the engine are more readable; they at least show mangled
c++ symbols instead of just addresses.
### 1.7.19 (build 20997, api 7, 2023-01-19)

View File

@ -1360,6 +1360,7 @@
<w>rcade</w>
<w>rcva</w>
<w>rcvs</w>
<w>rdynamic</w>
<w>reaaaly</w>
<w>readexactly</w>
<w>readset</w>

View File

@ -744,6 +744,10 @@ add_executable(ballisticakit
# AUTOGENERATED_PUBLIC_END
)
# Gets -rdynamic added when linking gcc builds which exports all symbols
# which gives us more meaningful stack traces using backtrace_symbols().
set_target_properties(ballisticakit PROPERTIES ENABLE_EXPORTS 1)
if (HEADLESS)
set_target_properties(ballisticakit PROPERTIES OUTPUT_NAME "ballisticakit_headless")
endif ()

View File

@ -28,7 +28,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21112
TARGET_BALLISTICA_BUILD = 21114
TARGET_BALLISTICA_VERSION = '1.7.20'
_g_env_config: EnvConfig | None = None

View File

@ -133,7 +133,7 @@ class DeathMatchGame(bs.TeamGameActivity[Player, Team]):
# Base kills needed to win on the size of the largest team.
self._score_to_win = self._kills_to_win_per_player * max(
1, max(len(t.players) for t in self.teams)
1, max((len(t.players) for t in self.teams), default=0)
)
self._update_scoreboard()

View File

@ -89,6 +89,91 @@ void NetworkReader::PokeSelf() {
}
}
void NetworkReader::DoPoll(bool* can_read_4, bool* can_read_6) {
struct pollfd fds[2]{};
int i{};
int index_4{-1};
int index_6{-1};
if (sd4_ != -1) {
fds[i].fd = sd4_;
fds[i].events = POLLIN;
index_4 = i++;
}
if (sd6_ != -1) {
fds[i].fd = sd6_;
fds[i].events = POLLIN;
index_6 = i++;
}
if (i > 0) {
int result = BA_SOCKET_POLL(fds, i, -1);
if (result == BA_SOCKET_ERROR_RETURN) {
// No big deal if we get interrupted occasionally.
if (g_core->platform->GetSocketError() == EINTR) {
// Aint no thang.
} else {
// Let's complain for anything else though.
Log(LogLevel::kError,
"Error on select: " + g_core->platform->GetSocketErrorString());
}
} else {
*can_read_4 = index_4 != -1 && fds[index_4].revents & POLLIN;
*can_read_6 = index_6 != -1 && fds[index_6].revents & POLLIN;
}
} else {
BA_LOG_ONCE(LogLevel::kError, "DoPoll called with neither sd4 or sd6 set.");
}
}
void NetworkReader::DoSelect(bool* can_read_4, bool* can_read_6) {
fd_set readset;
FD_ZERO(&readset);
if (sd4_ != -1) {
if (!g_buildconfig.ostype_windows()) {
// Try to get a clean error instead of a crash if we exceed our
// open file descriptor limit (except on windows where FD_SETSIZE
// is apparently a dummy value).
CheckFDThreshold(sd4_);
if (sd4_ < 0 || sd4_ >= FD_SETSIZE) {
FatalError("Socket/File Descriptor Overflow (sd4="
+ std::to_string(sd4_) + ", FD_SETSIZE="
+ std::to_string(FD_SETSIZE) + "). Please report this.");
}
}
FD_SET(sd4_, &readset); // NOLINT
}
if (sd6_ != -1) {
if (!g_buildconfig.ostype_windows()) {
// Try to get a clean error instead of a crash if we exceed our
// open file descriptor limit (except on windows where FD_SETSIZE
// is apparently a dummy value).
CheckFDThreshold(sd6_);
if (sd6_ < 0 || sd6_ >= FD_SETSIZE) {
FatalError("Socket/File Descriptor Overflow (sd6="
+ std::to_string(sd6_) + ", FD_SETSIZE="
+ std::to_string(FD_SETSIZE) + "). Please report this.");
}
}
FD_SET(sd6_, &readset); // NOLINT
}
int maxfd = std::max(sd4_, sd6_);
int sresult = select(maxfd + 1, &readset, nullptr, nullptr, nullptr);
if (sresult == BA_SOCKET_ERROR_RETURN) {
// No big deal if we get interrupted occasionally.
if (g_core->platform->GetSocketError() == EINTR) {
// Aint no thang.
} else {
// Let's complain for anything else though.
Log(LogLevel::kError,
"Error on select: " + g_core->platform->GetSocketErrorString());
}
} else {
*can_read_4 = sd4_ != -1 && FD_ISSET(sd4_, &readset);
*can_read_6 = sd6_ != -1 && FD_ISSET(sd6_, &readset);
}
}
void NetworkReader::CheckFDThreshold(int val) {
if (passed_fd_threshold_) {
return;
@ -130,67 +215,67 @@ auto NetworkReader::RunThread() -> int {
while (true) {
sockaddr_storage from{};
socklen_t from_size = sizeof(from);
fd_set readset;
FD_ZERO(&readset);
if (sd4_ != -1) {
if (!g_buildconfig.ostype_windows()) {
// Try to get a clean error instead of a crash if we exceed our
// open file descriptor limit (except on windows where FD_SETSIZE
// is apparently a dummy value).
CheckFDThreshold(sd4_);
if (sd4_ < 0 || sd4_ >= FD_SETSIZE) {
FatalError("Socket/File Descriptor Overflow (sd4="
+ std::to_string(sd4_) + ", FD_SETSIZE="
+ std::to_string(FD_SETSIZE) + "). Please report this.");
}
}
FD_SET(sd4_, &readset); // NOLINT
}
if (sd6_ != -1) {
if (!g_buildconfig.ostype_windows()) {
// Try to get a clean error instead of a crash if we exceed our
// open file descriptor limit (except on windows where FD_SETSIZE
// is apparently a dummy value).
CheckFDThreshold(sd6_);
if (sd6_ < 0 || sd6_ >= FD_SETSIZE) {
FatalError("Socket/File Descriptor Overflow (sd6="
+ std::to_string(sd6_) + ", FD_SETSIZE="
+ std::to_string(FD_SETSIZE) + "). Please report this.");
}
}
FD_SET(sd6_, &readset); // NOLINT
}
int maxfd = std::max(sd4_, sd6_);
int sresult = select(maxfd + 1, &readset, nullptr, nullptr, nullptr);
if (sresult == -1) {
// No big deal if we get interrupted occasionally.
if (g_core->platform->GetSocketError() == EINTR) {
// Aint no thang.
} else {
// Let's complain for anything else though.
Log(LogLevel::kError,
"Error on select: " + g_core->platform->GetSocketErrorString());
}
bool can_read_4{};
bool can_read_6{};
// A bit of history here: Had been using select() to wait for input
// here, but recently I've started seeing newer versions of android
// crashing due to file descriptor counts going over the standard set
// limit size of ~1000 or whatnot. So switching to poll() instead which
// sounds like it
if (explicit_bool(true)) {
DoPoll(&can_read_4, &can_read_6);
} else {
// Wait for any data on either of our sockets.
for (int sd : {sd4_, sd6_}) {
if (sd == -1 || !(FD_ISSET(sd, &readset))) {
continue;
DoSelect(&can_read_4, &can_read_6);
}
for (int s_index : {0, 1}) {
int sd;
bool can_read;
if (s_index == 0) {
sd = sd4_;
can_read = can_read_4;
} else if (s_index == 1) {
sd = sd6_;
can_read = can_read_6;
} else {
FatalError("Should not get here.");
sd = -1;
can_read = false;
}
if (!can_read) {
continue;
}
ssize_t rresult =
recvfrom(sd, buffer, sizeof(buffer), 0,
reinterpret_cast<sockaddr*>(&from), &from_size);
if (rresult == 0) {
Log(LogLevel::kError,
"NetworkReader Recv got length 0; this shouldn't "
"happen");
} else if (rresult == -1) {
// This needs to be locked during any sd changes/writes.
std::scoped_lock lock(sd_mutex_);
// If either of our sockets goes down lets close *both* of
// them.
if (sd4_ != -1) {
g_core->platform->CloseSocket(sd4_);
sd4_ = -1;
}
ssize_t rresult =
recvfrom(sd, buffer, sizeof(buffer), 0,
reinterpret_cast<sockaddr*>(&from), &from_size);
if (rresult == 0) {
Log(LogLevel::kError,
"NetworkReader Recv got length 0; this shouldn't "
"happen");
} else if (rresult == -1) {
if (sd6_ != -1) {
g_core->platform->CloseSocket(sd6_);
sd6_ = -1;
}
} else {
assert(from_size >= 0);
auto rresult2{static_cast<size_t>(rresult)};
// If we get *any* data while paused, kill both our
// sockets (we ping ourself for this purpose).
if (paused_) {
// This needs to be locked during any sd changes/writes.
std::scoped_lock lock(sd_mutex_);
// If either of our sockets goes down lets close *both* of
// them.
if (sd4_ != -1) {
g_core->platform->CloseSocket(sd4_);
sd4_ = -1;
@ -199,118 +284,101 @@ auto NetworkReader::RunThread() -> int {
g_core->platform->CloseSocket(sd6_);
sd6_ = -1;
}
} else {
assert(from_size >= 0);
auto rresult2{static_cast<size_t>(rresult)};
// If we get *any* data while paused, kill both our
// sockets (we ping ourself for this purpose).
if (paused_) {
break;
}
switch (buffer[0]) {
case BA_PACKET_POKE:
break;
case BA_PACKET_SIMPLE_PING: {
// This needs to be locked during any sd changes/writes.
std::scoped_lock lock(sd_mutex_);
if (sd4_ != -1) {
g_core->platform->CloseSocket(sd4_);
sd4_ = -1;
}
if (sd6_ != -1) {
g_core->platform->CloseSocket(sd6_);
sd6_ = -1;
char msg[1] = {BA_PACKET_SIMPLE_PONG};
sendto(sd, msg, 1, 0, reinterpret_cast<sockaddr*>(&from),
from_size);
break;
}
case BA_PACKET_JSON_PING: {
if (rresult2 > 1) {
std::vector<char> s_buffer(rresult2);
memcpy(s_buffer.data(), buffer + 1, rresult2 - 1);
s_buffer[rresult2 - 1] = 0; // terminate string
std::string response =
g_base->app_mode()->HandleJSONPing(s_buffer.data());
if (!response.empty()) {
std::vector<char> msg(1 + response.size());
msg[0] = BA_PACKET_JSON_PONG;
memcpy(msg.data() + 1, response.c_str(), response.size());
std::scoped_lock lock(sd_mutex_);
sendto(
sd, msg.data(),
static_cast_check_fit<socket_send_length_t>(msg.size()),
0, reinterpret_cast<sockaddr*>(&from), from_size);
}
}
break;
}
switch (buffer[0]) {
case BA_PACKET_POKE:
break;
case BA_PACKET_SIMPLE_PING: {
// This needs to be locked during any sd changes/writes.
std::scoped_lock lock(sd_mutex_);
char msg[1] = {BA_PACKET_SIMPLE_PONG};
sendto(sd, msg, 1, 0, reinterpret_cast<sockaddr*>(&from),
from_size);
break;
}
case BA_PACKET_JSON_PING: {
if (rresult2 > 1) {
std::vector<char> s_buffer(rresult2);
memcpy(s_buffer.data(), buffer + 1, rresult2 - 1);
s_buffer[rresult2 - 1] = 0; // terminate string
std::string response =
g_base->app_mode()->HandleJSONPing(s_buffer.data());
if (!response.empty()) {
std::vector<char> msg(1 + response.size());
msg[0] = BA_PACKET_JSON_PONG;
memcpy(msg.data() + 1, response.c_str(), response.size());
std::scoped_lock lock(sd_mutex_);
sendto(
sd, msg.data(),
static_cast_check_fit<socket_send_length_t>(msg.size()),
0, reinterpret_cast<sockaddr*>(&from), from_size);
}
case BA_PACKET_JSON_PONG: {
if (rresult2 > 1) {
std::vector<char> s_buffer(rresult2);
memcpy(s_buffer.data(), buffer + 1, rresult2 - 1);
s_buffer[rresult2 - 1] = 0; // terminate string
cJSON* data = cJSON_Parse(s_buffer.data());
if (data != nullptr) {
cJSON_Delete(data);
}
break;
}
case BA_PACKET_JSON_PONG: {
if (rresult2 > 1) {
std::vector<char> s_buffer(rresult2);
memcpy(s_buffer.data(), buffer + 1, rresult2 - 1);
s_buffer[rresult2 - 1] = 0; // terminate string
cJSON* data = cJSON_Parse(s_buffer.data());
if (data != nullptr) {
cJSON_Delete(data);
}
}
break;
}
case BA_PACKET_REMOTE_PING:
case BA_PACKET_REMOTE_PONG:
case BA_PACKET_REMOTE_ID_REQUEST:
case BA_PACKET_REMOTE_ID_RESPONSE:
case BA_PACKET_REMOTE_DISCONNECT:
case BA_PACKET_REMOTE_STATE:
case BA_PACKET_REMOTE_STATE2:
case BA_PACKET_REMOTE_STATE_ACK:
case BA_PACKET_REMOTE_DISCONNECT_ACK:
case BA_PACKET_REMOTE_GAME_QUERY:
case BA_PACKET_REMOTE_GAME_RESPONSE:
// These packets are associated with the remote app; let the
// remote server handle them.
if (remote_server_) {
remote_server_->HandleData(
sd, reinterpret_cast<uint8_t*>(buffer), rresult2,
reinterpret_cast<sockaddr*>(&from),
static_cast<size_t>(from_size));
}
break;
case BA_PACKET_CLIENT_REQUEST:
case BA_PACKET_CLIENT_ACCEPT:
case BA_PACKET_CLIENT_DENY:
case BA_PACKET_CLIENT_DENY_ALREADY_IN_PARTY:
case BA_PACKET_CLIENT_DENY_VERSION_MISMATCH:
case BA_PACKET_CLIENT_DENY_PARTY_FULL:
case BA_PACKET_DISCONNECT_FROM_CLIENT_REQUEST:
case BA_PACKET_DISCONNECT_FROM_CLIENT_ACK:
case BA_PACKET_DISCONNECT_FROM_HOST_REQUEST:
case BA_PACKET_DISCONNECT_FROM_HOST_ACK:
case BA_PACKET_CLIENT_GAMEPACKET_COMPRESSED:
case BA_PACKET_HOST_GAMEPACKET_COMPRESSED: {
// These messages are associated with udp host/client
// connections.. pass them to the logic thread to wrangle.
std::vector<uint8_t> msg_buffer(rresult2);
memcpy(msg_buffer.data(), buffer, rresult2);
PushIncomingUDPPacketCall(msg_buffer, SockAddr(from));
break;
}
case BA_PACKET_HOST_QUERY: {
g_base->app_mode()->HandleGameQuery(buffer, rresult2, &from);
// HandleGameQuery(buffer, rresult2, &from);
break;
}
default:
break;
break;
}
case BA_PACKET_REMOTE_PING:
case BA_PACKET_REMOTE_PONG:
case BA_PACKET_REMOTE_ID_REQUEST:
case BA_PACKET_REMOTE_ID_RESPONSE:
case BA_PACKET_REMOTE_DISCONNECT:
case BA_PACKET_REMOTE_STATE:
case BA_PACKET_REMOTE_STATE2:
case BA_PACKET_REMOTE_STATE_ACK:
case BA_PACKET_REMOTE_DISCONNECT_ACK:
case BA_PACKET_REMOTE_GAME_QUERY:
case BA_PACKET_REMOTE_GAME_RESPONSE:
// These packets are associated with the remote app; let the
// remote server handle them.
if (remote_server_) {
remote_server_->HandleData(
sd, reinterpret_cast<uint8_t*>(buffer), rresult2,
reinterpret_cast<sockaddr*>(&from),
static_cast<size_t>(from_size));
}
break;
case BA_PACKET_CLIENT_REQUEST:
case BA_PACKET_CLIENT_ACCEPT:
case BA_PACKET_CLIENT_DENY:
case BA_PACKET_CLIENT_DENY_ALREADY_IN_PARTY:
case BA_PACKET_CLIENT_DENY_VERSION_MISMATCH:
case BA_PACKET_CLIENT_DENY_PARTY_FULL:
case BA_PACKET_DISCONNECT_FROM_CLIENT_REQUEST:
case BA_PACKET_DISCONNECT_FROM_CLIENT_ACK:
case BA_PACKET_DISCONNECT_FROM_HOST_REQUEST:
case BA_PACKET_DISCONNECT_FROM_HOST_ACK:
case BA_PACKET_CLIENT_GAMEPACKET_COMPRESSED:
case BA_PACKET_HOST_GAMEPACKET_COMPRESSED: {
// These messages are associated with udp host/client
// connections.. pass them to the logic thread to wrangle.
std::vector<uint8_t> msg_buffer(rresult2);
memcpy(msg_buffer.data(), buffer, rresult2);
PushIncomingUDPPacketCall(msg_buffer, SockAddr(from));
break;
}
case BA_PACKET_HOST_QUERY: {
g_base->app_mode()->HandleGameQuery(buffer, rresult2, &from);
// HandleGameQuery(buffer, rresult2, &from);
break;
}
default:
break;
}
}
}

View File

@ -34,6 +34,8 @@ class NetworkReader {
private:
void CheckFDThreshold(int val);
void DoSelect(bool* can_read_4, bool* can_read_6);
void DoPoll(bool* can_read_4, bool* can_read_6);
void OpenSockets();
void PokeSelf();
auto RunThread() -> int;

View File

@ -926,14 +926,10 @@ auto SceneV1AppMode::GetNetworkDebugString() -> std::string {
return net_info_str;
}
auto SceneV1AppMode::GetDisplayPing() -> std::optional<float> {
float ping{};
char ping_str[32];
if (ConnectionToHost* connection_to_host =
connections()->connection_to_host()) {
if (connection_to_host->can_communicate()) {
return connection_to_host->current_ping();
// snprintf(ping_str, sizeof(ping_str), "%.0f ms", ping);
// return ping_str;
}
}
return {};

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21112;
const int kEngineBuildNumber = 21114;
const char* kEngineVersion = "1.7.20";
auto MonolithicMain(const core::CoreConfig& core_config) -> int {

View File

@ -185,6 +185,18 @@ namespace ballistica {
#define BA_ARCADE_BUILD 0
#endif
#ifndef BA_SOCKET_POLL_FD
#define BA_SOCKET_POLL_FD pollfd
#endif
#ifndef BA_SOCKET_ERROR_RETURN
#define BA_SOCKET_ERROR_RETURN -1
#endif
#ifndef BA_SOCKET_POLL
#define BA_SOCKET_POLL poll
#endif
#ifndef BA_SOCKET_SEND_DATA_TYPE
#define BA_SOCKET_SEND_DATA_TYPE uint8_t
#endif

View File

@ -39,6 +39,11 @@
#define BA_SOCKET_SEND_LENGTH_TYPE int
#define BA_SOCKET_SETSOCKOPT_VAL_TYPE char
#define BA_SOCKET_POLL WSAPoll
#define BA_SOCKET_POLL_FD POLLFD
#define BA_SOCKET_ERROR_RETURN SOCKET_ERROR
// On windows we always bundle python.
#define BA_CONTAINS_PYTHON_DIST 1

View File

@ -15,6 +15,7 @@
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>