summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSara Golemon <sara.golemon@mongodb.com>2017-11-17 13:14:09 -0500
committerSara Golemon <sara.golemon@mongodb.com>2018-01-28 10:15:14 -0500
commit08fe3aba7e9a5c8fa54426b68a503a852312d004 (patch)
tree3590959e9d3774f33853277a40ef9f880e598689
parent390557cbb338c9924b142b7a6f8b0808e87b147d (diff)
downloadmongo-08fe3aba7e9a5c8fa54426b68a503a852312d004.tar.gz
SERVER-32631 Deduplicate results in SockAddr::createAll()
(cherry picked from commit 62c9eedec658912f796f5bcdb25f57891e4069ca) (cherry picked from commit 22f10748b1561f55cd053c9a1b3aba00b83adfc9)
-rw-r--r--src/mongo/util/net/sockaddr.cpp52
-rw-r--r--src/mongo/util/net/sockaddr.h2
2 files changed, 33 insertions, 21 deletions
diff --git a/src/mongo/util/net/sockaddr.cpp b/src/mongo/util/net/sockaddr.cpp
index ca00f060769..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)
@@ -324,31 +326,43 @@ bool SockAddr::operator!=(const SockAddr& r) const {
}
bool SockAddr::operator<(const SockAddr& r) const {
- if (getType() < r.getType())
+ // Address family first
+ if (getType() < r.getType()) {
return true;
- else if (getType() > r.getType())
- return false;
-
- if (getPort() < r.getPort())
- return true;
- else if (getPort() > r.getPort())
+ }
+ if (getType() > r.getType()) {
return false;
+ }
+ // Address second
+ int cmp;
switch (getType()) {
- case AF_INET:
- return as<sockaddr_in>().sin_addr.s_addr < r.as<sockaddr_in>().sin_addr.s_addr;
+ 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:
- return memcmp(as<sockaddr_in6>().sin6_addr.s6_addr,
- r.as<sockaddr_in6>().sin6_addr.s6_addr,
- sizeof(in6_addr)) < 0;
+ cmp = memcmp(as<sockaddr_in6>().sin6_addr.s6_addr,
+ r.as<sockaddr_in6>().sin6_addr.s6_addr,
+ sizeof(in6_addr));
+ break;
case AF_UNIX:
- return strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path) < 0;
- case AF_UNSPEC:
- return false;
+ cmp = strcmp(as<sockaddr_un>().sun_path, r.as<sockaddr_un>().sun_path);
+ break;
default:
massert(SOCK_FAMILY_UNKNOWN_ERROR, "unsupported address family", false);
}
- return false;
+ if (cmp < 0) {
+ return true;
+ }
+ if (cmp > 0) {
+ return false;
+ }
+
+ // All else equal, compare port
+ return getPort() < r.getPort();
}
} // namespace mongo
diff --git a/src/mongo/util/net/sockaddr.h b/src/mongo/util/net/sockaddr.h
index 4f24503c945..371e7f8c17c 100644
--- a/src/mongo/util/net/sockaddr.h
+++ b/src/mongo/util/net/sockaddr.h
@@ -136,9 +136,7 @@ struct SockAddr {
bool isAnonymousUNIXSocket() const;
bool operator==(const SockAddr& r) const;
-
bool operator!=(const SockAddr& r) const;
-
bool operator<(const SockAddr& r) const;
const sockaddr* raw() const {