|
|
|
@ -173,7 +173,7 @@ static void do_nothing(void *ignored, grpc_op_error also_ignored) {} |
|
|
|
|
static send_action choose_send_action(grpc_call *call); |
|
|
|
|
static void enact_send_action(grpc_call *call, send_action sa); |
|
|
|
|
|
|
|
|
|
grpc_call *grpc_call_create(grpc_channel *channel, |
|
|
|
|
grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq, |
|
|
|
|
const void *server_transport_data) { |
|
|
|
|
size_t i; |
|
|
|
|
grpc_channel_stack *channel_stack = grpc_channel_get_channel_stack(channel); |
|
|
|
@ -182,6 +182,7 @@ grpc_call *grpc_call_create(grpc_channel *channel, |
|
|
|
|
memset(call, 0, sizeof(grpc_call)); |
|
|
|
|
gpr_mu_init(&call->mu); |
|
|
|
|
call->channel = channel; |
|
|
|
|
call->cq = cq; |
|
|
|
|
call->is_client = server_transport_data == NULL; |
|
|
|
|
for (i = 0; i < GRPC_IOREQ_OP_COUNT; i++) { |
|
|
|
|
call->request_set[i] = REQSET_EMPTY; |
|
|
|
@ -321,37 +322,49 @@ static void unlock(grpc_call *call) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void get_final_status(grpc_call *call, grpc_recv_status_args args) { |
|
|
|
|
static void get_final_status(grpc_call *call, grpc_ioreq_data out) { |
|
|
|
|
int i; |
|
|
|
|
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { |
|
|
|
|
if (call->status[i].is_set) { |
|
|
|
|
out.recv_status.set_value(call->status[i].code, |
|
|
|
|
out.recv_status.user_data); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
out.recv_status.set_value(GRPC_STATUS_UNKNOWN, out.recv_status.user_data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void get_final_details(grpc_call *call, grpc_ioreq_data out) { |
|
|
|
|
int i; |
|
|
|
|
for (i = 0; i < STATUS_SOURCE_COUNT; i++) { |
|
|
|
|
if (call->status[i].is_set) { |
|
|
|
|
*args.code = call->status[i].code; |
|
|
|
|
if (!args.details) return; |
|
|
|
|
if (call->status[i].details) { |
|
|
|
|
gpr_slice details = call->status[i].details->slice; |
|
|
|
|
size_t len = GPR_SLICE_LENGTH(details); |
|
|
|
|
if (len + 1 > *args.details_capacity) { |
|
|
|
|
*args.details_capacity = |
|
|
|
|
GPR_MAX(len + 1, *args.details_capacity * 3 / 2); |
|
|
|
|
*args.details = gpr_realloc(*args.details, *args.details_capacity); |
|
|
|
|
if (len + 1 > *out.recv_status_details.details_capacity) { |
|
|
|
|
*out.recv_status_details.details_capacity = GPR_MAX( |
|
|
|
|
len + 1, *out.recv_status_details.details_capacity * 3 / 2); |
|
|
|
|
*out.recv_status_details.details = |
|
|
|
|
gpr_realloc(*out.recv_status_details.details, |
|
|
|
|
*out.recv_status_details.details_capacity); |
|
|
|
|
} |
|
|
|
|
memcpy(*args.details, GPR_SLICE_START_PTR(details), len); |
|
|
|
|
(*args.details)[len] = 0; |
|
|
|
|
memcpy(*out.recv_status_details.details, GPR_SLICE_START_PTR(details), |
|
|
|
|
len); |
|
|
|
|
(*out.recv_status_details.details)[len] = 0; |
|
|
|
|
} else { |
|
|
|
|
goto no_details; |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
*args.code = GRPC_STATUS_UNKNOWN; |
|
|
|
|
if (!args.details) return; |
|
|
|
|
|
|
|
|
|
no_details: |
|
|
|
|
if (0 == *args.details_capacity) { |
|
|
|
|
*args.details_capacity = 8; |
|
|
|
|
*args.details = gpr_malloc(*args.details_capacity); |
|
|
|
|
if (0 == *out.recv_status_details.details_capacity) { |
|
|
|
|
*out.recv_status_details.details_capacity = 8; |
|
|
|
|
*out.recv_status_details.details = |
|
|
|
|
gpr_malloc(*out.recv_status_details.details_capacity); |
|
|
|
|
} |
|
|
|
|
**args.details = 0; |
|
|
|
|
**out.recv_status_details.details = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, |
|
|
|
@ -389,8 +402,11 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op, |
|
|
|
|
case GRPC_IOREQ_SEND_CLOSE: |
|
|
|
|
break; |
|
|
|
|
case GRPC_IOREQ_RECV_STATUS: |
|
|
|
|
get_final_status( |
|
|
|
|
call, call->request_data[GRPC_IOREQ_RECV_STATUS].recv_status); |
|
|
|
|
get_final_status(call, call->request_data[GRPC_IOREQ_RECV_STATUS]); |
|
|
|
|
break; |
|
|
|
|
case GRPC_IOREQ_RECV_STATUS_DETAILS: |
|
|
|
|
get_final_details(call, |
|
|
|
|
call->request_data[GRPC_IOREQ_RECV_STATUS_DETAILS]); |
|
|
|
|
break; |
|
|
|
|
case GRPC_IOREQ_RECV_INITIAL_METADATA: |
|
|
|
|
SWAP(grpc_metadata_array, call->buffered_metadata[0], |
|
|
|
@ -598,6 +614,7 @@ static void finish_read_ops(grpc_call *call) { |
|
|
|
|
finish_ioreq_op(call, GRPC_IOREQ_RECV_MESSAGE, GRPC_OP_OK); |
|
|
|
|
} |
|
|
|
|
finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS, GRPC_OP_OK); |
|
|
|
|
finish_ioreq_op(call, GRPC_IOREQ_RECV_STATUS_DETAILS, GRPC_OP_OK); |
|
|
|
|
finish_ioreq_op(call, GRPC_IOREQ_RECV_TRAILING_METADATA, GRPC_OP_OK); |
|
|
|
|
/* fallthrough */ |
|
|
|
|
case READ_STATE_GOT_INITIAL_METADATA: |
|
|
|
@ -675,20 +692,6 @@ static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs, |
|
|
|
|
return GRPC_CALL_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void call_start_ioreq_done(grpc_call *call, grpc_op_error status, |
|
|
|
|
void *user_data) { |
|
|
|
|
grpc_cq_end_ioreq(call->cq, user_data, call, do_nothing, NULL, status); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_call_start_ioreq(grpc_call *call, const grpc_ioreq *reqs, |
|
|
|
|
size_t nreqs, void *tag) { |
|
|
|
|
grpc_call_error err; |
|
|
|
|
lock(call); |
|
|
|
|
err = start_ioreq(call, reqs, nreqs, call_start_ioreq_done, tag); |
|
|
|
|
unlock(call); |
|
|
|
|
return err; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_call_start_ioreq_and_call_back( |
|
|
|
|
grpc_call *call, const grpc_ioreq *reqs, size_t nreqs, |
|
|
|
|
grpc_ioreq_completion_func on_complete, void *user_data) { |
|
|
|
@ -872,6 +875,121 @@ void grpc_call_initial_metadata_complete(grpc_call_element *surface_element) { |
|
|
|
|
set_read_state(call, READ_STATE_GOT_INITIAL_METADATA); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* BATCH API IMPLEMENTATION |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
static void set_status_value_directly(grpc_status_code status, void *dest) { |
|
|
|
|
*(grpc_status_code *)dest = status; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void set_cancelled_value(grpc_status_code status, void *dest) { |
|
|
|
|
*(grpc_status_code *)dest = (status != GRPC_STATUS_OK); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void finish_batch(grpc_call *call, grpc_op_error result, void *tag) {} |
|
|
|
|
|
|
|
|
|
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops, |
|
|
|
|
size_t nops, void *tag) { |
|
|
|
|
grpc_ioreq reqs[GRPC_IOREQ_OP_COUNT]; |
|
|
|
|
size_t in; |
|
|
|
|
size_t out; |
|
|
|
|
const grpc_op *op; |
|
|
|
|
grpc_ioreq *req; |
|
|
|
|
|
|
|
|
|
/* rewrite batch ops into ioreq ops */ |
|
|
|
|
for (in = 0, out = 0; in < nops; in++) { |
|
|
|
|
op = &ops[in]; |
|
|
|
|
switch (op->op) { |
|
|
|
|
case GRPC_OP_SEND_INITIAL_METADATA: |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_INITIAL_METADATA; |
|
|
|
|
req->data.send_metadata.count = op->data.send_initial_metadata.count; |
|
|
|
|
req->data.send_metadata.metadata = |
|
|
|
|
op->data.send_initial_metadata.metadata; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_MESSAGE: |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_MESSAGE; |
|
|
|
|
req->data.send_message = op->data.send_message; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_CLOSE_FROM_CLIENT: |
|
|
|
|
if (!call->is_client) { |
|
|
|
|
return GRPC_CALL_ERROR_NOT_ON_SERVER; |
|
|
|
|
} |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_CLOSE; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_SEND_STATUS_FROM_SERVER: |
|
|
|
|
if (call->is_client) { |
|
|
|
|
return GRPC_CALL_ERROR_NOT_ON_CLIENT; |
|
|
|
|
} |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_TRAILING_METADATA; |
|
|
|
|
req->data.send_metadata.count = |
|
|
|
|
op->data.send_status_from_server.trailing_metadata_count; |
|
|
|
|
req->data.send_metadata.metadata = |
|
|
|
|
op->data.send_status_from_server.trailing_metadata; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_STATUS; |
|
|
|
|
req->data.send_status.code = op->data.send_status_from_server.status; |
|
|
|
|
req->data.send_status.details = |
|
|
|
|
op->data.send_status_from_server.status_details; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_SEND_CLOSE; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_INITIAL_METADATA: |
|
|
|
|
if (!call->is_client) { |
|
|
|
|
return GRPC_CALL_ERROR_NOT_ON_SERVER; |
|
|
|
|
} |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_INITIAL_METADATA; |
|
|
|
|
req->data.recv_metadata = op->data.recv_initial_metadata; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_MESSAGE: |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_MESSAGE; |
|
|
|
|
req->data.recv_message = op->data.recv_message; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_STATUS_ON_CLIENT: |
|
|
|
|
if (!call->is_client) { |
|
|
|
|
return GRPC_CALL_ERROR_NOT_ON_SERVER; |
|
|
|
|
} |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_STATUS; |
|
|
|
|
req->data.recv_status.set_value = set_status_value_directly; |
|
|
|
|
req->data.recv_status.user_data = op->data.recv_status_on_client.status; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_STATUS_DETAILS; |
|
|
|
|
req->data.recv_status_details.details = |
|
|
|
|
op->data.recv_status_on_client.status_details; |
|
|
|
|
req->data.recv_status_details.details_capacity = |
|
|
|
|
op->data.recv_status_on_client.status_details_capacity; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_TRAILING_METADATA; |
|
|
|
|
req->data.recv_metadata = |
|
|
|
|
op->data.recv_status_on_client.trailing_metadata; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_CLOSE; |
|
|
|
|
break; |
|
|
|
|
case GRPC_OP_RECV_CLOSE_ON_SERVER: |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_STATUS; |
|
|
|
|
req->data.recv_status.set_value = set_cancelled_value; |
|
|
|
|
req->data.recv_status.user_data = |
|
|
|
|
op->data.recv_close_on_server.cancelled; |
|
|
|
|
req = &reqs[out++]; |
|
|
|
|
req->op = GRPC_IOREQ_RECV_CLOSE; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
grpc_cq_begin_op(call->cq, call, GRPC_OP_COMPLETE); |
|
|
|
|
|
|
|
|
|
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_batch, |
|
|
|
|
tag); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* LEGACY API IMPLEMENTATION |
|
|
|
|
* All this code will disappear as soon as wrappings are updated |
|
|
|
@ -985,7 +1103,7 @@ static void finish_send_metadata(grpc_call *call, grpc_op_error status, |
|
|
|
|
grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq, |
|
|
|
|
void *metadata_read_tag, |
|
|
|
|
void *finished_tag, gpr_uint32 flags) { |
|
|
|
|
grpc_ioreq reqs[3]; |
|
|
|
|
grpc_ioreq reqs[4]; |
|
|
|
|
legacy_state *ls; |
|
|
|
|
grpc_call_error err; |
|
|
|
|
|
|
|
|
@ -1014,11 +1132,13 @@ grpc_call_error grpc_call_invoke_old(grpc_call *call, grpc_completion_queue *cq, |
|
|
|
|
reqs[0].op = GRPC_IOREQ_RECV_TRAILING_METADATA; |
|
|
|
|
reqs[0].data.recv_metadata = &ls->trailing_md_in; |
|
|
|
|
reqs[1].op = GRPC_IOREQ_RECV_STATUS; |
|
|
|
|
reqs[1].data.recv_status.details = &ls->details; |
|
|
|
|
reqs[1].data.recv_status.details_capacity = &ls->details_capacity; |
|
|
|
|
reqs[1].data.recv_status.code = &ls->status; |
|
|
|
|
reqs[2].op = GRPC_IOREQ_RECV_CLOSE; |
|
|
|
|
err = start_ioreq(call, reqs, 3, finish_status, NULL); |
|
|
|
|
reqs[1].data.recv_status.user_data = &ls->status; |
|
|
|
|
reqs[1].data.recv_status.set_value = set_status_value_directly; |
|
|
|
|
reqs[2].op = GRPC_IOREQ_RECV_STATUS_DETAILS; |
|
|
|
|
reqs[2].data.recv_status_details.details = &ls->details; |
|
|
|
|
reqs[2].data.recv_status_details.details_capacity = &ls->details_capacity; |
|
|
|
|
reqs[3].op = GRPC_IOREQ_RECV_CLOSE; |
|
|
|
|
err = start_ioreq(call, reqs, 4, finish_status, NULL); |
|
|
|
|
if (err != GRPC_CALL_OK) goto done; |
|
|
|
|
|
|
|
|
|
done: |
|
|
|
@ -1046,9 +1166,8 @@ grpc_call_error grpc_call_server_accept_old(grpc_call *call, |
|
|
|
|
ls->finished_tag = finished_tag; |
|
|
|
|
|
|
|
|
|
reqs[0].op = GRPC_IOREQ_RECV_STATUS; |
|
|
|
|
reqs[0].data.recv_status.details = NULL; |
|
|
|
|
reqs[0].data.recv_status.details_capacity = 0; |
|
|
|
|
reqs[0].data.recv_status.code = &ls->status; |
|
|
|
|
reqs[0].data.recv_status.user_data = &ls->status; |
|
|
|
|
reqs[0].data.recv_status.set_value = set_status_value_directly; |
|
|
|
|
reqs[1].op = GRPC_IOREQ_RECV_CLOSE; |
|
|
|
|
err = start_ioreq(call, reqs, 2, finish_status, NULL); |
|
|
|
|
unlock(call); |
|
|
|
|