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