static void hc_mutate_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { /* grab pointers to our data from the call element */ call_data *calld = elem->call_data; channel_data *channeld = elem->channel_data; if (op->send_initial_metadata != NULL) { /* Decide which HTTP VERB to use. We use GET if the request is marked cacheable, and the operation contains both initial metadata and send message, and the payload is below the size threshold, and all the data for this request is immediately available. */ grpc_mdelem *method = GRPC_MDELEM_METHOD_POST; if ((op->send_initial_metadata_flags & GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && op->send_message != NULL && op->send_message->length < channeld->max_payload_size_for_get) { method = GRPC_MDELEM_METHOD_GET; /* The following write to calld->send_message_blocked isn't racy with reads in hc_start_transport_op (which deals with SEND_MESSAGE ops) because being here means ops->send_message is not NULL, which is primarily guarding the read there. */ calld->send_message_blocked = true; } else if (op->send_initial_metadata_flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { method = GRPC_MDELEM_METHOD_PUT; } /* Attempt to read the data from send_message and create a header field. */ if (method == GRPC_MDELEM_METHOD_GET) { /* allocate memory to hold the entire payload */ calld->payload_bytes = gpr_malloc(op->send_message->length); /* read slices of send_message and copy into payload_bytes */ calld->send_op = *op; calld->send_length = op->send_message->length; calld->send_flags = op->send_message->flags; continue_send_message(exec_ctx, elem); if (calld->send_message_blocked == false) { /* when all the send_message data is available, then create a MDELEM and append to headers */ grpc_mdelem *payload_bin = grpc_mdelem_from_metadata_strings( GRPC_MDSTR_GRPC_PAYLOAD_BIN, grpc_mdstr_from_buffer(calld->payload_bytes, op->send_message->length)); grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->payload_bin, payload_bin); calld->on_complete = op->on_complete; op->on_complete = &calld->hc_on_complete; op->send_message = NULL; } else { /* Not all data is available. Fall back to POST. */ gpr_log(GPR_DEBUG, "Request is marked Cacheable but not all data is available.\ Falling back to POST"); method = GRPC_MDELEM_METHOD_POST; } }
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, bool success) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; gpr_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { finish_send_message(exec_ctx, elem); } else { continue_send_message(exec_ctx, elem); } }
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; calld->send_message_blocked = false; grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { /* Pass down the original send_message op that was blocked.*/ grpc_slice_buffer_stream_init(&calld->replacement_stream, &calld->slices, calld->send_flags); calld->send_op.send_message = &calld->replacement_stream.base; calld->post_send = calld->send_op.on_complete; calld->send_op.on_complete = &calld->send_done; grpc_call_next_op(exec_ctx, elem, &calld->send_op); } else { continue_send_message(exec_ctx, elem); } }
static void got_slice(grpc_exec_ctx *exec_ctx, void *elemp, grpc_error *error) { grpc_call_element *elem = elemp; call_data *calld = elem->call_data; if (GRPC_ERROR_NONE != grpc_byte_stream_pull(exec_ctx, calld->send_op->payload->send_message.send_message, &calld->incoming_slice)) { /* Should never reach here */ abort(); } grpc_slice_buffer_add(&calld->slices, calld->incoming_slice); if (calld->send_length == calld->slices.length) { finish_send_message(exec_ctx, elem); } else { continue_send_message(exec_ctx, elem); } }
static void compress_start_transport_stream_op(grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op *op) { call_data *calld = elem->call_data; GPR_TIMER_BEGIN("compress_start_transport_stream_op", 0); if (op->send_initial_metadata) { process_send_initial_metadata(elem, op->send_initial_metadata); } if (op->send_message != NULL && !skip_compression(elem) && 0 == (op->send_message->flags & GRPC_WRITE_NO_COMPRESS)) { calld->send_op = *op; calld->send_length = op->send_message->length; calld->send_flags = op->send_message->flags; continue_send_message(exec_ctx, elem); } else { /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); } GPR_TIMER_END("compress_start_transport_stream_op", 0); }
static void compress_start_transport_stream_op_batch( grpc_exec_ctx *exec_ctx, grpc_call_element *elem, grpc_transport_stream_op_batch *op) { call_data *calld = elem->call_data; GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0); if (op->cancel_stream) { GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error); gpr_atm cur = gpr_atm_full_xchg( &calld->send_initial_metadata_state, CANCELLED_BIT | (gpr_atm)op->payload->cancel_stream.cancel_error); switch (cur) { case HAS_COMPRESSION_ALGORITHM: case NO_COMPRESSION_ALGORITHM: case INITIAL_METADATA_UNSEEN: break; default: if ((cur & CANCELLED_BIT) == 0) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, (grpc_transport_stream_op_batch *)cur, GRPC_ERROR_REF(op->payload->cancel_stream.cancel_error)); } else { GRPC_ERROR_UNREF((grpc_error *)(cur & ~CANCELLED_BIT)); } break; } } if (op->send_initial_metadata) { bool has_compression_algorithm; grpc_error *error = process_send_initial_metadata( exec_ctx, elem, op->payload->send_initial_metadata.send_initial_metadata, &has_compression_algorithm); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, op, error); return; } gpr_atm cur; retry_send_im: cur = gpr_atm_acq_load(&calld->send_initial_metadata_state); GPR_ASSERT(cur != HAS_COMPRESSION_ALGORITHM && cur != NO_COMPRESSION_ALGORITHM); if ((cur & CANCELLED_BIT) == 0) { if (!gpr_atm_rel_cas(&calld->send_initial_metadata_state, cur, has_compression_algorithm ? HAS_COMPRESSION_ALGORITHM : NO_COMPRESSION_ALGORITHM)) { goto retry_send_im; } if (cur != INITIAL_METADATA_UNSEEN) { grpc_call_next_op(exec_ctx, elem, (grpc_transport_stream_op_batch *)cur); } } } if (op->send_message) { gpr_atm cur; retry_send: cur = gpr_atm_acq_load(&calld->send_initial_metadata_state); switch (cur) { case INITIAL_METADATA_UNSEEN: if (!gpr_atm_rel_cas(&calld->send_initial_metadata_state, cur, (gpr_atm)op)) { goto retry_send; } break; case HAS_COMPRESSION_ALGORITHM: case NO_COMPRESSION_ALGORITHM: if (!skip_compression(elem, op->payload->send_message.send_message->flags, cur == HAS_COMPRESSION_ALGORITHM)) { calld->send_op = op; calld->send_length = op->payload->send_message.send_message->length; calld->send_flags = op->payload->send_message.send_message->flags; continue_send_message(exec_ctx, elem); } else { /* pass control down the stack */ grpc_call_next_op(exec_ctx, elem, op); } break; default: if (cur & CANCELLED_BIT) { grpc_transport_stream_op_batch_finish_with_failure( exec_ctx, op, GRPC_ERROR_REF((grpc_error *)(cur & ~CANCELLED_BIT))); } else { /* >1 send_message concurrently */ GPR_UNREACHABLE_CODE(break); } } } else {