nghttpx: Add SETTINGS ACK timeout to HTTP/2 backend connections
This commit is contained in:
parent
f2f8300b62
commit
d9f5451810
|
@ -59,7 +59,8 @@ SpdySession::SpdySession(event_base *evbase, SSL_CTX *ssl_ctx)
|
|||
notified_(false),
|
||||
wrbev_(nullptr),
|
||||
rdbev_(nullptr),
|
||||
flow_control_(false)
|
||||
flow_control_(false),
|
||||
settings_timerev_(nullptr)
|
||||
{}
|
||||
|
||||
SpdySession::~SpdySession()
|
||||
|
@ -75,6 +76,11 @@ int SpdySession::disconnect()
|
|||
nghttp2_session_del(session_);
|
||||
session_ = nullptr;
|
||||
|
||||
if(settings_timerev_) {
|
||||
event_free(settings_timerev_);
|
||||
settings_timerev_ = nullptr;
|
||||
}
|
||||
|
||||
if(ssl_) {
|
||||
SSL_shutdown(ssl_);
|
||||
}
|
||||
|
@ -746,6 +752,50 @@ int on_stream_close_callback
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
auto spdy = reinterpret_cast<SpdySession*>(arg);
|
||||
SSLOG(INFO, spdy) << "SETTINGS timeout";
|
||||
if(spdy->fail_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) {
|
||||
spdy->disconnect();
|
||||
return;
|
||||
}
|
||||
if(spdy->send() != 0) {
|
||||
spdy->disconnect();
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int SpdySession::start_settings_timer()
|
||||
{
|
||||
int rv;
|
||||
// We submit SETTINGS only once
|
||||
if(settings_timerev_) {
|
||||
return 0;
|
||||
}
|
||||
settings_timerev_ = evtimer_new(evbase_, settings_timeout_cb, this);
|
||||
if(settings_timerev_ == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
// SETTINGS ACK timeout is 10 seconds for now
|
||||
timeval settings_timeout = { 10, 0 };
|
||||
rv = evtimer_add(settings_timerev_, &settings_timeout);
|
||||
if(rv == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SpdySession::stop_settings_timer()
|
||||
{
|
||||
if(settings_timerev_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
event_free(settings_timerev_);
|
||||
settings_timerev_ = nullptr;
|
||||
}
|
||||
|
||||
namespace {
|
||||
int on_frame_recv_callback
|
||||
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
|
||||
|
@ -898,6 +948,12 @@ int on_frame_recv_callback
|
|||
}
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_SETTINGS:
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
|
||||
break;
|
||||
}
|
||||
spdy->stop_settings_timer();
|
||||
break;
|
||||
case NGHTTP2_PUSH_PROMISE:
|
||||
if(LOG_ENABLED(INFO)) {
|
||||
SSLOG(INFO, spdy) << "Received downstream PUSH_PROMISE stream_id="
|
||||
|
@ -969,6 +1025,21 @@ int before_frame_send_callback(nghttp2_session *session,
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int on_frame_send_callback(nghttp2_session* session,
|
||||
const nghttp2_frame *frame, void *user_data)
|
||||
{
|
||||
auto spdy = reinterpret_cast<SpdySession*>(user_data);
|
||||
if(frame->hd.type == NGHTTP2_SETTINGS &&
|
||||
(frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
|
||||
if(spdy->start_settings_timer() != 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int on_frame_not_send_callback(nghttp2_session *session,
|
||||
const nghttp2_frame *frame,
|
||||
|
@ -1059,6 +1130,7 @@ int SpdySession::on_connect()
|
|||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
||||
callbacks.before_frame_send_callback = before_frame_send_callback;
|
||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||
callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
|
||||
callbacks.on_frame_recv_parse_error_callback =
|
||||
on_frame_recv_parse_error_callback;
|
||||
|
@ -1190,4 +1262,14 @@ void SpdySession::set_state(int state)
|
|||
state_ = state;
|
||||
}
|
||||
|
||||
int SpdySession::fail_session(nghttp2_error_code error_code)
|
||||
{
|
||||
int rv;
|
||||
rv = nghttp2_session_fail_session(session_, error_code);
|
||||
if(rv != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
// |dconn|.
|
||||
int submit_window_update(SpdyDownstreamConnection *dconn, int32_t amount);
|
||||
|
||||
int fail_session(nghttp2_error_code error_code);
|
||||
|
||||
int32_t get_initial_window_size() const;
|
||||
|
||||
nghttp2_session* get_session() const;
|
||||
|
@ -99,6 +101,9 @@ public:
|
|||
int get_state() const;
|
||||
void set_state(int state);
|
||||
|
||||
int start_settings_timer();
|
||||
void stop_settings_timer();
|
||||
|
||||
enum {
|
||||
// Disconnected
|
||||
DISCONNECTED,
|
||||
|
@ -134,6 +139,7 @@ private:
|
|||
bool flow_control_;
|
||||
// Used to parse the response from HTTP proxy
|
||||
std::unique_ptr<http_parser> proxy_htp_;
|
||||
event *settings_timerev_;
|
||||
};
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
Loading…
Reference in New Issue