diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2018-01-10 16:54:33 -0500 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2018-01-12 16:26:19 -0500 |
commit | 62c9eedec658912f796f5bcdb25f57891e4069ca (patch) | |
tree | a8906ac1bbab22cc348eab5ad4241f2c295960f5 /src/mongo/util/net/sockaddr.cpp | |
parent | ca539d91d8da0080b348196b07c9d4e464d4e40e (diff) | |
download | mongo-62c9eedec658912f796f5bcdb25f57891e4069ca.tar.gz |
SERVER-32631 Deduplicate results in SockAddr::createAll()
Diffstat (limited to 'src/mongo/util/net/sockaddr.cpp')
-rw-r--r-- | src/mongo/util/net/sockaddr.cpp | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/mongo/util/net/sockaddr.cpp b/src/mongo/util/net/sockaddr.cpp index 6b441390d1c..137b1d1639b 100644 --- a/src/mongo/util/net/sockaddr.cpp +++ b/src/mongo/util/net/sockaddr.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" #include <iterator> +#include <set> +#include <vector> #include "mongo/util/net/sockaddr.h" @@ -177,7 +179,7 @@ std::vector<SockAddr> SockAddr::createAll(StringData target, int port, sa_family return {}; } - std::vector<SockAddr> ret; + std::set<SockAddr> ret; struct sockaddr_storage storage; memset(&storage, 0, sizeof(storage)); for (const auto* addrs = addrErr.second.get(); addrs; addrs = addrs->ai_next) { @@ -186,9 +188,9 @@ std::vector<SockAddr> SockAddr::createAll(StringData target, int port, sa_family // SockAddr constructor below can copy the entire buffer // without over-running addrinfo's storage memcpy(&storage, addrs->ai_addr, addrs->ai_addrlen); - ret.emplace_back(storage, addrs->ai_addrlen); + ret.emplace(storage, addrs->ai_addrlen); } - return ret; + return std::vector<SockAddr>(ret.begin(), ret.end()); } SockAddr::SockAddr(struct sockaddr_storage& other, socklen_t size) @@ -323,4 +325,44 @@ bool SockAddr::operator!=(const SockAddr& r) const { return !(*this == r); } +bool SockAddr::operator<(const SockAddr& r) const { + // Address family first + if (getType() < r.getType()) { + return true; + } + if (getType() > r.getType()) { + return false; + } + + // Address second + int cmp; + switch (getType()) { + case AF_INET: { + const auto laddr = ntohl(as<sockaddr_in>().sin_addr.s_addr); + const auto raddr = ntohl(r.as<sockaddr_in>().sin_addr.s_addr); + cmp = (laddr < raddr) ? -1 : (laddr > raddr) ? 1 : 0; + break; + } + case AF_INET6: + cmp = memcmp(as<sockaddr_in6>().sin6_addr.s6_addr, + r.as<sockaddr_in6>().sin6_addr.s6_addr, + sizeof(in6_addr)); + break; + case AF_UNIX: + cmp = strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path); + break; + default: + massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false); + } + if (cmp < 0) { + return true; + } + if (cmp > 0) { + return false; + } + + // All else equal, compare port + return getPort() < r.getPort(); +} + } // namespace mongo |