2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2012 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #include "shrpx_http2_session.h"
27 #include <netinet/tcp.h>
32 #include <openssl/err.h>
34 #include "shrpx_upstream.h"
35 #include "shrpx_downstream.h"
36 #include "shrpx_config.h"
37 #include "shrpx_error.h"
38 #include "shrpx_http2_downstream_connection.h"
39 #include "shrpx_client_handler.h"
40 #include "shrpx_ssl.h"
41 #include "shrpx_http.h"
42 #include "shrpx_worker_config.h"
48 using namespace nghttp2;
53 void connchk_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
54 auto http2session = static_cast<Http2Session *>(w->data);
55 SSLOG(INFO, http2session) << "connection check required";
56 ev_timer_stop(loop, w);
57 http2session->set_connection_check_state(
58 Http2Session::CONNECTION_CHECK_REQUIRED);
63 void settings_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
64 auto http2session = static_cast<Http2Session *>(w->data);
65 http2session->stop_settings_timer();
66 SSLOG(INFO, http2session) << "SETTINGS timeout";
67 if (http2session->terminate_session(NGHTTP2_SETTINGS_TIMEOUT) != 0) {
68 http2session->disconnect();
71 http2session->signal_write();
76 void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
77 auto conn = static_cast<Connection *>(w->data);
78 auto http2session = static_cast<Http2Session *>(conn->data);
80 if (LOG_ENABLED(INFO)) {
81 SSLOG(INFO, http2session) << "Timeout";
84 http2session->disconnect(http2session->get_state() ==
85 Http2Session::CONNECTING);
90 void readcb(struct ev_loop *loop, ev_io *w, int revents) {
92 auto conn = static_cast<Connection *>(w->data);
93 auto http2session = static_cast<Http2Session *>(conn->data);
94 http2session->connection_alive();
95 rv = http2session->do_read();
97 http2session->disconnect(http2session->should_hard_fail());
103 void writecb(struct ev_loop *loop, ev_io *w, int revents) {
105 auto conn = static_cast<Connection *>(w->data);
106 auto http2session = static_cast<Http2Session *>(conn->data);
107 http2session->clear_write_request();
108 http2session->connection_alive();
109 rv = http2session->do_write();
111 http2session->disconnect(http2session->should_hard_fail());
117 void wrschedcb(struct ev_loop *loop, ev_prepare *w, int revents) {
118 auto http2session = static_cast<Http2Session *>(w->data);
119 if (!http2session->write_requested()) {
122 http2session->clear_write_request();
123 switch (http2session->get_state()) {
124 case Http2Session::DISCONNECTED:
125 LOG(INFO) << "wrschedcb start connect";
126 if (http2session->initiate_connection() != 0) {
127 SSLOG(FATAL, http2session) << "Could not initiate backend connection";
128 http2session->disconnect(true);
131 case Http2Session::CONNECTED:
132 writecb(loop, http2session->get_wev(), revents);
138 Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx)
139 : conn_(loop, -1, nullptr, get_config()->downstream_write_timeout,
140 get_config()->downstream_read_timeout, 0, 0, 0, 0, writecb, readcb,
142 ssl_ctx_(ssl_ctx), session_(nullptr), data_pending_(nullptr),
143 data_pendinglen_(0), state_(DISCONNECTED),
144 connection_check_state_(CONNECTION_CHECK_NONE), flow_control_(false),
145 write_requested_(false) {
147 read_ = write_ = &Http2Session::noop;
148 on_read_ = on_write_ = &Http2Session::noop;
150 // We will resuse this many times, so use repeat timeout value.
151 ev_timer_init(&connchk_timer_, connchk_timeout_cb, 0., 5.);
153 connchk_timer_.data = this;
155 // SETTINGS ACK timeout is 10 seconds for now. We will resuse this
156 // many times, so use repeat timeout value.
157 ev_timer_init(&settings_timer_, settings_timeout_cb, 0., 10.);
159 settings_timer_.data = this;
161 ev_prepare_init(&wrsched_prep_, &wrschedcb);
162 wrsched_prep_.data = this;
164 ev_prepare_start(conn_.loop, &wrsched_prep_);
167 Http2Session::~Http2Session() { disconnect(); }
169 int Http2Session::disconnect(bool hard) {
170 if (LOG_ENABLED(INFO)) {
171 SSLOG(INFO, this) << "Disconnecting";
173 nghttp2_session_del(session_);
179 ev_timer_stop(conn_.loop, &settings_timer_);
180 ev_timer_stop(conn_.loop, &connchk_timer_);
182 read_ = write_ = &Http2Session::noop;
183 on_read_ = on_write_ = &Http2Session::noop;
191 connection_check_state_ = CONNECTION_CHECK_NONE;
192 state_ = DISCONNECTED;
194 // Delete all client handler associated to Downstream. When deleting
195 // Http2DownstreamConnection, it calls this object's
196 // remove_downstream_connection(). The multiple
197 // Http2DownstreamConnection objects belong to the same
198 // ClientHandler object. So first dump ClientHandler objects. We
199 // want to allow creating new pending Http2DownstreamConnection with
200 // this object. In order to achieve this, we first swap dconns_ and
201 // streams_. Upstream::on_downstream_reset() may add
202 // Http2DownstreamConnection.
203 std::set<Http2DownstreamConnection *> dconns;
204 dconns.swap(dconns_);
205 std::set<StreamData *> streams;
206 streams.swap(streams_);
208 std::set<ClientHandler *> handlers;
209 for (auto dc : dconns) {
210 if (!dc->get_client_handler()) {
213 handlers.insert(dc->get_client_handler());
215 for (auto h : handlers) {
216 if (h->get_upstream()->on_downstream_reset(hard) != 0) {
221 for (auto &s : streams) {
228 int Http2Session::check_cert() { return ssl::check_cert(conn_.tls.ssl); }
230 int Http2Session::initiate_connection() {
232 if (get_config()->downstream_http_proxy_host && state_ == DISCONNECTED) {
233 if (LOG_ENABLED(INFO)) {
234 SSLOG(INFO, this) << "Connecting to the proxy "
235 << get_config()->downstream_http_proxy_host.get() << ":"
236 << get_config()->downstream_http_proxy_port;
239 conn_.fd = util::create_nonblock_socket(
240 get_config()->downstream_http_proxy_addr.storage.ss_family);
242 if (conn_.fd == -1) {
246 rv = connect(conn_.fd, const_cast<sockaddr *>(
247 &get_config()->downstream_http_proxy_addr.sa),
248 get_config()->downstream_http_proxy_addrlen);
249 if (rv != 0 && errno != EINPROGRESS) {
250 SSLOG(ERROR, this) << "Failed to connect to the proxy "
251 << get_config()->downstream_http_proxy_host.get()
252 << ":" << get_config()->downstream_http_proxy_port;
256 ev_io_set(&conn_.rev, conn_.fd, EV_READ);
257 ev_io_set(&conn_.wev, conn_.fd, EV_WRITE);
259 conn_.wlimit.startw();
261 // TODO we should have timeout for connection establishment
262 ev_timer_again(conn_.loop, &conn_.wt);
264 write_ = &Http2Session::connected;
266 on_read_ = &Http2Session::downstream_read_proxy;
267 on_write_ = &Http2Session::downstream_connect_proxy;
269 proxy_htp_ = make_unique<http_parser>();
270 http_parser_init(proxy_htp_.get(), HTTP_RESPONSE);
271 proxy_htp_->data = this;
273 state_ = PROXY_CONNECTING;
278 if (state_ == DISCONNECTED || state_ == PROXY_CONNECTED) {
279 if (LOG_ENABLED(INFO)) {
280 SSLOG(INFO, this) << "Connecting to downstream server";
283 // We are establishing TLS connection.
284 conn_.tls.ssl = SSL_new(ssl_ctx_);
285 if (!conn_.tls.ssl) {
286 SSLOG(ERROR, this) << "SSL_new() failed: "
287 << ERR_error_string(ERR_get_error(), NULL);
291 const char *sni_name = nullptr;
292 if (get_config()->backend_tls_sni_name) {
293 sni_name = get_config()->backend_tls_sni_name.get();
295 sni_name = get_config()->downstream_addrs[0].host.get();
298 if (sni_name && !util::numeric_host(sni_name)) {
299 // TLS extensions: SNI. There is no documentation about the return
300 // code for this function (actually this is macro wrapping SSL_ctrl
301 // at the time of this writing).
302 SSL_set_tlsext_host_name(conn_.tls.ssl, sni_name);
304 // If state_ == PROXY_CONNECTED, we has connected to the proxy
305 // using conn_.fd and tunnel has been established.
306 if (state_ == DISCONNECTED) {
307 assert(conn_.fd == -1);
309 conn_.fd = util::create_nonblock_socket(
310 get_config()->downstream_addrs[0].addr.storage.ss_family);
311 if (conn_.fd == -1) {
317 // TODO maybe not thread-safe?
318 const_cast<sockaddr *>(&get_config()->downstream_addrs[0].addr.sa),
319 get_config()->downstream_addrs[0].addrlen);
320 if (rv != 0 && errno != EINPROGRESS) {
325 if (SSL_set_fd(conn_.tls.ssl, conn_.fd) == 0) {
329 SSL_set_connect_state(conn_.tls.ssl);
331 if (state_ == DISCONNECTED) {
332 // Without TLS and proxy.
333 assert(conn_.fd == -1);
335 conn_.fd = util::create_nonblock_socket(
336 get_config()->downstream_addrs[0].addr.storage.ss_family);
338 if (conn_.fd == -1) {
342 rv = connect(conn_.fd, const_cast<sockaddr *>(
343 &get_config()->downstream_addrs[0].addr.sa),
344 get_config()->downstream_addrs[0].addrlen);
345 if (rv != 0 && errno != EINPROGRESS) {
349 // Without TLS but with proxy. Connection already
351 if (on_connect() != -1) {
352 state_ = CONNECT_FAILING;
358 // rev_ and wev_ could possibly be active here. Since calling
359 // ev_io_set is not allowed while watcher is active, we have to
360 // stop them just in case.
361 conn_.rlimit.stopw();
362 conn_.wlimit.stopw();
364 ev_io_set(&conn_.rev, conn_.fd, EV_READ);
365 ev_io_set(&conn_.wev, conn_.fd, EV_WRITE);
367 write_ = &Http2Session::connected;
369 on_write_ = &Http2Session::downstream_write;
370 on_read_ = &Http2Session::downstream_read;
372 // We have been already connected when no TLS and proxy is used.
373 if (state_ != CONNECTED) {
375 conn_.wlimit.startw();
376 // TODO we should have timeout for connection establishment
377 ev_timer_again(conn_.loop, &conn_.wt);
379 conn_.rlimit.startw();
380 ev_timer_again(conn_.loop, &conn_.rt);
392 int htp_hdrs_completecb(http_parser *htp) {
393 auto http2session = static_cast<Http2Session *>(htp->data);
394 // We just check status code here
395 if (htp->status_code == 200) {
396 if (LOG_ENABLED(INFO)) {
397 SSLOG(INFO, http2session) << "Tunneling success";
399 http2session->set_state(Http2Session::PROXY_CONNECTED);
404 SSLOG(WARN, http2session) << "Tunneling failed: " << htp->status_code;
405 http2session->set_state(Http2Session::PROXY_FAILED);
412 http_parser_settings htp_hooks = {
413 nullptr, // http_cb on_message_begin;
414 nullptr, // http_data_cb on_url;
415 nullptr, // http_data_cb on_status;
416 nullptr, // http_data_cb on_header_field;
417 nullptr, // http_data_cb on_header_value;
418 htp_hdrs_completecb, // http_cb on_headers_complete;
419 nullptr, // http_data_cb on_body;
420 nullptr // http_cb on_message_complete;
424 int Http2Session::downstream_read_proxy() {
426 if (rb_.rleft() == 0) {
430 size_t nread = http_parser_execute(proxy_htp_.get(), &htp_hooks,
431 reinterpret_cast<const char *>(rb_.pos),
436 auto htperr = HTTP_PARSER_ERRNO(proxy_htp_.get());
438 if (htperr != HPE_OK) {
443 case Http2Session::PROXY_CONNECTED:
444 // Initiate SSL/TLS handshake through established tunnel.
445 if (initiate_connection() != 0) {
449 case Http2Session::PROXY_FAILED:
455 int Http2Session::downstream_connect_proxy() {
456 if (LOG_ENABLED(INFO)) {
457 SSLOG(INFO, this) << "Connected to the proxy";
459 std::string req = "CONNECT ";
460 req += get_config()->downstream_addrs[0].hostport.get();
461 req += " HTTP/1.1\r\nHost: ";
462 req += get_config()->downstream_addrs[0].host.get();
464 if (get_config()->downstream_http_proxy_userinfo) {
465 req += "Proxy-Authorization: Basic ";
466 size_t len = strlen(get_config()->downstream_http_proxy_userinfo.get());
467 req += base64::encode(get_config()->downstream_http_proxy_userinfo.get(),
468 get_config()->downstream_http_proxy_userinfo.get() +
473 if (LOG_ENABLED(INFO)) {
474 SSLOG(INFO, this) << "HTTP proxy request headers\n" << req;
476 auto nwrite = wb_.write(req.c_str(), req.size());
477 if (nwrite != req.size()) {
478 SSLOG(WARN, this) << "HTTP proxy request is too large";
481 on_write_ = &Http2Session::noop;
487 void Http2Session::add_downstream_connection(Http2DownstreamConnection *dconn) {
488 dconns_.insert(dconn);
492 Http2Session::remove_downstream_connection(Http2DownstreamConnection *dconn) {
493 dconns_.erase(dconn);
494 dconn->detach_stream_data();
497 void Http2Session::remove_stream_data(StreamData *sd) {
500 sd->dconn->detach_stream_data();
505 int Http2Session::submit_request(Http2DownstreamConnection *dconn, int32_t pri,
506 const nghttp2_nv *nva, size_t nvlen,
507 const nghttp2_data_provider *data_prd) {
508 assert(state_ == CONNECTED);
509 auto sd = make_unique<StreamData>();
510 // TODO Specify nullptr to pri_spec for now
512 nghttp2_submit_request(session_, nullptr, nva, nvlen, data_prd, sd.get());
514 SSLOG(FATAL, this) << "nghttp2_submit_request() failed: "
515 << nghttp2_strerror(stream_id);
519 dconn->attach_stream_data(sd.get());
520 dconn->get_downstream()->set_downstream_stream_id(stream_id);
521 streams_.insert(sd.release());
526 int Http2Session::submit_rst_stream(int32_t stream_id, uint32_t error_code) {
527 assert(state_ == CONNECTED);
528 if (LOG_ENABLED(INFO)) {
529 SSLOG(INFO, this) << "RST_STREAM stream_id=" << stream_id
530 << " with error_code=" << error_code;
532 int rv = nghttp2_submit_rst_stream(session_, NGHTTP2_FLAG_NONE, stream_id,
535 SSLOG(FATAL, this) << "nghttp2_submit_rst_stream() failed: "
536 << nghttp2_strerror(rv);
542 int Http2Session::submit_priority(Http2DownstreamConnection *dconn,
544 assert(state_ == CONNECTED);
550 // TODO Disabled temporarily
552 // rv = nghttp2_submit_priority(session_, NGHTTP2_FLAG_NONE,
553 // dconn->get_downstream()->
554 // get_downstream_stream_id(), pri);
558 if (rv < NGHTTP2_ERR_FATAL) {
559 SSLOG(FATAL, this) << "nghttp2_submit_priority() failed: "
560 << nghttp2_strerror(rv);
566 nghttp2_session *Http2Session::get_session() const { return session_; }
568 bool Http2Session::get_flow_control() const { return flow_control_; }
570 int Http2Session::resume_data(Http2DownstreamConnection *dconn) {
571 assert(state_ == CONNECTED);
572 auto downstream = dconn->get_downstream();
573 int rv = nghttp2_session_resume_data(session_,
574 downstream->get_downstream_stream_id());
577 case NGHTTP2_ERR_INVALID_ARGUMENT:
580 SSLOG(FATAL, this) << "nghttp2_resume_session() failed: "
581 << nghttp2_strerror(rv);
587 void call_downstream_readcb(Http2Session *http2session,
588 Downstream *downstream) {
589 auto upstream = downstream->get_upstream();
593 if (upstream->downstream_read(downstream->get_downstream_connection()) != 0) {
594 delete upstream->get_client_handler();
600 int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
601 uint32_t error_code, void *user_data) {
602 auto http2session = static_cast<Http2Session *>(user_data);
603 if (LOG_ENABLED(INFO)) {
604 SSLOG(INFO, http2session) << "Stream stream_id=" << stream_id
605 << " is being closed with error code "
608 auto sd = static_cast<StreamData *>(
609 nghttp2_session_get_stream_user_data(session, stream_id));
611 // We might get this close callback when pushed streams are
615 auto dconn = sd->dconn;
617 auto downstream = dconn->get_downstream();
618 if (downstream && downstream->get_downstream_stream_id() == stream_id) {
620 if (downstream->get_upgraded() &&
621 downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
622 // For tunneled connection, we have to submit RST_STREAM to
623 // upstream *after* whole response body is sent. We just set
624 // MSG_COMPLETE here. Upstream will take care of that.
625 downstream->get_upstream()->on_downstream_body_complete(downstream);
626 downstream->set_response_state(Downstream::MSG_COMPLETE);
627 } else if (error_code == NGHTTP2_NO_ERROR) {
628 switch (downstream->get_response_state()) {
629 case Downstream::MSG_COMPLETE:
630 case Downstream::MSG_BAD_HEADER:
633 downstream->set_response_state(Downstream::MSG_RESET);
635 } else if (downstream->get_response_state() !=
636 Downstream::MSG_BAD_HEADER) {
637 downstream->set_response_state(Downstream::MSG_RESET);
639 call_downstream_readcb(http2session, downstream);
640 // dconn may be deleted
643 // The life time of StreamData ends here
644 http2session->remove_stream_data(sd);
649 void Http2Session::start_settings_timer() {
650 ev_timer_again(conn_.loop, &settings_timer_);
653 void Http2Session::stop_settings_timer() {
654 ev_timer_stop(conn_.loop, &settings_timer_);
658 int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
659 const uint8_t *name, size_t namelen,
660 const uint8_t *value, size_t valuelen, uint8_t flags,
662 auto http2session = static_cast<Http2Session *>(user_data);
663 auto sd = static_cast<StreamData *>(
664 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
665 if (!sd || !sd->dconn) {
668 auto downstream = sd->dconn->get_downstream();
673 if (frame->hd.type != NGHTTP2_HEADERS ||
674 (frame->headers.cat != NGHTTP2_HCAT_RESPONSE &&
675 !downstream->get_expect_final_response())) {
679 if (downstream->get_response_headers_sum() > Downstream::MAX_HEADERS_SUM) {
680 if (LOG_ENABLED(INFO)) {
681 DLOG(INFO, downstream) << "Too large header block size="
682 << downstream->get_response_headers_sum();
684 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
686 if (!http2::check_nv(name, namelen, value, valuelen)) {
690 auto token = http2::lookup_token(name, namelen);
692 if (name[0] == ':') {
693 if (!downstream->response_pseudo_header_allowed(token)) {
694 http2session->submit_rst_stream(frame->hd.stream_id,
695 NGHTTP2_PROTOCOL_ERROR);
696 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
700 if (!http2::http2_header_allowed(token)) {
701 http2session->submit_rst_stream(frame->hd.stream_id,
702 NGHTTP2_PROTOCOL_ERROR);
703 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
706 if (token == http2::HD_CONTENT_LENGTH) {
707 auto len = util::parse_uint(value, valuelen);
709 http2session->submit_rst_stream(frame->hd.stream_id,
710 NGHTTP2_PROTOCOL_ERROR);
711 downstream->set_response_state(Downstream::MSG_BAD_HEADER);
712 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
714 if (downstream->get_response_content_length() != -1) {
715 http2session->submit_rst_stream(frame->hd.stream_id,
716 NGHTTP2_PROTOCOL_ERROR);
717 downstream->set_response_state(Downstream::MSG_BAD_HEADER);
718 return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
720 downstream->set_response_content_length(len);
723 downstream->add_response_header(name, namelen, value, valuelen,
724 flags & NGHTTP2_NV_FLAG_NO_INDEX, token);
730 int on_begin_headers_callback(nghttp2_session *session,
731 const nghttp2_frame *frame, void *user_data) {
732 auto http2session = static_cast<Http2Session *>(user_data);
733 if (frame->headers.cat != NGHTTP2_HCAT_RESPONSE) {
736 auto sd = static_cast<StreamData *>(
737 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
738 if (!sd || !sd->dconn) {
739 http2session->submit_rst_stream(frame->hd.stream_id,
740 NGHTTP2_INTERNAL_ERROR);
743 auto downstream = sd->dconn->get_downstream();
745 downstream->get_downstream_stream_id() != frame->hd.stream_id) {
746 http2session->submit_rst_stream(frame->hd.stream_id,
747 NGHTTP2_INTERNAL_ERROR);
755 int on_response_headers(Http2Session *http2session, Downstream *downstream,
756 nghttp2_session *session, const nghttp2_frame *frame) {
759 auto upstream = downstream->get_upstream();
761 auto &nva = downstream->get_response_headers();
763 downstream->set_expect_final_response(false);
765 auto status = downstream->get_response_header(http2::HD__STATUS);
768 if (!http2::non_empty_value(status) ||
769 (status_code = http2::parse_http_status_code(status->value)) == -1) {
771 http2session->submit_rst_stream(frame->hd.stream_id,
772 NGHTTP2_PROTOCOL_ERROR);
773 downstream->set_response_state(Downstream::MSG_RESET);
774 call_downstream_readcb(http2session, downstream);
779 downstream->set_response_http_status(status_code);
780 downstream->set_response_major(2);
781 downstream->set_response_minor(0);
783 if (LOG_ENABLED(INFO)) {
784 std::stringstream ss;
785 for (auto &nv : nva) {
786 ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n";
788 SSLOG(INFO, http2session)
789 << "HTTP response headers. stream_id=" << frame->hd.stream_id << "\n"
793 if (downstream->get_non_final_response()) {
795 if (LOG_ENABLED(INFO)) {
796 SSLOG(INFO, http2session) << "This is non-final response.";
799 downstream->set_expect_final_response(true);
800 rv = upstream->on_downstream_header_complete(downstream);
802 // Now Dowstream's response headers are erased.
805 http2session->submit_rst_stream(frame->hd.stream_id,
806 NGHTTP2_PROTOCOL_ERROR);
807 downstream->set_response_state(Downstream::MSG_RESET);
813 if (downstream->get_response_content_length() == -1 &&
814 downstream->expect_response_body()) {
815 // Here we have response body but Content-Length is not known in
817 if (downstream->get_request_major() <= 0 ||
818 (downstream->get_request_major() <= 1 &&
819 downstream->get_request_minor() <= 0)) {
820 // We simply close connection for pre-HTTP/1.1 in this case.
821 downstream->set_response_connection_close(true);
822 } else if (downstream->get_request_method() != "CONNECT") {
823 // Otherwise, use chunked encoding to keep upstream connection
824 // open. In HTTP2, we are supporsed not to receive
825 // transfer-encoding.
826 downstream->add_response_header("transfer-encoding", "chunked",
827 http2::HD_TRANSFER_ENCODING);
828 downstream->set_chunked_response(true);
832 downstream->set_response_state(Downstream::HEADER_COMPLETE);
833 downstream->check_upgrade_fulfilled();
834 if (downstream->get_upgraded()) {
835 downstream->set_response_connection_close(true);
836 // On upgrade sucess, both ends can send data
837 if (upstream->resume_read(SHRPX_MSG_BLOCK, downstream, 0) != 0) {
838 // If resume_read fails, just drop connection. Not ideal.
839 delete upstream->get_client_handler();
842 downstream->set_request_state(Downstream::HEADER_COMPLETE);
843 if (LOG_ENABLED(INFO)) {
844 SSLOG(INFO, http2session)
845 << "HTTP upgrade success. stream_id=" << frame->hd.stream_id;
847 } else if (downstream->get_request_method() == "CONNECT") {
848 // If request is CONNECT, terminate request body to avoid for
850 downstream->end_upload_data();
852 rv = upstream->on_downstream_header_complete(downstream);
854 http2session->submit_rst_stream(frame->hd.stream_id,
855 NGHTTP2_PROTOCOL_ERROR);
856 downstream->set_response_state(Downstream::MSG_RESET);
864 int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
867 auto http2session = static_cast<Http2Session *>(user_data);
869 switch (frame->hd.type) {
871 auto sd = static_cast<StreamData *>(
872 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
873 if (!sd || !sd->dconn) {
876 auto downstream = sd->dconn->get_downstream();
878 downstream->get_downstream_stream_id() != frame->hd.stream_id) {
882 auto upstream = downstream->get_upstream();
883 rv = upstream->on_downstream_body(downstream, nullptr, 0, true);
885 http2session->submit_rst_stream(frame->hd.stream_id,
886 NGHTTP2_INTERNAL_ERROR);
887 downstream->set_response_state(Downstream::MSG_RESET);
889 } else if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
891 downstream->disable_downstream_rtimer();
893 if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
895 downstream->set_response_state(Downstream::MSG_COMPLETE);
897 rv = upstream->on_downstream_body_complete(downstream);
900 downstream->set_response_state(Downstream::MSG_RESET);
905 call_downstream_readcb(http2session, downstream);
908 case NGHTTP2_HEADERS: {
909 auto sd = static_cast<StreamData *>(
910 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
911 if (!sd || !sd->dconn) {
914 auto downstream = sd->dconn->get_downstream();
920 if (frame->headers.cat == NGHTTP2_HCAT_RESPONSE) {
921 rv = on_response_headers(http2session, downstream, session, frame);
926 } else if (frame->headers.cat == NGHTTP2_HCAT_HEADERS) {
927 if (downstream->get_expect_final_response()) {
928 rv = on_response_headers(http2session, downstream, session, frame);
933 } else if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
934 http2session->submit_rst_stream(frame->hd.stream_id,
935 NGHTTP2_PROTOCOL_ERROR);
940 if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
942 downstream->disable_downstream_rtimer();
944 if (downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
945 downstream->set_response_state(Downstream::MSG_COMPLETE);
947 auto upstream = downstream->get_upstream();
949 rv = upstream->on_downstream_body_complete(downstream);
952 downstream->set_response_state(Downstream::MSG_RESET);
956 downstream->reset_downstream_rtimer();
959 // This may delete downstream
960 call_downstream_readcb(http2session, downstream);
964 case NGHTTP2_RST_STREAM: {
965 auto sd = static_cast<StreamData *>(
966 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
967 if (sd && sd->dconn) {
968 auto downstream = sd->dconn->get_downstream();
970 downstream->get_downstream_stream_id() == frame->hd.stream_id) {
972 downstream->set_response_rst_stream_error_code(
973 frame->rst_stream.error_code);
974 call_downstream_readcb(http2session, downstream);
979 case NGHTTP2_SETTINGS:
980 if ((frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
983 http2session->stop_settings_timer();
985 case NGHTTP2_PUSH_PROMISE:
986 if (LOG_ENABLED(INFO)) {
987 SSLOG(INFO, http2session)
988 << "Received downstream PUSH_PROMISE stream_id="
989 << frame->hd.stream_id
990 << ", promised_stream_id=" << frame->push_promise.promised_stream_id;
992 // We just respond with RST_STREAM.
993 http2session->submit_rst_stream(frame->push_promise.promised_stream_id,
994 NGHTTP2_REFUSED_STREAM);
1004 int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
1005 int32_t stream_id, const uint8_t *data,
1006 size_t len, void *user_data) {
1008 auto http2session = static_cast<Http2Session *>(user_data);
1009 auto sd = static_cast<StreamData *>(
1010 nghttp2_session_get_stream_user_data(session, stream_id));
1011 if (!sd || !sd->dconn) {
1012 http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
1014 if (http2session->consume(stream_id, len) != 0) {
1015 return NGHTTP2_ERR_CALLBACK_FAILURE;
1020 auto downstream = sd->dconn->get_downstream();
1021 if (!downstream || downstream->get_downstream_stream_id() != stream_id ||
1022 !downstream->expect_response_body()) {
1024 http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
1026 if (http2session->consume(stream_id, len) != 0) {
1027 return NGHTTP2_ERR_CALLBACK_FAILURE;
1033 // We don't want DATA after non-final response, which is illegal in
1035 if (downstream->get_non_final_response()) {
1036 http2session->submit_rst_stream(stream_id, NGHTTP2_PROTOCOL_ERROR);
1038 if (http2session->consume(stream_id, len) != 0) {
1039 return NGHTTP2_ERR_CALLBACK_FAILURE;
1045 downstream->reset_downstream_rtimer();
1047 downstream->add_response_bodylen(len);
1049 auto upstream = downstream->get_upstream();
1050 rv = upstream->on_downstream_body(downstream, data, len, false);
1052 http2session->submit_rst_stream(stream_id, NGHTTP2_INTERNAL_ERROR);
1054 if (http2session->consume(stream_id, len) != 0) {
1055 return NGHTTP2_ERR_CALLBACK_FAILURE;
1058 downstream->set_response_state(Downstream::MSG_RESET);
1061 downstream->add_response_datalen(len);
1063 call_downstream_readcb(http2session, downstream);
1069 int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
1071 auto http2session = static_cast<Http2Session *>(user_data);
1073 if (frame->hd.type == NGHTTP2_DATA || frame->hd.type == NGHTTP2_HEADERS) {
1074 if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
1078 auto sd = static_cast<StreamData *>(
1079 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
1081 if (!sd || !sd->dconn) {
1085 auto downstream = sd->dconn->get_downstream();
1088 downstream->get_downstream_stream_id() != frame->hd.stream_id) {
1092 downstream->reset_downstream_rtimer();
1097 if (frame->hd.type == NGHTTP2_SETTINGS &&
1098 (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0) {
1099 http2session->start_settings_timer();
1106 int on_frame_not_send_callback(nghttp2_session *session,
1107 const nghttp2_frame *frame, int lib_error_code,
1109 auto http2session = static_cast<Http2Session *>(user_data);
1110 if (LOG_ENABLED(INFO)) {
1111 SSLOG(INFO, http2session) << "Failed to send control frame type="
1112 << static_cast<uint32_t>(frame->hd.type)
1113 << "lib_error_code=" << lib_error_code << ":"
1114 << nghttp2_strerror(lib_error_code);
1116 if (frame->hd.type == NGHTTP2_HEADERS &&
1117 frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
1118 // To avoid stream hanging around, flag Downstream::MSG_RESET and
1119 // terminate the upstream and downstream connections.
1120 auto sd = static_cast<StreamData *>(
1121 nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
1126 auto downstream = sd->dconn->get_downstream();
1128 downstream->get_downstream_stream_id() != frame->hd.stream_id) {
1131 downstream->set_response_state(Downstream::MSG_RESET);
1132 call_downstream_readcb(http2session, downstream);
1134 http2session->remove_stream_data(sd);
1140 int Http2Session::on_connect() {
1143 state_ = Http2Session::CONNECTED;
1146 const unsigned char *next_proto = nullptr;
1147 unsigned int next_proto_len;
1148 SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
1149 for (int i = 0; i < 2; ++i) {
1151 if (LOG_ENABLED(INFO)) {
1152 std::string proto(next_proto, next_proto + next_proto_len);
1153 SSLOG(INFO, this) << "Negotiated next protocol: " << proto;
1155 if (!util::check_h2_is_selected(next_proto, next_proto_len)) {
1160 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
1161 SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
1162 #else // OPENSSL_VERSION_NUMBER < 0x10002000L
1164 #endif // OPENSSL_VERSION_NUMBER < 0x10002000L
1171 nghttp2_session_callbacks *callbacks;
1172 rv = nghttp2_session_callbacks_new(&callbacks);
1178 auto callbacks_deleter = defer(nghttp2_session_callbacks_del, callbacks);
1180 nghttp2_session_callbacks_set_on_stream_close_callback(
1181 callbacks, on_stream_close_callback);
1183 nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
1184 on_frame_recv_callback);
1186 nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
1187 callbacks, on_data_chunk_recv_callback);
1189 nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
1190 on_frame_send_callback);
1192 nghttp2_session_callbacks_set_on_frame_not_send_callback(
1193 callbacks, on_frame_not_send_callback);
1195 nghttp2_session_callbacks_set_on_header_callback(callbacks,
1196 on_header_callback);
1198 nghttp2_session_callbacks_set_on_begin_headers_callback(
1199 callbacks, on_begin_headers_callback);
1201 if (get_config()->padding) {
1202 nghttp2_session_callbacks_set_select_padding_callback(
1203 callbacks, http::select_padding_callback);
1206 rv = nghttp2_session_client_new2(&session_, callbacks, this,
1207 get_config()->http2_client_option);
1213 flow_control_ = true;
1215 std::array<nghttp2_settings_entry, 3> entry;
1216 entry[0].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
1218 entry[1].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
1219 entry[1].value = get_config()->http2_max_concurrent_streams;
1221 entry[2].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
1222 entry[2].value = (1 << get_config()->http2_downstream_window_bits) - 1;
1224 rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
1230 if (get_config()->http2_downstream_connection_window_bits > 16) {
1232 (1 << get_config()->http2_downstream_connection_window_bits) - 1 -
1233 NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
1234 rv = nghttp2_submit_window_update(session_, NGHTTP2_FLAG_NONE, 0, delta);
1240 auto nwrite = wb_.write(NGHTTP2_CLIENT_CONNECTION_PREFACE,
1241 NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
1242 if (nwrite != NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN) {
1243 SSLOG(FATAL, this) << "buffer is too small to send connection preface";
1247 auto must_terminate = !get_config()->downstream_no_tls &&
1248 !ssl::check_http2_requirement(conn_.tls.ssl);
1250 if (must_terminate) {
1251 rv = terminate_session(NGHTTP2_INADEQUATE_SECURITY);
1258 if (must_terminate) {
1262 reset_connection_check_timer();
1264 // submit pending request
1265 for (auto dconn : dconns_) {
1266 if (dconn->push_request_headers() == 0) {
1267 auto downstream = dconn->get_downstream();
1268 auto upstream = downstream->get_upstream();
1269 upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0);
1273 if (LOG_ENABLED(INFO)) {
1274 SSLOG(INFO, this) << "backend request failed";
1277 auto downstream = dconn->get_downstream();
1283 auto upstream = downstream->get_upstream();
1285 upstream->on_downstream_abort_request(downstream, 400);
1291 int Http2Session::do_read() { return read_(*this); }
1292 int Http2Session::do_write() { return write_(*this); }
1294 int Http2Session::on_read() { return on_read_(*this); }
1295 int Http2Session::on_write() { return on_write_(*this); }
1297 int Http2Session::downstream_read() {
1300 if (rb_.rleft() > 0) {
1301 rv = nghttp2_session_mem_recv(
1302 session_, reinterpret_cast<const uint8_t *>(rb_.pos), rb_.rleft());
1305 SSLOG(ERROR, this) << "nghttp2_session_recv() returned error: "
1306 << nghttp2_strerror(rv);
1310 // nghttp2_session_mem_recv() should consume all input data in
1315 if (nghttp2_session_want_read(session_) == 0 &&
1316 nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) {
1317 if (LOG_ENABLED(INFO)) {
1318 SSLOG(INFO, this) << "No more read/write for this HTTP2 session";
1327 int Http2Session::downstream_write() {
1328 if (data_pending_) {
1329 auto n = std::min(wb_.wleft(), data_pendinglen_);
1330 wb_.write(data_pending_, n);
1331 if (n < data_pendinglen_) {
1333 data_pendinglen_ -= n;
1337 data_pending_ = nullptr;
1338 data_pendinglen_ = 0;
1342 const uint8_t *data;
1343 auto datalen = nghttp2_session_mem_send(session_, &data);
1346 SSLOG(ERROR, this) << "nghttp2_session_mem_send() returned error: "
1347 << nghttp2_strerror(datalen);
1353 auto n = wb_.write(data, datalen);
1354 if (n < static_cast<decltype(n)>(datalen)) {
1355 data_pending_ = data + n;
1356 data_pendinglen_ = datalen - n;
1361 if (nghttp2_session_want_read(session_) == 0 &&
1362 nghttp2_session_want_write(session_) == 0 && wb_.rleft() == 0) {
1363 if (LOG_ENABLED(INFO)) {
1364 SSLOG(INFO, this) << "No more read/write for this session";
1372 void Http2Session::signal_write() { write_requested_ = true; }
1374 void Http2Session::clear_write_request() { write_requested_ = false; }
1376 bool Http2Session::write_requested() const { return write_requested_; }
1378 struct ev_loop *Http2Session::get_loop() const {
1382 ev_io *Http2Session::get_wev() { return &conn_.wev; }
1384 int Http2Session::get_state() const { return state_; }
1386 void Http2Session::set_state(int state) { state_ = state; }
1388 int Http2Session::terminate_session(uint32_t error_code) {
1390 rv = nghttp2_session_terminate_session(session_, error_code);
1397 SSL *Http2Session::get_ssl() const { return conn_.tls.ssl; }
1399 int Http2Session::consume(int32_t stream_id, size_t len) {
1406 rv = nghttp2_session_consume(session_, stream_id, len);
1409 SSLOG(WARN, this) << "nghttp2_session_consume() returned error: "
1410 << nghttp2_strerror(rv);
1418 bool Http2Session::can_push_request() const {
1419 return state_ == CONNECTED &&
1420 connection_check_state_ == CONNECTION_CHECK_NONE;
1423 void Http2Session::start_checking_connection() {
1424 if (state_ != CONNECTED ||
1425 connection_check_state_ != CONNECTION_CHECK_REQUIRED) {
1428 connection_check_state_ = CONNECTION_CHECK_STARTED;
1430 SSLOG(INFO, this) << "Start checking connection";
1431 // If connection is down, we may get error when writing data. Issue
1432 // ping frame to see whether connection is alive.
1433 nghttp2_submit_ping(session_, NGHTTP2_FLAG_NONE, NULL);
1438 void Http2Session::reset_connection_check_timer() {
1439 ev_timer_again(conn_.loop, &connchk_timer_);
1442 void Http2Session::connection_alive() {
1443 reset_connection_check_timer();
1445 if (connection_check_state_ == CONNECTION_CHECK_NONE) {
1449 SSLOG(INFO, this) << "Connection alive";
1450 connection_check_state_ = CONNECTION_CHECK_NONE;
1452 // submit pending request
1453 for (auto dconn : dconns_) {
1454 auto downstream = dconn->get_downstream();
1456 (downstream->get_request_state() != Downstream::HEADER_COMPLETE &&
1457 downstream->get_request_state() != Downstream::MSG_COMPLETE) ||
1458 downstream->get_response_state() != Downstream::INITIAL) {
1462 auto upstream = downstream->get_upstream();
1464 if (dconn->push_request_headers() == 0) {
1465 upstream->resume_read(SHRPX_NO_BUFFER, downstream, 0);
1469 if (LOG_ENABLED(INFO)) {
1470 SSLOG(INFO, this) << "backend request failed";
1473 upstream->on_downstream_abort_request(downstream, 400);
1477 void Http2Session::set_connection_check_state(int state) {
1478 connection_check_state_ = state;
1481 int Http2Session::noop() { return 0; }
1483 int Http2Session::connected() {
1484 if (!util::check_socket_connected(conn_.fd)) {
1488 if (LOG_ENABLED(INFO)) {
1489 SSLOG(INFO, this) << "Connection established";
1492 conn_.rlimit.startw();
1494 if (conn_.tls.ssl) {
1495 read_ = &Http2Session::tls_handshake;
1496 write_ = &Http2Session::tls_handshake;
1501 read_ = &Http2Session::read_clear;
1502 write_ = &Http2Session::write_clear;
1504 if (state_ == PROXY_CONNECTING) {
1508 if (on_connect() != 0) {
1509 state_ = CONNECT_FAILING;
1516 int Http2Session::read_clear() {
1517 ev_timer_again(conn_.loop, &conn_.rt);
1520 // we should process buffered data first before we read EOF.
1521 if (rb_.rleft() && on_read() != 0) {
1529 auto nread = conn_.read_clear(rb_.last, rb_.wleft());
1543 int Http2Session::write_clear() {
1544 ev_timer_again(conn_.loop, &conn_.rt);
1547 if (wb_.rleft() > 0) {
1548 auto nwrite = conn_.write_clear(wb_.pos, wb_.rleft());
1563 if (on_write() != 0) {
1566 if (wb_.rleft() == 0) {
1571 conn_.wlimit.stopw();
1572 ev_timer_stop(conn_.loop, &conn_.wt);
1577 int Http2Session::tls_handshake() {
1578 ev_timer_again(conn_.loop, &conn_.rt);
1582 auto rv = conn_.tls_handshake();
1584 if (rv == SHRPX_ERR_INPROGRESS) {
1592 if (LOG_ENABLED(INFO)) {
1593 SSLOG(INFO, this) << "SSL/TLS handshake completed";
1596 if (!get_config()->downstream_no_tls && !get_config()->insecure &&
1597 check_cert() != 0) {
1601 read_ = &Http2Session::read_tls;
1602 write_ = &Http2Session::write_tls;
1604 if (on_connect() != 0) {
1605 state_ = CONNECT_FAILING;
1612 int Http2Session::read_tls() {
1613 ev_timer_again(conn_.loop, &conn_.rt);
1618 // we should process buffered data first before we read EOF.
1619 if (rb_.rleft() && on_read() != 0) {
1627 auto nread = conn_.read_tls(rb_.last, rb_.wleft());
1641 int Http2Session::write_tls() {
1642 ev_timer_again(conn_.loop, &conn_.rt);
1647 if (wb_.rleft() > 0) {
1648 auto nwrite = conn_.write_tls(wb_.pos, wb_.rleft());
1663 if (on_write() != 0) {
1666 if (wb_.rleft() == 0) {
1671 conn_.wlimit.stopw();
1672 ev_timer_stop(conn_.loop, &conn_.wt);
1677 bool Http2Session::should_hard_fail() const {
1679 case PROXY_CONNECTING:
1682 case CONNECT_FAILING:
1689 } // namespace shrpx