Browse Source

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)
Adam Johnson 13 years ago
parent
commit
dc85bd6f86
  1. 85
      Sources/Plasma/PubUtilLib/plNetGameLib/Private/plNglGame.cpp

85
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;

Loading…
Cancel
Save