Example #1
0
def create_connections(*,
                       connection_window=None,
                       stream_window=None,
                       max_frame_size=None):
    server_conn = H2Connection(
        H2Configuration(client_side=False, header_encoding='ascii'))
    server_conn.initiate_connection()

    if connection_window is not None:
        initial_window_size = server_conn.local_settings.initial_window_size
        assert connection_window > initial_window_size, (
            '{} should be greater than {}'.format(connection_window,
                                                  initial_window_size))
        server_conn.increment_flow_control_window(connection_window -
                                                  initial_window_size)

    if stream_window is not None:
        server_conn.update_settings(
            {SettingCodes.INITIAL_WINDOW_SIZE: stream_window})

    if max_frame_size is not None:
        server_conn.update_settings(
            {SettingCodes.MAX_FRAME_SIZE: max_frame_size})

    client_conn = H2Connection(
        H2Configuration(client_side=True, header_encoding='ascii'))
    client_conn.initiate_connection()

    client_conn.receive_data(server_conn.data_to_send())
    server_conn.receive_data(client_conn.data_to_send())
    client_conn.receive_data(server_conn.data_to_send())

    return client_conn, server_conn
Example #2
0
 def __init__(self):
     config = H2Configuration(client_side=False, header_encoding='utf-8')
     self.conn = H2Connection(config=config)
     self.transport = None
     self.stream_data = {}  # type: Dict[int, RequestData]
     self.resp_stream_data = {}  # type: Dict[int, ResponseData]
     self.client_cert = None  # type: SSLCertT
Example #3
0
 def __init__(self, sock):
     config = H2Configuration(client_side=False,
                              validate_inbound_headers=False)
     self.tls = threading.local()
     self.tls.conns = {}
     self.sock = sock
     self.conn = H2Connection(config=config)
    def __init__(self, protocol):
        self.connection = H2Connection(
            H2Configuration(client_side=False, header_encoding='utf-8'))
        self._transport = TransportStub(self.connection)

        self._protocol = protocol
        self._protocol.connection_made(self._transport)
Example #5
0
    def __init__(self):
        # Our server-side state machine.
        self.conn = H2Connection(client_side=False)

        # The backing transport.
        self.transport = None

        # A dictionary of ``Stream`` objects, keyed by their stream ID. This
        # makes it easy to route data to the correct WSGI application instance.
        self.streams = {}

        # A queue of data emitted by WSGI applications that has not yet been
        # sent. Each stream may only have one chunk of data in either this
        # queue or the flow_controlled_data dictionary at any one time.
        self._stream_data = asyncio.Queue()

        # Data that has been pulled off the queue that is for a stream blocked
        # behind flow control limitations. This is used to avoid spinning on
        # _stream_data queue when a stream cannot have its data sent. Data that
        # cannot be sent on the connection when it is popped off the queue gets
        # placed here until the stream flow control window opens up again.
        self._flow_controlled_data = {}

        # A reference to the loop in which this protocol runs. This is needed
        # to synchronise up with background threads.
        self._loop = asyncio.get_event_loop()

        # Any streams that have been remotely reset. We keep track of these to
        # ensure that we don't emit data from a WSGI application whose stream
        # has been cancelled.
        self._reset_streams = set()

        # Keep track of the loop sending task so we can kill it when the
        # connection goes away.
        self._send_loop_task = None
Example #6
0
 def __init__(self, client_side=True, method_finder=None):
     print('client side', client_side)
     self.conn = H2Connection(
         config=H2Configuration(
             client_side=client_side, header_encoding='utf-8'))
     self.transport = None
     self.method_finder = method_finder
Example #7
0
 def __init__(self, base):
     self.server = base.server
     self._conn = H2Connection(client_side=False, header_encoding=False)
     self._requests = {}  # type: typing.Dict[int, HttpRequest]
     self._window = {}  # type: typing.Dict[int, int]
     self._responses = []  # type: typing.List[HttpResponse]
     AbstractWebProtocol.__init__(self, base)
Example #8
0
    def __init__(self, component, parent_context: Context):
        # The current component used by this connection.
        self.component = component

        self.parent_context = parent_context

        config = H2Configuration(client_side=False, header_encoding="utf-8")

        # The HTTP/2 state machine.
        self.conn = H2Connection(config=config)

        # The current transport for this connection.
        self.transport = None  # type: asyncio.WriteTransport

        # The current streams for this request.
        # This is a dictionary of stream_id -> data.
        self.streams = {}  # type: typing.Dict[H2State]

        # The current stream data queue.
        # This is a Queue of two-item tuples: (stream_data, stream_id).
        # These are plucked off of a Werkzeug request as they come in from Kyoukai.
        self.stream_data = collections.defaultdict(
            lambda *args: asyncio.Queue())

        # The current logger.
        self.logger = logging.getLogger("Kyoukai.HTTP2")

        # Client data.
        self.ip, self.client_port = None, None

        # If we're waiting to send data due to the window being exceeded.
        self._locked = collections.defaultdict(lambda *args: asyncio.Event())

        # The dictionary of stream tasks.
        self.stream_tasks = {}
