]> Git Repo - VerusCoin.git/blame - src/net.cpp
Fix bad merge: getaccountaddress was broken for new accounts
[VerusCoin.git] / src / net.cpp
CommitLineData
0a61b0df 1// Copyright (c) 2009-2010 Satoshi Nakamoto
b2120e22 2// Copyright (c) 2011 The Bitcoin developers
0a61b0df 3// Distributed under the MIT/X11 software license, see the accompanying
4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6#include "headers.h"
f23f9a03 7#include "irc.h"
1512d5ce 8#include "db.h"
40c2614e 9#include "net.h"
edd309e5 10#include "init.h"
fdd7d047 11#include "strlcpy.h"
0a61b0df 12
013df1cc
MC
13#ifdef __WXMSW__
14#include <string.h>
15#endif
16
8bb5edc1
MC
17#ifdef USE_UPNP
18#include <miniupnpc/miniwget.h>
19#include <miniupnpc/miniupnpc.h>
20#include <miniupnpc/upnpcommands.h>
21#include <miniupnpc/upnperrors.h>
22#endif
23
223b6f1b
WL
24using namespace std;
25using namespace boost;
26
0a61b0df 27static const int MAX_OUTBOUND_CONNECTIONS = 8;
28
29void ThreadMessageHandler2(void* parg);
30void ThreadSocketHandler2(void* parg);
31void ThreadOpenConnections2(void* parg);
8bb5edc1
MC
32#ifdef USE_UPNP
33void ThreadMapPort2(void* parg);
34#endif
0a61b0df 35bool OpenNetworkConnection(const CAddress& addrConnect);
36
37
38
39
40
41//
42// Global state variables
43//
44bool fClient = false;
a6a5bb7c 45bool fAllowDNS = false;
0a61b0df 46uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
a6a5bb7c 47CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
99860de3 48static CNode* pnodeLocalHost = NULL;
0a61b0df 49uint64 nLocalHostNonce = 0;
50array<int, 10> vnThreadsRunning;
99860de3 51static SOCKET hListenSocket = INVALID_SOCKET;
0a61b0df 52
53vector<CNode*> vNodes;
54CCriticalSection cs_vNodes;
55map<vector<unsigned char>, CAddress> mapAddresses;
56CCriticalSection cs_mapAddresses;
57map<CInv, CDataStream> mapRelay;
58deque<pair<int64, CInv> > vRelayExpiration;
59CCriticalSection cs_mapRelay;
60map<CInv, int64> mapAlreadyAskedFor;
61
62// Settings
63int fUseProxy = false;
76d660eb 64int nConnectTimeout = 5000;
a6a5bb7c 65CAddress addrProxy("127.0.0.1",9050);
0a61b0df 66
67
68
69
00bcfe0b
GA
70unsigned short GetListenPort()
71{
72 return (unsigned short)(GetArg("-port", GetDefaultPort()));
73}
0a61b0df 74
75void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
76{
77 // Filter out duplicate requests
78 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
79 return;
80 pindexLastGetBlocksBegin = pindexBegin;
81 hashLastGetBlocksEnd = hashEnd;
82
83 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
84}
85
86
87
88
89
76d660eb 90bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
0a61b0df 91{
92 hSocketRet = INVALID_SOCKET;
93
94 SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
95 if (hSocket == INVALID_SOCKET)
96 return false;
ec93a0e2 97#ifdef SO_NOSIGPIPE
0a61b0df 98 int set = 1;
99 setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
100#endif
101
482cb656 102 bool fProxy = (fUseProxy && addrConnect.IsRoutable());
0a61b0df 103 struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
104
76d660eb
PW
105#ifdef __WXMSW__
106 u_long fNonblock = 1;
107 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
108#else
109 int fFlags = fcntl(hSocket, F_GETFL, 0);
110 if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
111#endif
112 {
113 closesocket(hSocket);
114 return false;
115 }
116
117
0a61b0df 118 if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
76d660eb
PW
119 {
120 // WSAEINVAL is here because some legacy version of winsock uses it
121 if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
122 {
123 struct timeval timeout;
124 timeout.tv_sec = nTimeout / 1000;
125 timeout.tv_usec = (nTimeout % 1000) * 1000;
126
127 fd_set fdset;
128 FD_ZERO(&fdset);
129 FD_SET(hSocket, &fdset);
130 int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
131 if (nRet == 0)
132 {
133 printf("connection timeout\n");
134 closesocket(hSocket);
135 return false;
136 }
137 if (nRet == SOCKET_ERROR)
138 {
139 printf("select() for connection failed: %i\n",WSAGetLastError());
140 closesocket(hSocket);
141 return false;
142 }
143 socklen_t nRetSize = sizeof(nRet);
144#ifdef __WXMSW__
145 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
146#else
147 if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
148#endif
149 {
150 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
151 closesocket(hSocket);
152 return false;
153 }
154 if (nRet != 0)
155 {
013df1cc 156 printf("connect() failed after select(): %s\n",strerror(nRet));
76d660eb
PW
157 closesocket(hSocket);
158 return false;
159 }
160 }
161#ifdef __WXMSW__
162 else if (WSAGetLastError() != WSAEISCONN)
163#else
164 else
165#endif
166 {
ecd3e728 167 printf("connect() failed: %i\n",WSAGetLastError());
76d660eb
PW
168 closesocket(hSocket);
169 return false;
170 }
171 }
172
173 /*
174 this isn't even strictly necessary
175 CNode::ConnectNode immediately turns the socket back to non-blocking
176 but we'll turn it back to blocking just in case
177 */
178#ifdef __WXMSW__
179 fNonblock = 0;
180 if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
181#else
182 fFlags = fcntl(hSocket, F_GETFL, 0);
183 if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
184#endif
0a61b0df 185 {
186 closesocket(hSocket);
187 return false;
188 }
189
190 if (fProxy)
191 {
a6a5bb7c 192 printf("proxy connecting %s\n", addrConnect.ToString().c_str());
0a61b0df 193 char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
194 memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
195 memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
196 char* pszSocks4 = pszSocks4IP;
197 int nSize = sizeof(pszSocks4IP);
198
199 int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
200 if (ret != nSize)
201 {
202 closesocket(hSocket);
203 return error("Error sending to proxy");
204 }
205 char pchRet[8];
206 if (recv(hSocket, pchRet, 8, 0) != 8)
207 {
208 closesocket(hSocket);
209 return error("Error reading proxy response");
210 }
211 if (pchRet[1] != 0x5a)
212 {
213 closesocket(hSocket);
214 if (pchRet[1] != 0x5b)
215 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
216 return false;
217 }
a6a5bb7c 218 printf("proxy connected %s\n", addrConnect.ToString().c_str());
0a61b0df 219 }
220
221 hSocketRet = hSocket;
222 return true;
223}
224
a6a5bb7c
PW
225// portDefault is in host order
226bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
227{
228 vaddr.clear();
545a679a
PW
229 if (pszName[0] == 0)
230 return false;
a6a5bb7c
PW
231 int port = portDefault;
232 char psz[256];
233 char *pszHost = psz;
234 strlcpy(psz, pszName, sizeof(psz));
235 if (fAllowPort)
236 {
237 char* pszColon = strrchr(psz+1,':');
238 char *pszPortEnd = NULL;
239 int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
240 if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
241 {
242 if (psz[0] == '[' && pszColon[-1] == ']')
243 {
244 // Future: enable IPv6 colon-notation inside []
245 pszHost = psz+1;
246 pszColon[-1] = 0;
247 }
248 else
249 pszColon[0] = 0;
250 port = portParsed;
251 if (port < 0 || port > USHRT_MAX)
252 port = USHRT_MAX;
253 }
254 }
255
545a679a
PW
256 unsigned int addrIP = inet_addr(pszHost);
257 if (addrIP != INADDR_NONE)
a6a5bb7c
PW
258 {
259 // valid IP address passed
545a679a 260 vaddr.push_back(CAddress(addrIP, port, nServices));
a6a5bb7c
PW
261 return true;
262 }
263
264 if (!fAllowLookup)
265 return false;
266
267 struct hostent* phostent = gethostbyname(pszHost);
268 if (!phostent)
269 return false;
270
271 if (phostent->h_addrtype != AF_INET)
272 return false;
0a61b0df 273
a6a5bb7c
PW
274 char** ppAddr = phostent->h_addr_list;
275 while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
276 {
277 CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
278 if (addr.IsValid())
279 vaddr.push_back(addr);
280 ppAddr++;
281 }
282
283 return (vaddr.size() > 0);
284}
285
286// portDefault is in host order
287bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
288{
289 vector<CAddress> vaddr;
290 bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
291 if (fRet)
292 addr = vaddr[0];
293 return fRet;
294}
0a61b0df 295
296bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
297{
298 SOCKET hSocket;
299 if (!ConnectSocket(addrConnect, hSocket))
300 return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
301
302 send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
303
304 string strLine;
305 while (RecvLine(hSocket, strLine))
306 {
222e3de4 307 if (strLine.empty()) // HTTP response is separated from headers by blank line
0a61b0df 308 {
309 loop
310 {
311 if (!RecvLine(hSocket, strLine))
312 {
313 closesocket(hSocket);
314 return false;
315 }
222e3de4 316 if (pszKeyword == NULL)
317 break;
0a61b0df 318 if (strLine.find(pszKeyword) != -1)
319 {
320 strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
321 break;
322 }
323 }
324 closesocket(hSocket);
c891967b 325 if (strLine.find("<") != -1)
0a61b0df 326 strLine = strLine.substr(0, strLine.find("<"));
327 strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
328 while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
329 strLine.resize(strLine.size()-1);
a6a5bb7c 330 CAddress addr(strLine,0,true);
0a61b0df 331 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
332 if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
333 return false;
334 ipRet = addr.ip;
335 return true;
336 }
337 }
338 closesocket(hSocket);
339 return error("GetMyExternalIP() : connection closed");
340}
341
629e37dd 342// We now get our external IP from the IRC server first and only use this as a backup
0a61b0df 343bool GetMyExternalIP(unsigned int& ipRet)
344{
345 CAddress addrConnect;
346 const char* pszGet;
347 const char* pszKeyword;
348
349 if (fUseProxy)
350 return false;
351
352 for (int nLookup = 0; nLookup <= 1; nLookup++)
353 for (int nHost = 1; nHost <= 2; nHost++)
354 {
629e37dd 355 // We should be phasing out our use of sites like these. If we need
356 // replacements, we should ask for volunteers to put this simple
357 // php file on their webserver that prints the client IP:
358 // <?php echo $_SERVER["REMOTE_ADDR"]; ?>
0a61b0df 359 if (nHost == 1)
360 {
a6a5bb7c 361 addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
0a61b0df 362
363 if (nLookup == 1)
364 {
a6a5bb7c
PW
365 CAddress addrIP("checkip.dyndns.org", 80, true);
366 if (addrIP.IsValid())
367 addrConnect = addrIP;
0a61b0df 368 }
369
683bcb91 370 pszGet = "GET / HTTP/1.1\r\n"
371 "Host: checkip.dyndns.org\r\n"
372 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
0a61b0df 373 "Connection: close\r\n"
374 "\r\n";
375
683bcb91 376 pszKeyword = "Address:";
0a61b0df 377 }
378 else if (nHost == 2)
379 {
a6a5bb7c 380 addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
0a61b0df 381
382 if (nLookup == 1)
383 {
a6a5bb7c
PW
384 CAddress addrIP("www.showmyip.com", 80, true);
385 if (addrIP.IsValid())
386 addrConnect = addrIP;
0a61b0df 387 }
388
683bcb91 389 pszGet = "GET /simple/ HTTP/1.1\r\n"
390 "Host: www.showmyip.com\r\n"
0a61b0df 391 "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
392 "Connection: close\r\n"
393 "\r\n";
394
683bcb91 395 pszKeyword = NULL; // Returns just IP address
0a61b0df 396 }
397
398 if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
399 return true;
400 }
401
402 return false;
403}
404
629e37dd 405void ThreadGetMyExternalIP(void* parg)
406{
407 // Wait for IRC to get it first
408 if (!GetBoolArg("-noirc"))
409 {
410 for (int i = 0; i < 2 * 60; i++)
411 {
412 Sleep(1000);
413 if (fGotExternalIP || fShutdown)
414 return;
415 }
416 }
417
418 // Fallback in case IRC fails to get it
419 if (GetMyExternalIP(addrLocalHost.ip))
420 {
421 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
422 if (addrLocalHost.IsRoutable())
423 {
424 // If we already connected to a few before we had our IP, go back and addr them.
425 // setAddrKnown automatically filters any duplicate sends.
426 CAddress addr(addrLocalHost);
427 addr.nTime = GetAdjustedTime();
428 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 429 BOOST_FOREACH(CNode* pnode, vNodes)
629e37dd 430 pnode->PushAddress(addr);
431 }
432 }
433}
434
0a61b0df 435
436
437
438
8c414691 439bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
0a61b0df 440{
441 if (!addr.IsRoutable())
442 return false;
443 if (addr.ip == addrLocalHost.ip)
444 return false;
c891967b 445 addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
0a61b0df 446 CRITICAL_BLOCK(cs_mapAddresses)
447 {
448 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
449 if (it == mapAddresses.end())
450 {
451 // New address
a6a5bb7c 452 printf("AddAddress(%s)\n", addr.ToString().c_str());
0a61b0df 453 mapAddresses.insert(make_pair(addr.GetKey(), addr));
8c414691
PV
454 if (pAddrDB)
455 pAddrDB->WriteAddress(addr);
456 else
457 CAddrDB().WriteAddress(addr);
0a61b0df 458 return true;
459 }
460 else
461 {
462 bool fUpdated = false;
463 CAddress& addrFound = (*it).second;
464 if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
465 {
466 // Services have been added
467 addrFound.nServices |= addr.nServices;
468 fUpdated = true;
469 }
470 bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
471 int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
472 if (addrFound.nTime < addr.nTime - nUpdateInterval)
473 {
474 // Periodically update most recently seen time
475 addrFound.nTime = addr.nTime;
476 fUpdated = true;
477 }
478 if (fUpdated)
8c414691
PV
479 {
480 if (pAddrDB)
481 pAddrDB->WriteAddress(addrFound);
482 else
483 CAddrDB().WriteAddress(addrFound);
484 }
0a61b0df 485 }
486 }
487 return false;
488}
489
490void AddressCurrentlyConnected(const CAddress& addr)
491{
492 CRITICAL_BLOCK(cs_mapAddresses)
493 {
494 // Only if it's been published already
495 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
496 if (it != mapAddresses.end())
497 {
498 CAddress& addrFound = (*it).second;
499 int64 nUpdateInterval = 20 * 60;
500 if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
501 {
502 // Periodically update most recently seen time
503 addrFound.nTime = GetAdjustedTime();
504 CAddrDB addrdb;
505 addrdb.WriteAddress(addrFound);
506 }
507 }
508 }
509}
510
511
512
513
514
515void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
516{
517 // If the dialog might get closed before the reply comes back,
518 // call this in the destructor so it doesn't get called after it's deleted.
519 CRITICAL_BLOCK(cs_vNodes)
520 {
223b6f1b 521 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 522 {
523 CRITICAL_BLOCK(pnode->cs_mapRequests)
524 {
525 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
526 {
527 CRequestTracker& tracker = (*mi).second;
528 if (tracker.fn == fn && tracker.param1 == param1)
529 pnode->mapRequests.erase(mi++);
530 else
531 mi++;
532 }
533 }
534 }
535 }
536}
537
538
539
540
541
542
543
544//
545// Subscription methods for the broadcast and subscription system.
546// Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
547//
548// The subscription system uses a meet-in-the-middle strategy.
549// With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
550// subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
551//
552
553bool AnySubscribed(unsigned int nChannel)
554{
555 if (pnodeLocalHost->IsSubscribed(nChannel))
556 return true;
557 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 558 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 559 if (pnode->IsSubscribed(nChannel))
560 return true;
561 return false;
562}
563
564bool CNode::IsSubscribed(unsigned int nChannel)
565{
566 if (nChannel >= vfSubscribe.size())
567 return false;
568 return vfSubscribe[nChannel];
569}
570
571void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
572{
573 if (nChannel >= vfSubscribe.size())
574 return;
575
576 if (!AnySubscribed(nChannel))
577 {
578 // Relay subscribe
579 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 580 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 581 if (pnode != this)
582 pnode->PushMessage("subscribe", nChannel, nHops);
583 }
584
585 vfSubscribe[nChannel] = true;
586}
587
588void CNode::CancelSubscribe(unsigned int nChannel)
589{
590 if (nChannel >= vfSubscribe.size())
591 return;
592
593 // Prevent from relaying cancel if wasn't subscribed
594 if (!vfSubscribe[nChannel])
595 return;
596 vfSubscribe[nChannel] = false;
597
598 if (!AnySubscribed(nChannel))
599 {
600 // Relay subscription cancel
601 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 602 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 603 if (pnode != this)
604 pnode->PushMessage("sub-cancel", nChannel);
605 }
606}
607
608
609
610
611
612
613
614
615
616CNode* FindNode(unsigned int ip)
617{
618 CRITICAL_BLOCK(cs_vNodes)
619 {
223b6f1b 620 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 621 if (pnode->addr.ip == ip)
622 return (pnode);
623 }
624 return NULL;
625}
626
627CNode* FindNode(CAddress addr)
628{
629 CRITICAL_BLOCK(cs_vNodes)
630 {
223b6f1b 631 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 632 if (pnode->addr == addr)
633 return (pnode);
634 }
635 return NULL;
636}
637
638CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
639{
640 if (addrConnect.ip == addrLocalHost.ip)
641 return NULL;
642
643 // Look for an existing connection
644 CNode* pnode = FindNode(addrConnect.ip);
645 if (pnode)
646 {
647 if (nTimeout != 0)
648 pnode->AddRef(nTimeout);
649 else
650 pnode->AddRef();
651 return pnode;
652 }
653
654 /// debug print
655 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
a6a5bb7c 656 addrConnect.ToString().c_str(),
0a61b0df 657 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
658 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
659
660 CRITICAL_BLOCK(cs_mapAddresses)
661 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
662
663 // Connect
664 SOCKET hSocket;
665 if (ConnectSocket(addrConnect, hSocket))
666 {
667 /// debug print
a6a5bb7c 668 printf("connected %s\n", addrConnect.ToString().c_str());
0a61b0df 669
670 // Set to nonblocking
671#ifdef __WXMSW__
672 u_long nOne = 1;
673 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
674 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
675#else
676 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
677 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
678#endif
679
680 // Add node
681 CNode* pnode = new CNode(hSocket, addrConnect, false);
682 if (nTimeout != 0)
683 pnode->AddRef(nTimeout);
684 else
685 pnode->AddRef();
686 CRITICAL_BLOCK(cs_vNodes)
687 vNodes.push_back(pnode);
688
689 pnode->nTimeConnected = GetTime();
690 return pnode;
691 }
692 else
693 {
694 return NULL;
695 }
696}
697
698void CNode::CloseSocketDisconnect()
699{
700 fDisconnect = true;
701 if (hSocket != INVALID_SOCKET)
702 {
703 if (fDebug)
704 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
a6a5bb7c 705 printf("disconnecting node %s\n", addr.ToString().c_str());
0a61b0df 706 closesocket(hSocket);
707 hSocket = INVALID_SOCKET;
708 }
709}
710
711void CNode::Cleanup()
712{
713 // All of a nodes broadcasts and subscriptions are automatically torn down
714 // when it goes down, so a node has to stay up to keep its broadcast going.
715
716 // Cancel subscriptions
717 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
718 if (vfSubscribe[nChannel])
719 CancelSubscribe(nChannel);
720}
721
722
723
724
725
726
727
728
729
730
731
732
733
734void ThreadSocketHandler(void* parg)
735{
736 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
737 try
738 {
739 vnThreadsRunning[0]++;
740 ThreadSocketHandler2(parg);
741 vnThreadsRunning[0]--;
742 }
743 catch (std::exception& e) {
744 vnThreadsRunning[0]--;
745 PrintException(&e, "ThreadSocketHandler()");
746 } catch (...) {
747 vnThreadsRunning[0]--;
748 throw; // support pthread_cancel()
749 }
750 printf("ThreadSocketHandler exiting\n");
751}
752
753void ThreadSocketHandler2(void* parg)
754{
755 printf("ThreadSocketHandler started\n");
756 list<CNode*> vNodesDisconnected;
757 int nPrevNodeCount = 0;
758
759 loop
760 {
761 //
762 // Disconnect nodes
763 //
764 CRITICAL_BLOCK(cs_vNodes)
765 {
766 // Disconnect unused nodes
767 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 768 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 769 {
770 if (pnode->fDisconnect ||
771 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
772 {
773 // remove from vNodes
774 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
775
776 // close socket and cleanup
777 pnode->CloseSocketDisconnect();
778 pnode->Cleanup();
779
780 // hold in disconnected pool until all refs are released
781 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
782 if (pnode->fNetworkNode || pnode->fInbound)
783 pnode->Release();
784 vNodesDisconnected.push_back(pnode);
785 }
786 }
787
788 // Delete disconnected nodes
789 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 790 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 791 {
792 // wait until threads are done using it
793 if (pnode->GetRefCount() <= 0)
794 {
795 bool fDelete = false;
796 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
797 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
798 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
799 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
800 fDelete = true;
801 if (fDelete)
802 {
803 vNodesDisconnected.remove(pnode);
804 delete pnode;
805 }
806 }
807 }
808 }
809 if (vNodes.size() != nPrevNodeCount)
810 {
811 nPrevNodeCount = vNodes.size();
812 MainFrameRepaint();
813 }
814
815
816 //
817 // Find which sockets have data to receive
818 //
819 struct timeval timeout;
820 timeout.tv_sec = 0;
821 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
822
823 fd_set fdsetRecv;
824 fd_set fdsetSend;
825 fd_set fdsetError;
826 FD_ZERO(&fdsetRecv);
827 FD_ZERO(&fdsetSend);
828 FD_ZERO(&fdsetError);
829 SOCKET hSocketMax = 0;
5f88e888
W
830
831 if(hListenSocket != INVALID_SOCKET)
832 FD_SET(hListenSocket, &fdsetRecv);
0a61b0df 833 hSocketMax = max(hSocketMax, hListenSocket);
834 CRITICAL_BLOCK(cs_vNodes)
835 {
223b6f1b 836 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 837 {
d7f1d200 838 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 839 continue;
840 FD_SET(pnode->hSocket, &fdsetRecv);
841 FD_SET(pnode->hSocket, &fdsetError);
842 hSocketMax = max(hSocketMax, pnode->hSocket);
843 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
844 if (!pnode->vSend.empty())
845 FD_SET(pnode->hSocket, &fdsetSend);
846 }
847 }
848
849 vnThreadsRunning[0]--;
850 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
851 vnThreadsRunning[0]++;
852 if (fShutdown)
853 return;
854 if (nSelect == SOCKET_ERROR)
855 {
856 int nErr = WSAGetLastError();
c6710c7a
MC
857 if (hSocketMax > -1)
858 {
859 printf("socket select error %d\n", nErr);
860 for (int i = 0; i <= hSocketMax; i++)
861 FD_SET(i, &fdsetRecv);
862 }
0a61b0df 863 FD_ZERO(&fdsetSend);
864 FD_ZERO(&fdsetError);
865 Sleep(timeout.tv_usec/1000);
866 }
867
868
869 //
870 // Accept new connections
871 //
5f88e888 872 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
0a61b0df 873 {
874 struct sockaddr_in sockaddr;
875 socklen_t len = sizeof(sockaddr);
876 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
877 CAddress addr(sockaddr);
4698dd9a
CM
878 int nInbound = 0;
879
5a3e82f9 880 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 881 BOOST_FOREACH(CNode* pnode, vNodes)
5a3e82f9
GA
882 if (pnode->fInbound)
883 nInbound++;
0a61b0df 884 if (hSocket == INVALID_SOCKET)
885 {
886 if (WSAGetLastError() != WSAEWOULDBLOCK)
887 printf("socket error accept failed: %d\n", WSAGetLastError());
888 }
5a3e82f9 889 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
0a61b0df 890 {
891 closesocket(hSocket);
892 }
893 else
894 {
a6a5bb7c 895 printf("accepted connection %s\n", addr.ToString().c_str());
0a61b0df 896 CNode* pnode = new CNode(hSocket, addr, true);
897 pnode->AddRef();
898 CRITICAL_BLOCK(cs_vNodes)
899 vNodes.push_back(pnode);
900 }
901 }
902
903
904 //
905 // Service each socket
906 //
907 vector<CNode*> vNodesCopy;
908 CRITICAL_BLOCK(cs_vNodes)
909 {
910 vNodesCopy = vNodes;
223b6f1b 911 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 912 pnode->AddRef();
913 }
223b6f1b 914 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 915 {
916 if (fShutdown)
917 return;
918
919 //
920 // Receive
921 //
922 if (pnode->hSocket == INVALID_SOCKET)
923 continue;
924 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
925 {
926 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
927 {
928 CDataStream& vRecv = pnode->vRecv;
929 unsigned int nPos = vRecv.size();
930
49731745 931 if (nPos > ReceiveBufferSize()) {
0a61b0df 932 if (!pnode->fDisconnect)
9cbae55a 933 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
0a61b0df 934 pnode->CloseSocketDisconnect();
935 }
9cbae55a
GA
936 else {
937 // typical socket buffer is 8K-64K
938 char pchBuf[0x10000];
939 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
940 if (nBytes > 0)
0a61b0df 941 {
9cbae55a
GA
942 vRecv.resize(nPos + nBytes);
943 memcpy(&vRecv[nPos], pchBuf, nBytes);
944 pnode->nLastRecv = GetTime();
945 }
946 else if (nBytes == 0)
947 {
948 // socket closed gracefully
0a61b0df 949 if (!pnode->fDisconnect)
9cbae55a 950 printf("socket closed\n");
0a61b0df 951 pnode->CloseSocketDisconnect();
952 }
9cbae55a
GA
953 else if (nBytes < 0)
954 {
955 // error
956 int nErr = WSAGetLastError();
957 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
958 {
959 if (!pnode->fDisconnect)
960 printf("socket recv error %d\n", nErr);
961 pnode->CloseSocketDisconnect();
962 }
963 }
0a61b0df 964 }
965 }
966 }
967
968 //
969 // Send
970 //
971 if (pnode->hSocket == INVALID_SOCKET)
972 continue;
973 if (FD_ISSET(pnode->hSocket, &fdsetSend))
974 {
975 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
976 {
977 CDataStream& vSend = pnode->vSend;
978 if (!vSend.empty())
979 {
980 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
981 if (nBytes > 0)
982 {
983 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
984 pnode->nLastSend = GetTime();
985 }
986 else if (nBytes < 0)
987 {
988 // error
989 int nErr = WSAGetLastError();
990 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
991 {
992 printf("socket send error %d\n", nErr);
993 pnode->CloseSocketDisconnect();
994 }
995 }
49731745 996 if (vSend.size() > SendBufferSize()) {
9cbae55a
GA
997 if (!pnode->fDisconnect)
998 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
999 pnode->CloseSocketDisconnect();
1000 }
0a61b0df 1001 }
1002 }
1003 }
1004
1005 //
1006 // Inactivity checking
1007 //
1008 if (pnode->vSend.empty())
1009 pnode->nLastSendEmpty = GetTime();
1010 if (GetTime() - pnode->nTimeConnected > 60)
1011 {
1012 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1013 {
1014 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1015 pnode->fDisconnect = true;
1016 }
1017 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1018 {
1019 printf("socket not sending\n");
1020 pnode->fDisconnect = true;
1021 }
1022 else if (GetTime() - pnode->nLastRecv > 90*60)
1023 {
1024 printf("socket inactivity timeout\n");
1025 pnode->fDisconnect = true;
1026 }
1027 }
1028 }
1029 CRITICAL_BLOCK(cs_vNodes)
1030 {
223b6f1b 1031 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1032 pnode->Release();
1033 }
1034
0a61b0df 1035 Sleep(10);
1036 }
1037}
1038
1039
1040
1041
1042
1043
1044
1045
1046
8bb5edc1
MC
1047#ifdef USE_UPNP
1048void ThreadMapPort(void* parg)
1049{
1050 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1051 try
1052 {
1053 vnThreadsRunning[5]++;
1054 ThreadMapPort2(parg);
1055 vnThreadsRunning[5]--;
1056 }
1057 catch (std::exception& e) {
1058 vnThreadsRunning[5]--;
1059 PrintException(&e, "ThreadMapPort()");
1060 } catch (...) {
1061 vnThreadsRunning[5]--;
1062 PrintException(NULL, "ThreadMapPort()");
1063 }
1064 printf("ThreadMapPort exiting\n");
1065}
1066
1067void ThreadMapPort2(void* parg)
1068{
1069 printf("ThreadMapPort started\n");
1070
1071 char port[6];
00bcfe0b 1072 sprintf(port, "%d", GetListenPort());
8bb5edc1
MC
1073
1074 const char * rootdescurl = 0;
1075 const char * multicastif = 0;
1076 const char * minissdpdpath = 0;
b4ada906 1077 int error = 0;
8bb5edc1
MC
1078 struct UPNPDev * devlist = 0;
1079 char lanaddr[64];
1080
b4ada906 1081 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
8bb5edc1
MC
1082
1083 struct UPNPUrls urls;
1084 struct IGDdatas data;
1085 int r;
1086
f285d4f4
DH
1087 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1088 if (r == 1)
8bb5edc1
MC
1089 {
1090 char intClient[16];
1091 char intPort[6];
15656981 1092 string strDesc = "Bitcoin " + FormatFullVersion();
8bb5edc1 1093 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
15656981 1094 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
b4ada906 1095
8bb5edc1
MC
1096 if(r!=UPNPCOMMAND_SUCCESS)
1097 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1098 port, port, lanaddr, r, strupnperror(r));
1099 else
1100 printf("UPnP Port Mapping successful.\n");
1101 loop {
1102 if (fShutdown || !fUseUPnP)
1103 {
1104 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1105 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1106 freeUPNPDevlist(devlist); devlist = 0;
1107 FreeUPNPUrls(&urls);
1108 return;
1109 }
1110 Sleep(2000);
1111 }
1112 } else {
1113 printf("No valid UPnP IGDs found\n");
1114 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1115 if (r != 0)
1116 FreeUPNPUrls(&urls);
8bb5edc1 1117 loop {
973800b5 1118 if (fShutdown || !fUseUPnP)
8bb5edc1
MC
1119 return;
1120 Sleep(2000);
1121 }
1122 }
1123}
1124
1125void MapPort(bool fMapPort)
1126{
1127 if (fUseUPnP != fMapPort)
1128 {
1129 fUseUPnP = fMapPort;
64c7ee7e 1130 WriteSetting("fUseUPnP", fUseUPnP);
8bb5edc1
MC
1131 }
1132 if (fUseUPnP && vnThreadsRunning[5] < 1)
1133 {
1134 if (!CreateThread(ThreadMapPort, NULL))
1135 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1136 }
1137}
9f0ac169
GA
1138#else
1139void MapPort(bool /* unused fMapPort */)
1140{
1141 // Intentionally left blank.
1142}
8bb5edc1
MC
1143#endif
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
f684aec4
JG
1154static const char *strDNSSeed[] = {
1155 "bitseed.xf2.org",
a2b6c193 1156 "bitseed.bitcoin.org.uk",
f03c31db 1157 "dnsseed.bluematt.me",
f684aec4 1158};
0a61b0df 1159
f684aec4
JG
1160void DNSAddressSeed()
1161{
1162 int found = 0;
1163
ce8f78a7
MC
1164 if (!fTestNet)
1165 {
1166 printf("Loading addresses from DNS seeds (could take a while)\n");
d655a26c
SG
1167 CAddrDB addrDB;
1168 addrDB.TxnBegin();
f684aec4 1169
ce8f78a7
MC
1170 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1171 vector<CAddress> vaddr;
1172 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
a6a5bb7c 1173 {
ce8f78a7 1174 BOOST_FOREACH (CAddress& addr, vaddr)
a6a5bb7c 1175 {
ce8f78a7
MC
1176 if (addr.GetByte(3) != 127)
1177 {
1178 addr.nTime = 0;
d655a26c 1179 AddAddress(addr, 0, &addrDB);
ce8f78a7
MC
1180 found++;
1181 }
a6a5bb7c 1182 }
f684aec4
JG
1183 }
1184 }
d655a26c
SG
1185
1186 addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
f684aec4
JG
1187 }
1188
448b4516 1189 printf("%d addresses found from DNS seeds\n", found);
f684aec4 1190}
0a61b0df 1191
1192
1193
1194unsigned int pnSeed[] =
1195{
d2e2cb0d
DF
1196 0x1ddb1032, 0x6242ce40, 0x52d6a445, 0x2dd7a445, 0x8a53cd47, 0x73263750, 0xda23c257, 0xecd4ed57,
1197 0x0a40ec59, 0x75dce160, 0x7df76791, 0x89370bad, 0xa4f214ad, 0x767700ae, 0x638b0418, 0x868a1018,
1198 0xcd9f332e, 0x0129653e, 0xcc92dc3e, 0x96671640, 0x56487e40, 0x5b66f440, 0xb1d01f41, 0xf1dc6041,
1199 0xc1d12b42, 0x86ba1243, 0x6be4df43, 0x6d4cef43, 0xd18e0644, 0x1ab0b344, 0x6584a345, 0xe7c1a445,
1200 0x58cea445, 0xc5daa445, 0x21dda445, 0x3d3b5346, 0x13e55347, 0x1080d24a, 0x8e611e4b, 0x81518e4b,
1201 0x6c839e4b, 0xe2ad0a4c, 0xfbbc0a4c, 0x7f5b6e4c, 0x7244224e, 0x1300554e, 0x20690652, 0x5a48b652,
1202 0x75c5c752, 0x4335cc54, 0x340fd154, 0x87c07455, 0x087b2b56, 0x8a133a57, 0xac23c257, 0x70374959,
1203 0xfb63d45b, 0xb9a1685c, 0x180d765c, 0x674f645d, 0x04d3495e, 0x1de44b5e, 0x4ee8a362, 0x0ded1b63,
1204 0xc1b04b6d, 0x8d921581, 0x97b7ea82, 0x1cf83a8e, 0x91490bad, 0x09dc75ae, 0x9a6d79ae, 0xa26d79ae,
1205 0x0fd08fae, 0x0f3e3fb2, 0x4f944fb2, 0xcca448b8, 0x3ecd6ab8, 0xa9d5a5bc, 0x8d0119c1, 0x045997d5,
1206 0xca019dd9, 0x0d526c4d, 0xabf1ba44, 0x66b1ab55, 0x1165f462, 0x3ed7cbad, 0xa38fae6e, 0x3bd2cbad,
1207 0xd36f0547, 0x20df7840, 0x7a337742, 0x549f8e4b, 0x9062365c, 0xd399f562, 0x2b5274a1, 0x8edfa153,
1208 0x3bffb347, 0x7074bf58, 0xb74fcbad, 0x5b5a795b, 0x02fa29ce, 0x5a6738d4, 0xe8a1d23e, 0xef98c445,
1209 0x4b0f494c, 0xa2bc1e56, 0x7694ad63, 0xa4a800c3, 0x05fda6cd, 0x9f22175e, 0x364a795b, 0x536285d5,
1210 0xac44c9d4, 0x0b06254d, 0x150c2fd4, 0x32a50dcc, 0xfd79ce48, 0xf15cfa53, 0x66c01e60, 0x6bc26661,
1211 0xc03b47ae, 0x4dda1b81, 0x3285a4c1, 0x883ca96d, 0x35d60a4c, 0xdae09744, 0x2e314d61, 0x84e247cf,
1212 0x6c814552, 0x3a1cc658, 0x98d8f382, 0xe584cb5b, 0x15e86057, 0x7b01504e, 0xd852dd48, 0x56382f56,
1213 0x0a5df454, 0xa0d18d18, 0x2e89b148, 0xa79c114c, 0xcbdcd054, 0x5523bc43, 0xa9832640, 0x8a066144,
1214 0x3894c3bc, 0xab76bf58, 0x6a018ac1, 0xfebf4f43, 0x2f26c658, 0x31102f4e, 0x85e929d5, 0x2a1c175e,
1215 0xfc6c2cd1, 0x27b04b6d, 0xdf024650, 0x161748b8, 0x28be6580, 0x57be6580, 0x1cee677a, 0xaa6bb742,
1216 0x9a53964b, 0x0a5a2d4d, 0x2434c658, 0x9a494f57, 0x1ebb0e48, 0xf610b85d, 0x077ecf44, 0x085128bc,
1217 0x5ba17a18, 0x27ca1b42, 0xf8a00b56, 0xfcd4c257, 0xcf2fc15e, 0xd897e052, 0x4cada04f, 0x2f35f6d5,
1218 0x382ce8c9, 0xe523984b, 0x3f946846, 0x60c8be43, 0x41da6257, 0xde0be142, 0xae8a544b, 0xeff0c254,
1219 0x1e0f795b, 0xaeb28890, 0xca16acd9, 0x1e47ddd8, 0x8c8c4829, 0xd27dc747, 0xd53b1663, 0x4096b163,
1220 0x9c8dd958, 0xcb12f860, 0x9e79305c, 0x40c1a445, 0x4a90c2bc, 0x2c3a464d, 0x2727f23c, 0x30b04b6d,
1221 0x59024cb8, 0xa091e6ad, 0x31b04b6d, 0xc29d46a6, 0x63934fb2, 0xd9224dbe, 0x9f5910d8, 0x7f530a6b,
1222 0x752e9c95, 0x65453548, 0xa484be46, 0xce5a1b59, 0x710e0718, 0x46a13d18, 0xdaaf5318, 0xc4a8ff53,
1223 0x87abaa52, 0xb764cf51, 0xb2025d4a, 0x6d351e41, 0xc035c33e, 0xa432c162, 0x61ef34ae, 0xd16fddbc,
1224 0x0870e8c1, 0x3070e8c1, 0x9c71e8c1, 0xa4992363, 0x85a1f663, 0x4184e559, 0x18d96ed8, 0x17b8dbd5,
1225 0x60e7cd18, 0xe5ee104c, 0xab17ac62, 0x1e786e1b, 0x5d23b762, 0xf2388fae, 0x88270360, 0x9e5b3d80,
1226 0x7da518b2, 0xb5613b45, 0x1ad41f3e, 0xd550854a, 0x8617e9a9, 0x925b229c, 0xf2e92542, 0x47af0544,
1227 0x73b5a843, 0xb9b7a0ad, 0x03a748d0, 0x0a6ff862, 0x6694df62, 0x3bfac948, 0x8e098f4f, 0x746916c3,
1228 0x02f38e4f, 0x40bb1243, 0x6a54d162, 0x6008414b, 0xa513794c, 0x514aa343, 0x63781747, 0xdbb6795b,
1229 0xed065058, 0x42d24b46, 0x1518794c, 0x9b271681, 0x73e4ffad, 0x0654784f, 0x438dc945, 0x641846a6,
1230 0x2d1b0944, 0x94b59148, 0x8d369558, 0xa5a97662, 0x8b705b42, 0xce9204ae, 0x8d584450, 0x2df61555,
1231 0xeebff943, 0x2e75fb4d, 0x3ef8fc57, 0x9921135e, 0x8e31042e, 0xb5afad43, 0x89ecedd1, 0x9cfcc047,
1232 0x8fcd0f4c, 0xbe49f5ad, 0x146a8d45, 0x98669ab8, 0x98d9175e, 0xd1a8e46d, 0x839a3ab8, 0x40a0016c,
1233 0x6d27c257, 0x977fffad, 0x7baa5d5d, 0x1213be43, 0xb167e5a9, 0x640fe8ca, 0xbc9ea655, 0x0f820a4c,
1234 0x0f097059, 0x69ac957c, 0x366d8453, 0xb1ba2844, 0x8857f081, 0x70b5be63, 0xc545454b, 0xaf36ded1,
1235 0xb5a4b052, 0x21f062d1, 0x72ab89b2, 0x74a45318, 0x8312e6bc, 0xb916965f, 0x8aa7c858, 0xfe7effad,
0a61b0df 1236};
1237
1238
1239
1240void ThreadOpenConnections(void* parg)
1241{
1242 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1243 try
1244 {
1245 vnThreadsRunning[1]++;
1246 ThreadOpenConnections2(parg);
1247 vnThreadsRunning[1]--;
1248 }
1249 catch (std::exception& e) {
1250 vnThreadsRunning[1]--;
1251 PrintException(&e, "ThreadOpenConnections()");
1252 } catch (...) {
1253 vnThreadsRunning[1]--;
1254 PrintException(NULL, "ThreadOpenConnections()");
1255 }
1256 printf("ThreadOpenConnections exiting\n");
1257}
1258
1259void ThreadOpenConnections2(void* parg)
1260{
1261 printf("ThreadOpenConnections started\n");
1262
1263 // Connect to specific addresses
1264 if (mapArgs.count("-connect"))
1265 {
1266 for (int64 nLoop = 0;; nLoop++)
1267 {
223b6f1b 1268 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1269 {
a6a5bb7c 1270 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1271 if (addr.IsValid())
1272 OpenNetworkConnection(addr);
1273 for (int i = 0; i < 10 && i < nLoop; i++)
1274 {
1275 Sleep(500);
1276 if (fShutdown)
1277 return;
1278 }
1279 }
1280 }
1281 }
1282
1283 // Connect to manually added nodes first
1284 if (mapArgs.count("-addnode"))
1285 {
223b6f1b 1286 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
0a61b0df 1287 {
a6a5bb7c 1288 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1289 if (addr.IsValid())
1290 {
1291 OpenNetworkConnection(addr);
1292 Sleep(500);
1293 if (fShutdown)
1294 return;
1295 }
1296 }
1297 }
1298
1299 // Initiate network connections
1300 int64 nStart = GetTime();
1301 loop
1302 {
1303 // Limit outbound connections
1304 vnThreadsRunning[1]--;
1305 Sleep(500);
1306 loop
1307 {
1308 int nOutbound = 0;
1309 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1310 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1311 if (!pnode->fInbound)
1312 nOutbound++;
1313 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
5a3e82f9 1314 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
0a61b0df 1315 if (nOutbound < nMaxOutboundConnections)
1316 break;
1317 Sleep(2000);
1318 if (fShutdown)
1319 return;
1320 }
1321 vnThreadsRunning[1]++;
1322 if (fShutdown)
1323 return;
1324
1325 CRITICAL_BLOCK(cs_mapAddresses)
1326 {
1327 // Add seed nodes if IRC isn't working
1328 static bool fSeedUsed;
1329 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
5cbf7532 1330 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
0a61b0df 1331 {
1332 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1333 {
1334 // It'll only connect to one or two seed nodes because once it connects,
1335 // it'll get a pile of addresses with newer timestamps.
1336 CAddress addr;
1337 addr.ip = pnSeed[i];
1338 addr.nTime = 0;
1339 AddAddress(addr);
1340 }
1341 fSeedUsed = true;
1342 }
1343
1344 if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1345 {
1346 // Disconnect seed nodes
1347 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1348 static int64 nSeedDisconnected;
1349 if (nSeedDisconnected == 0)
1350 {
1351 nSeedDisconnected = GetTime();
1352 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1353 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1354 if (setSeed.count(pnode->addr.ip))
1355 pnode->fDisconnect = true;
1356 }
1357
1358 // Keep setting timestamps to 0 so they won't reconnect
1359 if (GetTime() - nSeedDisconnected < 60 * 60)
1360 {
223b6f1b 1361 BOOST_FOREACH(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
0a61b0df 1362 {
10abe4f2 1363 if (setSeed.count(item.second.ip) && item.second.nTime != 0)
0a61b0df 1364 {
1365 item.second.nTime = 0;
1366 CAddrDB().WriteAddress(item.second);
1367 }
1368 }
1369 }
1370 }
1371 }
1372
1373
1374 //
1375 // Choose an address to connect to based on most recently seen
1376 //
1377 CAddress addrConnect;
1378 int64 nBest = INT64_MIN;
1379
1380 // Only connect to one address per a.b.?.? range.
1381 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1382 set<unsigned int> setConnected;
1383 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1384 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1385 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1386
1387 CRITICAL_BLOCK(cs_mapAddresses)
1388 {
223b6f1b 1389 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
0a61b0df 1390 {
1391 const CAddress& addr = item.second;
1392 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1393 continue;
1394 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1395 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1396
1397 // Randomize the order in a deterministic way, putting the standard port first
1398 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
a6a5bb7c 1399 if (addr.port != htons(GetDefaultPort()))
0a61b0df 1400 nRandomizer += 2 * 60 * 60;
1401
1402 // Last seen Base retry frequency
1403 // <1 hour 10 min
1404 // 1 hour 1 hour
1405 // 4 hours 2 hours
1406 // 24 hours 5 hours
1407 // 48 hours 7 hours
1408 // 7 days 13 hours
1409 // 30 days 27 hours
1410 // 90 days 46 hours
1411 // 365 days 93 hours
1412 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1413
1414 // Fast reconnect for one hour after last seen
1415 if (nSinceLastSeen < 60 * 60)
1416 nDelay = 10 * 60;
1417
1418 // Limit retry frequency
1419 if (nSinceLastTry < nDelay)
1420 continue;
1421
1422 // If we have IRC, we'll be notified when they first come online,
1423 // and again every 24 hours by the refresh broadcast.
1424 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1425 continue;
1426
1427 // Only try the old stuff if we don't have enough connections
1428 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1429 continue;
1430
1431 // If multiple addresses are ready, prioritize by time since
1432 // last seen and time since last tried.
1433 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1434 if (nScore > nBest)
1435 {
1436 nBest = nScore;
1437 addrConnect = addr;
1438 }
1439 }
1440 }
1441
1442 if (addrConnect.IsValid())
1443 OpenNetworkConnection(addrConnect);
1444 }
1445}
1446
1447bool OpenNetworkConnection(const CAddress& addrConnect)
1448{
1449 //
1450 // Initiate outbound network connection
1451 //
1452 if (fShutdown)
1453 return false;
1454 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1455 return false;
1456
1457 vnThreadsRunning[1]--;
1458 CNode* pnode = ConnectNode(addrConnect);
1459 vnThreadsRunning[1]++;
1460 if (fShutdown)
1461 return false;
1462 if (!pnode)
1463 return false;
1464 pnode->fNetworkNode = true;
1465
0a61b0df 1466 return true;
1467}
1468
1469
1470
1471
1472
1473
1474
1475
1476void ThreadMessageHandler(void* parg)
1477{
1478 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1479 try
1480 {
1481 vnThreadsRunning[2]++;
1482 ThreadMessageHandler2(parg);
1483 vnThreadsRunning[2]--;
1484 }
1485 catch (std::exception& e) {
1486 vnThreadsRunning[2]--;
1487 PrintException(&e, "ThreadMessageHandler()");
1488 } catch (...) {
1489 vnThreadsRunning[2]--;
1490 PrintException(NULL, "ThreadMessageHandler()");
1491 }
1492 printf("ThreadMessageHandler exiting\n");
1493}
1494
1495void ThreadMessageHandler2(void* parg)
1496{
1497 printf("ThreadMessageHandler started\n");
1498 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1499 while (!fShutdown)
1500 {
1501 vector<CNode*> vNodesCopy;
1502 CRITICAL_BLOCK(cs_vNodes)
1503 {
1504 vNodesCopy = vNodes;
223b6f1b 1505 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1506 pnode->AddRef();
1507 }
1508
1509 // Poll the connected nodes for messages
1510 CNode* pnodeTrickle = NULL;
1511 if (!vNodesCopy.empty())
1512 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
223b6f1b 1513 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1514 {
1515 // Receive messages
1516 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1517 ProcessMessages(pnode);
1518 if (fShutdown)
1519 return;
1520
1521 // Send messages
1522 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1523 SendMessages(pnode, pnode == pnodeTrickle);
1524 if (fShutdown)
1525 return;
1526 }
1527
1528 CRITICAL_BLOCK(cs_vNodes)
1529 {
223b6f1b 1530 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1531 pnode->Release();
1532 }
1533
7629d36a 1534 // Wait and allow messages to bunch up.
1535 // Reduce vnThreadsRunning so StopNode has permission to exit while
1536 // we're sleeping, but we must always check fShutdown after doing this.
0a61b0df 1537 vnThreadsRunning[2]--;
1538 Sleep(100);
3f647537 1539 if (fRequestShutdown)
1540 Shutdown(NULL);
0a61b0df 1541 vnThreadsRunning[2]++;
1542 if (fShutdown)
1543 return;
1544 }
1545}
1546
1547
1548
1549
1550
1551
0a61b0df 1552bool BindListenPort(string& strError)
1553{
1554 strError = "";
1555 int nOne = 1;
00bcfe0b 1556 addrLocalHost.port = htons(GetListenPort());
0a61b0df 1557
1558#ifdef __WXMSW__
1559 // Initialize Windows Sockets
1560 WSADATA wsadata;
1561 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1562 if (ret != NO_ERROR)
1563 {
1564 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1565 printf("%s\n", strError.c_str());
1566 return false;
1567 }
1568#endif
1569
1570 // Create socket for listening for incoming connections
1571 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1572 if (hListenSocket == INVALID_SOCKET)
1573 {
1574 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1575 printf("%s\n", strError.c_str());
1576 return false;
1577 }
1578
ec93a0e2 1579#ifdef SO_NOSIGPIPE
0a61b0df 1580 // Different way of disabling SIGPIPE on BSD
1581 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1582#endif
1583
1584#ifndef __WXMSW__
1585 // Allow binding if the port is still in TIME_WAIT state after
1586 // the program was closed and restarted. Not an issue on windows.
1587 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1588#endif
1589
1590#ifdef __WXMSW__
1591 // Set to nonblocking, incoming connections will also inherit this
1592 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1593#else
1594 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1595#endif
1596 {
1597 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1598 printf("%s\n", strError.c_str());
1599 return false;
1600 }
1601
1602 // The sockaddr_in structure specifies the address family,
1603 // IP address, and port for the socket that is being bound
1604 struct sockaddr_in sockaddr;
1605 memset(&sockaddr, 0, sizeof(sockaddr));
1606 sockaddr.sin_family = AF_INET;
1607 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
00bcfe0b 1608 sockaddr.sin_port = htons(GetListenPort());
0a61b0df 1609 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1610 {
1611 int nErr = WSAGetLastError();
1612 if (nErr == WSAEADDRINUSE)
d9c6b09a 1613 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
0a61b0df 1614 else
1615 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1616 printf("%s\n", strError.c_str());
1617 return false;
1618 }
1619 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1620
1621 // Listen for incoming connections
1622 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1623 {
1624 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1625 printf("%s\n", strError.c_str());
1626 return false;
1627 }
1628
1629 return true;
1630}
1631
1632void StartNode(void* parg)
1633{
1634 if (pnodeLocalHost == NULL)
a6a5bb7c 1635 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
0a61b0df 1636
1637#ifdef __WXMSW__
1638 // Get local host ip
1639 char pszHostName[1000] = "";
1640 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1641 {
a6a5bb7c 1642 vector<CAddress> vaddr;
545a679a 1643 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
223b6f1b 1644 BOOST_FOREACH (const CAddress &addr, vaddr)
a6a5bb7c 1645 if (addr.GetByte(3) != 127)
0a61b0df 1646 {
1647 addrLocalHost = addr;
1648 break;
1649 }
0a61b0df 1650 }
1651#else
1652 // Get local host ip
1653 struct ifaddrs* myaddrs;
1654 if (getifaddrs(&myaddrs) == 0)
1655 {
1656 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1657 {
1658 if (ifa->ifa_addr == NULL) continue;
1659 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1660 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1661 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1662 char pszIP[100];
1663 if (ifa->ifa_addr->sa_family == AF_INET)
1664 {
1665 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1666 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1667 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1668
1669 // Take the first IP that isn't loopback 127.x.x.x
00bcfe0b 1670 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
0a61b0df 1671 if (addr.IsValid() && addr.GetByte(3) != 127)
1672 {
1673 addrLocalHost = addr;
1674 break;
1675 }
1676 }
1677 else if (ifa->ifa_addr->sa_family == AF_INET6)
1678 {
1679 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1680 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1681 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1682 }
1683 }
1684 freeifaddrs(myaddrs);
1685 }
1686#endif
1687 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1688
5f88e888 1689 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
0a61b0df 1690 {
1691 // Proxies can't take incoming connections
1692 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1693 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1694 }
1695 else
1696 {
629e37dd 1697 CreateThread(ThreadGetMyExternalIP, NULL);
0a61b0df 1698 }
1699
1700 //
1701 // Start threads
1702 //
1703
8bb5edc1
MC
1704 // Map ports with UPnP
1705 if (fHaveUPnP)
1706 MapPort(fUseUPnP);
1707
0a61b0df 1708 // Get addresses from IRC and advertise ours
1709 if (!CreateThread(ThreadIRCSeed, NULL))
1710 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1711
1712 // Send and receive from sockets, accept connections
858cebed 1713 CreateThread(ThreadSocketHandler, NULL, true);
0a61b0df 1714
1715 // Initiate outbound connections
1716 if (!CreateThread(ThreadOpenConnections, NULL))
1717 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1718
1719 // Process messages
1720 if (!CreateThread(ThreadMessageHandler, NULL))
1721 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1722
1723 // Generate coins in the background
64c7ee7e 1724 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
0a61b0df 1725}
1726
1727bool StopNode()
1728{
1729 printf("StopNode()\n");
1730 fShutdown = true;
1731 nTransactionsUpdated++;
1732 int64 nStart = GetTime();
8bb5edc1
MC
1733 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1734#ifdef USE_UPNP
1735 || vnThreadsRunning[5] > 0
1736#endif
1737 )
0a61b0df 1738 {
1739 if (GetTime() - nStart > 20)
1740 break;
1741 Sleep(20);
1742 }
1743 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1744 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1745 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1746 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1747 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
8bb5edc1 1748 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
0a61b0df 1749 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1750 Sleep(20);
1751 Sleep(50);
1752
1753 return true;
1754}
1755
1756class CNetCleanup
1757{
1758public:
1759 CNetCleanup()
1760 {
1761 }
1762 ~CNetCleanup()
1763 {
1764 // Close sockets
223b6f1b 1765 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1766 if (pnode->hSocket != INVALID_SOCKET)
1767 closesocket(pnode->hSocket);
1768 if (hListenSocket != INVALID_SOCKET)
1769 if (closesocket(hListenSocket) == SOCKET_ERROR)
1770 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1771
1772#ifdef __WXMSW__
1773 // Shutdown Windows Sockets
1774 WSACleanup();
1775#endif
1776 }
1777}
1778instance_of_cnetcleanup;
This page took 0.290694 seconds and 4 git commands to generate.