// Test with response larger than the limit. // If send_limit is true, applies send limit on server; otherwise, applies // recv limit on client. static void test_max_message_length_on_response(grpc_end2end_test_config config, bool send_limit, bool use_service_config, bool use_string_json_value) { gpr_log(GPR_INFO, "testing response with send_limit=%d use_service_config=%d " "use_string_json_value=%d", send_limit, use_service_config, use_string_json_value); grpc_end2end_test_fixture f; grpc_call *c = NULL; grpc_call *s = NULL; cq_verifier *cqv; grpc_op ops[6]; grpc_op *op; grpc_slice response_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); grpc_byte_buffer *recv_payload = NULL; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; grpc_channel_args *client_args = NULL; grpc_channel_args *server_args = NULL; if (use_service_config) { // We don't currently support service configs on the server side. GPR_ASSERT(!send_limit); grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVICE_CONFIG; arg.value.string = use_string_json_value ? "{\n" " \"methodConfig\": [ {\n" " \"name\": [\n" " { \"service\": \"service\", \"method\": \"method\" }\n" " ],\n" " \"maxResponseMessageBytes\": \"5\"\n" " } ]\n" "}" : "{\n" " \"methodConfig\": [ {\n" " \"name\": [\n" " { \"service\": \"service\", \"method\": \"method\" }\n" " ],\n" " \"maxResponseMessageBytes\": 5\n" " } ]\n" "}"; client_args = grpc_channel_args_copy_and_add(NULL, &arg, 1); } else { // Set limit via channel args. grpc_arg arg; arg.key = send_limit ? GRPC_ARG_MAX_SEND_MESSAGE_LENGTH : GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH; arg.type = GRPC_ARG_INTEGER; arg.value.integer = 5; grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); if (send_limit) { server_args = args; } else { client_args = args; } } f = begin_test(config, "test_max_response_message_length", client_args, server_args); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; if (client_args != NULL) grpc_channel_args_destroy(&exec_ctx, client_args); if (server_args != NULL) grpc_channel_args_destroy(&exec_ctx, server_args); grpc_exec_ctx_finish(&exec_ctx); } cqv = cq_verifier_create(f.cq); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/service/method"), get_host_override_slice("foo.test.google.fr:1234", config), gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &recv_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); error = 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); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = response_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_OK; grpc_slice status_details = grpc_slice_from_static_string("xyz"); op->data.send_status_from_server.status_details = &status_details; op->flags = 0; op->reserved = NULL; op++; 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), 1); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234")); GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT); GPR_ASSERT( grpc_slice_str_cmp( details, send_limit ? "Sent message larger than max (11 vs. 5)" : "Received message larger than max (11 vs. 5)") == 0); grpc_slice_unref(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_byte_buffer_destroy(response_payload); grpc_byte_buffer_destroy(recv_payload); grpc_call_destroy(c); if (s != NULL) grpc_call_destroy(s); cq_verifier_destroy(cqv); end_test(&f); config.tear_down_data(&f); }
/* Asserts that the log is empty. */ static void assert_log_empty(void) { size_t bytes_available; census_log_init_reader(); GPR_ASSERT(census_log_read_next(&bytes_available) == NULL); }
static void setup_test(int circular_log) { census_log_initialize(LOG_SIZE_IN_MB, circular_log); GPR_ASSERT(census_log_remaining_space() == LOG_SIZE_IN_BYTES); }
static int do_iocp_work() { BOOL success; DWORD bytes = 0; DWORD flags = 0; ULONG_PTR completion_key; LPOVERLAPPED overlapped; gpr_timespec wait_time = gpr_inf_future; grpc_winsocket *socket; grpc_winsocket_callback_info *info; void(*f)(void *, int) = NULL; void *opaque = NULL; success = GetQueuedCompletionStatus(g_iocp, &bytes, &completion_key, &overlapped, gpr_time_to_millis(wait_time)); if (!success && !overlapped) { /* The deadline got attained. */ return 0; } GPR_ASSERT(completion_key && overlapped); if (overlapped == &g_iocp_custom_overlap) { if (completion_key == (ULONG_PTR) &g_iocp_kick_token) { /* We were awoken from a kick. */ gpr_log(GPR_DEBUG, "do_iocp_work - got a kick"); return 1; } gpr_log(GPR_ERROR, "Unknown custom completion key."); abort(); } socket = (grpc_winsocket*) completion_key; if (overlapped == &socket->write_info.overlapped) { gpr_log(GPR_DEBUG, "do_iocp_work - got write packet"); info = &socket->write_info; } else if (overlapped == &socket->read_info.overlapped) { gpr_log(GPR_DEBUG, "do_iocp_work - got read packet"); info = &socket->read_info; } else { gpr_log(GPR_ERROR, "Unknown IOCP operation"); abort(); } success = WSAGetOverlappedResult(socket->socket, &info->overlapped, &bytes, FALSE, &flags); gpr_log(GPR_DEBUG, "bytes: %u, flags: %u - op %s", bytes, flags, success ? "succeeded" : "failed"); info->bytes_transfered = bytes; info->wsa_error = success ? 0 : WSAGetLastError(); GPR_ASSERT(overlapped == &info->overlapped); gpr_mu_lock(&socket->state_mu); GPR_ASSERT(!info->has_pending_iocp); if (info->cb) { f = info->cb; opaque = info->opaque; info->cb = NULL; } else { info->has_pending_iocp = 1; } gpr_mu_unlock(&socket->state_mu); if (f) f(opaque, 1); return 1; }
int main(int argc, char **argv) { grpc_event *ev; call_state *s; char *addr_buf = NULL; gpr_cmdline *cl; int shutdown_started = 0; int shutdown_finished = 0; int secure = 0; char *addr = NULL; char *fake_argv[1]; #define MAX_ARGS 4 grpc_arg arge[MAX_ARGS]; grpc_arg *e; grpc_channel_args args = {0, NULL}; grpc_http_server_page home_page = {"/", "text/html", "<head>\n" "<title>Echo Server</title>\n" "</head>\n" "<body>\n" "Welcome to the world of the future!\n" "</body>\n"}; GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; grpc_test_init(1, fake_argv); grpc_init(); srand(clock()); memset(arge, 0, sizeof(arge)); args.args = arge; cl = gpr_cmdline_create("echo server"); gpr_cmdline_add_string(cl, "bind", "Bind host:port", &addr); gpr_cmdline_add_flag(cl, "secure", "Run with security?", &secure); gpr_cmdline_parse(cl, argc, argv); gpr_cmdline_destroy(cl); e = &arge[args.num_args++]; e->type = GRPC_ARG_POINTER; e->key = GRPC_ARG_SERVE_OVER_HTTP; e->value.pointer.p = &home_page; if (addr == NULL) { gpr_join_host_port(&addr_buf, "::", grpc_pick_unused_port_or_die()); addr = addr_buf; } gpr_log(GPR_INFO, "creating server on: %s", addr); cq = grpc_completion_queue_create(); if (secure) { grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key, test_server1_cert}; grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1); server = grpc_server_create(cq, &args); GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); grpc_server_credentials_release(ssl_creds); } else { server = grpc_server_create(cq, &args); GPR_ASSERT(grpc_server_add_http2_port(server, addr)); } grpc_server_start(server); gpr_free(addr_buf); addr = addr_buf = NULL; request_call(); signal(SIGINT, sigint_handler); while (!shutdown_finished) { if (got_sigint && !shutdown_started) { gpr_log(GPR_INFO, "Shutting down due to SIGINT"); grpc_server_shutdown(server); grpc_completion_queue_shutdown(cq); shutdown_started = 1; } ev = grpc_completion_queue_next( cq, gpr_time_add(gpr_now(), gpr_time_from_seconds(1))); if (!ev) continue; s = ev->tag; switch (ev->type) { case GRPC_SERVER_RPC_NEW: if (ev->call != NULL) { /* initial ops are already started in request_call */ grpc_call_server_accept_old(ev->call, cq, s); grpc_call_server_end_initial_metadata_old(ev->call, GRPC_WRITE_BUFFER_HINT); GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); request_call(); } else { GPR_ASSERT(shutdown_started); gpr_free(s); } break; case GRPC_WRITE_ACCEPTED: GPR_ASSERT(ev->data.write_accepted == GRPC_OP_OK); GPR_ASSERT(grpc_call_start_read_old(ev->call, s) == GRPC_CALL_OK); break; case GRPC_READ: if (ev->data.read) { assert_read_ok(ev->tag, ev->data.read); GPR_ASSERT(grpc_call_start_write_old(ev->call, ev->data.read, s, GRPC_WRITE_BUFFER_HINT) == GRPC_CALL_OK); } else { GPR_ASSERT(grpc_call_start_write_status_old(ev->call, GRPC_STATUS_OK, NULL, s) == GRPC_CALL_OK); } break; case GRPC_FINISH_ACCEPTED: case GRPC_FINISHED: if (gpr_unref(&s->pending_ops)) { grpc_call_destroy(ev->call); gpr_free(s); } break; case GRPC_QUEUE_SHUTDOWN: GPR_ASSERT(shutdown_started); shutdown_finished = 1; break; default: GPR_ASSERT(0); } grpc_event_finish(ev); } grpc_server_destroy(server); grpc_completion_queue_destroy(cq); grpc_shutdown(); return 0; }
static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; int iov_size; ssize_t sent_length; ssize_t sending_length; ssize_t trailing; ssize_t unwind_slice_idx; ssize_t unwind_byte_idx; for (;;) { sending_length = 0; unwind_slice_idx = tcp->outgoing_slice_idx; unwind_byte_idx = tcp->outgoing_byte_idx; for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count && iov_size != MAX_WRITE_IOVEC; iov_size++) { iov[iov_size].iov_base = GPR_SLICE_START_PTR( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) + tcp->outgoing_byte_idx; iov[iov_size].iov_len = GPR_SLICE_LENGTH( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) - tcp->outgoing_byte_idx; sending_length += iov[iov_size].iov_len; tcp->outgoing_slice_idx++; tcp->outgoing_byte_idx = 0; } GPR_ASSERT(iov_size > 0); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = iov_size; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; GRPC_TIMER_BEGIN(GRPC_PTAG_SENDMSG, 0); do { /* TODO(klempner): Cork if this is a partial write */ sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS); } while (sent_length < 0 && errno == EINTR); GRPC_TIMER_END(GRPC_PTAG_SENDMSG, 0); if (sent_length < 0) { if (errno == EAGAIN) { tcp->outgoing_slice_idx = unwind_slice_idx; tcp->outgoing_byte_idx = unwind_byte_idx; return GRPC_ENDPOINT_PENDING; } else { /* TODO(klempner): Log some of these */ return GRPC_ENDPOINT_ERROR; } } GPR_ASSERT(tcp->outgoing_byte_idx == 0); trailing = sending_length - sent_length; while (trailing > 0) { ssize_t slice_length; tcp->outgoing_slice_idx--; slice_length = GPR_SLICE_LENGTH( tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]); if (slice_length > trailing) { tcp->outgoing_byte_idx = slice_length - trailing; break; } else { trailing -= slice_length; } } if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) { return GRPC_ENDPOINT_DONE; } }; }
/* Initiates a write. */ static grpc_endpoint_op_status win_write(grpc_endpoint *ep, gpr_slice_buffer *slices, grpc_iomgr_closure *cb) { grpc_tcp *tcp = (grpc_tcp *)ep; grpc_winsocket *socket = tcp->socket; grpc_winsocket_callback_info *info = &socket->write_info; unsigned i; DWORD bytes_sent; int status; WSABUF local_buffers[16]; WSABUF *allocated = NULL; WSABUF *buffers = local_buffers; GPR_ASSERT(!tcp->socket->write_info.outstanding); if (tcp->shutting_down) { return GRPC_ENDPOINT_ERROR; } TCP_REF(tcp, "write"); tcp->socket->write_info.outstanding = 1; tcp->write_cb = cb; tcp->write_slices = slices; if (tcp->write_slices->count > GPR_ARRAY_SIZE(local_buffers)) { buffers = (WSABUF *)gpr_malloc(sizeof(WSABUF) * tcp->write_slices->count); allocated = buffers; } for (i = 0; i < tcp->write_slices->count; i++) { buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices->slices[i]); buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices->slices[i]); } /* First, let's try a synchronous, non-blocking write. */ status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, NULL, NULL); info->wsa_error = status == 0 ? 0 : WSAGetLastError(); /* We would kind of expect to get a WSAEWOULDBLOCK here, especially on a busy connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { grpc_endpoint_op_status ret = GRPC_ENDPOINT_ERROR; if (status == 0) { ret = GRPC_ENDPOINT_DONE; GPR_ASSERT(bytes_sent == tcp->write_slices->length); } else { if (socket->read_info.wsa_error != WSAECONNRESET) { char *utf8_message = gpr_format_message(info->wsa_error); gpr_log(GPR_ERROR, "WSASend error: %s", utf8_message); gpr_free(utf8_message); } } if (allocated) gpr_free(allocated); tcp->socket->write_info.outstanding = 0; TCP_UNREF(tcp, "write"); return ret; } /* If we got a WSAEWOULDBLOCK earlier, then we need to re-do the same operation, this time asynchronously. */ memset(&socket->write_info.overlapped, 0, sizeof(OVERLAPPED)); status = WSASend(socket->socket, buffers, tcp->write_slices->count, &bytes_sent, 0, &socket->write_info.overlapped, NULL); if (allocated) gpr_free(allocated); if (status != 0) { int wsa_error = WSAGetLastError(); if (wsa_error != WSA_IO_PENDING) { tcp->socket->write_info.outstanding = 0; TCP_UNREF(tcp, "write"); return GRPC_ENDPOINT_ERROR; } } /* As all is now setup, we can now ask for the IOCP notification. It may trigger the callback immediately however, but no matter. */ grpc_socket_notify_on_write(socket, on_write, tcp); return GRPC_ENDPOINT_PENDING; }
int grpc_pick_unused_port_or_die(void) { int port = grpc_pick_unused_port(); GPR_ASSERT(port > 0); return port; }
void grpc_recycle_unused_port(int port) { GPR_ASSERT(free_chosen_port(port)); }
/* Cancel after accept, no payload */ static void test_cancel_after_accept(grpc_end2end_test_config config, cancellation_mode mode, bool use_service_config) { grpc_op ops[6]; grpc_op *op; grpc_call *c; grpc_call *s; gpr_timespec deadline = use_service_config ? gpr_inf_future(GPR_CLOCK_MONOTONIC) : five_seconds_time(); grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; grpc_byte_buffer *request_payload_recv = NULL; grpc_byte_buffer *response_payload_recv = NULL; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_slice response_payload_slice = grpc_slice_from_copied_string("hello you"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); grpc_byte_buffer *response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); int was_cancelled = 2; grpc_channel_args *args = NULL; if (use_service_config) { grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVICE_CONFIG; arg.value.string = "{\n" " \"methodConfig\": [ {\n" " \"name\": [\n" " { \"service\": \"service\", \"method\": \"method\" }\n" " ],\n" " \"timeout\": \"5s\"\n" " } ]\n" "}"; args = grpc_channel_args_copy_and_add(args, &arg, 1); } grpc_end2end_test_fixture f = begin_test(config, "cancel_after_accept", args, NULL); cq_verifier *cqv = cq_verifier_create(f.cq); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/service/method", get_host_override_string("foo.test.google.fr:1234", config), deadline, NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message = &response_payload_recv; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); error = grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.cq, f.cq, tag(2)); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), 1); cq_verify(cqv); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message = &request_payload_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = response_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(3), NULL); GPR_ASSERT(GRPC_CALL_OK == error); GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, NULL)); CQ_EXPECT_COMPLETION(cqv, tag(3), 1); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == mode.expect_status || status == GRPC_STATUS_INTERNAL); GPR_ASSERT(was_cancelled == 1); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(response_payload); grpc_byte_buffer_destroy(request_payload_recv); grpc_byte_buffer_destroy(response_payload_recv); gpr_free(details); grpc_call_destroy(c); grpc_call_destroy(s); if (args != NULL) grpc_channel_args_destroy(args); cq_verifier_destroy(cqv); end_test(&f); config.tear_down_data(&f); }
int grpc_pick_unused_port(void) { /* We repeatedly pick a port and then see whether or not it is available for use both as a TCP socket and a UDP socket. First, we pick a random large port number. For subsequent iterations, we bind to an anonymous port and let the OS pick the port number. The random port picking reduces the probability of races with other processes on kernels that want to reuse the same port numbers over and over. */ /* In alternating iterations we trial UDP ports before TCP ports UDP ports -- it could be the case that this machine has been using up UDP ports and they are scarcer. */ /* Type of port to first pick in next iteration */ int is_tcp = 1; int trial = 0; char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); if (env) { int port = grpc_pick_port_using_server(env); gpr_free(env); if (port != 0) { return port; } } for (;;) { int port; trial++; if (trial == 1) { port = _getpid() % (65536 - 30000) + 30000; } else if (trial <= NUM_RANDOM_PORTS_TO_PICK) { port = rand() % (65536 - 30000) + 30000; } else { port = 0; } if (has_port_been_chosen(port)) { continue; } if (!is_port_available(&port, is_tcp)) { continue; } GPR_ASSERT(port > 0); /* Check that the port # is free for the other type of socket also */ if (!is_port_available(&port, !is_tcp)) { /* In the next iteration trial to bind to the other type first because perhaps it is more rare. */ is_tcp = !is_tcp; continue; } /* TODO(ctiller): consider caching this port in some structure, to avoid handing it out again */ chose_port(port); return port; } /* The port iterator reached the end without finding a suitable port. */ return 0; }
static grpc_endpoint_write_status endpoint_write(grpc_endpoint *secure_ep, gpr_slice *slices, size_t nslices, grpc_endpoint_write_cb cb, void *user_data) { unsigned i; size_t output_buffer_count = 0; tsi_result result = TSI_OK; secure_endpoint *ep = (secure_endpoint *)secure_ep; gpr_uint8 *cur = GPR_SLICE_START_PTR(ep->write_staging_buffer); gpr_uint8 *end = GPR_SLICE_END_PTR(ep->write_staging_buffer); grpc_endpoint_write_status status; GPR_ASSERT(ep->output_buffer.count == 0); if (grpc_trace_secure_endpoint) { for (i = 0; i < nslices; i++) { char *data = gpr_dump_slice(slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data); gpr_free(data); } } for (i = 0; i < nslices; i++) { gpr_slice plain = slices[i]; gpr_uint8 *message_bytes = GPR_SLICE_START_PTR(plain); size_t message_size = GPR_SLICE_LENGTH(plain); while (message_size > 0) { size_t protected_buffer_size_to_send = (size_t)(end - cur); size_t processed_message_size = message_size; gpr_mu_lock(&ep->protector_mu); result = tsi_frame_protector_protect(ep->protector, message_bytes, &processed_message_size, cur, &protected_buffer_size_to_send); gpr_mu_unlock(&ep->protector_mu); if (result != TSI_OK) { gpr_log(GPR_ERROR, "Encryption error: %s", tsi_result_to_string(result)); break; } message_bytes += processed_message_size; message_size -= processed_message_size; cur += protected_buffer_size_to_send; if (cur == end) { flush_write_staging_buffer(ep, &cur, &end); } } if (result != TSI_OK) break; } if (result == TSI_OK) { size_t still_pending_size; do { size_t protected_buffer_size_to_send = (size_t)(end - cur); gpr_mu_lock(&ep->protector_mu); result = tsi_frame_protector_protect_flush(ep->protector, cur, &protected_buffer_size_to_send, &still_pending_size); gpr_mu_unlock(&ep->protector_mu); if (result != TSI_OK) break; cur += protected_buffer_size_to_send; if (cur == end) { flush_write_staging_buffer(ep, &cur, &end); } } while (still_pending_size > 0); if (cur != GPR_SLICE_START_PTR(ep->write_staging_buffer)) { gpr_slice_buffer_add( &ep->output_buffer, gpr_slice_split_head( &ep->write_staging_buffer, (size_t)(cur - GPR_SLICE_START_PTR(ep->write_staging_buffer)))); } } for (i = 0; i < nslices; i++) { gpr_slice_unref(slices[i]); } if (result != TSI_OK) { /* TODO(yangg) do different things according to the error type? */ gpr_slice_buffer_reset_and_unref(&ep->output_buffer); return GRPC_ENDPOINT_WRITE_ERROR; } /* clear output_buffer and let the lower level handle its slices. */ output_buffer_count = ep->output_buffer.count; ep->output_buffer.count = 0; ep->write_cb = cb; ep->write_user_data = user_data; /* Need to keep the endpoint alive across a transport */ secure_endpoint_ref(ep); status = grpc_endpoint_write(ep->wrapped_ep, ep->output_buffer.slices, output_buffer_count, on_write, ep); if (status != GRPC_ENDPOINT_WRITE_PENDING) { secure_endpoint_unref(ep); } return status; }
static void shrink_test(void) { gpr_log(GPR_INFO, "shrink_test"); grpc_timer_heap pq; size_t i; size_t expected_size; /* A large random number to allow for multiple shrinkages, at least 512. */ const size_t num_elements = (size_t)rand() % 2000 + 512; grpc_timer_heap_init(&pq); /* Create a priority queue with many elements. Make sure the Size() is correct. */ for (i = 0; i < num_elements; ++i) { GPR_ASSERT(i == pq.timer_count); grpc_timer_heap_add(&pq, create_test_elements(1)); } GPR_ASSERT(num_elements == pq.timer_count); /* Remove elements until the Size is 1/4 the original size. */ while (pq.timer_count > num_elements / 4) { grpc_timer *const te = pq.timers[pq.timer_count - 1]; grpc_timer_heap_remove(&pq, te); gpr_free(te); } GPR_ASSERT(num_elements / 4 == pq.timer_count); /* Expect that Capacity is in the right range: Size * 2 <= Capacity <= Size * 4 */ GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); check_valid(&pq); /* Remove the rest of the elements. Check that the Capacity is not more than 4 times the Size and not less than 2 times, but never goes below 16. */ expected_size = pq.timer_count; while (pq.timer_count > 0) { const size_t which = (size_t)rand() % pq.timer_count; grpc_timer *te = pq.timers[which]; grpc_timer_heap_remove(&pq, te); gpr_free(te); expected_size--; GPR_ASSERT(expected_size == pq.timer_count); GPR_ASSERT(pq.timer_count * 2 <= pq.timer_capacity); if (pq.timer_count >= 8) { GPR_ASSERT(pq.timer_capacity <= pq.timer_count * 4); } else { GPR_ASSERT(16 <= pq.timer_capacity); } check_valid(&pq); } GPR_ASSERT(0 == pq.timer_count); GPR_ASSERT(pq.timer_capacity >= 16 && pq.timer_capacity < 32); grpc_timer_heap_destroy(&pq); }
static void test2(void) { gpr_log(GPR_INFO, "test2"); grpc_timer_heap pq; static const size_t elems_size = 1000; elem_struct *elems = gpr_malloc(elems_size * sizeof(elem_struct)); size_t num_inserted = 0; grpc_timer_heap_init(&pq); memset(elems, 0, elems_size); for (size_t round = 0; round < 10000; round++) { int r = rand() % 1000; if (r <= 550) { /* 55% of the time we try to add something */ elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), false); if (el != NULL) { el->elem.deadline = random_deadline(); grpc_timer_heap_add(&pq, &el->elem); el->inserted = true; num_inserted++; check_valid(&pq); } } else if (r <= 650) { /* 10% of the time we try to remove something */ elem_struct *el = search_elems(elems, GPR_ARRAY_SIZE(elems), true); if (el != NULL) { grpc_timer_heap_remove(&pq, &el->elem); el->inserted = false; num_inserted--; check_valid(&pq); } } else { /* the remaining times we pop */ if (num_inserted > 0) { grpc_timer *top = grpc_timer_heap_top(&pq); grpc_timer_heap_pop(&pq); for (size_t i = 0; i < elems_size; i++) { if (top == &elems[i].elem) { GPR_ASSERT(elems[i].inserted); elems[i].inserted = false; } } num_inserted--; check_valid(&pq); } } if (num_inserted) { gpr_timespec *min_deadline = NULL; for (size_t i = 0; i < elems_size; i++) { if (elems[i].inserted) { if (min_deadline == NULL) { min_deadline = &elems[i].elem.deadline; } else { if (gpr_time_cmp(elems[i].elem.deadline, *min_deadline) < 0) { min_deadline = &elems[i].elem.deadline; } } } } GPR_ASSERT( 0 == gpr_time_cmp(grpc_timer_heap_top(&pq)->deadline, *min_deadline)); } } grpc_timer_heap_destroy(&pq); gpr_free(elems); }
static void test_early_server_shutdown_finishes_inflight_calls( grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; gpr_timespec deadline = five_seconds_time(); grpc_end2end_test_fixture f = begin_test(config, "test_early_server_shutdown_finishes_inflight_calls", NULL, NULL); cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->data.send_initial_metadata.metadata = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.server_cq, f.server_cq, tag(101))); cq_expect_completion(v_server, tag(101), 1); cq_verify(v_server); /* shutdown and destroy the server */ grpc_server_shutdown_and_notify(f.server, tag(0xdead)); cq_verify_empty(v_server); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102))); cq_expect_completion(v_server, tag(102), 1); cq_verify(v_server); grpc_call_destroy(s); cq_expect_completion(v_server, tag(0xdead), 1); cq_verify(v_server); cq_expect_completion(v_client, tag(1), 1); cq_verify(v_client); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 0); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); cq_verifier_destroy(v_client); cq_verifier_destroy(v_server); end_test(&f); config.tear_down_data(&f); }
static void do_request_and_shutdown_server(grpc_end2end_test_fixture *f, cq_verifier *v_client, cq_verifier *v_server) { grpc_call *c; grpc_call *s; gpr_timespec deadline = five_seconds_time(); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; c = grpc_channel_create_call(f->client, f->client_cq, "/foo", "foo.test.google.fr:1234", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op->flags = 0; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f->server, &s, &call_details, &request_metadata_recv, f->server_cq, f->server_cq, tag(101))); cq_expect_completion(v_server, tag(101), 1); cq_verify(v_server); /* should be able to shut down the server early - and still complete the request */ grpc_server_shutdown(f->server); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op->flags = 0; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102))); cq_expect_completion(v_server, tag(102), 1); cq_verify(v_server); cq_expect_completion(v_client, tag(1), 1); cq_verify(v_client); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); 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:1234")); GPR_ASSERT(was_cancelled == 0); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); grpc_call_destroy(s); }
static void tcp_continue_read(grpc_tcp *tcp) { struct msghdr msg; struct iovec iov[MAX_READ_IOVEC]; ssize_t read_bytes; size_t i; GPR_ASSERT(!tcp->finished_edge); GPR_ASSERT(tcp->iov_size <= MAX_READ_IOVEC); GPR_ASSERT(tcp->incoming_buffer->count <= MAX_READ_IOVEC); GRPC_TIMER_BEGIN(GRPC_PTAG_HANDLE_READ, 0); while (tcp->incoming_buffer->count < (size_t)tcp->iov_size) { gpr_slice_buffer_add_indexed(tcp->incoming_buffer, gpr_slice_malloc(tcp->slice_size)); } for (i = 0; i < tcp->incoming_buffer->count; i++) { iov[i].iov_base = GPR_SLICE_START_PTR(tcp->incoming_buffer->slices[i]); iov[i].iov_len = GPR_SLICE_LENGTH(tcp->incoming_buffer->slices[i]); } msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = tcp->iov_size; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; GRPC_TIMER_BEGIN(GRPC_PTAG_RECVMSG, 0); do { read_bytes = recvmsg(tcp->fd, &msg, 0); } while (read_bytes < 0 && errno == EINTR); GRPC_TIMER_END(GRPC_PTAG_RECVMSG, 0); if (read_bytes < 0) { /* NB: After calling call_read_cb a parallel call of the read handler may * be running. */ if (errno == EAGAIN) { if (tcp->iov_size > 1) { tcp->iov_size /= 2; } /* We've consumed the edge, request a new one */ grpc_fd_notify_on_read(tcp->em_fd, &tcp->read_closure); } else { /* TODO(klempner): Log interesting errors */ gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); call_read_cb(tcp, 0); TCP_UNREF(tcp, "read"); } } else if (read_bytes == 0) { /* 0 read size ==> end of stream */ gpr_slice_buffer_reset_and_unref(tcp->incoming_buffer); call_read_cb(tcp, 0); TCP_UNREF(tcp, "read"); } else { GPR_ASSERT((size_t)read_bytes <= tcp->incoming_buffer->length); if ((size_t)read_bytes < tcp->incoming_buffer->length) { gpr_slice_buffer_trim_end(tcp->incoming_buffer, tcp->incoming_buffer->length - read_bytes); } else if (tcp->iov_size < MAX_READ_IOVEC) { ++tcp->iov_size; } GPR_ASSERT((size_t)read_bytes == tcp->incoming_buffer->length); call_read_cb(tcp, 1); TCP_UNREF(tcp, "read"); } GRPC_TIMER_END(GRPC_PTAG_HANDLE_READ, 0); }
static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp, grpc_mdelem *md) { grpc_chttp2_transport *t = tp; grpc_chttp2_stream *s = t->incoming_stream; GPR_TIMER_BEGIN("on_initial_header", 0); GPR_ASSERT(s != NULL); GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_INFO, "HTTP:%d:HDR:%s: %s: %s", s->id, t->is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->key), grpc_mdstr_as_c_string(md->value))); if (md->key == GRPC_MDSTR_GRPC_STATUS && md != GRPC_MDELEM_GRPC_STATUS_0) { /* TODO(ctiller): check for a status like " 0" */ s->seen_error = true; } if (md->key == GRPC_MDSTR_GRPC_TIMEOUT) { gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout); if (!cached_timeout) { /* not already parsed: parse it now, and store the result away */ cached_timeout = gpr_malloc(sizeof(gpr_timespec)); if (!grpc_http2_decode_timeout(grpc_mdstr_as_c_string(md->value), cached_timeout)) { gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", grpc_mdstr_as_c_string(md->value)); *cached_timeout = gpr_inf_future(GPR_TIMESPAN); } cached_timeout = grpc_mdelem_set_user_data(md, free_timeout, cached_timeout); } grpc_chttp2_incoming_metadata_buffer_set_deadline( &s->metadata_buffer[0], gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), *cached_timeout)); GRPC_MDELEM_UNREF(md); } else { const size_t new_size = s->metadata_buffer[0].size + GRPC_MDELEM_LENGTH(md); const size_t metadata_size_limit = t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE]; if (new_size > metadata_size_limit) { gpr_log(GPR_DEBUG, "received initial metadata size exceeds limit (%" PRIuPTR " vs. %" PRIuPTR ")", new_size, metadata_size_limit); grpc_chttp2_cancel_stream( exec_ctx, t, s, grpc_error_set_int( GRPC_ERROR_CREATE("received initial metadata size exceeds limit"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED)); grpc_chttp2_parsing_become_skip_parser(exec_ctx, t); s->seen_error = true; GRPC_MDELEM_UNREF(md); } else { grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); } } GPR_TIMER_END("on_initial_header", 0); }
/* Create a secure client channel: Asynchronously: - resolve target - connect to it (trying alternatives as presented) - perform handshakes */ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds, const char *target, const grpc_channel_args *args, void *reserved) { grpc_arg connector_arg; grpc_channel_args *args_copy; grpc_channel_args *new_args_from_connector; grpc_channel_security_connector *security_connector; client_channel_factory *f; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE( "grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "reserved=%p)", 4, (creds, target, args, reserved)); GPR_ASSERT(reserved == NULL); if (grpc_find_security_connector_in_args(args) != NULL) { gpr_log(GPR_ERROR, "Cannot set security context in channel args."); grpc_exec_ctx_finish(&exec_ctx); return grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Security connector exists in channel args."); } if (grpc_channel_credentials_create_security_connector( creds, target, args, &security_connector, &new_args_from_connector) != GRPC_SECURITY_OK) { grpc_exec_ctx_finish(&exec_ctx); return grpc_lame_client_channel_create( target, GRPC_STATUS_INTERNAL, "Failed to create security connector."); } connector_arg = grpc_security_connector_to_arg(&security_connector->base); args_copy = grpc_channel_args_copy_and_add( new_args_from_connector != NULL ? new_args_from_connector : args, &connector_arg, 1); f = gpr_malloc(sizeof(*f)); memset(f, 0, sizeof(*f)); f->base.vtable = &client_channel_factory_vtable; gpr_ref_init(&f->refs, 1); f->merge_args = grpc_channel_args_copy(args_copy); grpc_channel_args_destroy(args_copy); if (new_args_from_connector != NULL) { grpc_channel_args_destroy(new_args_from_connector); } GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "grpc_secure_channel_create"); f->security_connector = security_connector; grpc_channel *channel = client_channel_factory_create_channel( &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); if (channel != NULL) { f->master = channel; GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create"); } grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_exec_ctx_finish(&exec_ctx); return channel; /* may be NULL */ }
static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, int is_continuation) { uint8_t is_eoh = (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0; grpc_chttp2_stream *s; /* TODO(ctiller): when to increment header_frames_received? */ if (is_eoh) { t->expect_continuation_stream_id = 0; } else { t->expect_continuation_stream_id = t->incoming_stream_id; } if (!is_continuation) { t->header_eof = (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0; } /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */ s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); if (s == NULL) { if (is_continuation) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream disbanded before CONTINUATION received")); return init_skip_frame_parser(exec_ctx, t, 1); } if (t->is_client) { if ((t->incoming_stream_id & 1) && t->incoming_stream_id < t->next_stream_id) { /* this is an old (probably cancelled) grpc_chttp2_stream */ } else { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client")); } return init_skip_frame_parser(exec_ctx, t, 1); } else if (t->last_new_stream_id >= t->incoming_stream_id) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring out of order new grpc_chttp2_stream request on server; " "last grpc_chttp2_stream " "id=%d, new grpc_chttp2_stream id=%d", t->last_new_stream_id, t->incoming_stream_id)); return init_skip_frame_parser(exec_ctx, t, 1); } else if ((t->incoming_stream_id & 1) == 0) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring grpc_chttp2_stream with non-client generated index %d", t->incoming_stream_id)); return init_skip_frame_parser(exec_ctx, t, 1); } t->last_new_stream_id = t->incoming_stream_id; s = t->incoming_stream = grpc_chttp2_parsing_accept_stream(exec_ctx, t, t->incoming_stream_id); if (s == NULL) { GRPC_CHTTP2_IF_TRACING( gpr_log(GPR_ERROR, "grpc_chttp2_stream not accepted")); return init_skip_frame_parser(exec_ctx, t, 1); } } else { t->incoming_stream = s; } GPR_ASSERT(s != NULL); s->stats.incoming.framing_bytes += 9; if (s->read_closed) { GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "skipping already closed grpc_chttp2_stream header")); t->incoming_stream = NULL; return init_skip_frame_parser(exec_ctx, t, 1); } t->parser = grpc_chttp2_header_parser_parse; t->parser_data = &t->hpack_parser; switch (s->header_frames_received) { case 0: t->hpack_parser.on_header = on_initial_header; break; case 1: t->hpack_parser.on_header = on_trailing_header; break; case 2: gpr_log(GPR_ERROR, "too many header frames received"); return init_skip_frame_parser(exec_ctx, t, 1); } t->hpack_parser.on_header_user_data = t; t->hpack_parser.is_boundary = is_eoh; t->hpack_parser.is_eof = (uint8_t)(is_eoh ? t->header_eof : 0); if (!is_continuation && (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY)) { grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser); } return GRPC_ERROR_NONE; }
static void test_threading(int producers, int consumers) { test_thread_options *options = gpr_malloc((producers + consumers) * sizeof(test_thread_options)); gpr_event phase1 = GPR_EVENT_INIT; gpr_event phase2 = GPR_EVENT_INIT; grpc_completion_queue *cc = grpc_completion_queue_create(); int i; int total_consumed = 0; static int optid = 101; gpr_log(GPR_INFO, "%s: %d producers, %d consumers", "test_threading", producers, consumers); /* start all threads: they will wait for phase1 */ for (i = 0; i < producers + consumers; i++) { gpr_thd_id id; gpr_event_init(&options[i].on_started); gpr_event_init(&options[i].on_phase1_done); gpr_event_init(&options[i].on_finished); options[i].phase1 = &phase1; options[i].phase2 = &phase2; options[i].events_triggered = 0; options[i].cc = cc; options[i].id = optid++; GPR_ASSERT(gpr_thd_new(&id, i < producers ? producer_thread : consumer_thread, options + i, NULL)); gpr_event_wait(&options[i].on_started, ten_seconds_time()); } /* start phase1: producers will pre-declare all operations they will complete */ gpr_log(GPR_INFO, "start phase 1"); gpr_event_set(&phase1, (void *)(gpr_intptr)1); gpr_log(GPR_INFO, "wait phase 1"); for (i = 0; i < producers + consumers; i++) { GPR_ASSERT(gpr_event_wait(&options[i].on_phase1_done, ten_seconds_time())); } gpr_log(GPR_INFO, "done phase 1"); /* start phase2: operations will complete, and consumers will consume them */ gpr_log(GPR_INFO, "start phase 2"); gpr_event_set(&phase2, (void *)(gpr_intptr)1); /* in parallel, we shutdown the completion channel - all events should still be consumed */ grpc_completion_queue_shutdown(cc); /* join all threads */ gpr_log(GPR_INFO, "wait phase 2"); for (i = 0; i < producers + consumers; i++) { GPR_ASSERT(gpr_event_wait(&options[i].on_finished, ten_seconds_time())); } gpr_log(GPR_INFO, "done phase 2"); /* destroy the completion channel */ grpc_completion_queue_destroy(cc); /* verify that everything was produced and consumed */ for (i = 0; i < producers + consumers; i++) { if (i < producers) { GPR_ASSERT(options[i].events_triggered == TEST_THREAD_EVENTS); } else { total_consumed += options[i].events_triggered; } } GPR_ASSERT(total_consumed == producers * TEST_THREAD_EVENTS); gpr_free(options); }
grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_slice slice) { uint8_t *beg = GRPC_SLICE_START_PTR(slice); uint8_t *end = GRPC_SLICE_END_PTR(slice); uint8_t *cur = beg; grpc_error *err; if (cur == end) return GRPC_ERROR_NONE; switch (t->deframe_state) { case GRPC_DTS_CLIENT_PREFIX_0: case GRPC_DTS_CLIENT_PREFIX_1: case GRPC_DTS_CLIENT_PREFIX_2: case GRPC_DTS_CLIENT_PREFIX_3: case GRPC_DTS_CLIENT_PREFIX_4: case GRPC_DTS_CLIENT_PREFIX_5: case GRPC_DTS_CLIENT_PREFIX_6: case GRPC_DTS_CLIENT_PREFIX_7: case GRPC_DTS_CLIENT_PREFIX_8: case GRPC_DTS_CLIENT_PREFIX_9: case GRPC_DTS_CLIENT_PREFIX_10: case GRPC_DTS_CLIENT_PREFIX_11: case GRPC_DTS_CLIENT_PREFIX_12: case GRPC_DTS_CLIENT_PREFIX_13: case GRPC_DTS_CLIENT_PREFIX_14: case GRPC_DTS_CLIENT_PREFIX_15: case GRPC_DTS_CLIENT_PREFIX_16: case GRPC_DTS_CLIENT_PREFIX_17: case GRPC_DTS_CLIENT_PREFIX_18: case GRPC_DTS_CLIENT_PREFIX_19: case GRPC_DTS_CLIENT_PREFIX_20: case GRPC_DTS_CLIENT_PREFIX_21: case GRPC_DTS_CLIENT_PREFIX_22: case GRPC_DTS_CLIENT_PREFIX_23: while (cur != end && t->deframe_state != GRPC_DTS_FH_0) { if (*cur != GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state]) { char *msg; gpr_asprintf( &msg, "Connect string mismatch: expected '%c' (%d) got '%c' (%d) " "at byte %d", GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state], (int)(uint8_t)GRPC_CHTTP2_CLIENT_CONNECT_STRING[t->deframe_state], *cur, (int)*cur, t->deframe_state); err = GRPC_ERROR_CREATE(msg); gpr_free(msg); return err; } ++cur; ++t->deframe_state; } if (cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ dts_fh_0: case GRPC_DTS_FH_0: GPR_ASSERT(cur < end); t->incoming_frame_size = ((uint32_t)*cur) << 16; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_1; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_1: GPR_ASSERT(cur < end); t->incoming_frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_2; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_2: GPR_ASSERT(cur < end); t->incoming_frame_size |= *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_3; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_3: GPR_ASSERT(cur < end); t->incoming_frame_type = *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_4; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_4: GPR_ASSERT(cur < end); t->incoming_frame_flags = *cur; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_5; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_5: GPR_ASSERT(cur < end); t->incoming_stream_id = (((uint32_t)*cur) & 0x7f) << 24; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_6; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_6: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur) << 16; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_7; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_7: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur) << 8; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_8; return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FH_8: GPR_ASSERT(cur < end); t->incoming_stream_id |= ((uint32_t)*cur); t->deframe_state = GRPC_DTS_FRAME; err = init_frame_parser(exec_ctx, t); if (err != GRPC_ERROR_NONE) { return err; } if (t->incoming_frame_size == 0) { err = parse_frame_slice(exec_ctx, t, gpr_empty_slice(), 1); if (err != GRPC_ERROR_NONE) { return err; } t->incoming_stream = NULL; if (++cur == end) { t->deframe_state = GRPC_DTS_FH_0; return GRPC_ERROR_NONE; } goto dts_fh_0; /* loop */ } else if (t->incoming_frame_size > t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]) { char *msg; gpr_asprintf(&msg, "Frame size %d is larger than max frame size %d", t->incoming_frame_size, t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE]); err = GRPC_ERROR_CREATE(msg); gpr_free(msg); return err; } if (++cur == end) { return GRPC_ERROR_NONE; } /* fallthrough */ case GRPC_DTS_FRAME: GPR_ASSERT(cur < end); if ((uint32_t)(end - cur) == t->incoming_frame_size) { err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 1); if (err != GRPC_ERROR_NONE) { return err; } t->deframe_state = GRPC_DTS_FH_0; t->incoming_stream = NULL; return GRPC_ERROR_NONE; } else if ((uint32_t)(end - cur) > t->incoming_frame_size) { size_t cur_offset = (size_t)(cur - beg); err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, cur_offset, cur_offset + t->incoming_frame_size), 1); if (err != GRPC_ERROR_NONE) { return err; } cur += t->incoming_frame_size; t->incoming_stream = NULL; goto dts_fh_0; /* loop */ } else { err = parse_frame_slice( exec_ctx, t, grpc_slice_sub_no_ref(slice, (size_t)(cur - beg), (size_t)(end - beg)), 0); if (err != GRPC_ERROR_NONE) { return err; } t->incoming_frame_size -= (uint32_t)(end - cur); return GRPC_ERROR_NONE; } GPR_UNREACHABLE_CODE(return 0); } GPR_UNREACHABLE_CODE(return 0); }
static void simple_request_body(grpc_end2end_test_fixture f) { grpc_call *c; grpc_call *s; gpr_timespec deadline = five_seconds_time(); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; c = grpc_channel_create_call(f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", "foo.test.google.fr:1234", deadline, NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); error = 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); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op->reserved = NULL; op++; 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), 1); cq_expect_completion(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); 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:1234")); GPR_ASSERT(was_cancelled == 1); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); grpc_call_destroy(s); cq_verifier_destroy(cqv); }
static void request_response_with_payload(grpc_end2end_test_fixture f) { gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); gpr_slice response_payload_slice = gpr_slice_from_copied_string("hello you"); grpc_call *c; grpc_call *s; grpc_byte_buffer *request_payload = grpc_byte_buffer_create(&request_payload_slice, 1); grpc_byte_buffer *response_payload = grpc_byte_buffer_create(&response_payload_slice, 1); gpr_timespec deadline = five_seconds_time(); cq_verifier *v_client = cq_verifier_create(f.client_cq); cq_verifier *v_server = cq_verifier_create(f.server_cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_byte_buffer *request_payload_recv = NULL; grpc_byte_buffer *response_payload_recv = NULL; grpc_call_details call_details; grpc_status_code status; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "foo.test.google.fr", deadline); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = request_payload; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message = &response_payload_recv; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.server_cq, tag(101))); cq_expect_completion(v_server, tag(101), GRPC_OP_OK); cq_verify(v_server); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = response_payload; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op++; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message = &request_payload_recv; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102))); cq_expect_completion(v_server, tag(102), GRPC_OP_OK); cq_verify(v_server); cq_expect_completion(v_client, tag(1), GRPC_OP_OK); cq_verify(v_client); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); 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); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you")); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); grpc_call_destroy(s); cq_verifier_destroy(v_client); cq_verifier_destroy(v_server); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(response_payload); grpc_byte_buffer_destroy(request_payload_recv); grpc_byte_buffer_destroy(response_payload_recv); }
static void simple_request_body(grpc_end2end_test_config config, grpc_end2end_test_fixture f, size_t index) { grpc_call *c; grpc_call *s; gpr_timespec deadline = five_seconds_time(); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_metadata extra_metadata[3]; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; memset(extra_metadata, 0, sizeof(extra_metadata)); extra_metadata[0].key = "hobbit-first-name"; extra_metadata[0].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][0]; extra_metadata[0].value_length = strlen(extra_metadata[0].value); extra_metadata[1].key = "hobbit-second-name"; extra_metadata[1].value = hobbits[index % GPR_ARRAY_SIZE(hobbits)][1]; extra_metadata[1].value_length = strlen(extra_metadata[1].value); extra_metadata[2].key = "dragon"; extra_metadata[2].value = dragons[index % GPR_ARRAY_SIZE(dragons)]; extra_metadata[2].value_length = strlen(extra_metadata[2].value); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, "/foo", get_host_override_string("foo.test.google.fr:1234", config), deadline, NULL); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = GPR_ARRAY_SIZE(extra_metadata); op->data.send_initial_metadata.metadata = extra_metadata; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); error = 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); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; op->data.send_status_from_server.status_details = "xyz"; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op->flags = 0; op->reserved = NULL; op++; 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), 1); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == strcmp(details, "xyz")); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); GPR_ASSERT(was_cancelled == 1); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_call_destroy(c); grpc_call_destroy(s); cq_verifier_destroy(cqv); }
static void must_succeed(void *arg, grpc_endpoint *tcp) { GPR_ASSERT(tcp); grpc_endpoint_shutdown(tcp); grpc_endpoint_destroy(tcp); gpr_event_set(arg, (void *)1); }
static void multiple_writers_single_reader(int circular_log) { /* Sleep interval between read iterations. */ static const gpr_int32 READ_ITERATION_INTERVAL_IN_MSEC = 10; /* Number of records written by each writer. */ static const gpr_int32 NUM_RECORDS_PER_WRITER = 10 * 1024 * 1024; /* Maximum record size. */ static const size_t MAX_RECORD_SIZE = 10; int ix; gpr_thd_id id; gpr_cv writers_done; int writers_count = NUM_WRITERS; gpr_mu writers_mu; /* protects writers_done and writers_count */ writer_thread_args writers[NUM_WRITERS]; gpr_cv reader_done; gpr_mu reader_mu; /* protects reader_done and reader.running */ reader_thread_args reader; gpr_int32 record_size = 1 + rand() % MAX_RECORD_SIZE; printf(" Record size: %d\n", record_size); /* Create and start writers. */ gpr_cv_init(&writers_done); gpr_mu_init(&writers_mu); for (ix = 0; ix < NUM_WRITERS; ++ix) { writers[ix].index = ix; writers[ix].record_size = record_size; writers[ix].num_records = NUM_RECORDS_PER_WRITER; writers[ix].done = &writers_done; writers[ix].count = &writers_count; writers[ix].mu = &writers_mu; gpr_thd_new(&id, &writer_thread, &writers[ix], NULL); } /* Start reader. */ reader.record_size = record_size; reader.read_iteration_interval_in_msec = READ_ITERATION_INTERVAL_IN_MSEC; reader.total_records = NUM_WRITERS * NUM_RECORDS_PER_WRITER; reader.stop_flag = 0; gpr_cv_init(&reader.stop); gpr_cv_init(&reader_done); reader.done = &reader_done; gpr_mu_init(&reader_mu); reader.mu = &reader_mu; reader.running = 1; gpr_thd_new(&id, &reader_thread, &reader, NULL); /* Wait for writers to finish. */ gpr_mu_lock(&writers_mu); while (writers_count != 0) { gpr_cv_wait(&writers_done, &writers_mu, gpr_inf_future); } gpr_mu_unlock(&writers_mu); gpr_mu_destroy(&writers_mu); gpr_cv_destroy(&writers_done); gpr_mu_lock(&reader_mu); if (circular_log) { /* Stop reader. */ reader.stop_flag = 1; gpr_cv_signal(&reader.stop); } /* wait for reader to finish */ while (reader.running) { gpr_cv_wait(&reader_done, &reader_mu, gpr_inf_future); } if (circular_log) { /* Assert that there were no out-of-space errors. */ GPR_ASSERT(0 == census_log_out_of_space_count()); } gpr_mu_unlock(&reader_mu); gpr_mu_destroy(&reader_mu); gpr_cv_destroy(&reader_done); printf(" Reader: finished\n"); }
static void must_fail(void *arg, grpc_endpoint *tcp) { GPR_ASSERT(!tcp); gpr_event_set(arg, (void *)1); }
static void init_channel_elem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, grpc_channel_element_args *args) { GPR_ASSERT(args->is_first); GPR_ASSERT(args->is_last); }
static void test_max_message_length(grpc_end2end_test_config config) { grpc_end2end_test_fixture f; grpc_arg server_arg; grpc_channel_args server_args; grpc_call *c; grpc_call *s; cq_verifier *v_client; cq_verifier *v_server; grpc_op ops[6]; grpc_op *op; gpr_slice request_payload_slice = gpr_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_metadata_array request_metadata_recv; grpc_call_details call_details; grpc_status_code status; char *details = NULL; size_t details_capacity = 0; int was_cancelled = 2; server_arg.key = GRPC_ARG_MAX_MESSAGE_LENGTH; server_arg.type = GRPC_ARG_INTEGER; server_arg.value.integer = 5; server_args.num_args = 1; server_args.args = &server_arg; f = begin_test(config, "test_max_message_length", NULL, &server_args); v_client = cq_verifier_create(f.client_cq); v_server = cq_verifier_create(f.server_cq); c = grpc_channel_create_call(f.client, f.client_cq, "/foo", "foo.test.google.fr:1234", gpr_inf_future); GPR_ASSERT(c); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); grpc_metadata_array_init(&request_metadata_recv); grpc_call_details_init(&call_details); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = request_payload; op++; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op++; op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &initial_metadata_recv; op++; op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; op->data.recv_status_on_client.status = &status; op->data.recv_status_on_client.status_details = &details; op->data.recv_status_on_client.status_details_capacity = &details_capacity; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, op - ops, tag(1))); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(f.server, &s, &call_details, &request_metadata_recv, f.server_cq, f.server_cq, tag(101))); cq_expect_completion(v_server, tag(101), 1); cq_verify(v_server); op = ops; op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &was_cancelled; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(s, ops, op - ops, tag(102))); cq_expect_completion(v_server, tag(102), 1); cq_verify(v_server); cq_expect_completion(v_client, tag(1), 1); cq_verify(v_client); GPR_ASSERT(status != GRPC_STATUS_OK); GPR_ASSERT(0 == strcmp(call_details.method, "/foo")); GPR_ASSERT(0 == strcmp(call_details.host, "foo.test.google.fr:1234")); GPR_ASSERT(was_cancelled == 1); gpr_free(details); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_metadata_array_destroy(&request_metadata_recv); grpc_call_details_destroy(&call_details); grpc_byte_buffer_destroy(request_payload); grpc_call_destroy(c); grpc_call_destroy(s); cq_verifier_destroy(v_client); cq_verifier_destroy(v_server); end_test(&f); config.tear_down_data(&f); }