コード例 #1
0
 def test_errback_default(self):
     """ Make sure default errback prints a warning message """
     deferred = Deferred()
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback)
     _call(deferred.errback, self.failure, self._logging_warning)
     self.assertTrue(self.count)
コード例 #2
0
    def _retrieve_tarball(self, ctx):
        ''' Retrieve tarball for a given version '''

        if not 'result' in ctx:
            logging.error('updater_runner: no result')
            self._schedule()
            return

        length, body, error = ctx.pop('result')
        if length == -1:
            logging.info('updater_runner: %s', str(error))
            self._schedule()
            return

        logging.info('updater_runner: signature (base64): %s',
                     base64.b64encode(body))

        ctx['signature'] = body
        ctx['uri'] = updater_utils.tarball_get_uri(self.system, ctx['vinfo'])

        logging.info('updater_runner: GET %s', ctx['uri'])

        deferred = Deferred()
        deferred.add_callback(self._process_files)
        deferred.add_errback(self._handle_failure)

        RUNNER_CORE.run('dload', deferred, False, ctx)
コード例 #3
0
 def run(self):
     ''' Periodically run rendezvous '''
     logging.info('background_rendezvous: automatic rendezvous...')
     deferred = Deferred()
     deferred.add_callback(self._after_rendezvous)
     deferred.add_errback(self._schedule)
     RUNNER_CORE.run('rendezvous', deferred, False, None)
コード例 #4
0
ファイル: skype_clnt.py プロジェクト: claudiuperta/neubot
 def _connection_lost(self, stream):
     ''' Invoked when the connection is lost '''
     deferred = Deferred()
     deferred.add_callback(self._connection_lost_internal)
     deferred.add_errback(lambda error: self._connection_lost_error(stream,
                                                                    error))
     deferred.callback(stream)
コード例 #5
0
ファイル: runner_core.py プロジェクト: claudiuperta/neubot
    def run_queue(self):
        ''' If possible run the first test in queue '''

        # Adapted from neubot/rendezvous/client.py

        if not self.queue:
            return
        if self.running:
            return

        #
        # Subscribe BEFORE starting the test, otherwise we
        # may miss the 'testdone' event if the connection
        # to the negotiator service fails, and we will stay
        # stuck forever.
        #
        NOTIFIER.subscribe('testdone', self.test_done)

        # Prevent concurrent tests
        self.running = True

        # Safely run first element in queue
        deferred = Deferred()
        deferred.add_callback(self._do_run_queue)
        deferred.add_errback(self._run_queue_error)
        deferred.callback(self.queue[0])
コード例 #6
0
 def test_errback_default(self):
     ''' Make sure default errback prints a warning message '''
     deferred = Deferred()
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback)
     _call(deferred.errback, self.failure, self._logging_warning)
     self.assertTrue(self.count)
コード例 #7
0
 def test_callback_to_errback(self):
     ''' Make sure we switch correctly from callback to errback '''
     deferred = Deferred()
     deferred.add_callback(self._callback)
     deferred.add_errback(self._errback)
     _call(deferred.callback, 65537)
     self.assertEqual(self.count_callbacks, 1)
     self.assertEqual(self.count_errbacks, 1)
コード例 #8
0
 def test_errback_chain(self):
     ''' Make sure the errback chain works '''
     deferred = Deferred()
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback_last)
     deferred.errback(self.failure)
     self.assertEqual(self.counter, 3)
コード例 #9
0
 def test_callback_to_errback(self):
     """ Make sure we switch correctly from callback to errback """
     deferred = Deferred()
     deferred.add_callback(self._callback)
     deferred.add_errback(self._errback)
     _call(deferred.callback, 65537)
     self.assertEqual(self.count_callbacks, 1)
     self.assertEqual(self.count_errbacks, 1)
コード例 #10
0
 def test_errback_chain(self):
     """ Make sure the errback chain works """
     deferred = Deferred()
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback)
     deferred.add_errback(self._errback_last)
     deferred.errback(self.failure)
     self.assertEqual(self.counter, 3)
