| 1785 | } |
| 1786 | |
| 1787 | void h2_stream_on_output_change(h2_stream *stream) |
| 1788 | { |
| 1789 | conn_rec *c1 = stream->session->c1; |
| 1790 | apr_status_t rv = APR_EAGAIN; |
| 1791 | |
| 1792 | /* stream->pout_recv_write signalled a change. Check what has happend, read |
| 1793 | * from it and act on seeing a response/data. */ |
| 1794 | H2_STRM_ASSERT_MAGIC(stream, H2_STRM_MAGIC_OK); |
| 1795 | if (!stream->output) { |
| 1796 | /* c2 has not assigned the output beam to the stream (yet). */ |
| 1797 | ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c1, |
| 1798 | H2_STRM_MSG(stream, "read_output, no output beam registered")); |
| 1799 | } |
| 1800 | else if (h2_stream_is_at_or_past(stream, H2_SS_CLOSED)) { |
| 1801 | ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c1, |
| 1802 | H2_STRM_LOG(APLOGNO(10301), stream, "already closed")); |
| 1803 | } |
| 1804 | else if (h2_stream_is_at(stream, H2_SS_CLOSED_L)) { |
| 1805 | /* We have delivered a response to a stream that was not closed |
| 1806 | * by the client. This could be a POST with body that we negate |
| 1807 | * and we need to RST_STREAM to end if. */ |
| 1808 | ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c1, |
| 1809 | H2_STRM_LOG(APLOGNO(10313), stream, "remote close missing")); |
| 1810 | h2_stream_rst(stream, H2_ERR_NO_ERROR); |
| 1811 | } |
| 1812 | else { |
| 1813 | /* stream is not closed, a change in output happened. There are |
| 1814 | * two modes of operation here: |
| 1815 | * 1) the final response has been submitted. nghttp2 is invoking |
| 1816 | * stream_data_cb() to progress the stream. This handles DATA, |
| 1817 | * trailers, EOS and ERRORs. |
| 1818 | * When stream_data_cb() runs out of things to send, it returns |
| 1819 | * NGHTTP2_ERR_DEFERRED and nghttp2 *suspends* further processing |
| 1820 | * until we tell it to resume. |
| 1821 | * 2) We have not seen the *final* response yet. The stream can not |
| 1822 | * send any response DATA. The nghttp2 stream_data_cb() is not |
| 1823 | * invoked. We need to receive output, expecting not DATA but |
| 1824 | * RESPONSEs (intermediate may arrive) and submit those. On |
| 1825 | * the final response, nghttp2 will start calling stream_data_cb(). |
| 1826 | */ |
| 1827 | if (stream->response) { |
| 1828 | nghttp2_session_resume_data(stream->session->ngh2, stream->id); |
| 1829 | ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c1, |
| 1830 | H2_STRM_MSG(stream, "resumed")); |
| 1831 | } |
| 1832 | else { |
| 1833 | stream_do_responses(stream); |
| 1834 | if (!stream->rst_error) { |
| 1835 | nghttp2_session_resume_data(stream->session->ngh2, stream->id); |
| 1836 | } |
| 1837 | } |
| 1838 | } |
| 1839 | } |
| 1840 | |
| 1841 | void h2_stream_on_input_change(h2_stream *stream) |
| 1842 | { |
no test coverage detected