Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / src / shrpx_downstream.cc
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2012 Tatsuhiro Tsujikawa
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
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.
24  */
25 #include "shrpx_downstream.h"
26
27 #include <cassert>
28
29 #include "http-parser/http_parser.h"
30
31 #include "shrpx_upstream.h"
32 #include "shrpx_client_handler.h"
33 #include "shrpx_config.h"
34 #include "shrpx_error.h"
35 #include "shrpx_downstream_connection.h"
36 #include "shrpx_downstream_queue.h"
37 #include "util.h"
38 #include "http2.h"
39
40 namespace shrpx {
41
42 namespace {
43 void upstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
44   auto downstream = static_cast<Downstream *>(w->data);
45   auto upstream = downstream->get_upstream();
46
47   auto which = revents == EV_READ ? "read" : "write";
48
49   if (LOG_ENABLED(INFO)) {
50     DLOG(INFO, downstream) << "upstream timeout stream_id="
51                            << downstream->get_stream_id() << " event=" << which;
52   }
53
54   downstream->disable_upstream_rtimer();
55   downstream->disable_upstream_wtimer();
56
57   upstream->on_timeout(downstream);
58 }
59 } // namespace
60
61 namespace {
62 void upstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
63   upstream_timeoutcb(loop, w, EV_READ);
64 }
65 } // namespace
66
67 namespace {
68 void upstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
69   upstream_timeoutcb(loop, w, EV_WRITE);
70 }
71 } // namespace
72
73 namespace {
74 void downstream_timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
75   auto downstream = static_cast<Downstream *>(w->data);
76
77   auto which = revents == EV_READ ? "read" : "write";
78
79   if (LOG_ENABLED(INFO)) {
80     DLOG(INFO, downstream) << "downstream timeout stream_id="
81                            << downstream->get_downstream_stream_id()
82                            << " event=" << which;
83   }
84
85   downstream->disable_downstream_rtimer();
86   downstream->disable_downstream_wtimer();
87
88   auto dconn = downstream->get_downstream_connection();
89
90   if (dconn) {
91     dconn->on_timeout();
92   }
93 }
94 } // namespace
95
96 namespace {
97 void downstream_rtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
98   downstream_timeoutcb(loop, w, EV_READ);
99 }
100 } // namespace
101
102 namespace {
103 void downstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
104   downstream_timeoutcb(loop, w, EV_WRITE);
105 }
106 } // namespace
107
108 // upstream could be nullptr for unittests
109 Downstream::Downstream(Upstream *upstream, MemchunkPool *mcpool,
110                        int32_t stream_id, int32_t priority)
111     : dlnext(nullptr), dlprev(nullptr),
112       request_start_time_(std::chrono::high_resolution_clock::now()),
113       request_buf_(mcpool), response_buf_(mcpool), request_bodylen_(0),
114       response_bodylen_(0), response_sent_bodylen_(0),
115       request_content_length_(-1), response_content_length_(-1),
116       upstream_(upstream), blocked_link_(nullptr), request_headers_sum_(0),
117       response_headers_sum_(0), request_datalen_(0), response_datalen_(0),
118       num_retry_(0), stream_id_(stream_id), priority_(priority),
119       downstream_stream_id_(-1),
120       response_rst_stream_error_code_(NGHTTP2_NO_ERROR),
121       request_state_(INITIAL), request_major_(1), request_minor_(1),
122       response_state_(INITIAL), response_http_status_(0), response_major_(1),
123       response_minor_(1), dispatch_state_(DISPATCH_NONE),
124       upgrade_request_(false), upgraded_(false), http2_upgrade_seen_(false),
125       chunked_request_(false), request_connection_close_(false),
126       request_header_key_prev_(false), request_trailer_key_prev_(false),
127       request_http2_expect_body_(false), chunked_response_(false),
128       response_connection_close_(false), response_header_key_prev_(false),
129       response_trailer_key_prev_(false), expect_final_response_(false),
130       request_pending_(false) {
131
132   ev_timer_init(&upstream_rtimer_, &upstream_rtimeoutcb, 0.,
133                 get_config()->stream_read_timeout);
134   ev_timer_init(&upstream_wtimer_, &upstream_wtimeoutcb, 0.,
135                 get_config()->stream_write_timeout);
136   ev_timer_init(&downstream_rtimer_, &downstream_rtimeoutcb, 0.,
137                 get_config()->stream_read_timeout);
138   ev_timer_init(&downstream_wtimer_, &downstream_wtimeoutcb, 0.,
139                 get_config()->stream_write_timeout);
140
141   upstream_rtimer_.data = this;
142   upstream_wtimer_.data = this;
143   downstream_rtimer_.data = this;
144   downstream_wtimer_.data = this;
145
146   http2::init_hdidx(request_hdidx_);
147   http2::init_hdidx(response_hdidx_);
148 }
149
150 Downstream::~Downstream() {
151   if (LOG_ENABLED(INFO)) {
152     DLOG(INFO, this) << "Deleting";
153   }
154
155   if (blocked_link_) {
156     detach_blocked_link(blocked_link_);
157   }
158
159   // check nullptr for unittest
160   if (upstream_) {
161     auto loop = upstream_->get_client_handler()->get_loop();
162
163     ev_timer_stop(loop, &upstream_rtimer_);
164     ev_timer_stop(loop, &upstream_wtimer_);
165     ev_timer_stop(loop, &downstream_rtimer_);
166     ev_timer_stop(loop, &downstream_wtimer_);
167   }
168
169   if (LOG_ENABLED(INFO)) {
170     DLOG(INFO, this) << "Deleted";
171   }
172 }
173
174 int Downstream::attach_downstream_connection(
175     std::unique_ptr<DownstreamConnection> dconn) {
176   if (dconn->attach_downstream(this) != 0) {
177     return -1;
178   }
179
180   dconn_ = std::move(dconn);
181
182   return 0;
183 }
184
185 void Downstream::detach_downstream_connection() {
186   if (!dconn_) {
187     return;
188   }
189
190   dconn_->detach_downstream(this);
191
192   auto handler = dconn_->get_client_handler();
193
194   handler->pool_downstream_connection(
195       std::unique_ptr<DownstreamConnection>(dconn_.release()));
196 }
197
198 void Downstream::release_downstream_connection() { dconn_.release(); }
199
200 DownstreamConnection *Downstream::get_downstream_connection() {
201   return dconn_.get();
202 }
203
204 std::unique_ptr<DownstreamConnection> Downstream::pop_downstream_connection() {
205   return std::unique_ptr<DownstreamConnection>(dconn_.release());
206 }
207
208 void Downstream::pause_read(IOCtrlReason reason) {
209   if (dconn_) {
210     dconn_->pause_read(reason);
211   }
212 }
213
214 int Downstream::resume_read(IOCtrlReason reason, size_t consumed) {
215   if (dconn_) {
216     return dconn_->resume_read(reason, consumed);
217   }
218
219   return 0;
220 }
221
222 void Downstream::force_resume_read() {
223   if (dconn_) {
224     dconn_->force_resume_read();
225   }
226 }
227
228 namespace {
229 const Headers::value_type *get_header_linear(const Headers &headers,
230                                              const std::string &name) {
231   const Headers::value_type *res = nullptr;
232   for (auto &kv : headers) {
233     if (kv.name == name) {
234       res = &kv;
235     }
236   }
237   return res;
238 }
239 } // namespace
240
241 const Headers &Downstream::get_request_headers() const {
242   return request_headers_;
243 }
244
245 void Downstream::assemble_request_cookie() {
246   std::string &cookie = assembled_request_cookie_;
247   cookie = "";
248   for (auto &kv : request_headers_) {
249     if (kv.name.size() != 6 || kv.name[5] != 'e' ||
250         !util::streq_l("cooki", kv.name.c_str(), 5)) {
251       continue;
252     }
253
254     auto end = kv.value.find_last_not_of(" ;");
255     if (end == std::string::npos) {
256       cookie += kv.value;
257     } else {
258       cookie.append(std::begin(kv.value), std::begin(kv.value) + end + 1);
259     }
260     cookie += "; ";
261   }
262   if (cookie.size() >= 2) {
263     cookie.erase(cookie.size() - 2);
264   }
265 }
266
267 Headers Downstream::crumble_request_cookie() {
268   Headers cookie_hdrs;
269   for (auto &kv : request_headers_) {
270     if (kv.name.size() != 6 || kv.name[5] != 'e' ||
271         !util::streq_l("cooki", kv.name.c_str(), 5)) {
272       continue;
273     }
274     size_t last = kv.value.size();
275
276     for (size_t j = 0; j < last;) {
277       j = kv.value.find_first_not_of("\t ;", j);
278       if (j == std::string::npos) {
279         break;
280       }
281       auto first = j;
282
283       j = kv.value.find(';', j);
284       if (j == std::string::npos) {
285         j = last;
286       }
287
288       cookie_hdrs.push_back(
289           Header("cookie", kv.value.substr(first, j - first), kv.no_index));
290     }
291   }
292   return cookie_hdrs;
293 }
294
295 const std::string &Downstream::get_assembled_request_cookie() const {
296   return assembled_request_cookie_;
297 }
298
299 namespace {
300 void add_header(bool &key_prev, size_t &sum, Headers &headers, std::string name,
301                 std::string value) {
302   key_prev = true;
303   sum += name.size() + value.size();
304   headers.emplace_back(std::move(name), std::move(value));
305 }
306 } // namespace
307
308 namespace {
309 void append_last_header_key(bool key_prev, size_t &sum, Headers &headers,
310                             const char *data, size_t len) {
311   assert(key_prev);
312   sum += len;
313   auto &item = headers.back();
314   item.name.append(data, len);
315 }
316 } // namespace
317
318 namespace {
319 void append_last_header_value(bool key_prev, size_t &sum, Headers &headers,
320                               const char *data, size_t len) {
321   assert(!key_prev);
322   sum += len;
323   auto &item = headers.back();
324   item.value.append(data, len);
325 }
326 } // namespace
327
328 namespace {
329 void set_last_header_value(bool &key_prev, size_t &sum, Headers &headers,
330                            const char *data, size_t len) {
331   key_prev = false;
332   sum += len;
333   auto &item = headers.back();
334   item.value.assign(data, len);
335 }
336 } // namespace
337
338 namespace {
339 int index_headers(http2::HeaderIndex &hdidx, Headers &headers,
340                   int64_t &content_length) {
341   for (size_t i = 0; i < headers.size(); ++i) {
342     auto &kv = headers[i];
343     util::inp_strlower(kv.name);
344
345     auto token = http2::lookup_token(
346         reinterpret_cast<const uint8_t *>(kv.name.c_str()), kv.name.size());
347     if (token < 0) {
348       continue;
349     }
350
351     kv.token = token;
352     http2::index_header(hdidx, token, i);
353
354     if (token == http2::HD_CONTENT_LENGTH) {
355       auto len = util::parse_uint(kv.value);
356       if (len == -1) {
357         return -1;
358       }
359       if (content_length != -1) {
360         return -1;
361       }
362       content_length = len;
363     }
364   }
365   return 0;
366 }
367 } // namespace
368
369 int Downstream::index_request_headers() {
370   return index_headers(request_hdidx_, request_headers_,
371                        request_content_length_);
372 }
373
374 const Headers::value_type *Downstream::get_request_header(int16_t token) const {
375   return http2::get_header(request_hdidx_, token, request_headers_);
376 }
377
378 const Headers::value_type *
379 Downstream::get_request_header(const std::string &name) const {
380   return get_header_linear(request_headers_, name);
381 }
382
383 void Downstream::add_request_header(std::string name, std::string value) {
384   add_header(request_header_key_prev_, request_headers_sum_, request_headers_,
385              std::move(name), std::move(value));
386 }
387
388 void Downstream::set_last_request_header_value(const char *data, size_t len) {
389   set_last_header_value(request_header_key_prev_, request_headers_sum_,
390                         request_headers_, data, len);
391 }
392
393 void Downstream::add_request_header(std::string name, std::string value,
394                                     int16_t token) {
395   http2::index_header(request_hdidx_, token, request_headers_.size());
396   request_headers_sum_ += name.size() + value.size();
397   request_headers_.emplace_back(std::move(name), std::move(value), false,
398                                 token);
399 }
400
401 void Downstream::add_request_header(const uint8_t *name, size_t namelen,
402                                     const uint8_t *value, size_t valuelen,
403                                     bool no_index, int16_t token) {
404   http2::index_header(request_hdidx_, token, request_headers_.size());
405   request_headers_sum_ += namelen + valuelen;
406   http2::add_header(request_headers_, name, namelen, value, valuelen, no_index,
407                     token);
408 }
409
410 bool Downstream::get_request_header_key_prev() const {
411   return request_header_key_prev_;
412 }
413
414 void Downstream::append_last_request_header_key(const char *data, size_t len) {
415   append_last_header_key(request_header_key_prev_, request_headers_sum_,
416                          request_headers_, data, len);
417 }
418
419 void Downstream::append_last_request_header_value(const char *data,
420                                                   size_t len) {
421   append_last_header_value(request_header_key_prev_, request_headers_sum_,
422                            request_headers_, data, len);
423 }
424
425 void Downstream::clear_request_headers() {
426   Headers().swap(request_headers_);
427   http2::init_hdidx(request_hdidx_);
428 }
429
430 size_t Downstream::get_request_headers_sum() const {
431   return request_headers_sum_;
432 }
433
434 void Downstream::add_request_trailer(const uint8_t *name, size_t namelen,
435                                      const uint8_t *value, size_t valuelen,
436                                      bool no_index, int16_t token) {
437   // we never index trailer part.  Header size limit should be applied
438   // to all request header fields combined.
439   request_headers_sum_ += namelen + valuelen;
440   http2::add_header(request_trailers_, name, namelen, value, valuelen, no_index,
441                     -1);
442 }
443
444 const Headers &Downstream::get_request_trailers() const {
445   return request_trailers_;
446 }
447
448 void Downstream::add_request_trailer(std::string name, std::string value) {
449   add_header(request_trailer_key_prev_, request_headers_sum_, request_trailers_,
450              std::move(name), std::move(value));
451 }
452
453 void Downstream::set_last_request_trailer_value(const char *data, size_t len) {
454   set_last_header_value(request_trailer_key_prev_, request_headers_sum_,
455                         request_trailers_, data, len);
456 }
457
458 bool Downstream::get_request_trailer_key_prev() const {
459   return request_trailer_key_prev_;
460 }
461
462 void Downstream::append_last_request_trailer_key(const char *data, size_t len) {
463   append_last_header_key(request_trailer_key_prev_, request_headers_sum_,
464                          request_trailers_, data, len);
465 }
466
467 void Downstream::append_last_request_trailer_value(const char *data,
468                                                    size_t len) {
469   append_last_header_value(request_trailer_key_prev_, request_headers_sum_,
470                            request_trailers_, data, len);
471 }
472
473 void Downstream::set_request_method(std::string method) {
474   request_method_ = std::move(method);
475 }
476
477 const std::string &Downstream::get_request_method() const {
478   return request_method_;
479 }
480
481 void Downstream::set_request_path(std::string path) {
482   request_path_ = std::move(path);
483 }
484
485 void Downstream::append_request_path(const char *data, size_t len) {
486   request_path_.append(data, len);
487 }
488
489 const std::string &Downstream::get_request_path() const {
490   return request_path_;
491 }
492
493 void Downstream::set_request_start_time(
494     std::chrono::high_resolution_clock::time_point time) {
495   request_start_time_ = std::move(time);
496 }
497
498 const std::chrono::high_resolution_clock::time_point &
499 Downstream::get_request_start_time() const {
500   return request_start_time_;
501 }
502
503 const std::string &Downstream::get_request_http2_scheme() const {
504   return request_http2_scheme_;
505 }
506
507 void Downstream::set_request_http2_scheme(std::string scheme) {
508   request_http2_scheme_ = std::move(scheme);
509 }
510
511 const std::string &Downstream::get_request_http2_authority() const {
512   return request_http2_authority_;
513 }
514
515 void Downstream::set_request_http2_authority(std::string authority) {
516   request_http2_authority_ = std::move(authority);
517 }
518
519 void Downstream::set_request_major(int major) { request_major_ = major; }
520
521 void Downstream::set_request_minor(int minor) { request_minor_ = minor; }
522
523 int Downstream::get_request_major() const { return request_major_; }
524
525 int Downstream::get_request_minor() const { return request_minor_; }
526
527 void Downstream::reset_upstream(Upstream *upstream) {
528   upstream_ = upstream;
529   if (dconn_) {
530     dconn_->on_upstream_change(upstream);
531   }
532 }
533
534 Upstream *Downstream::get_upstream() const { return upstream_; }
535
536 void Downstream::set_stream_id(int32_t stream_id) { stream_id_ = stream_id; }
537
538 int32_t Downstream::get_stream_id() const { return stream_id_; }
539
540 void Downstream::set_request_state(int state) { request_state_ = state; }
541
542 int Downstream::get_request_state() const { return request_state_; }
543
544 bool Downstream::get_chunked_request() const { return chunked_request_; }
545
546 void Downstream::set_chunked_request(bool f) { chunked_request_ = f; }
547
548 bool Downstream::get_request_connection_close() const {
549   return request_connection_close_;
550 }
551
552 void Downstream::set_request_connection_close(bool f) {
553   request_connection_close_ = f;
554 }
555
556 bool Downstream::get_request_http2_expect_body() const {
557   return request_http2_expect_body_;
558 }
559
560 void Downstream::set_request_http2_expect_body(bool f) {
561   request_http2_expect_body_ = f;
562 }
563
564 bool Downstream::request_buf_full() {
565   if (dconn_) {
566     return request_buf_.rleft() >= get_config()->downstream_request_buffer_size;
567   } else {
568     return false;
569   }
570 }
571
572 DefaultMemchunks *Downstream::get_request_buf() { return &request_buf_; }
573
574 // Call this function after this object is attached to
575 // Downstream. Otherwise, the program will crash.
576 int Downstream::push_request_headers() {
577   if (!dconn_) {
578     DLOG(INFO, this) << "dconn_ is NULL";
579     return -1;
580   }
581   return dconn_->push_request_headers();
582 }
583
584 int Downstream::push_upload_data_chunk(const uint8_t *data, size_t datalen) {
585   // Assumes that request headers have already been pushed to output
586   // buffer using push_request_headers().
587   if (!dconn_) {
588     DLOG(INFO, this) << "dconn_ is NULL";
589     return -1;
590   }
591   request_bodylen_ += datalen;
592   if (dconn_->push_upload_data_chunk(data, datalen) != 0) {
593     return -1;
594   }
595
596   request_datalen_ += datalen;
597
598   return 0;
599 }
600
601 int Downstream::end_upload_data() {
602   if (!dconn_) {
603     DLOG(INFO, this) << "dconn_ is NULL";
604     return -1;
605   }
606   return dconn_->end_upload_data();
607 }
608
609 const Headers &Downstream::get_response_headers() const {
610   return response_headers_;
611 }
612
613 int Downstream::index_response_headers() {
614   return index_headers(response_hdidx_, response_headers_,
615                        response_content_length_);
616 }
617
618 const Headers::value_type *
619 Downstream::get_response_header(int16_t token) const {
620   return http2::get_header(response_hdidx_, token, response_headers_);
621 }
622
623 void Downstream::rewrite_location_response_header(
624     const std::string &upstream_scheme) {
625   auto hd =
626       http2::get_header(response_hdidx_, http2::HD_LOCATION, response_headers_);
627   if (!hd) {
628     return;
629   }
630   http_parser_url u;
631   memset(&u, 0, sizeof(u));
632   int rv =
633       http_parser_parse_url((*hd).value.c_str(), (*hd).value.size(), 0, &u);
634   if (rv != 0) {
635     return;
636   }
637   std::string new_uri;
638   if (get_config()->no_host_rewrite || request_method_ == "CONNECT") {
639     if (!request_http2_authority_.empty()) {
640       new_uri = http2::rewrite_location_uri(
641           (*hd).value, u, request_http2_authority_, request_http2_authority_,
642           upstream_scheme);
643     }
644     if (new_uri.empty()) {
645       auto host = get_request_header(http2::HD_HOST);
646       if (host) {
647         new_uri = http2::rewrite_location_uri((*hd).value, u, (*host).value,
648                                               (*host).value, upstream_scheme);
649       } else if (!request_downstream_host_.empty()) {
650         new_uri = http2::rewrite_location_uri(
651             (*hd).value, u, request_downstream_host_, "", upstream_scheme);
652       } else {
653         return;
654       }
655     }
656   } else {
657     if (request_downstream_host_.empty()) {
658       return;
659     }
660     if (!request_http2_authority_.empty()) {
661       new_uri = http2::rewrite_location_uri(
662           (*hd).value, u, request_downstream_host_, request_http2_authority_,
663           upstream_scheme);
664     } else {
665       auto host = get_request_header(http2::HD_HOST);
666       if (host) {
667         new_uri = http2::rewrite_location_uri((*hd).value, u,
668                                               request_downstream_host_,
669                                               (*host).value, upstream_scheme);
670       } else {
671         new_uri = http2::rewrite_location_uri(
672             (*hd).value, u, request_downstream_host_, "", upstream_scheme);
673       }
674     }
675   }
676   if (!new_uri.empty()) {
677     auto idx = response_hdidx_[http2::HD_LOCATION];
678     response_headers_[idx].value = std::move(new_uri);
679   }
680 }
681
682 void Downstream::add_response_header(std::string name, std::string value) {
683   add_header(response_header_key_prev_, response_headers_sum_,
684              response_headers_, std::move(name), std::move(value));
685 }
686
687 void Downstream::set_last_response_header_value(const char *data, size_t len) {
688   set_last_header_value(response_header_key_prev_, response_headers_sum_,
689                         response_headers_, data, len);
690 }
691
692 void Downstream::add_response_header(std::string name, std::string value,
693                                      int16_t token) {
694   http2::index_header(response_hdidx_, token, response_headers_.size());
695   response_headers_sum_ += name.size() + value.size();
696   response_headers_.emplace_back(std::move(name), std::move(value), false,
697                                  token);
698 }
699
700 void Downstream::add_response_header(const uint8_t *name, size_t namelen,
701                                      const uint8_t *value, size_t valuelen,
702                                      bool no_index, int16_t token) {
703   http2::index_header(response_hdidx_, token, response_headers_.size());
704   response_headers_sum_ += namelen + valuelen;
705   http2::add_header(response_headers_, name, namelen, value, valuelen, no_index,
706                     token);
707 }
708
709 bool Downstream::get_response_header_key_prev() const {
710   return response_header_key_prev_;
711 }
712
713 void Downstream::append_last_response_header_key(const char *data, size_t len) {
714   append_last_header_key(response_header_key_prev_, response_headers_sum_,
715                          response_headers_, data, len);
716 }
717
718 void Downstream::append_last_response_header_value(const char *data,
719                                                    size_t len) {
720   append_last_header_value(response_header_key_prev_, response_headers_sum_,
721                            response_headers_, data, len);
722 }
723
724 void Downstream::clear_response_headers() {
725   Headers().swap(response_headers_);
726   http2::init_hdidx(response_hdidx_);
727 }
728
729 size_t Downstream::get_response_headers_sum() const {
730   return response_headers_sum_;
731 }
732
733 const Headers &Downstream::get_response_trailers() const {
734   return response_trailers_;
735 }
736
737 void Downstream::add_response_trailer(const uint8_t *name, size_t namelen,
738                                       const uint8_t *value, size_t valuelen,
739                                       bool no_index, int16_t token) {
740   response_headers_sum_ += namelen + valuelen;
741   http2::add_header(response_trailers_, name, namelen, value, valuelen,
742                     no_index, -1);
743 }
744
745 unsigned int Downstream::get_response_http_status() const {
746   return response_http_status_;
747 }
748
749 void Downstream::add_response_trailer(std::string name, std::string value) {
750   add_header(response_trailer_key_prev_, response_headers_sum_,
751              response_trailers_, std::move(name), std::move(value));
752 }
753
754 void Downstream::set_last_response_trailer_value(const char *data, size_t len) {
755   set_last_header_value(response_trailer_key_prev_, response_headers_sum_,
756                         response_trailers_, data, len);
757 }
758
759 bool Downstream::get_response_trailer_key_prev() const {
760   return response_trailer_key_prev_;
761 }
762
763 void Downstream::append_last_response_trailer_key(const char *data,
764                                                   size_t len) {
765   append_last_header_key(response_trailer_key_prev_, response_headers_sum_,
766                          response_trailers_, data, len);
767 }
768
769 void Downstream::append_last_response_trailer_value(const char *data,
770                                                     size_t len) {
771   append_last_header_value(response_trailer_key_prev_, response_headers_sum_,
772                            response_trailers_, data, len);
773 }
774
775 void Downstream::set_response_http_status(unsigned int status) {
776   response_http_status_ = status;
777 }
778
779 void Downstream::set_response_major(int major) { response_major_ = major; }
780
781 void Downstream::set_response_minor(int minor) { response_minor_ = minor; }
782
783 int Downstream::get_response_major() const { return response_major_; }
784
785 int Downstream::get_response_minor() const { return response_minor_; }
786
787 int Downstream::get_response_version() const {
788   return response_major_ * 100 + response_minor_;
789 }
790
791 bool Downstream::get_chunked_response() const { return chunked_response_; }
792
793 void Downstream::set_chunked_response(bool f) { chunked_response_ = f; }
794
795 bool Downstream::get_response_connection_close() const {
796   return response_connection_close_;
797 }
798
799 void Downstream::set_response_connection_close(bool f) {
800   response_connection_close_ = f;
801 }
802
803 int Downstream::on_read() {
804   if (!dconn_) {
805     DLOG(INFO, this) << "dconn_ is NULL";
806     return -1;
807   }
808   return dconn_->on_read();
809 }
810
811 int Downstream::change_priority(int32_t pri) {
812   if (!dconn_) {
813     DLOG(INFO, this) << "dconn_ is NULL";
814     return -1;
815   }
816   return dconn_->on_priority_change(pri);
817 }
818
819 void Downstream::set_response_state(int state) { response_state_ = state; }
820
821 int Downstream::get_response_state() const { return response_state_; }
822
823 DefaultMemchunks *Downstream::get_response_buf() { return &response_buf_; }
824
825 bool Downstream::response_buf_full() {
826   if (dconn_) {
827     return response_buf_.rleft() >=
828            get_config()->downstream_response_buffer_size;
829   } else {
830     return false;
831   }
832 }
833
834 void Downstream::add_response_bodylen(size_t amount) {
835   response_bodylen_ += amount;
836 }
837
838 int64_t Downstream::get_response_bodylen() const { return response_bodylen_; }
839
840 void Downstream::add_response_sent_bodylen(size_t amount) {
841   response_sent_bodylen_ += amount;
842 }
843
844 int64_t Downstream::get_response_sent_bodylen() const {
845   return response_sent_bodylen_;
846 }
847
848 int64_t Downstream::get_response_content_length() const {
849   return response_content_length_;
850 }
851
852 void Downstream::set_response_content_length(int64_t len) {
853   response_content_length_ = len;
854 }
855
856 int64_t Downstream::get_request_content_length() const {
857   return request_content_length_;
858 }
859
860 void Downstream::set_request_content_length(int64_t len) {
861   request_content_length_ = len;
862 }
863
864 bool Downstream::validate_request_bodylen() const {
865   if (request_content_length_ == -1) {
866     return true;
867   }
868
869   if (request_content_length_ != request_bodylen_) {
870     if (LOG_ENABLED(INFO)) {
871       DLOG(INFO, this) << "request invalid bodylen: content-length="
872                        << request_content_length_
873                        << ", received=" << request_bodylen_;
874     }
875     return false;
876   }
877
878   return true;
879 }
880
881 bool Downstream::validate_response_bodylen() const {
882   if (!expect_response_body() || response_content_length_ == -1) {
883     return true;
884   }
885
886   if (response_content_length_ != response_bodylen_) {
887     if (LOG_ENABLED(INFO)) {
888       DLOG(INFO, this) << "response invalid bodylen: content-length="
889                        << response_content_length_
890                        << ", received=" << response_bodylen_;
891     }
892     return false;
893   }
894
895   return true;
896 }
897
898 void Downstream::set_priority(int32_t pri) { priority_ = pri; }
899
900 int32_t Downstream::get_priority() const { return priority_; }
901
902 void Downstream::check_upgrade_fulfilled() {
903   if (request_method_ == "CONNECT") {
904     upgraded_ = 200 <= response_http_status_ && response_http_status_ < 300;
905
906     return;
907   }
908
909   if (response_http_status_ == 101) {
910     // TODO Do more strict checking for upgrade headers
911     upgraded_ = upgrade_request_;
912
913     return;
914   }
915 }
916
917 void Downstream::inspect_http2_request() {
918   if (request_method_ == "CONNECT") {
919     upgrade_request_ = true;
920   }
921 }
922
923 void Downstream::inspect_http1_request() {
924   if (request_method_ == "CONNECT") {
925     upgrade_request_ = true;
926   }
927
928   if (!upgrade_request_) {
929     auto idx = request_hdidx_[http2::HD_UPGRADE];
930     if (idx != -1) {
931       upgrade_request_ = true;
932
933       auto &val = request_headers_[idx].value;
934       // TODO Perform more strict checking for upgrade headers
935       if (util::streq_l(NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, val.c_str(),
936                         val.size())) {
937         http2_upgrade_seen_ = true;
938       }
939     }
940   }
941   auto idx = request_hdidx_[http2::HD_TRANSFER_ENCODING];
942   if (idx != -1) {
943     request_content_length_ = -1;
944     if (util::strifind(request_headers_[idx].value.c_str(), "chunked")) {
945       chunked_request_ = true;
946     }
947   }
948 }
949
950 void Downstream::inspect_http1_response() {
951   auto idx = response_hdidx_[http2::HD_TRANSFER_ENCODING];
952   if (idx != -1) {
953     response_content_length_ = -1;
954     if (util::strifind(response_headers_[idx].value.c_str(), "chunked")) {
955       chunked_response_ = true;
956     }
957   }
958 }
959
960 void Downstream::reset_response() {
961   response_http_status_ = 0;
962   response_major_ = 1;
963   response_minor_ = 1;
964 }
965
966 bool Downstream::get_non_final_response() const {
967   return response_http_status_ / 100 == 1;
968 }
969
970 bool Downstream::get_upgraded() const { return upgraded_; }
971
972 bool Downstream::get_upgrade_request() const { return upgrade_request_; }
973
974 bool Downstream::get_http2_upgrade_request() const {
975   return request_bodylen_ == 0 && http2_upgrade_seen_ &&
976          request_hdidx_[http2::HD_HTTP2_SETTINGS] != -1;
977 }
978
979 namespace {
980 const std::string EMPTY;
981 } // namespace
982
983 const std::string &Downstream::get_http2_settings() const {
984   auto idx = request_hdidx_[http2::HD_HTTP2_SETTINGS];
985   if (idx == -1) {
986     return EMPTY;
987   }
988   return request_headers_[idx].value;
989 }
990
991 void Downstream::set_downstream_stream_id(int32_t stream_id) {
992   downstream_stream_id_ = stream_id;
993 }
994
995 int32_t Downstream::get_downstream_stream_id() const {
996   return downstream_stream_id_;
997 }
998
999 uint32_t Downstream::get_response_rst_stream_error_code() const {
1000   return response_rst_stream_error_code_;
1001 }
1002
1003 void Downstream::set_response_rst_stream_error_code(uint32_t error_code) {
1004   response_rst_stream_error_code_ = error_code;
1005 }
1006
1007 void Downstream::set_expect_final_response(bool f) {
1008   expect_final_response_ = f;
1009 }
1010
1011 bool Downstream::get_expect_final_response() const {
1012   return expect_final_response_;
1013 }
1014
1015 size_t Downstream::get_request_datalen() const { return request_datalen_; }
1016
1017 void Downstream::dec_request_datalen(size_t len) {
1018   assert(request_datalen_ >= len);
1019   request_datalen_ -= len;
1020 }
1021
1022 void Downstream::reset_request_datalen() { request_datalen_ = 0; }
1023
1024 void Downstream::add_response_datalen(size_t len) { response_datalen_ += len; }
1025
1026 void Downstream::dec_response_datalen(size_t len) {
1027   assert(response_datalen_ >= len);
1028   response_datalen_ -= len;
1029 }
1030
1031 size_t Downstream::get_response_datalen() const { return response_datalen_; }
1032
1033 void Downstream::reset_response_datalen() { response_datalen_ = 0; }
1034
1035 bool Downstream::expect_response_body() const {
1036   return http2::expect_response_body(request_method_, response_http_status_);
1037 }
1038
1039 namespace {
1040 bool pseudo_header_allowed(const Headers &headers) {
1041   if (headers.empty()) {
1042     return true;
1043   }
1044
1045   return headers.back().name.c_str()[0] == ':';
1046 }
1047 } // namespace
1048
1049 bool Downstream::request_pseudo_header_allowed(int16_t token) const {
1050   if (!pseudo_header_allowed(request_headers_)) {
1051     return false;
1052   }
1053   return http2::check_http2_request_pseudo_header(request_hdidx_, token);
1054 }
1055
1056 bool Downstream::response_pseudo_header_allowed(int16_t token) const {
1057   if (!pseudo_header_allowed(response_headers_)) {
1058     return false;
1059   }
1060   return http2::check_http2_response_pseudo_header(response_hdidx_, token);
1061 }
1062
1063 namespace {
1064 void reset_timer(struct ev_loop *loop, ev_timer *w) { ev_timer_again(loop, w); }
1065 } // namespace
1066
1067 namespace {
1068 void try_reset_timer(struct ev_loop *loop, ev_timer *w) {
1069   if (!ev_is_active(w)) {
1070     return;
1071   }
1072   ev_timer_again(loop, w);
1073 }
1074 } // namespace
1075
1076 namespace {
1077 void ensure_timer(struct ev_loop *loop, ev_timer *w) {
1078   if (ev_is_active(w)) {
1079     return;
1080   }
1081   ev_timer_again(loop, w);
1082 }
1083 } // namespace
1084
1085 namespace {
1086 void disable_timer(struct ev_loop *loop, ev_timer *w) {
1087   ev_timer_stop(loop, w);
1088 }
1089 } // namespace
1090
1091 void Downstream::reset_upstream_rtimer() {
1092   if (get_config()->stream_read_timeout == 0.) {
1093     return;
1094   }
1095   auto loop = upstream_->get_client_handler()->get_loop();
1096   reset_timer(loop, &upstream_rtimer_);
1097 }
1098
1099 void Downstream::reset_upstream_wtimer() {
1100   auto loop = upstream_->get_client_handler()->get_loop();
1101   if (get_config()->stream_write_timeout != 0.) {
1102     reset_timer(loop, &upstream_wtimer_);
1103   }
1104   if (get_config()->stream_read_timeout != 0.) {
1105     try_reset_timer(loop, &upstream_rtimer_);
1106   }
1107 }
1108
1109 void Downstream::ensure_upstream_wtimer() {
1110   if (get_config()->stream_write_timeout == 0.) {
1111     return;
1112   }
1113   auto loop = upstream_->get_client_handler()->get_loop();
1114   ensure_timer(loop, &upstream_wtimer_);
1115 }
1116
1117 void Downstream::disable_upstream_rtimer() {
1118   if (get_config()->stream_read_timeout == 0.) {
1119     return;
1120   }
1121   auto loop = upstream_->get_client_handler()->get_loop();
1122   disable_timer(loop, &upstream_rtimer_);
1123 }
1124
1125 void Downstream::disable_upstream_wtimer() {
1126   if (get_config()->stream_write_timeout == 0.) {
1127     return;
1128   }
1129   auto loop = upstream_->get_client_handler()->get_loop();
1130   disable_timer(loop, &upstream_wtimer_);
1131 }
1132
1133 void Downstream::reset_downstream_rtimer() {
1134   if (get_config()->stream_read_timeout == 0.) {
1135     return;
1136   }
1137   auto loop = upstream_->get_client_handler()->get_loop();
1138   reset_timer(loop, &downstream_rtimer_);
1139 }
1140
1141 void Downstream::reset_downstream_wtimer() {
1142   auto loop = upstream_->get_client_handler()->get_loop();
1143   if (get_config()->stream_write_timeout != 0.) {
1144     reset_timer(loop, &downstream_wtimer_);
1145   }
1146   if (get_config()->stream_read_timeout != 0.) {
1147     try_reset_timer(loop, &downstream_rtimer_);
1148   }
1149 }
1150
1151 void Downstream::ensure_downstream_wtimer() {
1152   if (get_config()->stream_write_timeout == 0.) {
1153     return;
1154   }
1155   auto loop = upstream_->get_client_handler()->get_loop();
1156   ensure_timer(loop, &downstream_wtimer_);
1157 }
1158
1159 void Downstream::disable_downstream_rtimer() {
1160   if (get_config()->stream_read_timeout == 0.) {
1161     return;
1162   }
1163   auto loop = upstream_->get_client_handler()->get_loop();
1164   disable_timer(loop, &downstream_rtimer_);
1165 }
1166
1167 void Downstream::disable_downstream_wtimer() {
1168   if (get_config()->stream_write_timeout == 0.) {
1169     return;
1170   }
1171   auto loop = upstream_->get_client_handler()->get_loop();
1172   disable_timer(loop, &downstream_wtimer_);
1173 }
1174
1175 bool Downstream::accesslog_ready() const { return response_http_status_ > 0; }
1176
1177 void Downstream::add_retry() { ++num_retry_; }
1178
1179 bool Downstream::no_more_retry() const { return num_retry_ > 5; }
1180
1181 void Downstream::set_request_downstream_host(std::string host) {
1182   request_downstream_host_ = std::move(host);
1183 }
1184
1185 void Downstream::set_request_pending(bool f) { request_pending_ = f; }
1186
1187 bool Downstream::get_request_pending() const { return request_pending_; }
1188
1189 bool Downstream::request_submission_ready() const {
1190   return (request_state_ == Downstream::HEADER_COMPLETE ||
1191           request_state_ == Downstream::MSG_COMPLETE) &&
1192          request_pending_ && response_state_ == Downstream::INITIAL;
1193 }
1194
1195 int Downstream::get_dispatch_state() const { return dispatch_state_; }
1196
1197 void Downstream::set_dispatch_state(int s) { dispatch_state_ = s; }
1198
1199 void Downstream::attach_blocked_link(BlockedLink *l) {
1200   assert(!blocked_link_);
1201
1202   l->downstream = this;
1203   blocked_link_ = l;
1204 }
1205
1206 void Downstream::detach_blocked_link(BlockedLink *l) {
1207   assert(blocked_link_);
1208   assert(l->downstream == this);
1209
1210   l->downstream = nullptr;
1211   blocked_link_ = nullptr;
1212 }
1213
1214 void Downstream::add_request_headers_sum(size_t amount) {
1215   request_headers_sum_ += amount;
1216 }
1217
1218 } // namespace shrpx