Repeatedly resetting the timestamp for seed nodes in the database was slow. Only...
[novacoin.git] / net.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "headers.h"
6
7 static const int MAX_OUTBOUND_CONNECTIONS = 8;
8
9 void ThreadMessageHandler2(void* parg);
10 void ThreadSocketHandler2(void* parg);
11 void ThreadOpenConnections2(void* parg);
12 bool OpenNetworkConnection(const CAddress& addrConnect);
13
14
15
16
17
18 //
19 // Global state variables
20 //
21 bool fClient = false;
22 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
23 CAddress addrLocalHost(0, 0, nLocalServices);
24 CNode* pnodeLocalHost = NULL;
25 uint64 nLocalHostNonce = 0;
26 array<int, 10> vnThreadsRunning;
27 SOCKET hListenSocket = INVALID_SOCKET;
28
29 vector<CNode*> vNodes;
30 CCriticalSection cs_vNodes;
31 map<vector<unsigned char>, CAddress> mapAddresses;
32 CCriticalSection cs_mapAddresses;
33 map<CInv, CDataStream> mapRelay;
34 deque<pair<int64, CInv> > vRelayExpiration;
35 CCriticalSection cs_mapRelay;
36 map<CInv, int64> mapAlreadyAskedFor;
37
38 // Settings
39 int fUseProxy = false;
40 CAddress addrProxy("127.0.0.1:9050");
41
42
43
44
45
46 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
47 {
48     // Filter out duplicate requests
49     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
50         return;
51     pindexLastGetBlocksBegin = pindexBegin;
52     hashLastGetBlocksEnd = hashEnd;
53
54     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
55 }
56
57
58
59
60
61 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
62 {
63     hSocketRet = INVALID_SOCKET;
64
65     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
66     if (hSocket == INVALID_SOCKET)
67         return false;
68 #ifdef BSD
69     int set = 1;
70     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
71 #endif
72
73     bool fRoutable = !(addrConnect.GetByte(3) == 10 || (addrConnect.GetByte(3) == 192 && addrConnect.GetByte(2) == 168));
74     bool fProxy = (fUseProxy && fRoutable);
75     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
76
77     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
78     {
79         closesocket(hSocket);
80         return false;
81     }
82
83     if (fProxy)
84     {
85         printf("proxy connecting %s\n", addrConnect.ToStringLog().c_str());
86         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
87         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
88         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
89         char* pszSocks4 = pszSocks4IP;
90         int nSize = sizeof(pszSocks4IP);
91
92         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
93         if (ret != nSize)
94         {
95             closesocket(hSocket);
96             return error("Error sending to proxy");
97         }
98         char pchRet[8];
99         if (recv(hSocket, pchRet, 8, 0) != 8)
100         {
101             closesocket(hSocket);
102             return error("Error reading proxy response");
103         }
104         if (pchRet[1] != 0x5a)
105         {
106             closesocket(hSocket);
107             if (pchRet[1] != 0x5b)
108                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
109             return false;
110         }
111         printf("proxy connected %s\n", addrConnect.ToStringLog().c_str());
112     }
113
114     hSocketRet = hSocket;
115     return true;
116 }
117
118
119
120 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
121 {
122     SOCKET hSocket;
123     if (!ConnectSocket(addrConnect, hSocket))
124         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
125
126     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
127
128     string strLine;
129     while (RecvLine(hSocket, strLine))
130     {
131         if (strLine.empty()) // HTTP response is separated from headers by blank line
132         {
133             loop
134             {
135                 if (!RecvLine(hSocket, strLine))
136                 {
137                     closesocket(hSocket);
138                     return false;
139                 }
140                 if (pszKeyword == NULL)
141                     break;
142                 if (strLine.find(pszKeyword) != -1)
143                 {
144                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
145                     break;
146                 }
147             }
148             closesocket(hSocket);
149             if (strLine.find("<") != -1)
150                 strLine = strLine.substr(0, strLine.find("<"));
151             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
152             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
153                 strLine.resize(strLine.size()-1);
154             CAddress addr(strLine.c_str());
155             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
156             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
157                 return false;
158             ipRet = addr.ip;
159             return true;
160         }
161     }
162     closesocket(hSocket);
163     return error("GetMyExternalIP() : connection closed");
164 }
165
166 // We now get our external IP from the IRC server first and only use this as a backup
167 bool GetMyExternalIP(unsigned int& ipRet)
168 {
169     CAddress addrConnect;
170     const char* pszGet;
171     const char* pszKeyword;
172
173     if (fUseProxy)
174         return false;
175
176     for (int nLookup = 0; nLookup <= 1; nLookup++)
177     for (int nHost = 1; nHost <= 2; nHost++)
178     {
179         // We should be phasing out our use of sites like these.  If we need
180         // replacements, we should ask for volunteers to put this simple
181         // php file on their webserver that prints the client IP:
182         //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
183         if (nHost == 1)
184         {
185             addrConnect = CAddress("91.198.22.70:80"); // checkip.dyndns.org
186
187             if (nLookup == 1)
188             {
189                 struct hostent* phostent = gethostbyname("checkip.dyndns.org");
190                 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
191                     addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
192             }
193
194             pszGet = "GET / HTTP/1.1\r\n"
195                      "Host: checkip.dyndns.org\r\n"
196                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
197                      "Connection: close\r\n"
198                      "\r\n";
199
200             pszKeyword = "Address:";
201         }
202         else if (nHost == 2)
203         {
204             addrConnect = CAddress("74.208.43.192:80"); // www.showmyip.com
205
206             if (nLookup == 1)
207             {
208                 struct hostent* phostent = gethostbyname("www.showmyip.com");
209                 if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
210                     addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
211             }
212
213             pszGet = "GET /simple/ HTTP/1.1\r\n"
214                      "Host: www.showmyip.com\r\n"
215                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
216                      "Connection: close\r\n"
217                      "\r\n";
218
219             pszKeyword = NULL; // Returns just IP address
220         }
221
222         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
223             return true;
224     }
225
226     return false;
227 }
228
229 void ThreadGetMyExternalIP(void* parg)
230 {
231     // Wait for IRC to get it first
232     if (!GetBoolArg("-noirc"))
233     {
234         for (int i = 0; i < 2 * 60; i++)
235         {
236             Sleep(1000);
237             if (fGotExternalIP || fShutdown)
238                 return;
239         }
240     }
241
242     // Fallback in case IRC fails to get it
243     if (GetMyExternalIP(addrLocalHost.ip))
244     {
245         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
246         if (addrLocalHost.IsRoutable())
247         {
248             // If we already connected to a few before we had our IP, go back and addr them.
249             // setAddrKnown automatically filters any duplicate sends.
250             CAddress addr(addrLocalHost);
251             addr.nTime = GetAdjustedTime();
252             CRITICAL_BLOCK(cs_vNodes)
253                 foreach(CNode* pnode, vNodes)
254                     pnode->PushAddress(addr);
255         }
256     }
257 }
258
259
260
261
262
263 bool AddAddress(CAddress addr, int64 nTimePenalty)
264 {
265     if (!addr.IsRoutable())
266         return false;
267     if (addr.ip == addrLocalHost.ip)
268         return false;
269     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
270     CRITICAL_BLOCK(cs_mapAddresses)
271     {
272         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
273         if (it == mapAddresses.end())
274         {
275             // New address
276             printf("AddAddress(%s)\n", addr.ToStringLog().c_str());
277             mapAddresses.insert(make_pair(addr.GetKey(), addr));
278             CAddrDB().WriteAddress(addr);
279             return true;
280         }
281         else
282         {
283             bool fUpdated = false;
284             CAddress& addrFound = (*it).second;
285             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
286             {
287                 // Services have been added
288                 addrFound.nServices |= addr.nServices;
289                 fUpdated = true;
290             }
291             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
292             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
293             if (addrFound.nTime < addr.nTime - nUpdateInterval)
294             {
295                 // Periodically update most recently seen time
296                 addrFound.nTime = addr.nTime;
297                 fUpdated = true;
298             }
299             if (fUpdated)
300                 CAddrDB().WriteAddress(addrFound);
301         }
302     }
303     return false;
304 }
305
306 void AddressCurrentlyConnected(const CAddress& addr)
307 {
308     CRITICAL_BLOCK(cs_mapAddresses)
309     {
310         // Only if it's been published already
311         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
312         if (it != mapAddresses.end())
313         {
314             CAddress& addrFound = (*it).second;
315             int64 nUpdateInterval = 20 * 60;
316             if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
317             {
318                 // Periodically update most recently seen time
319                 addrFound.nTime = GetAdjustedTime();
320                 CAddrDB addrdb;
321                 addrdb.WriteAddress(addrFound);
322             }
323         }
324     }
325 }
326
327
328
329
330
331 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
332 {
333     // If the dialog might get closed before the reply comes back,
334     // call this in the destructor so it doesn't get called after it's deleted.
335     CRITICAL_BLOCK(cs_vNodes)
336     {
337         foreach(CNode* pnode, vNodes)
338         {
339             CRITICAL_BLOCK(pnode->cs_mapRequests)
340             {
341                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
342                 {
343                     CRequestTracker& tracker = (*mi).second;
344                     if (tracker.fn == fn && tracker.param1 == param1)
345                         pnode->mapRequests.erase(mi++);
346                     else
347                         mi++;
348                 }
349             }
350         }
351     }
352 }
353
354
355
356
357
358
359
360 //
361 // Subscription methods for the broadcast and subscription system.
362 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
363 //
364 // The subscription system uses a meet-in-the-middle strategy.
365 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
366 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
367 //
368
369 bool AnySubscribed(unsigned int nChannel)
370 {
371     if (pnodeLocalHost->IsSubscribed(nChannel))
372         return true;
373     CRITICAL_BLOCK(cs_vNodes)
374         foreach(CNode* pnode, vNodes)
375             if (pnode->IsSubscribed(nChannel))
376                 return true;
377     return false;
378 }
379
380 bool CNode::IsSubscribed(unsigned int nChannel)
381 {
382     if (nChannel >= vfSubscribe.size())
383         return false;
384     return vfSubscribe[nChannel];
385 }
386
387 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
388 {
389     if (nChannel >= vfSubscribe.size())
390         return;
391
392     if (!AnySubscribed(nChannel))
393     {
394         // Relay subscribe
395         CRITICAL_BLOCK(cs_vNodes)
396             foreach(CNode* pnode, vNodes)
397                 if (pnode != this)
398                     pnode->PushMessage("subscribe", nChannel, nHops);
399     }
400
401     vfSubscribe[nChannel] = true;
402 }
403
404 void CNode::CancelSubscribe(unsigned int nChannel)
405 {
406     if (nChannel >= vfSubscribe.size())
407         return;
408
409     // Prevent from relaying cancel if wasn't subscribed
410     if (!vfSubscribe[nChannel])
411         return;
412     vfSubscribe[nChannel] = false;
413
414     if (!AnySubscribed(nChannel))
415     {
416         // Relay subscription cancel
417         CRITICAL_BLOCK(cs_vNodes)
418             foreach(CNode* pnode, vNodes)
419                 if (pnode != this)
420                     pnode->PushMessage("sub-cancel", nChannel);
421     }
422 }
423
424
425
426
427
428
429
430
431
432 CNode* FindNode(unsigned int ip)
433 {
434     CRITICAL_BLOCK(cs_vNodes)
435     {
436         foreach(CNode* pnode, vNodes)
437             if (pnode->addr.ip == ip)
438                 return (pnode);
439     }
440     return NULL;
441 }
442
443 CNode* FindNode(CAddress addr)
444 {
445     CRITICAL_BLOCK(cs_vNodes)
446     {
447         foreach(CNode* pnode, vNodes)
448             if (pnode->addr == addr)
449                 return (pnode);
450     }
451     return NULL;
452 }
453
454 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
455 {
456     if (addrConnect.ip == addrLocalHost.ip)
457         return NULL;
458
459     // Look for an existing connection
460     CNode* pnode = FindNode(addrConnect.ip);
461     if (pnode)
462     {
463         if (nTimeout != 0)
464             pnode->AddRef(nTimeout);
465         else
466             pnode->AddRef();
467         return pnode;
468     }
469
470     /// debug print
471     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
472         addrConnect.ToStringLog().c_str(),
473         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
474         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
475
476     CRITICAL_BLOCK(cs_mapAddresses)
477         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
478
479     // Connect
480     SOCKET hSocket;
481     if (ConnectSocket(addrConnect, hSocket))
482     {
483         /// debug print
484         printf("connected %s\n", addrConnect.ToStringLog().c_str());
485
486         // Set to nonblocking
487 #ifdef __WXMSW__
488         u_long nOne = 1;
489         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
490             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
491 #else
492         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
493             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
494 #endif
495
496         // Add node
497         CNode* pnode = new CNode(hSocket, addrConnect, false);
498         if (nTimeout != 0)
499             pnode->AddRef(nTimeout);
500         else
501             pnode->AddRef();
502         CRITICAL_BLOCK(cs_vNodes)
503             vNodes.push_back(pnode);
504
505         pnode->nTimeConnected = GetTime();
506         return pnode;
507     }
508     else
509     {
510         return NULL;
511     }
512 }
513
514 void CNode::CloseSocketDisconnect()
515 {
516     fDisconnect = true;
517     if (hSocket != INVALID_SOCKET)
518     {
519         if (fDebug)
520             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
521         printf("disconnecting node %s\n", addr.ToStringLog().c_str());
522         closesocket(hSocket);
523         hSocket = INVALID_SOCKET;
524     }
525 }
526
527 void CNode::Cleanup()
528 {
529     // All of a nodes broadcasts and subscriptions are automatically torn down
530     // when it goes down, so a node has to stay up to keep its broadcast going.
531
532     // Cancel subscriptions
533     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
534         if (vfSubscribe[nChannel])
535             CancelSubscribe(nChannel);
536 }
537
538
539
540
541
542
543
544
545
546
547
548
549
550 void ThreadSocketHandler(void* parg)
551 {
552     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
553     try
554     {
555         vnThreadsRunning[0]++;
556         ThreadSocketHandler2(parg);
557         vnThreadsRunning[0]--;
558     }
559     catch (std::exception& e) {
560         vnThreadsRunning[0]--;
561         PrintException(&e, "ThreadSocketHandler()");
562     } catch (...) {
563         vnThreadsRunning[0]--;
564         throw; // support pthread_cancel()
565     }
566     printf("ThreadSocketHandler exiting\n");
567 }
568
569 void ThreadSocketHandler2(void* parg)
570 {
571     printf("ThreadSocketHandler started\n");
572     list<CNode*> vNodesDisconnected;
573     int nPrevNodeCount = 0;
574
575     loop
576     {
577         //
578         // Disconnect nodes
579         //
580         CRITICAL_BLOCK(cs_vNodes)
581         {
582             // Disconnect unused nodes
583             vector<CNode*> vNodesCopy = vNodes;
584             foreach(CNode* pnode, vNodesCopy)
585             {
586                 if (pnode->fDisconnect ||
587                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
588                 {
589                     // remove from vNodes
590                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
591
592                     // close socket and cleanup
593                     pnode->CloseSocketDisconnect();
594                     pnode->Cleanup();
595
596                     // hold in disconnected pool until all refs are released
597                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
598                     if (pnode->fNetworkNode || pnode->fInbound)
599                         pnode->Release();
600                     vNodesDisconnected.push_back(pnode);
601                 }
602             }
603
604             // Delete disconnected nodes
605             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
606             foreach(CNode* pnode, vNodesDisconnectedCopy)
607             {
608                 // wait until threads are done using it
609                 if (pnode->GetRefCount() <= 0)
610                 {
611                     bool fDelete = false;
612                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
613                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
614                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
615                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
616                         fDelete = true;
617                     if (fDelete)
618                     {
619                         vNodesDisconnected.remove(pnode);
620                         delete pnode;
621                     }
622                 }
623             }
624         }
625         if (vNodes.size() != nPrevNodeCount)
626         {
627             nPrevNodeCount = vNodes.size();
628             MainFrameRepaint();
629         }
630
631
632         //
633         // Find which sockets have data to receive
634         //
635         struct timeval timeout;
636         timeout.tv_sec  = 0;
637         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
638
639         fd_set fdsetRecv;
640         fd_set fdsetSend;
641         fd_set fdsetError;
642         FD_ZERO(&fdsetRecv);
643         FD_ZERO(&fdsetSend);
644         FD_ZERO(&fdsetError);
645         SOCKET hSocketMax = 0;
646
647         if(hListenSocket != INVALID_SOCKET)
648             FD_SET(hListenSocket, &fdsetRecv);
649         hSocketMax = max(hSocketMax, hListenSocket);
650         CRITICAL_BLOCK(cs_vNodes)
651         {
652             foreach(CNode* pnode, vNodes)
653             {
654                 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
655                     continue;
656                 FD_SET(pnode->hSocket, &fdsetRecv);
657                 FD_SET(pnode->hSocket, &fdsetError);
658                 hSocketMax = max(hSocketMax, pnode->hSocket);
659                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
660                     if (!pnode->vSend.empty())
661                         FD_SET(pnode->hSocket, &fdsetSend);
662             }
663         }
664
665         vnThreadsRunning[0]--;
666         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
667         vnThreadsRunning[0]++;
668         if (fShutdown)
669             return;
670         if (nSelect == SOCKET_ERROR)
671         {
672             int nErr = WSAGetLastError();
673             printf("socket select error %d\n", nErr);
674             for (int i = 0; i <= hSocketMax; i++)
675                 FD_SET(i, &fdsetRecv);
676             FD_ZERO(&fdsetSend);
677             FD_ZERO(&fdsetError);
678             Sleep(timeout.tv_usec/1000);
679         }
680
681
682         //
683         // Accept new connections
684         //
685         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
686         {
687             struct sockaddr_in sockaddr;
688             socklen_t len = sizeof(sockaddr);
689             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
690             CAddress addr(sockaddr);
691             bool fLimitConnections = false;
692             int nInbound = 0;
693
694             if (mapArgs.count("-maxconnections"))
695                 fLimitConnections = true;
696
697             if (fLimitConnections)
698             {
699                 CRITICAL_BLOCK(cs_vNodes)
700                     foreach(CNode* pnode, vNodes)
701                     if (pnode->fInbound)
702                         nInbound++;
703             }
704             if (hSocket == INVALID_SOCKET)
705             {
706                 if (WSAGetLastError() != WSAEWOULDBLOCK)
707                     printf("socket error accept failed: %d\n", WSAGetLastError());
708             }
709             else if (fLimitConnections && nInbound >= atoi(mapArgs["-maxconnections"]) - MAX_OUTBOUND_CONNECTIONS)
710             {
711                 closesocket(hSocket);
712             }
713             else
714             {
715                 printf("accepted connection %s\n", addr.ToStringLog().c_str());
716                 CNode* pnode = new CNode(hSocket, addr, true);
717                 pnode->AddRef();
718                 CRITICAL_BLOCK(cs_vNodes)
719                     vNodes.push_back(pnode);
720             }
721         }
722
723
724         //
725         // Service each socket
726         //
727         vector<CNode*> vNodesCopy;
728         CRITICAL_BLOCK(cs_vNodes)
729         {
730             vNodesCopy = vNodes;
731             foreach(CNode* pnode, vNodesCopy)
732                 pnode->AddRef();
733         }
734         foreach(CNode* pnode, vNodesCopy)
735         {
736             if (fShutdown)
737                 return;
738
739             //
740             // Receive
741             //
742             if (pnode->hSocket == INVALID_SOCKET)
743                 continue;
744             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
745             {
746                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
747                 {
748                     CDataStream& vRecv = pnode->vRecv;
749                     unsigned int nPos = vRecv.size();
750
751                     // typical socket buffer is 8K-64K
752                     char pchBuf[0x10000];
753                     int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
754                     if (nBytes > 0)
755                     {
756                         vRecv.resize(nPos + nBytes);
757                         memcpy(&vRecv[nPos], pchBuf, nBytes);
758                         pnode->nLastRecv = GetTime();
759                     }
760                     else if (nBytes == 0)
761                     {
762                         // socket closed gracefully
763                         if (!pnode->fDisconnect)
764                             printf("socket closed\n");
765                         pnode->CloseSocketDisconnect();
766                     }
767                     else if (nBytes < 0)
768                     {
769                         // error
770                         int nErr = WSAGetLastError();
771                         if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
772                         {
773                             if (!pnode->fDisconnect)
774                                 printf("socket recv error %d\n", nErr);
775                             pnode->CloseSocketDisconnect();
776                         }
777                     }
778                 }
779             }
780
781             //
782             // Send
783             //
784             if (pnode->hSocket == INVALID_SOCKET)
785                 continue;
786             if (FD_ISSET(pnode->hSocket, &fdsetSend))
787             {
788                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
789                 {
790                     CDataStream& vSend = pnode->vSend;
791                     if (!vSend.empty())
792                     {
793                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
794                         if (nBytes > 0)
795                         {
796                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
797                             pnode->nLastSend = GetTime();
798                         }
799                         else if (nBytes < 0)
800                         {
801                             // error
802                             int nErr = WSAGetLastError();
803                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
804                             {
805                                 printf("socket send error %d\n", nErr);
806                                 pnode->CloseSocketDisconnect();
807                             }
808                         }
809                     }
810                 }
811             }
812
813             //
814             // Inactivity checking
815             //
816             if (pnode->vSend.empty())
817                 pnode->nLastSendEmpty = GetTime();
818             if (GetTime() - pnode->nTimeConnected > 60)
819             {
820                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
821                 {
822                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
823                     pnode->fDisconnect = true;
824                 }
825                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
826                 {
827                     printf("socket not sending\n");
828                     pnode->fDisconnect = true;
829                 }
830                 else if (GetTime() - pnode->nLastRecv > 90*60)
831                 {
832                     printf("socket inactivity timeout\n");
833                     pnode->fDisconnect = true;
834                 }
835             }
836         }
837         CRITICAL_BLOCK(cs_vNodes)
838         {
839             foreach(CNode* pnode, vNodesCopy)
840                 pnode->Release();
841         }
842
843         Sleep(10);
844     }
845 }
846
847
848
849
850
851
852
853
854
855
856
857
858
859 unsigned int pnSeed[] =
860 {
861     // 2010/06
862     0x35218252, 0x9c9c9618, 0xda6bacad, 0xb9aca862, 0x97c235c6,
863     0x146f9562, 0xb67b9e4b, 0x87cf4bc0, 0xb83945d0, 0x984333ad,
864     0xbbeec555, 0x6f0eb440, 0xe0005318, 0x7797e460, 0xddc60fcc,
865     0xb3bbd24a, 0x1ac85746, 0x641846a6, 0x85ee1155, 0xbb2e7a4c,
866     0x9cb8514b, 0xfc342648, 0x62958fae, 0xd0a8c87a, 0xa800795b,
867     0xda8c814e, 0x256a0c80, 0x3f23ec63, 0xd565df43, 0x997d9044,
868     0xaa121448, 0xbed8688e, 0x59d09a5e, 0xb2931243, 0x3730ba18,
869     0xdd3462d0, 0x4e4d1448, 0x171df645, 0x84ee1155,
870     0x248ac445, 0x0e634444, 0x0ded1b63, 0x30c01e60,
871     0xa2b9a094, 0x29e4fd43, 0x9ce61b4c, 0xdae09744,
872
873     // 2010/08
874     0x5ae6bf43, 0x460be257, 0x7245c0cf, 0x4e0f028d, 0x26501760, 0x38643255, 0x67094f4f, 0x480449b8,
875     0x16545143, 0x1f082e5a, 0xaa428018, 0xe411e793, 0x14c1f862, 0x2726105b, 0x9b33ea50, 0xeeef86ca,
876     0xe3210d44, 0x0dca8b63, 0x3f9dfb18, 0x860340ad, 0xf33ba17a, 0x9018375c, 0x1de4e353, 0x0fa52dcb,
877     0x89c4555b, 0x109cf37b, 0x28c55b40, 0x04c801ae, 0x275c1e80, 0x6f7f745d, 0x7a2a5653, 0xa28e26d8,
878     0xa4e65db2, 0x99a06580, 0xf253ba44, 0x82cf6ab8, 0x859c2e8e, 0xf71a815d, 0xc18f1454, 0x71c8a943,
879     0x90d24e18, 0x311789b2, 0x74aba645, 0xde0bbfc3, 0xad724fad, 0xbf1ae15e, 0xbaa6fb54, 0x06e4d145,
880     0x51528645, 0x72120cd4, 0xd4cfd145, 0x0a7afed8, 0x9b9a5fad, 0x9e9ff45e, 0x10128355, 0xd44e8646,
881     0x04a07b47, 0x5fc9d547, 0xe0491e45, 0xbac21b41, 0x7aa31bae, 0x10483c5f, 0x94a23055, 0x73d9dc47,
882     0x1a99c247, 0x822fe847, 0x7e57ba48, 0xb19ea843, 0xa60621b2, 0x778cf163, 0x125c6556, 0xf94ba44f,
883     0xa61a0948, 0x6c839e4b, 0x29af5348, 0x68d84845, 0x752b95c3, 0xcf0d4663, 0x08e11e56, 0x75109550,
884     0x5f24b94c, 0x42426d4d, 0xfbbc0a4c, 0x70a9a246, 0xda7837cb, 0xae2a986d, 0xe283c358, 0x0c7ca954,
885     0x8e9bde59, 0x61521760, 0x6884444c, 0xa194e548, 0x9b8809cc, 0x16e96a8f, 0x956ff859, 0xfad5e555,
886     0x0ea70c80, 0x5b4ce26d, 0x7984444c, 0x1080d24a, 0x22a686cf, 0x6bf8c2ad, 0xb0f7485f, 0x06b66e56,
887     0x668373bc, 0x75506279, 0x3868694e, 0x12a5954b, 0x3a8b62d1, 0xb74fcbad, 0xa7dc3360, 0xc070b359,
888     0xa2b87242, 0xc45cab7c, 0x69882050, 0x14a5464b, 0x386acad5, 0x80b85db2, 0x1f78a062, 0xc608c55b,
889     0x4257d543, 0x7636ad80, 0x4432d655, 0xb2114d4b, 0x32639bd9, 0xadd75db2, 0x9be5a362, 0x6831bc5e,
890     0xf7f77046, 0x8f35ba81, 0x09bb4e59, 0xd0fb6b4e, 0xc5daa445, 0x9c611618, 0x355dcc62, 0xf2cf435e,
891     0x31e72c46, 0xdd8a43ad, 0x171f9c5b, 0xb4c2e355, 0xbe8af945, 0x613d3942, 0xe6f9e863, 0x7a3d855f,
892     0xa66adc47, 0x261089b2, 0x5a27105b, 0x6c28105b, 0xdd247946, 0xe6c3a445, 0x43a1ec63, 0x99b4dd5f,
893     0xb6834347, 0x5e9649bc, 0xf9dd545d, 0x6ae4c15b, 0xa5318a47, 0x7984ec47, 0x93a73b63, 0x0c60195f,
894     0xa5c85e4b, 0xa0a36dc2, 0x0739a95e, 0x3d44c15b, 0xfb940f4b, 0xd67c9148, 0x614f9876, 0x0a241c5f,
895     0xad9da74c, 0x4459abc8, 0x12e71b5f, 0x1c534a5d, 0x8ff5fc50, 0x2ca8864b, 0xd894fd80, 0x82ab3160,
896     0x390d804e, 0x2cf310cc, 0x680dad80, 0x691be15e, 0x5a8f4652, 0xaad0784d, 0x0d2431ad,
897 };
898
899
900
901 void ThreadOpenConnections(void* parg)
902 {
903     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
904     try
905     {
906         vnThreadsRunning[1]++;
907         ThreadOpenConnections2(parg);
908         vnThreadsRunning[1]--;
909     }
910     catch (std::exception& e) {
911         vnThreadsRunning[1]--;
912         PrintException(&e, "ThreadOpenConnections()");
913     } catch (...) {
914         vnThreadsRunning[1]--;
915         PrintException(NULL, "ThreadOpenConnections()");
916     }
917     printf("ThreadOpenConnections exiting\n");
918 }
919
920 void ThreadOpenConnections2(void* parg)
921 {
922     printf("ThreadOpenConnections started\n");
923
924     // Connect to specific addresses
925     if (mapArgs.count("-connect"))
926     {
927         for (int64 nLoop = 0;; nLoop++)
928         {
929             foreach(string strAddr, mapMultiArgs["-connect"])
930             {
931                 CAddress addr(strAddr, NODE_NETWORK);
932                 if (addr.IsValid())
933                     OpenNetworkConnection(addr);
934                 for (int i = 0; i < 10 && i < nLoop; i++)
935                 {
936                     Sleep(500);
937                     if (fShutdown)
938                         return;
939                 }
940             }
941         }
942     }
943
944     // Connect to manually added nodes first
945     if (mapArgs.count("-addnode"))
946     {
947         foreach(string strAddr, mapMultiArgs["-addnode"])
948         {
949             CAddress addr(strAddr, NODE_NETWORK);
950             if (addr.IsValid())
951             {
952                 OpenNetworkConnection(addr);
953                 Sleep(500);
954                 if (fShutdown)
955                     return;
956             }
957         }
958     }
959
960     // Initiate network connections
961     int64 nStart = GetTime();
962     loop
963     {
964         // Limit outbound connections
965         vnThreadsRunning[1]--;
966         Sleep(500);
967         loop
968         {
969             int nOutbound = 0;
970             CRITICAL_BLOCK(cs_vNodes)
971                 foreach(CNode* pnode, vNodes)
972                     if (!pnode->fInbound)
973                         nOutbound++;
974             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
975             if (mapArgs.count("-maxconnections"))
976                 nMaxOutboundConnections = min(nMaxOutboundConnections, atoi(mapArgs["-maxconnections"]));
977             if (nOutbound < nMaxOutboundConnections)
978                 break;
979             Sleep(2000);
980             if (fShutdown)
981                 return;
982         }
983         vnThreadsRunning[1]++;
984         if (fShutdown)
985             return;
986
987         CRITICAL_BLOCK(cs_mapAddresses)
988         {
989             // Add seed nodes if IRC isn't working
990             static bool fSeedUsed;
991             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
992             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
993             {
994                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
995                 {
996                     // It'll only connect to one or two seed nodes because once it connects,
997                     // it'll get a pile of addresses with newer timestamps.
998                     CAddress addr;
999                     addr.ip = pnSeed[i];
1000                     addr.nTime = 0;
1001                     AddAddress(addr);
1002                 }
1003                 fSeedUsed = true;
1004             }
1005
1006             if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1007             {
1008                 // Disconnect seed nodes
1009                 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1010                 static int64 nSeedDisconnected;
1011                 if (nSeedDisconnected == 0)
1012                 {
1013                     nSeedDisconnected = GetTime();
1014                     CRITICAL_BLOCK(cs_vNodes)
1015                         foreach(CNode* pnode, vNodes)
1016                             if (setSeed.count(pnode->addr.ip))
1017                                 pnode->fDisconnect = true;
1018                 }
1019
1020                 // Keep setting timestamps to 0 so they won't reconnect
1021                 if (GetTime() - nSeedDisconnected < 60 * 60)
1022                 {
1023                     foreach(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1024                     {
1025                         if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1026                         {
1027                             item.second.nTime = 0;
1028                             CAddrDB().WriteAddress(item.second);
1029                         }
1030                     }
1031                 }
1032             }
1033         }
1034
1035
1036         //
1037         // Choose an address to connect to based on most recently seen
1038         //
1039         CAddress addrConnect;
1040         int64 nBest = INT64_MIN;
1041
1042         // Only connect to one address per a.b.?.? range.
1043         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1044         set<unsigned int> setConnected;
1045         CRITICAL_BLOCK(cs_vNodes)
1046             foreach(CNode* pnode, vNodes)
1047                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1048
1049         CRITICAL_BLOCK(cs_mapAddresses)
1050         {
1051             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1052             {
1053                 const CAddress& addr = item.second;
1054                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1055                     continue;
1056                 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1057                 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1058
1059                 // Randomize the order in a deterministic way, putting the standard port first
1060                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1061                 if (addr.port != GetDefaultPort())
1062                     nRandomizer += 2 * 60 * 60;
1063
1064                 // Last seen  Base retry frequency
1065                 //   <1 hour   10 min
1066                 //    1 hour    1 hour
1067                 //    4 hours   2 hours
1068                 //   24 hours   5 hours
1069                 //   48 hours   7 hours
1070                 //    7 days   13 hours
1071                 //   30 days   27 hours
1072                 //   90 days   46 hours
1073                 //  365 days   93 hours
1074                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1075
1076                 // Fast reconnect for one hour after last seen
1077                 if (nSinceLastSeen < 60 * 60)
1078                     nDelay = 10 * 60;
1079
1080                 // Limit retry frequency
1081                 if (nSinceLastTry < nDelay)
1082                     continue;
1083
1084                 // If we have IRC, we'll be notified when they first come online,
1085                 // and again every 24 hours by the refresh broadcast.
1086                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1087                     continue;
1088
1089                 // Only try the old stuff if we don't have enough connections
1090                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1091                     continue;
1092
1093                 // If multiple addresses are ready, prioritize by time since
1094                 // last seen and time since last tried.
1095                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1096                 if (nScore > nBest)
1097                 {
1098                     nBest = nScore;
1099                     addrConnect = addr;
1100                 }
1101             }
1102         }
1103
1104         if (addrConnect.IsValid())
1105             OpenNetworkConnection(addrConnect);
1106     }
1107 }
1108
1109 bool OpenNetworkConnection(const CAddress& addrConnect)
1110 {
1111     //
1112     // Initiate outbound network connection
1113     //
1114     if (fShutdown)
1115         return false;
1116     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1117         return false;
1118
1119     vnThreadsRunning[1]--;
1120     CNode* pnode = ConnectNode(addrConnect);
1121     vnThreadsRunning[1]++;
1122     if (fShutdown)
1123         return false;
1124     if (!pnode)
1125         return false;
1126     pnode->fNetworkNode = true;
1127
1128     return true;
1129 }
1130
1131
1132
1133
1134
1135
1136
1137
1138 void ThreadMessageHandler(void* parg)
1139 {
1140     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1141     try
1142     {
1143         vnThreadsRunning[2]++;
1144         ThreadMessageHandler2(parg);
1145         vnThreadsRunning[2]--;
1146     }
1147     catch (std::exception& e) {
1148         vnThreadsRunning[2]--;
1149         PrintException(&e, "ThreadMessageHandler()");
1150     } catch (...) {
1151         vnThreadsRunning[2]--;
1152         PrintException(NULL, "ThreadMessageHandler()");
1153     }
1154     printf("ThreadMessageHandler exiting\n");
1155 }
1156
1157 void ThreadMessageHandler2(void* parg)
1158 {
1159     printf("ThreadMessageHandler started\n");
1160     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1161     while (!fShutdown)
1162     {
1163         vector<CNode*> vNodesCopy;
1164         CRITICAL_BLOCK(cs_vNodes)
1165         {
1166             vNodesCopy = vNodes;
1167             foreach(CNode* pnode, vNodesCopy)
1168                 pnode->AddRef();
1169         }
1170
1171         // Poll the connected nodes for messages
1172         CNode* pnodeTrickle = NULL;
1173         if (!vNodesCopy.empty())
1174             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1175         foreach(CNode* pnode, vNodesCopy)
1176         {
1177             // Receive messages
1178             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1179                 ProcessMessages(pnode);
1180             if (fShutdown)
1181                 return;
1182
1183             // Send messages
1184             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1185                 SendMessages(pnode, pnode == pnodeTrickle);
1186             if (fShutdown)
1187                 return;
1188         }
1189
1190         CRITICAL_BLOCK(cs_vNodes)
1191         {
1192             foreach(CNode* pnode, vNodesCopy)
1193                 pnode->Release();
1194         }
1195
1196         // Wait and allow messages to bunch up.
1197         // Reduce vnThreadsRunning so StopNode has permission to exit while
1198         // we're sleeping, but we must always check fShutdown after doing this.
1199         vnThreadsRunning[2]--;
1200         Sleep(100);
1201         if (fRequestShutdown)
1202             Shutdown(NULL);
1203         vnThreadsRunning[2]++;
1204         if (fShutdown)
1205             return;
1206     }
1207 }
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217 bool BindListenPort(string& strError)
1218 {
1219     strError = "";
1220     int nOne = 1;
1221     addrLocalHost.port = GetDefaultPort();
1222
1223 #ifdef __WXMSW__
1224     // Initialize Windows Sockets
1225     WSADATA wsadata;
1226     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1227     if (ret != NO_ERROR)
1228     {
1229         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1230         printf("%s\n", strError.c_str());
1231         return false;
1232     }
1233 #endif
1234
1235     // Create socket for listening for incoming connections
1236     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1237     if (hListenSocket == INVALID_SOCKET)
1238     {
1239         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1240         printf("%s\n", strError.c_str());
1241         return false;
1242     }
1243
1244 #ifdef BSD
1245     // Different way of disabling SIGPIPE on BSD
1246     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1247 #endif
1248
1249 #ifndef __WXMSW__
1250     // Allow binding if the port is still in TIME_WAIT state after
1251     // the program was closed and restarted.  Not an issue on windows.
1252     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1253 #endif
1254
1255 #ifdef __WXMSW__
1256     // Set to nonblocking, incoming connections will also inherit this
1257     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1258 #else
1259     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1260 #endif
1261     {
1262         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1263         printf("%s\n", strError.c_str());
1264         return false;
1265     }
1266
1267     // The sockaddr_in structure specifies the address family,
1268     // IP address, and port for the socket that is being bound
1269     struct sockaddr_in sockaddr;
1270     memset(&sockaddr, 0, sizeof(sockaddr));
1271     sockaddr.sin_family = AF_INET;
1272     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1273     sockaddr.sin_port = GetDefaultPort();
1274     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1275     {
1276         int nErr = WSAGetLastError();
1277         if (nErr == WSAEADDRINUSE)
1278             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1279         else
1280             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1281         printf("%s\n", strError.c_str());
1282         return false;
1283     }
1284     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1285
1286     // Listen for incoming connections
1287     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1288     {
1289         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1290         printf("%s\n", strError.c_str());
1291         return false;
1292     }
1293
1294     return true;
1295 }
1296
1297 void StartNode(void* parg)
1298 {
1299     if (pnodeLocalHost == NULL)
1300         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
1301
1302 #ifdef __WXMSW__
1303     // Get local host ip
1304     char pszHostName[1000] = "";
1305     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1306     {
1307         struct hostent* phostent = gethostbyname(pszHostName);
1308         if (phostent)
1309         {
1310             // Take the first IP that isn't loopback 127.x.x.x
1311             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1312                 printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
1313             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1314             {
1315                 CAddress addr(*(unsigned int*)phostent->h_addr_list[i], GetDefaultPort(), nLocalServices);
1316                 if (addr.IsValid() && addr.GetByte(3) != 127)
1317                 {
1318                     addrLocalHost = addr;
1319                     break;
1320                 }
1321             }
1322         }
1323     }
1324 #else
1325     // Get local host ip
1326     struct ifaddrs* myaddrs;
1327     if (getifaddrs(&myaddrs) == 0)
1328     {
1329         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1330         {
1331             if (ifa->ifa_addr == NULL) continue;
1332             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1333             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1334             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1335             char pszIP[100];
1336             if (ifa->ifa_addr->sa_family == AF_INET)
1337             {
1338                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1339                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1340                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1341
1342                 // Take the first IP that isn't loopback 127.x.x.x
1343                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetDefaultPort(), nLocalServices);
1344                 if (addr.IsValid() && addr.GetByte(3) != 127)
1345                 {
1346                     addrLocalHost = addr;
1347                     break;
1348                 }
1349             }
1350             else if (ifa->ifa_addr->sa_family == AF_INET6)
1351             {
1352                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1353                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1354                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1355             }
1356         }
1357         freeifaddrs(myaddrs);
1358     }
1359 #endif
1360     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1361
1362     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1363     {
1364         // Proxies can't take incoming connections
1365         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1366         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1367     }
1368     else
1369     {
1370         CreateThread(ThreadGetMyExternalIP, NULL);
1371     }
1372
1373     //
1374     // Start threads
1375     //
1376
1377     // Get addresses from IRC and advertise ours
1378     if (!CreateThread(ThreadIRCSeed, NULL))
1379         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1380
1381     // Send and receive from sockets, accept connections
1382     pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1383
1384     // Initiate outbound connections
1385     if (!CreateThread(ThreadOpenConnections, NULL))
1386         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1387
1388     // Process messages
1389     if (!CreateThread(ThreadMessageHandler, NULL))
1390         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1391
1392     // Generate coins in the background
1393     GenerateBitcoins(fGenerateBitcoins);
1394 }
1395
1396 bool StopNode()
1397 {
1398     printf("StopNode()\n");
1399     fShutdown = true;
1400     nTransactionsUpdated++;
1401     int64 nStart = GetTime();
1402     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
1403     {
1404         if (GetTime() - nStart > 20)
1405             break;
1406         Sleep(20);
1407     }
1408     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1409     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1410     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1411     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1412     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1413     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1414         Sleep(20);
1415     Sleep(50);
1416
1417     return true;
1418 }
1419
1420 class CNetCleanup
1421 {
1422 public:
1423     CNetCleanup()
1424     {
1425     }
1426     ~CNetCleanup()
1427     {
1428         // Close sockets
1429         foreach(CNode* pnode, vNodes)
1430             if (pnode->hSocket != INVALID_SOCKET)
1431                 closesocket(pnode->hSocket);
1432         if (hListenSocket != INVALID_SOCKET)
1433             if (closesocket(hListenSocket) == SOCKET_ERROR)
1434                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1435
1436 #ifdef __WXMSW__
1437         // Shutdown Windows Sockets
1438         WSACleanup();
1439 #endif
1440     }
1441 }
1442 instance_of_cnetcleanup;