| 2260 | } |
| 2261 | |
| 2262 | Http2SendDataFrameResult |
| 2263 | Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_length) |
| 2264 | { |
| 2265 | const ssize_t window_size = std::min(this->get_peer_rwnd(), stream->get_peer_rwnd()); |
| 2266 | const size_t buf_len = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA]); |
| 2267 | const size_t write_available_size = std::min(buf_len, static_cast<size_t>(window_size)); |
| 2268 | payload_length = 0; |
| 2269 | |
| 2270 | uint8_t flags = 0x00; |
| 2271 | IOBufferReader *resp_reader = stream->get_data_reader_for_send(); |
| 2272 | |
| 2273 | SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread()); |
| 2274 | |
| 2275 | if (!resp_reader) { |
| 2276 | Http2StreamDebug(this->session, stream->get_id(), "couldn't get data reader"); |
| 2277 | return Http2SendDataFrameResult::ERROR; |
| 2278 | } |
| 2279 | |
| 2280 | // Select appropriate payload length |
| 2281 | if (resp_reader->is_read_avail_more_than(0)) { |
| 2282 | // We only need to check for window size when there is a payload |
| 2283 | if (window_size <= 0) { |
| 2284 | if (session->is_outbound()) { |
| 2285 | ip_port_text_buffer ipb; |
| 2286 | const char *server_ip = ats_ip_ntop(session->get_proxy_session()->get_remote_addr(), ipb, sizeof(ipb)); |
| 2287 | // Warn the user to give them visibility that their server-side |
| 2288 | // connection is being limited by their server's flow control. Maybe |
| 2289 | // they can make adjustments. |
| 2290 | Warning("No window server_ip=%s session_wnd=%zd stream_wnd=%zd peer_initial_window=%u", server_ip, get_peer_rwnd(), |
| 2291 | stream->get_peer_rwnd(), this->peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)); |
| 2292 | } |
| 2293 | Http2StreamDebug(this->session, stream->get_id(), "No window session_wnd=%zd stream_wnd=%zd peer_initial_window=%u", |
| 2294 | get_peer_rwnd(), stream->get_peer_rwnd(), this->peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE)); |
| 2295 | this->session->flush(); |
| 2296 | return Http2SendDataFrameResult::NO_WINDOW; |
| 2297 | } |
| 2298 | |
| 2299 | if (resp_reader->is_read_avail_more_than(write_available_size)) { |
| 2300 | payload_length = write_available_size; |
| 2301 | } else { |
| 2302 | payload_length = resp_reader->read_avail(); |
| 2303 | } |
| 2304 | } else { |
| 2305 | payload_length = 0; |
| 2306 | } |
| 2307 | |
| 2308 | // For HTTP/2 sessions, is_write_high_water() returning true correlates to |
| 2309 | // our write buffer exceeding HTTP2_SETTINGS_MAX_FRAME_SIZE. Thus we will |
| 2310 | // hold off on processing the payload until the write buffer is drained. |
| 2311 | if (payload_length > 0 && this->session->is_write_high_water()) { |
| 2312 | Http2StreamDebug(this->session, stream->get_id(), "Not write avail, payload_length=%zu", payload_length); |
| 2313 | this->session->flush(); |
| 2314 | return Http2SendDataFrameResult::NOT_WRITE_AVAIL; |
| 2315 | } |
| 2316 | |
| 2317 | stream->update_sent_count(payload_length); |
| 2318 | |
| 2319 | // Are we at the end? |
nothing calls this directly
no test coverage detected