Exemplo n.º 1
0
    def _execute(self, transforms, *args, **kwargs):
        with stack_context.ExceptionStackContext(
                self._handle_websocket_exception):
            # Websocket only supports GET method
            if self.request.method != 'GET':
                self.stream.write(
                    tornado.escape.utf8(
                        "HTTP/1.1 405 Method Not Allowed\r\n\r\n"))
                self.stream.close()
                return

            # Upgrade header should be present and should be equal to WebSocket
            if self.request.headers.get("Upgrade", "").lower() != 'websocket':
                self.stream.write(
                    tornado.escape.utf8(
                        "HTTP/1.1 400 Bad Request\r\n\r\n"
                        "Can \"Upgrade\" only to \"WebSocket\"."))
                self.stream.close()
                return

            # Connection header should be upgrade. Some proxy servers/load balancers
            # might mess with it.
            if self.request.headers.get("Connection",
                                        "").lower().find('upgrade') == -1:
                self.stream.write(
                    tornado.escape.utf8("HTTP/1.1 400 Bad Request\r\n\r\n"
                                        "\"Connection\" must be \"Upgrade\"."))
                self.stream.close()
                return

            super(TornadioWebSocketHandler,
                  self)._execute(transforms, *args, **kwargs)
Exemplo n.º 2
0
 def wrapper(self, *args, **kwargs):
     if self.application._wsgi:
         raise Exception("@asynchronous is not supported for WSGI apps")
     self._auto_finish = False
     with stack_context.ExceptionStackContext(
             self._stack_context_handle_exception):
         return method(self, *args, **kwargs)
Exemplo n.º 3
0
def Task(func, *args, **kwargs):
    """Runs a single asynchronous operation.

    Takes a function (and optional additional arguments) and runs it with
    those arguments plus a ``callback`` keyword argument.  The argument passed
    to the callback is returned as the result of the yield expression.

    A `Task` is equivalent to a `Callback`/`Wait` pair (with a unique
    key generated automatically)::

        result = yield gen.Task(func, args)

        func(args, callback=(yield gen.Callback(key)))
        result = yield gen.Wait(key)

    .. versionchanged:: 3.3
       ``gen.Task`` is now a function that returns a `.Future`, instead of
       a subclass of `YieldPoint`.  It still behaves the same way when
       yielded.
    """
    future = Future()
    def handle_exception(typ, value, tb):
        if future.done():
            return False
        future.set_exc_info((typ, value, tb))
        return True
    def set_result(result):
        if future.done():
            return
        future.set_result(result)
    with stack_context.ExceptionStackContext(handle_exception):
        func(*args, callback=_argument_adapter(set_result), **kwargs)
    return future
Exemplo n.º 4
0
def Task(func, *args, **kwargs):
    """Adapts a callback-based asynchronous function for use in coroutines.

    Takes a function (and optional additional arguments) and runs it with
    those arguments plus a ``callback`` keyword argument.  The argument passed
    to the callback is returned as the result of the yield expression.

    .. versionchanged:: 4.0
       ``gen.Task`` is now a function that returns a `.Future`, instead of
       a subclass of `YieldPoint`.  It still behaves the same way when
       yielded.
    """
    future = _create_future()

    def handle_exception(typ, value, tb):
        if future.done():
            return False
        future_set_exc_info(future, (typ, value, tb))
        return True

    def set_result(result):
        if future.done():
            return
        future_set_result_unless_cancelled(future, result)

    with stack_context.ExceptionStackContext(handle_exception):
        func(*args, callback=_argument_adapter(set_result), **kwargs)
    return future
Exemplo n.º 5
0
    def __init__(
            self, io_loop, context, request, stream_id,
            release_callback=None, final_callback=None):
        self.io_loop = io_loop
        self.start_time = self.io_loop.time()
        self.context = context
        self.release_callback = release_callback
        self.final_callback = final_callback

        self.chunks = []
        self.headers = None
        self.code = None
        self.reason = None

        self._timeout = None
        self._pushed_streams = {}
        self._pushed_responses = {}
        self._stream_ended = False
        self._finalized = False
        self._decompressor = None
        self._pending_body = None
        self._sent = False

        self.stream_id = stream_id
        self.request = request
        self.context.set_stream_delegate(self.stream_id, self)

        if request.request_timeout:
            with stack_context.ExceptionStackContext(self.handle_exception):
                self._timeout = self.io_loop.add_timeout(
                    self.start_time + request.request_timeout, self._on_timeout)
