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