Timeout capability negotiation after 5 seconds when waiting on SASL.

This commit is contained in:
Dpeta 2023-02-28 23:32:35 +01:00
parent 5f817867eb
commit 82c7be4516
No known key found for this signature in database
GPG key ID: 51227517CEA0030C
2 changed files with 29 additions and 9 deletions

27
irc.py
View file

@ -95,6 +95,7 @@ class PesterIRC(QtCore.QThread):
self.channel_list = [] self.channel_list = []
self.channel_field = None self.channel_field = None
# Dict for connection server commands/replies to handling functions.
self.commands = { self.commands = {
"001": self._welcome, "001": self._welcome,
"005": self._featurelist, "005": self._featurelist,
@ -212,6 +213,8 @@ class PesterIRC(QtCore.QThread):
if self.mainwindow.userprofile.getAutoIdentify(): if self.mainwindow.userprofile.getAutoIdentify():
# Send plain, send end later when 903 or 904 is received. # Send plain, send end later when 903 or 904 is received.
self._send_irc.authenticate("PLAIN") self._send_irc.authenticate("PLAIN")
# Always call CAP END after 5 seconds.
self.cap_negotation_started.emit()
else: else:
# Without SASL, end caps here. # Without SASL, end caps here.
self._send_irc.cap("END") self._send_irc.cap("END")
@ -316,6 +319,15 @@ class PesterIRC(QtCore.QThread):
PchumLog.critical("set_connection_broken() got called, disconnecting.") PchumLog.critical("set_connection_broken() got called, disconnecting.")
self.disconnectIRC() self.disconnectIRC()
def end_cap_negotiation(self):
"""Send CAP END to end capability negotation.
Called from SASL-related functions here,
but also from a timer on the main thread that always triggers after 5 seconds.
"""
if not self.registered_irc:
self._send_irc.cap("END")
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def update_irc(self): def update_irc(self):
"""Get a silly scrunkler from the generator!!""" """Get a silly scrunkler from the generator!!"""
@ -326,7 +338,7 @@ class PesterIRC(QtCore.QThread):
return True return True
raise socket_exception raise socket_exception
except StopIteration: except StopIteration:
self._conn = self.conn_generator() self._conn = self._conn_generator()
return True return True
else: else:
return res return res
@ -1051,17 +1063,13 @@ class PesterIRC(QtCore.QThread):
def _sasl_skill_issue(self, *_msg): def _sasl_skill_issue(self, *_msg):
"""Handles all responses from server that indicate SASL authentication failed. """Handles all responses from server that indicate SASL authentication failed.
Replies that indicate we can't authenticate include: 902, 904, 905.""" Replies that indicate we can't authenticate include: 902, 904, 905.
if not self.registered_irc: Aborts SASL by sending CAP END, ending capability negotiation."""
self._send_irc.authenticate( self.end_cap_negotiation()
"*"
) # Abort SASL, optional since we send cap END anyway.
self._send_irc.cap("END")
def _saslsuccess(self, *_msg): def _saslsuccess(self, *_msg):
"""Handle 'RPL_SASLSUCCESS' reply from server, SASL authentication succeeded! woo yeah!!""" """Handle 'RPL_SASLSUCCESS' reply from server, SASL authentication succeeded! woo yeah!!"""
if not self.registered_irc: self.end_cap_negotiation()
self._send_irc.cap("END")
moodUpdated = QtCore.pyqtSignal(str, Mood) moodUpdated = QtCore.pyqtSignal(str, Mood)
colorUpdated = QtCore.pyqtSignal(str, QtGui.QColor) colorUpdated = QtCore.pyqtSignal(str, QtGui.QColor)
@ -1082,3 +1090,4 @@ class PesterIRC(QtCore.QThread):
userPresentUpdate = QtCore.pyqtSignal(str, str, str) userPresentUpdate = QtCore.pyqtSignal(str, str, str)
cannotSendToChan = QtCore.pyqtSignal(str, str) cannotSendToChan = QtCore.pyqtSignal(str, str)
signal_forbiddenchannel = QtCore.pyqtSignal(str, str) signal_forbiddenchannel = QtCore.pyqtSignal(str, str)
cap_negotation_started = QtCore.pyqtSignal()

View file

@ -1633,6 +1633,10 @@ class PesterWindow(MovingWindow):
self.waitingMessages = waitingMessageHolder(self) self.waitingMessages = waitingMessageHolder(self)
# Create timer for IRC cap negotiation timeout, started in capStarted().
self.cap_negotiation_timeout = QtCore.QTimer()
self.cap_negotiation_timeout.singleShot = True
self.idler = { self.idler = {
# autoidle # autoidle
"auto": False, "auto": False,
@ -3811,6 +3815,11 @@ class PesterWindow(MovingWindow):
self.parent.trayicon.hide() self.parent.trayicon.hide()
self.app.quit() self.app.quit()
@QtCore.pyqtSlot()
def capNegotationStarted(self):
"""IRC thread started capabilities negotiation, end it if it takes longer than 5 seconds."""
self.cap_negotiation_timeout.start(5000)
def updateServerJson(self): def updateServerJson(self):
PchumLog.info("'%s' chosen.", self.customServerPrompt_qline.text()) PchumLog.info("'%s' chosen.", self.customServerPrompt_qline.text())
server_and_port = self.customServerPrompt_qline.text().split(":") server_and_port = self.customServerPrompt_qline.text().split(":")
@ -4438,6 +4447,7 @@ class MainProgram(QtCore.QObject):
(widget.disconnectIRC, irc.disconnect_irc), (widget.disconnectIRC, irc.disconnect_irc),
(widget.changeNick, irc.send_nick), (widget.changeNick, irc.send_nick),
(widget.sendAuthenticate, irc.send_authenticate), (widget.sendAuthenticate, irc.send_authenticate),
(widget.cap_negotiation_timeout.timeout, irc.end_cap_negotiation),
# Connect IRC signal to widget slot/function. (IRC --> Widget) # Connect IRC signal to widget slot/function. (IRC --> Widget)
(irc.connected, widget.connected), (irc.connected, widget.connected),
(irc.askToConnect, widget.connectAnyway), (irc.askToConnect, widget.connectAnyway),
@ -4458,6 +4468,7 @@ class MainProgram(QtCore.QObject):
(irc.modesUpdated, widget.modesUpdated), (irc.modesUpdated, widget.modesUpdated),
(irc.cannotSendToChan, widget.cannotSendToChan), (irc.cannotSendToChan, widget.cannotSendToChan),
(irc.signal_forbiddenchannel, widget.forbiddenchannel), (irc.signal_forbiddenchannel, widget.forbiddenchannel),
(irc.cap_negotation_started, widget.capNegotationStarted),
) )
def connectWidgets(self, irc, widget): def connectWidgets(self, irc, widget):