Beispiel #1
0
void grpc_sopb_move_to(grpc_stream_op_buffer *src, grpc_stream_op_buffer *dst) {
  if (src->nops == 0) {
    return;
  }
  if (dst->nops == 0) {
    grpc_sopb_swap(src, dst);
    return;
  }
  grpc_sopb_append(dst, src->ops, src->nops);
  src->nops = 0;
}
Beispiel #2
0
/** Assembles a new grpc_stream_op_buffer with the compressed slices, modifying
 * the associated GRPC_OP_BEGIN_MESSAGE accordingly (new compressed length,
 * flags indicating compression is in effect) and replaces \a send_ops with it.
 * */
static void finish_compressed_sopb(grpc_stream_op_buffer *send_ops,
                                   grpc_call_element *elem) {
  size_t i;
  call_data *calld = elem->call_data;
  int new_slices_added = 0; /* GPR_FALSE */
  grpc_metadata_batch metadata;
  grpc_stream_op_buffer new_send_ops;
  grpc_sopb_init(&new_send_ops);

  for (i = 0; i < send_ops->nops; i++) {
    grpc_stream_op *sop = &send_ops->ops[i];
    switch (sop->type) {
      case GRPC_OP_BEGIN_MESSAGE:
        GPR_ASSERT(calld->slices.length <= GPR_UINT32_MAX);
        grpc_sopb_add_begin_message(
            &new_send_ops, (gpr_uint32)calld->slices.length,
            sop->data.begin_message.flags | GRPC_WRITE_INTERNAL_COMPRESS);
        break;
      case GRPC_OP_SLICE:
        /* Once we reach the slices section of the original buffer, simply add
         * all the new (compressed) slices. We obviously want to do this only
         * once, hence the "new_slices_added" guard. */
        if (!new_slices_added) {
          size_t j;
          for (j = 0; j < calld->slices.count; ++j) {
            grpc_sopb_add_slice(&new_send_ops,
                                gpr_slice_ref(calld->slices.slices[j]));
          }
          new_slices_added = 1; /* GPR_TRUE */
        }
        break;
      case GRPC_OP_METADATA:
        /* move the metadata to the new buffer. */
        grpc_metadata_batch_move(&metadata, &sop->data.metadata);
        grpc_sopb_add_metadata(&new_send_ops, metadata);
        break;
      case GRPC_NO_OP:
        break;
    }
  }
  grpc_sopb_swap(send_ops, &new_send_ops);
  grpc_sopb_destroy(&new_send_ops);
}
Beispiel #3
0
static void unlock_check_read_write_state(grpc_chttp2_transport *t) {
  grpc_chttp2_transport_global *transport_global = &t->global;
  grpc_chttp2_stream_global *stream_global;
  grpc_stream_state state;

  if (!t->parsing_active) {
    /* if a stream is in the stream map, and gets cancelled, we need to ensure
       we are not parsing before continuing the cancellation to keep things in
       a sane state */
    while (grpc_chttp2_list_pop_closed_waiting_for_parsing(transport_global,
                                                           &stream_global)) {
      GPR_ASSERT(stream_global->in_stream_map);
      GPR_ASSERT(stream_global->write_state != GRPC_WRITE_STATE_OPEN);
      GPR_ASSERT(stream_global->read_closed);
      remove_stream(t, stream_global->id);
      grpc_chttp2_list_add_read_write_state_changed(transport_global,
                                                    stream_global);
    }
  }

  while (grpc_chttp2_list_pop_read_write_state_changed(transport_global,
                                                       &stream_global)) {
    if (stream_global->cancelled) {
      stream_global->write_state = GRPC_WRITE_STATE_SENT_CLOSE;
      stream_global->read_closed = 1;
      if (!stream_global->published_cancelled) {
        char buffer[GPR_LTOA_MIN_BUFSIZE];
        gpr_ltoa(stream_global->cancelled_status, buffer);
        grpc_chttp2_incoming_metadata_buffer_add(&stream_global->incoming_metadata,
          grpc_mdelem_from_strings(t->metadata_context, "grpc-status", buffer));
        grpc_chttp2_incoming_metadata_buffer_place_metadata_batch_into(
          &stream_global->incoming_metadata,
          &stream_global->incoming_sopb);
        stream_global->published_cancelled = 1;
      }
    }
    if (stream_global->write_state == GRPC_WRITE_STATE_SENT_CLOSE &&
        stream_global->read_closed && stream_global->in_stream_map) {
      if (t->parsing_active) {
        grpc_chttp2_list_add_closed_waiting_for_parsing(transport_global,
                                                        stream_global);
      } else {
        remove_stream(t, stream_global->id);
      }
    }
    if (!stream_global->publish_sopb) {
      continue;
    }
    /* FIXME(ctiller): we include in_stream_map in our computation of
       whether the stream is write-closed. This is completely bogus,
       but has the effect of delaying stream-closed until the stream
       is indeed evicted from the stream map, making it safe to delete.
       To fix this will require having an edge after stream-closed
       indicating that the stream is closed AND safe to delete. */
    state = compute_state(
        stream_global->write_state == GRPC_WRITE_STATE_SENT_CLOSE &&
            !stream_global->in_stream_map,
        stream_global->read_closed);
    if (stream_global->incoming_sopb.nops == 0 &&
        state == stream_global->published_state) {
      continue;
    }
    grpc_chttp2_incoming_metadata_buffer_postprocess_sopb_and_begin_live_op(
        &stream_global->incoming_metadata, &stream_global->incoming_sopb,
        &stream_global->outstanding_metadata);
    grpc_sopb_swap(stream_global->publish_sopb, &stream_global->incoming_sopb);
    stream_global->published_state = *stream_global->publish_state = state;
    grpc_chttp2_schedule_closure(transport_global,
                                 stream_global->recv_done_closure, 1);
    stream_global->recv_done_closure = NULL;
    stream_global->publish_sopb = NULL;
    stream_global->publish_state = NULL;
  }
}