Commit 58beaa37 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Support spdy/3.1, require spdylay >= 1.2.0

parent 45c3c5b8
......@@ -210,7 +210,7 @@ fi
AM_CONDITIONAL([HAVE_LIBXML2], [ test "x${have_libxml2}" = "xyes" ])
# 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])
if test "x${have_spdylay}" = "xyes"; then
AC_DEFINE([HAVE_SPDYLAY], [1], [Define to 1 if you have `spdylay` library.])
......
......@@ -324,7 +324,7 @@ bool conf_exists(const char *path)
namespace {
const char *DEFAULT_NPN_LIST = NGHTTP2_PROTO_VERSION_ID ","
#ifdef HAVE_SPDYLAY
"spdy/3,spdy/2,"
"spdy/3.1,spdy/3,spdy/2,"
#endif // HAVE_SPDYLAY
"http/1.1";
} // namespace
......
......@@ -61,8 +61,7 @@ Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
response_connection_close_(false),
response_header_key_prev_(false),
response_body_buf_(nullptr),
response_rst_stream_error_code_(NGHTTP2_NO_ERROR),
recv_window_size_(0)
response_rst_stream_error_code_(NGHTTP2_NO_ERROR)
{}
Downstream::~Downstream()
......@@ -531,21 +530,6 @@ void Downstream::set_priority(int 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()
{
if(request_method_ == "CONNECT") {
......
......@@ -67,9 +67,6 @@ public:
// Returns true if output buffer is full. If underlying dconn_ is
// NULL, this function always returns false.
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.
void check_upgrade_fulfilled();
// Checks request headers whether the request is upgrade request or
......@@ -217,7 +214,6 @@ private:
evbuffer *response_body_buf_;
// RST_STREAM error_code from downstream HTTP2 connection
nghttp2_error_code response_rst_stream_error_code_;
int32_t recv_window_size_;
};
} // namespace shrpx
......
......@@ -254,14 +254,32 @@ void on_data_chunk_recv_callback(spdylay_session *session,
return;
}
if(upstream->get_flow_control()) {
downstream->inc_recv_window_size(len);
if(downstream->get_recv_window_size() >
std::max(65536, upstream->get_initial_window_size())) {
// If connection-level window control is not enabled (e.g,
// spdy/3), spdylay_session_get_recv_data_length() is always
// 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)) {
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
<< downstream->get_recv_window_size()
ULOG(INFO, upstream)
<< "Flow control error on connection: "
<< "recv_window_size="
<< spdylay_session_get_recv_data_length(session)
<< ", 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);
return;
......@@ -679,12 +697,13 @@ int SpdyUpstream::rst_stream(Downstream *downstream, int status_code)
return 0;
}
int SpdyUpstream::window_update(Downstream *downstream)
int SpdyUpstream::window_update(Downstream *downstream, int32_t delta)
{
int rv;
rv = spdylay_submit_window_update(session_, downstream->get_stream_id(),
downstream->get_recv_window_size());
downstream->set_recv_window_size(0);
rv = spdylay_submit_window_update(session_,
downstream ?
downstream->get_stream_id() : 0,
delta);
if(rv < SPDYLAY_ERR_FATAL) {
ULOG(FATAL, this) << "spdylay_submit_window_update() failed: "
<< spdylay_strerror(rv);
......@@ -921,11 +940,40 @@ int32_t SpdyUpstream::get_initial_window_size() const
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)
{
if(get_flow_control()) {
if(downstream->get_recv_window_size() >= get_initial_window_size()/2) {
window_update(downstream);
int32_t delta;
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();
......
......@@ -55,7 +55,7 @@ public:
spdylay_session* get_http2_session();
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);
virtual void pause_read(IOCtrlReason reason);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment