nghttpx: Support spdy/3.1, require spdylay >= 1.2.0
This commit is contained in:
parent
45c3c5b80f
commit
58beaa371d
|
@ -210,7 +210,7 @@ fi
|
||||||
AM_CONDITIONAL([HAVE_LIBXML2], [ test "x${have_libxml2}" = "xyes" ])
|
AM_CONDITIONAL([HAVE_LIBXML2], [ test "x${have_libxml2}" = "xyes" ])
|
||||||
|
|
||||||
# spdylay (for src/nghttpx)
|
# spdylay (for src/nghttpx)
|
||||||
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.0.0],
|
PKG_CHECK_MODULES([LIBSPDYLAY], [libspdylay >= 1.2.0],
|
||||||
[have_spdylay=yes], [have_spdylay=no])
|
[have_spdylay=yes], [have_spdylay=no])
|
||||||
if test "x${have_spdylay}" = "xyes"; then
|
if test "x${have_spdylay}" = "xyes"; then
|
||||||
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
|
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
|
||||||
|
|
|
@ -324,7 +324,7 @@ bool conf_exists(const char *path)
|
||||||
namespace {
|
namespace {
|
||||||
const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID ","
|
const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID ","
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
"spdy/3,spdy/2,"
|
"spdy/3.1,spdy/3,spdy/2,"
|
||||||
#endif // HAVE_SPDYLAY
|
#endif // HAVE_SPDYLAY
|
||||||
"http/1.1";
|
"http/1.1";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -61,8 +61,7 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
||||||
response_connection_close_(false),
|
response_connection_close_(false),
|
||||||
response_header_key_prev_(false),
|
response_header_key_prev_(false),
|
||||||
response_body_buf_(nullptr),
|
response_body_buf_(nullptr),
|
||||||
response_rst_stream_error_code_(NGHTTP2_NO_ERROR),
|
response_rst_stream_error_code_(NGHTTP2_NO_ERROR)
|
||||||
recv_window_size_(0)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Downstream::~Downstream()
|
Downstream::~Downstream()
|
||||||
|
@ -531,21 +530,6 @@ void Downstream::set_priority(int pri)
|
||||||
priority_ = pri;
|
priority_ = pri;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Downstream::get_recv_window_size() const
|
|
||||||
{
|
|
||||||
return recv_window_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Downstream::inc_recv_window_size(int32_t amount)
|
|
||||||
{
|
|
||||||
recv_window_size_ += amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Downstream::set_recv_window_size(int32_t new_size)
|
|
||||||
{
|
|
||||||
recv_window_size_ = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Downstream::check_upgrade_fulfilled()
|
void Downstream::check_upgrade_fulfilled()
|
||||||
{
|
{
|
||||||
if(request_method_ == "CONNECT") {
|
if(request_method_ == "CONNECT") {
|
||||||
|
|
|
@ -67,9 +67,6 @@ public:
|
||||||
// Returns true if output buffer is full. If underlying dconn_ is
|
// Returns true if output buffer is full. If underlying dconn_ is
|
||||||
// NULL, this function always returns false.
|
// NULL, this function always returns false.
|
||||||
bool get_output_buffer_full();
|
bool get_output_buffer_full();
|
||||||
int32_t get_recv_window_size() const;
|
|
||||||
void inc_recv_window_size(int32_t amount);
|
|
||||||
void set_recv_window_size(int32_t new_size);
|
|
||||||
// Returns true if upgrade (HTTP Upgrade or CONNECT) is succeeded.
|
// Returns true if upgrade (HTTP Upgrade or CONNECT) is succeeded.
|
||||||
void check_upgrade_fulfilled();
|
void check_upgrade_fulfilled();
|
||||||
// Checks request headers whether the request is upgrade request or
|
// Checks request headers whether the request is upgrade request or
|
||||||
|
@ -217,7 +214,6 @@ private:
|
||||||
evbuffer *response_body_buf_;
|
evbuffer *response_body_buf_;
|
||||||
// RST_STREAM error_code from downstream HTTP2 connection
|
// RST_STREAM error_code from downstream HTTP2 connection
|
||||||
nghttp2_error_code response_rst_stream_error_code_;
|
nghttp2_error_code response_rst_stream_error_code_;
|
||||||
int32_t recv_window_size_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -254,14 +254,32 @@ void on_data_chunk_recv_callback(spdylay_session *session,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(upstream->get_flow_control()) {
|
if(upstream->get_flow_control()) {
|
||||||
downstream->inc_recv_window_size(len);
|
// If connection-level window control is not enabled (e.g,
|
||||||
if(downstream->get_recv_window_size() >
|
// spdy/3), spdylay_session_get_recv_data_length() is always
|
||||||
std::max(65536, upstream->get_initial_window_size())) {
|
// returns 0.
|
||||||
|
if(spdylay_session_get_recv_data_length(session) >
|
||||||
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
||||||
|
spdylay_session_get_local_window_size(session))) {
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
|
ULOG(INFO, upstream)
|
||||||
<< downstream->get_recv_window_size()
|
<< "Flow control error on connection: "
|
||||||
|
<< "recv_window_size="
|
||||||
|
<< spdylay_session_get_recv_data_length(session)
|
||||||
<< ", initial_window_size="
|
<< ", initial_window_size="
|
||||||
<< upstream->get_initial_window_size();
|
<< spdylay_session_get_local_window_size(session);
|
||||||
|
}
|
||||||
|
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(spdylay_session_get_stream_recv_data_length(session, stream_id) >
|
||||||
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
||||||
|
spdylay_session_get_stream_local_window_size(session))) {
|
||||||
|
if(LOG_ENABLED(INFO)) {
|
||||||
|
ULOG(INFO, upstream)
|
||||||
|
<< "Flow control error: recv_window_size="
|
||||||
|
<< spdylay_session_get_stream_recv_data_length(session, stream_id)
|
||||||
|
<< ", initial_window_size="
|
||||||
|
<< spdylay_session_get_stream_local_window_size(session);
|
||||||
}
|
}
|
||||||
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
||||||
return;
|
return;
|
||||||
|
@ -679,12 +697,13 @@ int SpdyUpstream::rst_stream(Downstream *downstream, int status_code)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SpdyUpstream::window_update(Downstream *downstream)
|
int SpdyUpstream::window_update(Downstream *downstream, int32_t delta)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
rv = spdylay_submit_window_update(session_, downstream->get_stream_id(),
|
rv = spdylay_submit_window_update(session_,
|
||||||
downstream->get_recv_window_size());
|
downstream ?
|
||||||
downstream->set_recv_window_size(0);
|
downstream->get_stream_id() : 0,
|
||||||
|
delta);
|
||||||
if(rv < SPDYLAY_ERR_FATAL) {
|
if(rv < SPDYLAY_ERR_FATAL) {
|
||||||
ULOG(FATAL, this) << "spdylay_submit_window_update() failed: "
|
ULOG(FATAL, this) << "spdylay_submit_window_update() failed: "
|
||||||
<< spdylay_strerror(rv);
|
<< spdylay_strerror(rv);
|
||||||
|
@ -921,11 +940,40 @@ int32_t SpdyUpstream::get_initial_window_size() const
|
||||||
void SpdyUpstream::pause_read(IOCtrlReason reason)
|
void SpdyUpstream::pause_read(IOCtrlReason reason)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int32_t determine_window_update_transmission(spdylay_session *session,
|
||||||
|
int32_t stream_id)
|
||||||
|
{
|
||||||
|
int32_t recv_length, window_size;
|
||||||
|
if(stream_id == 0) {
|
||||||
|
recv_length = spdylay_session_get_recv_data_length(session);
|
||||||
|
window_size = spdylay_session_get_local_window_size(session);
|
||||||
|
} else {
|
||||||
|
recv_length = spdylay_session_get_stream_recv_data_length
|
||||||
|
(session, stream_id);
|
||||||
|
window_size = spdylay_session_get_stream_local_window_size(session);
|
||||||
|
}
|
||||||
|
if(recv_length != -1 && window_size != -1) {
|
||||||
|
if(recv_length >= window_size / 2) {
|
||||||
|
return recv_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int SpdyUpstream::resume_read(IOCtrlReason reason, Downstream *downstream)
|
int SpdyUpstream::resume_read(IOCtrlReason reason, Downstream *downstream)
|
||||||
{
|
{
|
||||||
if(get_flow_control()) {
|
if(get_flow_control()) {
|
||||||
if(downstream->get_recv_window_size() >= get_initial_window_size()/2) {
|
int32_t delta;
|
||||||
window_update(downstream);
|
delta = determine_window_update_transmission(session_, 0);
|
||||||
|
if(delta != -1) {
|
||||||
|
window_update(0, delta);
|
||||||
|
}
|
||||||
|
delta = determine_window_update_transmission
|
||||||
|
(session_, downstream->get_stream_id());
|
||||||
|
if(delta != -1) {
|
||||||
|
window_update(downstream, delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return send();
|
return send();
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
spdylay_session* get_http2_session();
|
spdylay_session* get_http2_session();
|
||||||
|
|
||||||
int rst_stream(Downstream *downstream, int status_code);
|
int rst_stream(Downstream *downstream, int status_code);
|
||||||
int window_update(Downstream *downstream);
|
int window_update(Downstream *downstream, int32_t delta);
|
||||||
int error_reply(Downstream *downstream, unsigned int status_code);
|
int error_reply(Downstream *downstream, unsigned int status_code);
|
||||||
|
|
||||||
virtual void pause_read(IOCtrlReason reason);
|
virtual void pause_read(IOCtrlReason reason);
|
||||||
|
|
Loading…
Reference in New Issue