]> Git Repo - VerusCoin.git/blame - src/net.cpp
Merge pull request #602 from wowus/master
[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
6853e627 13#ifdef WIN32
013df1cc
MC
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
6853e627 105#ifdef WIN32
76d660eb
PW
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);
6853e627 144#ifdef WIN32
76d660eb
PW
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 }
6853e627 161#ifdef WIN32
76d660eb
PW
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 */
6853e627 178#ifdef WIN32
76d660eb
PW
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);
94066965
GA
446 bool fUpdated = false;
447 bool fNew = false;
448 CAddress addrFound = addr;
449
0a61b0df 450 CRITICAL_BLOCK(cs_mapAddresses)
451 {
452 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
453 if (it == mapAddresses.end())
454 {
455 // New address
a6a5bb7c 456 printf("AddAddress(%s)\n", addr.ToString().c_str());
0a61b0df 457 mapAddresses.insert(make_pair(addr.GetKey(), addr));
94066965
GA
458 fUpdated = true;
459 fNew = true;
0a61b0df 460 }
461 else
462 {
94066965 463 addrFound = (*it).second;
0a61b0df 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 }
0a61b0df 478 }
479 }
94066965
GA
480 // There is a nasty deadlock bug if this is done inside the cs_mapAddresses
481 // CRITICAL_BLOCK:
482 // Thread 1: begin db transaction (locks inside-db-mutex)
483 // then AddAddress (locks cs_mapAddresses)
484 // Thread 2: AddAddress (locks cs_mapAddresses)
485 // ... then db operation hangs waiting for inside-db-mutex
486 if (fUpdated)
487 {
488 if (pAddrDB)
489 pAddrDB->WriteAddress(addrFound);
490 else
491 CAddrDB().WriteAddress(addrFound);
492 }
493 return fNew;
0a61b0df 494}
495
496void AddressCurrentlyConnected(const CAddress& addr)
497{
498 CRITICAL_BLOCK(cs_mapAddresses)
499 {
500 // Only if it's been published already
501 map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
502 if (it != mapAddresses.end())
503 {
504 CAddress& addrFound = (*it).second;
505 int64 nUpdateInterval = 20 * 60;
506 if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
507 {
508 // Periodically update most recently seen time
509 addrFound.nTime = GetAdjustedTime();
510 CAddrDB addrdb;
511 addrdb.WriteAddress(addrFound);
512 }
513 }
514 }
515}
516
517
518
519
520
521void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
522{
523 // If the dialog might get closed before the reply comes back,
524 // call this in the destructor so it doesn't get called after it's deleted.
525 CRITICAL_BLOCK(cs_vNodes)
526 {
223b6f1b 527 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 528 {
529 CRITICAL_BLOCK(pnode->cs_mapRequests)
530 {
531 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
532 {
533 CRequestTracker& tracker = (*mi).second;
534 if (tracker.fn == fn && tracker.param1 == param1)
535 pnode->mapRequests.erase(mi++);
536 else
537 mi++;
538 }
539 }
540 }
541 }
542}
543
544
545
546
547
548
549
550//
551// Subscription methods for the broadcast and subscription system.
552// Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
553//
554// The subscription system uses a meet-in-the-middle strategy.
555// With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
556// subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
557//
558
559bool AnySubscribed(unsigned int nChannel)
560{
561 if (pnodeLocalHost->IsSubscribed(nChannel))
562 return true;
563 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 564 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 565 if (pnode->IsSubscribed(nChannel))
566 return true;
567 return false;
568}
569
570bool CNode::IsSubscribed(unsigned int nChannel)
571{
572 if (nChannel >= vfSubscribe.size())
573 return false;
574 return vfSubscribe[nChannel];
575}
576
577void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
578{
579 if (nChannel >= vfSubscribe.size())
580 return;
581
582 if (!AnySubscribed(nChannel))
583 {
584 // Relay subscribe
585 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 586 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 587 if (pnode != this)
588 pnode->PushMessage("subscribe", nChannel, nHops);
589 }
590
591 vfSubscribe[nChannel] = true;
592}
593
594void CNode::CancelSubscribe(unsigned int nChannel)
595{
596 if (nChannel >= vfSubscribe.size())
597 return;
598
599 // Prevent from relaying cancel if wasn't subscribed
600 if (!vfSubscribe[nChannel])
601 return;
602 vfSubscribe[nChannel] = false;
603
604 if (!AnySubscribed(nChannel))
605 {
606 // Relay subscription cancel
607 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 608 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 609 if (pnode != this)
610 pnode->PushMessage("sub-cancel", nChannel);
611 }
612}
613
614
615
616
617
618
619
620
621
622CNode* FindNode(unsigned int ip)
623{
624 CRITICAL_BLOCK(cs_vNodes)
625 {
223b6f1b 626 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 627 if (pnode->addr.ip == ip)
628 return (pnode);
629 }
630 return NULL;
631}
632
633CNode* FindNode(CAddress addr)
634{
635 CRITICAL_BLOCK(cs_vNodes)
636 {
223b6f1b 637 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 638 if (pnode->addr == addr)
639 return (pnode);
640 }
641 return NULL;
642}
643
644CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
645{
646 if (addrConnect.ip == addrLocalHost.ip)
647 return NULL;
648
649 // Look for an existing connection
650 CNode* pnode = FindNode(addrConnect.ip);
651 if (pnode)
652 {
653 if (nTimeout != 0)
654 pnode->AddRef(nTimeout);
655 else
656 pnode->AddRef();
657 return pnode;
658 }
659
660 /// debug print
661 printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
a6a5bb7c 662 addrConnect.ToString().c_str(),
0a61b0df 663 (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
664 (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
665
666 CRITICAL_BLOCK(cs_mapAddresses)
667 mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
668
669 // Connect
670 SOCKET hSocket;
671 if (ConnectSocket(addrConnect, hSocket))
672 {
673 /// debug print
a6a5bb7c 674 printf("connected %s\n", addrConnect.ToString().c_str());
0a61b0df 675
676 // Set to nonblocking
6853e627 677#ifdef WIN32
0a61b0df 678 u_long nOne = 1;
679 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
680 printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
681#else
682 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
683 printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
684#endif
685
686 // Add node
687 CNode* pnode = new CNode(hSocket, addrConnect, false);
688 if (nTimeout != 0)
689 pnode->AddRef(nTimeout);
690 else
691 pnode->AddRef();
692 CRITICAL_BLOCK(cs_vNodes)
693 vNodes.push_back(pnode);
694
695 pnode->nTimeConnected = GetTime();
696 return pnode;
697 }
698 else
699 {
700 return NULL;
701 }
702}
703
704void CNode::CloseSocketDisconnect()
705{
706 fDisconnect = true;
707 if (hSocket != INVALID_SOCKET)
708 {
709 if (fDebug)
710 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
a6a5bb7c 711 printf("disconnecting node %s\n", addr.ToString().c_str());
0a61b0df 712 closesocket(hSocket);
713 hSocket = INVALID_SOCKET;
714 }
715}
716
717void CNode::Cleanup()
718{
719 // All of a nodes broadcasts and subscriptions are automatically torn down
720 // when it goes down, so a node has to stay up to keep its broadcast going.
721
722 // Cancel subscriptions
723 for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
724 if (vfSubscribe[nChannel])
725 CancelSubscribe(nChannel);
726}
727
728
15f3ad4d
GA
729std::map<unsigned int, int64> CNode::setBanned;
730CCriticalSection CNode::cs_setBanned;
731
732void CNode::ClearBanned()
733{
734 setBanned.clear();
735}
736
737bool CNode::IsBanned(unsigned int ip)
738{
739 bool fResult = false;
740 CRITICAL_BLOCK(cs_setBanned)
741 {
742 std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
743 if (i != setBanned.end())
744 {
745 int64 t = (*i).second;
746 if (GetTime() < t)
747 fResult = true;
748 }
749 }
750 return fResult;
751}
752
753bool CNode::Misbehaving(int howmuch)
754{
755 if (addr.IsLocal())
756 {
757 printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
758 return false;
759 }
760
761 nMisbehavior += howmuch;
762 if (nMisbehavior >= GetArg("-banscore", 100))
763 {
764 int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
765 CRITICAL_BLOCK(cs_setBanned)
766 if (setBanned[addr.ip] < banTime)
767 setBanned[addr.ip] = banTime;
768 CloseSocketDisconnect();
769 printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
770 return true;
771 }
772 return false;
773}
774
0a61b0df 775
776
777
778
779
780
781
782
783
784
785
786void ThreadSocketHandler(void* parg)
787{
788 IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
789 try
790 {
791 vnThreadsRunning[0]++;
792 ThreadSocketHandler2(parg);
793 vnThreadsRunning[0]--;
794 }
795 catch (std::exception& e) {
796 vnThreadsRunning[0]--;
797 PrintException(&e, "ThreadSocketHandler()");
798 } catch (...) {
799 vnThreadsRunning[0]--;
800 throw; // support pthread_cancel()
801 }
802 printf("ThreadSocketHandler exiting\n");
803}
804
805void ThreadSocketHandler2(void* parg)
806{
807 printf("ThreadSocketHandler started\n");
808 list<CNode*> vNodesDisconnected;
809 int nPrevNodeCount = 0;
810
811 loop
812 {
813 //
814 // Disconnect nodes
815 //
816 CRITICAL_BLOCK(cs_vNodes)
817 {
818 // Disconnect unused nodes
819 vector<CNode*> vNodesCopy = vNodes;
223b6f1b 820 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 821 {
822 if (pnode->fDisconnect ||
823 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
824 {
825 // remove from vNodes
826 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
827
828 // close socket and cleanup
829 pnode->CloseSocketDisconnect();
830 pnode->Cleanup();
831
832 // hold in disconnected pool until all refs are released
833 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
834 if (pnode->fNetworkNode || pnode->fInbound)
835 pnode->Release();
836 vNodesDisconnected.push_back(pnode);
837 }
838 }
839
840 // Delete disconnected nodes
841 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
223b6f1b 842 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
0a61b0df 843 {
844 // wait until threads are done using it
845 if (pnode->GetRefCount() <= 0)
846 {
847 bool fDelete = false;
848 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
849 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
850 TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
851 TRY_CRITICAL_BLOCK(pnode->cs_inventory)
852 fDelete = true;
853 if (fDelete)
854 {
855 vNodesDisconnected.remove(pnode);
856 delete pnode;
857 }
858 }
859 }
860 }
861 if (vNodes.size() != nPrevNodeCount)
862 {
863 nPrevNodeCount = vNodes.size();
864 MainFrameRepaint();
865 }
866
867
868 //
869 // Find which sockets have data to receive
870 //
871 struct timeval timeout;
872 timeout.tv_sec = 0;
873 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
874
875 fd_set fdsetRecv;
876 fd_set fdsetSend;
877 fd_set fdsetError;
878 FD_ZERO(&fdsetRecv);
879 FD_ZERO(&fdsetSend);
880 FD_ZERO(&fdsetError);
881 SOCKET hSocketMax = 0;
5f88e888
W
882
883 if(hListenSocket != INVALID_SOCKET)
884 FD_SET(hListenSocket, &fdsetRecv);
0a61b0df 885 hSocketMax = max(hSocketMax, hListenSocket);
886 CRITICAL_BLOCK(cs_vNodes)
887 {
223b6f1b 888 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 889 {
d7f1d200 890 if (pnode->hSocket == INVALID_SOCKET)
0a61b0df 891 continue;
892 FD_SET(pnode->hSocket, &fdsetRecv);
893 FD_SET(pnode->hSocket, &fdsetError);
894 hSocketMax = max(hSocketMax, pnode->hSocket);
895 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
896 if (!pnode->vSend.empty())
897 FD_SET(pnode->hSocket, &fdsetSend);
898 }
899 }
900
901 vnThreadsRunning[0]--;
902 int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
903 vnThreadsRunning[0]++;
904 if (fShutdown)
905 return;
906 if (nSelect == SOCKET_ERROR)
907 {
908 int nErr = WSAGetLastError();
c6710c7a
MC
909 if (hSocketMax > -1)
910 {
911 printf("socket select error %d\n", nErr);
912 for (int i = 0; i <= hSocketMax; i++)
913 FD_SET(i, &fdsetRecv);
914 }
0a61b0df 915 FD_ZERO(&fdsetSend);
916 FD_ZERO(&fdsetError);
917 Sleep(timeout.tv_usec/1000);
918 }
919
920
921 //
922 // Accept new connections
923 //
5f88e888 924 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
0a61b0df 925 {
926 struct sockaddr_in sockaddr;
927 socklen_t len = sizeof(sockaddr);
928 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
929 CAddress addr(sockaddr);
4698dd9a
CM
930 int nInbound = 0;
931
5a3e82f9 932 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 933 BOOST_FOREACH(CNode* pnode, vNodes)
5a3e82f9
GA
934 if (pnode->fInbound)
935 nInbound++;
0a61b0df 936 if (hSocket == INVALID_SOCKET)
937 {
938 if (WSAGetLastError() != WSAEWOULDBLOCK)
939 printf("socket error accept failed: %d\n", WSAGetLastError());
940 }
5a3e82f9 941 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
0a61b0df 942 {
943 closesocket(hSocket);
944 }
15f3ad4d
GA
945 else if (CNode::IsBanned(addr.ip))
946 {
947 printf("connetion from %s dropped (banned)\n", addr.ToString().c_str());
948 closesocket(hSocket);
949 }
0a61b0df 950 else
951 {
a6a5bb7c 952 printf("accepted connection %s\n", addr.ToString().c_str());
0a61b0df 953 CNode* pnode = new CNode(hSocket, addr, true);
954 pnode->AddRef();
955 CRITICAL_BLOCK(cs_vNodes)
956 vNodes.push_back(pnode);
957 }
958 }
959
960
961 //
962 // Service each socket
963 //
964 vector<CNode*> vNodesCopy;
965 CRITICAL_BLOCK(cs_vNodes)
966 {
967 vNodesCopy = vNodes;
223b6f1b 968 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 969 pnode->AddRef();
970 }
223b6f1b 971 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 972 {
973 if (fShutdown)
974 return;
975
976 //
977 // Receive
978 //
979 if (pnode->hSocket == INVALID_SOCKET)
980 continue;
981 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
982 {
983 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
984 {
985 CDataStream& vRecv = pnode->vRecv;
986 unsigned int nPos = vRecv.size();
987
49731745 988 if (nPos > ReceiveBufferSize()) {
0a61b0df 989 if (!pnode->fDisconnect)
9cbae55a 990 printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
0a61b0df 991 pnode->CloseSocketDisconnect();
992 }
9cbae55a
GA
993 else {
994 // typical socket buffer is 8K-64K
995 char pchBuf[0x10000];
996 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
997 if (nBytes > 0)
0a61b0df 998 {
9cbae55a
GA
999 vRecv.resize(nPos + nBytes);
1000 memcpy(&vRecv[nPos], pchBuf, nBytes);
1001 pnode->nLastRecv = GetTime();
1002 }
1003 else if (nBytes == 0)
1004 {
1005 // socket closed gracefully
0a61b0df 1006 if (!pnode->fDisconnect)
9cbae55a 1007 printf("socket closed\n");
0a61b0df 1008 pnode->CloseSocketDisconnect();
1009 }
9cbae55a
GA
1010 else if (nBytes < 0)
1011 {
1012 // error
1013 int nErr = WSAGetLastError();
1014 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1015 {
1016 if (!pnode->fDisconnect)
1017 printf("socket recv error %d\n", nErr);
1018 pnode->CloseSocketDisconnect();
1019 }
1020 }
0a61b0df 1021 }
1022 }
1023 }
1024
1025 //
1026 // Send
1027 //
1028 if (pnode->hSocket == INVALID_SOCKET)
1029 continue;
1030 if (FD_ISSET(pnode->hSocket, &fdsetSend))
1031 {
1032 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1033 {
1034 CDataStream& vSend = pnode->vSend;
1035 if (!vSend.empty())
1036 {
1037 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
1038 if (nBytes > 0)
1039 {
1040 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
1041 pnode->nLastSend = GetTime();
1042 }
1043 else if (nBytes < 0)
1044 {
1045 // error
1046 int nErr = WSAGetLastError();
1047 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
1048 {
1049 printf("socket send error %d\n", nErr);
1050 pnode->CloseSocketDisconnect();
1051 }
1052 }
49731745 1053 if (vSend.size() > SendBufferSize()) {
9cbae55a
GA
1054 if (!pnode->fDisconnect)
1055 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
1056 pnode->CloseSocketDisconnect();
1057 }
0a61b0df 1058 }
1059 }
1060 }
1061
1062 //
1063 // Inactivity checking
1064 //
1065 if (pnode->vSend.empty())
1066 pnode->nLastSendEmpty = GetTime();
1067 if (GetTime() - pnode->nTimeConnected > 60)
1068 {
1069 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1070 {
1071 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1072 pnode->fDisconnect = true;
1073 }
1074 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1075 {
1076 printf("socket not sending\n");
1077 pnode->fDisconnect = true;
1078 }
1079 else if (GetTime() - pnode->nLastRecv > 90*60)
1080 {
1081 printf("socket inactivity timeout\n");
1082 pnode->fDisconnect = true;
1083 }
1084 }
1085 }
1086 CRITICAL_BLOCK(cs_vNodes)
1087 {
223b6f1b 1088 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1089 pnode->Release();
1090 }
1091
0a61b0df 1092 Sleep(10);
1093 }
1094}
1095
1096
1097
1098
1099
1100
1101
1102
1103
8bb5edc1
MC
1104#ifdef USE_UPNP
1105void ThreadMapPort(void* parg)
1106{
1107 IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1108 try
1109 {
1110 vnThreadsRunning[5]++;
1111 ThreadMapPort2(parg);
1112 vnThreadsRunning[5]--;
1113 }
1114 catch (std::exception& e) {
1115 vnThreadsRunning[5]--;
1116 PrintException(&e, "ThreadMapPort()");
1117 } catch (...) {
1118 vnThreadsRunning[5]--;
1119 PrintException(NULL, "ThreadMapPort()");
1120 }
1121 printf("ThreadMapPort exiting\n");
1122}
1123
1124void ThreadMapPort2(void* parg)
1125{
1126 printf("ThreadMapPort started\n");
1127
1128 char port[6];
00bcfe0b 1129 sprintf(port, "%d", GetListenPort());
8bb5edc1
MC
1130
1131 const char * rootdescurl = 0;
1132 const char * multicastif = 0;
1133 const char * minissdpdpath = 0;
b4ada906 1134 int error = 0;
8bb5edc1
MC
1135 struct UPNPDev * devlist = 0;
1136 char lanaddr[64];
1137
b4ada906 1138 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
8bb5edc1
MC
1139
1140 struct UPNPUrls urls;
1141 struct IGDdatas data;
1142 int r;
1143
f285d4f4
DH
1144 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1145 if (r == 1)
8bb5edc1
MC
1146 {
1147 char intClient[16];
1148 char intPort[6];
15656981 1149 string strDesc = "Bitcoin " + FormatFullVersion();
8bb5edc1 1150 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
15656981 1151 port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0");
b4ada906 1152
8bb5edc1
MC
1153 if(r!=UPNPCOMMAND_SUCCESS)
1154 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1155 port, port, lanaddr, r, strupnperror(r));
1156 else
1157 printf("UPnP Port Mapping successful.\n");
1158 loop {
1159 if (fShutdown || !fUseUPnP)
1160 {
1161 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1162 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1163 freeUPNPDevlist(devlist); devlist = 0;
1164 FreeUPNPUrls(&urls);
1165 return;
1166 }
1167 Sleep(2000);
1168 }
1169 } else {
1170 printf("No valid UPnP IGDs found\n");
1171 freeUPNPDevlist(devlist); devlist = 0;
f285d4f4
DH
1172 if (r != 0)
1173 FreeUPNPUrls(&urls);
8bb5edc1 1174 loop {
973800b5 1175 if (fShutdown || !fUseUPnP)
8bb5edc1
MC
1176 return;
1177 Sleep(2000);
1178 }
1179 }
1180}
1181
1182void MapPort(bool fMapPort)
1183{
1184 if (fUseUPnP != fMapPort)
1185 {
1186 fUseUPnP = fMapPort;
64c7ee7e 1187 WriteSetting("fUseUPnP", fUseUPnP);
8bb5edc1
MC
1188 }
1189 if (fUseUPnP && vnThreadsRunning[5] < 1)
1190 {
1191 if (!CreateThread(ThreadMapPort, NULL))
1192 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1193 }
1194}
9f0ac169
GA
1195#else
1196void MapPort(bool /* unused fMapPort */)
1197{
1198 // Intentionally left blank.
1199}
8bb5edc1
MC
1200#endif
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
f684aec4
JG
1211static const char *strDNSSeed[] = {
1212 "bitseed.xf2.org",
f03c31db 1213 "dnsseed.bluematt.me",
f684aec4 1214};
0a61b0df 1215
f684aec4
JG
1216void DNSAddressSeed()
1217{
1218 int found = 0;
1219
ce8f78a7
MC
1220 if (!fTestNet)
1221 {
1222 printf("Loading addresses from DNS seeds (could take a while)\n");
d655a26c
SG
1223 CAddrDB addrDB;
1224 addrDB.TxnBegin();
f684aec4 1225
ce8f78a7
MC
1226 for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1227 vector<CAddress> vaddr;
1228 if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
a6a5bb7c 1229 {
ce8f78a7 1230 BOOST_FOREACH (CAddress& addr, vaddr)
a6a5bb7c 1231 {
ce8f78a7
MC
1232 if (addr.GetByte(3) != 127)
1233 {
1234 addr.nTime = 0;
d655a26c 1235 AddAddress(addr, 0, &addrDB);
ce8f78a7
MC
1236 found++;
1237 }
a6a5bb7c 1238 }
f684aec4
JG
1239 }
1240 }
d655a26c
SG
1241
1242 addrDB.TxnCommit(); // Save addresses (it's ok if this fails)
f684aec4
JG
1243 }
1244
448b4516 1245 printf("%d addresses found from DNS seeds\n", found);
f684aec4 1246}
0a61b0df 1247
1248
1249
1250unsigned int pnSeed[] =
1251{
bca179e8
DF
1252 0x6884ac63, 0x3ffecead, 0x2919b953, 0x0942fe50, 0x7a1d922e, 0xcdd6734a, 0x953a5bb6, 0x2c46922e,
1253 0xe2a5f143, 0xaa39103a, 0xa06afa5c, 0x135ffd59, 0xe8e82863, 0xf61ef029, 0xf75f042e, 0x2b363532,
1254 0x29b2df42, 0x16b1f64e, 0xd46e281b, 0x5280bf58, 0x60372229, 0x1be58e4f, 0xa8496f45, 0x1fb1a057,
1255 0x756b3844, 0x3bb79445, 0x0b375518, 0xcccb0102, 0xb682bf2e, 0x46431c02, 0x3a81073a, 0xa3771f1f,
1256 0x213a121f, 0x85dc2c1b, 0x56b4323b, 0xb34e8945, 0x3c40b33d, 0xfa276418, 0x1f818d29, 0xebe1e344,
1257 0xf6160a18, 0xf4fa384a, 0x34b09558, 0xb882b543, 0xe3ce2253, 0x6abf56d8, 0xe91b1155, 0x688ee6ad,
1258 0x2efc6058, 0x4792cd47, 0x0c32f757, 0x4c813a46, 0x8c93644a, 0x37507444, 0x813ad218, 0xdac06d4a,
1259 0xe4c63e4b, 0x21a1ea3c, 0x8d88556f, 0x30e9173a, 0x041f681b, 0xdc77ba50, 0xc0072753, 0xceddd44f,
1260 0x052d1743, 0xe3c77a4a, 0x13981c3a, 0x5685d918, 0x3c0e4e70, 0x3e56fb54, 0xb676ae0c, 0xac93c859,
1261 0x22279f43, 0x975a4542, 0xe527f071, 0xea162f2e, 0x3c65a32e, 0x5be5713b, 0x961ec418, 0xb202922e,
1262 0x5ef7be50, 0xce49f53e, 0x05803b47, 0x8463b055, 0x78576153, 0x3ec2ae3a, 0x4bbd7118, 0xafcee043,
1263 0x56a3e8ba, 0x6174de4d, 0x8d01ba4b, 0xc9af564e, 0xdbc9c547, 0xa627474d, 0xdada9244, 0xd3b3083a,
1264 0x523e071f, 0xd6b96f18, 0xbd527c46, 0xdf2bbb4d, 0xd37b4a4b, 0x3a6a2158, 0xc064b055, 0x18a8e055,
1265 0xec4dae3b, 0x0540416c, 0x475b4fbe, 0x064803b2, 0x48e9f062, 0x2898524b, 0xd315ff43, 0xf786d247,
1266 0xc7ea2f3e, 0xc087f043, 0xc163354b, 0x8250284d, 0xed300029, 0xbf36e05c, 0x8eb3ae4c, 0xe7aa623e,
1267 0x7ced0274, 0xdd362c1b, 0x362b995a, 0xca26b629, 0x3fc41618, 0xb97b364e, 0xa05b8729, 0x0f5e3c43,
1268 0xdf942618, 0x6aeb9b5b, 0xbf04762e, 0xfaaeb118, 0x87579958, 0x76520044, 0xc2660c5b, 0x628b201b,
1269 0xf193932e, 0x1c0ad045, 0xff908346, 0x8da9d4da, 0xed201c1f, 0xa47a2b1b, 0x330007d4, 0x8ba1ed47,
1270 0xb2f02d44, 0x7db62c1b, 0x781c454b, 0xc0300029, 0xb7062a45, 0x88b52e3a, 0x78dd6b63, 0x1cb9b718,
1271 0x5d358e47, 0x59912c3b, 0x79607544, 0x5197f759, 0xc023be48, 0xd1013743, 0x0f354057, 0x8e3aac3b,
1272 0x4114693e, 0x22316318, 0xe27dda50, 0x878eac3b, 0x4948a21f, 0x5db7f24c, 0x8ccb6157, 0x26a5de18,
1273 0x0a11bd43, 0x27bb1e41, 0x60a7a951, 0x3e16b35e, 0x07888b53, 0x5648a853, 0x0149fe50, 0xd070a34f,
1274 0x6454c96d, 0xd6e54758, 0xa96dc152, 0x65447861, 0xf6bdf95e, 0x10400202, 0x2c29d483, 0x18174732,
1275 0x1d840618, 0x12e61818, 0x089d3f3c, 0x917e931f, 0xd1b0c90e, 0x25bd3c42, 0xeb05775b, 0x7d550c59,
1276 0x6cfacb01, 0xe4224444, 0xa41dd943, 0x0f5aa643, 0x5e33731b, 0x81036d50, 0x6f46a0d1, 0x7731be43,
1277 0x14840e18, 0xf1e8d059, 0x661d2b1f, 0x40a3201b, 0x9407b843, 0xedf0254d, 0x7bd1a5bc, 0x073dbe51,
1278 0xe864a97b, 0x2efd947b, 0xb9ca0e45, 0x4e2113ad, 0xcc305731, 0xd39ca63c, 0x733df918, 0xda172b1f,
1279 0xaa03b34d, 0x7230fd4d, 0xf1ce6e3a, 0x2e9fab43, 0xa4010750, 0xa928bd18, 0x6809be42, 0xb19de348,
1280 0xff956270, 0x0d795f51, 0xd2dec247, 0x6df5774b, 0xbac11f79, 0xdfb05c75, 0x887683d8, 0xa1e83632,
1281 0x2c0f7671, 0x28bcb65d, 0xac2a7545, 0x3eebfc60, 0x304ad7c4, 0xa215a462, 0xc86f0f58, 0xcfb92ebe,
1282 0x5e23ed82, 0xf506184b, 0xec0f19b7, 0x060c59ad, 0x86ee3174, 0x85380774, 0xa199a562, 0x02b507ae,
1283 0x33eb2163, 0xf2112b1f, 0xb702ba50, 0x131b9618, 0x90ccd04a, 0x08f3273b, 0xecb61718, 0x64b8b44d,
1284 0x182bf4dc, 0xc7b68286, 0x6e318d5f, 0xfdb03654, 0xb3272e54, 0xe014ad4b, 0x274e4a31, 0x7806375c,
1285 0xbc34a748, 0x1b5ad94a, 0x6b54d10e, 0x73e2ae6e, 0x5529d483, 0x8455a76d, 0x99c13f47, 0x1d811741,
1286 0xa9782a78, 0x0b00464d, 0x7266ea50, 0x532dab46, 0x33e1413e, 0x780d0c18, 0x0fb0854e, 0x03370155,
1287 0x2693042e, 0xfa3d824a, 0x2bb1681b, 0x37ea2a18, 0x7fb8414b, 0x32e0713b, 0xacf38d3f, 0xa282716f,
1288 0xb1a09d7b, 0xa04b764b, 0x83c94d18, 0x05ee4c6d, 0x0e795f51, 0x46984352, 0xf80fc247, 0x3fccb946,
1289 0xd7ae244b, 0x0a8e0a4c, 0x57b141bc, 0x3647bed1, 0x1431b052, 0x803a8bbb, 0xfc69056b, 0xf5991862,
1290 0x14963b2e, 0xd35d5dda, 0xc6c73574, 0xc8f1405b, 0x0ca4224d, 0xecd36071, 0xa9461754, 0xe7a0ed72,
1291 0x559e8346, 0x1c9beec1, 0xc786ea4a, 0x9561b44d, 0x9788074d, 0x1a69934f, 0x23c5614c, 0x07c79d4b,
1292 0xc7ee52db, 0xc72df351, 0xcb135e44, 0xa0988346, 0xc211fc4c, 0x87dec34b, 0x1381074d, 0x04a65cb7,
1293 0x4409083a, 0x4a407a4c, 0x92b8d37d, 0xacf50b4d, 0xa58aa5bc, 0x448f801f, 0x9c83762e, 0x6fd5734a,
1294 0xfe2d454b, 0x84144c55, 0x05190e4c, 0xb2151448, 0x63867a3e, 0x16099018, 0x9c010d3c, 0x962d8f3d,
1295 0xd51ee453, 0x9d86801f, 0x68e87b47, 0x6bf7bb73, 0x5fc7910e, 0x10d90118, 0x3db04442, 0x729d3e4b,
1296 0xc397d842, 0x57bb15ad, 0x72f31f4e, 0xc9380043, 0x2bb24e18, 0xd9b8ab50, 0xb786801f, 0xf4dc4847,
1297 0x85f4bb51, 0x4435995b, 0x5ba07e40, 0x2c57392e, 0x3628124b, 0x9839b64b, 0x6fe8b24d, 0xaddce847,
1298 0x75260e45, 0x0c572a43, 0xfea21902, 0xb9f9742e, 0x5a70d443, 0x8fc5910e, 0x868d4744, 0x56245e02,
1299 0xd7eb5f02, 0x35c12c1b, 0x4373034b, 0x8786554c, 0xa6facf18, 0x4b11a31f, 0x3570664e, 0x5a64bc42,
1300 0x0b03983f, 0x8f457e4c, 0x0fd874c3, 0xb6cf31b2, 0x2bbc2d4e, 0x146ca5b2, 0x9d00b150, 0x048a4153,
1301 0xca4dcd43, 0xc1607cca, 0x8234cf57, 0x9c7daead, 0x3dc07658, 0xea5c6e4c, 0xf1a0084e, 0x16d2ee53,
1302 0x1b849418, 0xfe913a47, 0x1e988f62, 0x208b644c, 0xc55ee980, 0xbdbce747, 0xf59a384e, 0x0f56091b,
1303 0x7417b745, 0x0c37344e, 0x2c62ab47, 0xf8533a4d, 0x8030084d, 0x76b93c4b, 0xda6ea0ad, 0x3c54f618,
1304 0x63b0de1f, 0x7370d858, 0x1a70bb4c, 0xdda63b2e, 0x60b2ba50, 0x1ba7d048, 0xbe1b2c1b, 0xabea5747,
1305 0x29ad2e4d, 0xe8cd7642, 0x66c80e18, 0x138bf34a, 0xc6145e44, 0x2586794c, 0x07bc5478, 0x0da0b14d,
1306 0x8f95354e, 0x9eb11c62, 0xa1545e46, 0x2e7a2602, 0x408c9c3d, 0x59065d55, 0xf51d1a4c, 0x3bbc6a4e,
1307 0xc71b2a2e, 0xcdaaa545, 0x17d659d0, 0x5202e7ad, 0xf1b68445, 0x93375961, 0xbd88a043, 0x066ad655,
1308 0x890f6318, 0x7b7dca47, 0x99bdd662, 0x3bb4fc53, 0x1231efdc, 0xc0a99444, 0x96bbea47, 0x61ed8748,
1309 0x27dfa73b, 0x8d4d1754, 0x3460042e, 0x551f0c4c, 0x8d0e0718, 0x162ddc53, 0x53231718, 0x1ecd65d0,
1310 0x944d28bc, 0x3b79d058, 0xaff97fbc, 0x4860006c, 0xc101c90e, 0xace41743, 0xa5975d4c, 0x5cc2703e,
1311 0xb55a4450, 0x02d18840, 0xee2765ae, 0xd6012fd5, 0x24c94d7d, 0x8c6eec47, 0x7520ba5d, 0x9e15e460,
1312 0x8510b04c, 0x75ec3847, 0x1dfa6661, 0xe172b3ad, 0x5744c90e, 0x52a0a152, 0x8d6fad18, 0x67b74b6d,
1313 0x93a089b2, 0x0f3ac5d5, 0xe5de1855, 0x43d25747, 0x4bad804a, 0x55b408d8, 0x60a36441, 0xf553e860,
1314 0xdb2fa2c8, 0x03152b32, 0xdd27a7d5, 0x3116a8b8, 0x0a1d708c, 0xeee2f13c, 0x6acf436f, 0xce6eb4ca,
1315 0x101cd3d9, 0x1c48a6b8, 0xe57d6f44, 0x93dcf562,
0a61b0df 1316};
1317
1318
1319
1320void ThreadOpenConnections(void* parg)
1321{
1322 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1323 try
1324 {
1325 vnThreadsRunning[1]++;
1326 ThreadOpenConnections2(parg);
1327 vnThreadsRunning[1]--;
1328 }
1329 catch (std::exception& e) {
1330 vnThreadsRunning[1]--;
1331 PrintException(&e, "ThreadOpenConnections()");
1332 } catch (...) {
1333 vnThreadsRunning[1]--;
1334 PrintException(NULL, "ThreadOpenConnections()");
1335 }
1336 printf("ThreadOpenConnections exiting\n");
1337}
1338
1339void ThreadOpenConnections2(void* parg)
1340{
1341 printf("ThreadOpenConnections started\n");
1342
1343 // Connect to specific addresses
1344 if (mapArgs.count("-connect"))
1345 {
1346 for (int64 nLoop = 0;; nLoop++)
1347 {
223b6f1b 1348 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1349 {
a6a5bb7c 1350 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1351 if (addr.IsValid())
1352 OpenNetworkConnection(addr);
1353 for (int i = 0; i < 10 && i < nLoop; i++)
1354 {
1355 Sleep(500);
1356 if (fShutdown)
1357 return;
1358 }
1359 }
1360 }
1361 }
1362
1363 // Connect to manually added nodes first
1364 if (mapArgs.count("-addnode"))
1365 {
223b6f1b 1366 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
0a61b0df 1367 {
a6a5bb7c 1368 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1369 if (addr.IsValid())
1370 {
1371 OpenNetworkConnection(addr);
1372 Sleep(500);
1373 if (fShutdown)
1374 return;
1375 }
1376 }
1377 }
1378
1379 // Initiate network connections
1380 int64 nStart = GetTime();
1381 loop
1382 {
1383 // Limit outbound connections
1384 vnThreadsRunning[1]--;
1385 Sleep(500);
1386 loop
1387 {
1388 int nOutbound = 0;
1389 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1390 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1391 if (!pnode->fInbound)
1392 nOutbound++;
1393 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
5a3e82f9 1394 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
0a61b0df 1395 if (nOutbound < nMaxOutboundConnections)
1396 break;
1397 Sleep(2000);
1398 if (fShutdown)
1399 return;
1400 }
1401 vnThreadsRunning[1]++;
1402 if (fShutdown)
1403 return;
1404
1405 CRITICAL_BLOCK(cs_mapAddresses)
1406 {
1407 // Add seed nodes if IRC isn't working
0a61b0df 1408 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
5cbf7532 1409 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
0a61b0df 1410 {
1411 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1412 {
1413 // It'll only connect to one or two seed nodes because once it connects,
1414 // it'll get a pile of addresses with newer timestamps.
86fd7c5a
GA
1415 // Seed nodes are given a random 'last seen time' of between one and two
1416 // weeks ago.
1417 const int64 nOneWeek = 7*24*60*60;
0a61b0df 1418 CAddress addr;
1419 addr.ip = pnSeed[i];
86fd7c5a 1420 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
0a61b0df 1421 AddAddress(addr);
1422 }
0a61b0df 1423 }
1424 }
1425
1426
1427 //
1428 // Choose an address to connect to based on most recently seen
1429 //
1430 CAddress addrConnect;
1431 int64 nBest = INT64_MIN;
1432
1433 // Only connect to one address per a.b.?.? range.
1434 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1435 set<unsigned int> setConnected;
1436 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1437 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1438 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1439
a4e6ae10
LD
1440 int64 nANow = GetAdjustedTime();
1441
0a61b0df 1442 CRITICAL_BLOCK(cs_mapAddresses)
1443 {
223b6f1b 1444 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
0a61b0df 1445 {
1446 const CAddress& addr = item.second;
1447 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1448 continue;
a4e6ae10
LD
1449 int64 nSinceLastSeen = nANow - addr.nTime;
1450 int64 nSinceLastTry = nANow - addr.nLastTry;
0a61b0df 1451
1452 // Randomize the order in a deterministic way, putting the standard port first
1453 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
a6a5bb7c 1454 if (addr.port != htons(GetDefaultPort()))
0a61b0df 1455 nRandomizer += 2 * 60 * 60;
1456
1457 // Last seen Base retry frequency
1458 // <1 hour 10 min
1459 // 1 hour 1 hour
1460 // 4 hours 2 hours
1461 // 24 hours 5 hours
1462 // 48 hours 7 hours
1463 // 7 days 13 hours
1464 // 30 days 27 hours
1465 // 90 days 46 hours
1466 // 365 days 93 hours
1467 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1468
1469 // Fast reconnect for one hour after last seen
1470 if (nSinceLastSeen < 60 * 60)
1471 nDelay = 10 * 60;
1472
1473 // Limit retry frequency
1474 if (nSinceLastTry < nDelay)
1475 continue;
1476
1477 // If we have IRC, we'll be notified when they first come online,
1478 // and again every 24 hours by the refresh broadcast.
1479 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1480 continue;
1481
1482 // Only try the old stuff if we don't have enough connections
1483 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1484 continue;
1485
1486 // If multiple addresses are ready, prioritize by time since
1487 // last seen and time since last tried.
1488 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1489 if (nScore > nBest)
1490 {
1491 nBest = nScore;
1492 addrConnect = addr;
1493 }
1494 }
1495 }
1496
1497 if (addrConnect.IsValid())
1498 OpenNetworkConnection(addrConnect);
1499 }
1500}
1501
1502bool OpenNetworkConnection(const CAddress& addrConnect)
1503{
1504 //
1505 // Initiate outbound network connection
1506 //
1507 if (fShutdown)
1508 return false;
15f3ad4d
GA
1509 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
1510 FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
0a61b0df 1511 return false;
1512
1513 vnThreadsRunning[1]--;
1514 CNode* pnode = ConnectNode(addrConnect);
1515 vnThreadsRunning[1]++;
1516 if (fShutdown)
1517 return false;
1518 if (!pnode)
1519 return false;
1520 pnode->fNetworkNode = true;
1521
0a61b0df 1522 return true;
1523}
1524
1525
1526
1527
1528
1529
1530
1531
1532void ThreadMessageHandler(void* parg)
1533{
1534 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1535 try
1536 {
1537 vnThreadsRunning[2]++;
1538 ThreadMessageHandler2(parg);
1539 vnThreadsRunning[2]--;
1540 }
1541 catch (std::exception& e) {
1542 vnThreadsRunning[2]--;
1543 PrintException(&e, "ThreadMessageHandler()");
1544 } catch (...) {
1545 vnThreadsRunning[2]--;
1546 PrintException(NULL, "ThreadMessageHandler()");
1547 }
1548 printf("ThreadMessageHandler exiting\n");
1549}
1550
1551void ThreadMessageHandler2(void* parg)
1552{
1553 printf("ThreadMessageHandler started\n");
1554 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1555 while (!fShutdown)
1556 {
1557 vector<CNode*> vNodesCopy;
1558 CRITICAL_BLOCK(cs_vNodes)
1559 {
1560 vNodesCopy = vNodes;
223b6f1b 1561 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1562 pnode->AddRef();
1563 }
1564
1565 // Poll the connected nodes for messages
1566 CNode* pnodeTrickle = NULL;
1567 if (!vNodesCopy.empty())
1568 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
223b6f1b 1569 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1570 {
1571 // Receive messages
1572 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1573 ProcessMessages(pnode);
1574 if (fShutdown)
1575 return;
1576
1577 // Send messages
1578 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1579 SendMessages(pnode, pnode == pnodeTrickle);
1580 if (fShutdown)
1581 return;
1582 }
1583
1584 CRITICAL_BLOCK(cs_vNodes)
1585 {
223b6f1b 1586 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1587 pnode->Release();
1588 }
1589
7629d36a 1590 // Wait and allow messages to bunch up.
1591 // Reduce vnThreadsRunning so StopNode has permission to exit while
1592 // we're sleeping, but we must always check fShutdown after doing this.
0a61b0df 1593 vnThreadsRunning[2]--;
1594 Sleep(100);
3f647537 1595 if (fRequestShutdown)
1596 Shutdown(NULL);
0a61b0df 1597 vnThreadsRunning[2]++;
1598 if (fShutdown)
1599 return;
1600 }
1601}
1602
1603
1604
1605
1606
1607
0a61b0df 1608bool BindListenPort(string& strError)
1609{
1610 strError = "";
1611 int nOne = 1;
00bcfe0b 1612 addrLocalHost.port = htons(GetListenPort());
0a61b0df 1613
6853e627 1614#ifdef WIN32
0a61b0df 1615 // Initialize Windows Sockets
1616 WSADATA wsadata;
1617 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1618 if (ret != NO_ERROR)
1619 {
1620 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1621 printf("%s\n", strError.c_str());
1622 return false;
1623 }
1624#endif
1625
1626 // Create socket for listening for incoming connections
1627 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1628 if (hListenSocket == INVALID_SOCKET)
1629 {
1630 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1631 printf("%s\n", strError.c_str());
1632 return false;
1633 }
1634
ec93a0e2 1635#ifdef SO_NOSIGPIPE
0a61b0df 1636 // Different way of disabling SIGPIPE on BSD
1637 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1638#endif
1639
6853e627 1640#ifndef WIN32
0a61b0df 1641 // Allow binding if the port is still in TIME_WAIT state after
1642 // the program was closed and restarted. Not an issue on windows.
1643 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1644#endif
1645
6853e627 1646#ifdef WIN32
0a61b0df 1647 // Set to nonblocking, incoming connections will also inherit this
1648 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1649#else
1650 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1651#endif
1652 {
1653 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1654 printf("%s\n", strError.c_str());
1655 return false;
1656 }
1657
1658 // The sockaddr_in structure specifies the address family,
1659 // IP address, and port for the socket that is being bound
1660 struct sockaddr_in sockaddr;
1661 memset(&sockaddr, 0, sizeof(sockaddr));
1662 sockaddr.sin_family = AF_INET;
1663 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
00bcfe0b 1664 sockaddr.sin_port = htons(GetListenPort());
0a61b0df 1665 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1666 {
1667 int nErr = WSAGetLastError();
1668 if (nErr == WSAEADDRINUSE)
d9c6b09a 1669 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
0a61b0df 1670 else
1671 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1672 printf("%s\n", strError.c_str());
1673 return false;
1674 }
1675 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1676
1677 // Listen for incoming connections
1678 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1679 {
1680 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1681 printf("%s\n", strError.c_str());
1682 return false;
1683 }
1684
1685 return true;
1686}
1687
1688void StartNode(void* parg)
1689{
1690 if (pnodeLocalHost == NULL)
a6a5bb7c 1691 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
0a61b0df 1692
6853e627 1693#ifdef WIN32
0a61b0df 1694 // Get local host ip
1695 char pszHostName[1000] = "";
1696 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1697 {
a6a5bb7c 1698 vector<CAddress> vaddr;
545a679a 1699 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
223b6f1b 1700 BOOST_FOREACH (const CAddress &addr, vaddr)
a6a5bb7c 1701 if (addr.GetByte(3) != 127)
0a61b0df 1702 {
1703 addrLocalHost = addr;
1704 break;
1705 }
0a61b0df 1706 }
1707#else
1708 // Get local host ip
1709 struct ifaddrs* myaddrs;
1710 if (getifaddrs(&myaddrs) == 0)
1711 {
1712 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1713 {
1714 if (ifa->ifa_addr == NULL) continue;
1715 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1716 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1717 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1718 char pszIP[100];
1719 if (ifa->ifa_addr->sa_family == AF_INET)
1720 {
1721 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1722 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1723 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1724
1725 // Take the first IP that isn't loopback 127.x.x.x
00bcfe0b 1726 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
0a61b0df 1727 if (addr.IsValid() && addr.GetByte(3) != 127)
1728 {
1729 addrLocalHost = addr;
1730 break;
1731 }
1732 }
1733 else if (ifa->ifa_addr->sa_family == AF_INET6)
1734 {
1735 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1736 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1737 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1738 }
1739 }
1740 freeifaddrs(myaddrs);
1741 }
1742#endif
1743 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1744
5f88e888 1745 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
0a61b0df 1746 {
1747 // Proxies can't take incoming connections
1748 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1749 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1750 }
1751 else
1752 {
629e37dd 1753 CreateThread(ThreadGetMyExternalIP, NULL);
0a61b0df 1754 }
1755
1756 //
1757 // Start threads
1758 //
1759
8bb5edc1
MC
1760 // Map ports with UPnP
1761 if (fHaveUPnP)
1762 MapPort(fUseUPnP);
1763
0a61b0df 1764 // Get addresses from IRC and advertise ours
1765 if (!CreateThread(ThreadIRCSeed, NULL))
1766 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1767
1768 // Send and receive from sockets, accept connections
65ba3e2f
LD
1769 if (!CreateThread(ThreadSocketHandler, NULL))
1770 printf("Error: CreateThread(ThreadSocketHandler) failed\n");
0a61b0df 1771
1772 // Initiate outbound connections
1773 if (!CreateThread(ThreadOpenConnections, NULL))
1774 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1775
1776 // Process messages
1777 if (!CreateThread(ThreadMessageHandler, NULL))
1778 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1779
1780 // Generate coins in the background
64c7ee7e 1781 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
0a61b0df 1782}
1783
1784bool StopNode()
1785{
1786 printf("StopNode()\n");
1787 fShutdown = true;
1788 nTransactionsUpdated++;
1789 int64 nStart = GetTime();
8bb5edc1
MC
1790 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1791#ifdef USE_UPNP
1792 || vnThreadsRunning[5] > 0
1793#endif
1794 )
0a61b0df 1795 {
1796 if (GetTime() - nStart > 20)
1797 break;
1798 Sleep(20);
1799 }
1800 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1801 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1802 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1803 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1804 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
8bb5edc1 1805 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
0a61b0df 1806 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1807 Sleep(20);
1808 Sleep(50);
1809
1810 return true;
1811}
1812
1813class CNetCleanup
1814{
1815public:
1816 CNetCleanup()
1817 {
1818 }
1819 ~CNetCleanup()
1820 {
1821 // Close sockets
223b6f1b 1822 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1823 if (pnode->hSocket != INVALID_SOCKET)
1824 closesocket(pnode->hSocket);
1825 if (hListenSocket != INVALID_SOCKET)
1826 if (closesocket(hListenSocket) == SOCKET_ERROR)
1827 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1828
6853e627 1829#ifdef WIN32
0a61b0df 1830 // Shutdown Windows Sockets
1831 WSACleanup();
1832#endif
1833 }
1834}
1835instance_of_cnetcleanup;
This page took 0.311743 seconds and 4 git commands to generate.