App-level keepalive

This commit is contained in:
Dpeta 2022-08-14 20:44:28 +02:00
parent f78a9f97ac
commit 3d740658b0
4 changed files with 66 additions and 10 deletions

View file

@ -1,10 +1,17 @@
# Changelog # Changelog
(This document uses YYYY-MM-DD) (This document uses YYYY-MM-DD)
## [v2.4.2] - 2022-07-08 ## [v2.4.2] - 2022-08-14
### Added
- Application-level connection checks:
- Send ping if we haven't received any data from the server in 30 seconds.
- Show S3RV3R NOT R3SPOND1NG if the server hasn't responded in 45 seconds. (15 seconds after ping)
- Close connection and try to reconnect if the server hasn't responded in 90 seconds. (60 seconds after ping)
### Fixed ### Fixed
- Error when manually moving group. - Error when manually moving group.
- EOF on send not resulting in a disconnect.
## [v2.4.1] - 2022-07-05 ## [v2.4.1] - 2022-07-05

14
irc.py
View file

@ -40,6 +40,7 @@ class PesterIRC(QtCore.QThread):
QtCore.QThread.__init__(self) QtCore.QThread.__init__(self)
self.mainwindow = window self.mainwindow = window
self.config = config self.config = config
self.unresponsive = False
self.registeredIRC = False self.registeredIRC = False
self.metadata_supported = False self.metadata_supported = False
self.stopIRC = None self.stopIRC = None
@ -68,6 +69,7 @@ class PesterIRC(QtCore.QThread):
res = True res = True
try: try:
PchumLog.debug("updateIRC()") PchumLog.debug("updateIRC()")
self.mainwindow.sincerecv = 0
res = self.updateIRC() res = self.updateIRC()
except socket.timeout as se: except socket.timeout as se:
PchumLog.debug("timeout in thread %s" % (self)) PchumLog.debug("timeout in thread %s" % (self))
@ -340,7 +342,8 @@ class PesterIRC(QtCore.QThread):
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def pingServer(self): def pingServer(self):
try: try:
self.cli.send("PING %s" % int(time.time())) self.cli.send("PING :B33")
#self.cli.send("PING %s" % int(time.time()))
except OSError as e: except OSError as e:
PchumLog.warning(e) PchumLog.warning(e)
self.setConnectionBroken() self.setConnectionBroken()
@ -537,6 +540,13 @@ class PesterHandler(DefaultCommandHandler):
self.parent.messageReceived.emit(handle, msg) self.parent.messageReceived.emit(handle, msg)
def pong(self, *args):
# source, server, token
#print("PONG", source, server, token)
#self.parent.mainwindow.lastrecv = time.time()
#print("PONG TIME: %s" % self.parent.mainwindow.lastpong)
pass
def welcome(self, server, nick, msg): def welcome(self, server, nick, msg):
self.parent.setConnected() self.parent.setConnected()
#mychumhandle = self.mainwindow.profile().handle #mychumhandle = self.mainwindow.profile().handle
@ -839,7 +849,7 @@ class PesterHandler(DefaultCommandHandler):
self.parent.userPresentUpdate.emit(handle, channel, "left") self.parent.userPresentUpdate.emit(handle, channel, "left")
def ping(self, prefix, server): def ping(self, prefix, server):
self.parent.mainwindow.lastping = int(time.time()) #self.parent.mainwindow.lastping = time.time()
self.client.send('PONG', server) self.client.send('PONG', server)
def getMood(self, *chums): def getMood(self, *chums):

View file

@ -180,10 +180,10 @@ class IRCClient:
pass pass
else: else:
#raise se #raise se
_end = True # This ok? self._end = True # This ok?
except AttributeError: except AttributeError:
#raise se #raise se
_end = True # This ok? self._end = True # This ok?
def connect(self): def connect(self):
""" initiates the connection to the server set in self.host:self.port """ initiates the connection to the server set in self.host:self.port
@ -222,6 +222,17 @@ class IRCClient:
self.socket.setblocking(False) self.socket.setblocking(False)
elif self.blocking: elif self.blocking:
self.socket.setblocking(True) self.socket.setblocking(True)
#try:
# self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
# if hasattr(socket, "TCP_KEEPIDLE"):
# self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 1)
# if hasattr(socket, "TCP_KEEPINTVL"):
# self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 1)
# if hasattr(socket, "TCP_KEEPCNT"):
# self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 1)
#except Exception as e:
# print(e)
helpers.nick(self, self.nick) helpers.nick(self, self.nick)
helpers.user(self, self.username, self.realname) helpers.user(self, self.username, self.realname)

View file

@ -1500,8 +1500,8 @@ class PesterWindow(MovingWindow):
self.pingtimer = QtCore.QTimer() self.pingtimer = QtCore.QTimer()
self.pingtimer.timeout.connect(self.checkPing) self.pingtimer.timeout.connect(self.checkPing)
self.lastping = int(time.time()) self.sincerecv = 0 # Time since last recv
self.pingtimer.start(1000*90) self.pingtimer.start(1000*15) # time in ms
self.mychumhandleLabel.adjustSize() # Required so "CHUMHANDLE:" regardless of style-sheet. self.mychumhandleLabel.adjustSize() # Required so "CHUMHANDLE:" regardless of style-sheet.
self.moodsLabel.adjustSize() # Required so "MOOD:" regardless of style-sheet. self.moodsLabel.adjustSize() # Required so "MOOD:" regardless of style-sheet.
@ -1545,10 +1545,36 @@ class PesterWindow(MovingWindow):
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def checkPing(self): def checkPing(self):
curtime = int(time.time()) '''Check if server is alive on app level,
if curtime - self.lastping > 600: this function is called every 15sec'''
# Return without irc
if hasattr(self.parent, 'irc') == False:
return
# Presume connection is dead after 90 seconds of silence.
if self.sincerecv >= 90:
self.disconnectIRC.emit()
# Show unresponsive if timing out
if self.sincerecv >= 45:
if self.parent.irc.unresponsive == False:
self.parent.irc.unresponsive = True
self.parent.showLoading(self.parent.widget,
"S3RV3R NOT R3SPOND1NG >:?")
self.show()
self.setFocus()
else:
self.parent.irc.unresponsive = False
if self.loadingscreen:
self.loadingscreen.done(QtWidgets.QDialog.DialogCode.Accepted)
# Send a ping if it's been 30 seconds since we've heard from the server.
if self.sincerecv >= 30:
self.pingServer.emit() self.pingServer.emit()
self.sincerecv += 15 # Only updating every 10s is better for performance.
def profile(self): def profile(self):
return self.userprofile.chat return self.userprofile.chat
def closeConversations(self, switch=False): def closeConversations(self, switch=False):
@ -3972,7 +3998,9 @@ class MainProgram(QtCore.QObject):
widget.loadingscreen.loadinglabel.setText(msg) widget.loadingscreen.loadinglabel.setText(msg)
widget.loadingscreen.rejected.connect(widget.app.quit) widget.loadingscreen.rejected.connect(widget.app.quit)
self.widget.loadingscreen.tryAgain.connect(self.tryAgain) self.widget.loadingscreen.tryAgain.connect(self.tryAgain)
if hasattr(self, 'irc') and self.irc.registeredIRC: if (hasattr(self, 'irc')
and self.irc.registeredIRC
and self.irc.unresponsive == False):
return return
if self.reconnectok: if self.reconnectok:
widget.loadingscreen.showReconnect() widget.loadingscreen.showReconnect()