void grpc_server_start(grpc_server *server) { listener *l; size_t i; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GRPC_API_TRACE("grpc_server_start(server=%p)", 1, (server)); server->started = true; size_t pollset_count = 0; server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); for (i = 0; i < server->cq_count; i++) { if (!grpc_cq_is_non_listening_server_cq(server->cqs[i])) { server->pollsets[pollset_count++] = grpc_cq_pollset(server->cqs[i]); } } request_matcher_init(&server->unregistered_request_matcher, server->max_requested_calls, server); for (registered_method *rm = server->registered_methods; rm; rm = rm->next) { request_matcher_init(&rm->request_matcher, server->max_requested_calls, server); } for (l = server->listeners; l; l = l->next) { l->start(&exec_ctx, server, l->arg, server->pollsets, pollset_count); } grpc_exec_ctx_finish(&exec_ctx); }
void grpc_call_set_completion_queue(grpc_exec_ctx *exec_ctx, grpc_call *call, grpc_completion_queue *cq) { GPR_ASSERT(cq); call->cq = cq; GRPC_CQ_INTERNAL_REF(cq, "bind"); grpc_call_stack_set_pollset(exec_ctx, CALL_STACK_FROM_CALL(call), grpc_cq_pollset(cq)); }
static void server_setup_transport(void *ts, grpc_transport *transport) { grpc_end2end_test_fixture *f = ts; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_endpoint_pair *sfd = f->fixture_data; grpc_endpoint_add_to_pollset(&exec_ctx, sfd->server, grpc_cq_pollset(f->cq)); grpc_server_setup_transport(&exec_ctx, f->server, transport, NULL, grpc_server_get_channel_args(f->server)); grpc_exec_ctx_finish(&exec_ctx); }
static void partly_done(grpc_exec_ctx *exec_ctx, state_watcher *w, bool due_to_completion, grpc_error *error) { if (due_to_completion) { grpc_timer_cancel(exec_ctx, &w->alarm); } else { grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element( grpc_channel_get_channel_stack(w->channel)); grpc_client_channel_watch_connectivity_state( exec_ctx, client_channel_elem, grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)), NULL, &w->on_complete, NULL); } gpr_mu_lock(&w->mu); if (due_to_completion) { if (GRPC_TRACER_ON(grpc_trace_operation_failures)) { GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); } GRPC_ERROR_UNREF(error); error = GRPC_ERROR_NONE; } else { if (error == GRPC_ERROR_NONE) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Timed out waiting for connection state change"); } else if (error == GRPC_ERROR_CANCELLED) { error = GRPC_ERROR_NONE; } } switch (w->phase) { case WAITING: GRPC_ERROR_REF(error); w->error = error; w->phase = READY_TO_CALL_BACK; break; case READY_TO_CALL_BACK: if (error != GRPC_ERROR_NONE) { GPR_ASSERT(!due_to_completion); GRPC_ERROR_UNREF(w->error); GRPC_ERROR_REF(error); w->error = error; } w->phase = CALLING_BACK_AND_FINISHED; grpc_cq_end_op(exec_ctx, w->cq, w->tag, w->error, finished_completion, w, &w->completion_storage); break; case CALLING_BACK_AND_FINISHED: GPR_UNREACHABLE_CODE(return ); break; } gpr_mu_unlock(&w->mu); GRPC_ERROR_UNREF(error); }
void grpc_server_start(grpc_server *server) { listener *l; size_t i; server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); for (i = 0; i < server->cq_count; i++) { server->pollsets[i] = grpc_cq_pollset(server->cqs[i]); } for (l = server->listeners; l; l = l->next) { l->start(server, l->arg, server->pollsets, server->cq_count); } }
void grpc_channel_watch_connectivity_state( grpc_channel *channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue *cq, void *tag) { grpc_channel_element *client_channel_elem = grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; state_watcher *w = (state_watcher *)gpr_malloc(sizeof(*w)); GRPC_API_TRACE( "grpc_channel_watch_connectivity_state(" "channel=%p, last_observed_state=%d, " "deadline=gpr_timespec { tv_sec: %" PRId64 ", tv_nsec: %d, clock_type: %d }, " "cq=%p, tag=%p)", 7, (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, cq, tag)); GPR_ASSERT(grpc_cq_begin_op(cq, tag)); gpr_mu_init(&w->mu); GRPC_CLOSURE_INIT(&w->on_complete, watch_complete, w, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&w->on_timeout, timeout_complete, w, grpc_schedule_on_exec_ctx); w->phase = WAITING; w->state = last_observed_state; w->cq = cq; w->tag = tag; w->channel = channel; w->error = NULL; watcher_timer_init_arg *wa = (watcher_timer_init_arg *)gpr_malloc(sizeof(watcher_timer_init_arg)); wa->w = w; wa->deadline = deadline; GRPC_CLOSURE_INIT(&w->watcher_timer_init, watcher_timer_init, wa, grpc_schedule_on_exec_ctx); if (client_channel_elem->filter == &grpc_client_channel_filter) { GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); grpc_client_channel_watch_connectivity_state( &exec_ctx, client_channel_elem, grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &w->state, &w->on_complete, &w->watcher_timer_init); } else { abort(); } grpc_exec_ctx_finish(&exec_ctx); }
void grpc_server_start(grpc_server *server) { listener *l; size_t i; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; server->pollsets = gpr_malloc(sizeof(grpc_pollset *) * server->cq_count); for (i = 0; i < server->cq_count; i++) { server->pollsets[i] = grpc_cq_pollset(server->cqs[i]); } for (l = server->listeners; l; l = l->next) { l->start(&exec_ctx, server, l->arg, server->pollsets, server->cq_count); } grpc_exec_ctx_finish(&exec_ctx); }
void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { grpc_transport_op op; ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); memset(&op, 0, sizeof(op)); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); op.send_ping = &pr->closure; op.bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); top_elem->filter->start_transport_op(&exec_ctx, top_elem, &op); grpc_exec_ctx_finish(&exec_ctx); }
void grpc_channel_ping(grpc_channel *channel, grpc_completion_queue *cq, void *tag, void *reserved) { GRPC_API_TRACE("grpc_channel_ping(channel=%p, cq=%p, tag=%p, reserved=%p)", 4, (channel, cq, tag, reserved)); grpc_transport_op *op = grpc_make_transport_op(NULL); ping_result *pr = gpr_malloc(sizeof(*pr)); grpc_channel_element *top_elem = grpc_channel_stack_element(grpc_channel_get_channel_stack(channel), 0); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; GPR_ASSERT(reserved == NULL); pr->tag = tag; pr->cq = cq; grpc_closure_init(&pr->closure, ping_done, pr); op->send_ping = &pr->closure; op->bind_pollset = grpc_cq_pollset(cq); grpc_cq_begin_op(cq, tag); top_elem->filter->start_transport_op(&exec_ctx, top_elem, op); grpc_exec_ctx_finish(&exec_ctx); }
grpc_transport_setup_result grpc_server_setup_transport( grpc_server *s, grpc_transport *transport, grpc_channel_filter const **extra_filters, size_t num_extra_filters, grpc_mdctx *mdctx) { size_t num_filters = s->channel_filter_count + num_extra_filters + 1; grpc_channel_filter const **filters = gpr_malloc(sizeof(grpc_channel_filter *) * num_filters); size_t i; size_t num_registered_methods; size_t alloc; registered_method *rm; channel_registered_method *crm; grpc_channel *channel; channel_data *chand; grpc_mdstr *host; grpc_mdstr *method; gpr_uint32 hash; gpr_uint32 slots; gpr_uint32 probes; gpr_uint32 max_probes = 0; grpc_transport_setup_result result; for (i = 0; i < s->channel_filter_count; i++) { filters[i] = s->channel_filters[i]; } for (; i < s->channel_filter_count + num_extra_filters; i++) { filters[i] = extra_filters[i - s->channel_filter_count]; } filters[i] = &grpc_connected_channel_filter; for (i = 0; i < s->cq_count; i++) { grpc_transport_add_to_pollset(transport, grpc_cq_pollset(s->cqs[i])); } channel = grpc_channel_create_from_filters(filters, num_filters, s->channel_args, mdctx, 0); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0) ->channel_data; chand->server = s; server_ref(s); chand->channel = channel; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; chand->registered_methods = gpr_malloc(alloc); memset(chand->registered_methods, 0, alloc); for (rm = s->registered_methods; rm; rm = rm->next) { host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host) : NULL; method = grpc_mdstr_from_string(mdctx, rm->method); hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash); for (probes = 0; chand->registered_methods[(hash + probes) % slots] .server_registered_method != NULL; probes++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->host = host; crm->method = method; } chand->registered_method_slots = slots; chand->registered_method_max_probes = max_probes; } result = grpc_connected_channel_bind_transport( grpc_channel_get_channel_stack(channel), transport); gpr_mu_lock(&s->mu); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu); gpr_free(filters); return result; }
void grpc_run_bad_client_test(const char *name, const char *client_payload, size_t client_payload_length, grpc_bad_client_server_side_validator validator) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", name); /* Init grpc */ grpc_init(); /* Create endpoints */ sfd = grpc_iomgr_create_endpoint_pair(65536); /* Create server, completion events */ a.server = grpc_server_create_from_filters(NULL, 0, NULL); a.cq = grpc_completion_queue_create(); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq); grpc_server_start(a.server); grpc_create_chttp2_transport(server_setup_transport, &a, NULL, sfd.server, NULL, 0, grpc_mdctx_create(), 0); /* Bind everything into the same pollset */ grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq)); grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq)); /* Check a ground truth */ GPR_ASSERT(grpc_server_has_open_connections(a.server)); /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); /* Write data */ switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { case GRPC_ENDPOINT_WRITE_DONE: done_write(&a, 1); break; case GRPC_ENDPOINT_WRITE_PENDING: break; case GRPC_ENDPOINT_WRITE_ERROR: done_write(&a, 0); break; } /* Await completion */ GPR_ASSERT( gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); /* Shutdown */ grpc_endpoint_destroy(sfd.client); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); grpc_shutdown(); }
static void enact_send_action(grpc_call *call, send_action sa) { grpc_ioreq_data data; grpc_call_op op; size_t i; gpr_uint32 flags = 0; char status_str[GPR_LTOA_MIN_BUFSIZE]; switch (sa) { case SEND_NOTHING: abort(); break; case SEND_BUFFERED_INITIAL_METADATA: flags |= GRPC_WRITE_BUFFER_HINT; /* fallthrough */ case SEND_INITIAL_METADATA: data = call->request_data[GRPC_IOREQ_SEND_INITIAL_METADATA]; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; send_metadata(call, grpc_mdelem_from_string_and_buffer( call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length)); } op.type = GRPC_SEND_START; op.dir = GRPC_CALL_DOWN; op.flags = flags; op.data.start.pollset = grpc_cq_pollset(call->cq); op.done_cb = finish_start_step; op.user_data = call; grpc_call_execute_op(call, &op); break; case SEND_BUFFERED_MESSAGE: flags |= GRPC_WRITE_BUFFER_HINT; /* fallthrough */ case SEND_MESSAGE: data = call->request_data[GRPC_IOREQ_SEND_MESSAGE]; op.type = GRPC_SEND_MESSAGE; op.dir = GRPC_CALL_DOWN; op.flags = flags; op.data.message = data.send_message; op.done_cb = finish_write_step; op.user_data = call; grpc_call_execute_op(call, &op); break; case SEND_TRAILING_METADATA_AND_FINISH: /* send trailing metadata */ data = call->request_data[GRPC_IOREQ_SEND_TRAILING_METADATA]; for (i = 0; i < data.send_metadata.count; i++) { const grpc_metadata *md = &data.send_metadata.metadata[i]; send_metadata(call, grpc_mdelem_from_string_and_buffer( call->metadata_context, md->key, (const gpr_uint8 *)md->value, md->value_length)); } /* send status */ /* TODO(ctiller): cache common status values */ data = call->request_data[GRPC_IOREQ_SEND_STATUS]; gpr_ltoa(data.send_status.code, status_str); send_metadata( call, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_status.details) { send_metadata( call, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref(grpc_channel_get_message_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, data.send_status.details))); } /* fallthrough: see choose_send_action for details */ case SEND_FINISH: op.type = GRPC_SEND_FINISH; op.dir = GRPC_CALL_DOWN; op.flags = 0; op.done_cb = finish_finish_step; op.user_data = call; grpc_call_execute_op(call, &op); break; } }
void grpc_run_bad_client_test(grpc_bad_client_server_side_validator validator, const char *client_payload, size_t client_payload_length, gpr_uint32 flags) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; char *hex; grpc_transport *transport; grpc_mdctx *mdctx = grpc_mdctx_create(); gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", hex); gpr_free(hex); /* Init grpc */ grpc_init(); /* Create endpoints */ sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); /* Create server, completion events */ a.server = grpc_server_create_from_filters(NULL, 0, NULL); a.cq = grpc_completion_queue_create(NULL); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); a.validator = validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); grpc_server_start(a.server); transport = grpc_create_chttp2_transport(NULL, sfd.server, mdctx, 0); server_setup_transport(&a, transport, mdctx); grpc_chttp2_transport_start_reading(transport, NULL, 0); /* Bind everything into the same pollset */ grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(a.cq)); grpc_endpoint_add_to_pollset(sfd.server, grpc_cq_pollset(a.cq)); /* Check a ground truth */ GPR_ASSERT(grpc_server_has_open_connections(a.server)); /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); /* Write data */ switch (grpc_endpoint_write(sfd.client, &slice, 1, done_write, &a)) { case GRPC_ENDPOINT_WRITE_DONE: done_write(&a, 1); break; case GRPC_ENDPOINT_WRITE_PENDING: break; case GRPC_ENDPOINT_WRITE_ERROR: done_write(&a, 0); break; } /* Await completion */ GPR_ASSERT( gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); if (flags & GRPC_BAD_CLIENT_DISCONNECT) { grpc_endpoint_destroy(sfd.client); sfd.client = NULL; } GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); /* Shutdown */ if (sfd.client) { grpc_endpoint_destroy(sfd.client); } grpc_server_shutdown_and_notify(a.server, a.cq, NULL); GPR_ASSERT(grpc_completion_queue_pluck( a.cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL) .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); grpc_shutdown(); }
void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s, grpc_transport *transport, grpc_channel_filter const **extra_filters, size_t num_extra_filters, const grpc_channel_args *args) { size_t num_filters = s->channel_filter_count + num_extra_filters + 1; grpc_channel_filter const **filters = gpr_malloc(sizeof(grpc_channel_filter *) * num_filters); size_t i; size_t num_registered_methods; size_t alloc; registered_method *rm; channel_registered_method *crm; grpc_channel *channel; channel_data *chand; grpc_mdstr *host; grpc_mdstr *method; uint32_t hash; size_t slots; uint32_t probes; uint32_t max_probes = 0; grpc_transport_op op; for (i = 0; i < s->channel_filter_count; i++) { filters[i] = s->channel_filters[i]; } for (; i < s->channel_filter_count + num_extra_filters; i++) { filters[i] = extra_filters[i - s->channel_filter_count]; } filters[i] = &grpc_connected_channel_filter; for (i = 0; i < s->cq_count; i++) { memset(&op, 0, sizeof(op)); op.bind_pollset = grpc_cq_pollset(s->cqs[i]); grpc_transport_perform_op(exec_ctx, transport, &op); } channel = grpc_channel_create_from_filters(exec_ctx, NULL, filters, num_filters, args, 0); chand = (channel_data *)grpc_channel_stack_element( grpc_channel_get_channel_stack(channel), 0)->channel_data; chand->server = s; server_ref(s); chand->channel = channel; num_registered_methods = 0; for (rm = s->registered_methods; rm; rm = rm->next) { num_registered_methods++; } /* build a lookup table phrased in terms of mdstr's in this channels context to quickly find registered methods */ if (num_registered_methods > 0) { slots = 2 * num_registered_methods; alloc = sizeof(channel_registered_method) * slots; chand->registered_methods = gpr_malloc(alloc); memset(chand->registered_methods, 0, alloc); for (rm = s->registered_methods; rm; rm = rm->next) { host = rm->host ? grpc_mdstr_from_string(rm->host) : NULL; method = grpc_mdstr_from_string(rm->method); hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash); for (probes = 0; chand->registered_methods[(hash + probes) % slots] .server_registered_method != NULL; probes++) ; if (probes > max_probes) max_probes = probes; crm = &chand->registered_methods[(hash + probes) % slots]; crm->server_registered_method = rm; crm->host = host; crm->method = method; } GPR_ASSERT(slots <= UINT32_MAX); chand->registered_method_slots = (uint32_t)slots; chand->registered_method_max_probes = max_probes; } grpc_connected_channel_bind_transport(grpc_channel_get_channel_stack(channel), transport); gpr_mu_lock(&s->mu_global); chand->next = &s->root_channel_data; chand->prev = chand->next->prev; chand->next->prev = chand->prev->next = chand; gpr_mu_unlock(&s->mu_global); gpr_free((void *)filters); GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity"); memset(&op, 0, sizeof(op)); op.set_accept_stream = accept_stream; op.set_accept_stream_user_data = chand; op.on_connectivity_state_change = &chand->channel_connectivity_changed; op.connectivity_state = &chand->connectivity_state; op.disconnect = gpr_atm_acq_load(&s->shutdown_flag) != 0; grpc_transport_perform_op(exec_ctx, transport, &op); }
static int fill_send_ops(grpc_call *call, grpc_transport_op *op) { grpc_ioreq_data data; grpc_metadata_batch mdb; size_t i; char status_str[GPR_LTOA_MIN_BUFSIZE]; GPR_ASSERT(op->send_ops == NULL); switch (call->write_state) { case WRITE_STATE_INITIAL: if (!is_op_live(call, GRPC_IOREQ_SEND_INITIAL_METADATA)) { break; } data = call->request_data[GRPC_IOREQ_SEND_INITIAL_METADATA]; mdb.list = chain_metadata_from_app(call, data.send_metadata.count, data.send_metadata.metadata); mdb.garbage.head = mdb.garbage.tail = NULL; mdb.deadline = call->send_deadline; for (i = 0; i < call->send_initial_metadata_count; i++) { grpc_metadata_batch_link_head(&mdb, &call->send_initial_metadata[i]); } grpc_sopb_add_metadata(&call->send_ops, mdb); op->send_ops = &call->send_ops; op->bind_pollset = grpc_cq_pollset(call->cq); call->last_send_contains |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA; call->write_state = WRITE_STATE_STARTED; call->send_initial_metadata_count = 0; /* fall through intended */ case WRITE_STATE_STARTED: if (is_op_live(call, GRPC_IOREQ_SEND_MESSAGE)) { data = call->request_data[GRPC_IOREQ_SEND_MESSAGE]; grpc_sopb_add_begin_message( &call->send_ops, grpc_byte_buffer_length(data.send_message), 0); copy_byte_buffer_to_stream_ops(data.send_message, &call->send_ops); op->send_ops = &call->send_ops; call->last_send_contains |= 1 << GRPC_IOREQ_SEND_MESSAGE; } if (is_op_live(call, GRPC_IOREQ_SEND_CLOSE)) { op->is_last_send = 1; op->send_ops = &call->send_ops; call->last_send_contains |= 1 << GRPC_IOREQ_SEND_CLOSE; call->write_state = WRITE_STATE_WRITE_CLOSED; if (!call->is_client) { /* send trailing metadata */ data = call->request_data[GRPC_IOREQ_SEND_TRAILING_METADATA]; mdb.list = chain_metadata_from_app(call, data.send_metadata.count, data.send_metadata.metadata); mdb.garbage.head = mdb.garbage.tail = NULL; mdb.deadline = gpr_inf_future; /* send status */ /* TODO(ctiller): cache common status values */ data = call->request_data[GRPC_IOREQ_SEND_STATUS]; gpr_ltoa(data.send_status.code, status_str); grpc_metadata_batch_add_tail( &mdb, &call->status_link, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref(grpc_channel_get_status_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, status_str))); if (data.send_status.details) { grpc_metadata_batch_add_tail( &mdb, &call->details_link, grpc_mdelem_from_metadata_strings( call->metadata_context, grpc_mdstr_ref( grpc_channel_get_message_string(call->channel)), grpc_mdstr_from_string(call->metadata_context, data.send_status.details))); } grpc_sopb_add_metadata(&call->send_ops, mdb); } } break; case WRITE_STATE_WRITE_CLOSED: break; } if (op->send_ops) { op->on_done_send = call_on_done_send; op->send_user_data = call; } return op->send_ops != NULL; }
grpc_call *grpc_call_create(grpc_channel *channel, grpc_call *parent_call, uint32_t propagation_mask, grpc_completion_queue *cq, const void *server_transport_data, grpc_mdelem **add_initial_metadata, size_t add_initial_metadata_count, gpr_timespec send_deadline) { size_t i, j; grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel); grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_call *call; GPR_TIMER_BEGIN("grpc_call_create", 0); call = gpr_malloc(sizeof(grpc_call) + channel_stack->call_stack_size); memset(call, 0, sizeof(grpc_call)); gpr_mu_init(&call->mu); call->channel = channel; call->cq = cq; call->parent = parent_call; call->is_client = server_transport_data == NULL; if (call->is_client) { GPR_ASSERT(add_initial_metadata_count < MAX_SEND_EXTRA_METADATA_COUNT); for (i = 0; i < add_initial_metadata_count; i++) { call->send_extra_metadata[i].md = add_initial_metadata[i]; } call->send_extra_metadata_count = (int)add_initial_metadata_count; } else { GPR_ASSERT(add_initial_metadata_count == 0); call->send_extra_metadata_count = 0; } for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { call->metadata_batch[i][j].deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC); } } call->send_deadline = send_deadline; GRPC_CHANNEL_INTERNAL_REF(channel, "call"); /* initial refcount dropped by grpc_call_destroy */ grpc_call_stack_init(&exec_ctx, channel_stack, 1, destroy_call, call, call->context, server_transport_data, CALL_STACK_FROM_CALL(call)); if (cq != NULL) { GRPC_CQ_INTERNAL_REF(cq, "bind"); grpc_call_stack_set_pollset(&exec_ctx, CALL_STACK_FROM_CALL(call), grpc_cq_pollset(cq)); } if (parent_call != NULL) { GRPC_CALL_INTERNAL_REF(parent_call, "child"); GPR_ASSERT(call->is_client); GPR_ASSERT(!parent_call->is_client); gpr_mu_lock(&parent_call->mu); if (propagation_mask & GRPC_PROPAGATE_DEADLINE) { send_deadline = gpr_time_min( gpr_convert_clock_type(send_deadline, parent_call->send_deadline.clock_type), parent_call->send_deadline); } /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with * GRPC_PROPAGATE_STATS_CONTEXT */ /* TODO(ctiller): This should change to use the appropriate census start_op * call. */ if (propagation_mask & GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT) { GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT); grpc_call_context_set(call, GRPC_CONTEXT_TRACING, parent_call->context[GRPC_CONTEXT_TRACING].value, NULL); } else { GPR_ASSERT(propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT); } if (propagation_mask & GRPC_PROPAGATE_CANCELLATION) { call->cancellation_is_inherited = 1; } if (parent_call->first_child == NULL) { parent_call->first_child = call; call->sibling_next = call->sibling_prev = call; } else { call->sibling_next = parent_call->first_child; call->sibling_prev = parent_call->first_child->sibling_prev; call->sibling_next->sibling_prev = call->sibling_prev->sibling_next = call; } gpr_mu_unlock(&parent_call->mu); } if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) != 0) { set_deadline_alarm(&exec_ctx, call, send_deadline); } grpc_exec_ctx_finish(&exec_ctx); GPR_TIMER_END("grpc_call_create", 0); return call; }
static void test_pollset_conversion(void) { grpc_completion_queue *cq = grpc_completion_queue_create(NULL); GPR_ASSERT(grpc_cq_from_pollset(grpc_cq_pollset(cq)) == cq); shutdown_and_destroy(cq); }
void grpc_run_bad_client_test( grpc_bad_client_server_side_validator server_validator, grpc_bad_client_client_stream_validator client_validator, const char *client_payload, size_t client_payload_length, uint32_t flags) { grpc_endpoint_pair sfd; thd_args a; gpr_thd_id id; char *hex; grpc_transport *transport; gpr_slice slice = gpr_slice_from_copied_buffer(client_payload, client_payload_length); gpr_slice_buffer outgoing; grpc_closure done_write_closure; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; hex = gpr_dump(client_payload, client_payload_length, GPR_DUMP_HEX | GPR_DUMP_ASCII); /* Add a debug log */ gpr_log(GPR_INFO, "TEST: %s", hex); gpr_free(hex); /* Init grpc */ grpc_init(); /* Create endpoints */ sfd = grpc_iomgr_create_endpoint_pair("fixture", 65536); /* Create server, completion events */ a.server = grpc_server_create(NULL, NULL); a.cq = grpc_completion_queue_create(NULL); gpr_event_init(&a.done_thd); gpr_event_init(&a.done_write); a.validator = server_validator; grpc_server_register_completion_queue(a.server, a.cq, NULL); a.registered_method = grpc_server_register_method(a.server, GRPC_BAD_CLIENT_REGISTERED_METHOD, GRPC_BAD_CLIENT_REGISTERED_HOST, GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER, 0); grpc_server_start(a.server); transport = grpc_create_chttp2_transport(&exec_ctx, NULL, sfd.server, 0); server_setup_transport(&a, transport); grpc_chttp2_transport_start_reading(&exec_ctx, transport, NULL); grpc_exec_ctx_finish(&exec_ctx); /* Bind everything into the same pollset */ grpc_endpoint_add_to_pollset(&exec_ctx, sfd.client, grpc_cq_pollset(a.cq)); grpc_endpoint_add_to_pollset(&exec_ctx, sfd.server, grpc_cq_pollset(a.cq)); /* Check a ground truth */ GPR_ASSERT(grpc_server_has_open_connections(a.server)); /* Start validator */ gpr_thd_new(&id, thd_func, &a, NULL); gpr_slice_buffer_init(&outgoing); gpr_slice_buffer_add(&outgoing, slice); grpc_closure_init(&done_write_closure, done_write, &a); /* Write data */ grpc_endpoint_write(&exec_ctx, sfd.client, &outgoing, &done_write_closure); grpc_exec_ctx_finish(&exec_ctx); /* Await completion */ GPR_ASSERT( gpr_event_wait(&a.done_write, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); if (flags & GRPC_BAD_CLIENT_DISCONNECT) { grpc_endpoint_shutdown(&exec_ctx, sfd.client); grpc_endpoint_destroy(&exec_ctx, sfd.client); grpc_exec_ctx_finish(&exec_ctx); sfd.client = NULL; } GPR_ASSERT(gpr_event_wait(&a.done_thd, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); if (sfd.client != NULL) { // Validate client stream, if requested. if (client_validator != NULL) { read_args args; args.validator = client_validator; gpr_slice_buffer_init(&args.incoming); gpr_event_init(&args.read_done); grpc_closure read_done_closure; grpc_closure_init(&read_done_closure, read_done, &args); grpc_endpoint_read(&exec_ctx, sfd.client, &args.incoming, &read_done_closure); grpc_exec_ctx_finish(&exec_ctx); GPR_ASSERT( gpr_event_wait(&args.read_done, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))); gpr_slice_buffer_destroy(&args.incoming); } // Shutdown. grpc_endpoint_shutdown(&exec_ctx, sfd.client); grpc_endpoint_destroy(&exec_ctx, sfd.client); grpc_exec_ctx_finish(&exec_ctx); } grpc_server_shutdown_and_notify(a.server, a.cq, NULL); GPR_ASSERT(grpc_completion_queue_pluck( a.cq, NULL, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL) .type == GRPC_OP_COMPLETE); grpc_server_destroy(a.server); grpc_completion_queue_destroy(a.cq); gpr_slice_buffer_destroy(&outgoing); grpc_exec_ctx_finish(&exec_ctx); grpc_shutdown(); }