From 88d31ada75b70ce793bf0f799052ba638c54228a Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 9 Jan 2014 23:47:21 +0900 Subject: [PATCH] src: Handle PUSH_PROMISE from client and request HEADERS from server They are just RST_STREAMed for now --- src/HttpServer.cc | 11 +++++++++-- src/shrpx_http2_session.cc | 12 +++++++++--- src/shrpx_http2_upstream.cc | 16 ++++++++++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/HttpServer.cc b/src/HttpServer.cc index d11c23bb..582eb6da 100644 --- a/src/HttpServer.cc +++ b/src/HttpServer.cc @@ -368,10 +368,12 @@ int Http2Handler::on_connect() if(r != 0) { return r; } - nghttp2_settings_entry entry[3]; - size_t niv = 1; + nghttp2_settings_entry entry[4]; + size_t niv = 2; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].value = 100; + entry[1].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + entry[1].value = 0; if(sessions_->get_config()->no_flow_control) { entry[niv].settings_id = NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS; entry[niv].value = 1; @@ -820,6 +822,11 @@ int hd_on_frame_recv_callback hd->remove_settings_timer(); } break; + case NGHTTP2_PUSH_PROMISE: + nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); + break; default: break; } diff --git a/src/shrpx_http2_session.cc b/src/shrpx_http2_session.cc index b75ae583..0f8de258 100644 --- a/src/shrpx_http2_session.cc +++ b/src/shrpx_http2_session.cc @@ -808,6 +808,12 @@ int on_frame_recv_callback auto http2session = reinterpret_cast(user_data); switch(frame->hd.type) { case NGHTTP2_HEADERS: { + if(frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + // server sends request HEADERS + http2session->submit_rst_stream(frame->hd.stream_id, + NGHTTP2_REFUSED_STREAM); + break; + } if(frame->headers.cat != NGHTTP2_HCAT_RESPONSE) { break; } @@ -965,11 +971,11 @@ int on_frame_recv_callback case NGHTTP2_PUSH_PROMISE: if(LOG_ENABLED(INFO)) { SSLOG(INFO, http2session) - << "Received downstream PUSH_PROMISE stream_id=" - << frame->hd.stream_id; + << "Received downstream PUSH_PROMISE stream_id=" << frame->hd.stream_id + << ", promised_stream_id=" << frame->push_promise.promised_stream_id; } // We just respond with RST_STREAM. - http2session->submit_rst_stream(frame->hd.stream_id, + http2session->submit_rst_stream(frame->push_promise.promised_stream_id, NGHTTP2_REFUSED_STREAM); break; default: diff --git a/src/shrpx_http2_upstream.cc b/src/shrpx_http2_upstream.cc index 2f5ca110..680e8ca5 100644 --- a/src/shrpx_http2_upstream.cc +++ b/src/shrpx_http2_upstream.cc @@ -221,6 +221,7 @@ namespace { int on_frame_recv_callback (nghttp2_session *session, const nghttp2_frame *frame, void *user_data) { + int rv; auto upstream = reinterpret_cast(user_data); switch(frame->hd.type) { case NGHTTP2_HEADERS: { @@ -318,7 +319,7 @@ int on_frame_recv_callback downstream->check_upgrade_request(); auto dconn = upstream->get_client_handler()->get_downstream_connection(); - int rv = dconn->attach_downstream(downstream); + rv = dconn->attach_downstream(downstream); if(rv != 0) { // If downstream connection fails, issue RST_STREAM. upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); @@ -342,6 +343,14 @@ int on_frame_recv_callback } upstream->stop_settings_timer(); break; + case NGHTTP2_PUSH_PROMISE: + rv = nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, + frame->push_promise.promised_stream_id, + NGHTTP2_REFUSED_STREAM); + if(rv != 0) { + return NGHTTP2_ERR_CALLBACK_FAILURE; + } + break; default: break; } @@ -502,13 +511,16 @@ Http2Upstream::Http2Upstream(ClientHandler *handler) flow_control_ = true; // TODO Maybe call from outside? - nghttp2_settings_entry entry[2]; + nghttp2_settings_entry entry[3]; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].value = get_config()->http2_max_concurrent_streams; entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; entry[1].value = (1 << get_config()->http2_upstream_window_bits) - 1; + entry[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + entry[2].value = 0; + rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry, sizeof(entry)/sizeof(nghttp2_settings_entry));