diff --git a/src/shrpx.cc b/src/shrpx.cc index 4eee9795..f9d9c3bf 100644 --- a/src/shrpx.cc +++ b/src/shrpx.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -821,7 +822,9 @@ Connections: backend addresses are accepted by repeating this option. HTTP/2 backend does not support multiple backend addresses and the first occurrence of this option is - used. + used. UNIX domain socket can be specified by prefixing + path name with "unix:" (e.g., + -bunix:/var/run/backend.sock) Default: )" << DEFAULT_DOWNSTREAM_HOST << "," << DEFAULT_DOWNSTREAM_PORT << R"( -f, --frontend= @@ -1870,23 +1873,35 @@ int main(int argc, char **argv) { } for (auto &addr : mod_config()->downstream_addrs) { - auto ipv6 = util::ipv6_numeric_addr(addr.host.get()); - std::string hostport; - if (ipv6) { - hostport += "["; + if (util::istartsWith(addr.host.get(), SHRPX_UNIX_PATH_PREFIX)) { + // for AF_UNIX socket, we use "localhost" as host for backend + // hostport. This is used as Host header field to backend and + // not going to be passed to any syscalls. + addr.hostport = + strcopy(util::make_hostport("localhost", get_config()->port)); + + auto path = addr.host.get() + str_size(SHRPX_UNIX_PATH_PREFIX); + auto pathlen = strlen(path); + + if (pathlen + 1 > sizeof(addr.addr.un.sun_path)) { + LOG(FATAL) << "path unix domain socket is bound to is too long > " + << sizeof(addr.addr.un.sun_path); + exit(EXIT_FAILURE); + } + + LOG(INFO) << "Use UNIX domain socket path " << path + << " for backend connection"; + + addr.addr.un.sun_family = AF_UNIX; + // copy path including terminal NULL + std::copy_n(path, pathlen + 1, addr.addr.un.sun_path); + addr.addrlen = sizeof(addr.addr.un); + + continue; } - hostport += addr.host.get(); - - if (ipv6) { - hostport += "]"; - } - - hostport += ":"; - hostport += util::utos(addr.port); - - addr.hostport = strcopy(hostport); + addr.hostport = strcopy(util::make_hostport(addr.host.get(), addr.port)); if (resolve_hostname( &addr.addr, &addr.addrlen, addr.host.get(), addr.port, diff --git a/src/shrpx_config.cc b/src/shrpx_config.cc index 96775a03..5e87b390 100644 --- a/src/shrpx_config.cc +++ b/src/shrpx_config.cc @@ -521,6 +521,16 @@ int parse_config(const char *opt, const char *optarg) { char host[NI_MAXHOST]; uint16_t port; if (util::strieq(opt, SHRPX_OPT_BACKEND)) { + if (util::istartsWith(optarg, SHRPX_UNIX_PATH_PREFIX)) { + DownstreamAddr addr; + addr.host = strcopy(optarg); + addr.port = 0; + + mod_config()->downstream_addrs.push_back(std::move(addr)); + + return 0; + } + if (split_host_port(host, sizeof(host), &port, optarg) == -1) { return -1; } diff --git a/src/shrpx_config.h b/src/shrpx_config.h index e2c75514..5bb05861 100644 --- a/src/shrpx_config.h +++ b/src/shrpx_config.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +53,8 @@ class CertLookupTree; } // namespace ssl +#define SHRPX_UNIX_PATH_PREFIX "unix:" + extern const char SHRPX_OPT_PRIVATE_KEY_FILE[]; extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[]; extern const char SHRPX_OPT_CERTIFICATE_FILE[]; @@ -139,6 +142,7 @@ union sockaddr_union { sockaddr sa; sockaddr_in6 in6; sockaddr_in in; + sockaddr_un un; }; enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP }; diff --git a/src/util.cc b/src/util.cc index 72301216..465ea411 100644 --- a/src/util.cc +++ b/src/util.cc @@ -847,7 +847,9 @@ int create_nonblock_socket(int family) { make_socket_closeonexec(fd); #endif // !SOCK_NONBLOCK - make_socket_nodelay(fd); + if (family == AF_INET || family == AF_INET6) { + make_socket_nodelay(fd); + } return fd; } @@ -1016,6 +1018,26 @@ std::string dtos(double n) { return utos(static_cast(n)) + "." + (f.size() == 1 ? "0" : "") + f; } +std::string make_hostport(const char *host, uint16_t port) { + auto ipv6 = ipv6_numeric_addr(host); + std::string hostport; + + if (ipv6) { + hostport += "["; + } + + hostport += host; + + if (ipv6) { + hostport += "]"; + } + + hostport += ":"; + hostport += utos(port); + + return hostport; +} + } // namespace util } // namespace nghttp2 diff --git a/src/util.h b/src/util.h index c396a7c3..1345ba18 100644 --- a/src/util.h +++ b/src/util.h @@ -551,6 +551,11 @@ std::string duration_str(double t); // fractional digits follow. std::string format_duration(const std::chrono::microseconds &u); +// Creates "host:port" string using given |host| and |port|. If +// |host| is numeric IPv6 address (e.g., ::1), it is enclosed by "[" +// and "]". +std::string make_hostport(const char *host, uint16_t port); + } // namespace util } // namespace nghttp2