3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-12-25 12:12:53 +01:00

IRCNetwork: fix broken ping timeout handling

Check for ping outs in the ping scheduler instead of the listener... If the connection is dead, the listener won't ever be called.
This commit is contained in:
James Lu 2018-06-14 00:41:00 -07:00
parent b2421f5e15
commit 56c035a1f5

View File

@ -1528,6 +1528,10 @@ class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
class TLSValidationError(ConnectionError):
"""Exception raised when additional TLS verifications fail."""
# When this many pings in a row are missed, the ping timer loop will force a disconnect on the
# next cycle. Effectively the ping timeout is: pingfreq * (KEEPALIVE_MAX_MISSED + 1)
KEEPALIVE_MAX_MISSED = 2
class IRCNetwork(PyLinkNetworkCoreWithUtils):
S2S_BUFSIZE = 510
@ -1546,9 +1550,8 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
super()._init_vars(*args, **kwargs)
# Set IRC specific variables for ping checking and queuing
self.lastping = time.time()
self.lastping = time.time() # This actually tracks the last message received as of 2.0-alpha4
self.pingfreq = self.serverdata.get('pingfreq') or 90
self.pingtimeout = self.pingfreq * 3
self.maxsendq = self.serverdata.get('maxsendq', 4096)
self._queue = queue.Queue(self.maxsendq)
@ -1560,6 +1563,12 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
if self._aborted.is_set():
return
elapsed = time.time() - self.lastping
if elapsed > (self.pingfreq * KEEPALIVE_MAX_MISSED):
log.error('(%s) Disconnected from IRC: Ping timeout (%d secs)', self.name, elapsed)
self.disconnect()
return
self._ping_timer = threading.Timer(self.pingfreq, self._schedule_ping)
self._ping_timer.daemon = True
self._ping_timer.name = 'Ping timer loop for %s' % self.name
@ -1673,7 +1682,6 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
log.info("Connecting to network %r on %s:%s", self.name, ip, port)
# Use a lower timeout for the initial connect.
self._socket.settimeout(self.pingfreq)
# Start the actual connection
@ -1688,8 +1696,6 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
self._socket.close()
return
self._socket.settimeout(self.pingtimeout)
# Make sure future reads never block, since select doesn't always guarantee this.
self._socket.setblocking(False)
@ -1847,10 +1853,6 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
self._log_connection_error('(%s) Connection lost, disconnecting.', self.name)
self.disconnect()
return
elif (time.time() - self.lastping) > self.pingtimeout:
self._log_connection_error('(%s) Connection timed out.', self.name)
self.disconnect()
return
while b'\n' in self._buffer:
line, self._buffer = self._buffer.split(b'\n', 1)
@ -1858,6 +1860,9 @@ class IRCNetwork(PyLinkNetworkCoreWithUtils):
line = line.decode(self.encoding, "replace")
self.parse_irc_command(line)
# Update the last message received time
self.lastping = time.time()
def _send(self, data):
"""Sends raw text to the uplink server."""
if self._aborted.is_set():