Dash Core  0.12.2.1
P2P Digital Currency
netbase.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 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.
5 
6 #ifdef HAVE_CONFIG_H
7 #include "config/dash-config.h"
8 #endif
9 
10 #include "netbase.h"
11 
12 #include "hash.h"
13 #include "sync.h"
14 #include "uint256.h"
15 #include "random.h"
16 #include "util.h"
17 #include "utilstrencodings.h"
18 
19 #include <atomic>
20 
21 #ifndef WIN32
22 #include <fcntl.h>
23 #endif
24 
25 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
26 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
27 
28 #if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
29 #define MSG_NOSIGNAL 0
30 #endif
31 
32 // Settings
38 
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);
42 
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;
49 }
50 
51 std::string GetNetworkName(enum Network net) {
52  switch(net)
53  {
54  case NET_IPV4: return "ipv4";
55  case NET_IPV6: return "ipv6";
56  case NET_TOR: return "onion";
57  default: return "";
58  }
59 }
60 
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;
72  }
73  }
74  if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
75  hostOut = in.substr(1, in.size()-2);
76  else
77  hostOut = in;
78 }
79 
80 bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
81 {
82  vIP.clear();
83 
84  {
85  CNetAddr addr;
86  if (addr.SetSpecial(std::string(pszName))) {
87  vIP.push_back(addr);
88  return true;
89  }
90  }
91 
92 #ifdef HAVE_GETADDRINFO_A
93  struct in_addr ipv4_addr;
94 #ifdef HAVE_INET_PTON
95  if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) {
96  vIP.push_back(CNetAddr(ipv4_addr));
97  return true;
98  }
99 
100  struct in6_addr ipv6_addr;
101  if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) {
102  vIP.push_back(CNetAddr(ipv6_addr));
103  return true;
104  }
105 #else
106  ipv4_addr.s_addr = inet_addr(pszName);
107  if (ipv4_addr.s_addr != INADDR_NONE) {
108  vIP.push_back(CNetAddr(ipv4_addr));
109  return true;
110  }
111 #endif
112 #endif
113 
114  struct addrinfo aiHint;
115  memset(&aiHint, 0, sizeof(struct addrinfo));
116  aiHint.ai_socktype = SOCK_STREAM;
117  aiHint.ai_protocol = IPPROTO_TCP;
118  aiHint.ai_family = AF_UNSPEC;
119 #ifdef WIN32
120  aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
121 #else
122  aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
123 #endif
124 
125  struct addrinfo *aiRes = NULL;
126 #ifdef HAVE_GETADDRINFO_A
127  struct gaicb gcb, *query = &gcb;
128  memset(query, 0, sizeof(struct gaicb));
129  gcb.ar_name = pszName;
130  gcb.ar_request = &aiHint;
131  int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL);
132  if (nErr)
133  return false;
134 
135  do {
136  // Should set the timeout limit to a reasonable value to avoid
137  // generating unnecessary checking call during the polling loop,
138  // while it can still response to stop request quick enough.
139  // 2 seconds looks fine in our situation.
140  struct timespec ts = { 2, 0 };
141  gai_suspend(&query, 1, &ts);
142  boost::this_thread::interruption_point();
143 
144  nErr = gai_error(query);
145  if (0 == nErr)
146  aiRes = query->ar_result;
147  } while (nErr == EAI_INPROGRESS);
148 #else
149  int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes);
150 #endif
151  if (nErr)
152  return false;
153 
154  struct addrinfo *aiTrav = aiRes;
155  while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions))
156  {
157  if (aiTrav->ai_family == AF_INET)
158  {
159  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
160  vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr));
161  }
162 
163  if (aiTrav->ai_family == AF_INET6)
164  {
165  assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
166  vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr));
167  }
168 
169  aiTrav = aiTrav->ai_next;
170  }
171 
172  freeaddrinfo(aiRes);
173 
174  return (vIP.size() > 0);
175 }
176 
177 bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
178 {
179  std::string strHost(pszName);
180  if (strHost.empty())
181  return false;
182  if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
183  {
184  strHost = strHost.substr(1, strHost.size() - 2);
185  }
186 
187  return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
188 }
189 
190 bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup)
191 {
192  std::vector<CNetAddr> vIP;
193  LookupHost(pszName, vIP, 1, fAllowLookup);
194  if(vIP.empty())
195  return false;
196  addr = vIP.front();
197  return true;
198 }
199 
200 bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
201 {
202  if (pszName[0] == 0)
203  return false;
204  int port = portDefault;
205  std::string hostname = "";
206  SplitHostPort(std::string(pszName), port, hostname);
207 
208  std::vector<CNetAddr> vIP;
209  bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
210  if (!fRet)
211  return false;
212  vAddr.resize(vIP.size());
213  for (unsigned int i = 0; i < vIP.size(); i++)
214  vAddr[i] = CService(vIP[i], port);
215  return true;
216 }
217 
218 bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup)
219 {
220  std::vector<CService> vService;
221  bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
222  if (!fRet)
223  return false;
224  addr = vService[0];
225  return true;
226 }
227 
228 CService LookupNumeric(const char *pszName, int portDefault)
229 {
230  CService addr;
231  // "1.2:345" will fail to resolve the ip, but will still set the port.
232  // If the ip fails to resolve, re-init the result.
233  if(!Lookup(pszName, addr, portDefault, false))
234  addr = CService();
235  return addr;
236 }
237 
238 struct timeval MillisToTimeval(int64_t nTimeout)
239 {
240  struct timeval timeout;
241  timeout.tv_sec = nTimeout / 1000;
242  timeout.tv_usec = (nTimeout % 1000) * 1000;
243  return timeout;
244 }
245 
257 bool static InterruptibleRecv(char* data, size_t len, int timeout, SOCKET& hSocket)
258 {
259  int64_t curTime = GetTimeMillis();
260  int64_t endTime = curTime + timeout;
261  // Maximum time to wait in one select call. It will take up until this time (in millis)
262  // to break off in case of an interruption.
263  const int64_t maxWait = 1000;
264  while (len > 0 && curTime < endTime) {
265  ssize_t ret = recv(hSocket, data, len, 0); // Optimistically try the recv first
266  if (ret > 0) {
267  len -= ret;
268  data += ret;
269  } else if (ret == 0) { // Unexpected disconnection
270  return false;
271  } else { // Other error or blocking
272  int nErr = WSAGetLastError();
273  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) {
274  if (!IsSelectableSocket(hSocket)) {
275  return false;
276  }
277  struct timeval tval = MillisToTimeval(std::min(endTime - curTime, maxWait));
278  fd_set fdset;
279  FD_ZERO(&fdset);
280  FD_SET(hSocket, &fdset);
281  int nRet = select(hSocket + 1, &fdset, NULL, NULL, &tval);
282  if (nRet == SOCKET_ERROR) {
283  return false;
284  }
285  } else {
286  return false;
287  }
288  }
290  return false;
291  curTime = GetTimeMillis();
292  }
293  return len == 0;
294 }
295 
297 {
298  std::string username;
299  std::string password;
300 };
301 
303 static bool Socks5(const std::string& strDest, int port, const ProxyCredentials *auth, SOCKET& hSocket)
304 {
305  LogPrintf("SOCKS5 connecting %s\n", strDest);
306  if (strDest.size() > 255) {
307  CloseSocket(hSocket);
308  return error("Hostname too long");
309  }
310  // Accepted authentication methods
311  std::vector<uint8_t> vSocks5Init;
312  vSocks5Init.push_back(0x05);
313  if (auth) {
314  vSocks5Init.push_back(0x02); // # METHODS
315  vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
316  vSocks5Init.push_back(0x02); // X'02' USERNAME/PASSWORD (RFC1929)
317  } else {
318  vSocks5Init.push_back(0x01); // # METHODS
319  vSocks5Init.push_back(0x00); // X'00' NO AUTHENTICATION REQUIRED
320  }
321  ssize_t ret = send(hSocket, (const char*)begin_ptr(vSocks5Init), vSocks5Init.size(), MSG_NOSIGNAL);
322  if (ret != (ssize_t)vSocks5Init.size()) {
323  CloseSocket(hSocket);
324  return error("Error sending to proxy");
325  }
326  char pchRet1[2];
327  if (!InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
328  CloseSocket(hSocket);
329  return error("Error reading proxy response");
330  }
331  if (pchRet1[0] != 0x05) {
332  CloseSocket(hSocket);
333  return error("Proxy failed to initialize");
334  }
335  if (pchRet1[1] == 0x02 && auth) {
336  // Perform username/password authentication (as described in RFC1929)
337  std::vector<uint8_t> vAuth;
338  vAuth.push_back(0x01);
339  if (auth->username.size() > 255 || auth->password.size() > 255)
340  return error("Proxy username or password too long");
341  vAuth.push_back(auth->username.size());
342  vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
343  vAuth.push_back(auth->password.size());
344  vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
345  ret = send(hSocket, (const char*)begin_ptr(vAuth), vAuth.size(), MSG_NOSIGNAL);
346  if (ret != (ssize_t)vAuth.size()) {
347  CloseSocket(hSocket);
348  return error("Error sending authentication to proxy");
349  }
350  LogPrint("proxy", "SOCKS5 sending proxy authentication %s:%s\n", auth->username, auth->password);
351  char pchRetA[2];
352  if (!InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
353  CloseSocket(hSocket);
354  return error("Error reading proxy authentication response");
355  }
356  if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
357  CloseSocket(hSocket);
358  return error("Proxy authentication unsuccessful");
359  }
360  } else if (pchRet1[1] == 0x00) {
361  // Perform no authentication
362  } else {
363  CloseSocket(hSocket);
364  return error("Proxy requested wrong authentication method %02x", pchRet1[1]);
365  }
366  std::vector<uint8_t> vSocks5;
367  vSocks5.push_back(0x05); // VER protocol version
368  vSocks5.push_back(0x01); // CMD CONNECT
369  vSocks5.push_back(0x00); // RSV Reserved
370  vSocks5.push_back(0x03); // ATYP DOMAINNAME
371  vSocks5.push_back(strDest.size()); // Length<=255 is checked at beginning of function
372  vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
373  vSocks5.push_back((port >> 8) & 0xFF);
374  vSocks5.push_back((port >> 0) & 0xFF);
375  ret = send(hSocket, (const char*)begin_ptr(vSocks5), vSocks5.size(), MSG_NOSIGNAL);
376  if (ret != (ssize_t)vSocks5.size()) {
377  CloseSocket(hSocket);
378  return error("Error sending to proxy");
379  }
380  char pchRet2[4];
381  if (!InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) {
382  CloseSocket(hSocket);
383  return error("Error reading proxy response");
384  }
385  if (pchRet2[0] != 0x05) {
386  CloseSocket(hSocket);
387  return error("Proxy failed to accept request");
388  }
389  if (pchRet2[1] != 0x00) {
390  CloseSocket(hSocket);
391  switch (pchRet2[1])
392  {
393  case 0x01: return error("Proxy error: general failure");
394  case 0x02: return error("Proxy error: connection not allowed");
395  case 0x03: return error("Proxy error: network unreachable");
396  case 0x04: return error("Proxy error: host unreachable");
397  case 0x05: return error("Proxy error: connection refused");
398  case 0x06: return error("Proxy error: TTL expired");
399  case 0x07: return error("Proxy error: protocol error");
400  case 0x08: return error("Proxy error: address type not supported");
401  default: return error("Proxy error: unknown");
402  }
403  }
404  if (pchRet2[2] != 0x00) {
405  CloseSocket(hSocket);
406  return error("Error: malformed proxy response");
407  }
408  char pchRet3[256];
409  switch (pchRet2[3])
410  {
411  case 0x01: ret = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); break;
412  case 0x04: ret = InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); break;
413  case 0x03:
414  {
415  ret = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
416  if (!ret) {
417  CloseSocket(hSocket);
418  return error("Error reading from proxy");
419  }
420  int nRecv = pchRet3[0];
421  ret = InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
422  break;
423  }
424  default: CloseSocket(hSocket); return error("Error: malformed proxy response");
425  }
426  if (!ret) {
427  CloseSocket(hSocket);
428  return error("Error reading from proxy");
429  }
430  if (!InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) {
431  CloseSocket(hSocket);
432  return error("Error reading from proxy");
433  }
434  LogPrintf("SOCKS5 connected %s\n", strDest);
435  return true;
436 }
437 
438 bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRet, int nTimeout)
439 {
440  hSocketRet = INVALID_SOCKET;
441 
442  struct sockaddr_storage sockaddr;
443  socklen_t len = sizeof(sockaddr);
444  if (!addrConnect.GetSockAddr((struct sockaddr*)&sockaddr, &len)) {
445  LogPrintf("Cannot connect to %s: unsupported network\n", addrConnect.ToString());
446  return false;
447  }
448 
449  SOCKET hSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
450  if (hSocket == INVALID_SOCKET)
451  return false;
452 
453  int set = 1;
454 #ifdef SO_NOSIGPIPE
455  // Different way of disabling SIGPIPE on BSD
456  setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
457 #endif
458 
459  //Disable Nagle's algorithm
460 #ifdef WIN32
461  setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (const char*)&set, sizeof(int));
462 #else
463  setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (void*)&set, sizeof(int));
464 #endif
465 
466  // Set to non-blocking
467  if (!SetSocketNonBlocking(hSocket, true))
468  return error("ConnectSocketDirectly: Setting socket to non-blocking failed, error %s\n", NetworkErrorString(WSAGetLastError()));
469 
470  if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
471  {
472  int nErr = WSAGetLastError();
473  // WSAEINVAL is here because some legacy version of winsock uses it
474  if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL)
475  {
476  struct timeval timeout = MillisToTimeval(nTimeout);
477  fd_set fdset;
478  FD_ZERO(&fdset);
479  FD_SET(hSocket, &fdset);
480  int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
481  if (nRet == 0)
482  {
483  LogPrint("net", "connection to %s timeout\n", addrConnect.ToString());
484  CloseSocket(hSocket);
485  return false;
486  }
487  if (nRet == SOCKET_ERROR)
488  {
489  LogPrintf("select() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
490  CloseSocket(hSocket);
491  return false;
492  }
493  socklen_t nRetSize = sizeof(nRet);
494 #ifdef WIN32
495  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
496 #else
497  if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
498 #endif
499  {
500  LogPrintf("getsockopt() for %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
501  CloseSocket(hSocket);
502  return false;
503  }
504  if (nRet != 0)
505  {
506  LogPrintf("connect() to %s failed after select(): %s\n", addrConnect.ToString(), NetworkErrorString(nRet));
507  CloseSocket(hSocket);
508  return false;
509  }
510  }
511 #ifdef WIN32
512  else if (WSAGetLastError() != WSAEISCONN)
513 #else
514  else
515 #endif
516  {
517  LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), NetworkErrorString(WSAGetLastError()));
518  CloseSocket(hSocket);
519  return false;
520  }
521  }
522 
523  hSocketRet = hSocket;
524  return true;
525 }
526 
527 bool SetProxy(enum Network net, const proxyType &addrProxy) {
528  assert(net >= 0 && net < NET_MAX);
529  if (!addrProxy.IsValid())
530  return false;
532  proxyInfo[net] = addrProxy;
533  return true;
534 }
535 
536 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
537  assert(net >= 0 && net < NET_MAX);
539  if (!proxyInfo[net].IsValid())
540  return false;
541  proxyInfoOut = proxyInfo[net];
542  return true;
543 }
544 
545 bool SetNameProxy(const proxyType &addrProxy) {
546  if (!addrProxy.IsValid())
547  return false;
549  nameProxy = addrProxy;
550  return true;
551 }
552 
553 bool GetNameProxy(proxyType &nameProxyOut) {
555  if(!nameProxy.IsValid())
556  return false;
557  nameProxyOut = nameProxy;
558  return true;
559 }
560 
563  return nameProxy.IsValid();
564 }
565 
566 bool IsProxy(const CNetAddr &addr) {
568  for (int i = 0; i < NET_MAX; i++) {
569  if (addr == (CNetAddr)proxyInfo[i].proxy)
570  return true;
571  }
572  return false;
573 }
574 
575 static bool ConnectThroughProxy(const proxyType &proxy, const std::string& strDest, int port, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
576 {
577  SOCKET hSocket = INVALID_SOCKET;
578  // first connect to proxy server
579  if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
580  if (outProxyConnectionFailed)
581  *outProxyConnectionFailed = true;
582  return false;
583  }
584  // do socks negotiation
585  if (proxy.randomize_credentials) {
586  ProxyCredentials random_auth;
587  random_auth.username = strprintf("%i", insecure_rand());
588  random_auth.password = strprintf("%i", insecure_rand());
589  if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket))
590  return false;
591  } else {
592  if (!Socks5(strDest, (unsigned short)port, 0, hSocket))
593  return false;
594  }
595 
596  hSocketRet = hSocket;
597  return true;
598 }
599 
600 bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
601 {
602  proxyType proxy;
603  if (outProxyConnectionFailed)
604  *outProxyConnectionFailed = false;
605 
606  if (GetProxy(addrDest.GetNetwork(), proxy))
607  return ConnectThroughProxy(proxy, addrDest.ToStringIP(), addrDest.GetPort(), hSocketRet, nTimeout, outProxyConnectionFailed);
608  else // no proxy needed (none set for target network)
609  return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout);
610 }
611 
612 bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
613 {
614  std::string strDest;
615  int port = portDefault;
616 
617  if (outProxyConnectionFailed)
618  *outProxyConnectionFailed = false;
619 
620  SplitHostPort(std::string(pszDest), port, strDest);
621 
624 
625  std::vector<CService> addrResolved;
626  if (Lookup(strDest.c_str(), addrResolved, port, fNameLookup && !HaveNameProxy(), 256)) {
627  if (addrResolved.size() > 0) {
628  addr = addrResolved[GetRand(addrResolved.size())];
629  return ConnectSocket(addr, hSocketRet, nTimeout);
630  }
631  }
632 
633  addr = CService();
634 
635  if (!HaveNameProxy())
636  return false;
637  return ConnectThroughProxy(nameProxy, strDest, port, hSocketRet, nTimeout, outProxyConnectionFailed);
638 }
639 
640 bool LookupSubNet(const char* pszName, CSubNet& ret)
641 {
642  std::string strSubnet(pszName);
643  size_t slash = strSubnet.find_last_of('/');
644  std::vector<CNetAddr> vIP;
645 
646  std::string strAddress = strSubnet.substr(0, slash);
647  if (LookupHost(strAddress.c_str(), vIP, 1, false))
648  {
649  CNetAddr network = vIP[0];
650  if (slash != strSubnet.npos)
651  {
652  std::string strNetmask = strSubnet.substr(slash + 1);
653  int32_t n;
654  // IPv4 addresses start at offset 12, and first 12 bytes must match, so just offset n
655  if (ParseInt32(strNetmask, &n)) { // If valid number, assume /24 syntax
656  ret = CSubNet(network, n);
657  return ret.IsValid();
658  }
659  else // If not a valid number, try full netmask syntax
660  {
661  // Never allow lookup for netmask
662  if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
663  ret = CSubNet(network, vIP[0]);
664  return ret.IsValid();
665  }
666  }
667  }
668  else
669  {
670  ret = CSubNet(network);
671  return ret.IsValid();
672  }
673  }
674  return false;
675 }
676 
677 #ifdef WIN32
678 std::string NetworkErrorString(int err)
679 {
680  char buf[256];
681  buf[0] = 0;
682  if(FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
683  NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
684  buf, sizeof(buf), NULL))
685  {
686  return strprintf("%s (%d)", buf, err);
687  }
688  else
689  {
690  return strprintf("Unknown error (%d)", err);
691  }
692 }
693 #else
694 std::string NetworkErrorString(int err)
695 {
696  char buf[256];
697  const char *s = buf;
698  buf[0] = 0;
699  /* Too bad there are two incompatible implementations of the
700  * thread-safe strerror. */
701 #ifdef STRERROR_R_CHAR_P /* GNU variant can return a pointer outside the passed buffer */
702  s = strerror_r(err, buf, sizeof(buf));
703 #else /* POSIX variant always returns message in buffer */
704  if (strerror_r(err, buf, sizeof(buf)))
705  buf[0] = 0;
706 #endif
707  return strprintf("%s (%d)", s, err);
708 }
709 #endif
710 
711 bool CloseSocket(SOCKET& hSocket)
712 {
713  if (hSocket == INVALID_SOCKET)
714  return false;
715 #ifdef WIN32
716  int ret = closesocket(hSocket);
717 #else
718  int ret = close(hSocket);
719 #endif
720  hSocket = INVALID_SOCKET;
721  return ret != SOCKET_ERROR;
722 }
723 
724 bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking)
725 {
726  if (fNonBlocking) {
727 #ifdef WIN32
728  u_long nOne = 1;
729  if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
730 #else
731  int fFlags = fcntl(hSocket, F_GETFL, 0);
732  if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
733 #endif
734  CloseSocket(hSocket);
735  return false;
736  }
737  } else {
738 #ifdef WIN32
739  u_long nZero = 0;
740  if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
741 #else
742  int fFlags = fcntl(hSocket, F_GETFL, 0);
743  if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
744 #endif
745  CloseSocket(hSocket);
746  return false;
747  }
748  }
749 
750  return true;
751 }
752 
753 void InterruptSocks5(bool interrupt)
754 {
755  interruptSocks5Recv = interrupt;
756 }
static bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, int port, SOCKET &hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:575
#define WSAEINPROGRESS
Definition: compat.h:60
bool randomize_credentials
Definition: netbase.h:37
static bool ConnectSocketDirectly(const CService &addrConnect, SOCKET &hSocketRet, int nTimeout)
Definition: netbase.cpp:438
bool IsValid() const
Definition: netbase.h:34
#define strprintf
Definition: tinyformat.h:1011
std::string ToStringIP(bool fUseGetnameinfo=true) const
Definition: netaddress.cpp:241
static bool InterruptibleRecv(char *data, size_t len, int timeout, SOCKET &hSocket)
Definition: netbase.cpp:257
CService LookupNumeric(const char *pszName, int portDefault)
Definition: netbase.cpp:228
static bool Socks5(const std::string &strDest, int port, const ProxyCredentials *auth, SOCKET &hSocket)
Definition: netbase.cpp:303
bool GetNameProxy(proxyType &nameProxyOut)
Definition: netbase.cpp:553
u_int SOCKET
Definition: compat.h:52
std::string ToString(bool fUseGetnameinfo=true) const
Definition: netaddress.cpp:568
#define INVALID_SOCKET
Definition: compat.h:63
bool SetNameProxy(const proxyType &addrProxy)
Definition: netbase.cpp:545
#define WSAGetLastError()
Definition: compat.h:54
static uint32_t insecure_rand(void)
Definition: random.h:42
bool ConnectSocketByName(CService &addr, SOCKET &hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:612
static CCriticalSection cs_proxyInfos
Definition: netbase.cpp:35
CService proxy
Definition: netbase.h:36
static const int SOCKS5_RECV_TIMEOUT
Definition: netbase.cpp:40
unsigned short GetPort() const
Definition: netaddress.cpp:495
bool SetSocketNonBlocking(SOCKET &hSocket, bool fNonBlocking)
Definition: netbase.cpp:724
bool HaveNameProxy()
Definition: netbase.cpp:561
#define SOCKET_ERROR
Definition: compat.h:64
static bool IsSelectableSocket(SOCKET s)
Definition: compat.h:96
enum Network ParseNetwork(std::string net)
Definition: netbase.cpp:43
#define LogPrintf(...)
Definition: util.h:98
static bool LookupIntern(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:80
bool ParseInt32(const std::string &str, int32_t *out)
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
#define MSG_NOSIGNAL
Definition: compat.h:78
bool ConnectSocket(const CService &addrDest, SOCKET &hSocketRet, int nTimeout, bool *outProxyConnectionFailed)
Definition: netbase.cpp:600
static bool error(const char *format)
Definition: util.h:131
bool IsProxy(const CNetAddr &addr)
Definition: netbase.cpp:566
Network
Definition: netaddress.h:19
static std::atomic< bool > interruptSocks5Recv(false)
static const int DEFAULT_NAME_LOOKUP
-dns default
Definition: netbase.h:26
bool CloseSocket(SOCKET &hSocket)
Definition: netbase.cpp:711
int nConnectTimeout
Definition: netbase.cpp:36
#define WSAEWOULDBLOCK
Definition: compat.h:57
V::value_type * begin_ptr(V &v)
Definition: serialize.h:54
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:640
bool SetProxy(enum Network net, const proxyType &addrProxy)
Definition: netbase.cpp:527
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Definition: netbase.cpp:61
struct timeval MillisToTimeval(int64_t nTimeout)
Definition: netbase.cpp:238
static proxyType proxyInfo[NET_MAX]
Definition: netbase.cpp:33
bool IsValid() const
Definition: netaddress.cpp:698
#define WSAEINVAL
Definition: compat.h:55
int64_t GetTimeMillis()
Definition: utiltime.cpp:34
static const int DEFAULT_CONNECT_TIMEOUT
-timeout default
Definition: netbase.h:24
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Definition: netbase.cpp:200
bool SetSpecial(const std::string &strName)
Definition: netaddress.cpp:44
void InterruptSocks5(bool interrupt)
Definition: netbase.cpp:753
bool GetProxy(enum Network net, proxyType &proxyInfoOut)
Definition: netbase.cpp:536
std::string NetworkErrorString(int err)
Definition: netbase.cpp:694
std::string GetNetworkName(enum Network net)
Definition: netbase.cpp:51
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:177
enum Network GetNetwork() const
Definition: netaddress.cpp:227
int port
Definition: zmq_sub.py:8
bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const
Definition: netaddress.cpp:515
std::string password
Definition: netbase.cpp:299
std::string username
Definition: netbase.cpp:298
static proxyType nameProxy
Definition: netbase.cpp:34
bool fNameLookup
Definition: netbase.cpp:37
uint64_t GetRand(uint64_t nMax)
Definition: random.cpp:94