Exemplo n.º 1
0
 def test_no_data_on_closed_stream(self, tctx):
     frame_factory = FrameFactory()
     req = Request.make("GET", "http://example.com/")
     resp = {":status": 200}
     assert (
         Playbook(Http2Client(tctx)) << SendData(
             tctx.server,
             Placeholder(bytes))  # preamble + initial settings frame
         >> DataReceived(
             tctx.server,
             frame_factory.build_settings_frame({}, ack=True).serialize())
         >> http.RequestHeaders(1, req, end_stream=True) << SendData(
             tctx.server,
             b"\x00\x00\x06\x01\x05\x00\x00\x00\x01\x82\x86\x84\\\x81\x07")
         >> http.RequestEndOfMessage(1) >> DataReceived(
             tctx.server,
             frame_factory.build_headers_frame(resp).serialize()) <<
         http.ReceiveHttp(Placeholder(
             http.ResponseHeaders)) >> http.RequestProtocolError(
                 1, "cancelled", code=status_codes.CLIENT_CLOSED_REQUEST) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.CANCEL).serialize()) >> DataReceived(
                     tctx.server,
                     frame_factory.build_data_frame(b"foo").serialize()) <<
         SendData(
             tctx.server,
             frame_factory.build_rst_stream_frame(
                 1, ErrorCodes.STREAM_CLOSED).serialize())
     )  # important: no ResponseData event here!
Exemplo n.º 2
0
def test_early_server_data(tctx):
    playbook, cff = start_h2_client(tctx)
    sff = FrameFactory()

    tctx.server.address = ("example.com", 80)
    tctx.server.state = ConnectionState.OPEN
    tctx.server.alpn = b"h2"

    flow = Placeholder(HTTPFlow)
    server1 = Placeholder(bytes)
    server2 = Placeholder(bytes)
    assert (
            playbook
            >> DataReceived(tctx.client,
                            cff.build_headers_frame(example_request_headers, flags=["END_STREAM"]).serialize())
            << http.HttpRequestHeadersHook(flow)
            >> reply()
            << (h := http.HttpRequestHook(flow))
            # Surprise! We get data from the server before the request hook finishes.
            >> DataReceived(tctx.server, sff.build_settings_frame({}).serialize())
            << SendData(tctx.server, server1)
            # Request hook finishes...
            >> reply(to=h)
            << SendData(tctx.server, server2)
    )
    assert [type(x) for x in decode_frames(server1())] == [
        hyperframe.frame.SettingsFrame,
        hyperframe.frame.SettingsFrame,
    ]
    assert [type(x) for x in decode_frames(server2())] == [
        hyperframe.frame.HeadersFrame,
    ]
Exemplo n.º 3
0
def start_h2_client(tctx: Context) -> Tuple[Playbook, FrameFactory]:
    tctx.client.alpn = b"h2"
    frame_factory = FrameFactory()

    playbook = Playbook(http.HttpLayer(tctx, HTTPMode.regular))
    assert (
            playbook
            << SendData(tctx.client, Placeholder())  # initial settings frame
            >> DataReceived(tctx.client, frame_factory.preamble())
            >> DataReceived(tctx.client, frame_factory.build_settings_frame({}, ack=True).serialize())
    )
    return playbook, frame_factory
Exemplo n.º 4
0
def test_max_concurrency(tctx):
    playbook, cff = start_h2_client(tctx)
    server = Placeholder(Server)
    req1_bytes = Placeholder(bytes)
    settings_ack_bytes = Placeholder(bytes)
    req2_bytes = Placeholder(bytes)
    playbook.hooks = False
    sff = FrameFactory()

    assert (playbook >> DataReceived(
        tctx.client,
        cff.build_headers_frame(example_request_headers,
                                flags=["END_STREAM"],
                                stream_id=1).serialize()) <<
            OpenConnection(server) >> reply(None, side_effect=make_h2) <<
            SendData(server, req1_bytes) >> DataReceived(
                server,
                sff.build_settings_frame({
                    h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS:
                    1
                }).serialize()) << SendData(
                    server, settings_ack_bytes) >> DataReceived(
                        tctx.client,
                        cff.build_headers_frame(example_request_headers,
                                                flags=["END_STREAM"],
                                                stream_id=3).serialize())
            # Can't send it upstream yet, all streams in use!
            >> DataReceived(
                server,
                sff.build_headers_frame(example_response_headers,
                                        flags=["END_STREAM"],
                                        stream_id=1).serialize())
            # But now we can!
            << SendData(server, req2_bytes) <<
            SendData(tctx.client, Placeholder(bytes)) >> DataReceived(
                server,
                sff.build_headers_frame(example_response_headers,
                                        flags=["END_STREAM"],
                                        stream_id=3).serialize()) << SendData(
                                            tctx.client, Placeholder(bytes)))
    settings, req1 = decode_frames(req1_bytes())
    settings_ack, = decode_frames(settings_ack_bytes())
    req2, = decode_frames(req2_bytes())

    assert type(settings) == hyperframe.frame.SettingsFrame
    assert type(req1) == hyperframe.frame.HeadersFrame
    assert type(settings_ack) == hyperframe.frame.SettingsFrame
    assert type(req2) == hyperframe.frame.HeadersFrame
    assert req1.stream_id == 1
    assert req2.stream_id == 3
Exemplo n.º 5
0
def h2_frames(draw):
    ff = FrameFactory()
    headers1 = ff.build_headers_frame(headers=draw(h2_headers()))
    headers1.flags.clear()
    headers1.flags |= draw(h2_flags)
    headers2 = ff.build_headers_frame(headers=draw(h2_headers()),
                                      depends_on=draw(h2_stream_ids),
                                      stream_weight=draw(integers(0, 255)),
                                      exclusive=draw(booleans()))
    headers2.flags.clear()
    headers2.flags |= draw(h2_flags)
    settings = ff.build_settings_frame(settings=draw(
        dictionaries(
            keys=sampled_from(SettingCodes),
            values=integers(0, 2**32 - 1),
            max_size=5,
        )),
                                       ack=draw(booleans()))
    continuation = ff.build_continuation_frame(header_block=ff.encoder.encode(
        draw(h2_headers())),
                                               flags=draw(h2_flags))
    goaway = ff.build_goaway_frame(draw(h2_stream_ids))
    push_promise = ff.build_push_promise_frame(
        stream_id=draw(h2_stream_ids_nonzero),
        promised_stream_id=draw(h2_stream_ids),
        headers=draw(h2_headers()))
    rst = ff.build_rst_stream_frame(draw(h2_stream_ids_nonzero))
    prio = ff.build_priority_frame(
        stream_id=draw(h2_stream_ids_nonzero),
        weight=draw(integers(0, 255)),
        depends_on=draw(h2_stream_ids),
        exclusive=draw(booleans()),
    )
    data1 = ff.build_data_frame(draw(binary()), draw(h2_flags))
    data2 = ff.build_data_frame(draw(binary()),
                                draw(h2_flags),
                                stream_id=draw(h2_stream_ids_nonzero))
    window_update = ff.build_window_update_frame(draw(h2_stream_ids),
                                                 draw(integers(0, 2**32 - 1)))

    frames = draw(
        lists(sampled_from([
            headers1, headers2, settings, continuation, goaway, push_promise,
            rst, prio, data1, data2, window_update
        ]),
              min_size=1,
              max_size=11))
    return b"".join(x.serialize() for x in frames)