Exemplo n.º 6
0
 def __wrapper__(*args, **kwargs):
     _stack_context_handle_exception_partial = partial(
         _stack_context_handle_exception, handler=args[0])
     yield run_with_stack_context(
         stack_context.ExceptionStackContext(
             _stack_context_handle_exception_partial, delay_warning=True),
         lambda: method(*args, **kwargs))
Exemplo n.º 7
0
    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size, tcp_client, max_header_size,
                 max_body_size):
        self.start_time = io_loop.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.max_buffer_size = max_buffer_size
        self.tcp_client = tcp_client
        self.max_header_size = max_header_size
        self.max_body_size = max_body_size
        self.code = None
        self.headers = None
        self.chunks = []
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        self._sockaddr = None
        with stack_context.ExceptionStackContext(self._handle_exception):
            self.parsed = urlparse.urlsplit(_unicode(self.request.url))
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            host, port = httputil.split_host_and_port(netloc)
            if port is None:
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect

            if request.allow_ipv6 is False:
                af = socket.AF_INET
            else:
                af = socket.AF_UNSPEC

            ssl_options = self._get_ssl_options(self.parsed.scheme)

            timeout = min(self.request.connect_timeout,
                          self.request.request_timeout)
            if timeout:
                self._timeout = self.io_loop.add_timeout(
                    self.start_time + timeout,
                    stack_context.wrap(
                        functools.partial(self._on_timeout,
                                          "while connecting")))
            self.tcp_client.connect(host,
                                    port,
                                    af=af,
                                    ssl_options=ssl_options,
                                    max_buffer_size=self.max_buffer_size,
                                    callback=self._on_connect)
Exemplo n.º 8
0
 def __init__(self, callback, barrier_type, on_exception=None):
     callback = stack_context.wrap(callback)
     on_exception = stack_context.wrap(on_exception)
     # Parent frame is derived class __init__, so get grandparent frame.
     frame = sys._getframe().f_back.f_back
     self._barrier = _Barrier(callback, on_exception, barrier_type, frame)
     self._stack_context = stack_context.ExceptionStackContext(
         self._barrier.ReportException)
