static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { grpc_endpoint_test_fixture f = config.create_fixture(slice_size); grpc_slice_buffer incoming; grpc_slice s = grpc_slice_from_copied_string("hello world 12345678900987654321"); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; int n = 0; grpc_closure done_closure; gpr_log(GPR_INFO, "Start test left over"); grpc_slice_buffer_init(&incoming); grpc_closure_init(&done_closure, inc_call_ctr, &n, grpc_schedule_on_exec_ctx); grpc_endpoint_read(&exec_ctx, f.client_ep, &incoming, &done_closure); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT(n == 1); GPR_ASSERT(incoming.count == 1); GPR_ASSERT(grpc_slice_eq(s, incoming.slices[0])); grpc_endpoint_shutdown(&exec_ctx, f.client_ep, GRPC_ERROR_CREATE("test_leftover end")); grpc_endpoint_shutdown(&exec_ctx, f.server_ep, GRPC_ERROR_CREATE("test_leftover end")); grpc_endpoint_destroy(&exec_ctx, f.client_ep); grpc_endpoint_destroy(&exec_ctx, f.server_ep); grpc_exec_ctx_finish(&exec_ctx); grpc_slice_unref_internal(&exec_ctx, s); grpc_slice_buffer_destroy_internal(&exec_ctx, &incoming); clean_up(); }
static void test_send_messages_at_the_same_time() { gpr_log(GPR_INFO, "test_send_messages_at_the_same_time"); grpc_op *op; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); prepare_test(1); op = g_state.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_MESSAGE; op->data.send_message = request_payload; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = tag(2); op->flags = 0; op->reserved = NULL; op++; GPR_ASSERT(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS == grpc_call_start_batch(g_state.call, g_state.ops, (size_t)(op - g_state.ops), tag(1), NULL)); grpc_byte_buffer_destroy(request_payload); cleanup_test(); }
static void populate_entries(const test_entry* input, size_t num_entries, grpc_slice_hash_table_entry* output) { for (size_t i = 0; i < num_entries; ++i) { output[i].key = grpc_slice_from_copied_string(input[i].key); output[i].value = gpr_strdup(input[i].value); } }
static void test_algorithm_mesh(void) { int i; gpr_log(GPR_DEBUG, "test_algorithm_mesh"); for (i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { const char *name; grpc_compression_algorithm parsed; grpc_slice mdstr; grpc_mdelem mdelem; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT( grpc_compression_algorithm_name((grpc_compression_algorithm)i, &name)); GPR_ASSERT(grpc_compression_algorithm_parse( grpc_slice_from_static_string(name), &parsed)); GPR_ASSERT((int)parsed == i); mdstr = grpc_slice_from_copied_string(name); GPR_ASSERT(grpc_slice_eq(mdstr, grpc_compression_algorithm_slice(parsed))); GPR_ASSERT(parsed == grpc_compression_algorithm_from_slice(mdstr)); mdelem = grpc_compression_encoding_mdelem(parsed); GPR_ASSERT(grpc_slice_eq(GRPC_MDVALUE(mdelem), mdstr)); GPR_ASSERT(grpc_slice_eq(GRPC_MDKEY(mdelem), GRPC_MDSTR_GRPC_ENCODING)); grpc_slice_unref_internal(&exec_ctx, mdstr); GRPC_MDELEM_UNREF(&exec_ctx, mdelem); grpc_exec_ctx_finish(&exec_ctx); } /* test failure */ GPR_ASSERT(GRPC_MDISNULL( grpc_compression_encoding_mdelem(GRPC_COMPRESS_ALGORITHMS_COUNT))); }
static grpc_endpoint_test_fixture secure_endpoint_create_fixture_tcp_socketpair_leftover(size_t slice_size) { grpc_slice s = grpc_slice_from_copied_string("hello world 12345678900987654321"); grpc_endpoint_test_fixture f; f = secure_endpoint_create_fixture_tcp_socketpair(slice_size, &s, 1); return f; }
GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_array_add(grpc_metadata_array* array, const char* key, const char* value, size_t value_length) { size_t i = array->count; GPR_ASSERT(array->count < array->capacity); array->metadata[i].key = grpc_slice_from_copied_string(key); array->metadata[i].value = grpc_slice_from_copied_buffer(value, value_length); array->count++; }
static grpc_error *error_for_fd(int fd, const grpc_resolved_address *addr) { if (fd >= 0) return GRPC_ERROR_NONE; char *addr_str; grpc_sockaddr_to_string(&addr_str, addr, 0); grpc_error *err = grpc_error_set_str(GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(addr_str)); gpr_free(addr_str); return err; }
static void test_dump_slice(void) { static const char *text = "HELLO WORLD!"; static const char *long_text = "It was a bright cold day in April, and the clocks were striking " "thirteen. Winston Smith, his chin nuzzled into his breast in an effort " "to escape the vile wind, slipped quickly through the glass doors of " "Victory Mansions, though not quickly enough to prevent a swirl of " "gritty dust from entering along with him."; LOG_TEST_NAME("test_dump_slice"); expect_slice_dump(grpc_slice_from_copied_string(text), GPR_DUMP_ASCII, text); expect_slice_dump(grpc_slice_from_copied_string(long_text), GPR_DUMP_ASCII, long_text); expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX, "01"); expect_slice_dump(grpc_slice_from_copied_buffer("\x01", 1), GPR_DUMP_HEX | GPR_DUMP_ASCII, "01 '.'"); }
GPR_EXPORT grpc_call* GPR_CALLTYPE grpcsharp_channel_create_call( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* cq, const char* method, const char* host, gpr_timespec deadline) { grpc_slice method_slice = grpc_slice_from_copied_string(method); grpc_slice* host_slice_ptr = NULL; grpc_slice host_slice; if (host != NULL) { host_slice = grpc_slice_from_copied_string(host); host_slice_ptr = &host_slice; } grpc_call* ret = grpc_channel_create_call(channel, parent_call, propagation_mask, cq, method_slice, host_slice_ptr, deadline, NULL); grpc_slice_unref(method_slice); if (host != NULL) { grpc_slice_unref(host_slice); } return ret; }
/* Client sends a request, server replies with a payload, then waits for the keepalive watchdog timeouts before returning status. */ static void test_keepalive_timeout(grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; 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_arg keepalive_args[] = {{.type = GRPC_ARG_INTEGER, .key = GRPC_ARG_KEEPALIVE_TIME_MS, .value.integer = 1500}, {.type = GRPC_ARG_INTEGER,
static void reset_addr_and_set_magic_string(grpc_resolved_address **addr, grpc_slice *connect_string) { struct sockaddr_in target; *connect_string = grpc_slice_from_copied_string(magic_connect_string); gpr_free(*addr); target.sin_family = AF_INET; target.sin_addr.s_addr = htonl(INADDR_LOOPBACK); target.sin_port = htons((uint16_t)server_port); *addr = (grpc_resolved_address *)gpr_malloc(sizeof(grpc_resolved_address)); (*addr)->len = sizeof(target); memcpy((*addr)->addr, &target, sizeof(target)); }
static void deadline_enc(grpc_exec_ctx *exec_ctx, grpc_chttp2_hpack_compressor *c, gpr_timespec deadline, framer_state *st) { char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; grpc_mdelem mdelem; grpc_http2_encode_timeout( gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str); mdelem = grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_TIMEOUT, grpc_slice_from_copied_string(timeout_str)); hpack_enc(exec_ctx, c, mdelem, st); GRPC_MDELEM_UNREF(exec_ctx, mdelem); }
/* Creates and returns a grpc_slice containing random alphanumeric characters. */ static grpc_slice generate_random_slice() { size_t i; static const char chars[] = "abcdefghijklmnopqrstuvwxyz1234567890"; char *output; const size_t output_size = 1024 * 1024; output = gpr_malloc(output_size); for (i = 0; i < output_size - 1; ++i) { output[i] = chars[rand() % (int)(sizeof(chars) - 1)]; } output[output_size - 1] = '\0'; grpc_slice out = grpc_slice_from_copied_string(output); gpr_free(output); return out; }
grpc_error *grpc_load_file(const char *filename, int add_null_terminator, grpc_slice *output) { unsigned char *contents = NULL; size_t contents_size = 0; grpc_slice result = grpc_empty_slice(); FILE *file; size_t bytes_read = 0; grpc_error *error = GRPC_ERROR_NONE; GRPC_SCHEDULING_START_BLOCKING_REGION; file = fopen(filename, "rb"); if (file == NULL) { error = GRPC_OS_ERROR(errno, "fopen"); goto end; } fseek(file, 0, SEEK_END); /* Converting to size_t on the assumption that it will not fail */ contents_size = (size_t)ftell(file); fseek(file, 0, SEEK_SET); contents = (unsigned char *)gpr_malloc(contents_size + (add_null_terminator ? 1 : 0)); bytes_read = fread(contents, 1, contents_size, file); if (bytes_read < contents_size) { error = GRPC_OS_ERROR(errno, "fread"); GPR_ASSERT(ferror(file)); goto end; } if (add_null_terminator) { contents[contents_size++] = 0; } result = grpc_slice_new(contents, contents_size, gpr_free); end: *output = result; if (file != NULL) fclose(file); if (error != GRPC_ERROR_NONE) { grpc_error *error_out = grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to load file", &error, 1), GRPC_ERROR_STR_FILENAME, grpc_slice_from_copied_string( filename)); // TODO(ncteisen), always static? GRPC_ERROR_UNREF(error); error = error_out; } GRPC_SCHEDULING_END_BLOCKING_REGION; return error; }
static grpc_mdelem *client_recv_filter(void *user_data, grpc_mdelem *md) { client_recv_filter_args *a = user_data; if (md == GRPC_MDELEM_STATUS_200) { return NULL; } else if (md->key == GRPC_MDSTR_STATUS) { char *message_string; gpr_asprintf(&message_string, "Received http2 header with status: %s", grpc_mdstr_as_c_string(md->value)); grpc_slice message = grpc_slice_from_copied_string(message_string); gpr_free(message_string); grpc_call_element_send_close_with_message(a->exec_ctx, a->elem, GRPC_STATUS_CANCELLED, &message); return NULL; } else if (md->key == GRPC_MDSTR_GRPC_MESSAGE) { grpc_slice pct_decoded_msg = grpc_permissive_percent_decode_slice(md->value->slice); if (grpc_slice_is_equivalent(pct_decoded_msg, md->value->slice)) { grpc_slice_unref(pct_decoded_msg); return md; } else { return grpc_mdelem_from_metadata_strings( GRPC_MDSTR_GRPC_MESSAGE, grpc_mdstr_from_slice(pct_decoded_msg)); } } else if (md == GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC) { return NULL; } else if (md->key == GRPC_MDSTR_CONTENT_TYPE) { const char *value_str = grpc_mdstr_as_c_string(md->value); if (strncmp(value_str, EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) == 0 && (value_str[EXPECTED_CONTENT_TYPE_LENGTH] == '+' || value_str[EXPECTED_CONTENT_TYPE_LENGTH] == ';')) { /* Although the C implementation doesn't (currently) generate them, any custom +-suffix is explicitly valid. */ /* TODO(klempner): We should consider preallocating common values such as +proto or +json, or at least stashing them if we see them. */ /* TODO(klempner): Should we be surfacing this to application code? */ } else { /* TODO(klempner): We're currently allowing this, but we shouldn't see it without a proxy so log for now. */ gpr_log(GPR_INFO, "Unexpected content-type '%s'", value_str); } return NULL; } return md; }
static grpc_error *conforms_to(grpc_slice slice, const uint8_t *legal_bits, const char *err_desc) { const uint8_t *p = GRPC_SLICE_START_PTR(slice); const uint8_t *e = GRPC_SLICE_END_PTR(slice); for (; p != e; p++) { int idx = *p; int byte = idx / 8; int bit = idx % 8; if ((legal_bits[byte] & (1 << bit)) == 0) { char *dump = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); grpc_error *error = grpc_error_set_str( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc), GRPC_ERROR_INT_OFFSET, p - GRPC_SLICE_START_PTR(slice)), GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(dump)); gpr_free(dump); return error; } } return GRPC_ERROR_NONE; }
void* grpc_method_config_table_get(grpc_exec_ctx* exec_ctx, const grpc_slice_hash_table* table, grpc_slice path) { void* value = grpc_slice_hash_table_get(table, path); // If we didn't find a match for the path, try looking for a wildcard // entry (i.e., change "/service/method" to "/service/*"). if (value == NULL) { char* path_str = grpc_slice_to_c_string(path); const char* sep = strrchr(path_str, '/') + 1; const size_t len = (size_t)(sep - path_str); char* buf = gpr_malloc(len + 2); // '*' and NUL memcpy(buf, path_str, len); buf[len] = '*'; buf[len + 1] = '\0'; grpc_slice wildcard_path = grpc_slice_from_copied_string(buf); gpr_free(buf); value = grpc_slice_hash_table_get(table, wildcard_path); grpc_slice_unref_internal(exec_ctx, wildcard_path); gpr_free(path_str); } return value; }
// Callback to connect to the backend server specified by the HTTP // CONNECT request. static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) { proxy_connection* conn = arg; if (error != GRPC_ERROR_NONE) { // TODO(roth): Technically, in this case, we should handle the error // by returning an HTTP response to the client indicating that the // connection failed. However, for the purposes of this test code, // it's fine to pretend this is a client-side error, which will // cause the client connection to be dropped. proxy_connection_failed(exec_ctx, conn, true /* is_client */, "HTTP proxy server connect", error); return; } // We've established a connection, so send back a 200 response code to // the client. // The write callback inherits our reference to conn. grpc_slice slice = grpc_slice_from_copied_string("HTTP/1.0 200 connected\r\n\r\n"); grpc_slice_buffer_add(&conn->client_write_buffer, slice); grpc_endpoint_write(exec_ctx, conn->client_endpoint, &conn->client_write_buffer, &conn->on_write_response_done); }
// Parses the method config from \a json. Adds an entry to \a entries for // each name found, incrementing \a idx for each entry added. // Returns false on error. static bool parse_json_method_config( grpc_exec_ctx* exec_ctx, grpc_json* json, void* (*create_value)(const grpc_json* method_config_json), const grpc_slice_hash_table_vtable* vtable, grpc_slice_hash_table_entry* entries, size_t* idx) { // Construct value. void* method_config = create_value(json); if (method_config == NULL) return false; // Construct list of paths. bool success = false; gpr_strvec paths; gpr_strvec_init(&paths); for (grpc_json* child = json->child; child != NULL; child = child->next) { if (child->key == NULL) continue; if (strcmp(child->key, "name") == 0) { if (child->type != GRPC_JSON_ARRAY) goto done; for (grpc_json* name = child->child; name != NULL; name = name->next) { char* path = parse_json_method_name(name); gpr_strvec_add(&paths, path); } } } if (paths.count == 0) goto done; // No names specified. // Add entry for each path. for (size_t i = 0; i < paths.count; ++i) { entries[*idx].key = grpc_slice_from_copied_string(paths.strs[i]); entries[*idx].value = vtable->copy_value(method_config); entries[*idx].vtable = vtable; ++*idx; } success = true; done: vtable->destroy_value(exec_ctx, method_config); gpr_strvec_destroy(&paths); return success; }
static void multiple_shutdown_test(grpc_endpoint_test_config config) { grpc_endpoint_test_fixture f = begin_test(config, "multiple_shutdown_test", 128); int fail_count = 0; grpc_slice_buffer slice_buffer; grpc_slice_buffer_init(&slice_buffer); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_add_to_pollset(&exec_ctx, f.client_ep, g_pollset); grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, grpc_schedule_on_exec_ctx)); wait_for_fail_count(&exec_ctx, &fail_count, 0); grpc_endpoint_shutdown(&exec_ctx, f.client_ep, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); wait_for_fail_count(&exec_ctx, &fail_count, 1); grpc_endpoint_read(&exec_ctx, f.client_ep, &slice_buffer, GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, grpc_schedule_on_exec_ctx)); wait_for_fail_count(&exec_ctx, &fail_count, 2); grpc_slice_buffer_add(&slice_buffer, grpc_slice_from_copied_string("a")); grpc_endpoint_write(&exec_ctx, f.client_ep, &slice_buffer, GRPC_CLOSURE_CREATE(inc_on_failure, &fail_count, grpc_schedule_on_exec_ctx)); wait_for_fail_count(&exec_ctx, &fail_count, 3); grpc_endpoint_shutdown(&exec_ctx, f.client_ep, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test Shutdown")); wait_for_fail_count(&exec_ctx, &fail_count, 3); grpc_slice_buffer_destroy_internal(&exec_ctx, &slice_buffer); grpc_endpoint_destroy(&exec_ctx, f.client_ep); grpc_endpoint_destroy(&exec_ctx, f.server_ep); grpc_exec_ctx_finish(&exec_ctx); }
grpc_error *grpc_deframe_unprocessed_incoming_frames( grpc_exec_ctx *exec_ctx, grpc_chttp2_data_parser *p, grpc_chttp2_stream *s, grpc_slice_buffer *slices, grpc_slice *slice_out, grpc_byte_stream **stream_out) { grpc_error *error = GRPC_ERROR_NONE; grpc_chttp2_transport *t = s->t; while (slices->count > 0) { uint8_t *beg = NULL; uint8_t *end = NULL; uint8_t *cur = NULL; grpc_slice slice = grpc_slice_buffer_take_first(slices); beg = GRPC_SLICE_START_PTR(slice); end = GRPC_SLICE_END_PTR(slice); cur = beg; uint32_t message_flags; char *msg; if (cur == end) { grpc_slice_unref_internal(exec_ctx, slice); continue; } switch (p->state) { case GRPC_CHTTP2_DATA_ERROR: p->state = GRPC_CHTTP2_DATA_ERROR; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_REF(p->error); case GRPC_CHTTP2_DATA_FH_0: p->frame_type = *cur; switch (p->frame_type) { case 0: p->is_frame_compressed = false; /* GPR_FALSE */ break; case 1: p->is_frame_compressed = true; /* GPR_TRUE */ break; default: gpr_asprintf(&msg, "Bad GRPC frame type 0x%02x", p->frame_type); p->error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_STREAM_ID, (intptr_t)s->id); gpr_free(msg); msg = grpc_dump_slice(slice, GPR_DUMP_HEX | GPR_DUMP_ASCII); p->error = grpc_error_set_str(p->error, GRPC_ERROR_STR_RAW_BYTES, grpc_slice_from_copied_string(msg)); gpr_free(msg); p->error = grpc_error_set_int(p->error, GRPC_ERROR_INT_OFFSET, cur - beg); p->state = GRPC_CHTTP2_DATA_ERROR; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_REF(p->error); } if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_1; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_1: p->frame_size = ((uint32_t)*cur) << 24; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_2; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_2: p->frame_size |= ((uint32_t)*cur) << 16; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_3; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_3: p->frame_size |= ((uint32_t)*cur) << 8; if (++cur == end) { p->state = GRPC_CHTTP2_DATA_FH_4; grpc_slice_unref_internal(exec_ctx, slice); continue; } /* fallthrough */ case GRPC_CHTTP2_DATA_FH_4: GPR_ASSERT(stream_out != NULL); GPR_ASSERT(p->parsing_frame == NULL); p->frame_size |= ((uint32_t)*cur); p->state = GRPC_CHTTP2_DATA_FRAME; ++cur; message_flags = 0; if (p->is_frame_compressed) { message_flags |= GRPC_WRITE_INTERNAL_COMPRESS; } p->parsing_frame = grpc_chttp2_incoming_byte_stream_create( exec_ctx, t, s, p->frame_size, message_flags); *stream_out = &p->parsing_frame->base; if (p->parsing_frame->remaining_bytes == 0) { GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true)); p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; } s->pending_byte_stream = true; if (cur != end) { grpc_slice_buffer_undo_take_first( &s->unprocessed_incoming_frames_buffer, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); } grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; case GRPC_CHTTP2_DATA_FRAME: { GPR_ASSERT(p->parsing_frame != NULL); GPR_ASSERT(slice_out != NULL); if (cur == end) { grpc_slice_unref_internal(exec_ctx, slice); continue; } uint32_t remaining = (uint32_t)(end - cur); if (remaining == p->frame_size) { if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)), slice_out))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } else if (remaining < p->frame_size) { if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg)), slice_out))) { return error; } p->frame_size -= remaining; grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } else { GPR_ASSERT(remaining > p->frame_size); if (GRPC_ERROR_NONE != (grpc_chttp2_incoming_byte_stream_push( exec_ctx, p->parsing_frame, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(cur + p->frame_size - beg)), slice_out))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } if (GRPC_ERROR_NONE != (error = grpc_chttp2_incoming_byte_stream_finished( exec_ctx, p->parsing_frame, GRPC_ERROR_NONE, true))) { grpc_slice_unref_internal(exec_ctx, slice); return error; } p->parsing_frame = NULL; p->state = GRPC_CHTTP2_DATA_FH_0; cur += p->frame_size; grpc_slice_buffer_undo_take_first( &s->unprocessed_incoming_frames_buffer, grpc_slice_sub(slice, (size_t)(cur - beg), (size_t)(end - beg))); grpc_slice_unref_internal(exec_ctx, slice); return GRPC_ERROR_NONE; } } } } return GRPC_ERROR_NONE; }
int main(int argc, char **argv) { grpc_memory_counters_init(); grpc_slice slice = grpc_slice_from_copied_string("x"); char *fake_argv[1]; char *target = "localhost:443"; gpr_cmdline *cl; grpc_event event; grpc_init(); GPR_ASSERT(argc >= 1); fake_argv[0] = argv[0]; grpc_test_init(1, fake_argv); int warmup_iterations = 100; int benchmark_iterations = 1000; cl = gpr_cmdline_create("memory profiling client"); gpr_cmdline_add_string(cl, "target", "Target host:port", &target); gpr_cmdline_add_int(cl, "warmup", "Warmup iterations", &warmup_iterations); gpr_cmdline_add_int(cl, "benchmark", "Benchmark iterations", &benchmark_iterations); gpr_cmdline_parse(cl, argc, argv); gpr_cmdline_destroy(cl); for (size_t k = 0; k < GPR_ARRAY_SIZE(calls); k++) { calls[k].details = grpc_empty_slice(); } cq = grpc_completion_queue_create(NULL); struct grpc_memory_counters client_channel_start = grpc_memory_counters_snapshot(); channel = grpc_insecure_channel_create(target, NULL, NULL); int call_idx = 0; struct grpc_memory_counters before_server_create = send_snapshot_request( 0, grpc_slice_from_static_string("Reflector/GetBeforeSvrCreation")); struct grpc_memory_counters after_server_create = send_snapshot_request( 0, grpc_slice_from_static_string("Reflector/GetAfterSvrCreation")); // warmup period for (call_idx = 0; call_idx < warmup_iterations; ++call_idx) { init_ping_pong_request(call_idx + 1); } struct grpc_memory_counters server_benchmark_calls_start = send_snapshot_request( 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); struct grpc_memory_counters client_benchmark_calls_start = grpc_memory_counters_snapshot(); // benchmark period for (; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { init_ping_pong_request(call_idx + 1); } struct grpc_memory_counters client_calls_inflight = grpc_memory_counters_snapshot(); struct grpc_memory_counters server_calls_inflight = send_snapshot_request( 0, grpc_slice_from_static_string("Reflector/DestroyCalls")); do { event = grpc_completion_queue_next( cq, gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(10000, GPR_TIMESPAN)), NULL); } while (event.type != GRPC_QUEUE_TIMEOUT); // second step - recv status and destroy call for (call_idx = 0; call_idx < warmup_iterations + benchmark_iterations; ++call_idx) { finish_ping_pong_request(call_idx + 1); } struct grpc_memory_counters server_calls_end = send_snapshot_request( 0, grpc_slice_from_static_string("Reflector/SimpleSnapshot")); struct grpc_memory_counters client_channel_end = grpc_memory_counters_snapshot(); grpc_channel_destroy(channel); grpc_completion_queue_shutdown(cq); do { event = grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); } while (event.type != GRPC_QUEUE_SHUTDOWN); grpc_slice_unref(slice); grpc_completion_queue_destroy(cq); grpc_shutdown(); gpr_log(GPR_INFO, "---------client stats--------"); gpr_log(GPR_INFO, "client call memory usage: %f bytes per call", (double)(client_calls_inflight.total_size_relative - client_benchmark_calls_start.total_size_relative) / benchmark_iterations); gpr_log(GPR_INFO, "client channel memory usage %zi bytes", client_channel_end.total_size_relative - client_channel_start.total_size_relative); gpr_log(GPR_INFO, "---------server stats--------"); gpr_log(GPR_INFO, "server create: %zi bytes", after_server_create.total_size_relative - before_server_create.total_size_relative); gpr_log(GPR_INFO, "server call memory usage: %f bytes per call", (double)(server_calls_inflight.total_size_relative - server_benchmark_calls_start.total_size_relative) / benchmark_iterations); gpr_log(GPR_INFO, "server channel memory usage %zi bytes", server_calls_end.total_size_relative - after_server_create.total_size_relative); grpc_memory_counters_destroy(); return 0; }
static void request_with_payload_template( grpc_end2end_test_config config, const char *test_name, uint32_t client_send_flags_bitmask, grpc_compression_algorithm default_client_channel_compression_algorithm, grpc_compression_algorithm default_server_channel_compression_algorithm, grpc_compression_algorithm expected_algorithm_from_client, grpc_compression_algorithm expected_algorithm_from_server, grpc_metadata *client_init_metadata, bool set_server_level, grpc_compression_level server_compression_level, bool send_message_before_initial_metadata) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice; grpc_byte_buffer *request_payload = NULL; grpc_channel_args *client_args; grpc_channel_args *server_args; grpc_end2end_test_fixture f; 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; grpc_byte_buffer *response_payload_recv; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; cq_verifier *cqv; char request_str[1024]; char response_str[1024]; memset(request_str, 'x', 1023); request_str[1023] = '\0'; memset(response_str, 'y', 1023); response_str[1023] = '\0'; request_payload_slice = grpc_slice_from_copied_string(request_str); grpc_slice response_payload_slice = grpc_slice_from_copied_string(response_str); client_args = grpc_channel_args_set_compression_algorithm( NULL, default_client_channel_compression_algorithm); server_args = grpc_channel_args_set_compression_algorithm( NULL, default_server_channel_compression_algorithm); f = begin_test(config, test_name, client_args, server_args); cqv = cq_verifier_create(f.cq); gpr_timespec deadline = five_seconds_from_now(); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), get_host_override_slice("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); if (send_message_before_initial_metadata) { request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = client_send_flags_bitmask; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), true); } memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; if (client_init_metadata != NULL) { op->data.send_initial_metadata.count = 1; op->data.send_initial_metadata.metadata = client_init_metadata; } else { op->data.send_initial_metadata.count = 0; } 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_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(100)); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(100), true); cq_verify(cqv); GPR_ASSERT(GPR_BITCOUNT(grpc_call_test_only_get_encodings_accepted_by_peer( s)) == GRPC_COMPRESS_ALGORITHMS_COUNT); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_NONE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_DEFLATE) != 0); GPR_ASSERT(GPR_BITGET(grpc_call_test_only_get_encodings_accepted_by_peer(s), GRPC_COMPRESS_GZIP) != 0); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; if (set_server_level) { op->data.send_initial_metadata.maybe_compression_level.is_set = true; op->data.send_initial_metadata.maybe_compression_level.level = server_compression_level; } 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(101), NULL); GPR_ASSERT(GRPC_CALL_OK == error); for (int i = 0; i < 2; i++) { response_payload = grpc_raw_byte_buffer_create(&response_payload_slice, 1); if (i > 0 || !send_message_before_initial_metadata) { request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = client_send_flags_bitmask; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), 1); } memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &request_payload_recv; 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_verify(cqv); GPR_ASSERT(request_payload_recv->type == GRPC_BB_RAW); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, request_str)); GPR_ASSERT(request_payload_recv->data.raw.compression == expected_algorithm_from_client); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = response_payload; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); GPR_ASSERT(GRPC_CALL_OK == error); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &response_payload_recv; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(103), 1); CQ_EXPECT_COMPLETION(cqv, tag(3), 1); cq_verify(cqv); GPR_ASSERT(response_payload_recv->type == GRPC_BB_RAW); GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, response_str)); if (server_compression_level > GRPC_COMPRESS_LEVEL_NONE) { const grpc_compression_algorithm algo_for_server_level = grpc_call_compression_for_level(s, server_compression_level); GPR_ASSERT(response_payload_recv->data.raw.compression == algo_for_server_level); } else { GPR_ASSERT(response_payload_recv->data.raw.compression == expected_algorithm_from_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); } grpc_slice_unref(request_payload_slice); grpc_slice_unref(response_payload_slice); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; op->flags = 0; op->reserved = NULL; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); GPR_ASSERT(GRPC_CALL_OK == error); memset(ops, 0, sizeof(ops)); op = ops; 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(104), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); CQ_EXPECT_COMPLETION(cqv, tag(4), 1); CQ_EXPECT_COMPLETION(cqv, tag(101), 1); CQ_EXPECT_COMPLETION(cqv, tag(104), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); GPR_ASSERT(was_cancelled == 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_call_unref(c); grpc_call_unref(s); cq_verifier_destroy(cqv); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, client_args); grpc_channel_args_destroy(&exec_ctx, server_args); grpc_exec_ctx_finish(&exec_ctx); } end_test(&f); config.tear_down_data(&f); }
static void request_for_disabled_algorithm( grpc_end2end_test_config config, const char *test_name, uint32_t send_flags_bitmask, grpc_compression_algorithm algorithm_to_disable, grpc_compression_algorithm requested_client_compression_algorithm, grpc_status_code expected_error, grpc_metadata *client_metadata) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice; grpc_byte_buffer *request_payload; grpc_channel_args *client_args; grpc_channel_args *server_args; grpc_end2end_test_fixture f; 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_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; cq_verifier *cqv; char str[1024]; memset(str, 'x', 1023); str[1023] = '\0'; request_payload_slice = grpc_slice_from_copied_string(str); request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); client_args = grpc_channel_args_set_compression_algorithm( NULL, requested_client_compression_algorithm); server_args = grpc_channel_args_set_compression_algorithm(NULL, GRPC_COMPRESS_NONE); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; server_args = grpc_channel_args_compression_algorithm_set_state( &exec_ctx, &server_args, algorithm_to_disable, false); grpc_exec_ctx_finish(&exec_ctx); } f = begin_test(config, test_name, client_args, server_args); cqv = cq_verifier_create(f.cq); gpr_timespec deadline = five_seconds_from_now(); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), get_host_override_slice("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); 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); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; if (client_metadata != NULL) { op->data.send_initial_metadata.count = 1; op->data.send_initial_metadata.metadata = client_metadata; } else { op->data.send_initial_metadata.count = 0; } op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; op->flags = send_flags_bitmask; 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_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); CQ_EXPECT_COMPLETION(cqv, tag(101), true); 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_RECV_MESSAGE; op->data.recv_message.recv_message = &request_payload_recv; 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), false); op = ops; 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(103), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(103), true); CQ_EXPECT_COMPLETION(cqv, tag(1), true); cq_verify(cqv); /* call was cancelled (closed) ... */ GPR_ASSERT(was_cancelled != 0); /* with a certain error */ GPR_ASSERT(status == expected_error); const char *algo_name = NULL; GPR_ASSERT(grpc_compression_algorithm_name(algorithm_to_disable, &algo_name)); char *expected_details = NULL; gpr_asprintf(&expected_details, "Compression algorithm '%s' is disabled.", algo_name); /* and we expect a specific reason for it */ GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details)); gpr_free(expected_details); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); 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_call_unref(c); grpc_call_unref(s); cq_verifier_destroy(cqv); grpc_slice_unref(request_payload_slice); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(request_payload_recv); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, client_args); grpc_channel_args_destroy(&exec_ctx, server_args); grpc_exec_ctx_finish(&exec_ctx); } end_test(&f); config.tear_down_data(&f); }
/* Client sends a request with payload, server reads then returns status. */ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); gpr_timespec deadline = five_seconds_time(); grpc_end2end_test_fixture f = begin_test(config, "test_invoke_request_with_payload", NULL, NULL); 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_byte_buffer *request_payload_recv = NULL; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), get_host_override_slice("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 = 0; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; 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_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); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( f.server, &s, &call_details, &request_metadata_recv, f.cq, f.cq, tag(101))); 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_MESSAGE; op->data.recv_message.recv_message = &request_payload_recv; 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_verify(cqv); memset(ops, 0, sizeof(ops)); op = ops; 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_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(103), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(103), 1); CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world")); 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_call_destroy(c); grpc_call_destroy(s); cq_verifier_destroy(cqv); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(request_payload_recv); end_test(&f); config.tear_down_data(&f); }
// Simple request via a server filter that saves the reported latency value. static void test_request(grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1); grpc_end2end_test_fixture f = begin_test(config, "filter_latency", NULL, NULL); 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_byte_buffer *request_payload_recv = NULL; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details; int was_cancelled = 2; gpr_mu_lock(&g_mu); g_client_latency = gpr_time_0(GPR_TIMESPAN); g_server_latency = gpr_time_0(GPR_TIMESPAN); gpr_mu_unlock(&g_mu); const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec deadline = five_seconds_from_now(); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), get_host_override_slice("foo.test.google.fr", 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 = 0; op->data.send_initial_metadata.metadata = NULL; op->flags = 0; op->reserved = NULL; op++; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload; 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_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_SEND_STATUS_FROM_SERVER; op->data.send_status_from_server.trailing_metadata_count = 0; op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; grpc_slice status_string = grpc_slice_from_static_string("xyz"); op->data.send_status_from_server.status_details = &status_string; 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 == grpc_slice_str_cmp(details, "xyz")); 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_call_unref(s); grpc_call_unref(c); cq_verifier_destroy(cqv); grpc_byte_buffer_destroy(request_payload); grpc_byte_buffer_destroy(request_payload_recv); end_test(&f); config.tear_down_data(&f); const gpr_timespec end_time = gpr_now(GPR_CLOCK_MONOTONIC); const gpr_timespec max_latency = gpr_time_sub(end_time, start_time); // Perform checks after test tear-down // Guards against the case that there's outstanding channel-related work on a // call prior to verification gpr_mu_lock(&g_mu); GPR_ASSERT(gpr_time_cmp(max_latency, g_client_latency) >= 0); GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_client_latency) <= 0); GPR_ASSERT(gpr_time_cmp(max_latency, g_server_latency) >= 0); GPR_ASSERT(gpr_time_cmp(gpr_time_0(GPR_TIMESPAN), g_server_latency) <= 0); // Server latency should always be smaller than client latency, however since // we only calculate latency at destruction time, and that might mean that we // need to wait for outstanding channel-related work, this isn't verifiable // right now (the server MAY hold on to the call for longer than the client). // GPR_ASSERT(gpr_time_cmp(g_server_latency, g_client_latency) < 0); gpr_mu_unlock(&g_mu); }
static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, grpc_resolver_factory* factory, grpc_resolver_args* args) { if (0 != strcmp(args->uri->authority, "")) { gpr_log(GPR_ERROR, "authority based uri's not supported by the %s scheme", args->uri->scheme); return NULL; } // Get lb_enabled arg. Anything other than "0" is interpreted as true. const char* lb_enabled_qpart = grpc_uri_get_query_arg(args->uri, "lb_enabled"); const bool lb_enabled = lb_enabled_qpart != NULL && strcmp("0", lb_enabled_qpart) != 0; // Get the balancer's names. const char* balancer_names = grpc_uri_get_query_arg(args->uri, "balancer_names"); grpc_slice_buffer balancer_names_parts; grpc_slice_buffer_init(&balancer_names_parts); if (balancer_names != NULL) { const grpc_slice balancer_names_slice = grpc_slice_from_copied_string(balancer_names); grpc_slice_split(balancer_names_slice, ",", &balancer_names_parts); grpc_slice_unref(balancer_names_slice); } // Construct addresses. grpc_slice path_slice = grpc_slice_new(args->uri->path, strlen(args->uri->path), do_nothing); grpc_slice_buffer path_parts; grpc_slice_buffer_init(&path_parts); grpc_slice_split(path_slice, ",", &path_parts); if (balancer_names_parts.count > 0 && path_parts.count != balancer_names_parts.count) { gpr_log(GPR_ERROR, "Balancer names present but mismatched with number of addresses: " "%lu balancer names != %lu addresses", (unsigned long)balancer_names_parts.count, (unsigned long)path_parts.count); return NULL; } grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */); bool errors_found = false; for (size_t i = 0; i < addresses->num_addresses; i++) { grpc_uri ith_uri = *args->uri; char* part_str = grpc_slice_to_c_string(path_parts.slices[i]); ith_uri.path = part_str; if (!parse_ipv4(&ith_uri, &addresses->addresses[i].address)) { errors_found = true; } gpr_free(part_str); if (errors_found) break; addresses->addresses[i].is_balancer = lb_enabled; addresses->addresses[i].balancer_name = balancer_names_parts.count > 0 ? grpc_dump_slice(balancer_names_parts.slices[i], GPR_DUMP_ASCII) : NULL; } grpc_slice_buffer_destroy_internal(exec_ctx, &path_parts); grpc_slice_buffer_destroy_internal(exec_ctx, &balancer_names_parts); grpc_slice_unref(path_slice); if (errors_found) { grpc_lb_addresses_destroy(exec_ctx, addresses); return NULL; } // Instantiate resolver. fake_resolver* r = gpr_malloc(sizeof(fake_resolver)); memset(r, 0, sizeof(*r)); r->channel_args = grpc_channel_args_copy(args->args); r->addresses = addresses; gpr_mu_init(&r->mu); grpc_resolver_init(&r->base, &fake_resolver_vtable); return &r->base; }
/* 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; 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; 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); gpr_timespec deadline = use_service_config ? gpr_inf_future(GPR_CLOCK_MONOTONIC) : five_seconds_from_now(); 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), 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->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.send_message = request_payload; 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 = &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.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.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); grpc_slice_unref(details); grpc_call_unref(c); grpc_call_unref(s); if (args != NULL) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, args); grpc_exec_ctx_finish(&exec_ctx); } cq_verifier_destroy(cqv); end_test(&f); config.tear_down_data(&f); }
/* Client sends a request with payload, server reads then returns status. */ static void test_invoke_request_with_payload(grpc_end2end_test_config config) { grpc_call *c; grpc_call *s; grpc_slice request_payload_slice1 = grpc_slice_from_copied_string("hello world"); grpc_byte_buffer *request_payload1 = grpc_raw_byte_buffer_create(&request_payload_slice1, 1); grpc_slice request_payload_slice2 = grpc_slice_from_copied_string("abc123"); grpc_byte_buffer *request_payload2 = grpc_raw_byte_buffer_create(&request_payload_slice2, 1); grpc_end2end_test_fixture f = begin_test(config, "test_invoke_request_with_payload", NULL, NULL); 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_byte_buffer *request_payload_recv1 = NULL; grpc_byte_buffer *request_payload_recv2 = NULL; grpc_call_details call_details; grpc_status_code status; grpc_call_error error; grpc_slice details = grpc_empty_slice(); int was_cancelled = 2; gpr_timespec deadline = five_seconds_from_now(); c = grpc_channel_create_call( f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, grpc_slice_from_static_string("/foo"), get_host_override_slice("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 = 0; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); memset(ops, 0, sizeof(ops)); op = ops; 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++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( f.server, &s, &call_details, &request_metadata_recv, f.cq, f.cq, tag(101))); CQ_EXPECT_COMPLETION(cqv, tag(1), true); /* send message is buffered */ CQ_EXPECT_COMPLETION(cqv, tag(101), true); cq_verify(cqv); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload1; op->flags = GRPC_WRITE_BUFFER_HINT; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(3), NULL); GPR_ASSERT(GRPC_CALL_OK == error); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_INITIAL_METADATA; op->data.send_initial_metadata.count = 0; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* recv message should not succeed yet - it's buffered at the client still */ memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &request_payload_recv1; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(103), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(2), true); CQ_EXPECT_COMPLETION(cqv, tag(3), true); CQ_EXPECT_COMPLETION(cqv, tag(102), true); cq_verify(cqv); /* send another message, this time not buffered */ memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message.send_message = request_payload2; op->flags = 0; op++; error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(4), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* now the first send should match up with the first recv */ CQ_EXPECT_COMPLETION(cqv, tag(103), true); CQ_EXPECT_COMPLETION(cqv, tag(4), true); cq_verify(cqv); /* and the next recv should be ready immediately also */ memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message.recv_message = &request_payload_recv2; op++; error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(104), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(104), true); cq_verify(cqv); memset(ops, 0, sizeof(ops)); op = ops; op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; 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(4), NULL); memset(ops, 0, sizeof(ops)); op = ops; 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_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(105), NULL); GPR_ASSERT(GRPC_CALL_OK == error); CQ_EXPECT_COMPLETION(cqv, tag(105), 1); CQ_EXPECT_COMPLETION(cqv, tag(4), 1); cq_verify(cqv); GPR_ASSERT(status == GRPC_STATUS_OK); GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); validate_host_override_string("foo.test.google.fr:1234", call_details.host, config); GPR_ASSERT(was_cancelled == 0); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world")); GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123")); 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_call_unref(c); grpc_call_unref(s); cq_verifier_destroy(cqv); grpc_byte_buffer_destroy(request_payload1); grpc_byte_buffer_destroy(request_payload_recv1); grpc_byte_buffer_destroy(request_payload2); grpc_byte_buffer_destroy(request_payload_recv2); end_test(&f); config.tear_down_data(&f); }
static void on_writable(grpc_exec_ctx *exec_ctx, void *acp, grpc_error *error) { async_connect *ac = acp; int so_error = 0; socklen_t so_error_size; int err; int done; grpc_endpoint **ep = ac->ep; grpc_closure *closure = ac->closure; grpc_fd *fd; GRPC_ERROR_REF(error); if (grpc_tcp_trace) { const char *str = grpc_error_string(error); gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s", ac->addr_str, str); } gpr_mu_lock(&ac->mu); GPR_ASSERT(ac->fd); fd = ac->fd; ac->fd = NULL; gpr_mu_unlock(&ac->mu); grpc_timer_cancel(exec_ctx, &ac->alarm); gpr_mu_lock(&ac->mu); if (error != GRPC_ERROR_NONE) { error = grpc_error_set_str(error, GRPC_ERROR_STR_OS_ERROR, grpc_slice_from_static_string("Timeout occurred")); goto finish; } do { so_error_size = sizeof(so_error); err = getsockopt(grpc_fd_wrapped_fd(fd), SOL_SOCKET, SO_ERROR, &so_error, &so_error_size); } while (err < 0 && errno == EINTR); if (err < 0) { error = GRPC_OS_ERROR(errno, "getsockopt"); goto finish; } switch (so_error) { case 0: grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); *ep = grpc_tcp_client_create_from_fd(exec_ctx, fd, ac->channel_args, ac->addr_str); fd = NULL; break; case ENOBUFS: /* We will get one of these errors if we have run out of memory in the kernel for the data structures allocated when you connect a socket. If this happens it is very likely that if we wait a little bit then try again the connection will work (since other programs or this program will close their network connections and free up memory). This does _not_ indicate that there is anything wrong with the server we are connecting to, this is a local problem. If you are looking at this code, then chances are that your program or another program on the same computer opened too many network connections. The "easy" fix: don't do that! */ gpr_log(GPR_ERROR, "kernel out of buffers"); gpr_mu_unlock(&ac->mu); grpc_fd_notify_on_write(exec_ctx, fd, &ac->write_closure); return; case ECONNREFUSED: /* This error shouldn't happen for anything other than connect(). */ error = GRPC_OS_ERROR(so_error, "connect"); break; default: /* We don't really know which syscall triggered the problem here, so punt by reporting getsockopt(). */ error = GRPC_OS_ERROR(so_error, "getsockopt(SO_ERROR)"); break; } finish: if (fd != NULL) { grpc_pollset_set_del_fd(exec_ctx, ac->interested_parties, fd); grpc_fd_orphan(exec_ctx, fd, NULL, NULL, "tcp_client_orphan"); fd = NULL; } done = (--ac->refs == 0); gpr_mu_unlock(&ac->mu); if (error != GRPC_ERROR_NONE) { char *error_descr; grpc_slice str; bool ret = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &str); GPR_ASSERT(ret); char *desc = grpc_slice_to_c_string(str); gpr_asprintf(&error_descr, "Failed to connect to remote host: %s", desc); error = grpc_error_set_str(error, GRPC_ERROR_STR_DESCRIPTION, grpc_slice_from_copied_string(error_descr)); gpr_free(error_descr); gpr_free(desc); error = grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(ac->addr_str)); } if (done) { gpr_mu_destroy(&ac->mu); gpr_free(ac->addr_str); grpc_channel_args_destroy(exec_ctx, ac->channel_args); gpr_free(ac); } grpc_closure_sched(exec_ctx, closure, error); }