Merge #10816: Properly forbid -salvagewallet and -zapwallettxes for multi wallet.
[bitcoinplatinum.git] / src / netbase.cpp
blob3fb1c18f0308a453573b42b82d86e8ae24cc6e4e
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #ifdef HAVE_CONFIG_H
7 #include "config/bitcoin-config.h"
8 #endif
10 #include "netbase.h"
12 #include "hash.h"
13 #include "sync.h"
14 #include "uint256.h"
15 #include "random.h"
16 #include "util.h"
17 #include "utilstrencodings.h"
19 #include <atomic>
21 #ifndef WIN32
22 #include <fcntl.h>
23 #endif
25 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
26 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
28 #if !defined(HAVE_MSG_NOSIGNAL)
29 #define MSG_NOSIGNAL 0
30 #endif
32 // Settings
33 static proxyType proxyInfo[NET_MAX];
34 static proxyType nameProxy;
35 static CCriticalSection cs_proxyInfos;
36 int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
37 bool fNameLookup = DEFAULT_NAME_LOOKUP;
39 // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
40 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
41 static std::atomic<bool> interruptSocks5Recv(false);
43 enum Network ParseNetwork(std::string net) {
44 boost::to_lower(net);
45 if (net == "ipv4") return NET_IPV4;
46 if (net == "ipv6") return NET_IPV6;
47 if (net == "tor" || net == "onion") return NET_TOR;
48 return NET_UNROUTABLE;
51 std::string GetNetworkName(enum Network net) {
52 switch(net)
54 case NET_IPV4: return "ipv4";
55 case NET_IPV6: return "ipv6";
56 case NET_TOR: return "onion";
57 default: return "";
61 void SplitHostPort(std::string in, int &portOut, std::string &hostOut) {
62 size_t colon = in.find_last_of(':');
63 // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator
64 bool fHaveColon = colon != in.npos;
65 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
66 bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
67 if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
68 int32_t n;
69 if (ParseInt32(in.substr(colon + 1), &n) && n > 0 && n < 0x10000) {
70 in = in.substr(0, colon);
71 portOut = n;
74 if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
75 hostOut = in.substr(1, in.size()-2);
76 else
77 hostOut = in;
80 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
82 vIP.clear();
85 CNetAddr addr;
86 if (addr.SetSpecial(std::string(pszName))) {
87 vIP.push_back(addr);
88 return true;
92 struct addrinfo aiHint;
93 memset(&aiHint, 0, sizeof(struct addrinfo));
95 aiHint.ai_socktype = SOCK_STREAM;
96 aiHint.ai_protocol = IPPROTO_TCP;
97 aiHint.ai_family = AF_UNSPEC;
98 #ifdef WIN32
99 aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
100 #else
101 aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
102 #endif
103 struct addrinfo *aiRes = NULL;
104 int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
105 if (nErr)
106 return false;
108 struct addrinfo *aiTrav = aiRes;
109 while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
111 CNetAddr resolved;
112 if (aiTrav->ai_family == AF_INET)
114 assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
115 resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
118 if (aiTrav->ai_family == AF_INET6)
120 assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
121 struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
122 resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
124 /* Never allow resolving to an internal address. Consider any such result invalid */
125 if (!resolved.IsInternal()) {
126 vIP.push_back(resolved);
129 aiTrav = aiTrav->ai_next;
132 freeaddrinfo(aiRes);
134 return (vIP.size() > 0);
137 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
139 std::string strHost(pszName);
140 if (strHost.empty())
141 return false;
142 if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
144 strHost = strHost.substr(1, strHost.size() - 2);
147 return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
150 bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
152 std::vector<CNetAddr> vIP;
153 LookupHost(pszName, vIP, 1, fAllowLookup);
154 if(vIP.empty())
155 return false;
156 addr = vIP.front();
157 return true;
160 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
162 if (pszName[0] == 0)
163 return false;
164 int port = portDefault;
165 std::string hostname = "";
166 SplitHostPort(std::string(pszName), port, hostname);
168 std::vector<CNetAddr> vIP;
169 bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
170 if (!fRet)
171 return false;
172 vAddr.resize(vIP.size());
173 for (unsigned int i = 0; i < vIP.size(); i++)
174 vAddr[i] = CService(vIP[i], port);
175 return true;
178 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
180 std::vector<CService> vService;
181 bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
182 if (!fRet)
183 return false;
184 addr = vService[0];
185 return true;
188 CService LookupNumeric(const char *pszName, int portDefault)
190 CService addr;
191 // "1.2:345" will fail to resolve the ip, but will still set the port.
192 // If the ip fails to resolve, re-init the result.
193 if(!Lookup(pszName, addr, portDefault, false))
194 addr = CService();
195 return addr;
198 struct timeval MillisToTimeval(int64_t nTimeout)
200 struct timeval timeout;
201 timeout.tv_sec = nTimeout / 1000;
202 timeout.tv_usec = (nTimeout % 1000) * 1000;
203 return timeout;
206 enum class IntrRecvError {
208 Timeout,
209 Disconnected,
210 NetworkError,
211 Interrupted
215 * Read bytes from socket. This will either read the full number of bytes requested
216 * or return False on error or timeout.
217 * This function can be interrupted by calling InterruptSocks5()
219 * @param data Buffer to receive into
220 * @param len Length of data to receive
221 * @param timeout Timeout in milliseconds for receive operation
223 * @note This function requires that hSocket is in non-blocking mode.
225 static IntrRecvError InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
227 int64_t curTime = GetTimeMillis();
228 int64_t endTime = curTime + timeout;
229 // Maximum time to wait in one select call. It will take up until this time (in millis)
230 // to break off in case of an interruption.
231 const int64_t maxWait = 1000;
232 while (len > 0 && curTime < endTime) {
233 ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first
234 if (ret > 0) {
235 len -= ret;
236 data += ret;
237 } else if (ret == 0) { // Unexpected disconnection
238 return IntrRecvError::Disconnected;
239 } else { // Other error or blocking
240 int nErr = WSAGetLastError();
241 if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
242 if (!IsSelectableSocket(hSocket)) {
243 return IntrRecvError::NetworkError;
245 struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
246 fd_set fdset;
247 FD_ZERO(&fdset);
248 FD_SET(hSocket, &fdset);
249 int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval);
250 if (nRet == SOCKET_ERROR) {
251 return IntrRecvError::NetworkError;
253 } else {
254 return IntrRecvError::NetworkError;
257 if (interruptSocks5Recv)
258 return IntrRecvError::Interrupted;
259 curTime = GetTimeMillis();
261 return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
264 struct ProxyCredentials
266 std::string username;
267 std::string password;
270 std::string Socks5ErrorString(int err)
272 switch(err) {
273 case 0x01: return "general failure";
274 case 0x02: return "connection not allowed";
275 case 0x03: return "network unreachable";
276 case 0x04: return "host unreachable";
277 case 0x05: return "connection refused";
278 case 0x06: return "TTL expired";
279 case 0x07: return "protocol error";
280 case 0x08: return "address type not supported";
281 default: return "unknown";
285 /** Connect using SOCKS5 (as described in RFC1928) */
286 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
288 IntrRecvError recvr;
289 LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
290 if (strDest.size() > 255) {
291 CloseSocket(hSocket);
292 return error("Hostname too long");
294 // Accepted authentication methods
295 std::vector<uint8_t> vSocks5Init;
296 vSocks5Init.push_back(0x05);
297 if (auth) {
298 vSocks5Init.push_back(0x02); // # METHODS
299 vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
300 vSocks5Init.push_back(0x02); // X'02' USERNAME/PASSWORD (RFC1929)
301 } else {
302 vSocks5Init.push_back(0x01); // # METHODS
303 vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
305 ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
306 if (ret != (ssize_t)vSocks5Init.size()) {
307 CloseSocket(hSocket);
308 return error("Error sending to proxy");
310 char pchRet1[2];
311 if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
312 CloseSocket(hSocket);
313 LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
314 return false;
316 if (pchRet1[0] != 0x05) {
317 CloseSocket(hSocket);
318 return error("Proxy failed to initialize");
320 if (pchRet1[1] == 0x02 && auth) {
321 // Perform username/password authentication (as described in RFC1929)
322 std::vector<uint8_t> vAuth;
323 vAuth.push_back(0x01);
324 if (auth->username.size() > 255 || auth->password.size() > 255)
325 return error("Proxy username or password too long");
326 vAuth.push_back(auth->username.size());
327 vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
328 vAuth.push_back(auth->password.size());
329 vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
330 ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
331 if (ret != (ssize_t)vAuth.size()) {
332 CloseSocket(hSocket);
333 return error("Error sending authentication to proxy");
335 LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
336 char pchRetA[2];
337 if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
338 CloseSocket(hSocket);
339 return error("Error reading proxy authentication response");
341 if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
342 CloseSocket(hSocket);
343 return error("Proxy authentication unsuccessful");
345 } else if (pchRet1[1] == 0x00) {
346 // Perform no authentication
347 } else {
348 CloseSocket(hSocket);
349 return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
351 std::vector<uint8_t> vSocks5;
352 vSocks5.push_back(0x05); // VER protocol version
353 vSocks5.push_back(0x01); // CMD CONNECT
354 vSocks5.push_back(0x00); // RSV Reserved
355 vSocks5.push_back(0x03); // ATYP DOMAINNAME
356 vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
357 vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
358 vSocks5.push_back((port >> 8) & 0xFF);
359 vSocks5.push_back((port >> 0) & 0xFF);
360 ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
361 if (ret != (ssize_t)vSocks5.size()) {
362 CloseSocket(hSocket);
363 return error("Error sending to proxy");
365 char pchRet2[4];
366 if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
367 CloseSocket(hSocket);
368 if (recvr == IntrRecvError::Timeout) {
369 /* If a timeout happens here, this effectively means we timed out while connecting
370 * to the remote node. This is very common for Tor, so do not print an
371 * error message. */
372 return false;
373 } else {
374 return error("Error while reading proxy response");
377 if (pchRet2[0] != 0x05) {
378 CloseSocket(hSocket);
379 return error("Proxy failed to accept request");
381 if (pchRet2[1] != 0x00) {
382 // Failures to connect to a peer that are not proxy errors
383 CloseSocket(hSocket);
384 LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
385 return false;
387 if (pchRet2[2] != 0x00) {
388 CloseSocket(hSocket);
389 return error("Error: malformed proxy response");
391 char pchRet3[256];
392 switch (pchRet2[3])
394 case 0x01: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
395 case 0x04: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
396 case 0x03:
398 recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
399 if (recvr != IntrRecvError::OK) {
400 CloseSocket(hSocket);
401 return error("Error reading from proxy");
403 int nRecv = pchRet3[0];
404 recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
405 break;
407 default: CloseSocket(hSocket); return error("Error: malformed proxy response");
409 if (recvr != IntrRecvError::OK) {
410 CloseSocket(hSocket);
411 return error("Error reading from proxy");
413 if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
414 CloseSocket(hSocket);
415 return error("Error reading from proxy");
417 LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
418 return true;
421 bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
423 hSocketRet = INVALID_SOCKET;
425 struct sockaddr_storage sockaddr;
426 socklen_t len = sizeof(sockaddr);
427 if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
428 LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
429 return false;
432 SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
433 if (hSocket == INVALID_SOCKET)
434 return false;
436 #ifdef SO_NOSIGPIPE
437 int set = 1;
438 // Different way of disabling SIGPIPE on BSD
439 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
440 #endif
442 //Disable Nagle's algorithm
443 SetSocketNoDelay(hSocket);
445 // Set to non-blocking
446 if (!SetSocketNonBlocking(hSocket, true))
447 return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
449 if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
451 int nErr = WSAGetLastError();
452 // WSAEINVAL is here because some legacy version of winsock uses it
453 if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
455 struct timeval timeout = MillisToTimeval(nTimeout);
456 fd_set fdset;
457 FD_ZERO(&fdset);
458 FD_SET(hSocket, &fdset);
459 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
460 if (nRet == 0)
462 LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
463 CloseSocket(hSocket);
464 return false;
466 if (nRet == SOCKET_ERROR)
468 LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
469 CloseSocket(hSocket);
470 return false;
472 socklen_t nRetSize = sizeof(nRet);
473 #ifdef WIN32
474 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
475 #else
476 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
477 #endif
479 LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
480 CloseSocket(hSocket);
481 return false;
483 if (nRet != 0)
485 LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
486 CloseSocket(hSocket);
487 return false;
490 #ifdef WIN32
491 else if (WSAGetLastError() != WSAEISCONN)
492 #else
493 else
494 #endif
496 LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
497 CloseSocket(hSocket);
498 return false;
502 hSocketRet = hSocket;
503 return true;
506 bool SetProxy(enum Network net, const proxyType &addrProxy) {
507 assert(net >= 0 && net < NET_MAX);
508 if (!addrProxy.IsValid())
509 return false;
510 LOCK(cs_proxyInfos);
511 proxyInfo[net] = addrProxy;
512 return true;
515 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
516 assert(net >= 0 && net < NET_MAX);
517 LOCK(cs_proxyInfos);
518 if (!proxyInfo[net].IsValid())
519 return false;
520 proxyInfoOut = proxyInfo[net];
521 return true;
524 bool SetNameProxy(const proxyType &addrProxy) {
525 if (!addrProxy.IsValid())
526 return false;
527 LOCK(cs_proxyInfos);
528 nameProxy = addrProxy;
529 return true;
532 bool GetNameProxy(proxyType &nameProxyOut) {
533 LOCK(cs_proxyInfos);
534 if(!nameProxy.IsValid())
535 return false;
536 nameProxyOut = nameProxy;
537 return true;
540 bool HaveNameProxy() {
541 LOCK(cs_proxyInfos);
542 return nameProxy.IsValid();
545 bool IsProxy(const CNetAddr &addr) {
546 LOCK(cs_proxyInfos);
547 for (int i = 0; i < NET_MAX; i++) {
548 if (addr == (CNetAddr)proxyInfo[i].proxy)
549 return true;
551 return false;
554 static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
556 SOCKET hSocket = INVALID_SOCKET;
557 // first connect to proxy server
558 if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
559 if (outProxyConnectionFailed)
560 *outProxyConnectionFailed = true;
561 return false;
563 // do socks negotiation
564 if (proxy.randomize_credentials) {
565 ProxyCredentials random_auth;
566 static std::atomic_int counter(0);
567 random_auth.username = random_auth.password = strprintf("%i", counter++);
568 if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
569 return false;
570 } else {
571 if (!Socks5(strDest, (unsigned short)port, 0, hSocket))
572 return false;
575 hSocketRet = hSocket;
576 return true;
579 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
581 proxyType proxy;
582 if (outProxyConnectionFailed)
583 *outProxyConnectionFailed = false;
585 if (GetProxy(addrDest.GetNetwork(), proxy))
586 return ConnectThroughProxy(proxy, addrDest.ToStringIP(), addrDest.GetPort(), hSocketRet, nTimeout, outProxyConnectionFailed);
587 else // no proxy needed (none set for target network)
588 return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
591 bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
593 std::string strDest;
594 int port = portDefault;
596 if (outProxyConnectionFailed)
597 *outProxyConnectionFailed = false;
599 SplitHostPort(std::string(pszDest), port, strDest);
601 proxyType proxy;
602 GetNameProxy(proxy);
604 std::vector<CService> addrResolved;
605 if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) {
606 if (addrResolved.size() > 0) {
607 addr = addrResolved[GetRand(addrResolved.size())];
608 return ConnectSocket(addr, hSocketRet, nTimeout);
612 addr = CService();
614 if (!HaveNameProxy())
615 return false;
616 return ConnectThroughProxy(proxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
619 bool LookupSubNet(const char* pszName, CSubNet& ret)
621 std::string strSubnet(pszName);
622 size_t slash = strSubnet.find_last_of('/');
623 std::vector<CNetAddr> vIP;
625 std::string strAddress = strSubnet.substr(0, slash);
626 if (LookupHost(strAddress.c_str(), vIP, 1, false))
628 CNetAddr network = vIP[0];
629 if (slash != strSubnet.npos)
631 std::string strNetmask = strSubnet.substr(slash + 1);
632 int32_t n;
633 // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
634 if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
635 ret = CSubNet(network, n);
636 return ret.IsValid();
638 else // If not a valid number, try full netmask syntax
640 // Never allow lookup for netmask
641 if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
642 ret = CSubNet(network, vIP[0]);
643 return ret.IsValid();
647 else
649 ret = CSubNet(network);
650 return ret.IsValid();
653 return false;
656 #ifdef WIN32
657 std::string NetworkErrorString(int err)
659 char buf[256];
660 buf[0] = 0;
661 if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
662 NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
663 buf, sizeof(buf), NULL))
665 return strprintf("%s (%d)", buf, err);
667 else
669 return strprintf("Unknown error (%d)", err);
672 #else
673 std::string NetworkErrorString(int err)
675 char buf[256];
676 buf[0] = 0;
677 /* Too bad there are two incompatible implementations of the
678 * thread-safe strerror. */
679 const char *s;
680 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
681 s = strerror_r(err, buf, sizeof(buf));
682 #else /* POSIX variant always returns message in buffer */
683 s = buf;
684 if (strerror_r(err, buf, sizeof(buf)))
685 buf[0] = 0;
686 #endif
687 return strprintf("%s (%d)", s, err);
689 #endif
691 bool CloseSocket(SOCKET& hSocket)
693 if (hSocket == INVALID_SOCKET)
694 return false;
695 #ifdef WIN32
696 int ret = closesocket(hSocket);
697 #else
698 int ret = close(hSocket);
699 #endif
700 hSocket = INVALID_SOCKET;
701 return ret != SOCKET_ERROR;
704 bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking)
706 if (fNonBlocking) {
707 #ifdef WIN32
708 u_long nOne = 1;
709 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
710 #else
711 int fFlags = fcntl(hSocket, F_GETFL, 0);
712 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
713 #endif
714 CloseSocket(hSocket);
715 return false;
717 } else {
718 #ifdef WIN32
719 u_long nZero = 0;
720 if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
721 #else
722 int fFlags = fcntl(hSocket, F_GETFL, 0);
723 if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
724 #endif
725 CloseSocket(hSocket);
726 return false;
730 return true;
733 bool SetSocketNoDelay(SOCKET& hSocket)
735 int set = 1;
736 int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
737 return rc == 0;
740 void InterruptSocks5(bool interrupt)
742 interruptSocks5Recv = interrupt;