示例#1
0
    def __init__(self, bot, server_timeout=None, ping_timeout=None, **kwargs):
        AbstractIRCBackend.__init__(self, bot)
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\n')
        self.buffer = ''
        self.server_timeout = server_timeout or 120
        self.ping_timeout = ping_timeout or (self.server_timeout / 2)
        self.last_event_at = None
        self.host = None
        self.port = None
        self.source_address = None

        ping_job = Job(self.ping_timeout, _send_ping)
        timeout_job = Job(self.server_timeout, _check_timeout)

        self.timeout_scheduler = JobScheduler(self)
        self.timeout_scheduler.add_job(ping_job)
        self.timeout_scheduler.add_job(timeout_job)
示例#2
0
class AsynchatBackend(AbstractIRCBackend, asynchat.async_chat):
    def __init__(self, bot, server_timeout=None, ping_timeout=None, **kwargs):
        AbstractIRCBackend.__init__(self, bot)
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\n')
        self.buffer = ''
        self.server_timeout = server_timeout or 120
        self.ping_timeout = ping_timeout or (self.server_timeout / 2)
        self.last_event_at = None
        self.host = None
        self.port = None
        self.source_address = None

        ping_job = Job(self.ping_timeout, _send_ping)
        timeout_job = Job(self.server_timeout, _check_timeout)

        self.timeout_scheduler = JobScheduler(self)
        self.timeout_scheduler.add_job(ping_job)
        self.timeout_scheduler.add_job(timeout_job)

    def run_forever(self):
        asyncore.loop()

    def initiate_connect(self, host, port, source_address):
        self.host = host
        self.port = port
        self.source_address = source_address

        LOGGER.info('Connecting to %s:%s...', host, port)
        try:
            LOGGER.debug('Set socket')
            self.set_socket(
                socket.create_connection((host, port),
                                         source_address=source_address))
            LOGGER.debug('Connection attempt')
            self.connect((host, port))
        except socket.error as e:
            LOGGER.exception('Connection error: %s', e)
            self.handle_close()

    def handle_connect(self):
        """Called when the active opener's socket actually makes a connection."""
        LOGGER.info('Connection accepted by the server...')
        self.timeout_scheduler.start()
        self.bot.on_connect()

    def handle_close(self):
        """Called when the socket is closed"""
        self.timeout_scheduler.stop()
        self.timeout_scheduler.join(timeout=15)

        LOGGER.info('Connection closed...')
        try:
            self.bot.on_close()
        finally:
            if self.socket:
                LOGGER.debug('Closing socket')
                self.close()
                LOGGER.info('Closed!')

    def handle_error(self):
        """Called when an exception is raised and not otherwise handled."""
        LOGGER.info('Connection error...')
        self.bot.on_error()

    def collect_incoming_data(self, data):
        # We can't trust clients to pass valid unicode.
        try:
            data = unicode(data, encoding='utf-8')
        except UnicodeDecodeError:
            # not unicode, let's try cp1252
            try:
                data = unicode(data, encoding='cp1252')
            except UnicodeDecodeError:
                # Okay, let's try ISO8859-1
                try:
                    data = unicode(data, encoding='iso8859-1')
                except UnicodeDecodeError:
                    # Discard line if encoding is unknown
                    return
        if data:
            self.bot.log_raw(data, '<<')
        self.buffer += data
        self.last_event_at = datetime.datetime.utcnow()

    def found_terminator(self):
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.bot.on_message(line)

    def on_scheduler_error(self, scheduler, exc):
        """Called when the Job Scheduler fails."""
        LOGGER.exception('Error with the timeout scheduler: %s', exc)
        self.handle_close()

    def on_job_error(self, scheduler, job, exc):
        """Called when a job from the Job Scheduler fails."""
        LOGGER.exception('Error with the timeout scheduler: %s', exc)
        self.handle_close()
