Craig Tiller | d8df50c | 2015-06-12 07:53:56 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
yang-g | 897925e | 2016-01-28 09:23:46 -0800 | [diff] [blame] | 3 | * Copyright 2015-2016, Google Inc. |
Craig Tiller | d8df50c | 2015-06-12 07:53:56 -0700 | [diff] [blame] | 4 | * All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions are |
| 8 | * met: |
| 9 | * |
| 10 | * * Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * * Redistributions in binary form must reproduce the above |
| 13 | * copyright notice, this list of conditions and the following disclaimer |
| 14 | * in the documentation and/or other materials provided with the |
| 15 | * distribution. |
| 16 | * * Neither the name of Google Inc. nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived from |
| 18 | * this software without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | * |
| 32 | */ |
| 33 | |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 34 | #include "src/core/lib/transport/chttp2/internal.h" |
Craig Tiller | f96dfc3 | 2015-09-10 14:43:18 -0700 | [diff] [blame] | 35 | |
| 36 | #include <limits.h> |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 37 | |
| 38 | #include <grpc/support/log.h> |
| 39 | |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 40 | #include "src/core/lib/profiling/timers.h" |
| 41 | #include "src/core/lib/transport/chttp2/http2_errors.h" |
Craig Tiller | f96dfc3 | 2015-09-10 14:43:18 -0700 | [diff] [blame] | 42 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 43 | static void finalize_outbuf(grpc_exec_ctx *exec_ctx, |
| 44 | grpc_chttp2_transport_writing *transport_writing); |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 45 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 46 | int grpc_chttp2_unlocking_check_writes( |
yang-g | 276e32d | 2016-02-22 13:15:30 -0800 | [diff] [blame] | 47 | grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, |
Craig Tiller | 3c53bb2 | 2015-11-10 14:24:36 +0000 | [diff] [blame] | 48 | grpc_chttp2_transport_writing *transport_writing, int is_parsing) { |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 49 | grpc_chttp2_stream_global *stream_global; |
| 50 | grpc_chttp2_stream_writing *stream_writing; |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 51 | |
| 52 | GPR_TIMER_BEGIN("grpc_chttp2_unlocking_check_writes", 0); |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 53 | |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 54 | /* simple writes are queued to qbuf, and flushed here */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 55 | gpr_slice_buffer_swap(&transport_global->qbuf, &transport_writing->outbuf); |
| 56 | GPR_ASSERT(transport_global->qbuf.count == 0); |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 57 | |
Craig Tiller | 3c53bb2 | 2015-11-10 14:24:36 +0000 | [diff] [blame] | 58 | grpc_chttp2_hpack_compressor_set_max_table_size( |
| 59 | &transport_writing->hpack_compressor, |
| 60 | transport_global->settings[GRPC_PEER_SETTINGS] |
| 61 | [GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE]); |
Craig Tiller | 027a74c | 2015-11-10 08:37:46 +0000 | [diff] [blame] | 62 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 63 | if (transport_global->dirtied_local_settings && |
Craig Tiller | 3c53bb2 | 2015-11-10 14:24:36 +0000 | [diff] [blame] | 64 | !transport_global->sent_local_settings && !is_parsing) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 65 | gpr_slice_buffer_add( |
| 66 | &transport_writing->outbuf, |
| 67 | grpc_chttp2_settings_create( |
| 68 | transport_global->settings[GRPC_SENT_SETTINGS], |
| 69 | transport_global->settings[GRPC_LOCAL_SETTINGS], |
| 70 | transport_global->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS)); |
| 71 | transport_global->force_send_settings = 0; |
| 72 | transport_global->dirtied_local_settings = 0; |
| 73 | transport_global->sent_local_settings = 1; |
| 74 | } |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 75 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 76 | GRPC_CHTTP2_FLOW_MOVE_TRANSPORT("write", transport_writing, outgoing_window, |
| 77 | transport_global, outgoing_window); |
yang-g | 6494e8b | 2016-02-05 23:54:03 -0800 | [diff] [blame] | 78 | bool is_window_available = transport_writing->outgoing_window > 0; |
yang-g | 276e32d | 2016-02-22 13:15:30 -0800 | [diff] [blame] | 79 | grpc_chttp2_list_flush_writing_stalled_by_transport( |
| 80 | exec_ctx, transport_writing, is_window_available); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 81 | |
Craig Tiller | 4aa71a1 | 2015-06-15 13:00:55 -0700 | [diff] [blame] | 82 | /* for each grpc_chttp2_stream that's become writable, frame it's data |
Craig Tiller | 994c262 | 2015-07-23 14:00:58 -0700 | [diff] [blame] | 83 | (according to available window sizes) and add to the output buffer */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 84 | while (grpc_chttp2_list_pop_writable_stream( |
| 85 | transport_global, transport_writing, &stream_global, &stream_writing)) { |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 86 | bool sent_initial_metadata = stream_writing->sent_initial_metadata; |
| 87 | bool become_writable = false; |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 88 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 89 | stream_writing->id = stream_global->id; |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 90 | stream_writing->read_closed = stream_global->read_closed; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 91 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 92 | GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_writing, stream_writing, |
| 93 | outgoing_window, stream_global, |
| 94 | outgoing_window); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 95 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 96 | if (!sent_initial_metadata && stream_global->send_initial_metadata) { |
| 97 | stream_writing->send_initial_metadata = |
| 98 | stream_global->send_initial_metadata; |
| 99 | stream_global->send_initial_metadata = NULL; |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 100 | become_writable = true; |
| 101 | sent_initial_metadata = true; |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 102 | } |
| 103 | if (sent_initial_metadata) { |
| 104 | if (stream_global->send_message != NULL) { |
| 105 | gpr_slice hdr = gpr_slice_malloc(5); |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 106 | uint8_t *p = GPR_SLICE_START_PTR(hdr); |
| 107 | uint32_t len = stream_global->send_message->length; |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 108 | GPR_ASSERT(stream_writing->send_message == NULL); |
| 109 | p[0] = (stream_global->send_message->flags & |
| 110 | GRPC_WRITE_INTERNAL_COMPRESS) != 0; |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 111 | p[1] = (uint8_t)(len >> 24); |
| 112 | p[2] = (uint8_t)(len >> 16); |
| 113 | p[3] = (uint8_t)(len >> 8); |
| 114 | p[4] = (uint8_t)(len); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 115 | gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, hdr); |
| 116 | if (stream_global->send_message->length > 0) { |
| 117 | stream_writing->send_message = stream_global->send_message; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 118 | } else { |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 119 | stream_writing->send_message = NULL; |
| 120 | } |
| 121 | stream_writing->stream_fetched = 0; |
| 122 | stream_global->send_message = NULL; |
| 123 | } |
| 124 | if ((stream_writing->send_message != NULL || |
| 125 | stream_writing->flow_controlled_buffer.length > 0) && |
| 126 | stream_writing->outgoing_window > 0) { |
| 127 | if (transport_writing->outgoing_window > 0) { |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 128 | become_writable = true; |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 129 | } else { |
yang-g | 276e32d | 2016-02-22 13:15:30 -0800 | [diff] [blame] | 130 | grpc_chttp2_list_add_stalled_by_transport(transport_writing, |
| 131 | stream_writing); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 132 | } |
| 133 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 134 | if (stream_global->send_trailing_metadata) { |
| 135 | stream_writing->send_trailing_metadata = |
| 136 | stream_global->send_trailing_metadata; |
| 137 | stream_global->send_trailing_metadata = NULL; |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 138 | become_writable = true; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 139 | } |
| 140 | } |
| 141 | |
| 142 | if (!stream_global->read_closed && |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 143 | stream_global->unannounced_incoming_window_for_writing > 1024) { |
| 144 | GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing, |
| 145 | announce_window, stream_global, |
| 146 | unannounced_incoming_window_for_writing); |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 147 | become_writable = true; |
| 148 | } |
| 149 | |
| 150 | if (become_writable) { |
| 151 | grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing); |
| 152 | } else { |
| 153 | GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 154 | } |
| 155 | } |
| 156 | |
Craig Tiller | 4aa71a1 | 2015-06-15 13:00:55 -0700 | [diff] [blame] | 157 | /* if the grpc_chttp2_transport is ready to send a window update, do so here |
Craig Tiller | ab63073 | 2015-06-25 11:20:01 -0700 | [diff] [blame] | 158 | also; 3/4 is a magic number that will likely get tuned soon */ |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 159 | if (transport_global->announce_incoming_window > 0) { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 160 | uint32_t announced = (uint32_t)GPR_MIN( |
| 161 | transport_global->announce_incoming_window, UINT32_MAX); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 162 | GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_global, |
| 163 | announce_incoming_window, announced); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 164 | gpr_slice_buffer_add(&transport_writing->outbuf, |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 165 | grpc_chttp2_window_update_create(0, announced)); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 166 | } |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 167 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 168 | GPR_TIMER_END("grpc_chttp2_unlocking_check_writes", 0); |
| 169 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 170 | return transport_writing->outbuf.count > 0 || |
| 171 | grpc_chttp2_list_have_writing_streams(transport_writing); |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 174 | void grpc_chttp2_perform_writes( |
| 175 | grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_writing *transport_writing, |
| 176 | grpc_endpoint *endpoint) { |
| 177 | GPR_ASSERT(transport_writing->outbuf.count > 0 || |
| 178 | grpc_chttp2_list_have_writing_streams(transport_writing)); |
Craig Tiller | cdf52bc | 2015-06-16 13:00:27 -0700 | [diff] [blame] | 179 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 180 | finalize_outbuf(exec_ctx, transport_writing); |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 181 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 182 | GPR_ASSERT(endpoint); |
Craig Tiller | f932fd5 | 2015-06-17 07:38:20 -0700 | [diff] [blame] | 183 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 184 | if (transport_writing->outbuf.count > 0) { |
| 185 | grpc_endpoint_write(exec_ctx, endpoint, &transport_writing->outbuf, |
| 186 | &transport_writing->done_cb); |
| 187 | } else { |
Craig Tiller | 6c39686 | 2016-01-28 13:53:40 -0800 | [diff] [blame] | 188 | grpc_exec_ctx_enqueue(exec_ctx, &transport_writing->done_cb, true, NULL); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 189 | } |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 190 | } |
| 191 | |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 192 | static void finalize_outbuf(grpc_exec_ctx *exec_ctx, |
| 193 | grpc_chttp2_transport_writing *transport_writing) { |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 194 | grpc_chttp2_stream_writing *stream_writing; |
| 195 | |
Craig Tiller | 0ba432d | 2015-10-09 16:57:11 -0700 | [diff] [blame] | 196 | GPR_TIMER_BEGIN("finalize_outbuf", 0); |
Craig Tiller | 1f41b6b | 2015-10-09 15:07:02 -0700 | [diff] [blame] | 197 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 198 | while ( |
| 199 | grpc_chttp2_list_pop_writing_stream(transport_writing, &stream_writing)) { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 200 | uint32_t max_outgoing = |
| 201 | (uint32_t)GPR_MIN(GRPC_CHTTP2_MAX_PAYLOAD_LENGTH, |
| 202 | GPR_MIN(stream_writing->outgoing_window, |
| 203 | transport_writing->outgoing_window)); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 204 | /* send initial metadata if it's available */ |
| 205 | if (stream_writing->send_initial_metadata != NULL) { |
| 206 | grpc_chttp2_encode_header( |
| 207 | &transport_writing->hpack_compressor, stream_writing->id, |
| 208 | stream_writing->send_initial_metadata, 0, &transport_writing->outbuf); |
| 209 | stream_writing->send_initial_metadata = NULL; |
| 210 | stream_writing->sent_initial_metadata = 1; |
Craig Tiller | 8631652 | 2015-07-15 11:35:07 -0700 | [diff] [blame] | 211 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 212 | /* send any window updates */ |
| 213 | if (stream_writing->announce_window > 0 && |
| 214 | stream_writing->send_initial_metadata == NULL) { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 215 | uint32_t announce = stream_writing->announce_window; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 216 | gpr_slice_buffer_add( |
| 217 | &transport_writing->outbuf, |
| 218 | grpc_chttp2_window_update_create(stream_writing->id, |
| 219 | stream_writing->announce_window)); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 220 | GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, stream_writing, |
| 221 | announce_window, announce); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 222 | stream_writing->announce_window = 0; |
| 223 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 224 | /* fetch any body bytes */ |
| 225 | while (!stream_writing->fetching && stream_writing->send_message && |
| 226 | stream_writing->flow_controlled_buffer.length < max_outgoing && |
| 227 | stream_writing->stream_fetched < |
| 228 | stream_writing->send_message->length) { |
| 229 | if (grpc_byte_stream_next(exec_ctx, stream_writing->send_message, |
| 230 | &stream_writing->fetching_slice, max_outgoing, |
| 231 | &stream_writing->finished_fetch)) { |
| 232 | stream_writing->stream_fetched += |
| 233 | GPR_SLICE_LENGTH(stream_writing->fetching_slice); |
| 234 | if (stream_writing->stream_fetched == |
| 235 | stream_writing->send_message->length) { |
| 236 | stream_writing->send_message = NULL; |
| 237 | } |
| 238 | gpr_slice_buffer_add(&stream_writing->flow_controlled_buffer, |
| 239 | stream_writing->fetching_slice); |
| 240 | } else { |
| 241 | stream_writing->fetching = 1; |
| 242 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 243 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 244 | /* send any body bytes */ |
| 245 | if (stream_writing->flow_controlled_buffer.length > 0) { |
| 246 | if (max_outgoing > 0) { |
Craig Tiller | 7536af0 | 2015-12-22 13:49:30 -0800 | [diff] [blame] | 247 | uint32_t send_bytes = (uint32_t)GPR_MIN( |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 248 | max_outgoing, stream_writing->flow_controlled_buffer.length); |
| 249 | int is_last_data_frame = |
| 250 | stream_writing->send_message == NULL && |
| 251 | send_bytes == stream_writing->flow_controlled_buffer.length; |
| 252 | int is_last_frame = is_last_data_frame && |
| 253 | stream_writing->send_trailing_metadata != NULL && |
| 254 | grpc_metadata_batch_is_empty( |
| 255 | stream_writing->send_trailing_metadata); |
| 256 | grpc_chttp2_encode_data( |
| 257 | stream_writing->id, &stream_writing->flow_controlled_buffer, |
| 258 | send_bytes, is_last_frame, &transport_writing->outbuf); |
| 259 | GRPC_CHTTP2_FLOW_DEBIT_STREAM("write", transport_writing, |
| 260 | stream_writing, outgoing_window, |
| 261 | send_bytes); |
| 262 | GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("write", transport_writing, |
| 263 | outgoing_window, send_bytes); |
| 264 | if (is_last_frame) { |
| 265 | stream_writing->send_trailing_metadata = NULL; |
| 266 | stream_writing->sent_trailing_metadata = 1; |
| 267 | } |
| 268 | if (is_last_data_frame) { |
| 269 | GPR_ASSERT(stream_writing->send_message == NULL); |
| 270 | stream_writing->sent_message = 1; |
| 271 | } |
| 272 | } else if (transport_writing->outgoing_window == 0) { |
yang-g | 348f3a2 | 2016-01-27 16:17:32 -0800 | [diff] [blame] | 273 | grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing, |
| 274 | stream_writing); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 275 | grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); |
| 276 | } |
| 277 | } |
| 278 | /* send trailing metadata if it's available and we're ready for it */ |
| 279 | if (stream_writing->send_message == NULL && |
| 280 | stream_writing->flow_controlled_buffer.length == 0 && |
| 281 | stream_writing->send_trailing_metadata != NULL) { |
| 282 | if (grpc_metadata_batch_is_empty( |
| 283 | stream_writing->send_trailing_metadata)) { |
| 284 | grpc_chttp2_encode_data(stream_writing->id, |
| 285 | &stream_writing->flow_controlled_buffer, 0, 1, |
| 286 | &transport_writing->outbuf); |
| 287 | } else { |
| 288 | grpc_chttp2_encode_header(&transport_writing->hpack_compressor, |
| 289 | stream_writing->id, |
| 290 | stream_writing->send_trailing_metadata, 1, |
| 291 | &transport_writing->outbuf); |
| 292 | } |
| 293 | if (!transport_writing->is_client && !stream_writing->read_closed) { |
| 294 | gpr_slice_buffer_add(&transport_writing->outbuf, |
| 295 | grpc_chttp2_rst_stream_create( |
| 296 | stream_writing->id, GRPC_CHTTP2_NO_ERROR)); |
| 297 | } |
| 298 | stream_writing->send_trailing_metadata = NULL; |
| 299 | stream_writing->sent_trailing_metadata = 1; |
| 300 | } |
| 301 | /* if there's more to write, then loop, otherwise prepare to finish the |
| 302 | * write */ |
| 303 | if ((stream_writing->flow_controlled_buffer.length > 0 || |
| 304 | (stream_writing->send_message && !stream_writing->fetching)) && |
| 305 | stream_writing->outgoing_window > 0) { |
| 306 | if (transport_writing->outgoing_window > 0) { |
Craig Tiller | 0cb803d | 2016-03-02 22:17:24 -0800 | [diff] [blame] | 307 | grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 308 | } else { |
yang-g | 348f3a2 | 2016-01-27 16:17:32 -0800 | [diff] [blame] | 309 | grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing, |
| 310 | stream_writing); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 311 | grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); |
| 312 | } |
| 313 | } else { |
| 314 | grpc_chttp2_list_add_written_stream(transport_writing, stream_writing); |
| 315 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 316 | } |
Craig Tiller | 61ead3e | 2015-11-03 11:03:48 -0800 | [diff] [blame] | 317 | |
| 318 | GPR_TIMER_END("finalize_outbuf", 0); |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 319 | } |
| 320 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 321 | void grpc_chttp2_cleanup_writing( |
| 322 | grpc_exec_ctx *exec_ctx, grpc_chttp2_transport_global *transport_global, |
| 323 | grpc_chttp2_transport_writing *transport_writing) { |
Craig Tiller | d20efd2 | 2015-06-12 16:17:09 -0700 | [diff] [blame] | 324 | grpc_chttp2_stream_writing *stream_writing; |
| 325 | grpc_chttp2_stream_global *stream_global; |
yang-g | 348f3a2 | 2016-01-27 16:17:32 -0800 | [diff] [blame] | 326 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 327 | while (grpc_chttp2_list_pop_written_stream( |
| 328 | transport_global, transport_writing, &stream_global, &stream_writing)) { |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 329 | if (stream_writing->sent_initial_metadata) { |
| 330 | grpc_chttp2_complete_closure_step( |
| 331 | exec_ctx, &stream_global->send_initial_metadata_finished, 1); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 332 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 333 | if (stream_writing->sent_message) { |
| 334 | GPR_ASSERT(stream_writing->send_message == NULL); |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 335 | grpc_chttp2_complete_closure_step( |
| 336 | exec_ctx, &stream_global->send_message_finished, 1); |
| 337 | stream_writing->sent_message = 0; |
| 338 | } |
| 339 | if (stream_writing->sent_trailing_metadata) { |
| 340 | grpc_chttp2_complete_closure_step( |
| 341 | exec_ctx, &stream_global->send_trailing_metadata_finished, 1); |
| 342 | } |
Craig Tiller | 4579846 | 2015-12-14 21:42:53 -0800 | [diff] [blame] | 343 | if (stream_writing->sent_trailing_metadata) { |
| 344 | grpc_chttp2_mark_stream_closed(exec_ctx, transport_global, stream_global, |
| 345 | !transport_global->is_client, 1); |
| 346 | } |
Craig Tiller | 9d35a1f | 2015-11-02 14:16:12 -0800 | [diff] [blame] | 347 | GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing"); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 348 | } |
| 349 | gpr_slice_buffer_reset_and_unref(&transport_writing->outbuf); |
Craig Tiller | 3208e39 | 2015-06-12 08:17:02 -0700 | [diff] [blame] | 350 | } |