Example #1
0
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;
      }
    }
Example #2
0
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);
    }
}
Example #3
0
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);
  }
}
Example #5
0
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 {