diff --git a/CHANGELOG.md b/CHANGELOG.md index 161b5d4..daa931b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,17 @@ # Changelog (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 - Error when manually moving group. + - EOF on send not resulting in a disconnect. ## [v2.4.1] - 2022-07-05 diff --git a/irc.py b/irc.py index 311504d..c8f9168 100644 --- a/irc.py +++ b/irc.py @@ -40,6 +40,7 @@ class PesterIRC(QtCore.QThread): QtCore.QThread.__init__(self) self.mainwindow = window self.config = config + self.unresponsive = False self.registeredIRC = False self.metadata_supported = False self.stopIRC = None @@ -68,6 +69,7 @@ class PesterIRC(QtCore.QThread): res = True try: PchumLog.debug("updateIRC()") + self.mainwindow.sincerecv = 0 res = self.updateIRC() except socket.timeout as se: PchumLog.debug("timeout in thread %s" % (self)) @@ -340,7 +342,8 @@ class PesterIRC(QtCore.QThread): @QtCore.pyqtSlot() def pingServer(self): 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: PchumLog.warning(e) self.setConnectionBroken() @@ -537,6 +540,13 @@ class PesterHandler(DefaultCommandHandler): 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): self.parent.setConnected() #mychumhandle = self.mainwindow.profile().handle @@ -839,7 +849,7 @@ class PesterHandler(DefaultCommandHandler): self.parent.userPresentUpdate.emit(handle, channel, "left") def ping(self, prefix, server): - self.parent.mainwindow.lastping = int(time.time()) + #self.parent.mainwindow.lastping = time.time() self.client.send('PONG', server) def getMood(self, *chums): diff --git a/oyoyo/client.py b/oyoyo/client.py index 0b78dff..a0ee7a8 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -180,10 +180,10 @@ class IRCClient: pass else: #raise se - _end = True # This ok? + self._end = True # This ok? except AttributeError: #raise se - _end = True # This ok? + self._end = True # This ok? def connect(self): """ initiates the connection to the server set in self.host:self.port @@ -222,6 +222,17 @@ class IRCClient: self.socket.setblocking(False) elif self.blocking: 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.user(self, self.username, self.realname) diff --git a/pesterchum.py b/pesterchum.py index 33a54e8..55f1105 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -1500,8 +1500,8 @@ class PesterWindow(MovingWindow): self.pingtimer = QtCore.QTimer() self.pingtimer.timeout.connect(self.checkPing) - self.lastping = int(time.time()) - self.pingtimer.start(1000*90) + self.sincerecv = 0 # Time since last recv + self.pingtimer.start(1000*15) # time in ms self.mychumhandleLabel.adjustSize() # Required so "CHUMHANDLE:" regardless of style-sheet. self.moodsLabel.adjustSize() # Required so "MOOD:" regardless of style-sheet. @@ -1545,10 +1545,36 @@ class PesterWindow(MovingWindow): @QtCore.pyqtSlot() def checkPing(self): - curtime = int(time.time()) - if curtime - self.lastping > 600: + '''Check if server is alive on app level, + 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.sincerecv += 15 # Only updating every 10s is better for performance. + def profile(self): return self.userprofile.chat def closeConversations(self, switch=False): @@ -3972,7 +3998,9 @@ class MainProgram(QtCore.QObject): widget.loadingscreen.loadinglabel.setText(msg) widget.loadingscreen.rejected.connect(widget.app.quit) 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 if self.reconnectok: widget.loadingscreen.showReconnect()