示例#3
0
class AsynchatBackend(AbstractIRCBackend, asynchat.async_chat):
    """IRC backend implementation using :mod:`asynchat` (:mod:`asyncore`).

    :param bot: a Sopel instance
    :type bot: :class:`sopel.bot.Sopel`
    :param int server_timeout: connection timeout in seconds
    :param int ping_timeout: ping timeout in seconds
    """
    def __init__(self, bot, server_timeout=None, ping_timeout=None, **kwargs):
        AbstractIRCBackend.__init__(self, bot)
        asynchat.async_chat.__init__(self)
        self.set_terminator(b'\n')
        self.buffer = ''
        self.server_timeout = server_timeout or 120
        self.ping_timeout = ping_timeout or (self.server_timeout / 2)
        self.last_event_at = None
        self.host = None
        self.port = None
        self.source_address = None

        ping_job = Job(self.ping_timeout, _send_ping)
        timeout_job = Job(self.server_timeout, _check_timeout)

        self.timeout_scheduler = JobScheduler(self)
        self.timeout_scheduler.add_job(ping_job)
        self.timeout_scheduler.add_job(timeout_job)

    def run_forever(self):
        """Run forever."""
        asyncore.loop()

    def initiate_connect(self, host, port, source_address):
        """Initiate IRC connection.

        :param str host: IRC server hostname
        :param int port: IRC server port
        :param str source_address: the source address from which to initiate
                                   the connection attempt
        """
        self.host = host
        self.port = port
        self.source_address = source_address

        LOGGER.info('Connecting to %s:%s...', host, port)
        try:
            LOGGER.debug('Set socket')
            self.set_socket(socket.create_connection((host, port),
                            source_address=source_address))
            LOGGER.debug('Connection attempt')
            self.connect((host, port))
        except socket.error as e:
            LOGGER.exception('Connection error: %s', e)
            self.handle_close()

    def handle_connect(self):
        """Called when the active opener's socket actually makes a connection."""
        LOGGER.info('Connection accepted by the server...')
        self.timeout_scheduler.start()
        self.bot.on_connect()

    def handle_close(self):
        """Called when the socket is closed."""
        self.timeout_scheduler.stop()
        if current_thread() is not self.timeout_scheduler:
            self.timeout_scheduler.join(timeout=15)

        LOGGER.info('Connection closed...')
        try:
            self.bot.on_close()
        finally:
            if self.socket:
                LOGGER.debug('Closing socket')
                self.close()
                LOGGER.info('Closed!')

    def handle_error(self):
        """Called when an exception is raised and not otherwise handled."""
        LOGGER.info('Connection error...')
        self.bot.on_error()

    def collect_incoming_data(self, data):
        """Try to make sense of incoming data as Unicode.

        :param bytes data: the incoming raw bytes

        The incoming line is discarded (and thus ignored) if guessing the text
        encoding and decoding it fails.
        """
        # We can't trust clients to pass valid Unicode.
        try:
            data = unicode(data, encoding='utf-8')
        except UnicodeDecodeError:
            # not Unicode; let's try CP-1252
            try:
                data = unicode(data, encoding='cp1252')
            except UnicodeDecodeError:
                # Okay, let's try ISO 8859-1
                try:
                    data = unicode(data, encoding='iso8859-1')
                except UnicodeDecodeError:
                    # Discard line if encoding is unknown
                    return
        if data:
            self.bot.log_raw(data, '<<')
        self.buffer += data
        self.last_event_at = datetime.datetime.utcnow()

    def found_terminator(self):
        """Handle the end of an incoming message."""
        line = self.buffer
        if line.endswith('\r'):
            line = line[:-1]
        self.buffer = ''
        self.bot.on_message(line)

    def on_scheduler_error(self, scheduler, exc):
        """Called when the Job Scheduler fails."""
        LOGGER.exception('Error with the timeout scheduler: %s', exc)
        self.handle_close()

    def on_job_error(self, scheduler, job, exc):
        """Called when a job from the Job Scheduler fails."""
        LOGGER.exception('Error with the timeout scheduler: %s', exc)
        self.handle_close()