From d2836d195fc1145530b2af6190dfe4b4994a8f99 Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 12 Jul 2026 22:19:34 -0500 Subject: [PATCH] Steam transport: full connection diagnostics + polled connect state The three-machine test failed at exactly one step: the owner''s ConnectByIPAddress to a member''s fake console port retried silently for 120s while the member WAS listening on that port. The transport threw away Steam''s reason for killing each attempt. Now every connection state change logs the connection description, and drops log the end reason plus Steam''s debug string - the next run will say exactly which subsystem refused (cert, FakeIP directory, routing, accept). Connect also polls GetConnectionInfo directly instead of trusting only the callback flags, logs each attempt''s final state, no longer holds a pointer into the connection table across mutations, and paces retries at 1s. Co-Authored-By: Claude Fable 5 --- MUNGA_L4/L4STEAMTRANSPORT.cpp | 59 ++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/MUNGA_L4/L4STEAMTRANSPORT.cpp b/MUNGA_L4/L4STEAMTRANSPORT.cpp index 2cccc35..6e38734 100644 --- a/MUNGA_L4/L4STEAMTRANSPORT.cpp +++ b/MUNGA_L4/L4STEAMTRANSPORT.cpp @@ -169,11 +169,21 @@ namespace if (status->m_info.m_hListenSocket != k_HSteamListenSocket_Invalid) { // incoming: accept immediately, queue it when Connected - SteamNetworkingSockets()->AcceptConnection(status->m_hConn); + DEBUG_STREAM << "SteamNetTransport: incoming [" + << status->m_info.m_szConnectionDescription + << "] - accepting\n" << std::flush; + EResult accepted = SteamNetworkingSockets()->AcceptConnection(status->m_hConn); + if (accepted != k_EResultOK) + { + DEBUG_STREAM << "SteamNetTransport: AcceptConnection failed (EResult " + << (int) accepted << ")\n" << std::flush; + } } break; case k_ESteamNetworkingConnectionState_Connected: + DEBUG_STREAM << "SteamNetTransport: connected [" + << status->m_info.m_szConnectionDescription << "]\n" << std::flush; if (status->m_info.m_hListenSocket != k_HSteamListenSocket_Invalid) { ListenerRecord *listener = FindListener(status->m_info.m_hListenSocket); @@ -195,6 +205,10 @@ namespace case k_ESteamNetworkingConnectionState_ProblemDetectedLocally: case k_ESteamNetworkingConnectionState_ClosedByPeer: { + DEBUG_STREAM << "SteamNetTransport: dropped [" + << status->m_info.m_szConnectionDescription + << "] end reason " << status->m_info.m_eEndReason + << ": " << status->m_info.m_szEndDebug << "\n" << std::flush; ConnectionRecord *record = FindConnection(status->m_hConn); if (record != NULL) { @@ -304,29 +318,60 @@ namespace // mirror the TCP retry-while-refused loop, bounded: the // egg-ACK ordering means the peer may not be listening yet DWORD deadline = GetTickCount() + 120 * 1000; + int attempt = 0; for (;;) { + ++attempt; HSteamNetConnection handle = SteamNetworkingSockets()->ConnectByIPAddress(target, 1, &option); if (handle == k_HSteamNetConnection_Invalid) { + DEBUG_STREAM << "SteamNetTransport: ConnectByIPAddress refused the call\n" << std::flush; return InvalidConnection; } - ConnectionRecord *record = - AddConnection(handle, remote->sin_addr.S_un.S_addr, remote->sin_port); + AddConnection(handle, remote->sin_addr.S_un.S_addr, remote->sin_port); - while (!record->connected && !record->dead && - (LONG)(GetTickCount() - deadline) < 0) + // + // Poll the connection state directly (the callback also + // runs, for the log and the accept queues) + // + ESteamNetworkingConnectionState state = + k_ESteamNetworkingConnectionState_Connecting; + while ((LONG)(GetTickCount() - deadline) < 0) { SteamAPI_RunCallbacks(); + + SteamNetConnectionInfo_t info; + if (!SteamNetworkingSockets()->GetConnectionInfo(handle, &info)) + { + state = k_ESteamNetworkingConnectionState_Dead; + break; + } + state = info.m_eState; + if (state == k_ESteamNetworkingConnectionState_Connected || + state == k_ESteamNetworkingConnectionState_ProblemDetectedLocally || + state == k_ESteamNetworkingConnectionState_ClosedByPeer || + state == k_ESteamNetworkingConnectionState_None) + { + break; + } Sleep(25); } - if (record->connected) + if (state == k_ESteamNetworkingConnectionState_Connected) { + ConnectionRecord *record = FindConnection(handle); + if (record != NULL) + { + record->connected = True; + } + DEBUG_STREAM << "SteamNetTransport: connect succeeded (attempt " + << attempt << ")\n" << std::flush; return (Connection) handle; } // attempt failed - drop it and retry until the deadline + DEBUG_STREAM << "SteamNetTransport: attempt " << attempt + << " ended in state " << (int) state << "\n" << std::flush; SteamNetworkingSockets()->CloseConnection(handle, 0, "retry", false); RemoveConnection(handle); if ((LONG)(GetTickCount() - deadline) >= 0) @@ -334,7 +379,7 @@ namespace DEBUG_STREAM << "SteamNetTransport: connect timed out\n" << std::flush; return InvalidConnection; } - Sleep(250); + Sleep(1000); } }