• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2014 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_accept_handler.h"
26 
27 #ifdef HAVE_UNISTD_H
28 #  include <unistd.h>
29 #endif // HAVE_UNISTD_H
30 
31 #include <cerrno>
32 
33 #include "shrpx_connection_handler.h"
34 #include "shrpx_config.h"
35 #include "shrpx_log.h"
36 #include "util.h"
37 
38 using namespace nghttp2;
39 
40 namespace shrpx {
41 
42 namespace {
acceptcb(struct ev_loop * loop,ev_io * w,int revent)43 void acceptcb(struct ev_loop *loop, ev_io *w, int revent) {
44   auto h = static_cast<AcceptHandler *>(w->data);
45   h->accept_connection();
46 }
47 } // namespace
48 
AcceptHandler(const UpstreamAddr * faddr,ConnectionHandler * h)49 AcceptHandler::AcceptHandler(const UpstreamAddr *faddr, ConnectionHandler *h)
50     : conn_hnr_(h), faddr_(faddr) {
51   ev_io_init(&wev_, acceptcb, faddr_->fd, EV_READ);
52   wev_.data = this;
53   ev_io_start(conn_hnr_->get_loop(), &wev_);
54 }
55 
~AcceptHandler()56 AcceptHandler::~AcceptHandler() {
57   ev_io_stop(conn_hnr_->get_loop(), &wev_);
58   close(faddr_->fd);
59 }
60 
accept_connection()61 void AcceptHandler::accept_connection() {
62   sockaddr_union sockaddr;
63   socklen_t addrlen = sizeof(sockaddr);
64 
65 #ifdef HAVE_ACCEPT4
66   auto cfd =
67       accept4(faddr_->fd, &sockaddr.sa, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC);
68 #else  // !HAVE_ACCEPT4
69   auto cfd = accept(faddr_->fd, &sockaddr.sa, &addrlen);
70 #endif // !HAVE_ACCEPT4
71 
72   if (cfd == -1) {
73     switch (errno) {
74     case EINTR:
75     case ENETDOWN:
76     case EPROTO:
77     case ENOPROTOOPT:
78     case EHOSTDOWN:
79 #ifdef ENONET
80     case ENONET:
81 #endif // ENONET
82     case EHOSTUNREACH:
83     case EOPNOTSUPP:
84     case ENETUNREACH:
85       return;
86     case EMFILE:
87     case ENFILE:
88       LOG(WARN) << "acceptor: running out file descriptor; disable acceptor "
89                    "temporarily";
90       conn_hnr_->sleep_acceptor(get_config()->conn.listener.timeout.sleep);
91       return;
92     default:
93       return;
94     }
95   }
96 
97 #ifndef HAVE_ACCEPT4
98   util::make_socket_nonblocking(cfd);
99   util::make_socket_closeonexec(cfd);
100 #endif // !HAVE_ACCEPT4
101 
102   conn_hnr_->handle_connection(cfd, &sockaddr.sa, addrlen, faddr_);
103 }
104 
enable()105 void AcceptHandler::enable() { ev_io_start(conn_hnr_->get_loop(), &wev_); }
106 
disable()107 void AcceptHandler::disable() { ev_io_stop(conn_hnr_->get_loop(), &wev_); }
108 
get_fd() const109 int AcceptHandler::get_fd() const { return faddr_->fd; }
110 
111 } // namespace shrpx
112