コード例 #1
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])
コード例 #2
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)
コード例 #3
0
 def test_callback_chain(self):
     ''' Make sure the callback chain works '''
     deferred = Deferred()
     deferred.add_callback(self._callback)
     deferred.add_callback(self._callback)
     deferred.add_callback(self._callback)
     deferred.callback(0)
     self.assertEqual(self.counter, 3)
コード例 #4
0
 def test_callback_chain(self):
     """ Make sure the callback chain works """
     deferred = Deferred()
     deferred.add_callback(self._callback)
     deferred.add_callback(self._callback)
     deferred.add_callback(self._callback)
     deferred.callback(0)
     self.assertEqual(self.counter, 3)
コード例 #5
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)
コード例 #6
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())
コード例 #7
0
 def _process_collect_response(self, stream, remote_result):
     ''' Process response when in collect state '''
     context = stream.opaque
     extra = context.extra
     tmp = context.headers.get(CONTENT_TYPE)
     if context.code != CODE200 or tmp != APPLICATION_JSON:
         logging.warning('skype_negotiate: collect complete... bad response')
         stream.close()
         return
     deferred = Deferred()
     deferred.add_callback(self._save_results)
     deferred.callback((extra['local_result'], remote_result))
     extra['final_state'] = 1
     stream.close()
コード例 #8
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)
コード例 #9
0
 def test_callback():
     ''' Invoke callback() on empty deferred '''
     deferred = Deferred()
     deferred.callback(65537)
コード例 #10
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
コード例 #11
0
 def test_callback():
     """ Invoke callback() on empty deferred """
     deferred = Deferred()
     deferred.callback(65537)