static void test_ping(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); cq_verifier *cqv = cq_verifier_create(f.cq); grpc_connectivity_state state = GRPC_CHANNEL_IDLE; int i; config.init_client(&f, NULL, NULL); config.init_server(&f, NULL); grpc_channel_ping(f.client, f.cq, tag(0), NULL); CQ_EXPECT_COMPLETION(cqv, tag(0), 0); /* check that we're still in idle, and start connecting */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == GRPC_CHANNEL_IDLE); /* we'll go through some set of transitions (some might be missed), until READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(99)); CQ_EXPECT_COMPLETION(cqv, tag(99), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_TRANSIENT_FAILURE); } for (i = 1; i <= 5; i++) { grpc_channel_ping(f.client, f.cq, tag(i), NULL); CQ_EXPECT_COMPLETION(cqv, tag(i), 1); cq_verify(cqv); } grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1); cq_verify(cqv); /* cleanup server */ grpc_server_destroy(f.server); grpc_channel_destroy(f.client); grpc_completion_queue_shutdown(f.cq); grpc_completion_queue_destroy(f.cq); config.tear_down_data(&f); cq_verifier_destroy(cqv); }
// Needs to be called under global_connection_poolling_mu static void grpc_rb_channel_try_register_connection_polling( bg_watched_channel* bg) { grpc_connectivity_state conn_state; watch_state_op* op = NULL; GPR_ASSERT(channel_polling_thread_started || abort_channel_polling); if (bg->refcount == 0) { GPR_ASSERT(bg->channel_destroyed); bg_watched_channel_list_free_and_remove(bg); return; } GPR_ASSERT(bg->refcount == 1); if (bg->channel_destroyed || abort_channel_polling) { return; } conn_state = grpc_channel_check_connectivity_state(bg->channel, 0); if (conn_state == GRPC_CHANNEL_SHUTDOWN) { return; } GPR_ASSERT(bg_watched_channel_list_lookup(bg)); // prevent bg from being free'd by GC while background thread is watching it bg->refcount++; op = gpr_zalloc(sizeof(watch_state_op)); op->op_type = CONTINUOUS_WATCH; op->op.continuous_watch_callback_args.bg = bg; grpc_channel_watch_connectivity_state(bg->channel, conn_state, gpr_inf_future(GPR_CLOCK_REALTIME), channel_polling_cq, op); }
// Either start polling channel connection state or signal that it's free to // destroy. // Not safe to call while a channel's connection state is polled. static void grpc_rb_channel_try_register_connection_polling( grpc_rb_channel *wrapper) { grpc_connectivity_state conn_state; gpr_timespec sleep_time = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_millis(20, GPR_TIMESPAN)); GPR_ASSERT(wrapper); GPR_ASSERT(wrapper->wrapped); gpr_mu_lock(&wrapper->channel_mu); if (wrapper->request_safe_destroy) { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); return; } gpr_mu_lock(&global_connection_polling_mu); conn_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); if (conn_state != wrapper->current_connectivity_state) { wrapper->current_connectivity_state = conn_state; gpr_cv_broadcast(&wrapper->channel_cv); } // avoid posting work to the channel polling cq if it's been shutdown if (!abort_channel_polling && conn_state != GRPC_CHANNEL_SHUTDOWN) { grpc_channel_watch_connectivity_state( wrapper->wrapped, conn_state, sleep_time, channel_polling_cq, wrapper); } else { wrapper->safe_to_destroy = 1; gpr_cv_broadcast(&wrapper->channel_cv); } gpr_mu_unlock(&global_connection_polling_mu); gpr_mu_unlock(&wrapper->channel_mu); }
static void chttp2_init_client_micro_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { micro_fullstack_fixture_data *ffd = f->fixture_data; grpc_connectivity_state conn_state; grpc_connected_subchannel *connected; char *ipv4_localaddr; gpr_asprintf(&ipv4_localaddr, "ipv4:%s", ffd->localaddr); ffd->master_channel = channel_create(ipv4_localaddr, client_args, &ffd->sniffed_subchannel); gpr_free(ipv4_localaddr); gpr_log(GPR_INFO, "MASTER CHANNEL %p ", ffd->master_channel); /* the following will block. That's ok for this test */ conn_state = grpc_channel_check_connectivity_state(ffd->master_channel, 1 /* try to connect */); GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE); /* here sniffed_subchannel should be ready to use */ GPR_ASSERT(conn_state == GRPC_CHANNEL_IDLE); GPR_ASSERT(ffd->sniffed_subchannel != NULL); connected = connect_subchannel(ffd->sniffed_subchannel); f->client = grpc_client_uchannel_create(ffd->sniffed_subchannel, client_args); grpc_client_uchannel_set_connected_subchannel(f->client, connected); gpr_log(GPR_INFO, "CHANNEL WRAPPING SUBCHANNEL: %p(%p)", f->client, ffd->sniffed_subchannel); GPR_ASSERT(f->client); }
static void test_ping() { grpc_channel *client; request_data rdata; servers_fixture *f; cq_verifier *cqv; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; const size_t num_servers = 1; int i; rdata.call_details = gpr_malloc(sizeof(grpc_call_details) * num_servers); f = setup_servers("127.0.0.1", &rdata, num_servers); cqv = cq_verifier_create(f->cq); client = create_client(f); grpc_channel_ping(client, f->cq, tag(0), NULL); cq_expect_completion(cqv, tag(0), 0); /* check that we're still in idle, and start connecting */ GPR_ASSERT(grpc_channel_check_connectivity_state(client, 1) == GRPC_CHANNEL_IDLE); /* we'll go through some set of transitions (some might be missed), until READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f->cq, tag(99)); cq_expect_completion(cqv, tag(99), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(client, 0); GPR_ASSERT(state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_TRANSIENT_FAILURE); } for (i = 1; i <= 5; i++) { grpc_channel_ping(client, f->cq, tag(i), NULL); cq_expect_completion(cqv, tag(i), 1); cq_verify(cqv); } gpr_free(rdata.call_details); grpc_channel_destroy(client); teardown_servers(f); cq_verifier_destroy(cqv); }
static void test_get_channel_info() { grpc_channel *channel = grpc_insecure_channel_create("ipv4:127.0.0.1:1234", NULL, NULL); // Ensures that resolver returns. grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); // First, request no fields. This is a no-op. grpc_channel_info channel_info; memset(&channel_info, 0, sizeof(channel_info)); grpc_channel_get_info(channel, &channel_info); // Request LB policy name. char *lb_policy_name = NULL; channel_info.lb_policy_name = &lb_policy_name; grpc_channel_get_info(channel, &channel_info); GPR_ASSERT(lb_policy_name != NULL); GPR_ASSERT(strcmp(lb_policy_name, "pick_first") == 0); gpr_free(lb_policy_name); // Request service config, which does not exist, so we'll get nothing back. memset(&channel_info, 0, sizeof(channel_info)); char *service_config_json = "dummy_string"; channel_info.service_config_json = &service_config_json; grpc_channel_get_info(channel, &channel_info); GPR_ASSERT(service_config_json == NULL); // Recreate the channel such that it has a service config. grpc_channel_destroy(channel); grpc_arg arg; arg.type = GRPC_ARG_STRING; arg.key = GRPC_ARG_SERVICE_CONFIG; arg.value.string = "{\"loadBalancingPolicy\": \"ROUND_ROBIN\"}"; grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1); channel = grpc_insecure_channel_create("ipv4:127.0.0.1:1234", args, NULL); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_args_destroy(&exec_ctx, args); grpc_exec_ctx_finish(&exec_ctx); } // Ensures that resolver returns. grpc_channel_check_connectivity_state(channel, true /* try_to_connect */); // Now request the service config again. grpc_channel_get_info(channel, &channel_info); GPR_ASSERT(service_config_json != NULL); GPR_ASSERT(strcmp(service_config_json, arg.value.string) == 0); gpr_free(service_config_json); // Clean up. grpc_channel_destroy(channel); }
static void* get_state_without_gil(void* arg) { get_state_stack* stack = (get_state_stack*)arg; gpr_mu_lock(&global_connection_polling_mu); GPR_ASSERT(abort_channel_polling || channel_polling_thread_started); if (stack->bg->channel_destroyed) { stack->out = GRPC_CHANNEL_SHUTDOWN; } else { stack->out = grpc_channel_check_connectivity_state(stack->bg->channel, stack->try_to_connect); } gpr_mu_unlock(&global_connection_polling_mu); return NULL; }
void create_loop_destroy(void *addr) { for (int i = 0; i < NUM_OUTER_LOOPS; ++i) { grpc_completion_queue *cq = grpc_completion_queue_create(NULL); grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); for (int j = 0; j < NUM_INNER_LOOPS; ++j) { gpr_timespec later_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(DELAY_MILLIS); grpc_connectivity_state state = grpc_channel_check_connectivity_state(chan, 1); grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); gpr_timespec poll_time = GRPC_TIMEOUT_MILLIS_TO_DEADLINE(POLL_MILLIS); GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type == GRPC_OP_COMPLETE); } grpc_channel_destroy(chan); grpc_completion_queue_destroy(cq); } }
/* call-seq: insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'}) creds = ... secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ static VALUE grpc_rb_channel_get_connectivity_state(int argc, VALUE *argv, VALUE self) { VALUE try_to_connect = Qfalse; grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; /* "01" == 0 mandatory args, 1 (try_to_connect) is optional */ rb_scan_args(argc, argv, "01", try_to_connect); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); ch = wrapper->wrapped; if (ch == NULL) { rb_raise(rb_eRuntimeError, "closed!"); return Qnil; } return NUM2LONG( grpc_channel_check_connectivity_state(ch, (int)try_to_connect)); }
/** * Get the connectivity state of the channel * @param bool (optional) try to connect on the channel * @return long The grpc connectivity state */ PHP_METHOD(Channel, getConnectivityState) { wrapped_grpc_channel *channel = Z_WRAPPED_GRPC_CHANNEL_P(getThis()); zend_bool try_to_connect = 0; /* "|b" == 1 optional bool */ #ifndef FAST_ZPP if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &try_to_connect) == FAILURE) { zend_throw_exception(spl_ce_InvalidArgumentException, "getConnectivityState expects a bool", 1); return; } #else ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_BOOL(try_to_connect) ZEND_PARSE_PARAMETERS_END(); #endif RETURN_LONG(grpc_channel_check_connectivity_state(channel->wrapped, (int)try_to_connect)); }
void create_loop_destroy(void *addr) { for (int i = 0; i < NUM_OUTER_LOOPS; ++i) { grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); for (int j = 0; j < NUM_INNER_LOOPS; ++j) { gpr_timespec later_time = grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS); grpc_connectivity_state state = grpc_channel_check_connectivity_state(chan, 1); grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); gpr_timespec poll_time = grpc_timeout_milliseconds_to_deadline(POLL_MILLIS); GPR_ASSERT(grpc_completion_queue_next(cq, poll_time, NULL).type == GRPC_OP_COMPLETE); /* check that the watcher from "watch state" was free'd */ GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); } grpc_channel_destroy(chan); grpc_completion_queue_destroy(cq); } }
void watches_with_short_timeouts(void *addr) { for (int i = 0; i < NUM_OUTER_LOOPS_SHORT_TIMEOUTS; ++i) { grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); grpc_channel *chan = grpc_insecure_channel_create((char *)addr, NULL, NULL); for (int j = 0; j < NUM_INNER_LOOPS_SHORT_TIMEOUTS; ++j) { gpr_timespec later_time = grpc_timeout_milliseconds_to_deadline(DELAY_MILLIS_SHORT_TIMEOUTS); grpc_connectivity_state state = grpc_channel_check_connectivity_state(chan, 0); GPR_ASSERT(state == GRPC_CHANNEL_IDLE); grpc_channel_watch_connectivity_state(chan, state, later_time, cq, NULL); gpr_timespec poll_time = grpc_timeout_milliseconds_to_deadline(POLL_MILLIS_SHORT_TIMEOUTS); grpc_event ev = grpc_completion_queue_next(cq, poll_time, NULL); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); GPR_ASSERT(ev.success == false); /* check that the watcher from "watch state" was free'd */ GPR_ASSERT(grpc_channel_num_external_connectivity_watchers(chan) == 0); } grpc_channel_destroy(chan); grpc_completion_queue_destroy(cq); } }
/* call-seq: insecure_channel = Channel:new("myhost:8080", {'arg1': 'value1'}, :this_channel_is_insecure) creds = ... secure_channel = Channel:new("myhost:443", {'arg1': 'value1'}, creds) Creates channel instances. */ static VALUE grpc_rb_channel_init(int argc, VALUE *argv, VALUE self) { VALUE channel_args = Qnil; VALUE credentials = Qnil; VALUE target = Qnil; grpc_rb_channel *wrapper = NULL; grpc_channel *ch = NULL; grpc_channel_credentials *creds = NULL; char *target_chars = NULL; grpc_channel_args args; MEMZERO(&args, grpc_channel_args, 1); /* "3" == 3 mandatory args */ rb_scan_args(argc, argv, "3", &target, &channel_args, &credentials); TypedData_Get_Struct(self, grpc_rb_channel, &grpc_channel_data_type, wrapper); wrapper->mu_init_done = 0; target_chars = StringValueCStr(target); grpc_rb_hash_convert_to_channel_args(channel_args, &args); if (TYPE(credentials) == T_SYMBOL) { if (id_insecure_channel != SYM2ID(credentials)) { rb_raise(rb_eTypeError, "bad creds symbol, want :this_channel_is_insecure"); return Qnil; } ch = grpc_insecure_channel_create(target_chars, &args, NULL); } else { wrapper->credentials = credentials; creds = grpc_rb_get_wrapped_channel_credentials(credentials); ch = grpc_secure_channel_create(creds, target_chars, &args, NULL); } GPR_ASSERT(ch); wrapper->wrapped = ch; gpr_mu_init(&wrapper->channel_mu); gpr_cv_init(&wrapper->channel_cv); wrapper->mu_init_done = 1; gpr_mu_lock(&wrapper->channel_mu); wrapper->abort_watch_connectivity_state = 0; wrapper->current_connectivity_state = grpc_channel_check_connectivity_state(wrapper->wrapped, 0); wrapper->safe_to_destroy = 0; wrapper->request_safe_destroy = 0; gpr_cv_broadcast(&wrapper->channel_cv); gpr_mu_unlock(&wrapper->channel_mu); grpc_rb_channel_try_register_connection_polling(wrapper); if (args.args != NULL) { xfree(args.args); /* Allocated by grpc_rb_hash_convert_to_channel_args */ } if (ch == NULL) { rb_raise(rb_eRuntimeError, "could not create an rpc channel to target:%s", target_chars); return Qnil; } rb_ivar_set(self, id_target, target); wrapper->wrapped = ch; return self; }
GPR_EXPORT grpc_connectivity_state GPR_CALLTYPE grpcsharp_channel_check_connectivity_state(grpc_channel *channel, int32_t try_to_connect) { return grpc_channel_check_connectivity_state(channel, try_to_connect); }
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { grpc_test_only_set_metadata_hash_seed(0); if (squelch) gpr_set_log_function(dont_log); input_stream inp = {data, data + size}; grpc_resolve_address = my_resolve_address; grpc_tcp_client_connect_impl = my_tcp_client_connect; gpr_now_impl = now_impl; grpc_init(); GPR_ASSERT(g_channel == NULL); GPR_ASSERT(g_server == NULL); bool server_shutdown = false; int pending_server_shutdowns = 0; int pending_channel_watches = 0; int pending_pings = 0; g_active_call = new_call(NULL, ROOT); grpc_completion_queue *cq = grpc_completion_queue_create(NULL); while (!is_eof(&inp) || g_channel != NULL || g_server != NULL || pending_channel_watches > 0 || pending_pings > 0 || g_active_call->type != ROOT || g_active_call->next != g_active_call) { if (is_eof(&inp)) { if (g_channel != NULL) { grpc_channel_destroy(g_channel); g_channel = NULL; } if (g_server != NULL) { if (!server_shutdown) { grpc_server_shutdown_and_notify( g_server, cq, create_validator(assert_success_and_decrement, &pending_server_shutdowns)); server_shutdown = true; pending_server_shutdowns++; } else if (pending_server_shutdowns == 0) { grpc_server_destroy(g_server); g_server = NULL; } } call_state *s = g_active_call; do { if (s->type != PENDING_SERVER && s->call != NULL) { s = destroy_call(s); } else { s = s->next; } } while (s != g_active_call); g_now = gpr_time_add(g_now, gpr_time_from_seconds(1, GPR_TIMESPAN)); } switch (next_byte(&inp)) { // terminate on bad bytes default: end(&inp); break; // tickle completion queue case 0: { grpc_event ev = grpc_completion_queue_next( cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL); switch (ev.type) { case GRPC_OP_COMPLETE: { validator *v = ev.tag; v->validate(v->arg, ev.success); gpr_free(v); break; } case GRPC_QUEUE_TIMEOUT: break; case GRPC_QUEUE_SHUTDOWN: abort(); break; } break; } // increment global time case 1: { g_now = gpr_time_add( g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); break; } // create an insecure channel case 2: { if (g_channel == NULL) { char *target = read_string(&inp); char *target_uri; gpr_asprintf(&target_uri, "dns:%s", target); grpc_channel_args *args = read_args(&inp); g_channel = grpc_insecure_channel_create(target_uri, args, NULL); GPR_ASSERT(g_channel != NULL); grpc_channel_args_destroy(args); gpr_free(target_uri); gpr_free(target); } else { end(&inp); } break; } // destroy a channel case 3: { if (g_channel != NULL) { grpc_channel_destroy(g_channel); g_channel = NULL; } else { end(&inp); } break; } // bring up a server case 4: { if (g_server == NULL) { grpc_channel_args *args = read_args(&inp); g_server = grpc_server_create(args, NULL); GPR_ASSERT(g_server != NULL); grpc_channel_args_destroy(args); grpc_server_register_completion_queue(g_server, cq, NULL); grpc_server_start(g_server); server_shutdown = false; GPR_ASSERT(pending_server_shutdowns == 0); } else { end(&inp); } } // begin server shutdown case 5: { if (g_server != NULL) { grpc_server_shutdown_and_notify( g_server, cq, create_validator(assert_success_and_decrement, &pending_server_shutdowns)); pending_server_shutdowns++; server_shutdown = true; } else { end(&inp); } break; } // cancel all calls if shutdown case 6: { if (g_server != NULL && server_shutdown) { grpc_server_cancel_all_calls(g_server); } else { end(&inp); } break; } // destroy server case 7: { if (g_server != NULL && server_shutdown && pending_server_shutdowns == 0) { grpc_server_destroy(g_server); g_server = NULL; } else { end(&inp); } break; } // check connectivity case 8: { if (g_channel != NULL) { uint8_t try_to_connect = next_byte(&inp); if (try_to_connect == 0 || try_to_connect == 1) { grpc_channel_check_connectivity_state(g_channel, try_to_connect); } else { end(&inp); } } else { end(&inp); } break; } // watch connectivity case 9: { if (g_channel != NULL) { grpc_connectivity_state st = grpc_channel_check_connectivity_state(g_channel, 0); if (st != GRPC_CHANNEL_FATAL_FAILURE) { gpr_timespec deadline = gpr_time_add( gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); grpc_channel_watch_connectivity_state( g_channel, st, deadline, cq, create_validator(validate_connectivity_watch, make_connectivity_watch( deadline, &pending_channel_watches))); pending_channel_watches++; } } else { end(&inp); } break; } // create a call case 10: { bool ok = true; if (g_channel == NULL) ok = false; grpc_call *parent_call = NULL; if (g_active_call->type != ROOT) { if (g_active_call->call == NULL || g_active_call->type == CLIENT) { end(&inp); break; } parent_call = g_active_call->call; } uint32_t propagation_mask = read_uint32(&inp); char *method = read_string(&inp); char *host = read_string(&inp); gpr_timespec deadline = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN)); if (ok) { call_state *cs = new_call(g_active_call, CLIENT); cs->call = grpc_channel_create_call(g_channel, parent_call, propagation_mask, cq, method, host, deadline, NULL); } else { end(&inp); } gpr_free(method); gpr_free(host); break; } // switch the 'current' call case 11: { g_active_call = g_active_call->next; break; } // queue some ops on a call case 12: { if (g_active_call->type == PENDING_SERVER || g_active_call->type == ROOT || g_active_call->call == NULL) { end(&inp); break; } size_t num_ops = next_byte(&inp); if (num_ops > 6) { end(&inp); break; } grpc_op *ops = gpr_malloc(sizeof(grpc_op) * num_ops); bool ok = true; size_t i; grpc_op *op; for (i = 0; i < num_ops; i++) { op = &ops[i]; switch (next_byte(&inp)) { default: /* invalid value */ op->op = (grpc_op_type)-1; ok = false; break; case GRPC_OP_SEND_INITIAL_METADATA: op->op = GRPC_OP_SEND_INITIAL_METADATA; read_metadata(&inp, &op->data.send_initial_metadata.count, &op->data.send_initial_metadata.metadata, g_active_call); break; case GRPC_OP_SEND_MESSAGE: op->op = GRPC_OP_SEND_MESSAGE; op->data.send_message = read_message(&inp); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; break; case GRPC_OP_SEND_STATUS_FROM_SERVER: op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; read_metadata( &inp, &op->data.send_status_from_server.trailing_metadata_count, &op->data.send_status_from_server.trailing_metadata, g_active_call); op->data.send_status_from_server.status = next_byte(&inp); op->data.send_status_from_server.status_details = read_string(&inp); break; case GRPC_OP_RECV_INITIAL_METADATA: op->op = GRPC_OP_RECV_INITIAL_METADATA; op->data.recv_initial_metadata = &g_active_call->recv_initial_metadata; break; case GRPC_OP_RECV_MESSAGE: op->op = GRPC_OP_RECV_MESSAGE; op->data.recv_message = &g_active_call->recv_message; break; case GRPC_OP_RECV_STATUS_ON_CLIENT: op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; op->data.recv_status_on_client.status = &g_active_call->status; op->data.recv_status_on_client.trailing_metadata = &g_active_call->recv_trailing_metadata; op->data.recv_status_on_client.status_details = &g_active_call->recv_status_details; op->data.recv_status_on_client.status_details_capacity = &g_active_call->recv_status_details_capacity; break; case GRPC_OP_RECV_CLOSE_ON_SERVER: op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; op->data.recv_close_on_server.cancelled = &g_active_call->cancelled; break; } op->reserved = NULL; op->flags = read_uint32(&inp); } if (ok) { validator *v = create_validator(finished_batch, g_active_call); g_active_call->pending_ops++; grpc_call_error error = grpc_call_start_batch(g_active_call->call, ops, num_ops, v, NULL); if (error != GRPC_CALL_OK) { v->validate(v->arg, false); gpr_free(v); } } else { end(&inp); } for (i = 0; i < num_ops; i++) { op = &ops[i]; switch (op->op) { case GRPC_OP_SEND_INITIAL_METADATA: break; case GRPC_OP_SEND_MESSAGE: grpc_byte_buffer_destroy(op->data.send_message); break; case GRPC_OP_SEND_STATUS_FROM_SERVER: gpr_free((void *)op->data.send_status_from_server.status_details); break; case GRPC_OP_SEND_CLOSE_FROM_CLIENT: case GRPC_OP_RECV_INITIAL_METADATA: case GRPC_OP_RECV_MESSAGE: case GRPC_OP_RECV_STATUS_ON_CLIENT: case GRPC_OP_RECV_CLOSE_ON_SERVER: break; } } gpr_free(ops); break; } // cancel current call case 13: { if (g_active_call->type != ROOT && g_active_call->call != NULL) { grpc_call_cancel(g_active_call->call, NULL); } else { end(&inp); } break; } // get a calls peer case 14: { if (g_active_call->type != ROOT && g_active_call->call != NULL) { free_non_null(grpc_call_get_peer(g_active_call->call)); } else { end(&inp); } break; } // get a channels target case 15: { if (g_channel != NULL) { free_non_null(grpc_channel_get_target(g_channel)); } else { end(&inp); } break; } // send a ping on a channel case 16: { if (g_channel != NULL) { pending_pings++; grpc_channel_ping(g_channel, cq, create_validator(decrement, &pending_pings), NULL); } else { end(&inp); } break; } // enable a tracer case 17: { char *tracer = read_string(&inp); grpc_tracer_set_enabled(tracer, 1); gpr_free(tracer); break; } // disable a tracer case 18: { char *tracer = read_string(&inp); grpc_tracer_set_enabled(tracer, 0); gpr_free(tracer); break; } // request a server call case 19: { if (g_server == NULL) { end(&inp); break; } call_state *cs = new_call(g_active_call, PENDING_SERVER); cs->pending_ops++; validator *v = create_validator(finished_request_call, cs); grpc_call_error error = grpc_server_request_call(g_server, &cs->call, &cs->call_details, &cs->recv_initial_metadata, cq, cq, v); if (error != GRPC_CALL_OK) { v->validate(v->arg, false); gpr_free(v); } break; } // destroy a call case 20: { if (g_active_call->type != ROOT && g_active_call->type != PENDING_SERVER && g_active_call->call != NULL) { destroy_call(g_active_call); } else { end(&inp); } break; } } } GPR_ASSERT(g_channel == NULL); GPR_ASSERT(g_server == NULL); GPR_ASSERT(g_active_call->type == ROOT); GPR_ASSERT(g_active_call->next == g_active_call); gpr_free(g_active_call); grpc_completion_queue_shutdown(cq); GPR_ASSERT( grpc_completion_queue_next(cq, gpr_inf_past(GPR_CLOCK_REALTIME), NULL) .type == GRPC_QUEUE_SHUTDOWN); grpc_completion_queue_destroy(cq); grpc_shutdown(); return 0; }
/** Returns connection sequence (server indices), which must be freed */ static request_sequences perform_request(servers_fixture *f, grpc_channel *client, request_data *rdata, const test_spec *spec) { grpc_call *c; int s_idx; int *s_valid; grpc_op ops[6]; grpc_op *op; int was_cancelled; size_t i, iter_num; grpc_event ev; int read_tag; int completed_client; const request_sequences sequences = request_sequences_create(spec->num_iters); s_valid = gpr_malloc(sizeof(int) * f->num_servers); for (iter_num = 0; iter_num < spec->num_iters; iter_num++) { cq_verifier *cqv = cq_verifier_create(f->cq); was_cancelled = 2; for (i = 0; i < f->num_servers; i++) { if (spec->kill_at[iter_num][i] != 0) { kill_server(f, i); } else if (spec->revive_at[iter_num][i] != 0) { /* killing takes precedence */ revive_server(f, rdata, i); } } sequences.connections[iter_num] = -1; grpc_metadata_array_init(&rdata->initial_metadata_recv); grpc_metadata_array_init(&rdata->trailing_metadata_recv); for (i = 0; i < f->num_servers; i++) { grpc_call_details_init(&rdata->call_details[i]); } memset(s_valid, 0, f->num_servers * sizeof(int)); grpc_slice host = grpc_slice_from_static_string("foo.test.google.fr"); c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, f->cq, grpc_slice_from_static_string("/foo"), &host, gpr_inf_future(GPR_CLOCK_REALTIME), NULL); GPR_ASSERT(c); completed_client = 0; 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 = &rdata->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 = &rdata->trailing_metadata_recv; op->data.recv_status_on_client.status = &rdata->status; op->data.recv_status_on_client.status_details = &rdata->details; op->flags = 0; op->reserved = NULL; op++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL)); s_idx = -1; while ( (ev = grpc_completion_queue_next( f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL)) .type != GRPC_QUEUE_TIMEOUT) { GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); read_tag = ((int)(intptr_t)ev.tag); const grpc_connectivity_state conn_state = grpc_channel_check_connectivity_state(client, 0); sequences.connectivity_states[iter_num] = conn_state; gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%" PRIuPTR, ev.success, ev.type, read_tag, iter_num); if (ev.success && read_tag >= 1000) { GPR_ASSERT(s_idx == -1); /* only one server must reply */ /* only server notifications for non-shutdown events */ s_idx = read_tag - 1000; s_valid[s_idx] = 1; sequences.connections[iter_num] = s_idx; break; } else if (read_tag == 1) { gpr_log(GPR_DEBUG, "client timed out"); GPR_ASSERT(ev.success); completed_client = 1; } } if (s_idx >= 0) { 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_details = grpc_slice_from_static_string("xyz"); op->data.send_status_from_server.status_details = &status_details; 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++; GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(f->server_calls[s_idx], ops, (size_t)(op - ops), tag(102), NULL)); CQ_EXPECT_COMPLETION(cqv, tag(102), 1); if (!completed_client) { CQ_EXPECT_COMPLETION(cqv, tag(1), 1); } cq_verify(cqv); GPR_ASSERT(rdata->status == GRPC_STATUS_UNIMPLEMENTED); GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->details, "xyz")); GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].method, "/foo")); GPR_ASSERT(0 == grpc_slice_str_cmp(rdata->call_details[s_idx].host, "foo.test.google.fr")); GPR_ASSERT(was_cancelled == 1); grpc_call_unref(f->server_calls[s_idx]); /* ask for the next request on this server */ GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call( f->servers[s_idx], &f->server_calls[s_idx], &rdata->call_details[s_idx], &f->request_metadata_recv[s_idx], f->cq, f->cq, tag(1000 + (int)s_idx))); } else { /* no response from server */ grpc_call_cancel(c, NULL); if (!completed_client) { CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); } } GPR_ASSERT( grpc_completion_queue_next( f->cq, grpc_timeout_milliseconds_to_deadline(RETRY_TIMEOUT), NULL) .type == GRPC_QUEUE_TIMEOUT); grpc_metadata_array_destroy(&rdata->initial_metadata_recv); grpc_metadata_array_destroy(&rdata->trailing_metadata_recv); cq_verifier_destroy(cqv); grpc_call_unref(c); for (i = 0; i < f->num_servers; i++) { grpc_call_details_destroy(&rdata->call_details[i]); } grpc_slice_unref(rdata->details); } gpr_free(s_valid); return sequences; }
int main(int argc, char **argv) { grpc_channel *chan; grpc_call *call; grpc_completion_queue *cq; cq_verifier *cqv; grpc_op ops[6]; grpc_op *op; grpc_metadata_array initial_metadata_recv; grpc_metadata_array trailing_metadata_recv; grpc_status_code status; grpc_call_error error; grpc_slice details; char *peer; grpc_test_init(argc, argv); grpc_init(); grpc_metadata_array_init(&initial_metadata_recv); grpc_metadata_array_init(&trailing_metadata_recv); chan = grpc_lame_client_channel_create( "lampoon:national", GRPC_STATUS_UNKNOWN, "Rpc sent on a lame channel."); GPR_ASSERT(chan); test_transport_op(chan); GPR_ASSERT(GRPC_CHANNEL_SHUTDOWN == grpc_channel_check_connectivity_state(chan, 0)); cq = grpc_completion_queue_create(NULL); grpc_slice host = grpc_slice_from_static_string("anywhere"); call = grpc_channel_create_call(chan, NULL, GRPC_PROPAGATE_DEFAULTS, cq, grpc_slice_from_static_string("/Foo"), &host, grpc_timeout_seconds_to_deadline(100), NULL); GPR_ASSERT(call); cqv = cq_verifier_create(cq); 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_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(call, ops, (size_t)(op - ops), tag(1), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* the call should immediately fail */ CQ_EXPECT_COMPLETION(cqv, tag(1), 0); cq_verify(cqv); 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++; error = grpc_call_start_batch(call, ops, (size_t)(op - ops), tag(2), NULL); GPR_ASSERT(GRPC_CALL_OK == error); /* the call should immediately fail */ CQ_EXPECT_COMPLETION(cqv, tag(2), 1); cq_verify(cqv); peer = grpc_call_get_peer(call); GPR_ASSERT(strcmp(peer, "lampoon:national") == 0); gpr_free(peer); grpc_call_destroy(call); grpc_channel_destroy(chan); cq_verifier_destroy(cqv); grpc_completion_queue_destroy(cq); grpc_metadata_array_destroy(&initial_metadata_recv); grpc_metadata_array_destroy(&trailing_metadata_recv); grpc_slice_unref(details); grpc_shutdown(); return 0; }
static void test_connectivity(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(NULL, NULL); grpc_connectivity_state state; cq_verifier *cqv = cq_verifier_create(f.cq); child_events ce; gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; config.init_client(&f, NULL); ce.channel = f.client; ce.cq = f.cq; gpr_event_init(&ce.started); gpr_thd_options_set_joinable(&thdopt); GPR_ASSERT(gpr_thd_new(&thdid, child_thread, &ce, &thdopt)); gpr_event_wait(&ce.started, gpr_inf_future(GPR_CLOCK_MONOTONIC)); /* channels should start life in IDLE, and stay there */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); gpr_sleep_until(GRPC_TIMEOUT_MILLIS_TO_DEADLINE(100)); GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 0) == GRPC_CHANNEL_IDLE); /* start watching for a change */ gpr_log(GPR_DEBUG, "watching"); grpc_channel_watch_connectivity_state( f.client, GRPC_CHANNEL_IDLE, gpr_now(GPR_CLOCK_MONOTONIC), f.cq, tag(1)); /* eventually the child thread completion should trigger */ gpr_thd_join(thdid); /* check that we're still in idle, and start connecting */ GPR_ASSERT(grpc_channel_check_connectivity_state(f.client, 1) == GRPC_CHANNEL_IDLE); /* start watching for a change */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_IDLE, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(2)); /* and now the watch should trigger */ cq_expect_completion(cqv, tag(2), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); /* quickly followed by a transition to TRANSIENT_FAILURE */ grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_CONNECTING, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(3)); cq_expect_completion(cqv, tag(3), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING); gpr_log(GPR_DEBUG, "*** STARTING SERVER ***"); /* now let's bring up a server to connect to */ config.init_server(&f, NULL); gpr_log(GPR_DEBUG, "*** STARTED SERVER ***"); /* we'll go through some set of transitions (some might be missed), until READY is reached */ while (state != GRPC_CHANNEL_READY) { grpc_channel_watch_connectivity_state( f.client, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(4)); cq_expect_completion(cqv, tag(4), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_TRANSIENT_FAILURE); } /* bring down the server again */ /* we should go immediately to TRANSIENT_FAILURE */ gpr_log(GPR_DEBUG, "*** SHUTTING DOWN SERVER ***"); grpc_channel_watch_connectivity_state(f.client, GRPC_CHANNEL_READY, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), f.cq, tag(5)); grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead)); cq_expect_completion(cqv, tag(5), 1); cq_expect_completion(cqv, tag(0xdead), 1); cq_verify(cqv); state = grpc_channel_check_connectivity_state(f.client, 0); GPR_ASSERT(state == GRPC_CHANNEL_TRANSIENT_FAILURE || state == GRPC_CHANNEL_CONNECTING || state == GRPC_CHANNEL_IDLE); /* cleanup server */ grpc_server_destroy(f.server); gpr_log(GPR_DEBUG, "*** SHUTDOWN SERVER ***"); grpc_channel_destroy(f.client); grpc_completion_queue_shutdown(f.cq); grpc_completion_queue_destroy(f.cq); config.tear_down_data(&f); cq_verifier_destroy(cqv); }
// This test launches a minimal TLS server on a separate thread and then // establishes a TLS handshake via the core library to the server. The TLS // server validates ALPN aspects of the handshake and supplies the protocol // specified in the server_alpn_preferred argument to the client. static bool client_ssl_test(char *server_alpn_preferred) { bool success = true; grpc_init(); // Find a port we can bind to. Retries added to handle flakes in port server // and port picking. int port = -1; int server_socket = -1; int socket_retries = 10; while (server_socket == -1 && socket_retries-- > 0) { port = grpc_pick_unused_port_or_die(); server_socket = create_socket(port); if (server_socket == -1) { sleep(1); } } GPR_ASSERT(server_socket > 0); // Launch the TLS server thread. gpr_thd_options thdopt = gpr_thd_options_default(); gpr_thd_id thdid; gpr_thd_options_set_joinable(&thdopt); server_args args = {.socket = server_socket, .alpn_preferred = server_alpn_preferred}; GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &args, &thdopt)); // Load key pair and establish client SSL credentials. grpc_ssl_pem_key_cert_pair pem_key_cert_pair; gpr_slice ca_slice, cert_slice, key_slice; GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); const char *ca_cert = (const char *)GPR_SLICE_START_PTR(ca_slice); pem_key_cert_pair.private_key = (const char *)GPR_SLICE_START_PTR(key_slice); pem_key_cert_pair.cert_chain = (const char *)GPR_SLICE_START_PTR(cert_slice); grpc_channel_credentials *ssl_creds = grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL); // Establish a channel pointing at the TLS server. Since the gRPC runtime is // lazy, this won't necessarily establish a connection yet. char *target; gpr_asprintf(&target, "127.0.0.1:%d", port); grpc_arg ssl_name_override = {GRPC_ARG_STRING, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, {"foo.test.google.fr"}}; grpc_channel_args grpc_args; grpc_args.num_args = 1; grpc_args.args = &ssl_name_override; grpc_channel *channel = grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL); GPR_ASSERT(channel); gpr_free(target); // Initially the channel will be idle, the // grpc_channel_check_connectivity_state triggers an attempt to connect. GPR_ASSERT(grpc_channel_check_connectivity_state( channel, 1 /* try_to_connect */) == GRPC_CHANNEL_IDLE); // Wait a bounded number of times for the channel to be ready. When the // channel is ready, the initial TLS handshake will have successfully // completed and we know that the client's ALPN list satisfied the server. int retries = 10; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; grpc_completion_queue *cq = grpc_completion_queue_create(NULL); while (state != GRPC_CHANNEL_READY && retries-- > 0) { grpc_channel_watch_connectivity_state( channel, state, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(3), cq, NULL); gpr_timespec cq_deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5); grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); state = grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */); } grpc_completion_queue_destroy(cq); if (retries < 0) { success = false; } grpc_channel_destroy(channel); grpc_channel_credentials_release(ssl_creds); gpr_slice_unref(cert_slice); gpr_slice_unref(key_slice); gpr_slice_unref(ca_slice); gpr_thd_join(thdid); grpc_shutdown(); return success; }