diff options
| author | Andrew Stitcher <astitcher@apache.org> | 2011-08-12 22:32:05 +0000 |
|---|---|---|
| committer | Andrew Stitcher <astitcher@apache.org> | 2011-08-12 22:32:05 +0000 |
| commit | 5e4e74053e0451f5a103820e99eac00992061b4c (patch) | |
| tree | 17e31c3aa347ecc0cf59001f3c82120481f5f6bd /cpp/src/qpid/sys/posix/SocketAddress.cpp | |
| parent | 6035aef61fe726180a918a57a93d66833eaca96a (diff) | |
| download | qpid-python-5e4e74053e0451f5a103820e99eac00992061b4c.tar.gz | |
QPID-3405: IPv6 support for Unix C++ ports:
- On the Listen side we create separate listening sockets for IPv4 and IPv6
making sure to not allow the IPv6 socket to run dual stack. This makes the
reported IPv4 addresses look "normal" and would allow us to turn control
IPv4/IPv6 listening separately.
- On the connect side we make sure to try all the addresses returned by
getaddrinfo() in order until we either find one that connects or have
tried all of them.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1157272 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/sys/posix/SocketAddress.cpp')
| -rw-r--r-- | cpp/src/qpid/sys/posix/SocketAddress.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/cpp/src/qpid/sys/posix/SocketAddress.cpp b/cpp/src/qpid/sys/posix/SocketAddress.cpp index 10f1c8a563..67438c0d89 100644 --- a/cpp/src/qpid/sys/posix/SocketAddress.cpp +++ b/cpp/src/qpid/sys/posix/SocketAddress.cpp @@ -27,8 +27,6 @@ #include <string.h> #include <netdb.h> -#include <algorithm> - namespace qpid { namespace sys { @@ -73,19 +71,38 @@ std::string SocketAddress::asString(bool numeric) const dispName, sizeof(dispName), servName, sizeof(servName), NI_NUMERICHOST | NI_NUMERICSERV) != 0) - throw QPID_POSIX_ERROR(rc); + throw qpid::Exception(QPID_MSG(gai_strerror(rc))); std::string s(dispName); s += ":"; s += servName; return s; } +bool SocketAddress::nextAddress() { + bool r = currentAddrInfo->ai_next != 0; + if (r) + currentAddrInfo = currentAddrInfo->ai_next; + return r; +} + +void SocketAddress::setAddrInfoPort(uint16_t port) { + if (!currentAddrInfo) return; + + ::addrinfo& ai = *currentAddrInfo; + switch (ai.ai_family) { + case AF_INET: ((::sockaddr_in*)ai.ai_addr)->sin_port = htons(port); return; + case AF_INET6:((::sockaddr_in6*)ai.ai_addr)->sin6_port = htons(port); return; + default: throw Exception(QPID_MSG("Unexpected socket type")); + } +} + const ::addrinfo& getAddrInfo(const SocketAddress& sa) { if (!sa.addrInfo) { ::addrinfo hints; ::memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; // Change this to support IPv6 + hints.ai_flags = AI_ADDRCONFIG; // Only use protocols that we have configured interfaces for + hints.ai_family = AF_UNSPEC; // Allow both IPv4 and IPv6 hints.ai_socktype = SOCK_STREAM; const char* node = 0; @@ -99,9 +116,10 @@ const ::addrinfo& getAddrInfo(const SocketAddress& sa) int n = ::getaddrinfo(node, service, &hints, &sa.addrInfo); if (n != 0) throw Exception(QPID_MSG("Cannot resolve " << sa.asString(false) << ": " << ::gai_strerror(n))); + sa.currentAddrInfo = sa.addrInfo; } - return *sa.addrInfo; + return *sa.currentAddrInfo; } }} |
