nghttpx: Fix so that --padding option works again

This commit is contained in:
Tatsuhiro Tsujikawa 2015-10-04 10:36:20 +09:00
parent b1de6ca390
commit 0155c9115a
4 changed files with 55 additions and 14 deletions

View File

@ -972,10 +972,6 @@ void fill_default_config() {
mod_config()->padding = 0;
mod_config()->worker_frontend_connections = 0;
mod_config()->http2_upstream_callbacks = create_http2_upstream_callbacks();
mod_config()->http2_downstream_callbacks =
create_http2_downstream_callbacks();
nghttp2_option_new(&mod_config()->http2_option);
nghttp2_option_set_no_auto_window_update(get_config()->http2_option, 1);
nghttp2_option_set_no_recv_client_magic(get_config()->http2_option, 1);
@ -2503,6 +2499,10 @@ int main(int argc, char **argv) {
reset_timer();
}
mod_config()->http2_upstream_callbacks = create_http2_upstream_callbacks();
mod_config()->http2_downstream_callbacks =
create_http2_downstream_callbacks();
if (event_loop() != 0) {
return -1;
}

View File

@ -648,11 +648,16 @@ int on_frame_not_send_callback(nghttp2_session *session,
} // namespace
void Http2Upstream::set_pending_data_downstream(Downstream *downstream,
size_t n) {
size_t n, size_t padlen) {
pending_data_downstream_ = downstream;
data_pendinglen_ = n;
padding_pendinglen_ = padlen;
}
namespace {
constexpr auto PADDING = std::array<uint8_t, 256>{};
} // namespace
namespace {
int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
const uint8_t *framehd, size_t length,
@ -663,12 +668,26 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
auto wb = upstream->get_response_buf();
if (wb->wleft() < 9) {
return NGHTTP2_ERR_WOULDBLOCK;
size_t padlen;
if (frame->data.padlen == 0) {
if (wb->wleft() < 9) {
return NGHTTP2_ERR_WOULDBLOCK;
}
wb->write(framehd, 9);
padlen = 0;
} else {
if (wb->wleft() < 10) {
return NGHTTP2_ERR_WOULDBLOCK;
}
wb->write(framehd, 9);
padlen = frame->data.padlen - 1;
*wb->last++ = padlen;
}
wb->write(framehd, 9);
size_t npadwrite = 0;
auto nwrite = std::min(length, wb->wleft());
body->remove(wb->last, nwrite);
wb->write(nwrite);
@ -677,8 +696,16 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
// libnghttp2 that we wrote everything, so downstream could be
// deleted. We handle this situation in
// Http2Upstream::remove_downstream().
upstream->set_pending_data_downstream(downstream, length - nwrite);
upstream->set_pending_data_downstream(downstream, length - nwrite, padlen);
} else if (padlen > 0) {
npadwrite = std::min(padlen, wb->wleft());
wb->write(PADDING.data(), npadwrite);
if (npadwrite < padlen) {
upstream->set_pending_data_downstream(nullptr, 0, padlen - npadwrite);
}
}
if (wb->rleft() == 0) {
downstream->disable_upstream_wtimer();
} else {
@ -695,7 +722,7 @@ int send_data_callback(nghttp2_session *session, nghttp2_frame *frame,
downstream->add_response_sent_bodylen(length);
}
return nwrite < length ? NGHTTP2_ERR_PAUSE : 0;
return (nwrite < length || npadwrite < padlen) ? NGHTTP2_ERR_PAUSE : 0;
}
} // namespace
@ -821,7 +848,8 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
!get_config()->http2_proxy),
pending_response_buf_(handler->get_worker()->get_mcpool()),
pending_data_downstream_(nullptr), handler_(handler), session_(nullptr),
data_pending_(nullptr), data_pendinglen_(0), shutdown_handled_(false) {
data_pending_(nullptr), data_pendinglen_(0), padding_pendinglen_(0),
shutdown_handled_(false) {
int rv;
@ -971,6 +999,16 @@ int Http2Upstream::on_write() {
}
}
if (padding_pendinglen_ > 0) {
auto nwrite = std::min(wb_.wleft(), padding_pendinglen_);
wb_.write(PADDING.data(), nwrite);
padding_pendinglen_ -= nwrite;
if (padding_pendinglen_ > 0) {
return 0;
}
}
for (;;) {
const uint8_t *data;
auto datalen = nghttp2_session_mem_send(session_, &data);

View File

@ -114,7 +114,8 @@ public:
WriteBuffer *get_response_buf();
void set_pending_data_downstream(Downstream *downstream, size_t n);
void set_pending_data_downstream(Downstream *downstream, size_t n,
size_t padlen);
private:
WriteBuffer wb_;
@ -144,6 +145,7 @@ private:
// if pending_data_downstream_ is not nullptr, or
// pending_response_buf_ holds data to write.
size_t data_pendinglen_;
size_t padding_pendinglen_;
bool flow_control_;
bool shutdown_handled_;
};

View File

@ -455,7 +455,8 @@ void HttpDownstreamConnection::pause_read(IOCtrlReason reason) {
int HttpDownstreamConnection::resume_read(IOCtrlReason reason,
size_t consumed) {
if (downstream_->get_response_buf()->rleft() == 0) {
if (downstream_->get_response_buf()->rleft() <=
get_config()->downstream_request_buffer_size / 2) {
ioctrl_.resume_read(reason);
}