1
0
mirror of https://github.com/osmarks/ngircd.git synced 2024-12-13 02:10:27 +00:00

Fix PING-PONG handling when processing backlog in read buffers

Prior to this commit, the PONG wasn't registered correctly, becauuse the
"last ping" time was set to time(NULL), which could be bigger than the
"last data" time stamp, for example when handling the read buffer took
more than 1 second -- and this resulted in the PONG time out kicking in
effectively disconnecting a newly linked server for example, because
ngIRCd thought it was still waiting for a PONG: last data < last ping.

Now the "last ping" value has three possible values:

    0: new connection, no PING, no PONG so far.
    1: got a PONG, no longer waiting for a PONG.
  <t>: time stamp of last sent out PING command.
This commit is contained in:
Alexander Barton 2020-05-25 19:02:16 +02:00
parent 0d503945cb
commit dc6807338e
4 changed files with 16 additions and 8 deletions

View File

@ -45,13 +45,17 @@ Conn_UpdateIdle(CONN_ID Idx)
/**
* Update "ping timestamp", the time of the last outgoing PING request.
*
* the value 0 signals a newly connected client including servers during the
* initial "server burst"; and 1 means that no PONG is pending for a PING.
*
* @param Idx Connection index.
* @param TimeStamp 0, 1, or time stamp.
*/
GLOBAL void
Conn_UpdatePing(CONN_ID Idx)
Conn_UpdatePing(CONN_ID Idx, time_t TimeStamp)
{
assert(Idx > NONE);
My_Connections[Idx].lastping = time(NULL);
My_Connections[Idx].lastping = TimeStamp;
}
/*

View File

@ -30,7 +30,7 @@
GLOBAL void Conn_UpdateIdle PARAMS((CONN_ID Idx));
GLOBAL void Conn_UpdatePing PARAMS((CONN_ID Idx));
GLOBAL void Conn_UpdatePing PARAMS((CONN_ID Idx, time_t TimeStamp));
GLOBAL time_t Conn_GetSignon PARAMS((CONN_ID Idx));
GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx ));

View File

@ -1866,6 +1866,9 @@ Check_Connections(void)
CLIENT *c;
CONN_ID i;
char msg[64];
time_t time_now;
time_now = time(NULL);
for (i = 0; i < Pool_Size; i++) {
if (My_Connections[i].sock < 0)
@ -1880,7 +1883,7 @@ Check_Connections(void)
My_Connections[i].lastdata) {
/* We already sent a ping */
if (My_Connections[i].lastping <
time(NULL) - Conf_PongTimeout) {
time_now - Conf_PongTimeout) {
/* Timeout */
snprintf(msg, sizeof(msg),
"Ping timeout: %d seconds",
@ -1889,10 +1892,10 @@ Check_Connections(void)
Conn_Close(i, NULL, msg, true);
}
} else if (My_Connections[i].lastdata <
time(NULL) - Conf_PingTimeout) {
time_now - Conf_PingTimeout) {
/* We need to send a PING ... */
LogDebug("Connection %d: sending PING ...", i);
Conn_UpdatePing(i);
Conn_UpdatePing(i, time_now);
Conn_WriteStr(i, "PING :%s",
Client_ID(Client_ThisServer()));
}
@ -1903,7 +1906,7 @@ Check_Connections(void)
* still not registered. */
if (My_Connections[i].lastdata <
time(NULL) - Conf_PongTimeout) {
time_now - Conf_PongTimeout) {
LogDebug
("Unregistered connection %d timed out ...",
i);

View File

@ -877,11 +877,12 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
(long)(time(NULL) - Conn_GetSignon(conn)),
time(NULL) - Conn_GetSignon(conn) == 1 ? "" : "s",
Client_UserCount(), Channel_CountVisible(NULL));
Conn_UpdatePing(conn);
} else
LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
conn, (long)(time(NULL) - Conn_LastPing(conn)));
/* We got a PONG, so signal that none is pending on this connection. */
Conn_UpdatePing(conn, 1);
return CONNECTED;
} /* IRC_PONG */