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