From 58e1cc47b973fcfff85e7a5d00ed6430312694bf Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 13 Feb 2026 01:47:56 -0800 Subject: [PATCH] WorldSocket: parse buffered packets before handling FIN close --- src/network/world_socket.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/network/world_socket.cpp b/src/network/world_socket.cpp index 4604d62f..9ba4dcfa 100644 --- a/src/network/world_socket.cpp +++ b/src/network/world_socket.cpp @@ -250,6 +250,11 @@ void WorldSocket::send(const Packet& packet) { void WorldSocket::update() { if (!connected) return; + // Drain the socket. Some servers send an auth response and immediately close; a single recv() + // may read the response, and a subsequent recv() can return 0 (FIN). If we disconnect right + // away we lose the buffered response and the UI ends up with a generic "no characters" symptom. + bool sawClose = false; + bool receivedAny = false; size_t bytesReadThisTick = 0; int readOps = 0; while (connected) { @@ -257,6 +262,7 @@ void WorldSocket::update() { ssize_t received = net::portableRecv(sockfd, buffer, sizeof(buffer)); if (received > 0) { + receivedAny = true; ++readOps; bytesReadThisTick += static_cast(received); receiveBuffer.insert(receiveBuffer.end(), buffer, buffer + received); @@ -270,9 +276,8 @@ void WorldSocket::update() { } if (received == 0) { - LOG_INFO("World server connection closed"); - disconnect(); - return; + sawClose = true; + break; } int err = net::lastError(); @@ -285,7 +290,7 @@ void WorldSocket::update() { return; } - if (bytesReadThisTick > 0) { + if (receivedAny) { LOG_DEBUG("World socket read ", bytesReadThisTick, " bytes in ", readOps, " recv call(s), buffered=", receiveBuffer.size()); tryParsePackets(); @@ -294,6 +299,12 @@ void WorldSocket::update() { " bytes buffered (awaiting complete packet)"); } } + + if (sawClose) { + LOG_INFO("World server connection closed"); + disconnect(); + return; + } } void WorldSocket::tryParsePackets() {