Example #9
0
def test_unary_streaming_rpc_error_defered(transport, proto, clock):
    results = proto.call_unary_streaming_rpc('foo', b'payload', 5)
    conn = H2Connection(client_side=False)
    conn.initiate_connection()
    proto.dataReceived(conn.data_to_send())

    d = results.next()

    events = conn.receive_data(transport.value())
    transport.clear()
    req, events = next_event(events, h2.events.RequestReceived)

    conn.send_headers(req.stream_id, (
        (':status', '200'),
    ))
    conn.send_headers(
        req.stream_id,
        (
            ('grpc-status', '1'),
            ('grpc-message', 'I am sad'),
        ),
        end_stream=True
    )

    proto.dataReceived(conn.data_to_send())

    with pytest.raises(GRPCError) as excinfo:
        yield d

    value = str(excinfo.value).replace('u\'', '\'')
    assert value == 'Non-0 grpc-status code. \'1\' \'I am sad\''
Example #10
0
def test_size_too_large(transport, proto, clock):
    d = proto.call_rpc('foo', b'payload', 5)
    conn = H2Connection(client_side=False)
    conn.initiate_connection()
    proto.dataReceived(conn.data_to_send())

    events = conn.receive_data(transport.value())
    transport.clear()
    req, events = next_event(events, h2.events.RequestReceived)

    conn.send_headers(req.stream_id, (
        (':status', '200'),
        ('grpc-status', '0'),
        ('grpc-message', 'OK'),
    ))
    # Compression
    conn.send_data(req.stream_id, b'\x00')
    # Length of 'result' network byte order
    conn.send_data(req.stream_id, b'\x00\x00\x00\x09')
    conn.send_data(req.stream_id, b'result', end_stream=True)

    proto.dataReceived(conn.data_to_send())

    with pytest.raises(GRPCError) as excinfo:
        yield d
    assert str(excinfo.value) == 'Extra data in stream'
Example #11
0
    def __init__(self, handler, request):
        self.handler = handler
        self.wasc = handler.wasc
        self.request = request
        self.channel = request.channel

        # replace fifo with supporting priority, ready, removing
        if self.wasc.numthreads:
            self.channel.producer_fifo = http2_producer_ts_fifo()
        else:
            self.channel.producer_fifo = http2_producer_fifo()

        self.conn = H2Connection(H2Configuration(client_side=False))
        self.frame_buf = self.conn.incoming_buffer
        self.frame_buf.max_frame_size = self.conn.max_inbound_frame_size

        self.data_length = 0
        self.current_frame = None
        self.rfile = BytesIO()
        self.buf = b""

        self.requests = {}
        self.priorities = {}
        self.promises = {}

        self._closed = False
        self._got_preamble = False

        self._plock = threading.Lock()  # for self.conn
        self._clock = threading.Lock()  # for self.x
Example #12
0
 def __init__(self, methods: Dict[str, 'ServiceMethod'], *, loop):
     self._loop = loop
     self._events = asyncio.Queue()
     self.conn = H2Connection(client_side=False)
     self.transport = None
     self.stream_data = {}
     self.methods = methods
Example #13
0
    def __init__(self, root):
        config = H2Configuration(client_side=False)
        self.conn = H2Connection(config=config)
        self.known_proto = None
        self.root = root

        self._flow_control_deferreds = {}
Example #14
0
    def connection_made(self, transport: BaseTransport) -> None:
        sock = transport.get_extra_info('socket')
        if sock is not None:
            _set_nodelay(sock)

        h2_conn = H2Connection(config=self.h2_config)
        h2_conn.initiate_connection()

        initial = h2_conn.local_settings.initial_window_size
        conn_delta = self.config.http2_connection_window_size - initial
        stream_delta = self.config.http2_stream_window_size - initial
        if conn_delta:
            h2_conn.increment_flow_control_window(conn_delta)
        if stream_delta:
            h2_conn.update_settings({
                SettingCodes.INITIAL_WINDOW_SIZE:
                self.config.http2_stream_window_size,
            })

        self.connection = Connection(
            h2_conn,
            cast(Transport, transport),
            config=self.config,
        )
        self.connection.flush()
        self.connection.initialize()

        self.processor = EventsProcessor(self.handler, self.connection)
