From dc85bd6f86dc2378018519dc5b2fa81ac1b85ddd Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 25 Feb 2012 22:33:55 -0500 Subject: [PATCH] Implement Game auto pinger Evidently, the game connection never actually pinged. Instead, it relied on the propagation of a redundant game message. This is evil because we can sometimes hang out in the loading process for quite some time (eg beyond the socket timeout on either end) --- .../plNetGameLib/Private/plNglGame.cpp | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp index 1040c346..1c376e2f 100644 --- a/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp +++ b/Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp @@ -74,6 +74,11 @@ struct CliGmConn : AtomicRef { CliGmConn (); ~CliGmConn (); + // ping + void AutoPing (); + void StopAutoPing (); + void TimerPing (); + void Send (const uintptr_t fields[], unsigned count); }; @@ -207,6 +212,8 @@ static void UnlinkAndAbandonConn_CS (CliGmConn * conn) { //============================================================================ static bool ConnEncrypt (ENetError error, void * param) { CliGmConn * conn = (CliGmConn *) param; + if (!s_perf[kPingDisabled]) + conn->AutoPing(); if (IS_NET_SUCCESS(error)) { s_critsect.Enter(); @@ -262,6 +269,7 @@ static void NotifyConnSocketConnectFailed (CliGmConn * conn) { //============================================================================ static void NotifyConnSocketDisconnect (CliGmConn * conn) { + conn->StopAutoPing(); bool notify; s_critsect.Enter(); @@ -392,6 +400,19 @@ static void Connect ( * ***/ +//=========================================================================== +static unsigned CliGmConnTimerDestroyed (void * param) { + CliGmConn * conn = (CliGmConn *) param; + conn->DecRef("TimerDestroyed"); + return kAsyncTimeInfinite; +} + +//=========================================================================== +static unsigned CliGmConnPingTimerProc (void * param) { + ((CliGmConn *) param)->TimerPing(); + return kPingIntervalMs; +} + //============================================================================ CliGmConn::CliGmConn () { AtomicAdd(&s_perf[kPerfConnCount], 1); @@ -404,6 +425,59 @@ CliGmConn::~CliGmConn () { AtomicAdd(&s_perf[kPerfConnCount], -1); } +//============================================================================ +void CliGmConn::AutoPing () { + ASSERT(!pingTimer); + IncRef("PingTimer"); + critsect.Enter(); + { + AsyncTimerCreate( + &pingTimer, + CliGmConnPingTimerProc, + sock ? 0 : kAsyncTimeInfinite, + this + ); + } + critsect.Leave(); +} + +//============================================================================ +void CliGmConn::StopAutoPing () { + critsect.Enter(); + { + if (AsyncTimer * timer = pingTimer) { + pingTimer = nil; + AsyncTimerDeleteCallback(timer, CliGmConnTimerDestroyed); + } + } + critsect.Leave(); +} + +//============================================================================ +void CliGmConn::TimerPing () { + +#if 0 + // if the time difference between when we last sent a ping and when we last + // heard from the server is >= 3x the ping interval, the socket is stale. + if (pingSendTimeMs && abs(int(pingSendTimeMs - lastHeardTimeMs)) >= kPingTimeoutMs) { + // ping timed out, disconnect the socket + AsyncSocketDisconnect(sock, true); + } + else +#endif + { + // Send a ping request + pingSendTimeMs = GetNonZeroTimeMs(); + + const uintptr_t msg[] = { + kCli2Game_PingRequest, + pingSendTimeMs + }; + + Send(msg, arrsize(msg)); + } +} + //============================================================================ void CliGmConn::Send (const uintptr_t fields[], unsigned count) { critsect.Enter(); @@ -710,6 +784,17 @@ unsigned GameGetConnId () { //============================================================================ void GamePingEnable (bool enable) { s_perf[kPingDisabled] = !enable; + s_critsect.Enter(); + for (;;) { + if (!s_active) + break; + if (enable) + s_active->AutoPing(); + else + s_active->StopAutoPing(); + break; + } + s_critsect.Leave(); } } using namespace Ngl;