home · contact · privacy
Don't block main loop for duration of connecting attempt.
authorChristian Heller <c.heller@plomlompom.de>
Sat, 7 Jun 2025 17:42:09 +0000 (19:42 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Sat, 7 Jun 2025 17:42:09 +0000 (19:42 +0200)
ircplom.py

index 86c3b6ca304612204354d77f6a8ed255234250d0..62ad5157031ba139265f22f67aa9d55b9eadb148 100755 (executable)
@@ -157,23 +157,27 @@ class IrcConnection:
                  ) -> None:
         self._idx = idx
         self._q_to_main = q_to_main
+        self._login = login
         self._assumed_open = False
         self._recv_loop: Optional[SocketRecvLoop] = None
         self._socket = socket()
         self._socket.settimeout(TIMEOUT_CONNECT)
         self._broadcast('CONNECTION_WINDOW', self._idx)
-        try:
-            self._socket.connect((hostname, PORT))
-        except socket_gaierror as e:
-            self._broadcast('CONN_ALERT', str(e))
-            return
-        self._assumed_open = True
-        self._socket.settimeout(TIMEOUT_LOOP)
-        self._recv_loop = SocketRecvLoop(self._idx, self._q_to_main,
-                                         self._read_lines())
-        self._broadcast('SEND', IrcMessage('USER', [login[0], '0', '*',
-                                                    login[2]]))
-        self._broadcast('SEND', IrcMessage('NICK', [login[1]]))
+
+        def connect(self):
+            self._broadcast('CONN_ALERT', f'Connecting to {hostname} …')
+            try:
+                self._socket.connect((hostname, PORT))
+            except (TimeoutError, socket_gaierror) as e:
+                self._broadcast('CONN_ALERT', str(e))
+                return
+            self._socket.settimeout(TIMEOUT_LOOP)
+            self._assumed_open = True
+            self._broadcast('CONNECTED')
+            self._recv_loop = SocketRecvLoop(self._idx, self._q_to_main,
+                                             self._read_lines())
+
+        Thread(target=connect, args=(self,)).start()
 
     def close(self):
         'Close both SocketRecvLoop and socket.'
@@ -226,6 +230,11 @@ class IrcConnection:
 
     def handle(self, event: Event) -> None:
         'Process connection-directed Event into further steps.'
+        if event.type_ == 'CONNECTED':
+            self._broadcast('SEND', IrcMessage('USER', [self._login[0], '0',
+                                                        '*', self._login[2]]))
+            self._broadcast('SEND', IrcMessage('NICK', [self._login[1]]))
+            return
         msg: IrcMessage = event.payload[1]
         if event.type_ == 'SEND':
             self._write_line(msg.raw)
@@ -795,7 +804,7 @@ def run() -> None:
                 if event.type_ == 'INIT_CONNECTION':
                     connections += [IrcConnection(q_to_main, len(connections),
                                                   *event.payload)]
-                elif event.type_ in {'RECV', 'SEND'}:
+                elif event.type_ in {'CONNECTED', 'RECV', 'SEND'}:
                     connections[event.payload[0]].handle(event)
     finally:
         for conn in connections: