| 2357 | } |
| 2358 | |
| 2359 | void |
| 2360 | Http2ConnectionState::send_data_frames(Http2Stream *stream) |
| 2361 | { |
| 2362 | // To follow RFC 7540 must not send more frames other than priority on |
| 2363 | // a closed stream. So we return without sending |
| 2364 | if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL || |
| 2365 | stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) { |
| 2366 | Http2StreamDebug(this->session, stream->get_id(), "Shutdown half closed local stream"); |
| 2367 | stream->initiating_close(); |
| 2368 | return; |
| 2369 | } |
| 2370 | |
| 2371 | if (zombie_event != nullptr) { |
| 2372 | zombie_event->cancel(); |
| 2373 | zombie_event = nullptr; |
| 2374 | } |
| 2375 | |
| 2376 | size_t len = 0; |
| 2377 | Http2SendDataFrameResult result = Http2SendDataFrameResult::NO_ERROR; |
| 2378 | bool more_data = true; |
| 2379 | IOBufferReader *resp_reader = stream->get_data_reader_for_send(); |
| 2380 | while (more_data && result == Http2SendDataFrameResult::NO_ERROR) { |
| 2381 | result = send_a_data_frame(stream, len); |
| 2382 | more_data = resp_reader->is_read_avail_more_than(0); |
| 2383 | |
| 2384 | if (result == Http2SendDataFrameResult::DONE) { |
| 2385 | if (!stream->is_outbound_connection()) { |
| 2386 | if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) { |
| 2387 | // Delete a stream immediately |
| 2388 | Http2StreamDebug(this->session, stream->get_id(), "Shutdown stream"); |
| 2389 | stream->signal_write_event(VC_EVENT_WRITE_COMPLETE); |
| 2390 | stream->do_io_close(); |
| 2391 | } else { |
| 2392 | // This stream waits for the END_STREAM in half-closed (local) state until `http.transaction_no_activity_timeout_in`. |
| 2393 | // If no frame with END_STREAM is found, ATS actively closes the stream. |
| 2394 | Http2StreamDebug(this->session, stream->get_id(), "waiting END_STREAM"); |
| 2395 | } |
| 2396 | } else if (stream->is_outbound_connection() && stream->is_write_vio_done()) { |
| 2397 | stream->signal_write_event(VC_EVENT_WRITE_COMPLETE); |
| 2398 | } else { |
| 2399 | ink_release_assert(!"What case is this?"); |
| 2400 | } |
| 2401 | } else if (result == Http2SendDataFrameResult::NOT_WRITE_AVAIL) { |
| 2402 | // Schedule an even to wake up and try to resend the stream. |
| 2403 | schedule_stream_to_send_data_frames(stream); |
| 2404 | } |
| 2405 | } |
| 2406 | if (!more_data && result != Http2SendDataFrameResult::DONE) { |
| 2407 | stream->signal_write_event(VC_EVENT_WRITE_READY); |
| 2408 | } |
| 2409 | |
| 2410 | return; |
| 2411 | } |
| 2412 | |
| 2413 | void |
| 2414 | Http2ConnectionState::send_headers_frame(Http2Stream *stream) |
no test coverage detected