aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/netbase.cpp60
1 files changed, 59 insertions, 1 deletions
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 3c50174e75..f47b0f3563 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -3,6 +3,18 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifdef HAVE_CONFIG_H
+#include "bitcoin-config.h"
+#endif
+
+#ifdef HAVE_INET_PTON
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_GETADDRINFO_A
+#include <netdb.h>
+#endif
+
#include "netbase.h"
#include "hash.h"
@@ -71,9 +83,30 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
}
}
+#ifdef HAVE_GETADDRINFO_A
+ struct in_addr ipv4_addr;
+#ifdef HAVE_INET_PTON
+ if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
+ vIP.push_back(CNetAddr(ipv4_addr));
+ return true;
+ }
+
+ struct in6_addr ipv6_addr;
+ if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
+ vIP.push_back(CNetAddr(ipv6_addr));
+ return true;
+ }
+#else
+ ipv4_addr.s_addr = inet_addr(pszName);
+ if (ipv4_addr.s_addr != INADDR_NONE) {
+ vIP.push_back(CNetAddr(ipv4_addr));
+ return true;
+ }
+#endif
+#endif
+
struct addrinfo aiHint;
memset(&aiHint, 0, sizeof(struct addrinfo));
-
aiHint.ai_socktype = SOCK_STREAM;
aiHint.ai_protocol = IPPROTO_TCP;
aiHint.ai_family = AF_UNSPEC;
@@ -82,8 +115,33 @@ bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsign
#else
aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
#endif
+
struct addrinfo *aiRes = NULL;
+#ifdef HAVE_GETADDRINFO_A
+ struct gaicb gcb, *query = &gcb;
+ memset(query, 0, sizeof(struct gaicb));
+ gcb.ar_name = pszName;
+ gcb.ar_request = &aiHint;
+ int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
+ if (nErr)
+ return false;
+
+ do {
+ // Should set the timeout limit to a resonable value to avoid
+ // generating unnecessary checking call during the polling loop,
+ // while it can still response to stop request quick enough.
+ // 2 seconds looks fine in our situation.
+ struct timespec ts = { 2, 0 };
+ gai_suspend(&query, 1, &ts);
+ boost::this_thread::interruption_point();
+
+ nErr = gai_error(query);
+ if (0 == nErr)
+ aiRes = query->ar_result;
+ } while (nErr == EAI_INPROGRESS);
+#else
int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
+#endif
if (nErr)
return false;