nghttp, nghttpd: Add SETTINGS timeout handling
SETTINGS timeout is 10 seconds for now.
This commit is contained in:
parent
34b3833c71
commit
dc61f705df
|
@ -177,12 +177,16 @@ Http2Handler::Http2Handler(Sessions *sessions,
|
|||
int fd, SSL *ssl, int64_t session_id)
|
||||
: session_(nullptr), sessions_(sessions), bev_(nullptr), fd_(fd), ssl_(ssl),
|
||||
session_id_(session_id),
|
||||
left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_HEADER_LEN)
|
||||
left_connhd_len_(NGHTTP2_CLIENT_CONNECTION_HEADER_LEN),
|
||||
settings_timerev_(nullptr)
|
||||
{}
|
||||
|
||||
Http2Handler::~Http2Handler()
|
||||
{
|
||||
on_session_closed(this, session_id_);
|
||||
if(settings_timerev_) {
|
||||
event_free(settings_timerev_);
|
||||
}
|
||||
nghttp2_session_del(session_);
|
||||
if(ssl_) {
|
||||
SSL_shutdown(ssl_);
|
||||
|
@ -340,6 +344,15 @@ int Http2Handler::on_write()
|
|||
return rv;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
auto hd = reinterpret_cast<Http2Handler*>(arg);
|
||||
hd->submit_goaway(NGHTTP2_SETTINGS_TIMEOUT);
|
||||
hd->on_write();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int Http2Handler::on_connect()
|
||||
{
|
||||
int r;
|
||||
|
@ -362,6 +375,13 @@ int Http2Handler::on_connect()
|
|||
if(r != 0) {
|
||||
return r;
|
||||
}
|
||||
assert(settings_timerev_ == nullptr);
|
||||
settings_timerev_ = evtimer_new(sessions_->get_evbase(), settings_timeout_cb,
|
||||
this);
|
||||
// SETTINGS ACK timeout is 10 seconds for now
|
||||
timeval settings_timeout = { 10, 0 };
|
||||
evtimer_add(settings_timerev_, &settings_timeout);
|
||||
|
||||
return on_write();
|
||||
}
|
||||
|
||||
|
@ -524,6 +544,20 @@ void Http2Handler::set_left_connhd_len(size_t left)
|
|||
left_connhd_len_ = left;
|
||||
}
|
||||
|
||||
void Http2Handler::remove_settings_timer()
|
||||
{
|
||||
if(settings_timerev_) {
|
||||
evtimer_del(settings_timerev_);
|
||||
event_free(settings_timerev_);
|
||||
settings_timerev_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Http2Handler::submit_goaway(nghttp2_error_code error_code)
|
||||
{
|
||||
nghttp2_submit_goaway(session_, NGHTTP2_FLAG_NONE, error_code, NULL, 0);
|
||||
}
|
||||
|
||||
namespace {
|
||||
ssize_t hd_send_callback(nghttp2_session *session,
|
||||
const uint8_t *data, size_t len, int flags,
|
||||
|
@ -736,6 +770,11 @@ int hd_on_frame_recv_callback
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case NGHTTP2_SETTINGS:
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_ACK) {
|
||||
hd->remove_settings_timer();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/bufferevent.h>
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
@ -113,6 +114,8 @@ public:
|
|||
const Config* get_config() const;
|
||||
size_t get_left_connhd_len() const;
|
||||
void set_left_connhd_len(size_t left);
|
||||
void remove_settings_timer();
|
||||
void submit_goaway(nghttp2_error_code error_code);
|
||||
private:
|
||||
nghttp2_session *session_;
|
||||
Sessions *sessions_;
|
||||
|
@ -122,6 +125,7 @@ private:
|
|||
int64_t session_id_;
|
||||
std::map<int32_t, std::unique_ptr<Request>> id2req_;
|
||||
size_t left_connhd_len_;
|
||||
event *settings_timerev_;
|
||||
};
|
||||
|
||||
class HttpServer {
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <openssl/err.h>
|
||||
|
||||
#include <event.h>
|
||||
#include <event2/event.h>
|
||||
#include <event2/bufferevent_ssl.h>
|
||||
#include <event2/dns.h>
|
||||
|
||||
|
@ -401,6 +402,10 @@ void check_stream_id(nghttp2_session *session, int32_t stream_id,
|
|||
void *user_data);
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg);
|
||||
} // namespace
|
||||
|
||||
enum client_state {
|
||||
STATE_IDLE,
|
||||
STATE_CONNECTED
|
||||
|
@ -415,6 +420,7 @@ struct HttpClient {
|
|||
SSL_CTX *ssl_ctx;
|
||||
SSL *ssl;
|
||||
bufferevent *bev;
|
||||
event *settings_timerev;
|
||||
client_state state;
|
||||
std::vector<std::unique_ptr<Request>> reqvec;
|
||||
// Map from stream ID to Request object.
|
||||
|
@ -448,6 +454,7 @@ struct HttpClient {
|
|||
ssl_ctx(ssl_ctx),
|
||||
ssl(nullptr),
|
||||
bev(nullptr),
|
||||
settings_timerev(nullptr),
|
||||
state(STATE_IDLE),
|
||||
complete(0),
|
||||
upgrade_response_complete(false),
|
||||
|
@ -536,6 +543,10 @@ struct HttpClient {
|
|||
evdns_base_free(dnsbase, 1);
|
||||
dnsbase = nullptr;
|
||||
}
|
||||
if(settings_timerev) {
|
||||
event_free(settings_timerev);
|
||||
settings_timerev = nullptr;
|
||||
}
|
||||
if(ssl) {
|
||||
SSL_free(ssl);
|
||||
ssl = nullptr;
|
||||
|
@ -690,6 +701,12 @@ struct HttpClient {
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
assert(settings_timerev == nullptr);
|
||||
settings_timerev = evtimer_new(evbase, settings_timeout_cb, this);
|
||||
// SETTINGS ACK timeout is 10 seconds for now
|
||||
timeval settings_timeout = { 10, 0 };
|
||||
evtimer_add(settings_timerev, &settings_timeout);
|
||||
|
||||
if(config.connection_window_bits != -1) {
|
||||
int32_t wininc = (1 << config.connection_window_bits) - 1
|
||||
- NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
|
||||
|
@ -1054,6 +1071,16 @@ void check_stream_id(nghttp2_session *session, int32_t stream_id,
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
|
||||
{
|
||||
auto client = get_session(arg);
|
||||
nghttp2_submit_goaway(client->session, NGHTTP2_FLAG_NONE,
|
||||
NGHTTP2_SETTINGS_TIMEOUT, nullptr, 0);
|
||||
client->on_write();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
int before_frame_send_callback
|
||||
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
|
||||
|
@ -1129,6 +1156,15 @@ int on_frame_recv_callback2
|
|||
}
|
||||
}
|
||||
check_response_header(session, frame, user_data);
|
||||
if(frame->hd.type == NGHTTP2_SETTINGS &&
|
||||
(frame->hd.flags & NGHTTP2_FLAG_ACK)) {
|
||||
auto client = get_session(user_data);
|
||||
if(client->settings_timerev) {
|
||||
evtimer_del(client->settings_timerev);
|
||||
event_free(client->settings_timerev);
|
||||
client->settings_timerev = nullptr;
|
||||
}
|
||||
}
|
||||
if(config.verbose) {
|
||||
on_frame_recv_callback(session, frame, user_data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue