return ClientEvent.affector('handle_msg', client_id=self.client_id
).kw(msg=msg)
+ def _on_handled_loop_exception(self, e: IrcConnAbortException
+ ) -> ClientEvent:
+ return ClientEvent.affector('on_handled_loop_exception',
+ client_id=self.client_id).kw(e=e)
+
@dataclass
class ClientQueueMixin(QueueMixin, ClientIdMixin):
self.conn = None
self.update_login(nick_confirmed=False)
+ def on_handled_loop_exception(self, e: IrcConnAbortException) -> None:
+ 'Gracefully handle broken connection.'
+ self._log.alert(f'connection broken: {e}')
+ self.close()
+
def handle_msg(self, msg: IrcMessage) -> None:
'Process incoming msg towards appropriate client steps.'
self._log.add(msg.raw, prefix=_LOG_PREFIX_RECV_RAW, stream=STREAM_RAW)
def _make_recv_event(self, msg: IrcMessage) -> Event:
pass
+ @abstractmethod
+ def _on_handled_loop_exception(self, _: IrcConnAbortException) -> Event:
+ pass
+
def _read_lines(self) -> Iterator[Optional[Event]]:
assert self._socket is not None
bytes_total = b''
buffer_linesep = b''
- while True:
- try:
- bytes_new = self._socket.recv(_CONN_RECV_BUFSIZE)
- except TimeoutError:
- yield None
- continue
- except ConnectionResetError as e:
- raise e
- except OSError as e:
- if e.errno == 9:
+ i = 0
+ try:
+ while True:
+ i += 1
+ try:
+ bytes_new = self._socket.recv(_CONN_RECV_BUFSIZE)
+ if i >= 10:
+ raise IrcConnAbortException("DEBUG")
+ except TimeoutError:
+ yield None
+ continue
+ except ConnectionResetError as e:
+ raise IrcConnAbortException(e) from e
+ except OSError as e:
+ if e.errno == 9:
+ raise IrcConnAbortException(e) from e
+ raise e
+ if not bytes_new:
break
- raise e
- if not bytes_new:
- break
- for c in bytes_new:
- c_byted = c.to_bytes()
- if c not in _IRCSPEC_LINE_SEPARATOR:
- bytes_total += c_byted
- buffer_linesep = b''
- elif c == _IRCSPEC_LINE_SEPARATOR[0]:
- buffer_linesep = c_byted
- else:
- buffer_linesep += c_byted
- if buffer_linesep == _IRCSPEC_LINE_SEPARATOR:
- buffer_linesep = b''
- yield self._make_recv_event(
+ for c in bytes_new:
+ c_byted = c.to_bytes()
+ if c not in _IRCSPEC_LINE_SEPARATOR:
+ bytes_total += c_byted
+ buffer_linesep = b''
+ elif c == _IRCSPEC_LINE_SEPARATOR[0]:
+ buffer_linesep = c_byted
+ else:
+ buffer_linesep += c_byted
+ if buffer_linesep == _IRCSPEC_LINE_SEPARATOR:
+ buffer_linesep = b''
+ yield self._make_recv_event(
IrcMessage.from_raw(bytes_total.decode('utf-8')))
- bytes_total = b''
+ bytes_total = b''
+ except IrcConnAbortException as e:
+ yield self._on_handled_loop_exception(e)