Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / src / shrpx_client_handler.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_client_handler.h"
26
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif // HAVE_UNISTD_H
30 #include <cerrno>
31
32 #include "shrpx_upstream.h"
33 #include "shrpx_http2_upstream.h"
34 #include "shrpx_https_upstream.h"
35 #include "shrpx_config.h"
36 #include "shrpx_http_downstream_connection.h"
37 #include "shrpx_http2_downstream_connection.h"
38 #include "shrpx_ssl.h"
39 #include "shrpx_worker.h"
40 #include "shrpx_downstream_connection_pool.h"
41 #include "shrpx_downstream.h"
42 #ifdef HAVE_SPDYLAY
43 #include "shrpx_spdy_upstream.h"
44 #endif // HAVE_SPDYLAY
45 #include "util.h"
46 #include "template.h"
47
48 using namespace nghttp2;
49
50 namespace shrpx {
51
52 namespace {
53 void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
54   auto conn = static_cast<Connection *>(w->data);
55   auto handler = static_cast<ClientHandler *>(conn->data);
56
57   if (LOG_ENABLED(INFO)) {
58     CLOG(INFO, handler) << "Time out";
59   }
60
61   delete handler;
62 }
63 } // namespace
64
65 namespace {
66 void shutdowncb(struct ev_loop *loop, ev_timer *w, int revents) {
67   auto handler = static_cast<ClientHandler *>(w->data);
68
69   if (LOG_ENABLED(INFO)) {
70     CLOG(INFO, handler) << "Close connection due to TLS renegotiation";
71   }
72
73   delete handler;
74 }
75 } // namespace
76
77 namespace {
78 void readcb(struct ev_loop *loop, ev_io *w, int revents) {
79   auto conn = static_cast<Connection *>(w->data);
80   auto handler = static_cast<ClientHandler *>(conn->data);
81
82   if (handler->do_read() != 0) {
83     delete handler;
84     return;
85   }
86   if (handler->do_write() != 0) {
87     delete handler;
88     return;
89   }
90 }
91 } // namespace
92
93 namespace {
94 void writecb(struct ev_loop *loop, ev_io *w, int revents) {
95   auto conn = static_cast<Connection *>(w->data);
96   auto handler = static_cast<ClientHandler *>(conn->data);
97
98   if (handler->do_write() != 0) {
99     delete handler;
100     return;
101   }
102 }
103 } // namespace
104
105 int ClientHandler::read_clear() {
106   ev_timer_again(conn_.loop, &conn_.rt);
107
108   for (;;) {
109     if (rb_.rleft() && on_read() != 0) {
110       return -1;
111     }
112     if (rb_.rleft() == 0) {
113       rb_.reset();
114     } else if (rb_.wleft() == 0) {
115       conn_.rlimit.stopw();
116       return 0;
117     }
118
119     auto nread = conn_.read_clear(rb_.last, rb_.wleft());
120
121     if (nread == 0) {
122       return 0;
123     }
124
125     if (nread < 0) {
126       return -1;
127     }
128
129     rb_.write(nread);
130   }
131 }
132
133 int ClientHandler::write_clear() {
134   ev_timer_again(conn_.loop, &conn_.rt);
135
136   for (;;) {
137     if (wb_.rleft() > 0) {
138       auto nwrite = conn_.write_clear(wb_.pos, wb_.rleft());
139       if (nwrite == 0) {
140         return 0;
141       }
142       if (nwrite < 0) {
143         return -1;
144       }
145       wb_.drain(nwrite);
146       continue;
147     }
148     wb_.reset();
149     if (on_write() != 0) {
150       return -1;
151     }
152     if (wb_.rleft() == 0) {
153       break;
154     }
155   }
156
157   conn_.wlimit.stopw();
158   ev_timer_stop(conn_.loop, &conn_.wt);
159
160   return 0;
161 }
162
163 int ClientHandler::tls_handshake() {
164   ev_timer_again(conn_.loop, &conn_.rt);
165
166   ERR_clear_error();
167
168   auto rv = conn_.tls_handshake();
169
170   if (rv == SHRPX_ERR_INPROGRESS) {
171     return 0;
172   }
173
174   if (rv < 0) {
175     return -1;
176   }
177
178   if (LOG_ENABLED(INFO)) {
179     CLOG(INFO, this) << "SSL/TLS handshake completed";
180   }
181
182   if (validate_next_proto() != 0) {
183     return -1;
184   }
185
186   read_ = &ClientHandler::read_tls;
187   write_ = &ClientHandler::write_tls;
188
189   return 0;
190 }
191
192 int ClientHandler::read_tls() {
193   ev_timer_again(conn_.loop, &conn_.rt);
194
195   ERR_clear_error();
196
197   for (;;) {
198     // we should process buffered data first before we read EOF.
199     if (rb_.rleft() && on_read() != 0) {
200       return -1;
201     }
202     if (rb_.rleft() == 0) {
203       rb_.reset();
204     } else if (rb_.wleft() == 0) {
205       conn_.rlimit.stopw();
206       return 0;
207     }
208
209     auto nread = conn_.read_tls(rb_.last, rb_.wleft());
210
211     if (nread == 0) {
212       return 0;
213     }
214
215     if (nread < 0) {
216       return -1;
217     }
218
219     rb_.write(nread);
220   }
221 }
222
223 int ClientHandler::write_tls() {
224   ev_timer_again(conn_.loop, &conn_.rt);
225
226   ERR_clear_error();
227
228   for (;;) {
229     if (wb_.rleft() > 0) {
230       auto nwrite = conn_.write_tls(wb_.pos, wb_.rleft());
231
232       if (nwrite == 0) {
233         return 0;
234       }
235
236       if (nwrite < 0) {
237         return -1;
238       }
239
240       wb_.drain(nwrite);
241
242       continue;
243     }
244     wb_.reset();
245     if (on_write() != 0) {
246       return -1;
247     }
248     if (wb_.rleft() == 0) {
249       break;
250     }
251   }
252
253   conn_.wlimit.stopw();
254   ev_timer_stop(conn_.loop, &conn_.wt);
255
256   return 0;
257 }
258
259 int ClientHandler::upstream_noop() { return 0; }
260
261 int ClientHandler::upstream_read() {
262   assert(upstream_);
263   if (upstream_->on_read() != 0) {
264     return -1;
265   }
266   return 0;
267 }
268
269 int ClientHandler::upstream_write() {
270   assert(upstream_);
271   if (upstream_->on_write() != 0) {
272     return -1;
273   }
274
275   if (get_should_close_after_write() && wb_.rleft() == 0) {
276     return -1;
277   }
278
279   return 0;
280 }
281
282 int ClientHandler::upstream_http2_connhd_read() {
283   auto nread = std::min(left_connhd_len_, rb_.rleft());
284   if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_,
285              rb_.pos, nread) != 0) {
286     // There is no downgrade path here. Just drop the connection.
287     if (LOG_ENABLED(INFO)) {
288       CLOG(INFO, this) << "invalid client connection header";
289     }
290
291     return -1;
292   }
293
294   left_connhd_len_ -= nread;
295   rb_.drain(nread);
296   conn_.rlimit.startw();
297
298   if (left_connhd_len_ == 0) {
299     on_read_ = &ClientHandler::upstream_read;
300     // Run on_read to process data left in buffer since they are not
301     // notified further
302     if (on_read() != 0) {
303       return -1;
304     }
305     return 0;
306   }
307
308   return 0;
309 }
310
311 int ClientHandler::upstream_http1_connhd_read() {
312   auto nread = std::min(left_connhd_len_, rb_.rleft());
313   if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN - left_connhd_len_,
314              rb_.pos, nread) != 0) {
315     if (LOG_ENABLED(INFO)) {
316       CLOG(INFO, this) << "This is HTTP/1.1 connection, "
317                        << "but may be upgraded to HTTP/2 later.";
318     }
319
320     // Reset header length for later HTTP/2 upgrade
321     left_connhd_len_ = NGHTTP2_CLIENT_MAGIC_LEN;
322     on_read_ = &ClientHandler::upstream_read;
323     on_write_ = &ClientHandler::upstream_write;
324
325     if (on_read() != 0) {
326       return -1;
327     }
328
329     return 0;
330   }
331
332   left_connhd_len_ -= nread;
333   rb_.drain(nread);
334   conn_.rlimit.startw();
335
336   if (left_connhd_len_ == 0) {
337     if (LOG_ENABLED(INFO)) {
338       CLOG(INFO, this) << "direct HTTP/2 connection";
339     }
340
341     direct_http2_upgrade();
342     on_read_ = &ClientHandler::upstream_read;
343     on_write_ = &ClientHandler::upstream_write;
344
345     // Run on_read to process data left in buffer since they are not
346     // notified further
347     if (on_read() != 0) {
348       return -1;
349     }
350
351     return 0;
352   }
353
354   return 0;
355 }
356
357 ClientHandler::ClientHandler(Worker *worker, int fd, SSL *ssl,
358                              const char *ipaddr, const char *port)
359     : conn_(worker->get_loop(), fd, ssl, get_config()->upstream_write_timeout,
360             get_config()->upstream_read_timeout, get_config()->write_rate,
361             get_config()->write_burst, get_config()->read_rate,
362             get_config()->read_burst, writecb, readcb, timeoutcb, this),
363       ipaddr_(ipaddr), port_(port), worker_(worker),
364       http2session_(worker_->next_http2_session()),
365       left_connhd_len_(NGHTTP2_CLIENT_MAGIC_LEN),
366       should_close_after_write_(false) {
367
368   ++worker_->get_worker_stat()->num_connections;
369
370   ev_timer_init(&reneg_shutdown_timer_, shutdowncb, 0., 0.);
371
372   reneg_shutdown_timer_.data = this;
373
374   conn_.rlimit.startw();
375   ev_timer_again(conn_.loop, &conn_.rt);
376
377   if (conn_.tls.ssl) {
378     SSL_set_app_data(conn_.tls.ssl, &conn_);
379     read_ = write_ = &ClientHandler::tls_handshake;
380     on_read_ = &ClientHandler::upstream_noop;
381     on_write_ = &ClientHandler::upstream_write;
382   } else {
383     // For non-TLS version, first create HttpsUpstream. It may be
384     // upgraded to HTTP/2 through HTTP Upgrade or direct HTTP/2
385     // connection.
386     upstream_ = make_unique<HttpsUpstream>(this);
387     alpn_ = "http/1.1";
388     read_ = &ClientHandler::read_clear;
389     write_ = &ClientHandler::write_clear;
390     on_read_ = &ClientHandler::upstream_http1_connhd_read;
391     on_write_ = &ClientHandler::upstream_noop;
392   }
393 }
394
395 ClientHandler::~ClientHandler() {
396   if (LOG_ENABLED(INFO)) {
397     CLOG(INFO, this) << "Deleting";
398   }
399
400   if (upstream_) {
401     upstream_->on_handler_delete();
402   }
403
404   auto worker_stat = worker_->get_worker_stat();
405   --worker_stat->num_connections;
406
407   if (worker_stat->num_connections == 0) {
408     worker_->schedule_clear_mcpool();
409   }
410
411   ev_timer_stop(conn_.loop, &reneg_shutdown_timer_);
412
413   // TODO If backend is http/2, and it is in CONNECTED state, signal
414   // it and make it loopbreak when output is zero.
415   if (worker_->get_graceful_shutdown() && worker_stat->num_connections == 0) {
416     ev_break(conn_.loop);
417   }
418
419   if (LOG_ENABLED(INFO)) {
420     CLOG(INFO, this) << "Deleted";
421   }
422 }
423
424 Upstream *ClientHandler::get_upstream() { return upstream_.get(); }
425
426 struct ev_loop *ClientHandler::get_loop() const {
427   return conn_.loop;
428 }
429
430 void ClientHandler::reset_upstream_read_timeout(ev_tstamp t) {
431   conn_.rt.repeat = t;
432   if (ev_is_active(&conn_.rt)) {
433     ev_timer_again(conn_.loop, &conn_.rt);
434   }
435 }
436
437 void ClientHandler::reset_upstream_write_timeout(ev_tstamp t) {
438   conn_.wt.repeat = t;
439   if (ev_is_active(&conn_.wt)) {
440     ev_timer_again(conn_.loop, &conn_.wt);
441   }
442 }
443
444 int ClientHandler::validate_next_proto() {
445   const unsigned char *next_proto = nullptr;
446   unsigned int next_proto_len;
447   int rv;
448
449   // First set callback for catch all cases
450   on_read_ = &ClientHandler::upstream_read;
451
452   SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
453   for (int i = 0; i < 2; ++i) {
454     if (next_proto) {
455       if (LOG_ENABLED(INFO)) {
456         std::string proto(next_proto, next_proto + next_proto_len);
457         CLOG(INFO, this) << "The negotiated next protocol: " << proto;
458       }
459       if (!ssl::in_proto_list(get_config()->npn_list, next_proto,
460                               next_proto_len)) {
461         break;
462       }
463       if (util::check_h2_is_selected(next_proto, next_proto_len)) {
464
465         on_read_ = &ClientHandler::upstream_http2_connhd_read;
466
467         auto http2_upstream = make_unique<Http2Upstream>(this);
468
469         if (!ssl::check_http2_requirement(conn_.tls.ssl)) {
470           rv = http2_upstream->terminate_session(NGHTTP2_INADEQUATE_SECURITY);
471
472           if (rv != 0) {
473             return -1;
474           }
475         }
476
477         upstream_ = std::move(http2_upstream);
478         alpn_.assign(next_proto, next_proto + next_proto_len);
479
480         // At this point, input buffer is already filled with some
481         // bytes.  The read callback is not called until new data
482         // come. So consume input buffer here.
483         if (on_read() != 0) {
484           return -1;
485         }
486
487         return 0;
488       } else {
489 #ifdef HAVE_SPDYLAY
490         uint16_t version = spdylay_npn_get_version(next_proto, next_proto_len);
491         if (version) {
492           upstream_ = make_unique<SpdyUpstream>(version, this);
493
494           switch (version) {
495           case SPDYLAY_PROTO_SPDY2:
496             alpn_ = "spdy/2";
497             break;
498           case SPDYLAY_PROTO_SPDY3:
499             alpn_ = "spdy/3";
500             break;
501           case SPDYLAY_PROTO_SPDY3_1:
502             alpn_ = "spdy/3.1";
503             break;
504           default:
505             alpn_ = "spdy/unknown";
506           }
507
508           // At this point, input buffer is already filled with some
509           // bytes.  The read callback is not called until new data
510           // come. So consume input buffer here.
511           if (on_read() != 0) {
512             return -1;
513           }
514
515           return 0;
516         }
517 #endif // HAVE_SPDYLAY
518         if (next_proto_len == 8 && memcmp("http/1.1", next_proto, 8) == 0) {
519           upstream_ = make_unique<HttpsUpstream>(this);
520           alpn_ = "http/1.1";
521
522           // At this point, input buffer is already filled with some
523           // bytes.  The read callback is not called until new data
524           // come. So consume input buffer here.
525           if (on_read() != 0) {
526             return -1;
527           }
528
529           return 0;
530         }
531       }
532       break;
533     }
534 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
535     SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
536 #else  // OPENSSL_VERSION_NUMBER < 0x10002000L
537     break;
538 #endif // OPENSSL_VERSION_NUMBER < 0x10002000L
539   }
540   if (!next_proto) {
541     if (LOG_ENABLED(INFO)) {
542       CLOG(INFO, this) << "No protocol negotiated. Fallback to HTTP/1.1";
543     }
544     upstream_ = make_unique<HttpsUpstream>(this);
545     alpn_ = "http/1.1";
546
547     // At this point, input buffer is already filled with some bytes.
548     // The read callback is not called until new data come. So consume
549     // input buffer here.
550     if (on_read() != 0) {
551       return -1;
552     }
553
554     return 0;
555   }
556   if (LOG_ENABLED(INFO)) {
557     CLOG(INFO, this) << "The negotiated protocol is not supported";
558   }
559   return -1;
560 }
561
562 int ClientHandler::do_read() { return read_(*this); }
563 int ClientHandler::do_write() { return write_(*this); }
564
565 int ClientHandler::on_read() {
566   auto rv = on_read_(*this);
567   if (rv != 0) {
568     return rv;
569   }
570   conn_.handle_tls_pending_read();
571   return 0;
572 }
573 int ClientHandler::on_write() { return on_write_(*this); }
574
575 const std::string &ClientHandler::get_ipaddr() const { return ipaddr_; }
576
577 bool ClientHandler::get_should_close_after_write() const {
578   return should_close_after_write_;
579 }
580
581 void ClientHandler::set_should_close_after_write(bool f) {
582   should_close_after_write_ = f;
583 }
584
585 void ClientHandler::pool_downstream_connection(
586     std::unique_ptr<DownstreamConnection> dconn) {
587   if (!dconn->poolable()) {
588     return;
589   }
590   if (LOG_ENABLED(INFO)) {
591     CLOG(INFO, this) << "Pooling downstream connection DCONN:" << dconn.get();
592   }
593   dconn->set_client_handler(nullptr);
594   auto dconn_pool = worker_->get_dconn_pool();
595   dconn_pool->add_downstream_connection(std::move(dconn));
596 }
597
598 void ClientHandler::remove_downstream_connection(DownstreamConnection *dconn) {
599   if (LOG_ENABLED(INFO)) {
600     CLOG(INFO, this) << "Removing downstream connection DCONN:" << dconn
601                      << " from pool";
602   }
603   auto dconn_pool = worker_->get_dconn_pool();
604   dconn_pool->remove_downstream_connection(dconn);
605 }
606
607 std::unique_ptr<DownstreamConnection>
608 ClientHandler::get_downstream_connection() {
609   auto dconn_pool = worker_->get_dconn_pool();
610   auto dconn = dconn_pool->pop_downstream_connection();
611
612   if (!dconn) {
613     if (LOG_ENABLED(INFO)) {
614       CLOG(INFO, this) << "Downstream connection pool is empty."
615                        << " Create new one";
616     }
617
618     auto dconn_pool = worker_->get_dconn_pool();
619
620     if (http2session_) {
621       dconn = make_unique<Http2DownstreamConnection>(dconn_pool, http2session_);
622     } else {
623       dconn = make_unique<HttpDownstreamConnection>(dconn_pool, conn_.loop);
624     }
625     dconn->set_client_handler(this);
626     return dconn;
627   }
628
629   dconn->set_client_handler(this);
630
631   if (LOG_ENABLED(INFO)) {
632     CLOG(INFO, this) << "Reuse downstream connection DCONN:" << dconn.get()
633                      << " from pool";
634   }
635
636   return dconn;
637 }
638
639 MemchunkPool *ClientHandler::get_mcpool() { return worker_->get_mcpool(); }
640
641 SSL *ClientHandler::get_ssl() const { return conn_.tls.ssl; }
642
643 ConnectBlocker *ClientHandler::get_connect_blocker() const {
644   return worker_->get_connect_blocker();
645 }
646
647 void ClientHandler::direct_http2_upgrade() {
648   upstream_ = make_unique<Http2Upstream>(this);
649   alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID;
650   on_read_ = &ClientHandler::upstream_read;
651 }
652
653 int ClientHandler::perform_http2_upgrade(HttpsUpstream *http) {
654   auto upstream = make_unique<Http2Upstream>(this);
655   if (upstream->upgrade_upstream(http) != 0) {
656     return -1;
657   }
658   // http pointer is now owned by upstream.
659   upstream_.release();
660   upstream_ = std::move(upstream);
661   // TODO We might get other version id in HTTP2-settings, if we
662   // support aliasing for h2, but we just use library default for now.
663   alpn_ = NGHTTP2_CLEARTEXT_PROTO_VERSION_ID;
664   on_read_ = &ClientHandler::upstream_http2_connhd_read;
665
666   static char res[] = "HTTP/1.1 101 Switching Protocols\r\n"
667                       "Connection: Upgrade\r\n"
668                       "Upgrade: " NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "\r\n"
669                       "\r\n";
670   wb_.write(res, sizeof(res) - 1);
671   signal_write();
672   return 0;
673 }
674
675 bool ClientHandler::get_http2_upgrade_allowed() const { return !conn_.tls.ssl; }
676
677 std::string ClientHandler::get_upstream_scheme() const {
678   if (conn_.tls.ssl) {
679     return "https";
680   } else {
681     return "http";
682   }
683 }
684
685 void ClientHandler::start_immediate_shutdown() {
686   ev_timer_start(conn_.loop, &reneg_shutdown_timer_);
687 }
688
689 namespace {
690 // Construct absolute request URI from |downstream|, mainly to log
691 // request URI for proxy request (HTTP/2 proxy or client proxy).  This
692 // is mostly same routine found in
693 // HttpDownstreamConnection::push_request_headers(), but vastly
694 // simplified since we only care about absolute URI.
695 std::string construct_absolute_request_uri(Downstream *downstream) {
696   const char *authority = nullptr, *host = nullptr;
697   if (!downstream->get_request_http2_authority().empty()) {
698     authority = downstream->get_request_http2_authority().c_str();
699   }
700   auto h = downstream->get_request_header(http2::HD_HOST);
701   if (h) {
702     host = h->value.c_str();
703   }
704   if (!authority && !host) {
705     return downstream->get_request_path();
706   }
707   std::string uri;
708   if (downstream->get_request_http2_scheme().empty()) {
709     // this comes from HTTP/1 upstream without scheme.  Just use http.
710     uri += "http://";
711   } else {
712     uri += downstream->get_request_http2_scheme();
713     uri += "://";
714   }
715   if (authority) {
716     uri += authority;
717   } else {
718     uri += host;
719   }
720
721   // Server-wide OPTIONS takes following form in proxy request:
722   //
723   // OPTIONS http://example.org HTTP/1.1
724   //
725   // Notice that no slash after authority. See
726   // http://tools.ietf.org/html/rfc7230#section-5.3.4
727   if (downstream->get_request_path() != "*") {
728     uri += downstream->get_request_path();
729   }
730   return uri;
731 }
732 } // namespace
733
734 void ClientHandler::write_accesslog(Downstream *downstream) {
735   upstream_accesslog(
736       get_config()->accesslog_format,
737       LogSpec{
738           downstream, ipaddr_.c_str(), downstream->get_request_method().c_str(),
739
740           (downstream->get_request_method() != "CONNECT" &&
741            (get_config()->http2_proxy || get_config()->client_proxy))
742               ? construct_absolute_request_uri(downstream).c_str()
743               : downstream->get_request_path().empty()
744                     ? downstream->get_request_http2_authority().c_str()
745                     : downstream->get_request_path().c_str(),
746
747           alpn_.c_str(),
748
749           std::chrono::system_clock::now(),          // time_now
750           downstream->get_request_start_time(),      // request_start_time
751           std::chrono::high_resolution_clock::now(), // request_end_time
752
753           downstream->get_request_major(), downstream->get_request_minor(),
754           downstream->get_response_http_status(),
755           downstream->get_response_sent_bodylen(), port_.c_str(),
756           get_config()->port, get_config()->pid,
757       });
758 }
759
760 void ClientHandler::write_accesslog(int major, int minor, unsigned int status,
761                                     int64_t body_bytes_sent) {
762   auto time_now = std::chrono::system_clock::now();
763   auto highres_now = std::chrono::high_resolution_clock::now();
764
765   upstream_accesslog(get_config()->accesslog_format,
766                      LogSpec{
767                          nullptr, ipaddr_.c_str(),
768                          "-", // method
769                          "-", // path,
770                          alpn_.c_str(), time_now,
771                          highres_now,  // request_start_time TODO is
772                                        // there a better value?
773                          highres_now,  // request_end_time
774                          major, minor, // major, minor
775                          status, body_bytes_sent, port_.c_str(),
776                          get_config()->port, get_config()->pid,
777                      });
778 }
779
780 ClientHandler::WriteBuf *ClientHandler::get_wb() { return &wb_; }
781
782 ClientHandler::ReadBuf *ClientHandler::get_rb() { return &rb_; }
783
784 void ClientHandler::signal_write() { conn_.wlimit.startw(); }
785
786 RateLimit *ClientHandler::get_rlimit() { return &conn_.rlimit; }
787 RateLimit *ClientHandler::get_wlimit() { return &conn_.wlimit; }
788
789 ev_io *ClientHandler::get_wev() { return &conn_.wev; }
790
791 Worker *ClientHandler::get_worker() const { return worker_; }
792
793 } // namespace shrpx