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
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
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)
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
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
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)
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 = {}
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\''
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'
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
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
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 = {}
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)
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
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()
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)
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()
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
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 = {}
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
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
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
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
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()
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)
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)
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'
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