commit dc6807338e240d8093f43337dab7bfe488c35c4a from: Alexander Barton date: Mon May 25 20:59:58 2020 UTC 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. : time stamp of last sent out PING command. commit - 0d503945cb527e275ef6644a234a6876ff61322b commit + dc6807338e240d8093f43337dab7bfe488c35c4a blob - 72d38b8621ff559c9c93903989e7c091b018be79 blob + 3cf8a3a62b27d43ce32fcc1101f765dac3775fb7 --- src/ngircd/conn-func.c +++ src/ngircd/conn-func.c @@ -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; } /* blob - 1d05acc88d5623979a371e80aedc3f4a61e480c8 blob + 37f70363a8b24c1221798442be74c35ef2acf672 --- src/ngircd/conn-func.h +++ src/ngircd/conn-func.h @@ -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 )); blob - c304fdb574ffc497552f76fec4c531bb5c359abe blob + 94c6c4a8b1683fa75ca3fd4f6daaf98884d29dfd --- src/ngircd/conn.c +++ src/ngircd/conn.c @@ -1866,7 +1866,10 @@ 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) continue; @@ -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); blob - 846b10d6e8aa2f08951c393f545aba0deb8ae331 blob + f682e216f273279501d33a036973cdb738ba9848 --- src/ngircd/irc-login.c +++ src/ngircd/irc-login.c @@ -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 */