예제 #1
0
static void hc_mutate_op(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) {
    grpc_metadata_batch_filter(op->send_initial_metadata, client_strip_filter,
                               elem);
    /* Send : prefixed headers, which have to be before any application
       layer headers. */
    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->method,
                                 GRPC_MDELEM_METHOD_POST);
    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->scheme,
                                 channeld->static_scheme);
    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->te_trailers,
                                 GRPC_MDELEM_TE_TRAILERS);
    grpc_metadata_batch_add_tail(
        op->send_initial_metadata, &calld->content_type,
        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
    grpc_metadata_batch_add_tail(op->send_initial_metadata, &calld->user_agent,
                                 GRPC_MDELEM_REF(channeld->user_agent));
  }

  if (op->recv_initial_metadata != NULL) {
    /* substitute our callback for the higher callback */
    calld->recv_initial_metadata = op->recv_initial_metadata;
    calld->on_done_recv = op->on_complete;
    op->on_complete = &calld->hc_on_recv;
  }
}
static void hs_mutate_op(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;
  size_t i;

  if (op->send_ops && !calld->sent_status) {
    size_t nops = op->send_ops->nops;
    grpc_stream_op *ops = op->send_ops->ops;
    for (i = 0; i < nops; i++) {
      grpc_stream_op *op = &ops[i];
      if (op->type != GRPC_OP_METADATA) continue;
      calld->sent_status = 1;
      grpc_metadata_batch_add_head(&op->data.metadata, &calld->status,
                                   GRPC_MDELEM_REF(channeld->status_ok));
      grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
                                   GRPC_MDELEM_REF(channeld->content_type));
      break;
    }
  }

  if (op->recv_ops && !calld->got_initial_metadata) {
    /* substitute our callback for the higher callback */
    calld->recv_ops = op->recv_ops;
    calld->on_done_recv = op->on_done_recv;
    op->on_done_recv = &calld->hs_on_recv;
  }
}
예제 #3
0
/* Called either:
     - in response to an API call (or similar) from above, to send something
     - a network event (or similar) from below, to receive something
   op contains type and call direction information, in addition to the data
   that is being sent or received. */
static void call_op(grpc_call_element *elem, grpc_call_element *from_elem,
                    grpc_call_op *op) {
  /* grab pointers to our data from the call element */
  call_data *calld = elem->call_data;
  channel_data *channeld = elem->channel_data;
  GRPC_CALL_LOG_OP(GPR_INFO, elem, op);

  switch (op->type) {
    case GRPC_RECV_METADATA:
      grpc_metadata_batch_filter(&op->data.metadata, server_filter, elem);
      if (!calld->got_initial_metadata) {
        calld->got_initial_metadata = 1;
        /* Have we seen the required http2 transport headers?
           (:method, :scheme, content-type, with :path and :authority covered
           at the channel level right now) */
        if (calld->seen_post && calld->seen_scheme && calld->seen_te_trailers &&
            calld->seen_path) {
          grpc_call_next_op(elem, op);
        } else {
          if (!calld->seen_path) {
            gpr_log(GPR_ERROR, "Missing :path header");
          }
          if (!calld->seen_post) {
            gpr_log(GPR_ERROR, "Missing :method header");
          }
          if (!calld->seen_scheme) {
            gpr_log(GPR_ERROR, "Missing :scheme header");
          }
          if (!calld->seen_te_trailers) {
            gpr_log(GPR_ERROR, "Missing te trailers header");
          }
          /* Error this call out */
          grpc_metadata_batch_destroy(&op->data.metadata);
          op->done_cb(op->user_data, GRPC_OP_OK);
          grpc_call_element_send_cancel(elem);
        }
      } else {
        grpc_call_next_op(elem, op);
      }
      break;
    case GRPC_SEND_METADATA:
      /* If we haven't sent status 200 yet, we need to so so because it needs to
         come before any non : prefixed metadata. */
      if (!calld->sent_status) {
        calld->sent_status = 1;
        grpc_metadata_batch_add_head(&op->data.metadata, &calld->status,
                                     grpc_mdelem_ref(channeld->status_ok));
      }
      grpc_call_next_op(elem, op);
      break;
    default:
      /* pass control up or down the stack depending on op->dir */
      grpc_call_next_op(elem, op);
      break;
  }
}
예제 #4
0
static void hc_mutate_op(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;
  size_t i;
  if (op->send_ops && !calld->sent_initial_metadata) {
    size_t nops = op->send_ops->nops;
    grpc_stream_op *ops = op->send_ops->ops;
    for (i = 0; i < nops; i++) {
      grpc_stream_op *op = &ops[i];
      if (op->type != GRPC_OP_METADATA) continue;
      calld->sent_initial_metadata = 1;
      grpc_metadata_batch_filter(&op->data.metadata, client_strip_filter, elem);
      /* Send : prefixed headers, which have to be before any application
         layer headers. */
      grpc_metadata_batch_add_head(&op->data.metadata, &calld->method,
                                   GRPC_MDELEM_REF(channeld->method));
      grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme,
                                   GRPC_MDELEM_REF(channeld->scheme));
      grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers,
                                   GRPC_MDELEM_REF(channeld->te_trailers));
      grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
                                   GRPC_MDELEM_REF(channeld->content_type));
      grpc_metadata_batch_add_tail(&op->data.metadata, &calld->user_agent,
                                   GRPC_MDELEM_REF(channeld->user_agent));
      break;
    }
  }

  if (op->recv_ops && !calld->got_initial_metadata) {
    /* substitute our callback for the higher callback */
    calld->recv_ops = op->recv_ops;
    calld->on_done_recv = op->on_done_recv;
    op->on_done_recv = &calld->hc_on_recv;
  }
}
예제 #5
0
static void hs_mutate_op(grpc_call_element *elem,
                         grpc_transport_stream_op *op) {
  /* grab pointers to our data from the call element */
  call_data *calld = elem->call_data;

  if (op->send_initial_metadata != NULL && !calld->sent_status) {
    calld->sent_status = 1;
    grpc_metadata_batch_add_head(op->send_initial_metadata, &calld->status,
                                 GRPC_MDELEM_STATUS_200);
    grpc_metadata_batch_add_tail(
        op->send_initial_metadata, &calld->content_type,
        GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC);
  }

  if (op->recv_initial_metadata) {
    /* substitute our callback for the higher callback */
    GPR_ASSERT(op->recv_idempotent_request != NULL);
    calld->recv_initial_metadata = op->recv_initial_metadata;
    calld->recv_idempotent_request = op->recv_idempotent_request;
    calld->on_done_recv = op->recv_initial_metadata_ready;
    op->recv_initial_metadata_ready = &calld->hs_on_recv;
  }
}
예제 #6
0
/** Filter's "main" function, called for any incoming grpc_transport_stream_op
 * instance that holds a non-zero number of send operations, accesible to this
 * function in \a send_ops.  */
