Define SockAddr and use it instead of raw std::pair

pull/538/head
Tatsuhiro Tsujikawa 2016-01-09 17:20:03 +09:00
parent d2d06395d9
commit e899eba76f
4 changed files with 45 additions and 52 deletions

View File

@ -228,11 +228,11 @@ void BtSetup::setup(std::vector<std::unique_ptr<Command>>& commands,
} }
} }
else { else {
std::vector<std::pair<sockaddr_union, socklen_t>> ifAddrs; auto ifAddrs = SocketCore::getInterfaceAddress(lpdInterface, AF_INET,
getInterfaceAddress(ifAddrs, lpdInterface, AF_INET, AI_NUMERICHOST); AI_NUMERICHOST);
for (const auto& i : ifAddrs) { for (const auto& soaddr : ifAddrs) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
if (inetNtop(AF_INET, &i.first.in.sin_addr, host, sizeof(host)) == if (inetNtop(AF_INET, &soaddr.su.in.sin_addr, host, sizeof(host)) ==
0 && 0 &&
receiver->init(host)) { receiver->init(host)) {
initialized = true; initialized = true;

View File

@ -130,11 +130,9 @@ enum TlsState {
int SocketCore::protocolFamily_ = AF_UNSPEC; int SocketCore::protocolFamily_ = AF_UNSPEC;
int SocketCore::ipDscp_ = 0; int SocketCore::ipDscp_ = 0;
std::vector<std::pair<sockaddr_union, socklen_t>> SocketCore::bindAddrs_; std::vector<SockAddr> SocketCore::bindAddrs_;
std::vector<std::vector<std::pair<sockaddr_union, socklen_t>>> std::vector<std::vector<SockAddr>> SocketCore::bindAddrsList_;
SocketCore::bindAddrsList_; std::vector<std::vector<SockAddr>>::iterator SocketCore::bindAddrsListIt_;
std::vector<std::vector<std::pair<sockaddr_union, socklen_t>>>::iterator
SocketCore::bindAddrsListIt_;
int SocketCore::socketRecvBufferSize_ = 0; int SocketCore::socketRecvBufferSize_ = 0;
@ -318,10 +316,10 @@ void SocketCore::bind(const char* addr, uint16_t port, int family, int flags)
std::array<char, NI_MAXHOST> host; std::array<char, NI_MAXHOST> host;
for (const auto& bindAddrs : bindAddrsList_) { for (const auto& bindAddrs : bindAddrsList_) {
for (const auto& a : bindAddrs) { for (const auto& a : bindAddrs) {
if (family != AF_UNSPEC && family != a.first.storage.ss_family) { if (family != AF_UNSPEC && family != a.su.storage.ss_family) {
continue; continue;
} }
auto s = getnameinfo(&a.first.sa, a.second, host.data(), NI_MAXHOST, auto s = getnameinfo(&a.su.sa, a.suLength, host.data(), NI_MAXHOST,
nullptr, 0, NI_NUMERICHOST); nullptr, 0, NI_NUMERICHOST);
if (s) { if (s) {
error = gai_strerror(s); error = gai_strerror(s);
@ -462,11 +460,8 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port,
if (!bindAddrs_.empty()) { if (!bindAddrs_.empty()) {
bool bindSuccess = false; bool bindSuccess = false;
for (std::vector<std::pair<sockaddr_union, socklen_t>>::const_iterator for (const auto& soaddr : bindAddrs_) {
i = bindAddrs_.begin(), if (::bind(fd, &soaddr.su.sa, soaddr.suLength) == -1) {
eoi = bindAddrs_.end();
i != eoi; ++i) {
if (::bind(fd, &(*i).first.sa, (*i).second) == -1) {
errNum = SOCKET_ERRNO; errNum = SOCKET_ERRNO;
error = errorMsg(errNum); error = errorMsg(errNum);
A2_LOG_DEBUG(fmt(EX_SOCKET_BIND, error.c_str())); A2_LOG_DEBUG(fmt(EX_SOCKET_BIND, error.c_str()));
@ -1276,8 +1271,7 @@ bool SocketCore::wantWrite() const { return wantWrite_; }
void SocketCore::bindAddress(const std::string& iface) void SocketCore::bindAddress(const std::string& iface)
{ {
std::vector<std::pair<sockaddr_union, socklen_t>> bindAddrs; auto bindAddrs = getInterfaceAddress(iface, protocolFamily_);
getInterfaceAddress(bindAddrs, iface, protocolFamily_);
if (bindAddrs.empty()) { if (bindAddrs.empty()) {
throw DL_ABORT_EX( throw DL_ABORT_EX(
fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), "not available")); fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), "not available"));
@ -1286,7 +1280,7 @@ void SocketCore::bindAddress(const std::string& iface)
for (const auto& a : bindAddrs_) { for (const auto& a : bindAddrs_) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
int s; int s;
s = getnameinfo(&a.first.sa, a.second, host, NI_MAXHOST, nullptr, 0, s = getnameinfo(&a.su.sa, a.suLength, host, NI_MAXHOST, nullptr, 0,
NI_NUMERICHOST); NI_NUMERICHOST);
if (s == 0) { if (s == 0) {
A2_LOG_DEBUG(fmt("Sockets will bind to %s", host)); A2_LOG_DEBUG(fmt("Sockets will bind to %s", host));
@ -1298,7 +1292,7 @@ void SocketCore::bindAddress(const std::string& iface)
void SocketCore::bindAllAddress(const std::string& ifaces) void SocketCore::bindAllAddress(const std::string& ifaces)
{ {
std::vector<std::vector<std::pair<sockaddr_union, socklen_t>>> bindAddrsList; std::vector<std::vector<SockAddr>> bindAddrsList;
std::vector<std::string> ifaceList; std::vector<std::string> ifaceList;
util::split(ifaces.begin(), ifaces.end(), std::back_inserter(ifaceList), ',', util::split(ifaces.begin(), ifaces.end(), std::back_inserter(ifaceList), ',',
true); true);
@ -1307,8 +1301,7 @@ void SocketCore::bindAllAddress(const std::string& ifaces)
"List of interfaces is empty, one or more interfaces is required"); "List of interfaces is empty, one or more interfaces is required");
} }
for (auto& iface : ifaceList) { for (auto& iface : ifaceList) {
std::vector<std::pair<sockaddr_union, socklen_t>> bindAddrs; auto bindAddrs = getInterfaceAddress(iface, protocolFamily_);
getInterfaceAddress(bindAddrs, iface, protocolFamily_);
if (bindAddrs.empty()) { if (bindAddrs.empty()) {
throw DL_ABORT_EX( throw DL_ABORT_EX(
fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), "not available")); fmt(MSG_INTERFACE_NOT_FOUND, iface.c_str(), "not available"));
@ -1317,7 +1310,7 @@ void SocketCore::bindAllAddress(const std::string& ifaces)
for (const auto& a : bindAddrs) { for (const auto& a : bindAddrs) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
int s; int s;
s = getnameinfo(&a.first.sa, a.second, host, NI_MAXHOST, nullptr, 0, s = getnameinfo(&a.su.sa, a.suLength, host, NI_MAXHOST, nullptr, 0,
NI_NUMERICHOST); NI_NUMERICHOST);
if (s == 0) { if (s == 0) {
A2_LOG_DEBUG(fmt("Sockets will bind to %s", host)); A2_LOG_DEBUG(fmt("Sockets will bind to %s", host));
@ -1336,11 +1329,11 @@ void SocketCore::setSocketRecvBufferSize(int size)
int SocketCore::getSocketRecvBufferSize() { return socketRecvBufferSize_; } int SocketCore::getSocketRecvBufferSize() { return socketRecvBufferSize_; }
void getInterfaceAddress( std::vector<SockAddr> SocketCore::getInterfaceAddress(const std::string& iface,
std::vector<std::pair<sockaddr_union, socklen_t>>& ifAddrs, int family, int aiFlags)
const std::string& iface, int family, int aiFlags)
{ {
A2_LOG_DEBUG(fmt("Finding interface %s", iface.c_str())); A2_LOG_DEBUG(fmt("Finding interface %s", iface.c_str()));
std::vector<SockAddr> ifAddrs;
#ifdef HAVE_GETIFADDRS #ifdef HAVE_GETIFADDRS
// First find interface in interface addresses // First find interface in interface addresses
struct ifaddrs* ifaddr = nullptr; struct ifaddrs* ifaddr = nullptr;
@ -1376,12 +1369,11 @@ void getInterfaceAddress(
continue; continue;
} }
if (strcmp(iface.c_str(), ifa->ifa_name) == 0) { if (strcmp(iface.c_str(), ifa->ifa_name) == 0) {
socklen_t bindAddrLen = SockAddr soaddr;
soaddr.suLength =
iffamily == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); iffamily == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
sockaddr_union bindAddr; memcpy(&soaddr.su, ifa->ifa_addr, soaddr.suLength);
memset(&bindAddr, 0, sizeof(bindAddr)); ifAddrs.push_back(soaddr);
memcpy(&bindAddr.storage, ifa->ifa_addr, bindAddrLen);
ifAddrs.push_back(std::make_pair(bindAddr, bindAddrLen));
} }
} }
} }
@ -1404,10 +1396,10 @@ void getInterfaceAddress(
try { try {
SocketCore socket; SocketCore socket;
socket.bind(rp->ai_addr, rp->ai_addrlen); socket.bind(rp->ai_addr, rp->ai_addrlen);
sockaddr_union bindAddr; SockAddr soaddr;
memset(&bindAddr, 0, sizeof(bindAddr)); memcpy(&soaddr.su, rp->ai_addr, rp->ai_addrlen);
memcpy(&bindAddr.storage, rp->ai_addr, rp->ai_addrlen); soaddr.suLength = rp->ai_addrlen;
ifAddrs.push_back(std::make_pair(bindAddr, rp->ai_addrlen)); ifAddrs.push_back(soaddr);
} }
catch (RecoverableException& e) { catch (RecoverableException& e) {
continue; continue;
@ -1415,6 +1407,8 @@ void getInterfaceAddress(
} }
} }
} }
return ifAddrs;
} }
namespace { namespace {

View File

@ -73,11 +73,9 @@ private:
static int protocolFamily_; static int protocolFamily_;
static int ipDscp_; static int ipDscp_;
static std::vector<std::pair<sockaddr_union, socklen_t>> bindAddrs_; static std::vector<SockAddr> bindAddrs_;
static std::vector<std::vector<std::pair<sockaddr_union, socklen_t>>> static std::vector<std::vector<SockAddr>> bindAddrsList_;
bindAddrsList_; static std::vector<std::vector<SockAddr>>::iterator bindAddrsListIt_;
static std::vector<std::vector<std::pair<sockaddr_union, socklen_t>>>::
iterator bindAddrsListIt_;
static int socketRecvBufferSize_; static int socketRecvBufferSize_;
@ -372,9 +370,14 @@ public:
static void bindAddress(const std::string& iface); static void bindAddress(const std::string& iface);
static void bindAllAddress(const std::string& ifaces); static void bindAllAddress(const std::string& ifaces);
friend void getInterfaceAddress( // Collects IP addresses of given interface iface and stores in
std::vector<std::pair<sockaddr_union, socklen_t>>& ifAddrs, // ifAddres. iface may be specified as a hostname, IP address or
const std::string& iface, int family, int aiFlags); // interface name like eth0. You can limit the family of IP
// addresses to collect using family argument. aiFlags is passed to
// getaddrinfo() as hints.ai_flags. No throw.
static std::vector<SockAddr> getInterfaceAddress(const std::string& iface,
int family = AF_UNSPEC,
int aiFlags = 0);
}; };
// Set default ai_flags. hints.ai_flags is initialized with this // Set default ai_flags. hints.ai_flags is initialized with this
@ -389,15 +392,6 @@ int callGetaddrinfo(struct addrinfo** resPtr, const char* host,
const char* service, int family, int sockType, int flags, const char* service, int family, int sockType, int flags,
int protocol); int protocol);
// Collects IP addresses of given interface iface and stores in
// ifAddres. iface may be specified as a hostname, IP address or
// interface name like eth0. You can limit the family of IP addresses
// to collect using family argument. aiFlags is passed to
// getaddrinfo() as hints.ai_flags. No throw.
void getInterfaceAddress(
std::vector<std::pair<sockaddr_union, socklen_t>>& ifAddrs,
const std::string& iface, int family = AF_UNSPEC, int aiFlags = 0);
// Provides functionality of inet_ntop using getnameinfo. The return // Provides functionality of inet_ntop using getnameinfo. The return
// value is the exact value of getnameinfo returns. You can get error // value is the exact value of getnameinfo returns. You can get error
// message using gai_strerror(3). // message using gai_strerror(3).

View File

@ -115,6 +115,11 @@ union sockaddr_union {
sockaddr_in in; sockaddr_in in;
}; };
struct SockAddr {
sockaddr_union su;
socklen_t suLength;
};
#define A2_DEFAULT_IOV_MAX 128 #define A2_DEFAULT_IOV_MAX 128
#if defined(IOV_MAX) && IOV_MAX < A2_DEFAULT_IOV_MAX #if defined(IOV_MAX) && IOV_MAX < A2_DEFAULT_IOV_MAX