The -rpcssl command line option is a boolean, like -server, -daemon, -testnet, etc...
[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             if (hSocket == INVALID_SOCKET)
692             {
693                 if (WSAGetLastError() != WSAEWOULDBLOCK)
694                     printf("socket error accept failed: %d\n", WSAGetLastError());
695             }
696             else if (mapArgs.count("-maxconnections") && (int)vNodes.size() >= atoi(mapArgs["-maxconnections"]) - MAX_OUTBOUND_CONNECTIONS)
697             {
698                 closesocket(hSocket);
699             }
700             else
701             {
702                 printf("accepted connection %s\n", addr.ToStringLog().c_str());
703                 CNode* pnode = new CNode(hSocket, addr, true);
704                 pnode->AddRef();
705                 CRITICAL_BLOCK(cs_vNodes)
706                     vNodes.push_back(pnode);
707             }
708         }
709
710
711         //
712         // Service each socket
713         //
714         vector<CNode*> vNodesCopy;
715         CRITICAL_BLOCK(cs_vNodes)
716         {
717             vNodesCopy = vNodes;
718             foreach(CNode* pnode, vNodesCopy)
719                 pnode->AddRef();
720         }
721         foreach(CNode* pnode, vNodesCopy)
722         {
723             if (fShutdown)
724                 return;
725
726             //
727             // Receive
728             //
729             if (pnode->hSocket == INVALID_SOCKET)
730                 continue;
731             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
732             {
733                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
734                 {
735                     CDataStream& vRecv = pnode->vRecv;
736                     unsigned int nPos = vRecv.size();
737
738                     // typical socket buffer is 8K-64K
739                     char pchBuf[0x10000];
740                     int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
741                     if (nBytes > 0)
742                     {
743                         vRecv.resize(nPos + nBytes);
744                         memcpy(&vRecv[nPos], pchBuf, nBytes);
745                         pnode->nLastRecv = GetTime();
746                     }
747                     else if (nBytes == 0)
748                     {
749                         // socket closed gracefully
750                         if (!pnode->fDisconnect)
751                             printf("socket closed\n");
752                         pnode->CloseSocketDisconnect();
753                     }
754                     else if (nBytes < 0)
755                     {
756                         // error
757                         int nErr = WSAGetLastError();
758                         if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
759                         {
760                             if (!pnode->fDisconnect)
761                                 printf("socket recv error %d\n", nErr);
762                             pnode->CloseSocketDisconnect();
763                         }
764                     }
765                 }
766             }
767
768             //
769             // Send
770             //
771             if (pnode->hSocket == INVALID_SOCKET)
772                 continue;
773             if (FD_ISSET(pnode->hSocket, &fdsetSend))
774             {
775                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
776                 {
777                     CDataStream& vSend = pnode->vSend;
778                     if (!vSend.empty())
779                     {
780                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
781                         if (nBytes > 0)
782                         {
783                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
784                             pnode->nLastSend = GetTime();
785                         }
786                         else if (nBytes < 0)
787                         {
788                             // error
789                             int nErr = WSAGetLastError();
790                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
791                             {
792                                 printf("socket send error %d\n", nErr);
793                                 pnode->CloseSocketDisconnect();
794                             }
795                         }
796                     }
797                 }
798             }
799
800             //
801             // Inactivity checking
802             //
803             if (pnode->vSend.empty())
804                 pnode->nLastSendEmpty = GetTime();
805             if (GetTime() - pnode->nTimeConnected > 60)
806             {
807                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
808                 {
809                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
810                     pnode->fDisconnect = true;
811                 }
812                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
813                 {
814                     printf("socket not sending\n");
815                     pnode->fDisconnect = true;
816                 }
817                 else if (GetTime() - pnode->nLastRecv > 90*60)
818                 {
819                     printf("socket inactivity timeout\n");
820                     pnode->fDisconnect = true;
821                 }
822             }
823         }
824         CRITICAL_BLOCK(cs_vNodes)
825         {
826             foreach(CNode* pnode, vNodesCopy)
827                 pnode->Release();
828         }
829
830         Sleep(10);
831     }
832 }
833
834
835
836
837
838
839
840
841
842
843
844
845
846 unsigned int pnSeed[] =
847 {
848     // 2010/06
849     0x35218252, 0x9c9c9618, 0xda6bacad, 0xb9aca862, 0x97c235c6,
850     0x146f9562, 0xb67b9e4b, 0x87cf4bc0, 0xb83945d0, 0x984333ad,
851     0xbbeec555, 0x6f0eb440, 0xe0005318, 0x7797e460, 0xddc60fcc,
852     0xb3bbd24a, 0x1ac85746, 0x641846a6, 0x85ee1155, 0xbb2e7a4c,
853     0x9cb8514b, 0xfc342648, 0x62958fae, 0xd0a8c87a, 0xa800795b,
854     0xda8c814e, 0x256a0c80, 0x3f23ec63, 0xd565df43, 0x997d9044,
855     0xaa121448, 0xbed8688e, 0x59d09a5e, 0xb2931243, 0x3730ba18,
856     0xdd3462d0, 0x4e4d1448, 0x171df645, 0x84ee1155,
857     0x248ac445, 0x0e634444, 0x0ded1b63, 0x30c01e60,
858     0xa2b9a094, 0x29e4fd43, 0x9ce61b4c, 0xdae09744,
859
860     // 2010/08
861     0x5ae6bf43, 0x460be257, 0x7245c0cf, 0x4e0f028d, 0x26501760, 0x38643255, 0x67094f4f, 0x480449b8,
862     0x16545143, 0x1f082e5a, 0xaa428018, 0xe411e793, 0x14c1f862, 0x2726105b, 0x9b33ea50, 0xeeef86ca,
863     0xe3210d44, 0x0dca8b63, 0x3f9dfb18, 0x860340ad, 0xf33ba17a, 0x9018375c, 0x1de4e353, 0x0fa52dcb,
864     0x89c4555b, 0x109cf37b, 0x28c55b40, 0x04c801ae, 0x275c1e80, 0x6f7f745d, 0x7a2a5653, 0xa28e26d8,
865     0xa4e65db2, 0x99a06580, 0xf253ba44, 0x82cf6ab8, 0x859c2e8e, 0xf71a815d, 0xc18f1454, 0x71c8a943,
866     0x90d24e18, 0x311789b2, 0x74aba645, 0xde0bbfc3, 0xad724fad, 0xbf1ae15e, 0xbaa6fb54, 0x06e4d145,
867     0x51528645, 0x72120cd4, 0xd4cfd145, 0x0a7afed8, 0x9b9a5fad, 0x9e9ff45e, 0x10128355, 0xd44e8646,
868     0x04a07b47, 0x5fc9d547, 0xe0491e45, 0xbac21b41, 0x7aa31bae, 0x10483c5f, 0x94a23055, 0x73d9dc47,
869     0x1a99c247, 0x822fe847, 0x7e57ba48, 0xb19ea843, 0xa60621b2, 0x778cf163, 0x125c6556, 0xf94ba44f,
870     0xa61a0948, 0x6c839e4b, 0x29af5348, 0x68d84845, 0x752b95c3, 0xcf0d4663, 0x08e11e56, 0x75109550,
871     0x5f24b94c, 0x42426d4d, 0xfbbc0a4c, 0x70a9a246, 0xda7837cb, 0xae2a986d, 0xe283c358, 0x0c7ca954,
872     0x8e9bde59, 0x61521760, 0x6884444c, 0xa194e548, 0x9b8809cc, 0x16e96a8f, 0x956ff859, 0xfad5e555,
873     0x0ea70c80, 0x5b4ce26d, 0x7984444c, 0x1080d24a, 0x22a686cf, 0x6bf8c2ad, 0xb0f7485f, 0x06b66e56,
874     0x668373bc, 0x75506279, 0x3868694e, 0x12a5954b, 0x3a8b62d1, 0xb74fcbad, 0xa7dc3360, 0xc070b359,
875     0xa2b87242, 0xc45cab7c, 0x69882050, 0x14a5464b, 0x386acad5, 0x80b85db2, 0x1f78a062, 0xc608c55b,
876     0x4257d543, 0x7636ad80, 0x4432d655, 0xb2114d4b, 0x32639bd9, 0xadd75db2, 0x9be5a362, 0x6831bc5e,
877     0xf7f77046, 0x8f35ba81, 0x09bb4e59, 0xd0fb6b4e, 0xc5daa445, 0x9c611618, 0x355dcc62, 0xf2cf435e,
878     0x31e72c46, 0xdd8a43ad, 0x171f9c5b, 0xb4c2e355, 0xbe8af945, 0x613d3942, 0xe6f9e863, 0x7a3d855f,
879     0xa66adc47, 0x261089b2, 0x5a27105b, 0x6c28105b, 0xdd247946, 0xe6c3a445, 0x43a1ec63, 0x99b4dd5f,
880     0xb6834347, 0x5e9649bc, 0xf9dd545d, 0x6ae4c15b, 0xa5318a47, 0x7984ec47, 0x93a73b63, 0x0c60195f,
881     0xa5c85e4b, 0xa0a36dc2, 0x0739a95e, 0x3d44c15b, 0xfb940f4b, 0xd67c9148, 0x614f9876, 0x0a241c5f,
882     0xad9da74c, 0x4459abc8, 0x12e71b5f, 0x1c534a5d, 0x8ff5fc50, 0x2ca8864b, 0xd894fd80, 0x82ab3160,
883     0x390d804e, 0x2cf310cc, 0x680dad80, 0x691be15e, 0x5a8f4652, 0xaad0784d, 0x0d2431ad,
884 };
885
886
887
888 void ThreadOpenConnections(void* parg)
889 {
890     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
891     try
892     {
893         vnThreadsRunning[1]++;
894         ThreadOpenConnections2(parg);
895         vnThreadsRunning[1]--;
896     }
897     catch (std::exception& e) {
898         vnThreadsRunning[1]--;
899         PrintException(&e, "ThreadOpenConnections()");
900     } catch (...) {
901         vnThreadsRunning[1]--;
902         PrintException(NULL, "ThreadOpenConnections()");
903     }
904     printf("ThreadOpenConnections exiting\n");
905 }
906
907 void ThreadOpenConnections2(void* parg)
908 {
909     printf("ThreadOpenConnections started\n");
910
911     // Connect to specific addresses
912     if (mapArgs.count("-connect"))
913     {
914         for (int64 nLoop = 0;; nLoop++)
915         {
916             foreach(string strAddr, mapMultiArgs["-connect"])
917             {
918                 CAddress addr(strAddr, NODE_NETWORK);
919                 if (addr.IsValid())
920                     OpenNetworkConnection(addr);
921                 for (int i = 0; i < 10 && i < nLoop; i++)
922                 {
923                     Sleep(500);
924                     if (fShutdown)
925                         return;
926                 }
927             }
928         }
929     }
930
931     // Connect to manually added nodes first
932     if (mapArgs.count("-addnode"))
933     {
934         foreach(string strAddr, mapMultiArgs["-addnode"])
935         {
936             CAddress addr(strAddr, NODE_NETWORK);
937             if (addr.IsValid())
938             {
939                 OpenNetworkConnection(addr);
940                 Sleep(500);
941                 if (fShutdown)
942                     return;
943             }
944         }
945     }
946
947     // Initiate network connections
948     int64 nStart = GetTime();
949     loop
950     {
951         // Limit outbound connections
952         vnThreadsRunning[1]--;
953         Sleep(500);
954         loop
955         {
956             int nOutbound = 0;
957             CRITICAL_BLOCK(cs_vNodes)
958                 foreach(CNode* pnode, vNodes)
959                     if (!pnode->fInbound)
960                         nOutbound++;
961             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
962             if (mapArgs.count("-maxconnections"))
963                 nMaxOutboundConnections = min(nMaxOutboundConnections, atoi(mapArgs["-maxconnections"]));
964             if (nOutbound < nMaxOutboundConnections)
965                 break;
966             Sleep(2000);
967             if (fShutdown)
968                 return;
969         }
970         vnThreadsRunning[1]++;
971         if (fShutdown)
972             return;
973
974         CRITICAL_BLOCK(cs_mapAddresses)
975         {
976             // Add seed nodes if IRC isn't working
977             static bool fSeedUsed;
978             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
979             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
980             {
981                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
982                 {
983                     // It'll only connect to one or two seed nodes because once it connects,
984                     // it'll get a pile of addresses with newer timestamps.
985                     CAddress addr;
986                     addr.ip = pnSeed[i];
987                     addr.nTime = 0;
988                     AddAddress(addr);
989                 }
990                 fSeedUsed = true;
991             }
992
993             if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
994             {
995                 // Disconnect seed nodes
996                 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
997                 static int64 nSeedDisconnected;
998                 if (nSeedDisconnected == 0)
999                 {
1000                     nSeedDisconnected = GetTime();
1001                     CRITICAL_BLOCK(cs_vNodes)
1002                         foreach(CNode* pnode, vNodes)
1003                             if (setSeed.count(pnode->addr.ip))
1004                                 pnode->fDisconnect = true;
1005                 }
1006
1007                 // Keep setting timestamps to 0 so they won't reconnect
1008                 if (GetTime() - nSeedDisconnected < 60 * 60)
1009                 {
1010                     foreach(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1011                     {
1012                         if (setSeed.count(item.second.ip))
1013                         {
1014                             item.second.nTime = 0;
1015                             CAddrDB().WriteAddress(item.second);
1016                         }
1017                     }
1018                 }
1019             }
1020         }
1021
1022
1023         //
1024         // Choose an address to connect to based on most recently seen
1025         //
1026         CAddress addrConnect;
1027         int64 nBest = INT64_MIN;
1028
1029         // Only connect to one address per a.b.?.? range.
1030         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1031         set<unsigned int> setConnected;
1032         CRITICAL_BLOCK(cs_vNodes)
1033             foreach(CNode* pnode, vNodes)
1034                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1035
1036         CRITICAL_BLOCK(cs_mapAddresses)
1037         {
1038             foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1039             {
1040                 const CAddress& addr = item.second;
1041                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1042                     continue;
1043                 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1044                 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1045
1046                 // Randomize the order in a deterministic way, putting the standard port first
1047                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1048                 if (addr.port != GetDefaultPort())
1049                     nRandomizer += 2 * 60 * 60;
1050
1051                 // Last seen  Base retry frequency
1052                 //   <1 hour   10 min
1053                 //    1 hour    1 hour
1054                 //    4 hours   2 hours
1055                 //   24 hours   5 hours
1056                 //   48 hours   7 hours
1057                 //    7 days   13 hours
1058                 //   30 days   27 hours
1059                 //   90 days   46 hours
1060                 //  365 days   93 hours
1061                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1062
1063                 // Fast reconnect for one hour after last seen
1064                 if (nSinceLastSeen < 60 * 60)
1065                     nDelay = 10 * 60;
1066
1067                 // Limit retry frequency
1068                 if (nSinceLastTry < nDelay)
1069                     continue;
1070
1071                 // If we have IRC, we'll be notified when they first come online,
1072                 // and again every 24 hours by the refresh broadcast.
1073                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1074                     continue;
1075
1076                 // Only try the old stuff if we don't have enough connections
1077                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1078                     continue;
1079
1080                 // If multiple addresses are ready, prioritize by time since
1081                 // last seen and time since last tried.
1082                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1083                 if (nScore > nBest)
1084                 {
1085                     nBest = nScore;
1086                     addrConnect = addr;
1087                 }
1088             }
1089         }
1090
1091         if (addrConnect.IsValid())
1092             OpenNetworkConnection(addrConnect);
1093     }
1094 }
1095
1096 bool OpenNetworkConnection(const CAddress& addrConnect)
1097 {
1098     //
1099     // Initiate outbound network connection
1100     //
1101     if (fShutdown)
1102         return false;
1103     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1104         return false;
1105
1106     vnThreadsRunning[1]--;
1107     CNode* pnode = ConnectNode(addrConnect);
1108     vnThreadsRunning[1]++;
1109     if (fShutdown)
1110         return false;
1111     if (!pnode)
1112         return false;
1113     pnode->fNetworkNode = true;
1114
1115     return true;
1116 }
1117
1118
1119
1120
1121
1122
1123
1124
1125 void ThreadMessageHandler(void* parg)
1126 {
1127     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1128     try
1129     {
1130         vnThreadsRunning[2]++;
1131         ThreadMessageHandler2(parg);
1132         vnThreadsRunning[2]--;
1133     }
1134     catch (std::exception& e) {
1135         vnThreadsRunning[2]--;
1136         PrintException(&e, "ThreadMessageHandler()");
1137     } catch (...) {
1138         vnThreadsRunning[2]--;
1139         PrintException(NULL, "ThreadMessageHandler()");
1140     }
1141     printf("ThreadMessageHandler exiting\n");
1142 }
1143
1144 void ThreadMessageHandler2(void* parg)
1145 {
1146     printf("ThreadMessageHandler started\n");
1147     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1148     while (!fShutdown)
1149     {
1150         vector<CNode*> vNodesCopy;
1151         CRITICAL_BLOCK(cs_vNodes)
1152         {
1153             vNodesCopy = vNodes;
1154             foreach(CNode* pnode, vNodesCopy)
1155                 pnode->AddRef();
1156         }
1157
1158         // Poll the connected nodes for messages
1159         CNode* pnodeTrickle = NULL;
1160         if (!vNodesCopy.empty())
1161             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1162         foreach(CNode* pnode, vNodesCopy)
1163         {
1164             // Receive messages
1165             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1166                 ProcessMessages(pnode);
1167             if (fShutdown)
1168                 return;
1169
1170             // Send messages
1171             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1172                 SendMessages(pnode, pnode == pnodeTrickle);
1173             if (fShutdown)
1174                 return;
1175         }
1176
1177         CRITICAL_BLOCK(cs_vNodes)
1178         {
1179             foreach(CNode* pnode, vNodesCopy)
1180                 pnode->Release();
1181         }
1182
1183         // Wait and allow messages to bunch up.
1184         // Reduce vnThreadsRunning so StopNode has permission to exit while
1185         // we're sleeping, but we must always check fShutdown after doing this.
1186         vnThreadsRunning[2]--;
1187         Sleep(100);
1188         if (fRequestShutdown)
1189             Shutdown(NULL);
1190         vnThreadsRunning[2]++;
1191         if (fShutdown)
1192             return;
1193     }
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204 bool BindListenPort(string& strError)
1205 {
1206     strError = "";
1207     int nOne = 1;
1208     addrLocalHost.port = GetDefaultPort();
1209
1210 #ifdef __WXMSW__
1211     // Initialize Windows Sockets
1212     WSADATA wsadata;
1213     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1214     if (ret != NO_ERROR)
1215     {
1216         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1217         printf("%s\n", strError.c_str());
1218         return false;
1219     }
1220 #endif
1221
1222     // Create socket for listening for incoming connections
1223     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1224     if (hListenSocket == INVALID_SOCKET)
1225     {
1226         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1227         printf("%s\n", strError.c_str());
1228         return false;
1229     }
1230
1231 #ifdef BSD
1232     // Different way of disabling SIGPIPE on BSD
1233     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1234 #endif
1235
1236 #ifndef __WXMSW__
1237     // Allow binding if the port is still in TIME_WAIT state after
1238     // the program was closed and restarted.  Not an issue on windows.
1239     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1240 #endif
1241
1242 #ifdef __WXMSW__
1243     // Set to nonblocking, incoming connections will also inherit this
1244     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1245 #else
1246     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1247 #endif
1248     {
1249         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1250         printf("%s\n", strError.c_str());
1251         return false;
1252     }
1253
1254     // The sockaddr_in structure specifies the address family,
1255     // IP address, and port for the socket that is being bound
1256     struct sockaddr_in sockaddr;
1257     memset(&sockaddr, 0, sizeof(sockaddr));
1258     sockaddr.sin_family = AF_INET;
1259     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1260     sockaddr.sin_port = GetDefaultPort();
1261     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1262     {
1263         int nErr = WSAGetLastError();
1264         if (nErr == WSAEADDRINUSE)
1265             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1266         else
1267             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1268         printf("%s\n", strError.c_str());
1269         return false;
1270     }
1271     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1272
1273     // Listen for incoming connections
1274     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1275     {
1276         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1277         printf("%s\n", strError.c_str());
1278         return false;
1279     }
1280
1281     return true;
1282 }
1283
1284 void StartNode(void* parg)
1285 {
1286     if (pnodeLocalHost == NULL)
1287         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", nLocalServices));
1288
1289 #ifdef __WXMSW__
1290     // Get local host ip
1291     char pszHostName[1000] = "";
1292     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1293     {
1294         struct hostent* phostent = gethostbyname(pszHostName);
1295         if (phostent)
1296         {
1297             // Take the first IP that isn't loopback 127.x.x.x
1298             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1299                 printf("host ip %d: %s\n", i, CAddress(*(unsigned int*)phostent->h_addr_list[i]).ToStringIP().c_str());
1300             for (int i = 0; phostent->h_addr_list[i] != NULL; i++)
1301             {
1302                 CAddress addr(*(unsigned int*)phostent->h_addr_list[i], GetDefaultPort(), nLocalServices);
1303                 if (addr.IsValid() && addr.GetByte(3) != 127)
1304                 {
1305                     addrLocalHost = addr;
1306                     break;
1307                 }
1308             }
1309         }
1310     }
1311 #else
1312     // Get local host ip
1313     struct ifaddrs* myaddrs;
1314     if (getifaddrs(&myaddrs) == 0)
1315     {
1316         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1317         {
1318             if (ifa->ifa_addr == NULL) continue;
1319             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1320             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1321             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1322             char pszIP[100];
1323             if (ifa->ifa_addr->sa_family == AF_INET)
1324             {
1325                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1326                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1327                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1328
1329                 // Take the first IP that isn't loopback 127.x.x.x
1330                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetDefaultPort(), nLocalServices);
1331                 if (addr.IsValid() && addr.GetByte(3) != 127)
1332                 {
1333                     addrLocalHost = addr;
1334                     break;
1335                 }
1336             }
1337             else if (ifa->ifa_addr->sa_family == AF_INET6)
1338             {
1339                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1340                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1341                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1342             }
1343         }
1344         freeifaddrs(myaddrs);
1345     }
1346 #endif
1347     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1348
1349     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1350     {
1351         // Proxies can't take incoming connections
1352         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1353         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1354     }
1355     else
1356     {
1357         CreateThread(ThreadGetMyExternalIP, NULL);
1358     }
1359
1360     //
1361     // Start threads
1362     //
1363
1364     // Get addresses from IRC and advertise ours
1365     if (!CreateThread(ThreadIRCSeed, NULL))
1366         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1367
1368     // Send and receive from sockets, accept connections
1369     pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1370
1371     // Initiate outbound connections
1372     if (!CreateThread(ThreadOpenConnections, NULL))
1373         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1374
1375     // Process messages
1376     if (!CreateThread(ThreadMessageHandler, NULL))
1377         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1378
1379     // Generate coins in the background
1380     GenerateBitcoins(fGenerateBitcoins);
1381 }
1382
1383 bool StopNode()
1384 {
1385     printf("StopNode()\n");
1386     fShutdown = true;
1387     nTransactionsUpdated++;
1388     int64 nStart = GetTime();
1389     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0)
1390     {
1391         if (GetTime() - nStart > 20)
1392             break;
1393         Sleep(20);
1394     }
1395     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1396     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1397     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1398     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1399     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1400     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1401         Sleep(20);
1402     Sleep(50);
1403
1404     return true;
1405 }
1406
1407 class CNetCleanup
1408 {
1409 public:
1410     CNetCleanup()
1411     {
1412     }
1413     ~CNetCleanup()
1414     {
1415         // Close sockets
1416         foreach(CNode* pnode, vNodes)
1417             if (pnode->hSocket != INVALID_SOCKET)
1418                 closesocket(pnode->hSocket);
1419         if (hListenSocket != INVALID_SOCKET)
1420             if (closesocket(hListenSocket) == SOCKET_ERROR)
1421                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1422
1423 #ifdef __WXMSW__
1424         // Shutdown Windows Sockets
1425         WSACleanup();
1426 #endif
1427     }
1428 }
1429 instance_of_cnetcleanup;