コード例 #11
0
ファイル: connector.py プロジェクト: EverlastingFire/neubot
 def handle_write(self):
     POLLER.unset_writable(self)
     if not utils_net.isconnected(self.endpoint, self.sock):
         self._connection_failed()
         return
     deferred = Deferred()
     deferred.add_callback(self._handle_connect)
     deferred.add_errback(self._handle_connect_error)
     deferred.callback(utils.ticks())
コード例 #12
0
ファイル: raw_clnt.py プロジェクト: neubot/neubot
 def _periodic(self, args):
     """ Periodically snap goodput """
     stream = args[0]
     if stream.opaque:
         deferred = Deferred()
         deferred.add_callback(self._periodic_internal)
         deferred.add_errback(lambda err: self._periodic_error(stream, err))
         deferred.callback(stream)
         POLLER.sched(1, self._periodic, stream)
コード例 #13
0
 def run(self):
     ''' Periodically run rendezvous '''
     #
     # Except from opening the browser, privacy actions are
     # now performed by RUNNER_CORE
     #
     if not privacy.allowed_to_run():
         self._open_browser_on_windows('privacy.html')
     logging.info('background_rendezvous: automatic rendezvous...')
     deferred = Deferred()
     deferred.add_callback(self._after_rendezvous)
     deferred.add_errback(self._schedule)
     RUNNER_CORE.run('rendezvous', deferred, False, None)
コード例 #14
0
    def retrieve_files(self, ctx, vinfo):
        ''' Retrieve files for a given version '''
        # Note: this is a separate function for testability

        uri = updater_utils.signature_get_uri(self.system, vinfo)
        ctx['uri'] = uri
        ctx['vinfo'] = vinfo
        logging.info('updater_runner: GET %s', uri)

        deferred = Deferred()
        deferred.add_callback(self._retrieve_tarball)
        deferred.add_errback(self._handle_failure)

        RUNNER_CORE.run('dload', deferred, False, ctx)
コード例 #15
0
 def _process_negotiate_response(self, stream, response):
     ''' Process response when in negotiate state '''
     # Note: this function MUST be callable multiple times
     extra = stream.opaque.extra
     extra['authorization'] = response['authorization']
     if response['unchoked']:
         logging.debug('skype_negotiate: negotiate complete... unchoked')
         response['address'] = extra['address']  # XXX
         logging.debug('skype_negotiate: test in progress...')
         deferred = Deferred()
         deferred.add_callback(self._start_test)
         errback = lambda error: self._handle_test_failure(stream, error)
         deferred.add_errback(errback)
         successback = lambda state: self._handle_test_success(stream, state)
         deferred.callback((successback, errback, response, extra))
         return
     queue_pos = response['queue_pos']
     logging.debug('skype_negotiate: negotiate complete... in queue (%d)',
       queue_pos)
     STATE.update('negotiate', {'queue_pos': queue_pos})
     self.handle_connection_made(stream)  # Tail call (sort of)
コード例 #16
0
    def retrieve_versioninfo(self):
        ''' Retrieve version information '''

        #
        # The windows updater is still experimental, so it
        # is disabled by default and one needs to enable it
        # explicitly using the Web UI.
        #
        if not CONFIG['win32_updater']:
            self._schedule()
            return

        channel = CONFIG['win32_updater_channel']
        ctx = { 'uri': updater_utils.versioninfo_get_uri(self.system,
                                                         channel) }

        deferred = Deferred()
        deferred.add_callback(self._process_versioninfo)
        deferred.add_errback(self._handle_failure)

        RUNNER_CORE.run('dload', deferred, False, ctx)
コード例 #17
0
    def test_deferred_ping_pong(self):
        """ Make sure we ping pong between callback and errback """
        deferred = Deferred()

        deferred.add_errback(self._errback)
        deferred.add_callback(self._callback)
        deferred.add_callback(self._callback)
        deferred.add_errback(self._errback)
        deferred.add_callback(self._callback)
        deferred.add_errback(self._errback)

        _call(deferred.callback, 0)

        self.assertEqual(self.count_callbacks, 2)
        self.assertEqual(self.count_errbacks, 2)