static void process_send_ops(grpc_call_element *elem,
                             grpc_stream_op_buffer *send_ops) {
    call_data *calld = elem->call_data;
    channel_data *channeld = elem->channel_data;
    size_t i;
    int did_compress = 0;

    /* In streaming calls, we need to reset the previously accumulated slices */
    gpr_slice_buffer_reset_and_unref(&calld->slices);
    for (i = 0; i < send_ops->nops; ++i) {
        grpc_stream_op *sop = &send_ops->ops[i];
        switch (sop->type) {
        case GRPC_OP_BEGIN_MESSAGE:
            /* buffer up slices until we've processed all the expected ones (as
             * given by GRPC_OP_BEGIN_MESSAGE) */
            calld->remaining_slice_bytes = sop->data.begin_message.length;
            if (sop->data.begin_message.flags & GRPC_WRITE_NO_COMPRESS) {
                calld->has_compression_algorithm = 1; /* GPR_TRUE */
                calld->compression_algorithm = GRPC_COMPRESS_NONE;
            }
            break;
        case GRPC_OP_METADATA:
            if (!calld->written_initial_metadata) {
                /* Parse incoming request for compression. If any, it'll be available
                 * at calld->compression_algorithm */
                grpc_metadata_batch_filter(&(sop->data.metadata),
                                           compression_md_filter, elem);
                if (!calld->has_compression_algorithm) {
                    /* If no algorithm was found in the metadata and we aren't
                     * exceptionally skipping compression, fall back to the channel
                     * default */
                    calld->compression_algorithm =
                        channeld->default_compression_algorithm;
                    calld->has_compression_algorithm = 1; /* GPR_TRUE */
                }
                /* hint compression algorithm */
                grpc_metadata_batch_add_tail(
                    &(sop->data.metadata), &calld->compression_algorithm_storage,
                    GRPC_MDELEM_REF(channeld->mdelem_compression_algorithms
                                    [calld->compression_algorithm]));

                /* convey supported compression algorithms */
                grpc_metadata_batch_add_head(
                    &(sop->data.metadata), &calld->accept_encoding_storage,
                    GRPC_MDELEM_REF(channeld->mdelem_accept_encoding));

                calld->written_initial_metadata = 1; /* GPR_TRUE */
            }
            break;
        case GRPC_OP_SLICE:
            if (skip_compression(channeld, calld)) continue;
            GPR_ASSERT(calld->remaining_slice_bytes > 0);
            /* Increase input ref count, gpr_slice_buffer_add takes ownership.  */
            gpr_slice_buffer_add(&calld->slices, gpr_slice_ref(sop->data.slice));
            calld->remaining_slice_bytes -= GPR_SLICE_LENGTH(sop->data.slice);
            if (calld->remaining_slice_bytes == 0) {
                did_compress =
                    compress_send_sb(calld->compression_algorithm, &calld->slices);
            }
            break;
        case GRPC_NO_OP:
            break;
        }
    }

    /* Modify the send_ops stream_op_buffer depending on whether compression was
     * carried out */
    if (did_compress) {
        finish_compressed_sopb(send_ops, elem);
    }
}