nghttpx: Support UNIX domain socket in backend connections

This commit is contained in:
Tatsuhiro Tsujikawa 2015-02-22 12:27:51 +09:00
parent 49781da8f0
commit 997f9233bc
5 changed files with 72 additions and 16 deletions

View File

@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <signal.h>
#include <netinet/in.h>
@ -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=<HOST,PORT>
@ -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);
}
hostport += addr.host.get();
LOG(INFO) << "Use UNIX domain socket path " << path
<< " for backend connection";
if (ipv6) {
hostport += "]";
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 += ":";
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,

View File

@ -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;
}

View File

@ -30,6 +30,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
@ -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 };

View File

@ -847,7 +847,9 @@ int create_nonblock_socket(int family) {
make_socket_closeonexec(fd);
#endif // !SOCK_NONBLOCK
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<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 nghttp2

View File

@ -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