Raven Core  3.0.0
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2016 The Bitcoin Core developers
3 // Copyright (c) 2017-2019 The Raven Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #ifdef HAVE_CONFIG_H
8 #include "config/raven-config.h"
9 #endif
10 
11 #include "netbase.h"
12 
13 #include "hash.h"
14 #include "sync.h"
15 #include "uint256.h"
16 #include "random.h"
17 #include "util.h"
18 #include "utilstrencodings.h"
19 
20 #include <atomic>
21 
22 #ifndef WIN32
23 #include <fcntl.h>
24 #endif
25 
26 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
27 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
28 
29 #if !defined(HAVE_MSG_NOSIGNAL)
30 #define MSG_NOSIGNAL 0
31 #endif
32 
33 // Settings
34 static proxyType proxyInfo[NET_MAX];
35 static proxyType nameProxy;
36 static CCriticalSection cs_proxyInfos;
37 int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
38 bool fNameLookup = DEFAULT_NAME_LOOKUP;
39 
40 // Need ample time for negotiation for very slow proxies such as Tor (milliseconds)
41 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
42 static std::atomic<bool> interruptSocks5Recv(false);
43 
44 enum Network ParseNetwork(std::string net) {
45  boost::to_lower(net);
46  if (net == "ipv4") return NET_IPV4;
47  if (net == "ipv6") return NET_IPV6;
48  if (net == "tor" || net == "onion") return NET_TOR;
49  return NET_UNROUTABLE;
50 }
51 
52 std::string GetNetworkName(enum Network net) {
53  switch(net)
54  {
55  case NET_IPV4: return "ipv4";
56  case NET_IPV6: return "ipv6";
57  case NET_TOR: return "onion";
58  default: return "";
59  }
60 }
61 
62 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
63 {
64  vIP.clear();
65 
66  {
67  CNetAddr addr;
68  if (addr.SetSpecial(std::string(pszName))) {
69  vIP.push_back(addr);
70  return true;
71  }
72  }
73 
74  struct addrinfo aiHint;
75  memset(&aiHint, 0, sizeof(struct addrinfo));
76 
77  aiHint.ai_socktype = SOCK_STREAM;
78  aiHint.ai_protocol = IPPROTO_TCP;
79  aiHint.ai_family = AF_UNSPEC;
80 #ifdef WIN32
81  aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
82 #else
83  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
84 #endif
85  struct addrinfo *aiRes = nullptr;
86  int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
87  if (nErr)
88  return false;
89 
90  struct addrinfo *aiTrav = aiRes;
91  while (aiTrav != nullptr && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
92  {
93  CNetAddr resolved;
94  if (aiTrav->ai_family == AF_INET)
95  {
96  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
97  resolved = CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr);
98  }
99 
100  if (aiTrav->ai_family == AF_INET6)
101  {
102  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
103  struct sockaddr_in6* s6 = (struct sockaddr_in6*) aiTrav->ai_addr;
104  resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
105  }
106  /* Never allow resolving to an internal address. Consider any such result invalid */
107  if (!resolved.IsInternal()) {
108  vIP.push_back(resolved);
109  }
110 
111  aiTrav = aiTrav->ai_next;
112  }
113 
114  freeaddrinfo(aiRes);
115 
116  return (vIP.size() > 0);
117 }
118 
119 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
120 {
121  std::string strHost(pszName);
122  if (strHost.empty())
123  return false;
124  if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
125  {
126  strHost = strHost.substr(1, strHost.size() - 2);
127  }
128 
129  return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
130 }
131 
132 bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
133 {
134  std::vector<CNetAddr> vIP;
135  LookupHost(pszName, vIP, 1, fAllowLookup);
136  if(vIP.empty())
137  return false;
138  addr = vIP.front();
139  return true;
140 }
141 
142 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
143 {
144  if (pszName[0] == 0)
145  return false;
146  int port = portDefault;
147  std::string hostname = "";
148  SplitHostPort(std::string(pszName), port, hostname);
149 
150  std::vector<CNetAddr> vIP;
151  bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
152  if (!fRet)
153  return false;
154  vAddr.resize(vIP.size());
155  for (unsigned int i = 0; i < vIP.size(); i++)
156  vAddr[i] = CService(vIP[i], port);
157  return true;
158 }
159 
160 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
161 {
162  std::vector<CService> vService;
163  bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
164  if (!fRet)
165  return false;
166  addr = vService[0];
167  return true;
168 }
169 
170 CService LookupNumeric(const char *pszName, int portDefault)
171 {
172  CService addr;
173  // "1.2:345" will fail to resolve the ip, but will still set the port.
174  // If the ip fails to resolve, re-init the result.
175  if(!Lookup(pszName, addr, portDefault, false))
176  addr = CService();
177  return addr;
178 }
179 
180 struct timeval MillisToTimeval(int64_t nTimeout)
181 {
182  struct timeval timeout;
183  timeout.tv_sec = nTimeout / 1000;
184  timeout.tv_usec = (nTimeout % 1000) * 1000;
185  return timeout;
186 }
187 
189 enum SOCKSVersion: uint8_t {
190  SOCKS4 = 0x04,
191  SOCKS5 = 0x05
192 };
193 
195 enum SOCKS5Method: uint8_t {
196  NOAUTH = 0x00,
197  GSSAPI = 0x01,
198  USER_PASS = 0x02,
199  NO_ACCEPTABLE = 0xff,
200 };
201 
203 enum SOCKS5Command: uint8_t {
204  CONNECT = 0x01,
205  BIND = 0x02,
207 };
208 
210 enum SOCKS5Reply: uint8_t {
211  SUCCEEDED = 0x00,
212  GENFAILURE = 0x01,
213  NOTALLOWED = 0x02,
214  NETUNREACHABLE = 0x03,
216  CONNREFUSED = 0x05,
217  TTLEXPIRED = 0x06,
218  CMDUNSUPPORTED = 0x07,
220 };
221 
223 enum SOCKS5Atyp: uint8_t {
224  IPV4 = 0x01,
225  DOMAINNAME = 0x03,
226  IPV6 = 0x04,
227 };
228 
230 enum class IntrRecvError {
231  OK,
232  Timeout,
233  Disconnected,
234  NetworkError,
236 };
237 
249 static IntrRecvError InterruptibleRecv(uint8_t* data, size_t len, int timeout, const SOCKET& hSocket)
250 {
251  int64_t curTime = GetTimeMillis();
252  int64_t endTime = curTime + timeout;
253  // Maximum time to wait in one select call. It will take up until this time (in millis)
254  // to break off in case of an interruption.
255  const int64_t maxWait = 1000;
256  while (len > 0 && curTime < endTime) {
257  ssize_t ret = recv(hSocket, (char*)data, len, 0); // Optimistically try the recv first
258  if (ret > 0) {
259  len -= ret;
260  data += ret;
261  } else if (ret == 0) { // Unexpected disconnection
263  } else { // Other error or blocking
264  int nErr = WSAGetLastError();
265  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
266  if (!IsSelectableSocket(hSocket)) {
268  }
269  struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
270  fd_set fdset;
271  FD_ZERO(&fdset);
272  FD_SET(hSocket, &fdset);
273  int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
274  if (nRet == SOCKET_ERROR) {
276  }
277  } else {
279  }
280  }
281  if (interruptSocks5Recv)
283  curTime = GetTimeMillis();
284  }
285  return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
286 }
287 
290 {
291  std::string username;
292  std::string password;
293 };
294 
296 std::string Socks5ErrorString(uint8_t err)
297 {
298  switch(err) {
300  return "general failure";
302  return "connection not allowed";
304  return "network unreachable";
306  return "host unreachable";
308  return "connection refused";
310  return "TTL expired";
312  return "protocol error";
314  return "address type not supported";
315  default:
316  return "unknown";
317  }
318 }
319 
321 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
322 {
323  IntrRecvError recvr;
324  LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
325  if (strDest.size() > 255) {
326  CloseSocket(hSocket);
327  return error("Hostname too long");
328  }
329  // Accepted authentication methods
330  std::vector<uint8_t> vSocks5Init;
331  vSocks5Init.push_back(SOCKSVersion::SOCKS5);
332  if (auth) {
333  vSocks5Init.push_back(0x02); // Number of methods
334  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
335  vSocks5Init.push_back(SOCKS5Method::USER_PASS);
336  } else {
337  vSocks5Init.push_back(0x01); // Number of methods
338  vSocks5Init.push_back(SOCKS5Method::NOAUTH);
339  }
340  ssize_t ret = send(hSocket, (const char*)vSocks5Init.data(), vSocks5Init.size(), MSG_NOSIGNAL);
341  if (ret != (ssize_t)vSocks5Init.size()) {
342  CloseSocket(hSocket);
343  return error("Error sending to proxy");
344  }
345  uint8_t pchRet1[2];
346  if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
347  CloseSocket(hSocket);
348  LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() timeout or other failure\n", strDest, port);
349  return false;
350  }
351  if (pchRet1[0] != SOCKSVersion::SOCKS5) {
352  CloseSocket(hSocket);
353  return error("Proxy failed to initialize");
354  }
355  if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
356  // Perform username/password authentication (as described in RFC1929)
357  std::vector<uint8_t> vAuth;
358  vAuth.push_back(0x01); // Current (and only) version of user/pass subnegotiation
359  if (auth->username.size() > 255 || auth->password.size() > 255)
360  return error("Proxy username or password too long");
361  vAuth.push_back(auth->username.size());
362  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
363  vAuth.push_back(auth->password.size());
364  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
365  ret = send(hSocket, (const char*)vAuth.data(), vAuth.size(), MSG_NOSIGNAL);
366  if (ret != (ssize_t)vAuth.size()) {
367  CloseSocket(hSocket);
368  return error("Error sending authentication to proxy");
369  }
370  LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
371  uint8_t pchRetA[2];
372  if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
373  CloseSocket(hSocket);
374  return error("Error reading proxy authentication response");
375  }
376  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
377  CloseSocket(hSocket);
378  return error("Proxy authentication unsuccessful");
379  }
380  } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
381  // Perform no authentication
382  } else {
383  CloseSocket(hSocket);
384  return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
385  }
386  std::vector<uint8_t> vSocks5;
387  vSocks5.push_back(SOCKSVersion::SOCKS5); // VER protocol version
388  vSocks5.push_back(SOCKS5Command::CONNECT); // CMD CONNECT
389  vSocks5.push_back(0x00); // RSV Reserved must be 0
390  vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); // ATYP DOMAINNAME
391  vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
392  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
393  vSocks5.push_back((port >> 8) & 0xFF);
394  vSocks5.push_back((port >> 0) & 0xFF);
395  ret = send(hSocket, (const char*)vSocks5.data(), vSocks5.size(), MSG_NOSIGNAL);
396  if (ret != (ssize_t)vSocks5.size()) {
397  CloseSocket(hSocket);
398  return error("Error sending to proxy");
399  }
400  uint8_t pchRet2[4];
401  if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
402  CloseSocket(hSocket);
403  if (recvr == IntrRecvError::Timeout) {
404  /* If a timeout happens here, this effectively means we timed out while connecting
405  * to the remote node. This is very common for Tor, so do not print an
406  * error message. */
407  return false;
408  } else {
409  return error("Error while reading proxy response");
410  }
411  }
412  if (pchRet2[0] != SOCKSVersion::SOCKS5) {
413  CloseSocket(hSocket);
414  return error("Proxy failed to accept request");
415  }
416  if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
417  // Failures to connect to a peer that are not proxy errors
418  CloseSocket(hSocket);
419  LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, Socks5ErrorString(pchRet2[1]));
420  return false;
421  }
422  if (pchRet2[2] != 0x00) { // Reserved field must be 0
423  CloseSocket(hSocket);
424  return error("Error: malformed proxy response");
425  }
426  uint8_t pchRet3[256];
427  switch (pchRet2[3])
428  {
429  case SOCKS5Atyp::IPV4: recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
430  case SOCKS5Atyp::IPV6: recvr = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
432  {
433  recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
434  if (recvr != IntrRecvError::OK) {
435  CloseSocket(hSocket);
436  return error("Error reading from proxy");
437  }
438  int nRecv = pchRet3[0];
439  recvr = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
440  break;
441  }
442  default: CloseSocket(hSocket); return error("Error: malformed proxy response");
443  }
444  if (recvr != IntrRecvError::OK) {
445  CloseSocket(hSocket);
446  return error("Error reading from proxy");
447  }
448  if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != IntrRecvError::OK) {
449  CloseSocket(hSocket);
450  return error("Error reading from proxy");
451  }
452  LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
453  return true;
454 }
455 
456 bool ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
457 {
458  hSocketRet = INVALID_SOCKET;
459 
460  struct sockaddr_storage sockaddr;
461  socklen_t len = sizeof(sockaddr);
462  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
463  LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
464  return false;
465  }
466 
467  SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
468  if (hSocket == INVALID_SOCKET)
469  return false;
470 
471 #ifdef SO_NOSIGPIPE
472  int set = 1;
473  // Different way of disabling SIGPIPE on BSD
474  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
475 #endif
476 
477  //Disable Nagle's algorithm
478  SetSocketNoDelay(hSocket);
479 
480  // Set to non-blocking
481  if (!SetSocketNonBlocking(hSocket, true)) {
482  CloseSocket(hSocket);
483  return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
484  }
485 
486  if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
487  {
488  int nErr = WSAGetLastError();
489  // WSAEINVAL is here because some legacy version of winsock uses it
490  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
491  {
492  struct timeval timeout = MillisToTimeval(nTimeout);
493  fd_set fdset;
494  FD_ZERO(&fdset);
495  FD_SET(hSocket, &fdset);
496  int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
497  if (nRet == 0)
498  {
499  LogPrint(BCLog::NET, "connection to %s timeout\n", addrConnect.ToString());
500  CloseSocket(hSocket);
501  return false;
502  }
503  if (nRet == SOCKET_ERROR)
504  {
505  LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
506  CloseSocket(hSocket);
507  return false;
508  }
509  socklen_t nRetSize = sizeof(nRet);
510 #ifdef WIN32
511  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
512 #else
513  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
514 #endif
515  {
516  LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
517  CloseSocket(hSocket);
518  return false;
519  }
520  if (nRet != 0)
521  {
522  LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
523  CloseSocket(hSocket);
524  return false;
525  }
526  }
527 #ifdef WIN32
528  else if (WSAGetLastError() != WSAEISCONN)
529 #else
530  else
531 #endif
532  {
533  LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
534  CloseSocket(hSocket);
535  return false;
536  }
537  }
538 
539  hSocketRet = hSocket;
540  return true;
541 }
542 
543 bool SetProxy(enum Network net, const proxyType &addrProxy) {
544  assert(net >= 0 && net < NET_MAX);
545  if (!addrProxy.IsValid())
546  return false;
547  LOCK(cs_proxyInfos);
548  proxyInfo[net] = addrProxy;
549  return true;
550 }
551 
552 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
553  assert(net >= 0 && net < NET_MAX);
554  LOCK(cs_proxyInfos);
555  if (!proxyInfo[net].IsValid())
556  return false;
557  proxyInfoOut = proxyInfo[net];
558  return true;
559 }
560 
561 bool SetNameProxy(const proxyType &addrProxy) {
562  if (!addrProxy.IsValid())
563  return false;
564  LOCK(cs_proxyInfos);
565  nameProxy = addrProxy;
566  return true;
567 }
568 
569 bool GetNameProxy(proxyType &nameProxyOut) {
570  LOCK(cs_proxyInfos);
571  if(!nameProxy.IsValid())
572  return false;
573  nameProxyOut = nameProxy;
574  return true;
575 }
576 
578  LOCK(cs_proxyInfos);
579  return nameProxy.IsValid();
580 }
581 
582 bool IsProxy(const CNetAddr &addr) {
583  LOCK(cs_proxyInfos);
584  for (int i = 0; i < NET_MAX; i++) {
585  if (addr == (CNetAddr)proxyInfo[i].proxy)
586  return true;
587  }
588  return false;
589 }
590 
591 bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
592 {
593  SOCKET hSocket = INVALID_SOCKET;
594  // first connect to proxy server
595  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
596  if (outProxyConnectionFailed)
597  *outProxyConnectionFailed = true;
598  return false;
599  }
600  // do socks negotiation
601  if (proxy.randomize_credentials) {
602  ProxyCredentials random_auth;
603  static std::atomic_int counter(0);
604  random_auth.username = random_auth.password = strprintf("%i", counter++);
605  if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
606  return false;
607  } else {
608  if (!Socks5(strDest, (unsigned short)port, 0, hSocket))
609  return false;
610  }
611 
612  hSocketRet = hSocket;
613  return true;
614 }
615 bool LookupSubNet(const char* pszName, CSubNet& ret)
616 {
617  std::string strSubnet(pszName);
618  size_t slash = strSubnet.find_last_of('/');
619  std::vector<CNetAddr> vIP;
620 
621  std::string strAddress = strSubnet.substr(0, slash);
622  if (LookupHost(strAddress.c_str(), vIP, 1, false))
623  {
624  CNetAddr network = vIP[0];
625  if (slash != strSubnet.npos)
626  {
627  std::string strNetmask = strSubnet.substr(slash + 1);
628  int32_t n;
629  // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
630  if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
631  ret = CSubNet(network, n);
632  return ret.IsValid();
633  }
634  else // If not a valid number, try full netmask syntax
635  {
636  // Never allow lookup for netmask
637  if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
638  ret = CSubNet(network, vIP[0]);
639  return ret.IsValid();
640  }
641  }
642  }
643  else
644  {
645  ret = CSubNet(network);
646  return ret.IsValid();
647  }
648  }
649  return false;
650 }
651 
652 #ifdef WIN32
653 std::string NetworkErrorString(int err)
654 {
655  char buf[256];
656  buf[0] = 0;
657  if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
658  nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
659  buf, sizeof(buf), nullptr))
660  {
661  return strprintf("%s (%d)", buf, err);
662  }
663  else
664  {
665  return strprintf("Unknown error (%d)", err);
666  }
667 }
668 #else
669 std::string NetworkErrorString(int err)
670 {
671  char buf[256];
672  buf[0] = 0;
673  /* Too bad there are two incompatible implementations of the
674  * thread-safe strerror. */
675  const char *s;
676 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
677  s = strerror_r(err, buf, sizeof(buf));
678 #else /* POSIX variant always returns message in buffer */
679  s = buf;
680  if (strerror_r(err, buf, sizeof(buf)))
681  buf[0] = 0;
682 #endif
683  return strprintf("%s (%d)", s, err);
684 }
685 #endif
686 
687 bool CloseSocket(SOCKET& hSocket)
688 {
689  if (hSocket == INVALID_SOCKET)
690  return false;
691 #ifdef WIN32
692  int ret = closesocket(hSocket);
693 #else
694  int ret = close(hSocket);
695 #endif
696  hSocket = INVALID_SOCKET;
697  return ret != SOCKET_ERROR;
698 }
699 
700 bool SetSocketNonBlocking(const SOCKET& hSocket, bool fNonBlocking)
701 {
702  if (fNonBlocking) {
703 #ifdef WIN32
704  u_long nOne = 1;
705  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
706 #else
707  int fFlags = fcntl(hSocket, F_GETFL, 0);
708  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
709 #endif
710  return false;
711  }
712  } else {
713 #ifdef WIN32
714  u_long nZero = 0;
715  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
716 #else
717  int fFlags = fcntl(hSocket, F_GETFL, 0);
718  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
719 #endif
720  return false;
721  }
722  }
723 
724  return true;
725 }
726 
727 bool SetSocketNoDelay(const SOCKET& hSocket)
728 {
729  int set = 1;
730  int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
731  return rc == 0;
732 }
733 
734 void InterruptSocks5(bool interrupt)
735 {
736  interruptSocks5Recv = interrupt;
737 }
#define WSAEINPROGRESS
Definition: compat.h:60
Network unreachable.
Definition: netbase.cpp:216
SOCKS5Reply
Values defined for REP in RFC1928.
Definition: netbase.cpp:210
GSSAPI.
Definition: netbase.cpp:198
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET &hSocketRet, int nTimeout)
Definition: netbase.cpp:456
No authentication required.
Definition: netbase.cpp:197
#define strprintf
Definition: tinyformat.h:1054
Connection not allowed by ruleset.
Definition: netbase.cpp:214
CService LookupNumeric(const char *pszName, int portDefault)
Definition: netbase.cpp:170
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:569
bool IsInternal() const
Definition: netaddress.cpp:242
#define INVALID_SOCKET
Definition: compat.h:63
bool SetNameProxy(const proxyType &addrProxy)
Definition: netbase.cpp:561
#define WSAGetLastError()
Definition: compat.h:54
SOCKS5Command
Values defined for CMD in RFC1928.
Definition: netbase.cpp:203
std::string Socks5ErrorString(uint8_t err)
Convert SOCKS5 reply to an error message.
Definition: netbase.cpp:296
bool HaveNameProxy()
Definition: netbase.cpp:577
#define SOCKET_ERROR
Definition: compat.h:64
enum Network ParseNetwork(std::string net)
Definition: netbase.cpp:44
#define LogPrintf(...)
Definition: util.h:149
bool randomize_credentials
Definition: netbase.h:38
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
Username/password.
Definition: netbase.cpp:199
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Definition: netaddress.cpp:543
#define LOCK(cs)
Definition: sync.h:176
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:141
Credentials for proxy authentication.
Definition: netbase.cpp:289
IntrRecvError
Status codes that can be returned by InterruptibleRecv.
Definition: netbase.cpp:230
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:582
SOCKSVersion
SOCKS version.
Definition: netbase.cpp:189
Succeeded.
Definition: netbase.cpp:212
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, int port, SOCKET &hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:591
Network
Definition: netaddress.h:20
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:687
int nConnectTimeout
Definition: netbase.cpp:37
#define WSAEWOULDBLOCK
Definition: compat.h:57
SOCKS5Method
Values defined for METHOD in RFC1928.
Definition: netbase.cpp:195
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:615
unsigned int SOCKET
Definition: compat.h:52
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:543
bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking)
Disable or enable blocking-mode for a socket.
Definition: netbase.cpp:700
#define s6
Definition: sph_hamsi.c:218
struct timeval MillisToTimeval(int64_t nTimeout)
Convert milliseconds to a struct timeval for e.g.
Definition: netbase.cpp:180
#define LogPrint(category,...)
Definition: util.h:160
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:32
Network unreachable.
Definition: netbase.cpp:215
bool IsValid() const
Definition: netaddress.cpp:722
CService proxy
Definition: netbase.h:37
bool IsValid() const
Definition: netbase.h:35
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Connection refused.
Definition: netbase.cpp:217
#define WSAEINVAL
Definition: compat.h:55
bool SetSocketNoDelay(const SOCKET &hSocket)
Set the TCP_NODELAY flag on a socket.
Definition: netbase.cpp:727
int64_t GetTimeMillis()
Definition: utiltime.cpp:40
#define MSG_NOSIGNAL
Definition: netbase.cpp:30
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Definition: netbase.cpp:142
bool error(const char *fmt, const Args &... args)
Definition: util.h:168
bool SetSpecial(const std::string &strName)
Definition: netaddress.cpp:61
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:734
std::string password
Definition: netbase.cpp:292
std::string ToString() const
Definition: netaddress.cpp:597
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:552
std::string NetworkErrorString(int err)
Return readable error string for a network error code.
Definition: netbase.cpp:669
Command not supported.
Definition: netbase.cpp:219
TTL expired.
Definition: netbase.cpp:218
General failure.
Definition: netbase.cpp:213
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:52
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:119
std::string username
Definition: netbase.cpp:291
SOCKS5Atyp
Values defined for ATYPE in RFC1928.
Definition: netbase.cpp:223
bool fNameLookup
Definition: netbase.cpp:38
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:92