Changed writing code to honor the peer's header size limit setting.

Changed large_metadata test to only cover the case where both the client
and server support large metadata; I will cover the other cases in
separate tests in a subsequent commit.
pull/6320/head
Mark D. Roth 9 years ago
parent 125590f9d5
commit ebbbce3e6e
  1. 85
      src/core/ext/transport/chttp2/transport/chttp2_transport.c
  2. 35
      test/core/end2end/tests/large_metadata.c

@ -854,24 +854,37 @@ static void perform_stream_op_locked(
stream_global->send_initial_metadata_finished =
add_closure_barrier(on_complete);
stream_global->send_initial_metadata = op->send_initial_metadata;
if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
stream_global->seen_error = true;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (!stream_global->write_closed) {
if (transport_global->is_client) {
GPR_ASSERT(stream_global->id == 0);
grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
stream_global);
maybe_start_some_streams(exec_ctx, transport_global);
const size_t metadata_size = grpc_metadata_batch_size(
op->send_initial_metadata);
const size_t metadata_peer_limit =
transport_global->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
if (metadata_size > metadata_peer_limit) {
gpr_log(GPR_DEBUG,
"initial metadata size exceeds peer limit (%lu vs. %lu)",
metadata_size, metadata_peer_limit);
cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED);
} else {
if (contains_non_ok_status(transport_global, op->send_initial_metadata)) {
stream_global->seen_error = true;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (!stream_global->write_closed) {
if (transport_global->is_client) {
GPR_ASSERT(stream_global->id == 0);
grpc_chttp2_list_add_waiting_for_concurrency(transport_global,
stream_global);
maybe_start_some_streams(exec_ctx, transport_global);
} else {
GPR_ASSERT(stream_global->id != 0);
grpc_chttp2_become_writable(transport_global, stream_global);
}
} else {
GPR_ASSERT(stream_global->id != 0);
grpc_chttp2_become_writable(transport_global, stream_global);
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_initial_metadata_finished, 0);
}
} else {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_initial_metadata_finished, 0);
}
}
@ -895,19 +908,33 @@ static void perform_stream_op_locked(
stream_global->send_trailing_metadata_finished =
add_closure_barrier(on_complete);
stream_global->send_trailing_metadata = op->send_trailing_metadata;
if (contains_non_ok_status(transport_global, op->send_trailing_metadata)) {
stream_global->seen_error = true;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_trailing_metadata_finished,
grpc_metadata_batch_is_empty(op->send_trailing_metadata));
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
grpc_chttp2_become_writable(transport_global, stream_global);
const size_t metadata_size = grpc_metadata_batch_size(
op->send_trailing_metadata);
const size_t metadata_peer_limit =
transport_global->settings[GRPC_PEER_SETTINGS]
[GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
if (metadata_size > metadata_peer_limit) {
gpr_log(GPR_DEBUG,
"trailing metadata size exceeds peer limit (%lu vs. %lu)",
metadata_size, metadata_peer_limit);
cancel_from_api(exec_ctx, transport_global, stream_global,
GRPC_STATUS_RESOURCE_EXHAUSTED);
} else {
if (contains_non_ok_status(transport_global,
op->send_trailing_metadata)) {
stream_global->seen_error = true;
grpc_chttp2_list_add_check_read_ops(transport_global, stream_global);
}
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, stream_global,
&stream_global->send_trailing_metadata_finished,
grpc_metadata_batch_is_empty(op->send_trailing_metadata));
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
}

@ -97,9 +97,8 @@ static void end_test(grpc_end2end_test_fixture *f) {
grpc_completion_queue_destroy(f->cq);
}
/* Request with a large amount of metadata.*/
static void test_request_with_large_metadata(grpc_end2end_test_config config,
int allow_large_metadata) {
/* Request with a large amount of metadata. */
static void test_request_with_large_metadata(grpc_end2end_test_config config) {
grpc_call *c;
grpc_call *s;
gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world");
@ -107,16 +106,12 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
grpc_raw_byte_buffer_create(&request_payload_slice, 1);
gpr_timespec deadline = five_seconds_time();
grpc_metadata meta;
const char *test_name = allow_large_metadata
? "test_request_with_large_metadata_allowed"
: "test_request_with_large_metadata_not_allowed";
const size_t large_size = 64 * 1024;
grpc_arg arg = { GRPC_ARG_INTEGER, GRPC_ARG_MAX_METADATA_SIZE,
{ .integer=(int)large_size + 1024 } };
grpc_channel_args args = { 1, &arg };
grpc_channel_args* use_args = allow_large_metadata ? &args : NULL;
grpc_end2end_test_fixture f = begin_test(
config, test_name, use_args, use_args);
config, "test_request_with_large_metadata", &args, &args);
cq_verifier *cqv = cq_verifier_create(f.cq);
grpc_op ops[6];
grpc_op *op;
@ -146,6 +141,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
grpc_metadata_array_init(&request_metadata_recv);
grpc_call_details_init(&call_details);
/* Client: send request. */
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 1;
@ -182,9 +178,11 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
grpc_server_request_call(f.server, &s, &call_details,
&request_metadata_recv, f.cq, f.cq, tag(101));
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(101), 1);
cq_verify(cqv);
/* Server: send initial metadata and receive request. */
op = ops;
op->op = GRPC_OP_SEND_INITIAL_METADATA;
op->data.send_initial_metadata.count = 0;
@ -199,9 +197,11 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL);
GPR_ASSERT(GRPC_CALL_OK == error);
cq_expect_completion(cqv, tag(102), allow_large_metadata);
cq_expect_completion(cqv, tag(102), 1);
cq_verify(cqv);
/* Server: receive close and send status. This should trigger
completion of request on client. */
op = ops;
op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
op->data.recv_close_on_server.cancelled = &was_cancelled;
@ -222,19 +222,13 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
cq_expect_completion(cqv, tag(1), 1);
cq_verify(cqv);
GPR_ASSERT(status == (allow_large_metadata ? GRPC_STATUS_OK
: GRPC_STATUS_RESOURCE_EXHAUSTED));
GPR_ASSERT(status == GRPC_STATUS_OK);
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(0 == strcmp(call_details.method, "/foo"));
GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr"));
GPR_ASSERT(was_cancelled == 0);
if (allow_large_metadata) {
GPR_ASSERT(0 == strcmp(details, "xyz"));
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
} else {
GPR_ASSERT(request_payload_recv == NULL);
GPR_ASSERT(!contains_metadata_key(&request_metadata_recv, "key"));
}
GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
GPR_ASSERT(contains_metadata(&request_metadata_recv, "key", meta.value));
gpr_free(details);
grpc_metadata_array_destroy(&initial_metadata_recv);
@ -257,8 +251,7 @@ static void test_request_with_large_metadata(grpc_end2end_test_config config,
}
void large_metadata(grpc_end2end_test_config config) {
test_request_with_large_metadata(config, 1);
test_request_with_large_metadata(config, 0);
test_request_with_large_metadata(config);
}
void large_metadata_pre_init(void) {}

Loading…
Cancel
Save