class IrcConnection:
'Abstracts socket connection, loop over it, and handling messages from it.'
- _socket: socket
def __init__(self,
q_to_main: EventQueue,
) -> None:
self._idx = idx
self._q_to_main = q_to_main
+ self._hostname = hostname
self._login = login
+ self._socket: Optional[socket] = None
self._assumed_open = False
self._recv_loop: Optional[SocketRecvLoop] = None
- self._socket = socket()
- self._socket.settimeout(TIMEOUT_CONNECT)
self._broadcast('CONNECTION_WINDOW', self._idx)
+ self._start_connecting()
+
+ def _start_connecting(self) -> None:
def connect(self):
- self._broadcast('CONN_ALERT', f'Connecting to {hostname} …')
+ self._socket = socket()
+ self._broadcast('CONN_ALERT',
+ f'Connecting to {self._hostname} …')
+ self._socket.settimeout(TIMEOUT_CONNECT)
try:
- self._socket.connect((hostname, PORT))
+ self._socket.connect((self._hostname, PORT))
except (TimeoutError, socket_gaierror) as e:
self._broadcast('CONN_ALERT', str(e))
return
self._assumed_open = False
if self._recv_loop:
self._recv_loop.stop()
- self._socket.close()
+ self._recv_loop = None
+ if self._socket:
+ self._socket.close()
+ self._socket = None
def _broadcast(self, type_: str, payload: Any = None) -> None:
'Send event to main loop via queue, with connection index as 1st arg.'
def _read_lines(self) -> Iterator[Optional[str]]:
'Receive line-separator-delimited messages from socket.'
+ assert self._socket is not None
bytes_total = b''
buffer_linesep = b''
while True:
def _write_line(self, line: str) -> None:
'Send line-separator-delimited message over socket.'
- if not self._assumed_open:
+ if not (self._socket and self._assumed_open):
self._broadcast('CONN_ALERT',
'cannot send, assuming connection closed')
return
'*', self._login[2]]))
self._broadcast('SEND', IrcMessage('NICK', [self._login[1]]))
return
+ if event.type_ == 'INIT_RECONNECTION':
+ if self._assumed_open:
+ self._broadcast('CONN_ALERT', 'Reconnect called, but still '
+ 'seem connected, so nothing to do.')
+ else:
+ self._start_connecting()
+ return
msg: IrcMessage = event.payload[1]
if event.type_ == 'SEND':
self._write_line(msg.raw)
self._window_idx = idx
self.window.draw()
+ def cmd__reconnect(self) -> Optional[str]:
+ 'Send INIT_RECONNECTION to server if in connection window.'
+ if self.window not in self._conn_windows:
+ return 'can only reconnect from inside connection window.'
+ conn_idx = self._conn_windows.index(self.window)
+ self.broadcast('INIT_RECONNECTION', (conn_idx,))
+ return None
+
def cmd__connect(self,
hostname: str,
username: str,
if event.type_ == 'INIT_CONNECTION':
connections += [IrcConnection(q_to_main, len(connections),
*event.payload)]
- elif event.type_ in {'CONNECTED', 'RECV', 'SEND'}:
+ elif event.type_ in {
+ 'CONNECTED', 'INIT_RECONNECTION', 'RECV', 'SEND'}:
connections[event.payload[0]].handle(event)
finally:
for conn in connections: