]> Git Repo - VerusCoin.git/blob - src/netbase.cpp
Remove references to X11 licence
[VerusCoin.git] / src / netbase.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #ifdef HAVE_CONFIG_H
7 #include "config/bitcoin-config.h"
8 #endif
9
10 #include "netbase.h"
11
12 #include "hash.h"
13 #include "sync.h"
14 #include "uint256.h"
15 #include "util.h"
16 #include "utilstrencodings.h"
17
18 #ifdef HAVE_GETADDRINFO_A
19 #include <netdb.h>
20 #endif
21
22 #ifndef WIN32
23 #if HAVE_INET_PTON
24 #include <arpa/inet.h>
25 #endif
26 #include <fcntl.h>
27 #endif
28
29 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
30 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
31 #include <boost/thread.hpp>
32
33 #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
34 #define MSG_NOSIGNAL 0
35 #endif
36
37 using namespace std;
38
39 // Settings
40 static proxyType proxyInfo[NET_MAX];
41 static CService nameProxy;
42 static CCriticalSection cs_proxyInfos;
43 int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
44 bool fNameLookup = false;
45
46 static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
47
48 // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
49 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
50
51 enum Network ParseNetwork(std::string net) {
52     boost::to_lower(net);
53     if (net == "ipv4") return NET_IPV4;
54     if (net == "ipv6") return NET_IPV6;
55     if (net == "tor" || net == "onion")  return NET_TOR;
56     return NET_UNROUTABLE;
57 }
58
59 std::string GetNetworkName(enum Network net) {
60     switch(net)
61     {
62     case NET_IPV4: return "ipv4";
63     case NET_IPV6: return "ipv6";
64     case NET_TOR: return "onion";
65     default: return "";
66     }
67 }
68
69 void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
70     size_t colon = in.find_last_of(':');
71     // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
72     bool fHaveColon = colon != in.npos;
73     bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe
74     bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
75     if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
76         int32_t n;
77         if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
78             in = in.substr(0, colon);
79             portOut = n;
80         }
81     }
82     if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
83         hostOut = in.substr(1, in.size()-2);
84     else
85         hostOut = in;
86 }
87
88 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
89 {
90     vIP.clear();
91
92     {
93         CNetAddr addr;
94         if (addr.SetSpecial(std::string(pszName))) {
95             vIP.push_back(addr);
96             return true;
97         }
98     }
99
100 #ifdef HAVE_GETADDRINFO_A
101     struct in_addr ipv4_addr;
102 #ifdef HAVE_INET_PTON
103     if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
104         vIP.push_back(CNetAddr(ipv4_addr));
105         return true;
106     }
107
108     struct in6_addr ipv6_addr;
109     if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
110         vIP.push_back(CNetAddr(ipv6_addr));
111         return true;
112     }
113 #else
114     ipv4_addr.s_addr = inet_addr(pszName);
115     if (ipv4_addr.s_addr != INADDR_NONE) {
116         vIP.push_back(CNetAddr(ipv4_addr));
117         return true;
118     }
119 #endif
120 #endif
121
122     struct addrinfo aiHint;
123     memset(&aiHint, 0, sizeof(struct addrinfo));
124     aiHint.ai_socktype = SOCK_STREAM;
125     aiHint.ai_protocol = IPPROTO_TCP;
126     aiHint.ai_family = AF_UNSPEC;
127 #ifdef WIN32
128     aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
129 #else
130     aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
131 #endif
132
133     struct addrinfo *aiRes = NULL;
134 #ifdef HAVE_GETADDRINFO_A
135     struct gaicb gcb, *query = &gcb;
136     memset(query, 0, sizeof(struct gaicb));
137     gcb.ar_name = pszName;
138     gcb.ar_request = &aiHint;
139     int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
140     if (nErr)
141         return false;
142
143     do {
144         // Should set the timeout limit to a resonable value to avoid
145         // generating unnecessary checking call during the polling loop,
146         // while it can still response to stop request quick enough.
147         // 2 seconds looks fine in our situation.
148         struct timespec ts = { 2, 0 };
149         gai_suspend(&query, 1, &ts);
150         boost::this_thread::interruption_point();
151
152         nErr = gai_error(query);
153         if (0 == nErr)
154             aiRes = query->ar_result;
155     } while (nErr == EAI_INPROGRESS);
156 #else
157     int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
158 #endif
159     if (nErr)
160         return false;
161
162     struct addrinfo *aiTrav = aiRes;
163     while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
164     {
165         if (aiTrav->ai_family == AF_INET)
166         {
167             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
168             vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
169         }
170
171         if (aiTrav->ai_family == AF_INET6)
172         {
173             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
174             vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
175         }
176
177         aiTrav = aiTrav->ai_next;
178     }
179
180     freeaddrinfo(aiRes);
181
182     return (vIP.size() > 0);
183 }
184
185 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
186 {
187     std::string strHost(pszName);
188     if (strHost.empty())
189         return false;
190     if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
191     {
192         strHost = strHost.substr(1, strHost.size() - 2);
193     }
194
195     return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
196 }
197
198 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
199 {
200     if (pszName[0] == 0)
201         return false;
202     int port = portDefault;
203     std::string hostname = "";
204     SplitHostPort(std::string(pszName), port, hostname);
205
206     std::vector<CNetAddr> vIP;
207     bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
208     if (!fRet)
209         return false;
210     vAddr.resize(vIP.size());
211     for (unsigned int i = 0; i < vIP.size(); i++)
212         vAddr[i] = CService(vIP[i], port);
213     return true;
214 }
215
216 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
217 {
218     std::vector<CService> vService;
219     bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
220     if (!fRet)
221         return false;
222     addr = vService[0];
223     return true;
224 }
225
226 bool LookupNumeric(const char *pszName, CService& addr, int portDefault)
227 {
228     return Lookup(pszName, addr, portDefault, false);
229 }
230
231 /**
232  * Convert milliseconds to a struct timeval for select.
233  */
234 struct timeval static MillisToTimeval(int64_t nTimeout)
235 {
236     struct timeval timeout;
237     timeout.tv_sec  = nTimeout / 1000;
238     timeout.tv_usec = (nTimeout % 1000) * 1000;
239     return timeout;
240 }
241
242 /**
243  * Read bytes from socket. This will either read the full number of bytes requested
244  * or return False on error or timeout.
245  * This function can be interrupted by boost thread interrupt.
246  *
247  * @param data Buffer to receive into
248  * @param len  Length of data to receive
249  * @param timeout  Timeout in milliseconds for receive operation
250  *
251  * @note This function requires that hSocket is in non-blocking mode.
252  */
253 bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
254 {
255     int64_t curTime = GetTimeMillis();
256     int64_t endTime = curTime + timeout;
257     // Maximum time to wait in one select call. It will take up until this time (in millis)
258     // to break off in case of an interruption.
259     const int64_t maxWait = 1000;
260     while (len > 0 && curTime < endTime) {
261         ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first
262         if (ret > 0) {
263             len -= ret;
264             data += ret;
265         } else if (ret == 0) { // Unexpected disconnection
266             return false;
267         } else { // Other error or blocking
268             int nErr = WSAGetLastError();
269             if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
270                 struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
271                 fd_set fdset;
272                 FD_ZERO(&fdset);
273                 FD_SET(hSocket, &fdset);
274                 int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval);
275                 if (nRet == SOCKET_ERROR) {
276                     return false;
277                 }
278             } else {
279                 return false;
280             }
281         }
282         boost::this_thread::interruption_point();
283         curTime = GetTimeMillis();
284     }
285     return len == 0;
286 }
287
288 bool static Socks5(string strDest, int port, SOCKET& hSocket)
289 {
290     LogPrintf("SOCKS5 connecting %s\n", strDest);
291     if (strDest.size() > 255)
292     {
293         CloseSocket(hSocket);
294         return error("Hostname too long");
295     }
296     char pszSocks5Init[] = "\5\1\0";
297     ssize_t nSize = sizeof(pszSocks5Init) - 1;
298
299     ssize_t ret = send(hSocket, pszSocks5Init, nSize, MSG_NOSIGNAL);
300     if (ret != nSize)
301     {
302         CloseSocket(hSocket);
303         return error("Error sending to proxy");
304     }
305     char pchRet1[2];
306     if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket))
307     {
308         CloseSocket(hSocket);
309         return error("Error reading proxy response");
310     }
311     if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00)
312     {
313         CloseSocket(hSocket);
314         return error("Proxy failed to initialize");
315     }
316     string strSocks5("\5\1");
317     strSocks5 += '\000'; strSocks5 += '\003';
318     strSocks5 += static_cast<char>(std::min((int)strDest.size(), 255));
319     strSocks5 += strDest;
320     strSocks5 += static_cast<char>((port >> 8) & 0xFF);
321     strSocks5 += static_cast<char>((port >> 0) & 0xFF);
322     ret = send(hSocket, strSocks5.data(), strSocks5.size(), MSG_NOSIGNAL);
323     if (ret != (ssize_t)strSocks5.size())
324     {
325         CloseSocket(hSocket);
326         return error("Error sending to proxy");
327     }
328     char pchRet2[4];
329     if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket))
330     {
331         CloseSocket(hSocket);
332         return error("Error reading proxy response");
333     }
334     if (pchRet2[0] != 0x05)
335     {
336         CloseSocket(hSocket);
337         return error("Proxy failed to accept request");
338     }
339     if (pchRet2[1] != 0x00)
340     {
341         CloseSocket(hSocket);
342         switch (pchRet2[1])
343         {
344             case 0x01: return error("Proxy error: general failure");
345             case 0x02: return error("Proxy error: connection not allowed");
346             case 0x03: return error("Proxy error: network unreachable");
347             case 0x04: return error("Proxy error: host unreachable");
348             case 0x05: return error("Proxy error: connection refused");
349             case 0x06: return error("Proxy error: TTL expired");
350             case 0x07: return error("Proxy error: protocol error");
351             case 0x08: return error("Proxy error: address type not supported");
352             default:   return error("Proxy error: unknown");
353         }
354     }
355     if (pchRet2[2] != 0x00)
356     {
357         CloseSocket(hSocket);
358         return error("Error: malformed proxy response");
359     }
360     char pchRet3[256];
361     switch (pchRet2[3])
362     {
363         case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
364         case 0x04: ret = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
365         case 0x03:
366         {
367             ret = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
368             if (!ret) {
369                 CloseSocket(hSocket);
370                 return error("Error reading from proxy");
371             }
372             int nRecv = pchRet3[0];
373             ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
374             break;
375         }
376         default: CloseSocket(hSocket); return error("Error: malformed proxy response");
377     }
378     if (!ret)
379     {
380         CloseSocket(hSocket);
381         return error("Error reading from proxy");
382     }
383     if (!InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket))
384     {
385         CloseSocket(hSocket);
386         return error("Error reading from proxy");
387     }
388     LogPrintf("SOCKS5 connected %s\n", strDest);
389     return true;
390 }
391
392 bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
393 {
394     hSocketRet = INVALID_SOCKET;
395
396     struct sockaddr_storage sockaddr;
397     socklen_t len = sizeof(sockaddr);
398     if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
399         LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
400         return false;
401     }
402
403     SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
404     if (hSocket == INVALID_SOCKET)
405         return false;
406
407 #ifdef SO_NOSIGPIPE
408     int set = 1;
409     // Different way of disabling SIGPIPE on BSD
410     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
411 #endif
412
413     // Set to non-blocking
414     if (!SetSocketNonBlocking(hSocket, true))
415         return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
416
417     if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
418     {
419         int nErr = WSAGetLastError();
420         // WSAEINVAL is here because some legacy version of winsock uses it
421         if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
422         {
423             struct timeval timeout = MillisToTimeval(nTimeout);
424             fd_set fdset;
425             FD_ZERO(&fdset);
426             FD_SET(hSocket, &fdset);
427             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
428             if (nRet == 0)
429             {
430                 LogPrint("net", "connection to %s timeout\n", addrConnect.ToString());
431                 CloseSocket(hSocket);
432                 return false;
433             }
434             if (nRet == SOCKET_ERROR)
435             {
436                 LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
437                 CloseSocket(hSocket);
438                 return false;
439             }
440             socklen_t nRetSize = sizeof(nRet);
441 #ifdef WIN32
442             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
443 #else
444             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
445 #endif
446             {
447                 LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
448                 CloseSocket(hSocket);
449                 return false;
450             }
451             if (nRet != 0)
452             {
453                 LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
454                 CloseSocket(hSocket);
455                 return false;
456             }
457         }
458 #ifdef WIN32
459         else if (WSAGetLastError() != WSAEISCONN)
460 #else
461         else
462 #endif
463         {
464             LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
465             CloseSocket(hSocket);
466             return false;
467         }
468     }
469
470     hSocketRet = hSocket;
471     return true;
472 }
473
474 bool SetProxy(enum Network net, CService addrProxy) {
475     assert(net >= 0 && net < NET_MAX);
476     if (!addrProxy.IsValid())
477         return false;
478     LOCK(cs_proxyInfos);
479     proxyInfo[net] = addrProxy;
480     return true;
481 }
482
483 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
484     assert(net >= 0 && net < NET_MAX);
485     LOCK(cs_proxyInfos);
486     if (!proxyInfo[net].IsValid())
487         return false;
488     proxyInfoOut = proxyInfo[net];
489     return true;
490 }
491
492 bool SetNameProxy(CService addrProxy) {
493     if (!addrProxy.IsValid())
494         return false;
495     LOCK(cs_proxyInfos);
496     nameProxy = addrProxy;
497     return true;
498 }
499
500 bool GetNameProxy(CService &nameProxyOut) {
501     LOCK(cs_proxyInfos);
502     if(!nameProxy.IsValid())
503         return false;
504     nameProxyOut = nameProxy;
505     return true;
506 }
507
508 bool HaveNameProxy() {
509     LOCK(cs_proxyInfos);
510     return nameProxy.IsValid();
511 }
512
513 bool IsProxy(const CNetAddr &addr) {
514     LOCK(cs_proxyInfos);
515     for (int i = 0; i < NET_MAX; i++) {
516         if (addr == (CNetAddr)proxyInfo[i])
517             return true;
518     }
519     return false;
520 }
521
522 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
523 {
524     proxyType proxy;
525     if (outProxyConnectionFailed)
526         *outProxyConnectionFailed = false;
527     // no proxy needed (none set for target network)
528     if (!GetProxy(addrDest.GetNetwork(), proxy))
529         return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
530
531     SOCKET hSocket = INVALID_SOCKET;
532
533     // first connect to proxy server
534     if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) {
535         if (outProxyConnectionFailed)
536             *outProxyConnectionFailed = true;
537         return false;
538     }
539     // do socks negotiation
540     if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket))
541         return false;
542
543     hSocketRet = hSocket;
544     return true;
545 }
546
547 bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
548 {
549     string strDest;
550     int port = portDefault;
551
552     if (outProxyConnectionFailed)
553         *outProxyConnectionFailed = false;
554
555     SplitHostPort(string(pszDest), port, strDest);
556
557     SOCKET hSocket = INVALID_SOCKET;
558
559     CService nameProxy;
560     GetNameProxy(nameProxy);
561
562     CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port);
563     if (addrResolved.IsValid()) {
564         addr = addrResolved;
565         return ConnectSocket(addr, hSocketRet, nTimeout);
566     }
567
568     addr = CService("0.0.0.0:0");
569
570     if (!HaveNameProxy())
571         return false;
572     // first connect to name proxy server
573     if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) {
574         if (outProxyConnectionFailed)
575             *outProxyConnectionFailed = true;
576         return false;
577     }
578     // do socks negotiation
579     if (!Socks5(strDest, (unsigned short)port, hSocket))
580         return false;
581
582     hSocketRet = hSocket;
583     return true;
584 }
585
586 void CNetAddr::Init()
587 {
588     memset(ip, 0, sizeof(ip));
589 }
590
591 void CNetAddr::SetIP(const CNetAddr& ipIn)
592 {
593     memcpy(ip, ipIn.ip, sizeof(ip));
594 }
595
596 void CNetAddr::SetRaw(Network network, const uint8_t *ip_in)
597 {
598     switch(network)
599     {
600         case NET_IPV4:
601             memcpy(ip, pchIPv4, 12);
602             memcpy(ip+12, ip_in, 4);
603             break;
604         case NET_IPV6:
605             memcpy(ip, ip_in, 16);
606             break;
607         default:
608             assert(!"invalid network");
609     }
610 }
611
612 static const unsigned char pchOnionCat[] = {0xFD,0x87,0xD8,0x7E,0xEB,0x43};
613
614 bool CNetAddr::SetSpecial(const std::string &strName)
615 {
616     if (strName.size()>6 && strName.substr(strName.size() - 6, 6) == ".onion") {
617         std::vector<unsigned char> vchAddr = DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
618         if (vchAddr.size() != 16-sizeof(pchOnionCat))
619             return false;
620         memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
621         for (unsigned int i=0; i<16-sizeof(pchOnionCat); i++)
622             ip[i + sizeof(pchOnionCat)] = vchAddr[i];
623         return true;
624     }
625     return false;
626 }
627
628 CNetAddr::CNetAddr()
629 {
630     Init();
631 }
632
633 CNetAddr::CNetAddr(const struct in_addr& ipv4Addr)
634 {
635     SetRaw(NET_IPV4, (const uint8_t*)&ipv4Addr);
636 }
637
638 CNetAddr::CNetAddr(const struct in6_addr& ipv6Addr)
639 {
640     SetRaw(NET_IPV6, (const uint8_t*)&ipv6Addr);
641 }
642
643 CNetAddr::CNetAddr(const char *pszIp, bool fAllowLookup)
644 {
645     Init();
646     std::vector<CNetAddr> vIP;
647     if (LookupHost(pszIp, vIP, 1, fAllowLookup))
648         *this = vIP[0];
649 }
650
651 CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup)
652 {
653     Init();
654     std::vector<CNetAddr> vIP;
655     if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup))
656         *this = vIP[0];
657 }
658
659 unsigned int CNetAddr::GetByte(int n) const
660 {
661     return ip[15-n];
662 }
663
664 bool CNetAddr::IsIPv4() const
665 {
666     return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
667 }
668
669 bool CNetAddr::IsIPv6() const
670 {
671     return (!IsIPv4() && !IsTor());
672 }
673
674 bool CNetAddr::IsRFC1918() const
675 {
676     return IsIPv4() && (
677         GetByte(3) == 10 ||
678         (GetByte(3) == 192 && GetByte(2) == 168) ||
679         (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
680 }
681
682 bool CNetAddr::IsRFC2544() const
683 {
684     return IsIPv4() && GetByte(3) == 198 && (GetByte(2) == 18 || GetByte(2) == 19);
685 }
686
687 bool CNetAddr::IsRFC3927() const
688 {
689     return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
690 }
691
692 bool CNetAddr::IsRFC6598() const
693 {
694     return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 && GetByte(2) <= 127;
695 }
696
697 bool CNetAddr::IsRFC5737() const
698 {
699     return IsIPv4() && ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
700         (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
701         (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
702 }
703
704 bool CNetAddr::IsRFC3849() const
705 {
706     return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D && GetByte(12) == 0xB8;
707 }
708
709 bool CNetAddr::IsRFC3964() const
710 {
711     return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
712 }
713
714 bool CNetAddr::IsRFC6052() const
715 {
716     static const unsigned char pchRFC6052[] = {0,0x64,0xFF,0x9B,0,0,0,0,0,0,0,0};
717     return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
718 }
719
720 bool CNetAddr::IsRFC4380() const
721 {
722     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 && GetByte(12) == 0);
723 }
724
725 bool CNetAddr::IsRFC4862() const
726 {
727     static const unsigned char pchRFC4862[] = {0xFE,0x80,0,0,0,0,0,0};
728     return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
729 }
730
731 bool CNetAddr::IsRFC4193() const
732 {
733     return ((GetByte(15) & 0xFE) == 0xFC);
734 }
735
736 bool CNetAddr::IsRFC6145() const
737 {
738     static const unsigned char pchRFC6145[] = {0,0,0,0,0,0,0,0,0xFF,0xFF,0,0};
739     return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
740 }
741
742 bool CNetAddr::IsRFC4843() const
743 {
744     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 && (GetByte(12) & 0xF0) == 0x10);
745 }
746
747 bool CNetAddr::IsTor() const
748 {
749     return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
750 }
751
752 bool CNetAddr::IsLocal() const
753 {
754     // IPv4 loopback
755    if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0))
756        return true;
757
758    // IPv6 loopback (::1/128)
759    static const unsigned char pchLocal[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
760    if (memcmp(ip, pchLocal, 16) == 0)
761        return true;
762
763    return false;
764 }
765
766 bool CNetAddr::IsMulticast() const
767 {
768     return    (IsIPv4() && (GetByte(3) & 0xF0) == 0xE0)
769            || (GetByte(15) == 0xFF);
770 }
771
772 bool CNetAddr::IsValid() const
773 {
774     // Cleanup 3-byte shifted addresses caused by garbage in size field
775     // of addr messages from versions before 0.2.9 checksum.
776     // Two consecutive addr messages look like this:
777     // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26 addr26 addr26...
778     // so if the first length field is garbled, it reads the second batch
779     // of addr misaligned by 3 bytes.
780     if (memcmp(ip, pchIPv4+3, sizeof(pchIPv4)-3) == 0)
781         return false;
782
783     // unspecified IPv6 address (::/128)
784     unsigned char ipNone[16] = {};
785     if (memcmp(ip, ipNone, 16) == 0)
786         return false;
787
788     // documentation IPv6 address
789     if (IsRFC3849())
790         return false;
791
792     if (IsIPv4())
793     {
794         // INADDR_NONE
795         uint32_t ipNone = INADDR_NONE;
796         if (memcmp(ip+12, &ipNone, 4) == 0)
797             return false;
798
799         // 0
800         ipNone = 0;
801         if (memcmp(ip+12, &ipNone, 4) == 0)
802             return false;
803     }
804
805     return true;
806 }
807
808 bool CNetAddr::IsRoutable() const
809 {
810     return IsValid() && !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() || IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) || IsRFC4843() || IsLocal());
811 }
812
813 enum Network CNetAddr::GetNetwork() const
814 {
815     if (!IsRoutable())
816         return NET_UNROUTABLE;
817
818     if (IsIPv4())
819         return NET_IPV4;
820
821     if (IsTor())
822         return NET_TOR;
823
824     return NET_IPV6;
825 }
826
827 std::string CNetAddr::ToStringIP() const
828 {
829     if (IsTor())
830         return EncodeBase32(&ip[6], 10) + ".onion";
831     CService serv(*this, 0);
832     struct sockaddr_storage sockaddr;
833     socklen_t socklen = sizeof(sockaddr);
834     if (serv.GetSockAddr((struct sockaddr*)&sockaddr, &socklen)) {
835         char name[1025] = "";
836         if (!getnameinfo((const struct sockaddr*)&sockaddr, socklen, name, sizeof(name), NULL, 0, NI_NUMERICHOST))
837             return std::string(name);
838     }
839     if (IsIPv4())
840         return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1), GetByte(0));
841     else
842         return strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
843                          GetByte(15) << 8 | GetByte(14), GetByte(13) << 8 | GetByte(12),
844                          GetByte(11) << 8 | GetByte(10), GetByte(9) << 8 | GetByte(8),
845                          GetByte(7) << 8 | GetByte(6), GetByte(5) << 8 | GetByte(4),
846                          GetByte(3) << 8 | GetByte(2), GetByte(1) << 8 | GetByte(0));
847 }
848
849 std::string CNetAddr::ToString() const
850 {
851     return ToStringIP();
852 }
853
854 bool operator==(const CNetAddr& a, const CNetAddr& b)
855 {
856     return (memcmp(a.ip, b.ip, 16) == 0);
857 }
858
859 bool operator!=(const CNetAddr& a, const CNetAddr& b)
860 {
861     return (memcmp(a.ip, b.ip, 16) != 0);
862 }
863
864 bool operator<(const CNetAddr& a, const CNetAddr& b)
865 {
866     return (memcmp(a.ip, b.ip, 16) < 0);
867 }
868
869 bool CNetAddr::GetInAddr(struct in_addr* pipv4Addr) const
870 {
871     if (!IsIPv4())
872         return false;
873     memcpy(pipv4Addr, ip+12, 4);
874     return true;
875 }
876
877 bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const
878 {
879     memcpy(pipv6Addr, ip, 16);
880     return true;
881 }
882
883 // get canonical identifier of an address' group
884 // no two connections will be attempted to addresses with the same group
885 std::vector<unsigned char> CNetAddr::GetGroup() const
886 {
887     std::vector<unsigned char> vchRet;
888     int nClass = NET_IPV6;
889     int nStartByte = 0;
890     int nBits = 16;
891
892     // all local addresses belong to the same group
893     if (IsLocal())
894     {
895         nClass = 255;
896         nBits = 0;
897     }
898
899     // all unroutable addresses belong to the same group
900     if (!IsRoutable())
901     {
902         nClass = NET_UNROUTABLE;
903         nBits = 0;
904     }
905     // for IPv4 addresses, '1' + the 16 higher-order bits of the IP
906     // includes mapped IPv4, SIIT translated IPv4, and the well-known prefix
907     else if (IsIPv4() || IsRFC6145() || IsRFC6052())
908     {
909         nClass = NET_IPV4;
910         nStartByte = 12;
911     }
912     // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
913     else if (IsRFC3964())
914     {
915         nClass = NET_IPV4;
916         nStartByte = 2;
917     }
918     // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4 address
919     else if (IsRFC4380())
920     {
921         vchRet.push_back(NET_IPV4);
922         vchRet.push_back(GetByte(3) ^ 0xFF);
923         vchRet.push_back(GetByte(2) ^ 0xFF);
924         return vchRet;
925     }
926     else if (IsTor())
927     {
928         nClass = NET_TOR;
929         nStartByte = 6;
930         nBits = 4;
931     }
932     // for he.net, use /36 groups
933     else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70)
934         nBits = 36;
935     // for the rest of the IPv6 network, use /32 groups
936     else
937         nBits = 32;
938
939     vchRet.push_back(nClass);
940     while (nBits >= 8)
941     {
942         vchRet.push_back(GetByte(15 - nStartByte));
943         nStartByte++;
944         nBits -= 8;
945     }
946     if (nBits > 0)
947         vchRet.push_back(GetByte(15 - nStartByte) | ((1 << nBits) - 1));
948
949     return vchRet;
950 }
951
952 uint64_t CNetAddr::GetHash() const
953 {
954     uint256 hash = Hash(&ip[0], &ip[16]);
955     uint64_t nRet;
956     memcpy(&nRet, &hash, sizeof(nRet));
957     return nRet;
958 }
959
960 // private extensions to enum Network, only returned by GetExtNetwork,
961 // and only used in GetReachabilityFrom
962 static const int NET_UNKNOWN = NET_MAX + 0;
963 static const int NET_TEREDO  = NET_MAX + 1;
964 int static GetExtNetwork(const CNetAddr *addr)
965 {
966     if (addr == NULL)
967         return NET_UNKNOWN;
968     if (addr->IsRFC4380())
969         return NET_TEREDO;
970     return addr->GetNetwork();
971 }
972
973 /** Calculates a metric for how reachable (*this) is from a given partner */
974 int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const
975 {
976     enum Reachability {
977         REACH_UNREACHABLE,
978         REACH_DEFAULT,
979         REACH_TEREDO,
980         REACH_IPV6_WEAK,
981         REACH_IPV4,
982         REACH_IPV6_STRONG,
983         REACH_PRIVATE
984     };
985
986     if (!IsRoutable())
987         return REACH_UNREACHABLE;
988
989     int ourNet = GetExtNetwork(this);
990     int theirNet = GetExtNetwork(paddrPartner);
991     bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
992
993     switch(theirNet) {
994     case NET_IPV4:
995         switch(ourNet) {
996         default:       return REACH_DEFAULT;
997         case NET_IPV4: return REACH_IPV4;
998         }
999     case NET_IPV6:
1000         switch(ourNet) {
1001         default:         return REACH_DEFAULT;
1002         case NET_TEREDO: return REACH_TEREDO;
1003         case NET_IPV4:   return REACH_IPV4;
1004         case NET_IPV6:   return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG; // only prefer giving our IPv6 address if it's not tunnelled
1005         }
1006     case NET_TOR:
1007         switch(ourNet) {
1008         default:         return REACH_DEFAULT;
1009         case NET_IPV4:   return REACH_IPV4; // Tor users can connect to IPv4 as well
1010         case NET_TOR:    return REACH_PRIVATE;
1011         }
1012     case NET_TEREDO:
1013         switch(ourNet) {
1014         default:          return REACH_DEFAULT;
1015         case NET_TEREDO:  return REACH_TEREDO;
1016         case NET_IPV6:    return REACH_IPV6_WEAK;
1017         case NET_IPV4:    return REACH_IPV4;
1018         }
1019     case NET_UNKNOWN:
1020     case NET_UNROUTABLE:
1021     default:
1022         switch(ourNet) {
1023         default:          return REACH_DEFAULT;
1024         case NET_TEREDO:  return REACH_TEREDO;
1025         case NET_IPV6:    return REACH_IPV6_WEAK;
1026         case NET_IPV4:    return REACH_IPV4;
1027         case NET_TOR:     return REACH_PRIVATE; // either from Tor, or don't care about our address
1028         }
1029     }
1030 }
1031
1032 void CService::Init()
1033 {
1034     port = 0;
1035 }
1036
1037 CService::CService()
1038 {
1039     Init();
1040 }
1041
1042 CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn)
1043 {
1044 }
1045
1046 CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn)
1047 {
1048 }
1049
1050 CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn)
1051 {
1052 }
1053
1054 CService::CService(const struct sockaddr_in& addr) : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port))
1055 {
1056     assert(addr.sin_family == AF_INET);
1057 }
1058
1059 CService::CService(const struct sockaddr_in6 &addr) : CNetAddr(addr.sin6_addr), port(ntohs(addr.sin6_port))
1060 {
1061    assert(addr.sin6_family == AF_INET6);
1062 }
1063
1064 bool CService::SetSockAddr(const struct sockaddr *paddr)
1065 {
1066     switch (paddr->sa_family) {
1067     case AF_INET:
1068         *this = CService(*(const struct sockaddr_in*)paddr);
1069         return true;
1070     case AF_INET6:
1071         *this = CService(*(const struct sockaddr_in6*)paddr);
1072         return true;
1073     default:
1074         return false;
1075     }
1076 }
1077
1078 CService::CService(const char *pszIpPort, bool fAllowLookup)
1079 {
1080     Init();
1081     CService ip;
1082     if (Lookup(pszIpPort, ip, 0, fAllowLookup))
1083         *this = ip;
1084 }
1085
1086 CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
1087 {
1088     Init();
1089     CService ip;
1090     if (Lookup(pszIpPort, ip, portDefault, fAllowLookup))
1091         *this = ip;
1092 }
1093
1094 CService::CService(const std::string &strIpPort, bool fAllowLookup)
1095 {
1096     Init();
1097     CService ip;
1098     if (Lookup(strIpPort.c_str(), ip, 0, fAllowLookup))
1099         *this = ip;
1100 }
1101
1102 CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup)
1103 {
1104     Init();
1105     CService ip;
1106     if (Lookup(strIpPort.c_str(), ip, portDefault, fAllowLookup))
1107         *this = ip;
1108 }
1109
1110 unsigned short CService::GetPort() const
1111 {
1112     return port;
1113 }
1114
1115 bool operator==(const CService& a, const CService& b)
1116 {
1117     return (CNetAddr)a == (CNetAddr)b && a.port == b.port;
1118 }
1119
1120 bool operator!=(const CService& a, const CService& b)
1121 {
1122     return (CNetAddr)a != (CNetAddr)b || a.port != b.port;
1123 }
1124
1125 bool operator<(const CService& a, const CService& b)
1126 {
1127     return (CNetAddr)a < (CNetAddr)b || ((CNetAddr)a == (CNetAddr)b && a.port < b.port);
1128 }
1129
1130 bool CService::GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const
1131 {
1132     if (IsIPv4()) {
1133         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in))
1134             return false;
1135         *addrlen = sizeof(struct sockaddr_in);
1136         struct sockaddr_in *paddrin = (struct sockaddr_in*)paddr;
1137         memset(paddrin, 0, *addrlen);
1138         if (!GetInAddr(&paddrin->sin_addr))
1139             return false;
1140         paddrin->sin_family = AF_INET;
1141         paddrin->sin_port = htons(port);
1142         return true;
1143     }
1144     if (IsIPv6()) {
1145         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6))
1146             return false;
1147         *addrlen = sizeof(struct sockaddr_in6);
1148         struct sockaddr_in6 *paddrin6 = (struct sockaddr_in6*)paddr;
1149         memset(paddrin6, 0, *addrlen);
1150         if (!GetIn6Addr(&paddrin6->sin6_addr))
1151             return false;
1152         paddrin6->sin6_family = AF_INET6;
1153         paddrin6->sin6_port = htons(port);
1154         return true;
1155     }
1156     return false;
1157 }
1158
1159 std::vector<unsigned char> CService::GetKey() const
1160 {
1161      std::vector<unsigned char> vKey;
1162      vKey.resize(18);
1163      memcpy(&vKey[0], ip, 16);
1164      vKey[16] = port / 0x100;
1165      vKey[17] = port & 0x0FF;
1166      return vKey;
1167 }
1168
1169 std::string CService::ToStringPort() const
1170 {
1171     return strprintf("%u", port);
1172 }
1173
1174 std::string CService::ToStringIPPort() const
1175 {
1176     if (IsIPv4() || IsTor()) {
1177         return ToStringIP() + ":" + ToStringPort();
1178     } else {
1179         return "[" + ToStringIP() + "]:" + ToStringPort();
1180     }
1181 }
1182
1183 std::string CService::ToString() const
1184 {
1185     return ToStringIPPort();
1186 }
1187
1188 void CService::SetPort(unsigned short portIn)
1189 {
1190     port = portIn;
1191 }
1192
1193 CSubNet::CSubNet():
1194     valid(false)
1195 {
1196     memset(netmask, 0, sizeof(netmask));
1197 }
1198
1199 CSubNet::CSubNet(const std::string &strSubnet, bool fAllowLookup)
1200 {
1201     size_t slash = strSubnet.find_last_of('/');
1202     std::vector<CNetAddr> vIP;
1203
1204     valid = true;
1205     // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
1206     memset(netmask, 255, sizeof(netmask));
1207
1208     std::string strAddress = strSubnet.substr(0, slash);
1209     if (LookupHost(strAddress.c_str(), vIP, 1, fAllowLookup))
1210     {
1211         network = vIP[0];
1212         if (slash != strSubnet.npos)
1213         {
1214             std::string strNetmask = strSubnet.substr(slash + 1);
1215             int32_t n;
1216             // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
1217             int noffset = network.IsIPv4() ? (12 * 8) : 0;
1218             if (ParseInt32(strNetmask, &n)) // If valid number, assume /24 symtex
1219             {
1220                 if(n >= 0 && n <= (128 - noffset)) // Only valid if in range of bits of address
1221                 {
1222                     n += noffset;
1223                     // Clear bits [n..127]
1224                     for (; n < 128; ++n)
1225                         netmask[n>>3] &= ~(1<<(n&7));
1226                 }
1227                 else
1228                 {
1229                     valid = false;
1230                 }
1231             }
1232             else // If not a valid number, try full netmask syntax
1233             {
1234                 if (LookupHost(strNetmask.c_str(), vIP, 1, false)) // Never allow lookup for netmask
1235                 {
1236                     // Remember: GetByte returns bytes in reversed order
1237                     // Copy only the *last* four bytes in case of IPv4, the rest of the mask should stay 1's as
1238                     // we don't want pchIPv4 to be part of the mask.
1239                     int asize = network.IsIPv4() ? 4 : 16;
1240                     for(int x=0; x<asize; ++x)
1241                         netmask[15-x] = vIP[0].GetByte(x);
1242                 }
1243                 else
1244                 {
1245                     valid = false;
1246                 }
1247             }
1248         }
1249     }
1250     else
1251     {
1252         valid = false;
1253     }
1254 }
1255
1256 bool CSubNet::Match(const CNetAddr &addr) const
1257 {
1258     if (!valid || !addr.IsValid())
1259         return false;
1260     for(int x=0; x<16; ++x)
1261         if ((addr.GetByte(x) & netmask[15-x]) != network.GetByte(x))
1262             return false;
1263     return true;
1264 }
1265
1266 std::string CSubNet::ToString() const
1267 {
1268     std::string strNetmask;
1269     if (network.IsIPv4())
1270         strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13], netmask[14], netmask[15]);
1271     else
1272         strNetmask = strprintf("%x:%x:%x:%x:%x:%x:%x:%x",
1273                          netmask[0] << 8 | netmask[1], netmask[2] << 8 | netmask[3],
1274                          netmask[4] << 8 | netmask[5], netmask[6] << 8 | netmask[7],
1275                          netmask[8] << 8 | netmask[9], netmask[10] << 8 | netmask[11],
1276                          netmask[12] << 8 | netmask[13], netmask[14] << 8 | netmask[15]);
1277     return network.ToString() + "/" + strNetmask;
1278 }
1279
1280 bool CSubNet::IsValid() const
1281 {
1282     return valid;
1283 }
1284
1285 bool operator==(const CSubNet& a, const CSubNet& b)
1286 {
1287     return a.valid == b.valid && a.network == b.network && !memcmp(a.netmask, b.netmask, 16);
1288 }
1289
1290 bool operator!=(const CSubNet& a, const CSubNet& b)
1291 {
1292     return !(a==b);
1293 }
1294
1295 #ifdef WIN32
1296 std::string NetworkErrorString(int err)
1297 {
1298     char buf[256];
1299     buf[0] = 0;
1300     if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
1301             NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1302             buf, sizeof(buf), NULL))
1303     {
1304         return strprintf("%s (%d)", buf, err);
1305     }
1306     else
1307     {
1308         return strprintf("Unknown error (%d)", err);
1309     }
1310 }
1311 #else
1312 std::string NetworkErrorString(int err)
1313 {
1314     char buf[256];
1315     const char *s = buf;
1316     buf[0] = 0;
1317     /* Too bad there are two incompatible implementations of the
1318      * thread-safe strerror. */
1319 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
1320     s = strerror_r(err, buf, sizeof(buf));
1321 #else /* POSIX variant always returns message in buffer */
1322     if (strerror_r(err, buf, sizeof(buf)))
1323         buf[0] = 0;
1324 #endif
1325     return strprintf("%s (%d)", s, err);
1326 }
1327 #endif
1328
1329 bool CloseSocket(SOCKET& hSocket)
1330 {
1331     if (hSocket == INVALID_SOCKET)
1332         return false;
1333 #ifdef WIN32
1334     int ret = closesocket(hSocket);
1335 #else
1336     int ret = close(hSocket);
1337 #endif
1338     hSocket = INVALID_SOCKET;
1339     return ret != SOCKET_ERROR;
1340 }
1341
1342 bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking)
1343 {
1344     if (fNonBlocking) {
1345 #ifdef WIN32
1346         u_long nOne = 1;
1347         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
1348 #else
1349         int fFlags = fcntl(hSocket, F_GETFL, 0);
1350         if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
1351 #endif
1352             CloseSocket(hSocket);
1353             return false;
1354         }
1355     } else {
1356 #ifdef WIN32
1357         u_long nZero = 0;
1358         if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
1359 #else
1360         int fFlags = fcntl(hSocket, F_GETFL, 0);
1361         if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
1362 #endif
1363             CloseSocket(hSocket);
1364             return false;
1365         }
1366     }
1367
1368     return true;
1369 }
This page took 0.100828 seconds and 4 git commands to generate.