]> Git Repo - VerusCoin.git/blame - src/net.cpp
ignore stuff
[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{
bca179e8
DF
1196 0x6884ac63, 0x3ffecead, 0x2919b953, 0x0942fe50, 0x7a1d922e, 0xcdd6734a, 0x953a5bb6, 0x2c46922e,
1197 0xe2a5f143, 0xaa39103a, 0xa06afa5c, 0x135ffd59, 0xe8e82863, 0xf61ef029, 0xf75f042e, 0x2b363532,
1198 0x29b2df42, 0x16b1f64e, 0xd46e281b, 0x5280bf58, 0x60372229, 0x1be58e4f, 0xa8496f45, 0x1fb1a057,
1199 0x756b3844, 0x3bb79445, 0x0b375518, 0xcccb0102, 0xb682bf2e, 0x46431c02, 0x3a81073a, 0xa3771f1f,
1200 0x213a121f, 0x85dc2c1b, 0x56b4323b, 0xb34e8945, 0x3c40b33d, 0xfa276418, 0x1f818d29, 0xebe1e344,
1201 0xf6160a18, 0xf4fa384a, 0x34b09558, 0xb882b543, 0xe3ce2253, 0x6abf56d8, 0xe91b1155, 0x688ee6ad,
1202 0x2efc6058, 0x4792cd47, 0x0c32f757, 0x4c813a46, 0x8c93644a, 0x37507444, 0x813ad218, 0xdac06d4a,
1203 0xe4c63e4b, 0x21a1ea3c, 0x8d88556f, 0x30e9173a, 0x041f681b, 0xdc77ba50, 0xc0072753, 0xceddd44f,
1204 0x052d1743, 0xe3c77a4a, 0x13981c3a, 0x5685d918, 0x3c0e4e70, 0x3e56fb54, 0xb676ae0c, 0xac93c859,
1205 0x22279f43, 0x975a4542, 0xe527f071, 0xea162f2e, 0x3c65a32e, 0x5be5713b, 0x961ec418, 0xb202922e,
1206 0x5ef7be50, 0xce49f53e, 0x05803b47, 0x8463b055, 0x78576153, 0x3ec2ae3a, 0x4bbd7118, 0xafcee043,
1207 0x56a3e8ba, 0x6174de4d, 0x8d01ba4b, 0xc9af564e, 0xdbc9c547, 0xa627474d, 0xdada9244, 0xd3b3083a,
1208 0x523e071f, 0xd6b96f18, 0xbd527c46, 0xdf2bbb4d, 0xd37b4a4b, 0x3a6a2158, 0xc064b055, 0x18a8e055,
1209 0xec4dae3b, 0x0540416c, 0x475b4fbe, 0x064803b2, 0x48e9f062, 0x2898524b, 0xd315ff43, 0xf786d247,
1210 0xc7ea2f3e, 0xc087f043, 0xc163354b, 0x8250284d, 0xed300029, 0xbf36e05c, 0x8eb3ae4c, 0xe7aa623e,
1211 0x7ced0274, 0xdd362c1b, 0x362b995a, 0xca26b629, 0x3fc41618, 0xb97b364e, 0xa05b8729, 0x0f5e3c43,
1212 0xdf942618, 0x6aeb9b5b, 0xbf04762e, 0xfaaeb118, 0x87579958, 0x76520044, 0xc2660c5b, 0x628b201b,
1213 0xf193932e, 0x1c0ad045, 0xff908346, 0x8da9d4da, 0xed201c1f, 0xa47a2b1b, 0x330007d4, 0x8ba1ed47,
1214 0xb2f02d44, 0x7db62c1b, 0x781c454b, 0xc0300029, 0xb7062a45, 0x88b52e3a, 0x78dd6b63, 0x1cb9b718,
1215 0x5d358e47, 0x59912c3b, 0x79607544, 0x5197f759, 0xc023be48, 0xd1013743, 0x0f354057, 0x8e3aac3b,
1216 0x4114693e, 0x22316318, 0xe27dda50, 0x878eac3b, 0x4948a21f, 0x5db7f24c, 0x8ccb6157, 0x26a5de18,
1217 0x0a11bd43, 0x27bb1e41, 0x60a7a951, 0x3e16b35e, 0x07888b53, 0x5648a853, 0x0149fe50, 0xd070a34f,
1218 0x6454c96d, 0xd6e54758, 0xa96dc152, 0x65447861, 0xf6bdf95e, 0x10400202, 0x2c29d483, 0x18174732,
1219 0x1d840618, 0x12e61818, 0x089d3f3c, 0x917e931f, 0xd1b0c90e, 0x25bd3c42, 0xeb05775b, 0x7d550c59,
1220 0x6cfacb01, 0xe4224444, 0xa41dd943, 0x0f5aa643, 0x5e33731b, 0x81036d50, 0x6f46a0d1, 0x7731be43,
1221 0x14840e18, 0xf1e8d059, 0x661d2b1f, 0x40a3201b, 0x9407b843, 0xedf0254d, 0x7bd1a5bc, 0x073dbe51,
1222 0xe864a97b, 0x2efd947b, 0xb9ca0e45, 0x4e2113ad, 0xcc305731, 0xd39ca63c, 0x733df918, 0xda172b1f,
1223 0xaa03b34d, 0x7230fd4d, 0xf1ce6e3a, 0x2e9fab43, 0xa4010750, 0xa928bd18, 0x6809be42, 0xb19de348,
1224 0xff956270, 0x0d795f51, 0xd2dec247, 0x6df5774b, 0xbac11f79, 0xdfb05c75, 0x887683d8, 0xa1e83632,
1225 0x2c0f7671, 0x28bcb65d, 0xac2a7545, 0x3eebfc60, 0x304ad7c4, 0xa215a462, 0xc86f0f58, 0xcfb92ebe,
1226 0x5e23ed82, 0xf506184b, 0xec0f19b7, 0x060c59ad, 0x86ee3174, 0x85380774, 0xa199a562, 0x02b507ae,
1227 0x33eb2163, 0xf2112b1f, 0xb702ba50, 0x131b9618, 0x90ccd04a, 0x08f3273b, 0xecb61718, 0x64b8b44d,
1228 0x182bf4dc, 0xc7b68286, 0x6e318d5f, 0xfdb03654, 0xb3272e54, 0xe014ad4b, 0x274e4a31, 0x7806375c,
1229 0xbc34a748, 0x1b5ad94a, 0x6b54d10e, 0x73e2ae6e, 0x5529d483, 0x8455a76d, 0x99c13f47, 0x1d811741,
1230 0xa9782a78, 0x0b00464d, 0x7266ea50, 0x532dab46, 0x33e1413e, 0x780d0c18, 0x0fb0854e, 0x03370155,
1231 0x2693042e, 0xfa3d824a, 0x2bb1681b, 0x37ea2a18, 0x7fb8414b, 0x32e0713b, 0xacf38d3f, 0xa282716f,
1232 0xb1a09d7b, 0xa04b764b, 0x83c94d18, 0x05ee4c6d, 0x0e795f51, 0x46984352, 0xf80fc247, 0x3fccb946,
1233 0xd7ae244b, 0x0a8e0a4c, 0x57b141bc, 0x3647bed1, 0x1431b052, 0x803a8bbb, 0xfc69056b, 0xf5991862,
1234 0x14963b2e, 0xd35d5dda, 0xc6c73574, 0xc8f1405b, 0x0ca4224d, 0xecd36071, 0xa9461754, 0xe7a0ed72,
1235 0x559e8346, 0x1c9beec1, 0xc786ea4a, 0x9561b44d, 0x9788074d, 0x1a69934f, 0x23c5614c, 0x07c79d4b,
1236 0xc7ee52db, 0xc72df351, 0xcb135e44, 0xa0988346, 0xc211fc4c, 0x87dec34b, 0x1381074d, 0x04a65cb7,
1237 0x4409083a, 0x4a407a4c, 0x92b8d37d, 0xacf50b4d, 0xa58aa5bc, 0x448f801f, 0x9c83762e, 0x6fd5734a,
1238 0xfe2d454b, 0x84144c55, 0x05190e4c, 0xb2151448, 0x63867a3e, 0x16099018, 0x9c010d3c, 0x962d8f3d,
1239 0xd51ee453, 0x9d86801f, 0x68e87b47, 0x6bf7bb73, 0x5fc7910e, 0x10d90118, 0x3db04442, 0x729d3e4b,
1240 0xc397d842, 0x57bb15ad, 0x72f31f4e, 0xc9380043, 0x2bb24e18, 0xd9b8ab50, 0xb786801f, 0xf4dc4847,
1241 0x85f4bb51, 0x4435995b, 0x5ba07e40, 0x2c57392e, 0x3628124b, 0x9839b64b, 0x6fe8b24d, 0xaddce847,
1242 0x75260e45, 0x0c572a43, 0xfea21902, 0xb9f9742e, 0x5a70d443, 0x8fc5910e, 0x868d4744, 0x56245e02,
1243 0xd7eb5f02, 0x35c12c1b, 0x4373034b, 0x8786554c, 0xa6facf18, 0x4b11a31f, 0x3570664e, 0x5a64bc42,
1244 0x0b03983f, 0x8f457e4c, 0x0fd874c3, 0xb6cf31b2, 0x2bbc2d4e, 0x146ca5b2, 0x9d00b150, 0x048a4153,
1245 0xca4dcd43, 0xc1607cca, 0x8234cf57, 0x9c7daead, 0x3dc07658, 0xea5c6e4c, 0xf1a0084e, 0x16d2ee53,
1246 0x1b849418, 0xfe913a47, 0x1e988f62, 0x208b644c, 0xc55ee980, 0xbdbce747, 0xf59a384e, 0x0f56091b,
1247 0x7417b745, 0x0c37344e, 0x2c62ab47, 0xf8533a4d, 0x8030084d, 0x76b93c4b, 0xda6ea0ad, 0x3c54f618,
1248 0x63b0de1f, 0x7370d858, 0x1a70bb4c, 0xdda63b2e, 0x60b2ba50, 0x1ba7d048, 0xbe1b2c1b, 0xabea5747,
1249 0x29ad2e4d, 0xe8cd7642, 0x66c80e18, 0x138bf34a, 0xc6145e44, 0x2586794c, 0x07bc5478, 0x0da0b14d,
1250 0x8f95354e, 0x9eb11c62, 0xa1545e46, 0x2e7a2602, 0x408c9c3d, 0x59065d55, 0xf51d1a4c, 0x3bbc6a4e,
1251 0xc71b2a2e, 0xcdaaa545, 0x17d659d0, 0x5202e7ad, 0xf1b68445, 0x93375961, 0xbd88a043, 0x066ad655,
1252 0x890f6318, 0x7b7dca47, 0x99bdd662, 0x3bb4fc53, 0x1231efdc, 0xc0a99444, 0x96bbea47, 0x61ed8748,
1253 0x27dfa73b, 0x8d4d1754, 0x3460042e, 0x551f0c4c, 0x8d0e0718, 0x162ddc53, 0x53231718, 0x1ecd65d0,
1254 0x944d28bc, 0x3b79d058, 0xaff97fbc, 0x4860006c, 0xc101c90e, 0xace41743, 0xa5975d4c, 0x5cc2703e,
1255 0xb55a4450, 0x02d18840, 0xee2765ae, 0xd6012fd5, 0x24c94d7d, 0x8c6eec47, 0x7520ba5d, 0x9e15e460,
1256 0x8510b04c, 0x75ec3847, 0x1dfa6661, 0xe172b3ad, 0x5744c90e, 0x52a0a152, 0x8d6fad18, 0x67b74b6d,
1257 0x93a089b2, 0x0f3ac5d5, 0xe5de1855, 0x43d25747, 0x4bad804a, 0x55b408d8, 0x60a36441, 0xf553e860,
1258 0xdb2fa2c8, 0x03152b32, 0xdd27a7d5, 0x3116a8b8, 0x0a1d708c, 0xeee2f13c, 0x6acf436f, 0xce6eb4ca,
1259 0x101cd3d9, 0x1c48a6b8, 0xe57d6f44, 0x93dcf562,
0a61b0df 1260};
1261
1262
1263
1264void ThreadOpenConnections(void* parg)
1265{
1266 IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1267 try
1268 {
1269 vnThreadsRunning[1]++;
1270 ThreadOpenConnections2(parg);
1271 vnThreadsRunning[1]--;
1272 }
1273 catch (std::exception& e) {
1274 vnThreadsRunning[1]--;
1275 PrintException(&e, "ThreadOpenConnections()");
1276 } catch (...) {
1277 vnThreadsRunning[1]--;
1278 PrintException(NULL, "ThreadOpenConnections()");
1279 }
1280 printf("ThreadOpenConnections exiting\n");
1281}
1282
1283void ThreadOpenConnections2(void* parg)
1284{
1285 printf("ThreadOpenConnections started\n");
1286
1287 // Connect to specific addresses
1288 if (mapArgs.count("-connect"))
1289 {
1290 for (int64 nLoop = 0;; nLoop++)
1291 {
223b6f1b 1292 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
0a61b0df 1293 {
a6a5bb7c 1294 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1295 if (addr.IsValid())
1296 OpenNetworkConnection(addr);
1297 for (int i = 0; i < 10 && i < nLoop; i++)
1298 {
1299 Sleep(500);
1300 if (fShutdown)
1301 return;
1302 }
1303 }
1304 }
1305 }
1306
1307 // Connect to manually added nodes first
1308 if (mapArgs.count("-addnode"))
1309 {
223b6f1b 1310 BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
0a61b0df 1311 {
a6a5bb7c 1312 CAddress addr(strAddr, fAllowDNS);
0a61b0df 1313 if (addr.IsValid())
1314 {
1315 OpenNetworkConnection(addr);
1316 Sleep(500);
1317 if (fShutdown)
1318 return;
1319 }
1320 }
1321 }
1322
1323 // Initiate network connections
1324 int64 nStart = GetTime();
1325 loop
1326 {
1327 // Limit outbound connections
1328 vnThreadsRunning[1]--;
1329 Sleep(500);
1330 loop
1331 {
1332 int nOutbound = 0;
1333 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1334 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1335 if (!pnode->fInbound)
1336 nOutbound++;
1337 int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
5a3e82f9 1338 nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
0a61b0df 1339 if (nOutbound < nMaxOutboundConnections)
1340 break;
1341 Sleep(2000);
1342 if (fShutdown)
1343 return;
1344 }
1345 vnThreadsRunning[1]++;
1346 if (fShutdown)
1347 return;
1348
1349 CRITICAL_BLOCK(cs_mapAddresses)
1350 {
1351 // Add seed nodes if IRC isn't working
0a61b0df 1352 bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
5cbf7532 1353 if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
0a61b0df 1354 {
1355 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1356 {
1357 // It'll only connect to one or two seed nodes because once it connects,
1358 // it'll get a pile of addresses with newer timestamps.
86fd7c5a
GA
1359 // Seed nodes are given a random 'last seen time' of between one and two
1360 // weeks ago.
1361 const int64 nOneWeek = 7*24*60*60;
0a61b0df 1362 CAddress addr;
1363 addr.ip = pnSeed[i];
86fd7c5a 1364 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
0a61b0df 1365 AddAddress(addr);
1366 }
0a61b0df 1367 }
1368 }
1369
1370
1371 //
1372 // Choose an address to connect to based on most recently seen
1373 //
1374 CAddress addrConnect;
1375 int64 nBest = INT64_MIN;
1376
1377 // Only connect to one address per a.b.?.? range.
1378 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1379 set<unsigned int> setConnected;
1380 CRITICAL_BLOCK(cs_vNodes)
223b6f1b 1381 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1382 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1383
1384 CRITICAL_BLOCK(cs_mapAddresses)
1385 {
223b6f1b 1386 BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
0a61b0df 1387 {
1388 const CAddress& addr = item.second;
1389 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1390 continue;
1391 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1392 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1393
1394 // Randomize the order in a deterministic way, putting the standard port first
1395 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
a6a5bb7c 1396 if (addr.port != htons(GetDefaultPort()))
0a61b0df 1397 nRandomizer += 2 * 60 * 60;
1398
1399 // Last seen Base retry frequency
1400 // <1 hour 10 min
1401 // 1 hour 1 hour
1402 // 4 hours 2 hours
1403 // 24 hours 5 hours
1404 // 48 hours 7 hours
1405 // 7 days 13 hours
1406 // 30 days 27 hours
1407 // 90 days 46 hours
1408 // 365 days 93 hours
1409 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1410
1411 // Fast reconnect for one hour after last seen
1412 if (nSinceLastSeen < 60 * 60)
1413 nDelay = 10 * 60;
1414
1415 // Limit retry frequency
1416 if (nSinceLastTry < nDelay)
1417 continue;
1418
1419 // If we have IRC, we'll be notified when they first come online,
1420 // and again every 24 hours by the refresh broadcast.
1421 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1422 continue;
1423
1424 // Only try the old stuff if we don't have enough connections
1425 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1426 continue;
1427
1428 // If multiple addresses are ready, prioritize by time since
1429 // last seen and time since last tried.
1430 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1431 if (nScore > nBest)
1432 {
1433 nBest = nScore;
1434 addrConnect = addr;
1435 }
1436 }
1437 }
1438
1439 if (addrConnect.IsValid())
1440 OpenNetworkConnection(addrConnect);
1441 }
1442}
1443
1444bool OpenNetworkConnection(const CAddress& addrConnect)
1445{
1446 //
1447 // Initiate outbound network connection
1448 //
1449 if (fShutdown)
1450 return false;
1451 if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1452 return false;
1453
1454 vnThreadsRunning[1]--;
1455 CNode* pnode = ConnectNode(addrConnect);
1456 vnThreadsRunning[1]++;
1457 if (fShutdown)
1458 return false;
1459 if (!pnode)
1460 return false;
1461 pnode->fNetworkNode = true;
1462
0a61b0df 1463 return true;
1464}
1465
1466
1467
1468
1469
1470
1471
1472
1473void ThreadMessageHandler(void* parg)
1474{
1475 IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1476 try
1477 {
1478 vnThreadsRunning[2]++;
1479 ThreadMessageHandler2(parg);
1480 vnThreadsRunning[2]--;
1481 }
1482 catch (std::exception& e) {
1483 vnThreadsRunning[2]--;
1484 PrintException(&e, "ThreadMessageHandler()");
1485 } catch (...) {
1486 vnThreadsRunning[2]--;
1487 PrintException(NULL, "ThreadMessageHandler()");
1488 }
1489 printf("ThreadMessageHandler exiting\n");
1490}
1491
1492void ThreadMessageHandler2(void* parg)
1493{
1494 printf("ThreadMessageHandler started\n");
1495 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1496 while (!fShutdown)
1497 {
1498 vector<CNode*> vNodesCopy;
1499 CRITICAL_BLOCK(cs_vNodes)
1500 {
1501 vNodesCopy = vNodes;
223b6f1b 1502 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1503 pnode->AddRef();
1504 }
1505
1506 // Poll the connected nodes for messages
1507 CNode* pnodeTrickle = NULL;
1508 if (!vNodesCopy.empty())
1509 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
223b6f1b 1510 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1511 {
1512 // Receive messages
1513 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1514 ProcessMessages(pnode);
1515 if (fShutdown)
1516 return;
1517
1518 // Send messages
1519 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1520 SendMessages(pnode, pnode == pnodeTrickle);
1521 if (fShutdown)
1522 return;
1523 }
1524
1525 CRITICAL_BLOCK(cs_vNodes)
1526 {
223b6f1b 1527 BOOST_FOREACH(CNode* pnode, vNodesCopy)
0a61b0df 1528 pnode->Release();
1529 }
1530
7629d36a 1531 // Wait and allow messages to bunch up.
1532 // Reduce vnThreadsRunning so StopNode has permission to exit while
1533 // we're sleeping, but we must always check fShutdown after doing this.
0a61b0df 1534 vnThreadsRunning[2]--;
1535 Sleep(100);
3f647537 1536 if (fRequestShutdown)
1537 Shutdown(NULL);
0a61b0df 1538 vnThreadsRunning[2]++;
1539 if (fShutdown)
1540 return;
1541 }
1542}
1543
1544
1545
1546
1547
1548
0a61b0df 1549bool BindListenPort(string& strError)
1550{
1551 strError = "";
1552 int nOne = 1;
00bcfe0b 1553 addrLocalHost.port = htons(GetListenPort());
0a61b0df 1554
1555#ifdef __WXMSW__
1556 // Initialize Windows Sockets
1557 WSADATA wsadata;
1558 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1559 if (ret != NO_ERROR)
1560 {
1561 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1562 printf("%s\n", strError.c_str());
1563 return false;
1564 }
1565#endif
1566
1567 // Create socket for listening for incoming connections
1568 hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1569 if (hListenSocket == INVALID_SOCKET)
1570 {
1571 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1572 printf("%s\n", strError.c_str());
1573 return false;
1574 }
1575
ec93a0e2 1576#ifdef SO_NOSIGPIPE
0a61b0df 1577 // Different way of disabling SIGPIPE on BSD
1578 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1579#endif
1580
1581#ifndef __WXMSW__
1582 // Allow binding if the port is still in TIME_WAIT state after
1583 // the program was closed and restarted. Not an issue on windows.
1584 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1585#endif
1586
1587#ifdef __WXMSW__
1588 // Set to nonblocking, incoming connections will also inherit this
1589 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1590#else
1591 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1592#endif
1593 {
1594 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1595 printf("%s\n", strError.c_str());
1596 return false;
1597 }
1598
1599 // The sockaddr_in structure specifies the address family,
1600 // IP address, and port for the socket that is being bound
1601 struct sockaddr_in sockaddr;
1602 memset(&sockaddr, 0, sizeof(sockaddr));
1603 sockaddr.sin_family = AF_INET;
1604 sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
00bcfe0b 1605 sockaddr.sin_port = htons(GetListenPort());
0a61b0df 1606 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1607 {
1608 int nErr = WSAGetLastError();
1609 if (nErr == WSAEADDRINUSE)
d9c6b09a 1610 strError = strprintf(_("Unable to bind to port %d on this computer. Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
0a61b0df 1611 else
1612 strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1613 printf("%s\n", strError.c_str());
1614 return false;
1615 }
1616 printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1617
1618 // Listen for incoming connections
1619 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1620 {
1621 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1622 printf("%s\n", strError.c_str());
1623 return false;
1624 }
1625
1626 return true;
1627}
1628
1629void StartNode(void* parg)
1630{
1631 if (pnodeLocalHost == NULL)
a6a5bb7c 1632 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
0a61b0df 1633
1634#ifdef __WXMSW__
1635 // Get local host ip
1636 char pszHostName[1000] = "";
1637 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1638 {
a6a5bb7c 1639 vector<CAddress> vaddr;
545a679a 1640 if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
223b6f1b 1641 BOOST_FOREACH (const CAddress &addr, vaddr)
a6a5bb7c 1642 if (addr.GetByte(3) != 127)
0a61b0df 1643 {
1644 addrLocalHost = addr;
1645 break;
1646 }
0a61b0df 1647 }
1648#else
1649 // Get local host ip
1650 struct ifaddrs* myaddrs;
1651 if (getifaddrs(&myaddrs) == 0)
1652 {
1653 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1654 {
1655 if (ifa->ifa_addr == NULL) continue;
1656 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1657 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1658 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1659 char pszIP[100];
1660 if (ifa->ifa_addr->sa_family == AF_INET)
1661 {
1662 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1663 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1664 printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1665
1666 // Take the first IP that isn't loopback 127.x.x.x
00bcfe0b 1667 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
0a61b0df 1668 if (addr.IsValid() && addr.GetByte(3) != 127)
1669 {
1670 addrLocalHost = addr;
1671 break;
1672 }
1673 }
1674 else if (ifa->ifa_addr->sa_family == AF_INET6)
1675 {
1676 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1677 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1678 printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1679 }
1680 }
1681 freeifaddrs(myaddrs);
1682 }
1683#endif
1684 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1685
5f88e888 1686 if (fUseProxy || mapArgs.count("-connect") || fNoListen)
0a61b0df 1687 {
1688 // Proxies can't take incoming connections
1689 addrLocalHost.ip = CAddress("0.0.0.0").ip;
1690 printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1691 }
1692 else
1693 {
629e37dd 1694 CreateThread(ThreadGetMyExternalIP, NULL);
0a61b0df 1695 }
1696
1697 //
1698 // Start threads
1699 //
1700
8bb5edc1
MC
1701 // Map ports with UPnP
1702 if (fHaveUPnP)
1703 MapPort(fUseUPnP);
1704
0a61b0df 1705 // Get addresses from IRC and advertise ours
1706 if (!CreateThread(ThreadIRCSeed, NULL))
1707 printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1708
1709 // Send and receive from sockets, accept connections
858cebed 1710 CreateThread(ThreadSocketHandler, NULL, true);
0a61b0df 1711
1712 // Initiate outbound connections
1713 if (!CreateThread(ThreadOpenConnections, NULL))
1714 printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1715
1716 // Process messages
1717 if (!CreateThread(ThreadMessageHandler, NULL))
1718 printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1719
1720 // Generate coins in the background
64c7ee7e 1721 GenerateBitcoins(fGenerateBitcoins, pwalletMain);
0a61b0df 1722}
1723
1724bool StopNode()
1725{
1726 printf("StopNode()\n");
1727 fShutdown = true;
1728 nTransactionsUpdated++;
1729 int64 nStart = GetTime();
8bb5edc1
MC
1730 while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1731#ifdef USE_UPNP
1732 || vnThreadsRunning[5] > 0
1733#endif
1734 )
0a61b0df 1735 {
1736 if (GetTime() - nStart > 20)
1737 break;
1738 Sleep(20);
1739 }
1740 if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1741 if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1742 if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1743 if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1744 if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
8bb5edc1 1745 if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
0a61b0df 1746 while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1747 Sleep(20);
1748 Sleep(50);
1749
1750 return true;
1751}
1752
1753class CNetCleanup
1754{
1755public:
1756 CNetCleanup()
1757 {
1758 }
1759 ~CNetCleanup()
1760 {
1761 // Close sockets
223b6f1b 1762 BOOST_FOREACH(CNode* pnode, vNodes)
0a61b0df 1763 if (pnode->hSocket != INVALID_SOCKET)
1764 closesocket(pnode->hSocket);
1765 if (hListenSocket != INVALID_SOCKET)
1766 if (closesocket(hListenSocket) == SOCKET_ERROR)
1767 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1768
1769#ifdef __WXMSW__
1770 // Shutdown Windows Sockets
1771 WSACleanup();
1772#endif
1773 }
1774}
1775instance_of_cnetcleanup;
This page took 0.26435 seconds and 4 git commands to generate.