Example #15
0
 def __init__(self):
     config = H2Configuration(client_side=False, header_encoding='utf-8')
     self.conn = H2Connection(config=config)
     self.transport = None
     self.stream_data = {}
     self.flow_control_futures = {}
     self.received_images_c = 0
Example #16
0
    def handle_one_request(self):
        """
        This is the main HTTP/2.0 Handler. When a browser opens a connection to the server
        on the HTTP/2.0 port, Because there can be multiple H2 connections active at the same
        time, a UUID is created for each so that it is easier to tell them apart in the logs.
        """

        config = H2Configuration(client_side=False)
        self.conn = H2ConnectionGuard(H2Connection(config=config))
        self.close_connection = False

        # Generate a UUID to make it easier to distinguish different H2 connection debug messages
        uid = uuid.uuid4()

        self.logger.debug('(%s) Initiating h2 Connection' % uid)

        with self.conn as connection:
            connection.initiate_connection()
            data = connection.data_to_send()

        self.request.sendall(data)

        self.request_threads = []

        # TODO Need to do some major work on multithreading. Current idea is to have a thread per stream
        # so that processing of the request can start from the first frame.

        while not self.close_connection:
            try:
                # This size may need to be made variable based on remote settings?
                data = self.request.recv(65535)

                with self.conn as connection:
                    events = connection.receive_data(data)

                self.logger.debug('(%s) Events: ' % (uid) + str(events))

                for event in events:
                    if isinstance(event, RequestReceived):
                        self.logger.debug('(%s) Parsing RequestReceived' %
                                          (uid))
                        self._h2_parse_request(event)
                        t = threading.Thread(
                            target=BaseWebTestRequestHandler.finish_handling,
                            args=(self, True, H2Response))
                        self.request_threads.append(t)
                        t.start()
                    if isinstance(event, ConnectionTerminated):
                        self.logger.debug(
                            '(%s) Connection terminated by remote peer ' %
                            (uid))
                        self.close_connection = True

            except (socket.timeout, socket.error) as e:
                self.logger.debug('(%s) ERROR - Closing Connection - \n%s' %
                                  (uid, str(e)))
                self.close_connection = True
                for t in self.request_threads:
                    t.join()
Example #17
0
    def connection_made(self, transport: Transport):  # type: ignore
        h2_conn = H2Connection(config=self.config)
        h2_conn.initiate_connection()

        self.connection = Connection(h2_conn, transport, loop=self.loop)
        self.connection.flush()

        self.processor = EventsProcessor(self.handler, self.connection)
Example #18
0
 def connection_made(self, transport):
     self._peername = transport.get_extra_info('peername')
     logger.debug(f'Connection to {self._peername} established')
     self._transport = transport
     self._h2 = H2Connection(config=self._h2_config)
     self._h2.initiate_connection()
     self._flush()
     self.resume_writing()
Example #19
0
 def __init__(self, file_path):
     self.conn = H2Connection()
     self.known_proto = None
     self.request_made = False
     self.request_complete = False
     self.file_path = file_path
     self.flow_control_deferred = None
     self.fileobj = None
     self.file_size = None
Example #20
0
 def __init__(self, sock, h2_to_server=False):
     listening_config = H2Configuration(client_side=False,
                                        validate_inbound_headers=False)
     self.tls = threading.local()
     self.tls.http_conns = {}
     self.sock = sock
     self.listening_conn = H2Connection(config=listening_config)
     self.is_h2_to_server = h2_to_server
     self.request_infos = {}
Example #21
0
def test_timeout(transport, proto, clock):
    d = proto.call_rpc('foo', b'payload', 5)
    conn = H2Connection(client_side=False)
    conn.initiate_connection()
    proto.dataReceived(conn.data_to_send())

    clock.advance(6)

    with pytest.raises(TimeoutError):
        yield d
Example #22
0
 def __init__(self):
     self.h2conn = H2Connection()
     self.file_tx_size = -1
     self.bytes_received = 0
     self.sysdiagnose_bytes = []  # list of bytestrings
     self.sysdiagnose_filename = ""
     # state vars
     self.accept_phase = False  # determines whether we are in "wait" phase or "accept" phase
     self.response_received = False
     self.file_stream_open = False
Example #23
0
def test_max_window_size(config):
    server_h2c = H2Connection(
        H2Configuration(client_side=False, header_encoding='ascii'))
    proto = H2Protocol(Mock(), config.__for_test__(),
                       H2Configuration(client_side=True))
    proto.connection_made(TransportStub(server_h2c))
    assert server_h2c.outbound_flow_control_window \
        == config.http2_connection_window_size
    assert server_h2c.remote_settings.initial_window_size \
        == config.http2_stream_window_size
