void grpc_chttp2_list_add_writing_stalled_by_transport( grpc_chttp2_transport_writing *transport_writing, grpc_chttp2_stream_writing *stream_writing) { grpc_chttp2_stream *stream = STREAM_FROM_WRITING(stream_writing); gpr_log(GPR_DEBUG, "writing stalled %d", stream->global.id); if (!stream->included[GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT]) { GRPC_CHTTP2_STREAM_REF(&stream->global, "chttp2_writing_stalled"); } stream_list_add(TRANSPORT_FROM_WRITING(transport_writing), stream, GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT); }
int grpc_chttp2_unlocking_check_writes( grpc_chttp2_transport_global *transport_global, grpc_chttp2_transport_writing *transport_writing, int is_parsing) { grpc_chttp2_stream_global *stream_global; grpc_chttp2_stream_writing *stream_writing; GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0); /* simple writes are queued to qbuf, and flushed here */ gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); GPR_ASSERT(transport_global->qbuf.count == 0); grpc_chttp2_hpack_compressor_set_max_table_size( &transport_writing->hpack_compressor, transport_global->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); if (transport_global->dirtied_local_settings && !transport_global->sent_local_settings && !is_parsing) { gpr_slice_buffer_add( &transport_writing->outbuf, grpc_chttp2_settings_create( transport_global->settings[GRPC_SENT_SETTINGS], transport_global->settings[GRPC_LOCAL_SETTINGS], transport_global->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS)); transport_global->force_send_settings = 0; transport_global->dirtied_local_settings = 0; transport_global->sent_local_settings = 1; } GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, transport_global, outgoing_window); bool is_window_available = transport_writing->outgoing_window > 0; grpc_chttp2_list_flush_writing_stalled_by_transport(transport_writing, is_window_available); /* for each grpc_chttp2_stream that's become writable, frame it's data (according to available window sizes) and add to the output buffer */ while (grpc_chttp2_list_pop_writable_stream( transport_global, transport_writing, &stream_global, &stream_writing)) { uint8_t sent_initial_metadata; stream_writing->id = stream_global->id; stream_writing->read_closed = stream_global->read_closed; GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_writing, stream_writing, outgoing_window, stream_global, outgoing_window); sent_initial_metadata = stream_writing->sent_initial_metadata; if (!sent_initial_metadata && stream_global->send_initial_metadata) { stream_writing->send_initial_metadata = stream_global->send_initial_metadata; stream_global->send_initial_metadata = NULL; if (grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing)) { GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); } sent_initial_metadata = 1; } if (sent_initial_metadata) { if (stream_global->send_message != NULL) { gpr_slice hdr = gpr_slice_malloc(5); uint8_t *p = GPR_SLICE_START_PTR(hdr); uint32_t len = stream_global->send_message->length; GPR_ASSERT(stream_writing->send_message == NULL); p[0] = (stream_global->send_message->flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0; p[1] = (uint8_t)(len >> 24); p[2] = (uint8_t)(len >> 16); p[3] = (uint8_t)(len >> 8); p[4] = (uint8_t)(len); gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, hdr); if (stream_global->send_message->length > 0) { stream_writing->send_message = stream_global->send_message; } else { stream_writing->send_message = NULL; } stream_writing->stream_fetched = 0; stream_global->send_message = NULL; } if ((stream_writing->send_message != NULL || stream_writing->flow_controlled_buffer.length > 0) && stream_writing->outgoing_window > 0) { if (transport_writing->outgoing_window > 0) { if (grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing)) { GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); } } else { grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing, stream_writing); } } if (stream_global->send_trailing_metadata) { stream_writing->send_trailing_metadata = stream_global->send_trailing_metadata; stream_global->send_trailing_metadata = NULL; if (grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing)) { GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); } } } if (!stream_global->read_closed && stream_global->unannounced_incoming_window_for_writing > 1024) { GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing, announce_window, stream_global, unannounced_incoming_window_for_writing); if (grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing)) { GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing"); } } }