コード例 #18
0
    def test_deferred_ping_pong(self):
        ''' Make sure we ping pong between callback and errback '''
        deferred = Deferred()

        deferred.add_errback(self._errback)
        deferred.add_callback(self._callback)
        deferred.add_callback(self._callback)
        deferred.add_errback(self._errback)
        deferred.add_callback(self._callback)
        deferred.add_errback(self._errback)

        _call(deferred.callback, 0)

        self.assertEqual(self.count_callbacks, 2)
        self.assertEqual(self.count_errbacks, 2)
コード例 #19
0
ファイル: stream.py プロジェクト: EverlastingFire/neubot
class Stream(Pollable):

    ''' A pollable stream socket '''

    #
    # Init path: register connection_made() and connection_lost() callbacks,
    # and eventually configure SSL.  Note that this class routes the calls
    # to another class, so the protocol does not need to subclass this class,
    # reducing explict code dependency.
    #

    def __init__(self, sock, connection_made, connection_lost, sslconfig,
                 sslcert, opaque):
        Pollable.__init__(self)

        self.filenum = sock.fileno()
        self.myname = utils_net.getsockname(sock)
        self.peername = utils_net.getpeername(sock)
        self.logname = '%s %s' % (utils_net.format_epnt(self.myname),
                                  utils_net.format_epnt(self.peername))

        logging.debug('stream: __init__(): %s', self.logname)

        # Variables pointing to other objects
        self.atclose = Deferred()
        self.atconnect = Deferred()
        self.opaque = opaque
        self.recv_complete = None
        self.send_complete = None
        self.send_octets = EMPTY_STRING
        self.sock = None

        # Variables we don't need to clear
        self.bytes_in = 0
        self.bytes_out = 0
        self.conn_rst = False
        self.eof = False
        self.isclosed = False
        self.recv_bytes = 0
        self.recv_blocked = False
        self.send_blocked = False

        self.atclose.add_callback(connection_lost)
        self.atconnect.add_callback(connection_made)
        self.atconnect.add_errback(self._connection_made_error)

        if not sslconfig:
            self.sock = _stream_wrapper(sock)
            self.atconnect.callback(self)
            return

        #
        # Lazy import: this fails on Python 2.5, because SSL is not part of
        # v2.5 standard library.  We do not intercept the error here, because
        # accept() code already needs to setup a try..except to route any
        # error away from the listening socket.
        #
        from neubot import sslstream

        #
        # If there is SSL support, initialise() deals transparently with SSL
        # negotiation, and invokes connection_made() when done.  Errors are
        # routed to the POLLER, which generates CLOSE events accordingly.
        #
        sslstream.initialise(self, sock, sslcert)

    def _connection_made_error(self, exception):
        ''' Invoked when connection_made() callback fails '''
        logging.warning('stream: connection_made() failed: %s', str(exception))
        POLLER.close(self)

    #
    # Close path: the close() function simply tells the poller to generate
    # the handle_close() event, the handle_close() function is reentrant and
    # invokes the registered callback functions.
    #

    def register_cleanup(self, func):
        ''' Register a cleanup function '''
        self.atclose.add_callback(func)

    def close(self):
        ''' Close the stream '''
        POLLER.close(self)

    def handle_close(self):

        if self.isclosed:
            return

        logging.debug('stream: closing %s', self.logname)
        self.isclosed = True

        self.atclose.callback_each_np(self)
        self.sock.close()

        self.atclose = None
        self.atconnect = None
        self.opaque = None
        self.recv_complete = None
        self.send_complete = None
        self.send_octets = None
        self.sock = None

    def __del__(self):
        logging.debug('stream: __del__(): %s', self.logname)

    #
    # Receive path: the protocol invokes recv() to start an async recv()
    # operation, the poller invokes handle_read() when the socket becomes
    # readbable, handle_read() invokes recv_complete() when the recv()
    # is complete.
    #

    def recv(self, recv_bytes, recv_complete):
        ''' Async recv() '''

        if self.isclosed:
            raise RuntimeError('stream: recv() on a closed stream')
        if self.recv_bytes > 0:
            raise RuntimeError('stream: already recv()ing')
        if recv_bytes <= 0:
            raise RuntimeError('stream: invalid recv_bytes')

        self.recv_bytes = recv_bytes
        self.recv_complete = recv_complete

        if self.recv_blocked:
            logging.debug('stream: recv() is blocked')
            return

        POLLER.set_readable(self)

    def handle_read(self):

        #
        # Deal with the case where recv() is blocked by send(), that happens
        # when we are using SSL and write() returned WANT_READ.  In the common
        # case, this costs just one extra if in the fast path.
        #
        if self.recv_blocked:
            logging.debug('stream: handle_read() => handle_write()')
            POLLER.set_writable(self)
            if self.recv_bytes <= 0:
                POLLER.unset_readable(self)
            self.recv_blocked = False
            self.handle_write()
            return

        status, octets = self.sock.sorecv(self.recv_bytes)

        #
        # Optimisation: reorder if branches such that the ones more relevant
        # for better performance come first.  Testing in early 2011 showed that
        # this arrangement allows to gain a little more speed.  (And the code
        # is still readable.)
        #

        if status == SUCCESS and octets:
            self.bytes_in += len(octets)
            self.recv_bytes = 0
            POLLER.unset_readable(self)
            self.recv_complete(self, octets)
            return

        if status == WANT_READ:
            return

        if status == WANT_WRITE:
            logging.debug('stream: blocking send()')
            POLLER.unset_readable(self)
            POLLER.set_writable(self)
            self.send_blocked = True
            return

        if status == SUCCESS and not octets:
            logging.debug('stream: EOF')
            self.eof = True
            POLLER.close(self)
            return

        if status == CONNRST and not octets:
            logging.debug('stream: RST ')
            self.conn_rst = True
            POLLER.close(self)
            return

        raise RuntimeError('stream: invalid status')

    #
    # Send path: the protocol invokes start send to start an async send()
    # operation, the poller invokes handle_write() when the underlying socket
    # becomes writable, handle_write() invokes send_complete() when send()
    # is complete.
    #

    def send(self, send_octets, send_complete):
        ''' Async send() '''

        if self.isclosed:
            raise RuntimeError('stream: send() on a closed stream')
        if self.send_octets:
            raise RuntimeError('stream: already send()ing')

        self.send_octets = send_octets
        self.send_complete = send_complete

        if self.send_blocked:
            logging.debug('stream: send() is blocked')
            return

        POLLER.set_writable(self)

    def handle_write(self):

        #
        # Deal with the case where send() is blocked by recv(), that happens
        # when we are using SSL and recv() returned WANT_WRITE.  In the common
        # case, this costs just one extra if in the fast path.
        #
        if self.send_blocked:
            logging.debug('stream: handle_write() => handle_read()')
            POLLER.set_readable(self)
            if not self.send_octets:
                POLLER.unset_writable(self)
            self.send_blocked = False
            self.handle_read()
            return

        status, count = self.sock.sosend(self.send_octets)

        #
        # Optimisation: reorder if branches such that the ones more relevant
        # for better performance come first.  Testing in early 2011 showed that
        # this arrangement allows to gain a little more speed.  (And the code
        # is still readable.)
        #

        if status == SUCCESS and count > 0:
            self.bytes_out += count

            if count == len(self.send_octets):
                POLLER.unset_writable(self)
                self.send_octets = EMPTY_STRING
                self.send_complete(self)
                return

            if count < len(self.send_octets):
                self.send_octets = six.buff(self.send_octets, count)
                return

            raise RuntimeError('stream: invalid count')

        if status == WANT_WRITE:
            return

        if status == WANT_READ:
            logging.debug('stream: blocking recv()')
            POLLER.unset_writable(self)
            POLLER.set_readable(self)
            self.recv_blocked = True
            return

        if status == CONNRST and count == 0:
            logging.debug('stream: RST')
            self.conn_rst = True
            POLLER.close(self)
            return

        if status == SUCCESS and count < 0:
            raise RuntimeError('stream: negative count')

        raise RuntimeError('stream: invalid status')

    #
    # Miscellaneous functions
    #

    def __repr__(self):
        return self.logname

    def fileno(self):
        return self.filenum