Example #24
0
    def __init__ (self, handler, request):
        self._default_varialbes (handler, request)
        self.conn = H2Connection (H2Configuration (client_side = False))

        self._frame_buf = self.conn.incoming_buffer
        self._frame_buf.max_frame_size = self.conn.max_inbound_frame_size
        self._data_length = 0
        self._current_frame = None
        self._rfile = BytesIO ()
        self._buf = b""
        self._got_preamble = False
Example #25
0
    def __init__(self, sock, client_side):
        self.sock = sock

        config = H2Configuration(client_side=client_side)
        self.conn = H2Connection(config=config)

        self.receive_streams = {}
        self.send_streams = {}

        self.run = True
        self.stopped = Event()
Example #26
0
    def connection_made(self, transport: Transport):  # type: ignore
        sock = transport.get_extra_info('socket')
        if sock is not None:
            _set_nodelay(sock)

        h2_conn = H2Connection(config=self.config)
        h2_conn.initiate_connection()

        self.connection = Connection(h2_conn, transport, loop=self.loop)
        self.connection.flush()

        self.processor = EventsProcessor(self.handler, self.connection)
Example #27
0
    def __init__(self, *, loop):
        server_config = H2Configuration(client_side=False,
                                        header_encoding='utf-8')
        self.server_h2c = H2Connection(server_config)

        self.to_server_transport = TransportStub(self.server_h2c)

        client_config = H2Configuration(client_side=True,
                                        header_encoding='utf-8')
        self.client_proto = H2Protocol(client.Handler(), client_config,
                                       loop=loop)
        self.client_proto.connection_made(self.to_server_transport)
Example #28
0
 def __init__(self, upstream_resolver=None, uri=None, logger=None):
     config = H2Configuration(client_side=False, header_encoding='utf-8')
     self.conn = H2Connection(config=config)
     self.logger = logger
     if logger is None:
         self.logger = utils.configure_logger('doh-proxy', 'DEBUG')
     self.transport = None
     self.stream_data = {}
     self.upstream_resolver = upstream_resolver
     self.uri = constants.DOH_URI if uri is None else uri
     assert upstream_resolver is not None, \
         'An upstream resolver must be provided'
Example #29
0
def test_unary_streaming_rpc_success(transport, proto):
    result = proto.call_unary_streaming_rpc('foo', b'payload', 5)
    conn = H2Connection(client_side=False)
    conn.initiate_connection()
    proto.dataReceived(conn.data_to_send())

    events = conn.receive_data(transport.value())
    transport.clear()

    req, events = next_event(events, h2.events.RequestReceived)
    data, events = collect_data(events, req.stream_id)
    end, events = next_event(events, h2.events.StreamEnded)

    assert req.headers[0] == (':method', 'POST')
    assert req.headers[1] == (':scheme', 'http')
    assert req.headers[2] == (':path', 'foo')
    assert req.headers[3] == (':authority', 'localhost:8080')
    assert req.headers[4] == ('grpc-timeout', '5050m')
    assert req.headers[5] == ('te', 'trailers')
    assert req.headers[6] == ('content-type', 'application/grpc+proto')

    # No compression
    assert data[0:1] == b'\x00'
    # Length of 'payload' network byte order
    assert data[1:5] == b'\x00\x00\x00\x07'
    assert data[5:] == b'payload'

    assert end.stream_id == req.stream_id

    conn.send_headers(req.stream_id, (
        (':status', '200'),
        ('grpc-status', '0'),
        ('grpc-message', 'OK'),
    ))

    # No compression
    conn.send_data(req.stream_id, b'\x00')
    # Length of 'result1' network byte order
    conn.send_data(req.stream_id, b'\x00\x00\x00\x07')
    conn.send_data(req.stream_id, b'result1')

    # No compression
    conn.send_data(req.stream_id, b'\x00')
    # Length of 'result2' network byte order
    conn.send_data(req.stream_id, b'\x00\x00\x00\x07')
    conn.send_data(req.stream_id, b'result2', end_stream=True)

    proto.dataReceived(conn.data_to_send())

    for i, d in enumerate(result, 1):
        if d is None:
            break
        assert ('result%s' % i).encode('ascii') == (yield d)
    def __init__(self, settings: dict, loop: asyncio.AbstractEventLoop):
        super().__init__()
        self.loop = loop
        self.transport: asyncio.Transport = None
        self.peername = None
        self.socket = None
        self.h2conn = H2Connection()
        self.logger = logging.getLogger(self.__class__.__name__)

        self.connection_open = False

        self._sent_streams = {}
        self._settings = settings
        self._goaway_waiter = None