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),
|
notified_(false),
|
||||||
wrbev_(nullptr),
|
wrbev_(nullptr),
|
||||||
rdbev_(nullptr),
|
rdbev_(nullptr),
|
||||||
flow_control_(false)
|
flow_control_(false),
|
||||||
|
settings_timerev_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
SpdySession::~SpdySession()
|
SpdySession::~SpdySession()
|
||||||
|
@ -75,6 +76,11 @@ int SpdySession::disconnect()
|
||||||
nghttp2_session_del(session_);
|
nghttp2_session_del(session_);
|
||||||
session_ = nullptr;
|
session_ = nullptr;
|
||||||
|
|
||||||
|
if(settings_timerev_) {
|
||||||
|
event_free(settings_timerev_);
|
||||||
|
settings_timerev_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if(ssl_) {
|
if(ssl_) {
|
||||||
SSL_shutdown(ssl_);
|
SSL_shutdown(ssl_);
|
||||||
}
|
}
|
||||||
|
@ -746,6 +752,50 @@ int on_stream_close_callback
|
||||||
}
|
}
|
||||||
} // namespace
|
} // 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 {
|
namespace {
|
||||||
int on_frame_recv_callback
|
int on_frame_recv_callback
|
||||||
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
|
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
|
||||||
|
@ -898,6 +948,12 @@ int on_frame_recv_callback
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case NGHTTP2_SETTINGS:
|
||||||
|
if((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spdy->stop_settings_timer();
|
||||||
|
break;
|
||||||
case NGHTTP2_PUSH_PROMISE:
|
case NGHTTP2_PUSH_PROMISE:
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
SSLOG(INFO, spdy) << "Received downstream PUSH_PROMISE stream_id="
|
SSLOG(INFO, spdy) << "Received downstream PUSH_PROMISE stream_id="
|
||||||
|
@ -969,6 +1025,21 @@ int before_frame_send_callback(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
} // namespace
|
} // 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 {
|
namespace {
|
||||||
int on_frame_not_send_callback(nghttp2_session *session,
|
int on_frame_not_send_callback(nghttp2_session *session,
|
||||||
const nghttp2_frame *frame,
|
const nghttp2_frame *frame,
|
||||||
|
@ -1059,6 +1130,7 @@ int SpdySession::on_connect()
|
||||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||||
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
|
||||||
callbacks.before_frame_send_callback = before_frame_send_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_not_send_callback = on_frame_not_send_callback;
|
||||||
callbacks.on_frame_recv_parse_error_callback =
|
callbacks.on_frame_recv_parse_error_callback =
|
||||||
on_frame_recv_parse_error_callback;
|
on_frame_recv_parse_error_callback;
|
||||||
|
@ -1190,4 +1262,14 @@ void SpdySession::set_state(int state)
|
||||||
state_ = 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
|
} // namespace shrpx
|
||||||
|
|
|
@ -74,6 +74,8 @@ public:
|
||||||
// |dconn|.
|
// |dconn|.
|
||||||
int submit_window_update(SpdyDownstreamConnection *dconn, int32_t amount);
|
int submit_window_update(SpdyDownstreamConnection *dconn, int32_t amount);
|
||||||
|
|
||||||
|
int fail_session(nghttp2_error_code error_code);
|
||||||
|
|
||||||
int32_t get_initial_window_size() const;
|
int32_t get_initial_window_size() const;
|
||||||
|
|
||||||
nghttp2_session* get_session() const;
|
nghttp2_session* get_session() const;
|
||||||
|
@ -99,6 +101,9 @@ public:
|
||||||
int get_state() const;
|
int get_state() const;
|
||||||
void set_state(int state);
|
void set_state(int state);
|
||||||
|
|
||||||
|
int start_settings_timer();
|
||||||
|
void stop_settings_timer();
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
// Disconnected
|
// Disconnected
|
||||||
DISCONNECTED,
|
DISCONNECTED,
|
||||||
|
@ -134,6 +139,7 @@ private:
|
||||||
bool flow_control_;
|
bool flow_control_;
|
||||||
// Used to parse the response from HTTP proxy
|
// Used to parse the response from HTTP proxy
|
||||||
std::unique_ptr<http_parser> proxy_htp_;
|
std::unique_ptr<http_parser> proxy_htp_;
|
||||||
|
event *settings_timerev_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
Loading…
Reference in New Issue