nghttpx: Create struct Address which holds struct sockaddr_union and length

This commit is contained in:
Tatsuhiro Tsujikawa 2015-07-27 01:41:10 +09:00
parent efcd43a367
commit cd25c6846e
11 changed files with 55 additions and 63 deletions

View File

@ -117,8 +117,8 @@ const int GRACEFUL_SHUTDOWN_SIGNAL = SIGQUIT;
#define ENV_UNIX_PATH "NGHTTP2_UNIX_PATH" #define ENV_UNIX_PATH "NGHTTP2_UNIX_PATH"
namespace { namespace {
int resolve_hostname(sockaddr_union *addr, size_t *addrlen, int resolve_hostname(Address *addr, const char *hostname, uint16_t port,
const char *hostname, uint16_t port, int family) { int family) {
int rv; int rv;
auto service = util::utos(port); auto service = util::utos(port);
@ -155,8 +155,8 @@ int resolve_hostname(sockaddr_union *addr, size_t *addrlen,
<< " succeeded: " << host; << " succeeded: " << host;
} }
memcpy(addr, res->ai_addr, res->ai_addrlen); memcpy(&addr->su, res->ai_addr, res->ai_addrlen);
*addrlen = res->ai_addrlen; addr->len = res->ai_addrlen;
freeaddrinfo(res); freeaddrinfo(res);
return 0; return 0;
} }
@ -963,7 +963,6 @@ void fill_default_config() {
mod_config()->downstream_http_proxy_userinfo = nullptr; mod_config()->downstream_http_proxy_userinfo = nullptr;
mod_config()->downstream_http_proxy_host = nullptr; mod_config()->downstream_http_proxy_host = nullptr;
mod_config()->downstream_http_proxy_port = 0; mod_config()->downstream_http_proxy_port = 0;
mod_config()->downstream_http_proxy_addrlen = 0;
mod_config()->read_rate = 0; mod_config()->read_rate = 0;
mod_config()->read_burst = 0; mod_config()->read_burst = 0;
mod_config()->write_rate = 0; mod_config()->write_rate = 0;
@ -2347,19 +2346,19 @@ int main(int argc, char **argv) {
auto path = addr.host.get(); auto path = addr.host.get();
auto pathlen = strlen(path); auto pathlen = strlen(path);
if (pathlen + 1 > sizeof(addr.addr.un.sun_path)) { if (pathlen + 1 > sizeof(addr.addr.su.un.sun_path)) {
LOG(FATAL) << "UNIX domain socket path " << path << " is too long > " LOG(FATAL) << "UNIX domain socket path " << path << " is too long > "
<< sizeof(addr.addr.un.sun_path); << sizeof(addr.addr.su.un.sun_path);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
LOG(INFO) << "Use UNIX domain socket path " << path LOG(INFO) << "Use UNIX domain socket path " << path
<< " for backend connection"; << " for backend connection";
addr.addr.un.sun_family = AF_UNIX; addr.addr.su.un.sun_family = AF_UNIX;
// copy path including terminal NULL // copy path including terminal NULL
std::copy_n(path, pathlen + 1, addr.addr.un.sun_path); std::copy_n(path, pathlen + 1, addr.addr.su.un.sun_path);
addr.addrlen = sizeof(addr.addr.un); addr.addr.len = sizeof(addr.addr.su.un);
continue; continue;
} }
@ -2367,7 +2366,7 @@ int main(int argc, char **argv) {
addr.hostport = strcopy(util::make_hostport(addr.host.get(), addr.port)); 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.host.get(), addr.port,
get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6 get_config()->backend_ipv4 ? AF_INET : (get_config()->backend_ipv6
? AF_INET6 ? AF_INET6
: AF_UNSPEC)) == -1) { : AF_UNSPEC)) == -1) {
@ -2381,7 +2380,6 @@ int main(int argc, char **argv) {
LOG(INFO) << "Resolving backend http proxy address"; LOG(INFO) << "Resolving backend http proxy address";
} }
if (resolve_hostname(&mod_config()->downstream_http_proxy_addr, if (resolve_hostname(&mod_config()->downstream_http_proxy_addr,
&mod_config()->downstream_http_proxy_addrlen,
get_config()->downstream_http_proxy_host.get(), get_config()->downstream_http_proxy_host.get(),
get_config()->downstream_http_proxy_port, get_config()->downstream_http_proxy_port,
AF_UNSPEC) == -1) { AF_UNSPEC) == -1) {
@ -2391,7 +2389,6 @@ int main(int argc, char **argv) {
if (get_config()->session_cache_memcached_host) { if (get_config()->session_cache_memcached_host) {
if (resolve_hostname(&mod_config()->session_cache_memcached_addr, if (resolve_hostname(&mod_config()->session_cache_memcached_addr,
&mod_config()->session_cache_memcached_addrlen,
get_config()->session_cache_memcached_host.get(), get_config()->session_cache_memcached_host.get(),
get_config()->session_cache_memcached_port, get_config()->session_cache_memcached_port,
AF_UNSPEC) == -1) { AF_UNSPEC) == -1) {

View File

@ -81,7 +81,7 @@ TicketKeys::~TicketKeys() {
DownstreamAddr::DownstreamAddr(const DownstreamAddr &other) DownstreamAddr::DownstreamAddr(const DownstreamAddr &other)
: addr(other.addr), host(other.host ? strcopy(other.host.get()) : nullptr), : addr(other.addr), host(other.host ? strcopy(other.host.get()) : nullptr),
hostport(other.hostport ? strcopy(other.hostport.get()) : nullptr), hostport(other.hostport ? strcopy(other.hostport.get()) : nullptr),
addrlen(other.addrlen), port(other.port), host_unix(other.host_unix) {} port(other.port), host_unix(other.host_unix) {}
DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) { DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) {
if (this == &other) { if (this == &other) {
@ -91,7 +91,6 @@ DownstreamAddr &DownstreamAddr::operator=(const DownstreamAddr &other) {
addr = other.addr; addr = other.addr;
host = (other.host ? strcopy(other.host.get()) : nullptr); host = (other.host ? strcopy(other.host.get()) : nullptr);
hostport = (other.hostport ? strcopy(other.hostport.get()) : nullptr); hostport = (other.hostport ? strcopy(other.hostport.get()) : nullptr);
addrlen = other.addrlen;
port = other.port; port = other.port;
host_unix = other.host_unix; host_unix = other.host_unix;

View File

@ -184,6 +184,11 @@ union sockaddr_union {
sockaddr_un un; sockaddr_un un;
}; };
struct Address {
size_t len;
union sockaddr_union su;
};
enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP }; enum shrpx_proto { PROTO_HTTP2, PROTO_HTTP };
struct AltSvc { struct AltSvc {
@ -195,18 +200,17 @@ struct AltSvc {
}; };
struct DownstreamAddr { struct DownstreamAddr {
DownstreamAddr() : addr{{0}}, addrlen(0), port(0), host_unix(false) {} DownstreamAddr() : addr{}, port(0), host_unix(false) {}
DownstreamAddr(const DownstreamAddr &other); DownstreamAddr(const DownstreamAddr &other);
DownstreamAddr(DownstreamAddr &&) = default; DownstreamAddr(DownstreamAddr &&) = default;
DownstreamAddr &operator=(const DownstreamAddr &other); DownstreamAddr &operator=(const DownstreamAddr &other);
DownstreamAddr &operator=(DownstreamAddr &&other) = default; DownstreamAddr &operator=(DownstreamAddr &&other) = default;
sockaddr_union addr; Address addr;
// backend address. If |host_unix| is true, this is UNIX domain // backend address. If |host_unix| is true, this is UNIX domain
// socket path. // socket path.
std::unique_ptr<char[]> host; std::unique_ptr<char[]> host;
std::unique_ptr<char[]> hostport; std::unique_ptr<char[]> hostport;
size_t addrlen;
// backend port. 0 if |host_unix| is true. // backend port. 0 if |host_unix| is true.
uint16_t port; uint16_t port;
// true if |host| contains UNIX domain socket path. // true if |host| contains UNIX domain socket path.
@ -254,8 +258,8 @@ struct Config {
// list of supported SSL/TLS protocol strings. // list of supported SSL/TLS protocol strings.
std::vector<std::string> tls_proto_list; std::vector<std::string> tls_proto_list;
// binary form of http proxy host and port // binary form of http proxy host and port
sockaddr_union downstream_http_proxy_addr; Address downstream_http_proxy_addr;
sockaddr_union session_cache_memcached_addr; Address session_cache_memcached_addr;
std::chrono::seconds tls_session_timeout; std::chrono::seconds tls_session_timeout;
ev_tstamp http2_upstream_read_timeout; ev_tstamp http2_upstream_read_timeout;
ev_tstamp upstream_read_timeout; ev_tstamp upstream_read_timeout;
@ -318,9 +322,6 @@ struct Config {
size_t http2_downstream_connections_per_worker; size_t http2_downstream_connections_per_worker;
size_t downstream_connections_per_host; size_t downstream_connections_per_host;
size_t downstream_connections_per_frontend; size_t downstream_connections_per_frontend;
// actual size of downstream_http_proxy_addr
size_t downstream_http_proxy_addrlen;
size_t session_cache_memcached_addrlen;
size_t read_rate; size_t read_rate;
size_t read_burst; size_t read_burst;
size_t write_rate; size_t write_rate;

View File

@ -276,15 +276,15 @@ int Http2Session::initiate_connection() {
} }
conn_.fd = util::create_nonblock_socket( conn_.fd = util::create_nonblock_socket(
get_config()->downstream_http_proxy_addr.storage.ss_family); get_config()->downstream_http_proxy_addr.su.storage.ss_family);
if (conn_.fd == -1) { if (conn_.fd == -1) {
connect_blocker_->on_failure(); connect_blocker_->on_failure();
return -1; return -1;
} }
rv = connect(conn_.fd, &get_config()->downstream_http_proxy_addr.sa, rv = connect(conn_.fd, &get_config()->downstream_http_proxy_addr.su.sa,
get_config()->downstream_http_proxy_addrlen); get_config()->downstream_http_proxy_addr.len);
if (rv != 0 && errno != EINPROGRESS) { if (rv != 0 && errno != EINPROGRESS) {
SSLOG(ERROR, this) << "Failed to connect to the proxy " SSLOG(ERROR, this) << "Failed to connect to the proxy "
<< get_config()->downstream_http_proxy_host.get() << get_config()->downstream_http_proxy_host.get()
@ -350,7 +350,7 @@ int Http2Session::initiate_connection() {
assert(conn_.fd == -1); assert(conn_.fd == -1);
conn_.fd = util::create_nonblock_socket( conn_.fd = util::create_nonblock_socket(
downstream_addr.addr.storage.ss_family); downstream_addr.addr.su.storage.ss_family);
if (conn_.fd == -1) { if (conn_.fd == -1) {
connect_blocker_->on_failure(); connect_blocker_->on_failure();
return -1; return -1;
@ -358,8 +358,8 @@ int Http2Session::initiate_connection() {
rv = connect(conn_.fd, rv = connect(conn_.fd,
// TODO maybe not thread-safe? // TODO maybe not thread-safe?
const_cast<sockaddr *>(&downstream_addr.addr.sa), const_cast<sockaddr *>(&downstream_addr.addr.su.sa),
downstream_addr.addrlen); downstream_addr.addr.len);
if (rv != 0 && errno != EINPROGRESS) { if (rv != 0 && errno != EINPROGRESS) {
connect_blocker_->on_failure(); connect_blocker_->on_failure();
return -1; return -1;
@ -376,15 +376,16 @@ int Http2Session::initiate_connection() {
assert(conn_.fd == -1); assert(conn_.fd == -1);
conn_.fd = util::create_nonblock_socket( conn_.fd = util::create_nonblock_socket(
downstream_addr.addr.storage.ss_family); downstream_addr.addr.su.storage.ss_family);
if (conn_.fd == -1) { if (conn_.fd == -1) {
connect_blocker_->on_failure(); connect_blocker_->on_failure();
return -1; return -1;
} }
rv = connect(conn_.fd, const_cast<sockaddr *>(&downstream_addr.addr.sa), rv = connect(conn_.fd,
downstream_addr.addrlen); const_cast<sockaddr *>(&downstream_addr.addr.su.sa),
downstream_addr.addr.len);
if (rv != 0 && errno != EINPROGRESS) { if (rv != 0 && errno != EINPROGRESS) {
connect_blocker_->on_failure(); connect_blocker_->on_failure();
return -1; return -1;

View File

@ -147,7 +147,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
next_downstream = 0; next_downstream = 0;
} }
conn_.fd = util::create_nonblock_socket(addr.addr.storage.ss_family); conn_.fd = util::create_nonblock_socket(addr.addr.su.storage.ss_family);
if (conn_.fd == -1) { if (conn_.fd == -1) {
auto error = errno; auto error = errno;
@ -159,7 +159,7 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
} }
int rv; int rv;
rv = connect(conn_.fd, &addr.addr.sa, addr.addrlen); rv = connect(conn_.fd, &addr.addr.su.sa, addr.addr.len);
if (rv != 0 && errno != EINPROGRESS) { if (rv != 0 && errno != EINPROGRESS) {
auto error = errno; auto error = errno;
DCLOG(WARN, this) << "connect() failed; errno=" << error; DCLOG(WARN, this) << "connect() failed; errno=" << error;

View File

@ -85,12 +85,11 @@ void connectcb(struct ev_loop *loop, ev_io *w, int revents) {
constexpr ev_tstamp write_timeout = 10.; constexpr ev_tstamp write_timeout = 10.;
constexpr ev_tstamp read_timeout = 10.; constexpr ev_tstamp read_timeout = 10.;
MemcachedConnection::MemcachedConnection(const sockaddr_union *addr, MemcachedConnection::MemcachedConnection(const Address *addr,
size_t addrlen, struct ev_loop *loop) struct ev_loop *loop)
: conn_(loop, -1, nullptr, write_timeout, read_timeout, 0, 0, 0, 0, : conn_(loop, -1, nullptr, write_timeout, read_timeout, 0, 0, 0, 0,
connectcb, readcb, timeoutcb, this), connectcb, readcb, timeoutcb, this),
parse_state_{}, addr_(addr), addrlen_(addrlen), sendsum_(0), parse_state_{}, addr_(addr), sendsum_(0), connected_(false) {}
connected_(false) {}
MemcachedConnection::~MemcachedConnection() { disconnect(); } MemcachedConnection::~MemcachedConnection() { disconnect(); }
@ -125,7 +124,7 @@ void MemcachedConnection::disconnect() {
int MemcachedConnection::initiate_connection() { int MemcachedConnection::initiate_connection() {
assert(conn_.fd == -1); assert(conn_.fd == -1);
conn_.fd = util::create_nonblock_socket(addr_->storage.ss_family); conn_.fd = util::create_nonblock_socket(addr_->su.storage.ss_family);
if (conn_.fd == -1) { if (conn_.fd == -1) {
auto error = errno; auto error = errno;
@ -135,7 +134,7 @@ int MemcachedConnection::initiate_connection() {
} }
int rv; int rv;
rv = connect(conn_.fd, &addr_->sa, addrlen_); rv = connect(conn_.fd, &addr_->su.sa, addr_->len);
if (rv != 0 && errno != EINPROGRESS) { if (rv != 0 && errno != EINPROGRESS) {
auto error = errno; auto error = errno;
MCLOG(WARN, this) << "connect() failed; errno=" << error; MCLOG(WARN, this) << "connect() failed; errno=" << error;

View File

@ -40,7 +40,7 @@ using namespace nghttp2;
namespace shrpx { namespace shrpx {
struct MemcachedRequest; struct MemcachedRequest;
union sockaddr_union; struct Address;
enum { enum {
MEMCACHED_PARSE_HEADER24, MEMCACHED_PARSE_HEADER24,
@ -93,8 +93,7 @@ constexpr uint8_t MEMCACHED_RES_MAGIC = 0x81;
// https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol // https://code.google.com/p/memcached/wiki/MemcacheBinaryProtocol
class MemcachedConnection { class MemcachedConnection {
public: public:
MemcachedConnection(const sockaddr_union *addr, size_t addrlen, MemcachedConnection(const Address *addr, struct ev_loop *loop);
struct ev_loop *loop);
~MemcachedConnection(); ~MemcachedConnection();
void disconnect(); void disconnect();
@ -118,8 +117,7 @@ private:
std::deque<std::unique_ptr<MemcachedRequest>> sendq_; std::deque<std::unique_ptr<MemcachedRequest>> sendq_;
std::deque<MemcachedSendbuf> sendbufv_; std::deque<MemcachedSendbuf> sendbufv_;
MemcachedParseState parse_state_; MemcachedParseState parse_state_;
const sockaddr_union *addr_; const Address *addr_;
size_t addrlen_;
// Sum of the bytes to be transmitted in sendbufv_. // Sum of the bytes to be transmitted in sendbufv_.
size_t sendsum_; size_t sendsum_;
bool connected_; bool connected_;

View File

@ -30,10 +30,9 @@
namespace shrpx { namespace shrpx {
MemcachedDispatcher::MemcachedDispatcher(const sockaddr_union *addr, MemcachedDispatcher::MemcachedDispatcher(const Address *addr,
size_t addrlen, struct ev_loop *loop) struct ev_loop *loop)
: loop_(loop), : loop_(loop), mconn_(make_unique<MemcachedConnection>(addr, loop_)) {}
mconn_(make_unique<MemcachedConnection>(addr, addrlen, loop_)) {}
MemcachedDispatcher::~MemcachedDispatcher() {} MemcachedDispatcher::~MemcachedDispatcher() {}

View File

@ -35,12 +35,11 @@ namespace shrpx {
struct MemcachedRequest; struct MemcachedRequest;
class MemcachedConnection; class MemcachedConnection;
union sockaddr_union; struct Address;
class MemcachedDispatcher { class MemcachedDispatcher {
public: public:
MemcachedDispatcher(const sockaddr_union *addr, size_t addrlen, MemcachedDispatcher(const Address *addr, struct ev_loop *loop);
struct ev_loop *loop);
~MemcachedDispatcher(); ~MemcachedDispatcher();
int add_request(std::unique_ptr<MemcachedRequest> req); int add_request(std::unique_ptr<MemcachedRequest> req);

View File

@ -768,8 +768,8 @@ bool tls_hostname_match(const char *pattern, const char *hostname) {
} // namespace } // namespace
namespace { namespace {
int verify_hostname(const char *hostname, const sockaddr_union *su, int verify_hostname(const char *hostname, const Address *addr,
size_t salen, const std::vector<std::string> &dns_names, const std::vector<std::string> &dns_names,
const std::vector<std::string> &ip_addrs, const std::vector<std::string> &ip_addrs,
const std::string &common_name) { const std::string &common_name) {
if (util::numeric_host(hostname)) { if (util::numeric_host(hostname)) {
@ -777,19 +777,19 @@ int verify_hostname(const char *hostname, const sockaddr_union *su,
return util::strieq(common_name.c_str(), hostname) ? 0 : -1; return util::strieq(common_name.c_str(), hostname) ? 0 : -1;
} }
const void *saddr; const void *saddr;
switch (su->storage.ss_family) { switch (addr->su.storage.ss_family) {
case AF_INET: case AF_INET:
saddr = &su->in.sin_addr; saddr = &addr->su.in.sin_addr;
break; break;
case AF_INET6: case AF_INET6:
saddr = &su->in6.sin6_addr; saddr = &addr->su.in6.sin6_addr;
break; break;
default: default:
return -1; return -1;
} }
for (size_t i = 0; i < ip_addrs.size(); ++i) { for (size_t i = 0; i < ip_addrs.size(); ++i) {
if (salen == ip_addrs[i].size() && if (addr->len == ip_addrs[i].size() &&
memcmp(saddr, ip_addrs[i].c_str(), salen) == 0) { memcmp(saddr, ip_addrs[i].c_str(), addr->len) == 0) {
return 0; return 0;
} }
} }
@ -884,8 +884,8 @@ int check_cert(SSL *ssl, const DownstreamAddr *addr) {
std::vector<std::string> dns_names; std::vector<std::string> dns_names;
std::vector<std::string> ip_addrs; std::vector<std::string> ip_addrs;
get_altnames(cert, dns_names, ip_addrs, common_name); get_altnames(cert, dns_names, ip_addrs, common_name);
if (verify_hostname(addr->host.get(), &addr->addr, addr->addrlen, dns_names, if (verify_hostname(addr->host.get(), &addr->addr, dns_names, ip_addrs,
ip_addrs, common_name) != 0) { common_name) != 0) {
LOG(ERROR) << "Certificate verification failed: hostname does not match"; LOG(ERROR) << "Certificate verification failed: hostname does not match";
return -1; return -1;
} }

View File

@ -78,8 +78,7 @@ Worker::Worker(struct ev_loop *loop, SSL_CTX *sv_ssl_ctx, SSL_CTX *cl_ssl_ctx,
if (get_config()->session_cache_memcached_host) { if (get_config()->session_cache_memcached_host) {
session_cache_memcached_dispatcher_ = make_unique<MemcachedDispatcher>( session_cache_memcached_dispatcher_ = make_unique<MemcachedDispatcher>(
&get_config()->session_cache_memcached_addr, &get_config()->session_cache_memcached_addr, loop);
get_config()->session_cache_memcached_addrlen, loop);
} }
if (get_config()->downstream_proto == PROTO_HTTP2) { if (get_config()->downstream_proto == PROTO_HTTP2) {