From c13c05f51d6eb492775660bd28faafdc3444e34c Mon Sep 17 00:00:00 2001 From: Dpeta Date: Fri, 18 Mar 2022 09:55:01 +0000 Subject: [PATCH] experimenting with sockets --- irc.py | 70 ++++++++++++++++++++++++++++++++----------------- oyoyo/client.py | 53 +++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/irc.py b/irc.py index c2b9c28..234ef41 100644 --- a/irc.py +++ b/irc.py @@ -78,7 +78,7 @@ class PesterIRC(QtCore.QThread): self.registeredIRC = True self.connected.emit() def setConnectionBroken(self): - PchumLog.debug("setconnection broken") + PchumLog.critical("setconnection broken") self.reconnectIRC() #self.brokenConnection = True @QtCore.pyqtSlot() @@ -99,7 +99,7 @@ class PesterIRC(QtCore.QThread): return res @QtCore.pyqtSlot() def reconnectIRC(self): - PchumLog.debug("reconnectIRC() from thread %s" % (self)) + PchumLog.warning("reconnectIRC() from thread %s" % (self)) self.cli.close() @QtCore.pyqtSlot(PesterProfile) @@ -114,7 +114,8 @@ class PesterIRC(QtCore.QThread): t = str(text) try: helpers.notice(self.cli, h, t) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def sendMessage(self, text, handle): @@ -160,7 +161,8 @@ class PesterIRC(QtCore.QThread): try: for t in textl: helpers.msg(self.cli, h, t) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, bool) def startConvo(self, handle, initiated): @@ -169,14 +171,16 @@ class PesterIRC(QtCore.QThread): helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd())) if initiated: helpers.msg(self.cli, h, "PESTERCHUM:BEGIN") - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def endConvo(self, handle): h = str(handle) try: helpers.msg(self.cli, h, "PESTERCHUM:CEASE") - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot() def updateProfile(self): @@ -184,7 +188,8 @@ class PesterIRC(QtCore.QThread): handle = me.handle try: helpers.nick(self.cli, handle) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() self.mainwindow.closeConversations(True) self.mainwindow.doAutoIdentify() @@ -196,7 +201,8 @@ class PesterIRC(QtCore.QThread): me = self.mainwindow.profile() try: helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value())) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot() def updateColor(self): @@ -205,34 +211,39 @@ class PesterIRC(QtCore.QThread): for h in list(self.mainwindow.convos.keys()): try: helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd())) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def blockedChum(self, handle): h = str(handle) try: helpers.msg(self.cli, h, "PESTERCHUM:BLOCK") - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def unblockedChum(self, handle): h = str(handle) try: helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK") - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def requestNames(self, channel): c = str(channel) try: helpers.names(self.cli, c) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot() def requestChannelList(self): try: helpers.channel_list(self.cli) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def joinChannel(self, channel): @@ -240,7 +251,8 @@ class PesterIRC(QtCore.QThread): try: helpers.join(self.cli, c) helpers.mode(self.cli, c, "", None) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def leftChannel(self, channel): @@ -248,7 +260,8 @@ class PesterIRC(QtCore.QThread): try: helpers.part(self.cli, c) self.cli.command_handler.joined = False - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def kickUser(self, handle, channel): @@ -264,7 +277,8 @@ class PesterIRC(QtCore.QThread): reason = "" try: helpers.kick(self.cli, h, c, reason) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString, QString) def setChannelMode(self, channel, mode, command): @@ -276,14 +290,16 @@ class PesterIRC(QtCore.QThread): cmd = None try: helpers.mode(self.cli, c, m, cmd) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) def channelNames(self, channel): c = str(channel) try: helpers.names(self.cli, c) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def inviteChum(self, handle, channel): @@ -291,14 +307,16 @@ class PesterIRC(QtCore.QThread): c = str(channel) try: helpers.invite(self.cli, h, c) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot() def pingServer(self): try: self.cli.send("PING %s" % int(time())) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(bool) @@ -308,7 +326,8 @@ class PesterIRC(QtCore.QThread): self.cli.send("AWAY Idle") else: self.cli.send("AWAY") - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) @@ -317,7 +336,8 @@ class PesterIRC(QtCore.QThread): h = str(handle) try: helpers.ctcp(self.cli, c, "NOQUIRKS", h) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.setConnectionBroken() def quit_dc(self): @@ -647,14 +667,16 @@ class PesterHandler(DefaultCommandHandler): if len(chumglub+chandle) >= 350: try: helpers.msg(self.client, "#pesterchum", chumglub) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.parent.setConnectionBroken() chumglub = "GETMOOD " chumglub += chandle if chumglub != "GETMOOD ": try: helpers.msg(self.client, "#pesterchum", chumglub) - except socket.error: + except socket.error as e: + PchumLog.warning(e) self.parent.setConnectionBroken() #def isOn(self, *chums): diff --git a/oyoyo/client.py b/oyoyo/client.py index 0f26eda..d4cce75 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -30,6 +30,7 @@ import traceback import ostools import ssl import json +import select _datadir = ostools.getDataDir() from oyoyo.parse import * @@ -93,19 +94,22 @@ class IRCClient: if TLS == False: #print("false") self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + #self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) else: self.context = ssl.create_default_context() self.context.check_hostname = False self.context.verify_mode = ssl.CERT_NONE self.bare_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket = self.context.wrap_socket(self.bare_socket) + #self.socket.setsockopt(socket.IPPROTO_TCP, socket.SO_KEEPALIVE, 1) + self.blocking = True + self.socket.setblocking(self.blocking) self.nick = None self.real_name = None self.host = None self.port = None self.connect_cb = None - self.blocking = False self.timeout = None self.__dict__.update(kwargs) @@ -138,15 +142,28 @@ class IRCClient: elif type(arg).__name__ == 'unicode': bargs.append(arg.encode(encoding)) else: + PchumLog.warning('Refusing to send one of the args from provided: %s'% repr([(type(arg), arg) for arg in args])) raise IRCClientError('Refusing to send one of the args from provided: %s' % repr([(type(arg), arg) for arg in args])) msg = bytes(" ", "UTF-8").join(bargs) PchumLog.info('---> send "%s"' % msg) try: - self.socket.sendall(msg + bytes("\r\n", "UTF-8")) + # Extra block to give a failed write another try, causes a reconnect otherwise + retry = 0 + while retry < 5: + try: + ready_to_read, ready_to_write, in_error = select.select([], [self.socket], []) + PchumLog.debug("ready_to_write (len %s): " % len(ready_to_write) + str(ready_to_write)) + #ready_to_write[0].sendall(msg + bytes("\r\n", "UTF-8")) + for x in ready_to_write: + x.sendall(msg + bytes("\r\n", "UTF-8")) + break + except socket.error as e: + retry += 1 + PchumLog.warning("socket.error (retry %s) %s" % (retry, e)) except socket.error as se: - PchumLog.debug("socket.error %s" % se) + PchumLog.warning("socket.error %s" % se) try: # a little dance of compatibility to get the errno errno = se.errno except AttributeError: @@ -178,17 +195,25 @@ class IRCClient: buffer = bytes() while not self._end: try: - buffer += self.socket.recv(1024) + ready_to_read, ready_to_write, in_error = select.select([self.socket], [], []) # Don't wanna cause an unnecessary timeout + # Though this could probably be 90 + PchumLog.debug("ready_to_read (len %s): " % len(ready_to_read) + str(ready_to_read)) + for x in ready_to_read: + buffer += x.recv(1024) + #print("pre-recv") + #buffer += self.socket.recv(1024) + #print("post-recv") + #print(buffer) #raise socket.timeout except socket.timeout as e: + PchumLog.warning("timeout in client.py, " + e) if self._end: break - PchumLog.debug("timeout in client.py") raise e except socket.error as e: + PchumLog.warning("conn socket.error %s in %s" % (e, self)) if self._end: break - PchumLog.debug("error %s" % e) try: # a little dance of compatibility to get the errno errno = e.errno except AttributeError: @@ -200,7 +225,9 @@ class IRCClient: else: if self._end: break + PchumLog.debug("pre buffer check, len(buffer) = " + str(len(buffer))) if len(buffer) == 0 and self.blocking: + PchumLog.debug("len(buffer) = 0") raise socket.error("Connection closed") data = buffer.split(bytes("\n", "UTF-8")) @@ -209,6 +236,7 @@ class IRCClient: PchumLog.debug("data = " + str(data)) for el in data: + PchumLog.debug("el=%s, data=%s" % (el,data)) prefix, command, args = parse_raw_irc_command(el) try: self.command_handler.run(command, prefix, *args) @@ -240,11 +268,14 @@ class IRCClient: PchumLog.info('shutdown socket') #print("shutdown socket") self._end = True - self.socket.shutdown(socket.SHUT_WR) - self.socket.close() - - def simple_send(self, message): - self.socket.sendall(bytes(message, "UTF-8")) + try: + self.socket.shutdown(SHUT_RDWR) + except OSError as e: + PchumLog.warning("Error while shutting down socket, already broken? %s" % e) + try: + self.socket.close() + except OSError as e: + PchumLog.warning("Error while closing socket, already broken? %s" % e) def quit(self, msg): PchumLog.info("QUIT")