Exemplo n.º 9
0
    def handle_yield(self, yielded):
        # Lists containing YieldPoints require stack contexts;
        # other lists are handled in convert_yielded.
        if _contains_yieldpoint(yielded):
            yielded = multi(yielded)

        if isinstance(yielded, YieldPoint):
            # YieldPoints are too closely coupled to the Runner to go
            # through the generic convert_yielded mechanism.
            self.future = Future()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        future_set_result_unless_cancelled(
                            self.future, yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = Future()
                    future_set_exc_info(self.future, sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()

                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        else:
            try:
                self.future = convert_yielded(yielded)
            except BadYieldError:
                self.future = Future()
                future_set_exc_info(self.future, sys.exc_info())

        if self.future is moment:
            self.io_loop.add_callback(self.run)
            return False
        elif not self.future.done():

            def inner(f):
                # Break a reference cycle to speed GC.
                f = None  # noqa
                self.run()

            self.io_loop.add_future(self.future, inner)
            return False
        return True
Exemplo n.º 10
0
 def testWithStackContext2(self):
   """Ensure Retry doesn't interfere with asynchronous function that throws immediately."""
   try:
     with stack_context.ExceptionStackContext(self._OnError):
       retry.CallWithRetryAsync(retry.RetryPolicy(), self._AsyncFuncRaisesError,
                                callback=self._OnCompleted)
     self.assert_(False, 'Expected exception to be raised')
   except:
     self.wait()
Exemplo n.º 11
0
    def test_stack_context(self):
        # See http://tornadoweb.org/en/stable/stack_context.html
        # MotorPool.get_socket can block waiting for a callback in another
        # context to return a socket. We verify MotorPool's stack-context
        # handling by testing that exceptions raised in get_socket's
        # continuation are caught in get_socket's stack context, not
        # return_socket's.

        loop = self.io_loop
        history = []
        cx = self.motor_client(max_pool_size=1)

        # Open a socket
        yield cx.motor_test.test_collection.find_one()

        pool = cx._get_primary_pool()
        self.assertEqual(1, len(pool.sockets))
        sock_info = pool.get_socket()

        main_gr = greenlet.getcurrent()

        def catch_get_sock_exc(exc_type, exc_value, exc_traceback):
            history.extend(['get_sock_exc', exc_value])
            return True  # Don't propagate

        def catch_return_sock_exc(exc_type, exc_value, exc_traceback):
            history.extend(['return_sock_exc', exc_value])
            return True  # Don't propagate

        def get_socket():
            # Blocks until socket is available, since max_pool_size is 1.
            pool.get_socket()
            loop.add_callback(raise_callback)

        my_assert = AssertionError('foo')

        def raise_callback():
            history.append('raise')
            raise my_assert

        def return_socket():
            with stack_context.ExceptionStackContext(catch_return_sock_exc):
                pool.maybe_return_socket(sock_info)

            main_gr.switch()

        with stack_context.ExceptionStackContext(catch_get_sock_exc):
            loop.add_callback(greenlet.greenlet(get_socket).switch)

        greenlet.greenlet(return_socket).switch()
        yield self.pause(0.1)

        # 'return_sock_exc' was *not* added to history, because stack context
        # wasn't leaked from return_socket to get_socket.
        self.assertEqual(['raise', 'get_sock_exc', my_assert], history)
        cx.close()
Exemplo n.º 12
0
    def __init__(self, io_loop, client, request, release_callback,
                 final_callback, max_buffer_size):
        self.start_time = io_loop.time()
        self.io_loop = io_loop
        self.client = client
        self.request = request
        self.release_callback = release_callback
        self.final_callback = final_callback
        self.max_buffer_size = max_buffer_size
        self.code = None
        self.headers = None
        self.chunks = None
        self._decompressor = None
        # Timeout handle returned by IOLoop.add_timeout
        self._timeout = None
        with stack_context.ExceptionStackContext(self._handle_exception):
            self.parsed = urlparse.urlsplit(_unicode(self.request.url))
            if ssl is None and self.parsed.scheme == "https":
                raise ValueError("HTTPS requires either python2.6+ or "
                                 "curl_httpclient")
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect
            if self.client.hostname_mapping is not None:
                host = self.client.hostname_mapping.get(host, host)

            if request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            self.client.resolver.getaddrinfo(host,
                                             port,
                                             af,
                                             socket.SOCK_STREAM,
                                             0,
                                             0,
                                             callback=self._on_resolve)
Exemplo n.º 13
0
    def on_connect(self, io_stream):
        log.debug('IOStream opened %s', type(io_stream))
        if self.timed_out:
            log.debug('Connection timeout before socket connected!')
            io_stream.close()
            return

        if self.secure:
            if io_stream.socket.selected_alpn_protocol() not in AlPN_PROTOCOLS:
                log.error(
                    'Negotiated protocols mismatch, got %s, expected one of %s',
                    io_stream.socket.selected_alpn_protocol(),
                    AlPN_PROTOCOLS
                )
                raise ConnectionError('Negotiated protocols mismatch')

        self._is_connected = True

        # remove the connection timeout
        self.io_loop.remove_timeout(self._connect_timeout_t)
        self._connect_timeout_t = None

        self.io_stream = io_stream
        self.io_stream.set_nodelay(True)

        # set the close callback
        self.io_stream.set_close_callback(self.on_close)

        # initialize the connection
        self.h2conn = h2.connection.H2Connection(
            h2.config.H2Configuration(client_side=True)
        )

        # initiate the h2 connection
        self.h2conn.initiate_connection()

        # disable server push
        self.h2conn.update_settings({
            h2.settings.SettingCodes.ENABLE_PUSH: 0,
            h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS:
                self.max_concurrent_streams,
            h2.settings.SettingCodes.INITIAL_WINDOW_SIZE:
                self.initial_window_size
        })

        # set the stream reading callback
        with stack_context.ExceptionStackContext(
                functools.partial(self.on_error, 'during read')
        ):
            self.io_stream.read_bytes(
                num_bytes=65535,
                streaming_callback=self.data_received,
                callback=self.data_received
            )

        self.flush()
Exemplo n.º 14
0
    def process_events(self, events):
        """
        Processes events received on the HTTP/2 connection and
        dispatches them to their corresponding HTTPStreams.
        """
        recv_streams = dict()

        for event in events:
            log.debug(['PROCESSING EVENT', event])
            stream_id = getattr(event, 'stream_id', None)

            if type(event) in self.event_handlers:
                for ev_handler in self.event_handlers[type(event)]:
                    ev_handler(event)

            if isinstance(event, h2.events.DataReceived):
                recv_streams[stream_id] = (recv_streams.get(stream_id, 0) +
                                           event.flow_controlled_length)
            elif isinstance(event, h2.events.WindowUpdated):
                if stream_id == 0:
                    self.flow_control_window.produce(event.delta)
                    log.debug(
                        'INCREMENTED CONNECTION WINDOW BY %d, NOW AT %d',
                        event.delta, self.flow_control_window.value
                    )
            elif isinstance(event, h2.events.RemoteSettingsChanged):
                self.process_settings(event)

            if stream_id and stream_id in self._ongoing_streams:
                stream = self._ongoing_streams[stream_id]
                with stack_context.ExceptionStackContext(
                        stream.handle_exception
                ):
                    stream.handle_event(event)

        recv_connection = 0
        for stream_id, num_bytes in six.iteritems(recv_streams):
            if not num_bytes or stream_id not in self._ongoing_streams:
                continue

            log.debug(
                'Incrementing flow control window for stream %d with %d',
                stream_id, num_bytes
            )
            self.h2conn.increment_flow_control_window(num_bytes, stream_id)

            recv_connection += num_bytes

        if recv_connection:
            log.debug(
                'Incrementing window flow control with %d', recv_connection
            )
            self.h2conn.increment_flow_control_window(recv_connection)

        # flush data that has been generated after processing these events
        self.flush()
Exemplo n.º 15
0
    def send(self, subject='Uber Now', body='Its time to book Uber'):

        with stack_context.ExceptionStackContext(self.error_handler):
            send_mail(str(subject),
                      str(body),
                      self.fro, [self.to],
                      callback=self.callback,
                      connection=EmailBackend(self.host, self.port,
                                              self.username, self.password,
                                              True))
Exemplo n.º 16
0
 def testWithStackContext3(self):
   """Ensure Retry doesn't interfere with asynchronous callback that throws."""
   try:
     with stack_context.ExceptionStackContext(self._OnError):
       retry.CallWithRetryAsync(retry.RetryPolicy(check_exception=lambda typ, val, tb: True), self._AsyncFunc,
                                callback=self._OnCompletedRaisesError)
     self.wait()
     self.assert_(False, 'Expected exception to be raised')
   except Exception as e:
     self.assert_('_OnCompletedRaisesError' in e.message, e)
Exemplo n.º 17
0
    def resolve(self):
        self.proxy_host = getattr(self.request, 'proxy_host', None)
        self.proxy_port = getattr(self.request, 'proxy_port', 8080)

        if self.proxy_host:
            host = self.proxy_host
            port = self.proxy_port
            self.is_support_keepalive = False

        with stack_context.ExceptionStackContext(self._handle_exception):
            self.parsed = urlparse.urlsplit(_unicode(self.request.url))
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            match = re.match(r'^(.+):(\d+)$', netloc)
            if match:
                host = match.group(1)
                port = int(match.group(2))
            else:
                host = netloc
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r'^\[.*\]$', host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect

            if self.request.allow_ipv6:
                af = socket.AF_UNSPEC
            else:
                # We only try the first IP we get from getaddrinfo,
                # so restrict to ipv4 by default.
                af = socket.AF_INET

            self.update_timeout()

        if self.is_connected():
            self.logger.info('is connecting ....')
            self._on_connect()
        else:
            if not self.proxy_host:
                self.resolver.resolve(host,
                                      port,
                                      af,
                                      callback=self._on_resolve)
            else:
                self.resolver.resolve(self.proxy_host,
                                      self.proxy_port,
                                      af,
                                      callback=self._on_resolve)
Exemplo n.º 18
0
            def read_until_cancelled(*args, **kwargs):
                if cancelled():
                    return

                with stack_context.ExceptionStackContext(
                        partial(self.on_error, 'during read', cancelled)):
                    self.io_stream.read_bytes(
                        num_bytes=65535,
                        streaming_callback=partial(
                            self.receive_data_until_cancelled, cancelled),
                        callback=read_until_cancelled)
Exemplo n.º 19
0
    def wrapper(self, *args, **kwargs):
        self._auto_finish = False
        self.token = yield stack_context.run_with_stack_context(
            stack_context.ExceptionStackContext(
                self._stack_context_handle_exception), self.validate_token)
        if not self.token:
            raise tornado.web.HTTPError(403)

        with stack_context.ExceptionStackContext(
                self._stack_context_handle_exception):

            result = method(self, *args, **kwargs)

            if isinstance(result, Future):

                def future_complete(f):
                    f.result()
                    if not self._finished:
                        self.finish()

                IOLoop.current().add_future(result, future_complete)
Exemplo n.º 20
0
    def _execute(self, transforms, *args, **kwargs):
        self.open_args = args
        self.open_kwargs = kwargs

        # Websocket only supports GET method
        with stack_context.ExceptionStackContext(
                self._handle_websocket_exception):
            # Websocket only supports GET method
            if self.request.method != 'GET':
                self.stream.write(
                    tornado.escape.utf8(
                        "HTTP/1.1 405 Method Not Allowed\r\n\r\n"))
                self.stream.close()
                return

            # Upgrade header should be present and should be equal to WebSocket
            if self.request.headers.get("Upgrade", "").lower() != 'websocket':
                self.stream.write(
                    tornado.escape.utf8(
                        "HTTP/1.1 400 Bad Request\r\n\r\n"
                        "Can \"Upgrade\" only to \"WebSocket\"."))
                self.stream.close()
                return

            # Connection header should be upgrade. Some proxy servers/load balancers
            # might mess with it.
            headers = self.request.headers
            connection = map(lambda s: s.strip().lower(),
                             headers.get("Connection", "").split(","))
            if 'upgrade' not in connection:
                self.stream.write(
                    tornado.escape.utf8("HTTP/1.1 400 Bad Request\r\n\r\n"
                                        "\"Connection\" must be \"Upgrade\"."))
                self.stream.close()
                return

            #self.stream.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1)

            # Handle proper protocol version
            if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8",
                                                                     "13"):
                self.ws_connection = WebSocketProtocol8(self)
                self.ws_connection.accept_connection()

            elif self.request.headers.get("Sec-WebSocket-Version"):
                self.stream.write(
                    tornado.escape.utf8("HTTP/1.1 426 Upgrade Required\r\n"
                                        "Sec-WebSocket-Version: 8\r\n\r\n"))
                self.stream.close()

            else:
                self.ws_connection = websocket.WebSocketProtocol76(self)
                self.ws_connection.accept_connection()
Exemplo n.º 21
0
    def handle_yield(self, yielded):
        # Lists containing YieldPoints require stack contexts;
        # other lists are handled via multi_future in convert_yielded.
        if (isinstance(yielded, list) and
                any(isinstance(f, YieldPoint) for f in yielded)):
            yielded = Multi(yielded)
        elif (isinstance(yielded, dict) and
              any(isinstance(f, YieldPoint) for f in yielded.values())):
            yielded = Multi(yielded)

        if isinstance(yielded, YieldPoint):
            # YieldPoints are too closely coupled to the Runner to go
            # through the generic convert_yielded mechanism.
            self.future = TracebackFuture()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        self.future.set_result(
                            yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = TracebackFuture()
                    self.future.set_exc_info(sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()
                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        else:
            try:
                self.future = convert_yielded(yielded)
            except BadYieldError:
                self.future = TracebackFuture()
                self.future.set_exc_info(sys.exc_info())

        if not self.future.done() or self.future is moment:
            self.io_loop.add_future(
                self.future, lambda f: self.run())
            return False
        return True
Exemplo n.º 22
0
    def make_connection(self, ready_callback, close_callback):
        if self.connect_timeout:
            timed_out = [False]
            start_time = time.time()

            def _on_timeout():
                timed_out[0] = True
                close_callback(io_stream=None,
                               reason=HTTP2ConnectionTimeout(time.time() -
                                                             start_time))

            def _on_connect(io_stream):
                if timed_out[0]:
                    io_stream.close()
                    return
                self.io_loop.remove_timeout(timeout_handle)
                self._on_connect(io_stream, ready_callback, close_callback)

            timeout_handle = self.io_loop.add_timeout(
                start_time + self.connect_timeout, _on_timeout)

        else:
            _on_connect = functools.partial(
                self._on_connect,
                ready_callback=ready_callback,
                close_callback=close_callback,
            )

        logger.info('Establishing HTTP/2 connection to %s:%s...', self.host,
                    self.port)
        with stack_context.ExceptionStackContext(
                functools.partial(self._handle_exception, close_callback)):

            addr_info = socket.getaddrinfo(self.host, self.port,
                                           socket.AF_UNSPEC,
                                           socket.SOCK_STREAM, 0, 0)
            af, sock_type, proto, canon_name, sockaddr = addr_info[0]

            if self.secure:
                io_stream = _SSLIOStream(socket.socket(af, sock_type, proto),
                                         hostname=self.host,
                                         io_loop=self.io_loop,
                                         ssl_options=self.ssl_options,
                                         max_buffer_size=self.max_buffer_size)
            else:
                io_stream = iostream.IOStream(
                    socket.socket(af, sock_type, proto),
                    io_loop=self.io_loop,
                    max_buffer_size=self.max_buffer_size)

            io_stream.connect(sockaddr,
                              functools.partial(_on_connect, io_stream))
Exemplo n.º 23
0
    def handle_yield(self, yielded):
        # 返回True已经完成,False表示Future未完成,添加到ioloop中
        # Lists containing YieldPoints require stack contexts;
        # other lists are handled in convert_yielded.
        # 处理 yield list or dict 情况
        if _contains_yieldpoint(yielded):
            yielded = multi(yielded)

        if isinstance(yielded, YieldPoint):
            # YieldPoints are too closely coupled to the Runner to go
            # through the generic convert_yielded mechanism.
            self.future = TracebackFuture()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        self.future.set_result(yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = TracebackFuture()
                    self.future.set_exc_info(sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()

                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        else:
            # Future情况,为r = yield fetch()之类返回的Future
            try:
                self.future = convert_yielded(yielded)
            except BadYieldError:
                self.future = TracebackFuture()
                self.future.set_exc_info(sys.exc_info())

        if not self.future.done() or self.future is moment:
            self.io_loop.add_future(self.future, lambda f: self.run())
            return False
        return True
Exemplo n.º 24
0
    def handle_yield(self, yielded):
        if isinstance(yielded, list):
            if all(is_future(f) for f in yielded):
                yielded = multi_future(yielded)
            else:
                yielded = Multi(yielded)
        elif isinstance(yielded, dict):
            if all(is_future(f) for f in yielded.values()):
                yielded = multi_future(yielded)
            else:
                yielded = Multi(yielded)

        if isinstance(yielded, YieldPoint):
            self.future = TracebackFuture()

            def start_yield_point():
                try:
                    yielded.start(self)
                    if yielded.is_ready():
                        self.future.set_result(yielded.get_result())
                    else:
                        self.yield_point = yielded
                except Exception:
                    self.future = TracebackFuture()
                    self.future.set_exc_info(sys.exc_info())

            if self.stack_context_deactivate is None:
                # Start a stack context if this is the first
                # YieldPoint we've seen.
                with stack_context.ExceptionStackContext(
                        self.handle_exception) as deactivate:
                    self.stack_context_deactivate = deactivate

                    def cb():
                        start_yield_point()
                        self.run()

                    self.io_loop.add_callback(cb)
                    return False
            else:
                start_yield_point()
        elif is_future(yielded):
            self.future = yielded
            if not self.future.done() or self.future is moment:
                self.io_loop.add_future(self.future, lambda f: self.run())
                return False
        else:
            self.future = TracebackFuture()
            self.future.set_exception(
                BadYieldError("yielded unknown object %r" % (yielded, )))
        return True
Exemplo n.º 25
0
    def handle_request(self, request, callback_clear_active, callback):
        """
        Create an HTTP2Stream object for the current request.
        :param request: client request
        :type request: HTTPRequest
        :param callback_clear_active: function executed when the request
                                      finishes, removes the current stream
                                      from the list of active streams.
        :param callback: function executed when the request finishes
        """
        stream = self.stream_cls(self.connection, request,
                                 callback_clear_active, callback, self.io_loop)

        with stack_context.ExceptionStackContext(stream.handle_exception):
            stream.begin_request()
Exemplo n.º 26
0
 def __init__(self, host, port, io_loop):
     self.io_loop = io_loop
     self.resolver = Resolver()
     self.stream = None
     self.queue = deque()
     self._callbacks = {}
     self._connected = False
     self.read_state = self.READ_HEAD
     self.prev_response = None
     self.prof = {}
     with stack_context.ExceptionStackContext(self._handle_exception):
         self.resolver.resolve(host,
                               port,
                               socket.AF_INET,
                               callback=self._on_resolve)
Exemplo n.º 27
0
 def __init__(self, host, port, io_loop, key):
     self.io_loop = io_loop
     self.resolver = Resolver()
     self._callbacks = {}
     self._connected = False
     self.queue = deque()
     self.key = key
     self.stream = None
     self.pepv_act_resp = None
     self.prof = {}
     with stack_context.ExceptionStackContext(self._handle_exception):
         self.resolver.resolve(host,
                               port,
                               socket.AF_INET,
                               callback=self._on_resolve)
Exemplo n.º 28
0
    def wrapper(self, *args, **kwargs):
        self._auto_finish = False
        with stack_context.ExceptionStackContext(
                self._stack_context_handle_exception):
            result = method(self, *args, **kwargs)
            if is_future(result):

                def future_complete(f):
                    f.result()
                    if not self._finished:
                        self.finish()

                IOLoop.current().add_future(result, future_complete)
                return None
            return result
Exemplo n.º 29
0
    def _process_events(self, events):
        stream_inbounds = collections.defaultdict(int)

        for event in events:
            if isinstance(event, h2.events.DataReceived):
                stream_inbounds[
                    event.stream_id] += event.flow_controlled_length

            if isinstance(event, h2.events.PushedStreamReceived):
                stream_id = event.parent_stream_id
            else:
                stream_id = getattr(event, 'stream_id', None)

            if stream_id is not None and stream_id != 0:
                if stream_id in self.stream_delegates:
                    stream_delegate = self.stream_delegates[stream_id]

                    with stack_context.ExceptionStackContext(
                            stream_delegate.handle_exception):
                        stream_delegate.handle_event(event)
                else:
                    # FIXME: our nginx server will simply reset stream,
                    # without increase the window size which consumed by
                    # queued data frame which was belongs to the stream we're resetting
                    # self.reset_stream(stream_id)
                    if stream_id in self.reset_stream_ids:
                        if isinstance(event, h2.events.StreamEnded):
                            self.reset_stream_ids.remove(stream_id)
                    else:
                        logger.warning('Unexpected stream: %s, event: %r',
                                       stream_id, event)

                continue

            event_type = type(event)
            if event_type in self.event_handlers:
                try:
                    self.event_handlers[event_type](event)
                except Exception as err:
                    logger.exception('Exception while handling event: %r', err)

                continue

            logger.debug('ignored event: %r, %r', event, event.__dict__)

        for stream_id, stream_inbound in stream_inbounds.items():
            self.h2_conn.acknowledge_received_data(stream_inbound, stream_id)
Exemplo n.º 30
0
    def send(self,
             stream=False,
             timeout=None,
             verify=True,
             cert=None,
             proxies=None):
        request = self.request
        connect_timeout, self.read_timeout = parse_timeout(timeout)
        self.stream_body = stream

        # set connect timeout
        with stack_context.ExceptionStackContext(self._handle_exception):
            if connect_timeout:
                self._timeout = self.io_loop.call_later(
                    connect_timeout,
                    stack_context.wrap(
                        functools.partial(self._on_timeout,
                                          'while connecting')))

            # set proxy related info
            proxy = select_proxy(request.url, proxies)
            self.headers = request.headers.copy()
            if proxy:
                proxy = prepend_scheme_if_needed(proxy, 'http')
                parsed = urlparse(proxy)
                scheme, host, port = parsed.scheme, proxy, parsed.port
                port = port or (443 if scheme == 'https' else 80)
                self.start_line = RequestStartLine(request.method, request.url,
                                                   '')
                self.headers.update(get_proxy_headers(proxy))
            else:
                host, port = None, None
                self.start_line = request.start_line

            self.tcp_client.connect(request.host,
                                    request.port,
                                    af=request.af,
                                    ssl_options=self._get_ssl_options(
                                        request, verify, cert),
                                    max_buffer_size=self.max_buffer_size,
                                    source_ip=host,
                                    source_port=port,
                                    callback=self._on_connect)