Commit 997f9233 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Support UNIX domain socket in backend connections

parent 49781da8
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h> #include <netdb.h>
#include <signal.h> #include <signal.h>
#include <netinet/in.h> #include <netinet/in.h>
...@@ -821,7 +822,9 @@ Connections: ...@@ -821,7 +822,9 @@ Connections:
backend addresses are accepted by repeating this option. backend addresses are accepted by repeating this option.
HTTP/2 backend does not support multiple backend HTTP/2 backend does not support multiple backend
addresses and the first occurrence of this option is 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: )" << DEFAULT_DOWNSTREAM_HOST << ","
<< DEFAULT_DOWNSTREAM_PORT << R"( << DEFAULT_DOWNSTREAM_PORT << R"(
-f, --frontend=<HOST,PORT> -f, --frontend=<HOST,PORT>
...@@ -1870,23 +1873,35 @@ int main(int argc, char **argv) { ...@@ -1870,23 +1873,35 @@ int main(int argc, char **argv) {
} }
for (auto &addr : mod_config()->downstream_addrs) { for (auto &addr : mod_config()->downstream_addrs) {
auto ipv6 = util::ipv6_numeric_addr(addr.host.get());
std::string hostport;
if (ipv6) { if (util::istartsWith(addr.host.get(), SHRPX_UNIX_PATH_PREFIX)) {
hostport += "["; // 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));
hostport += addr.host.get(); auto path = addr.host.get() + str_size(SHRPX_UNIX_PATH_PREFIX);
auto pathlen = strlen(path);
if (ipv6) { if (pathlen + 1 > sizeof(addr.addr.un.sun_path)) {
hostport += "]"; 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";
hostport += ":"; addr.addr.un.sun_family = AF_UNIX;
hostport += util::utos(addr.port); // copy path including terminal NULL
std::copy_n(path, pathlen + 1, addr.addr.un.sun_path);
addr.addrlen = sizeof(addr.addr.un);
continue;
}
addr.hostport = strcopy(hostport); addr.hostport = strcopy(util::make_hostport(addr.host.get(), addr.port));
if (resolve_hostname( if (resolve_hostname(
&addr.addr, &addr.addrlen, addr.host.get(), addr.port, &addr.addr, &addr.addrlen, addr.host.get(), addr.port,
......
...@@ -521,6 +521,16 @@ int parse_config(const char *opt, const char *optarg) { ...@@ -521,6 +521,16 @@ int parse_config(const char *opt, const char *optarg) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
uint16_t port; uint16_t port;
if (util::strieq(opt, SHRPX_OPT_BACKEND)) { 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) { if (split_host_port(host, sizeof(host), &port, optarg) == -1) {
return -1; return -1;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <cstdio> #include <cstdio>
...@@ -52,6 +53,8 @@ class CertLookupTree; ...@@ -52,6 +53,8 @@ class CertLookupTree;
} // namespace ssl } // namespace ssl
#define SHRPX_UNIX_PATH_PREFIX "unix:"
extern const char SHRPX_OPT_PRIVATE_KEY_FILE[]; extern const char SHRPX_OPT_PRIVATE_KEY_FILE[];
extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[]; extern const char SHRPX_OPT_PRIVATE_KEY_PASSWD_FILE[];
extern const char SHRPX_OPT_CERTIFICATE_FILE[]; extern const char SHRPX_OPT_CERTIFICATE_FILE[];
...@@ -139,6 +142,7 @@ union sockaddr_union { ...@@ -139,6 +142,7 @@ union sockaddr_union {
sockaddr sa; sockaddr sa;
sockaddr_in6 in6; sockaddr_in6 in6;
sockaddr_in in; sockaddr_in in;
sockaddr_un un;
}; };
enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP }; enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP };
......
...@@ -847,7 +847,9 @@ int create_nonblock_socket(int family) { ...@@ -847,7 +847,9 @@ int create_nonblock_socket(int family) {
make_socket_closeonexec(fd); make_socket_closeonexec(fd);
#endif // !SOCK_NONBLOCK #endif // !SOCK_NONBLOCK
make_socket_nodelay(fd); if (family == AF_INET || family == AF_INET6) {
make_socket_nodelay(fd);
}
return fd; return fd;
} }
...@@ -1016,6 +1018,26 @@ std::string dtos(double n) { ...@@ -1016,6 +1018,26 @@ std::string dtos(double n) {
return utos(static_cast<int64_t>(n)) + "." + (f.size() == 1 ? "0" : "") + f; return utos(static_cast<int64_t>(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 util
} // namespace nghttp2 } // namespace nghttp2
...@@ -551,6 +551,11 @@ std::string duration_str(double t); ...@@ -551,6 +551,11 @@ std::string duration_str(double t);
// fractional digits follow. // fractional digits follow.
std::string format_duration(const std::chrono::microseconds &u); 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 util
} // namespace nghttp2 } // namespace nghttp2
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment