static apr_status_t h2_session_abort_int(h2_session *session, int reason) { assert(session); if (!session->aborted) { session->aborted = 1; nghttp2_session_terminate_session(session->ngh2, reason); h2_mplx_abort(session->mplx); } return APR_SUCCESS; }
/* nghttp2_on_stream_close_callback: Called when a stream is about to closed. This example program only deals with 1 HTTP request (1 stream), if it is closed, we send GOAWAY and tear down the session */ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data) { http2_session_data *session_data = (http2_session_data *)user_data; int rv; if (session_data->stream_data->stream_id == stream_id) { fprintf(stderr, "Stream %d closed with error_code=%u\n", stream_id, error_code); rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); if (rv != 0) { return NGHTTP2_ERR_CALLBACK_FAILURE; } } return 0; }
/** * @brief Callback function invoked when the stream |stream_id| is closed. * We use this function to know if the response is fully received. Since we just fetch 1 resource in this program, after * the response is received, we submit GOAWAY and close the session. * @param[in] session: nghttp2 session. * @param[in] stream_id: stream id. * @param[in] error_code: The reason of closure. * Usually one of :enum:`nghttp2_error_code`, but that is not guaranteed. The stream_user_data, which was specified in * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still available in this function. * @param[in] user_data: The |user_data| pointer is the third argument passed in to the call to * `nghttp2_session_client_new()` or `nghttp2_session_server_new()` * @return The implementation of this function must return 0 if it succeeds. * If nonzero is returned, it is treated as fatal error and `nghttp2_session_send()` * and `nghttp2_session_mem_send()` functions immediately return :enum: * `NGHTTP2_ERR_CALLBACK_FAILURE`. */ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id, uint32_t error_code, void *user_data) { struct Request *req; req = nghttp2_session_get_stream_user_data(session, stream_id); if (req) { int rv; rv = nghttp2_session_terminate_session(session, NGHTTP2_NO_ERROR); if (rv != 0) { printf("stream close nghttp2_session_terminate_session\r\n"); } } return 0; }
static apr_status_t h2_session_abort_int(h2_session *session, int reason) { AP_DEBUG_ASSERT(session); if (!session->aborted) { session->aborted = 1; if (session->ngh2) { if (!reason) { nghttp2_submit_goaway(session->ngh2, NGHTTP2_FLAG_NONE, session->max_stream_received, reason, NULL, 0); nghttp2_session_send(session->ngh2); h2_conn_io_flush(&session->io); } else { const char *err = nghttp2_strerror(reason); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, session->c, "session(%ld): aborting session, reason=%d %s", session->id, reason, err); if (NGHTTP2_ERR_EOF == reason) { /* This is our way of indication that the connection is * gone. No use to send any GOAWAY frames. */ nghttp2_session_terminate_session(session->ngh2, reason); } else { /* The connection might still be there and we shut down * with GOAWAY and reason information. */ nghttp2_submit_goaway(session->ngh2, NGHTTP2_FLAG_NONE, session->max_stream_received, reason, (const uint8_t *)err, strlen(err)); nghttp2_session_send(session->ngh2); h2_conn_io_flush(&session->io); } } } h2_mplx_abort(session->mplx); } return APR_SUCCESS; }