|
|
|
@ -88,7 +88,7 @@ enum e_op_id { |
|
|
|
|
|
|
|
|
|
/* Cronet callbacks. See cronet_c_for_grpc.h for documentation for each. */ |
|
|
|
|
|
|
|
|
|
static void on_request_headers_sent(bidirectional_stream *); |
|
|
|
|
static void on_stream_ready(bidirectional_stream *); |
|
|
|
|
static void on_response_headers_received( |
|
|
|
|
bidirectional_stream *, const bidirectional_stream_header_array *, |
|
|
|
|
const char *); |
|
|
|
@ -100,7 +100,7 @@ static void on_succeeded(bidirectional_stream *); |
|
|
|
|
static void on_failed(bidirectional_stream *, int); |
|
|
|
|
static void on_canceled(bidirectional_stream *); |
|
|
|
|
static bidirectional_stream_callback cronet_callbacks = { |
|
|
|
|
on_request_headers_sent, |
|
|
|
|
on_stream_ready, |
|
|
|
|
on_response_headers_received, |
|
|
|
|
on_read_completed, |
|
|
|
|
on_write_completed, |
|
|
|
@ -114,6 +114,7 @@ struct grpc_cronet_transport { |
|
|
|
|
grpc_transport base; /* must be first element in this structure */ |
|
|
|
|
stream_engine *engine; |
|
|
|
|
char *host; |
|
|
|
|
bool use_packet_coalescing; |
|
|
|
|
}; |
|
|
|
|
typedef struct grpc_cronet_transport grpc_cronet_transport; |
|
|
|
|
|
|
|
|
@ -152,6 +153,9 @@ struct op_state { |
|
|
|
|
bool state_callback_received[OP_NUM_OPS]; |
|
|
|
|
bool fail_state; |
|
|
|
|
bool flush_read; |
|
|
|
|
bool flush_cronet_when_ready; |
|
|
|
|
bool pending_write_for_trailer; |
|
|
|
|
bool unprocessed_send_message; |
|
|
|
|
grpc_error *cancel_error; |
|
|
|
|
/* data structure for storing data coming from server */ |
|
|
|
|
struct read_state rs; |
|
|
|
@ -175,7 +179,7 @@ struct op_storage { |
|
|
|
|
struct stream_obj { |
|
|
|
|
struct op_and_state *oas; |
|
|
|
|
grpc_transport_stream_op *curr_op; |
|
|
|
|
grpc_cronet_transport curr_ct; |
|
|
|
|
grpc_cronet_transport *curr_ct; |
|
|
|
|
grpc_stream *curr_gs; |
|
|
|
|
bidirectional_stream *cbs; |
|
|
|
|
bidirectional_stream_header_array header_array; |
|
|
|
@ -274,6 +278,9 @@ static void add_to_storage(struct stream_obj *s, grpc_transport_stream_op *op) { |
|
|
|
|
new_op->next = storage->head; |
|
|
|
|
storage->head = new_op; |
|
|
|
|
storage->num_pending_ops++; |
|
|
|
|
if (op->send_message) { |
|
|
|
|
s->state.unprocessed_send_message = true; |
|
|
|
|
} |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "adding new op %p. %d in the queue.", new_op, |
|
|
|
|
storage->num_pending_ops); |
|
|
|
|
gpr_mu_unlock(&s->mu); |
|
|
|
@ -406,9 +413,10 @@ static void on_succeeded(bidirectional_stream *stream) { |
|
|
|
|
/*
|
|
|
|
|
Cronet callback |
|
|
|
|
*/ |
|
|
|
|
static void on_request_headers_sent(bidirectional_stream *stream) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "W: on_request_headers_sent(%p)", stream); |
|
|
|
|
static void on_stream_ready(bidirectional_stream *stream) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "W: on_stream_ready(%p)", stream); |
|
|
|
|
stream_obj *s = (stream_obj *)stream->annotation; |
|
|
|
|
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; |
|
|
|
|
gpr_mu_lock(&s->mu); |
|
|
|
|
s->state.state_op_done[OP_SEND_INITIAL_METADATA] = true; |
|
|
|
|
s->state.state_callback_received[OP_SEND_INITIAL_METADATA] = true; |
|
|
|
@ -417,6 +425,14 @@ static void on_request_headers_sent(bidirectional_stream *stream) { |
|
|
|
|
gpr_free(s->header_array.headers); |
|
|
|
|
s->header_array.headers = NULL; |
|
|
|
|
} |
|
|
|
|
/* Send the initial metadata on wire if there is no SEND_MESSAGE or
|
|
|
|
|
* SEND_TRAILING_METADATA ops pending */ |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
if (s->state.flush_cronet_when_ready) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "cronet_bidirectional_stream_flush (%p)", s->cbs); |
|
|
|
|
bidirectional_stream_flush(stream); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(&s->mu); |
|
|
|
|
execute_from_storage(s); |
|
|
|
|
} |
|
|
|
@ -528,6 +544,7 @@ static void on_response_trailers_received( |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "R: on_response_trailers_received(%p,%p)", stream, |
|
|
|
|
trailers); |
|
|
|
|
stream_obj *s = (stream_obj *)stream->annotation; |
|
|
|
|
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; |
|
|
|
|
gpr_mu_lock(&s->mu); |
|
|
|
|
memset(&s->state.rs.trailing_metadata, 0, |
|
|
|
|
sizeof(s->state.rs.trailing_metadata)); |
|
|
|
@ -558,6 +575,10 @@ static void on_response_trailers_received( |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); |
|
|
|
|
s->state.state_callback_received[OP_SEND_MESSAGE] = false; |
|
|
|
|
bidirectional_stream_write(s->cbs, "", 0, true); |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); |
|
|
|
|
bidirectional_stream_flush(s->cbs); |
|
|
|
|
} |
|
|
|
|
s->state.state_op_done[OP_SEND_TRAILING_METADATA] = true; |
|
|
|
|
|
|
|
|
|
gpr_mu_unlock(&s->mu); |
|
|
|
@ -607,7 +628,7 @@ static void convert_metadata_to_cronet_headers( |
|
|
|
|
curr = curr->next; |
|
|
|
|
num_headers_available++; |
|
|
|
|
} |
|
|
|
|
/* Allocate enough memory. It is freed in the on_request_headers_sent callback
|
|
|
|
|
/* Allocate enough memory. It is freed in the on_stream_ready callback
|
|
|
|
|
*/ |
|
|
|
|
bidirectional_stream_header *headers = |
|
|
|
|
(bidirectional_stream_header *)gpr_malloc( |
|
|
|
@ -687,8 +708,10 @@ static bool header_has_authority(grpc_linked_mdelem *head) { |
|
|
|
|
executed. This is the heart of the state machine. |
|
|
|
|
*/ |
|
|
|
|
static bool op_can_be_run(grpc_transport_stream_op *curr_op, |
|
|
|
|
struct op_state *stream_state, |
|
|
|
|
struct op_state *op_state, enum e_op_id op_id) { |
|
|
|
|
struct stream_obj *s, struct op_state *op_state, |
|
|
|
|
enum e_op_id op_id) { |
|
|
|
|
struct op_state *stream_state = &s->state; |
|
|
|
|
grpc_cronet_transport *t = s->curr_ct; |
|
|
|
|
bool result = true; |
|
|
|
|
/* When call is canceled, every op can be run, except under following
|
|
|
|
|
conditions |
|
|
|
@ -755,12 +778,14 @@ static bool op_can_be_run(grpc_transport_stream_op *curr_op, |
|
|
|
|
else if (!stream_state->state_callback_received[OP_SEND_INITIAL_METADATA]) |
|
|
|
|
result = false; |
|
|
|
|
/* we haven't sent message yet */ |
|
|
|
|
else if (curr_op->send_message && |
|
|
|
|
else if (stream_state->unprocessed_send_message && |
|
|
|
|
!stream_state->state_op_done[OP_SEND_MESSAGE]) |
|
|
|
|
result = false; |
|
|
|
|
/* we haven't got on_write_completed for the send yet */ |
|
|
|
|
else if (stream_state->state_op_done[OP_SEND_MESSAGE] && |
|
|
|
|
!stream_state->state_callback_received[OP_SEND_MESSAGE]) |
|
|
|
|
!stream_state->state_callback_received[OP_SEND_MESSAGE] && |
|
|
|
|
!(t->use_packet_coalescing && |
|
|
|
|
stream_state->pending_write_for_trailer)) |
|
|
|
|
result = false; |
|
|
|
|
} else if (op_id == OP_CANCEL_ERROR) { |
|
|
|
|
/* already executed */ |
|
|
|
@ -833,24 +858,28 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
struct op_and_state *oas) { |
|
|
|
|
grpc_transport_stream_op *stream_op = &oas->op; |
|
|
|
|
struct stream_obj *s = oas->s; |
|
|
|
|
grpc_cronet_transport *t = (grpc_cronet_transport *)s->curr_ct; |
|
|
|
|
struct op_state *stream_state = &s->state; |
|
|
|
|
enum e_op_result result = NO_ACTION_POSSIBLE; |
|
|
|
|
if (stream_op->send_initial_metadata && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_SEND_INITIAL_METADATA)) { |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, OP_SEND_INITIAL_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_INITIAL_METADATA", oas); |
|
|
|
|
/* Start new cronet stream. It is destroyed in on_succeeded, on_canceled,
|
|
|
|
|
* on_failed */ |
|
|
|
|
GPR_ASSERT(s->cbs == NULL); |
|
|
|
|
GPR_ASSERT(!stream_state->state_op_done[OP_SEND_INITIAL_METADATA]); |
|
|
|
|
s->cbs = bidirectional_stream_create(s->curr_ct.engine, s->curr_gs, |
|
|
|
|
&cronet_callbacks); |
|
|
|
|
s->cbs = |
|
|
|
|
bidirectional_stream_create(t->engine, s->curr_gs, &cronet_callbacks); |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "%p = bidirectional_stream_create()", s->cbs); |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
bidirectional_stream_disable_auto_flush(s->cbs, true); |
|
|
|
|
bidirectional_stream_delay_request_headers_until_flush(s->cbs, true); |
|
|
|
|
} |
|
|
|
|
char *url = NULL; |
|
|
|
|
const char *method = "POST"; |
|
|
|
|
s->header_array.headers = NULL; |
|
|
|
|
convert_metadata_to_cronet_headers( |
|
|
|
|
stream_op->send_initial_metadata->list.head, s->curr_ct.host, &url, |
|
|
|
|
stream_op->send_initial_metadata->list.head, t->host, &url, |
|
|
|
|
&s->header_array.headers, &s->header_array.count, &method); |
|
|
|
|
s->header_array.capacity = s->header_array.count; |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_start(%p, %s)", s->cbs, url); |
|
|
|
@ -862,30 +891,16 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
gpr_free((void *)s->header_array.headers[header_index].value); |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_SEND_INITIAL_METADATA] = true; |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} else if (stream_op->recv_initial_metadata && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_RECV_INITIAL_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas); |
|
|
|
|
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
} else if (stream_state->state_callback_received[OP_FAILED]) { |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
} else { |
|
|
|
|
grpc_chttp2_incoming_metadata_buffer_publish( |
|
|
|
|
exec_ctx, &oas->s->state.rs.initial_metadata, |
|
|
|
|
stream_op->recv_initial_metadata); |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
if (!stream_op->send_message && !stream_op->send_trailing_metadata) { |
|
|
|
|
s->state.flush_cronet_when_ready = true; |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true; |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} else if (stream_op->send_message && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_SEND_MESSAGE)) { |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, OP_SEND_MESSAGE)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_MESSAGE", oas); |
|
|
|
|
stream_state->unprocessed_send_message = false; |
|
|
|
|
if (stream_state->state_callback_received[OP_FAILED]) { |
|
|
|
|
result = NO_ACTION_POSSIBLE; |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); |
|
|
|
@ -916,16 +931,63 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
stream_state->state_callback_received[OP_SEND_MESSAGE] = false; |
|
|
|
|
bidirectional_stream_write(s->cbs, stream_state->ws.write_buffer, |
|
|
|
|
(int)write_buffer_size, false); |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
if (!stream_op->send_trailing_metadata) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); |
|
|
|
|
bidirectional_stream_flush(s->cbs); |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} else { |
|
|
|
|
stream_state->pending_write_for_trailer = true; |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
result = NO_ACTION_POSSIBLE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_SEND_MESSAGE] = true; |
|
|
|
|
oas->state.state_op_done[OP_SEND_MESSAGE] = true; |
|
|
|
|
} else if (stream_op->send_trailing_metadata && |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, |
|
|
|
|
OP_SEND_TRAILING_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas); |
|
|
|
|
if (stream_state->state_callback_received[OP_FAILED]) { |
|
|
|
|
result = NO_ACTION_POSSIBLE; |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); |
|
|
|
|
} else { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); |
|
|
|
|
stream_state->state_callback_received[OP_SEND_MESSAGE] = false; |
|
|
|
|
bidirectional_stream_write(s->cbs, "", 0, true); |
|
|
|
|
if (t->use_packet_coalescing) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_flush (%p)", s->cbs); |
|
|
|
|
bidirectional_stream_flush(s->cbs); |
|
|
|
|
} |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true; |
|
|
|
|
} else if (stream_op->recv_initial_metadata && |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, |
|
|
|
|
OP_RECV_INITIAL_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_INITIAL_METADATA", oas); |
|
|
|
|
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
} else if (stream_state->state_callback_received[OP_FAILED]) { |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
} else { |
|
|
|
|
grpc_chttp2_incoming_metadata_buffer_publish( |
|
|
|
|
exec_ctx, &oas->s->state.rs.initial_metadata, |
|
|
|
|
stream_op->recv_initial_metadata); |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->recv_initial_metadata_ready, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_RECV_INITIAL_METADATA] = true; |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} else if (stream_op->recv_message && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_RECV_MESSAGE)) { |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, OP_RECV_MESSAGE)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_MESSAGE", oas); |
|
|
|
|
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "Stream is cancelled."); |
|
|
|
@ -980,6 +1042,16 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
GRPC_ERROR_NONE); |
|
|
|
|
stream_state->state_op_done[OP_RECV_MESSAGE] = true; |
|
|
|
|
oas->state.state_op_done[OP_RECV_MESSAGE] = true; |
|
|
|
|
|
|
|
|
|
/* Extra read to trigger on_succeed */ |
|
|
|
|
stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; |
|
|
|
|
stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; |
|
|
|
|
stream_state->rs.received_bytes = 0; |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); |
|
|
|
|
stream_state->state_op_done[OP_READ_REQ_MADE] = |
|
|
|
|
true; /* Indicates that at least one read request has been made */ |
|
|
|
|
bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, |
|
|
|
|
stream_state->rs.remaining_bytes); |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} |
|
|
|
|
} else if (stream_state->rs.remaining_bytes == 0) { |
|
|
|
@ -1027,7 +1099,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} |
|
|
|
|
} else if (stream_op->recv_trailing_metadata && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, |
|
|
|
|
OP_RECV_TRAILING_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas); |
|
|
|
|
if (oas->s->state.rs.trailing_metadata_valid) { |
|
|
|
@ -1038,23 +1110,8 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_RECV_TRAILING_METADATA] = true; |
|
|
|
|
result = ACTION_TAKEN_NO_CALLBACK; |
|
|
|
|
} else if (stream_op->send_trailing_metadata && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_SEND_TRAILING_METADATA)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_SEND_TRAILING_METADATA", oas); |
|
|
|
|
if (stream_state->state_callback_received[OP_FAILED]) { |
|
|
|
|
result = NO_ACTION_POSSIBLE; |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "Stream is either cancelled or failed."); |
|
|
|
|
} else { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "bidirectional_stream_write (%p, 0)", s->cbs); |
|
|
|
|
stream_state->state_callback_received[OP_SEND_MESSAGE] = false; |
|
|
|
|
bidirectional_stream_write(s->cbs, "", 0, true); |
|
|
|
|
result = ACTION_TAKEN_WITH_CALLBACK; |
|
|
|
|
} |
|
|
|
|
stream_state->state_op_done[OP_SEND_TRAILING_METADATA] = true; |
|
|
|
|
} else if (stream_op->cancel_error && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_CANCEL_ERROR)) { |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, OP_CANCEL_ERROR)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_CANCEL_ERROR", oas); |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "W: bidirectional_stream_cancel(%p)", s->cbs); |
|
|
|
|
if (s->cbs) { |
|
|
|
@ -1068,8 +1125,7 @@ static enum e_op_result execute_stream_op(grpc_exec_ctx *exec_ctx, |
|
|
|
|
stream_state->cancel_error = GRPC_ERROR_REF(stream_op->cancel_error); |
|
|
|
|
} |
|
|
|
|
} else if (stream_op->on_complete && |
|
|
|
|
op_can_be_run(stream_op, stream_state, &oas->state, |
|
|
|
|
OP_ON_COMPLETE)) { |
|
|
|
|
op_can_be_run(stream_op, s, &oas->state, OP_ON_COMPLETE)) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "running: %p OP_ON_COMPLETE", oas); |
|
|
|
|
if (stream_state->state_op_done[OP_CANCEL_ERROR]) { |
|
|
|
|
grpc_closure_sched(exec_ctx, stream_op->on_complete, |
|
|
|
@ -1133,6 +1189,12 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt, |
|
|
|
|
sizeof(s->state.state_callback_received)); |
|
|
|
|
s->state.fail_state = s->state.flush_read = false; |
|
|
|
|
s->state.cancel_error = NULL; |
|
|
|
|
s->state.flush_cronet_when_ready = s->state.pending_write_for_trailer = false; |
|
|
|
|
s->state.unprocessed_send_message = false; |
|
|
|
|
|
|
|
|
|
s->curr_gs = gs; |
|
|
|
|
s->curr_ct = (grpc_cronet_transport *)gt; |
|
|
|
|
|
|
|
|
|
gpr_mu_init(&s->mu); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -1148,8 +1210,6 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, |
|
|
|
|
grpc_stream *gs, grpc_transport_stream_op *op) { |
|
|
|
|
CRONET_LOG(GPR_DEBUG, "perform_stream_op"); |
|
|
|
|
stream_obj *s = (stream_obj *)gs; |
|
|
|
|
s->curr_gs = gs; |
|
|
|
|
memcpy(&s->curr_ct, gt, sizeof(grpc_cronet_transport)); |
|
|
|
|
add_to_storage(s, op); |
|
|
|
|
if (op->send_initial_metadata && |
|
|
|
|
header_has_authority(op->send_initial_metadata->list.head)) { |
|
|
|
@ -1197,7 +1257,8 @@ static grpc_endpoint *get_endpoint(grpc_exec_ctx *exec_ctx, |
|
|
|
|
static void perform_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt, |
|
|
|
|
grpc_transport_op *op) {} |
|
|
|
|
|
|
|
|
|
const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj), |
|
|
|
|
static const grpc_transport_vtable grpc_cronet_vtable = { |
|
|
|
|
sizeof(stream_obj), |
|
|
|
|
"cronet_http", |
|
|
|
|
init_stream, |
|
|
|
|
set_pollset_do_nothing, |
|
|
|
@ -1208,3 +1269,46 @@ const grpc_transport_vtable grpc_cronet_vtable = {sizeof(stream_obj), |
|
|
|
|
destroy_transport, |
|
|
|
|
get_peer, |
|
|
|
|
get_endpoint}; |
|
|
|
|
|
|
|
|
|
grpc_transport *grpc_create_cronet_transport(void *engine, const char *target, |
|
|
|
|
const grpc_channel_args *args, |
|
|
|
|
void *reserved) { |
|
|
|
|
grpc_cronet_transport *ct = gpr_malloc(sizeof(grpc_cronet_transport)); |
|
|
|
|
if (!ct) { |
|
|
|
|
goto error; |
|
|
|
|
} |
|
|
|
|
ct->base.vtable = &grpc_cronet_vtable; |
|
|
|
|
ct->engine = engine; |
|
|
|
|
ct->host = gpr_malloc(strlen(target) + 1); |
|
|
|
|
if (!ct->host) { |
|
|
|
|
goto error; |
|
|
|
|
} |
|
|
|
|
strcpy(ct->host, target); |
|
|
|
|
|
|
|
|
|
ct->use_packet_coalescing = true; |
|
|
|
|
if (args) { |
|
|
|
|
for (size_t i = 0; i < args->num_args; i++) { |
|
|
|
|
if (0 == |
|
|
|
|
strcmp(args->args[i].key, GRPC_ARG_USE_CRONET_PACKET_COALESCING)) { |
|
|
|
|
if (args->args[i].type != GRPC_ARG_INTEGER) { |
|
|
|
|
gpr_log(GPR_ERROR, "%s ignored: it must be an integer", |
|
|
|
|
GRPC_ARG_USE_CRONET_PACKET_COALESCING); |
|
|
|
|
} else { |
|
|
|
|
ct->use_packet_coalescing = (args->args[i].value.integer != 0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return &ct->base; |
|
|
|
|
|
|
|
|
|
error: |
|
|
|
|
if (ct) { |
|
|
|
|
if (ct->host) { |
|
|
|
|
gpr_free(ct->host); |
|
|
|
|
} |
|
|
|
|
gpr_free(ct); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|