PPCoin: Separate from bitcoin network; Rename directories and files
[novacoin.git] / src / net.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The PPCoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "headers.h"
7 #include "irc.h"
8 #include "db.h"
9 #include "net.h"
10 #include "init.h"
11 #include "strlcpy.h"
12
13 #ifdef __WXMSW__
14 #include <string.h>
15 // This file can be downloaded as a part of the Windows Platform SDK
16 // and is required for Bitcoin binaries to work properly on versions
17 // of Windows before XP.  If you are doing builds of Bitcoin for
18 // public release, you should uncomment this line.
19 //#include <WSPiApi.h>
20 #endif
21
22 #ifdef USE_UPNP
23 #include <miniupnpc/miniwget.h>
24 #include <miniupnpc/miniupnpc.h>
25 #include <miniupnpc/upnpcommands.h>
26 #include <miniupnpc/upnperrors.h>
27 #endif
28
29 using namespace std;
30 using namespace boost;
31
32 static const int MAX_OUTBOUND_CONNECTIONS = 8;
33
34 void ThreadMessageHandler2(void* parg);
35 void ThreadSocketHandler2(void* parg);
36 void ThreadOpenConnections2(void* parg);
37 #ifdef USE_UPNP
38 void ThreadMapPort2(void* parg);
39 #endif
40 bool OpenNetworkConnection(const CAddress& addrConnect);
41
42
43
44
45
46 //
47 // Global state variables
48 //
49 bool fClient = false;
50 bool fAllowDNS = false;
51 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
52 CAddress addrLocalHost("0.0.0.0", 0, false, nLocalServices);
53 CNode* pnodeLocalHost = NULL;
54 uint64 nLocalHostNonce = 0;
55 array<int, 10> vnThreadsRunning;
56 SOCKET hListenSocket = INVALID_SOCKET;
57
58 vector<CNode*> vNodes;
59 CCriticalSection cs_vNodes;
60 map<vector<unsigned char>, CAddress> mapAddresses;
61 CCriticalSection cs_mapAddresses;
62 map<CInv, CDataStream> mapRelay;
63 deque<pair<int64, CInv> > vRelayExpiration;
64 CCriticalSection cs_mapRelay;
65 map<CInv, int64> mapAlreadyAskedFor;
66
67 // Settings
68 int fUseProxy = false;
69 int nConnectTimeout = 5000;
70 CAddress addrProxy("127.0.0.1",9050);
71
72
73
74
75 unsigned short GetListenPort()
76 {
77     return (unsigned short)(GetArg("-port", GetDefaultPort()));
78 }
79
80 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
81 {
82     // Filter out duplicate requests
83     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
84         return;
85     pindexLastGetBlocksBegin = pindexBegin;
86     hashLastGetBlocksEnd = hashEnd;
87
88     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
89 }
90
91
92
93
94
95 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
96 {
97     hSocketRet = INVALID_SOCKET;
98
99     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
100     if (hSocket == INVALID_SOCKET)
101         return false;
102 #ifdef BSD
103     int set = 1;
104     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
105 #endif
106
107     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
108     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
109
110 #ifdef __WXMSW__
111     u_long fNonblock = 1;
112     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
113 #else
114     int fFlags = fcntl(hSocket, F_GETFL, 0);
115     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
116 #endif
117     {
118         closesocket(hSocket);
119         return false;
120     }
121
122
123     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
124     {
125         // WSAEINVAL is here because some legacy version of winsock uses it
126         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
127         {
128             struct timeval timeout;
129             timeout.tv_sec  = nTimeout / 1000;
130             timeout.tv_usec = (nTimeout % 1000) * 1000;
131
132             fd_set fdset;
133             FD_ZERO(&fdset);
134             FD_SET(hSocket, &fdset);
135             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
136             if (nRet == 0)
137             {
138                 printf("connection timeout\n");
139                 closesocket(hSocket);
140                 return false;
141             }
142             if (nRet == SOCKET_ERROR)
143             {
144                 printf("select() for connection failed: %i\n",WSAGetLastError());
145                 closesocket(hSocket);
146                 return false;
147             }
148             socklen_t nRetSize = sizeof(nRet);
149 #ifdef __WXMSW__
150             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
151 #else
152             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
153 #endif
154             {
155                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
156                 closesocket(hSocket);
157                 return false;
158             }
159             if (nRet != 0)
160             {
161                 printf("connect() failed after select(): %s\n",strerror(nRet));
162                 closesocket(hSocket);
163                 return false;
164             }
165         }
166 #ifdef __WXMSW__
167         else if (WSAGetLastError() != WSAEISCONN)
168 #else
169         else
170 #endif
171         {
172             printf("connect() failed: %i\n",WSAGetLastError());
173             closesocket(hSocket);
174             return false;
175         }
176     }
177
178     /*
179     this isn't even strictly necessary
180     CNode::ConnectNode immediately turns the socket back to non-blocking
181     but we'll turn it back to blocking just in case
182     */
183 #ifdef __WXMSW__
184     fNonblock = 0;
185     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
186 #else
187     fFlags = fcntl(hSocket, F_GETFL, 0);
188     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
189 #endif
190     {
191         closesocket(hSocket);
192         return false;
193     }
194
195     if (fProxy)
196     {
197         printf("proxy connecting %s\n", addrConnect.ToString().c_str());
198         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
199         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
200         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
201         char* pszSocks4 = pszSocks4IP;
202         int nSize = sizeof(pszSocks4IP);
203
204         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
205         if (ret != nSize)
206         {
207             closesocket(hSocket);
208             return error("Error sending to proxy");
209         }
210         char pchRet[8];
211         if (recv(hSocket, pchRet, 8, 0) != 8)
212         {
213             closesocket(hSocket);
214             return error("Error reading proxy response");
215         }
216         if (pchRet[1] != 0x5a)
217         {
218             closesocket(hSocket);
219             if (pchRet[1] != 0x5b)
220                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
221             return false;
222         }
223         printf("proxy connected %s\n", addrConnect.ToString().c_str());
224     }
225
226     hSocketRet = hSocket;
227     return true;
228 }
229
230 // portDefault is in host order
231 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup, int portDefault, bool fAllowPort)
232 {
233     vaddr.clear();
234     if (pszName[0] == 0)
235         return false;
236     int port = portDefault;
237     char psz[256];
238     char *pszHost = psz;
239     strlcpy(psz, pszName, sizeof(psz));
240     if (fAllowPort)
241     {
242         char* pszColon = strrchr(psz+1,':');
243         char *pszPortEnd = NULL;
244         int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
245         if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
246         {
247             if (psz[0] == '[' && pszColon[-1] == ']')
248             {
249                 // Future: enable IPv6 colon-notation inside []
250                 pszHost = psz+1;
251                 pszColon[-1] = 0;
252             }
253             else
254                 pszColon[0] = 0;
255             port = portParsed;
256             if (port < 0 || port > USHRT_MAX)
257                 port = USHRT_MAX;
258         }
259     }
260
261     unsigned int addrIP = inet_addr(pszHost);
262     if (addrIP != INADDR_NONE)
263     {
264         // valid IP address passed
265         vaddr.push_back(CAddress(addrIP, port, nServices));
266         return true;
267     }
268
269     if (!fAllowLookup)
270         return false;
271
272     struct hostent* phostent = gethostbyname(pszHost);
273     if (!phostent)
274         return false;
275
276     if (phostent->h_addrtype != AF_INET)
277         return false;
278
279     char** ppAddr = phostent->h_addr_list;
280     while (*ppAddr != NULL && vaddr.size() != nMaxSolutions)
281     {
282         CAddress addr(((struct in_addr*)ppAddr[0])->s_addr, port, nServices);
283         if (addr.IsValid())
284             vaddr.push_back(addr);
285         ppAddr++;
286     }
287
288     return (vaddr.size() > 0);
289 }
290
291 // portDefault is in host order
292 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup, int portDefault, bool fAllowPort)
293 {
294     vector<CAddress> vaddr;
295     bool fRet = Lookup(pszName, vaddr, nServices, 1, fAllowLookup, portDefault, fAllowPort);
296     if (fRet)
297         addr = vaddr[0];
298     return fRet;
299 }
300
301 bool GetMyExternalIP2(const CAddress& addrConnect, const char* pszGet, const char* pszKeyword, unsigned int& ipRet)
302 {
303     SOCKET hSocket;
304     if (!ConnectSocket(addrConnect, hSocket))
305         return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
306
307     send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
308
309     string strLine;
310     while (RecvLine(hSocket, strLine))
311     {
312         if (strLine.empty()) // HTTP response is separated from headers by blank line
313         {
314             loop
315             {
316                 if (!RecvLine(hSocket, strLine))
317                 {
318                     closesocket(hSocket);
319                     return false;
320                 }
321                 if (pszKeyword == NULL)
322                     break;
323                 if (strLine.find(pszKeyword) != -1)
324                 {
325                     strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword));
326                     break;
327                 }
328             }
329             closesocket(hSocket);
330             if (strLine.find("<") != -1)
331                 strLine = strLine.substr(0, strLine.find("<"));
332             strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r"));
333             while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
334                 strLine.resize(strLine.size()-1);
335             CAddress addr(strLine,0,true);
336             printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
337             if (addr.ip == 0 || addr.ip == INADDR_NONE || !addr.IsRoutable())
338                 return false;
339             ipRet = addr.ip;
340             return true;
341         }
342     }
343     closesocket(hSocket);
344     return error("GetMyExternalIP() : connection closed");
345 }
346
347 // We now get our external IP from the IRC server first and only use this as a backup
348 bool GetMyExternalIP(unsigned int& ipRet)
349 {
350     CAddress addrConnect;
351     const char* pszGet;
352     const char* pszKeyword;
353
354     if (fUseProxy)
355         return false;
356
357     for (int nLookup = 0; nLookup <= 1; nLookup++)
358     for (int nHost = 1; nHost <= 2; nHost++)
359     {
360         // We should be phasing out our use of sites like these.  If we need
361         // replacements, we should ask for volunteers to put this simple
362         // php file on their webserver that prints the client IP:
363         //  <?php echo $_SERVER["REMOTE_ADDR"]; ?>
364         if (nHost == 1)
365         {
366             addrConnect = CAddress("91.198.22.70",80); // checkip.dyndns.org
367
368             if (nLookup == 1)
369             {
370                 CAddress addrIP("checkip.dyndns.org", 80, true);
371                 if (addrIP.IsValid())
372                     addrConnect = addrIP;
373             }
374
375             pszGet = "GET / HTTP/1.1\r\n"
376                      "Host: checkip.dyndns.org\r\n"
377                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
378                      "Connection: close\r\n"
379                      "\r\n";
380
381             pszKeyword = "Address:";
382         }
383         else if (nHost == 2)
384         {
385             addrConnect = CAddress("74.208.43.192", 80); // www.showmyip.com
386
387             if (nLookup == 1)
388             {
389                 CAddress addrIP("www.showmyip.com", 80, true);
390                 if (addrIP.IsValid())
391                     addrConnect = addrIP;
392             }
393
394             pszGet = "GET /simple/ HTTP/1.1\r\n"
395                      "Host: www.showmyip.com\r\n"
396                      "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
397                      "Connection: close\r\n"
398                      "\r\n";
399
400             pszKeyword = NULL; // Returns just IP address
401         }
402
403         if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
404             return true;
405     }
406
407     return false;
408 }
409
410 void ThreadGetMyExternalIP(void* parg)
411 {
412     // Wait for IRC to get it first
413     if (!GetBoolArg("-noirc"))
414     {
415         for (int i = 0; i < 2 * 60; i++)
416         {
417             Sleep(1000);
418             if (fGotExternalIP || fShutdown)
419                 return;
420         }
421     }
422
423     // Fallback in case IRC fails to get it
424     if (GetMyExternalIP(addrLocalHost.ip))
425     {
426         printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
427         if (addrLocalHost.IsRoutable())
428         {
429             // If we already connected to a few before we had our IP, go back and addr them.
430             // setAddrKnown automatically filters any duplicate sends.
431             CAddress addr(addrLocalHost);
432             addr.nTime = GetAdjustedTime();
433             CRITICAL_BLOCK(cs_vNodes)
434                 BOOST_FOREACH(CNode* pnode, vNodes)
435                     pnode->PushAddress(addr);
436         }
437     }
438 }
439
440
441
442
443
444 bool AddAddress(CAddress addr, int64 nTimePenalty)
445 {
446     if (!addr.IsRoutable())
447         return false;
448     if (addr.ip == addrLocalHost.ip)
449         return false;
450     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
451     CRITICAL_BLOCK(cs_mapAddresses)
452     {
453         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
454         if (it == mapAddresses.end())
455         {
456             // New address
457             printf("AddAddress(%s)\n", addr.ToString().c_str());
458             mapAddresses.insert(make_pair(addr.GetKey(), addr));
459             CAddrDB().WriteAddress(addr);
460             return true;
461         }
462         else
463         {
464             bool fUpdated = false;
465             CAddress& addrFound = (*it).second;
466             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
467             {
468                 // Services have been added
469                 addrFound.nServices |= addr.nServices;
470                 fUpdated = true;
471             }
472             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
473             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
474             if (addrFound.nTime < addr.nTime - nUpdateInterval)
475             {
476                 // Periodically update most recently seen time
477                 addrFound.nTime = addr.nTime;
478                 fUpdated = true;
479             }
480             if (fUpdated)
481                 CAddrDB().WriteAddress(addrFound);
482         }
483     }
484     return false;
485 }
486
487 void AddressCurrentlyConnected(const CAddress& addr)
488 {
489     CRITICAL_BLOCK(cs_mapAddresses)
490     {
491         // Only if it's been published already
492         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
493         if (it != mapAddresses.end())
494         {
495             CAddress& addrFound = (*it).second;
496             int64 nUpdateInterval = 20 * 60;
497             if (addrFound.nTime < GetAdjustedTime() - nUpdateInterval)
498             {
499                 // Periodically update most recently seen time
500                 addrFound.nTime = GetAdjustedTime();
501                 CAddrDB addrdb;
502                 addrdb.WriteAddress(addrFound);
503             }
504         }
505     }
506 }
507
508
509
510
511
512 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
513 {
514     // If the dialog might get closed before the reply comes back,
515     // call this in the destructor so it doesn't get called after it's deleted.
516     CRITICAL_BLOCK(cs_vNodes)
517     {
518         BOOST_FOREACH(CNode* pnode, vNodes)
519         {
520             CRITICAL_BLOCK(pnode->cs_mapRequests)
521             {
522                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
523                 {
524                     CRequestTracker& tracker = (*mi).second;
525                     if (tracker.fn == fn && tracker.param1 == param1)
526                         pnode->mapRequests.erase(mi++);
527                     else
528                         mi++;
529                 }
530             }
531         }
532     }
533 }
534
535
536
537
538
539
540
541 //
542 // Subscription methods for the broadcast and subscription system.
543 // Channel numbers are message numbers, i.e. MSG_TABLE and MSG_PRODUCT.
544 //
545 // The subscription system uses a meet-in-the-middle strategy.
546 // With 100,000 nodes, if senders broadcast to 1000 random nodes and receivers
547 // subscribe to 1000 random nodes, 99.995% (1 - 0.99^1000) of messages will get through.
548 //
549
550 bool AnySubscribed(unsigned int nChannel)
551 {
552     if (pnodeLocalHost->IsSubscribed(nChannel))
553         return true;
554     CRITICAL_BLOCK(cs_vNodes)
555         BOOST_FOREACH(CNode* pnode, vNodes)
556             if (pnode->IsSubscribed(nChannel))
557                 return true;
558     return false;
559 }
560
561 bool CNode::IsSubscribed(unsigned int nChannel)
562 {
563     if (nChannel >= vfSubscribe.size())
564         return false;
565     return vfSubscribe[nChannel];
566 }
567
568 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
569 {
570     if (nChannel >= vfSubscribe.size())
571         return;
572
573     if (!AnySubscribed(nChannel))
574     {
575         // Relay subscribe
576         CRITICAL_BLOCK(cs_vNodes)
577             BOOST_FOREACH(CNode* pnode, vNodes)
578                 if (pnode != this)
579                     pnode->PushMessage("subscribe", nChannel, nHops);
580     }
581
582     vfSubscribe[nChannel] = true;
583 }
584
585 void CNode::CancelSubscribe(unsigned int nChannel)
586 {
587     if (nChannel >= vfSubscribe.size())
588         return;
589
590     // Prevent from relaying cancel if wasn't subscribed
591     if (!vfSubscribe[nChannel])
592         return;
593     vfSubscribe[nChannel] = false;
594
595     if (!AnySubscribed(nChannel))
596     {
597         // Relay subscription cancel
598         CRITICAL_BLOCK(cs_vNodes)
599             BOOST_FOREACH(CNode* pnode, vNodes)
600                 if (pnode != this)
601                     pnode->PushMessage("sub-cancel", nChannel);
602     }
603 }
604
605
606
607
608
609
610
611
612
613 CNode* FindNode(unsigned int ip)
614 {
615     CRITICAL_BLOCK(cs_vNodes)
616     {
617         BOOST_FOREACH(CNode* pnode, vNodes)
618             if (pnode->addr.ip == ip)
619                 return (pnode);
620     }
621     return NULL;
622 }
623
624 CNode* FindNode(CAddress addr)
625 {
626     CRITICAL_BLOCK(cs_vNodes)
627     {
628         BOOST_FOREACH(CNode* pnode, vNodes)
629             if (pnode->addr == addr)
630                 return (pnode);
631     }
632     return NULL;
633 }
634
635 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
636 {
637     if (addrConnect.ip == addrLocalHost.ip)
638         return NULL;
639
640     // Look for an existing connection
641     CNode* pnode = FindNode(addrConnect.ip);
642     if (pnode)
643     {
644         if (nTimeout != 0)
645             pnode->AddRef(nTimeout);
646         else
647             pnode->AddRef();
648         return pnode;
649     }
650
651     /// debug print
652     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
653         addrConnect.ToString().c_str(),
654         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
655         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
656
657     CRITICAL_BLOCK(cs_mapAddresses)
658         mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
659
660     // Connect
661     SOCKET hSocket;
662     if (ConnectSocket(addrConnect, hSocket))
663     {
664         /// debug print
665         printf("connected %s\n", addrConnect.ToString().c_str());
666
667         // Set to nonblocking
668 #ifdef __WXMSW__
669         u_long nOne = 1;
670         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
671             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
672 #else
673         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
674             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
675 #endif
676
677         // Add node
678         CNode* pnode = new CNode(hSocket, addrConnect, false);
679         if (nTimeout != 0)
680             pnode->AddRef(nTimeout);
681         else
682             pnode->AddRef();
683         CRITICAL_BLOCK(cs_vNodes)
684             vNodes.push_back(pnode);
685
686         pnode->nTimeConnected = GetTime();
687         return pnode;
688     }
689     else
690     {
691         return NULL;
692     }
693 }
694
695 void CNode::CloseSocketDisconnect()
696 {
697     fDisconnect = true;
698     if (hSocket != INVALID_SOCKET)
699     {
700         if (fDebug)
701             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
702         printf("disconnecting node %s\n", addr.ToString().c_str());
703         closesocket(hSocket);
704         hSocket = INVALID_SOCKET;
705     }
706 }
707
708 void CNode::Cleanup()
709 {
710     // All of a nodes broadcasts and subscriptions are automatically torn down
711     // when it goes down, so a node has to stay up to keep its broadcast going.
712
713     // Cancel subscriptions
714     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
715         if (vfSubscribe[nChannel])
716             CancelSubscribe(nChannel);
717 }
718
719
720
721
722
723
724
725
726
727
728
729
730
731 void ThreadSocketHandler(void* parg)
732 {
733     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
734     try
735     {
736         vnThreadsRunning[0]++;
737         ThreadSocketHandler2(parg);
738         vnThreadsRunning[0]--;
739     }
740     catch (std::exception& e) {
741         vnThreadsRunning[0]--;
742         PrintException(&e, "ThreadSocketHandler()");
743     } catch (...) {
744         vnThreadsRunning[0]--;
745         throw; // support pthread_cancel()
746     }
747     printf("ThreadSocketHandler exiting\n");
748 }
749
750 void ThreadSocketHandler2(void* parg)
751 {
752     printf("ThreadSocketHandler started\n");
753     list<CNode*> vNodesDisconnected;
754     int nPrevNodeCount = 0;
755
756     loop
757     {
758         //
759         // Disconnect nodes
760         //
761         CRITICAL_BLOCK(cs_vNodes)
762         {
763             // Disconnect unused nodes
764             vector<CNode*> vNodesCopy = vNodes;
765             BOOST_FOREACH(CNode* pnode, vNodesCopy)
766             {
767                 if (pnode->fDisconnect ||
768                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
769                 {
770                     // remove from vNodes
771                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
772
773                     // close socket and cleanup
774                     pnode->CloseSocketDisconnect();
775                     pnode->Cleanup();
776
777                     // hold in disconnected pool until all refs are released
778                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
779                     if (pnode->fNetworkNode || pnode->fInbound)
780                         pnode->Release();
781                     vNodesDisconnected.push_back(pnode);
782                 }
783             }
784
785             // Delete disconnected nodes
786             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
787             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
788             {
789                 // wait until threads are done using it
790                 if (pnode->GetRefCount() <= 0)
791                 {
792                     bool fDelete = false;
793                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
794                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
795                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
796                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
797                         fDelete = true;
798                     if (fDelete)
799                     {
800                         vNodesDisconnected.remove(pnode);
801                         delete pnode;
802                     }
803                 }
804             }
805         }
806         if (vNodes.size() != nPrevNodeCount)
807         {
808             nPrevNodeCount = vNodes.size();
809             MainFrameRepaint();
810         }
811
812
813         //
814         // Find which sockets have data to receive
815         //
816         struct timeval timeout;
817         timeout.tv_sec  = 0;
818         timeout.tv_usec = 50000; // frequency to poll pnode->vSend
819
820         fd_set fdsetRecv;
821         fd_set fdsetSend;
822         fd_set fdsetError;
823         FD_ZERO(&fdsetRecv);
824         FD_ZERO(&fdsetSend);
825         FD_ZERO(&fdsetError);
826         SOCKET hSocketMax = 0;
827
828         if(hListenSocket != INVALID_SOCKET)
829             FD_SET(hListenSocket, &fdsetRecv);
830         hSocketMax = max(hSocketMax, hListenSocket);
831         CRITICAL_BLOCK(cs_vNodes)
832         {
833             BOOST_FOREACH(CNode* pnode, vNodes)
834             {
835                 if (pnode->hSocket == INVALID_SOCKET || pnode->hSocket < 0)
836                     continue;
837                 FD_SET(pnode->hSocket, &fdsetRecv);
838                 FD_SET(pnode->hSocket, &fdsetError);
839                 hSocketMax = max(hSocketMax, pnode->hSocket);
840                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
841                     if (!pnode->vSend.empty())
842                         FD_SET(pnode->hSocket, &fdsetSend);
843             }
844         }
845
846         vnThreadsRunning[0]--;
847         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
848         vnThreadsRunning[0]++;
849         if (fShutdown)
850             return;
851         if (nSelect == SOCKET_ERROR)
852         {
853             int nErr = WSAGetLastError();
854             if (hSocketMax > -1)
855             {
856                 printf("socket select error %d\n", nErr);
857                 for (int i = 0; i <= hSocketMax; i++)
858                     FD_SET(i, &fdsetRecv);
859             }
860             FD_ZERO(&fdsetSend);
861             FD_ZERO(&fdsetError);
862             Sleep(timeout.tv_usec/1000);
863         }
864
865
866         //
867         // Accept new connections
868         //
869         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
870         {
871             struct sockaddr_in sockaddr;
872             socklen_t len = sizeof(sockaddr);
873             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
874             CAddress addr(sockaddr);
875             int nInbound = 0;
876
877             CRITICAL_BLOCK(cs_vNodes)
878                 BOOST_FOREACH(CNode* pnode, vNodes)
879                 if (pnode->fInbound)
880                     nInbound++;
881             if (hSocket == INVALID_SOCKET)
882             {
883                 if (WSAGetLastError() != WSAEWOULDBLOCK)
884                     printf("socket error accept failed: %d\n", WSAGetLastError());
885             }
886             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
887             {
888                 closesocket(hSocket);
889             }
890             else
891             {
892                 printf("accepted connection %s\n", addr.ToString().c_str());
893                 CNode* pnode = new CNode(hSocket, addr, true);
894                 pnode->AddRef();
895                 CRITICAL_BLOCK(cs_vNodes)
896                     vNodes.push_back(pnode);
897             }
898         }
899
900
901         //
902         // Service each socket
903         //
904         vector<CNode*> vNodesCopy;
905         CRITICAL_BLOCK(cs_vNodes)
906         {
907             vNodesCopy = vNodes;
908             BOOST_FOREACH(CNode* pnode, vNodesCopy)
909                 pnode->AddRef();
910         }
911         BOOST_FOREACH(CNode* pnode, vNodesCopy)
912         {
913             if (fShutdown)
914                 return;
915
916             //
917             // Receive
918             //
919             if (pnode->hSocket == INVALID_SOCKET)
920                 continue;
921             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
922             {
923                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
924                 {
925                     CDataStream& vRecv = pnode->vRecv;
926                     unsigned int nPos = vRecv.size();
927
928                     if (nPos > ReceiveBufferSize()) {
929                         if (!pnode->fDisconnect)
930                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
931                         pnode->CloseSocketDisconnect();
932                     }
933                     else {
934                         // typical socket buffer is 8K-64K
935                         char pchBuf[0x10000];
936                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
937                         if (nBytes > 0)
938                         {
939                             vRecv.resize(nPos + nBytes);
940                             memcpy(&vRecv[nPos], pchBuf, nBytes);
941                             pnode->nLastRecv = GetTime();
942                         }
943                         else if (nBytes == 0)
944                         {
945                             // socket closed gracefully
946                             if (!pnode->fDisconnect)
947                                 printf("socket closed\n");
948                             pnode->CloseSocketDisconnect();
949                         }
950                         else if (nBytes < 0)
951                         {
952                             // error
953                             int nErr = WSAGetLastError();
954                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
955                             {
956                                 if (!pnode->fDisconnect)
957                                     printf("socket recv error %d\n", nErr);
958                                 pnode->CloseSocketDisconnect();
959                             }
960                         }
961                     }
962                 }
963             }
964
965             //
966             // Send
967             //
968             if (pnode->hSocket == INVALID_SOCKET)
969                 continue;
970             if (FD_ISSET(pnode->hSocket, &fdsetSend))
971             {
972                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
973                 {
974                     CDataStream& vSend = pnode->vSend;
975                     if (!vSend.empty())
976                     {
977                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
978                         if (nBytes > 0)
979                         {
980                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
981                             pnode->nLastSend = GetTime();
982                         }
983                         else if (nBytes < 0)
984                         {
985                             // error
986                             int nErr = WSAGetLastError();
987                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
988                             {
989                                 printf("socket send error %d\n", nErr);
990                                 pnode->CloseSocketDisconnect();
991                             }
992                         }
993                         if (vSend.size() > SendBufferSize()) {
994                             if (!pnode->fDisconnect)
995                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
996                             pnode->CloseSocketDisconnect();
997                         }
998                     }
999                 }
1000             }
1001
1002             //
1003             // Inactivity checking
1004             //
1005             if (pnode->vSend.empty())
1006                 pnode->nLastSendEmpty = GetTime();
1007             if (GetTime() - pnode->nTimeConnected > 60)
1008             {
1009                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
1010                 {
1011                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
1012                     pnode->fDisconnect = true;
1013                 }
1014                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
1015                 {
1016                     printf("socket not sending\n");
1017                     pnode->fDisconnect = true;
1018                 }
1019                 else if (GetTime() - pnode->nLastRecv > 90*60)
1020                 {
1021                     printf("socket inactivity timeout\n");
1022                     pnode->fDisconnect = true;
1023                 }
1024             }
1025         }
1026         CRITICAL_BLOCK(cs_vNodes)
1027         {
1028             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1029                 pnode->Release();
1030         }
1031
1032         Sleep(10);
1033     }
1034 }
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 #ifdef USE_UPNP
1045 void ThreadMapPort(void* parg)
1046 {
1047     IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg));
1048     try
1049     {
1050         vnThreadsRunning[5]++;
1051         ThreadMapPort2(parg);
1052         vnThreadsRunning[5]--;
1053     }
1054     catch (std::exception& e) {
1055         vnThreadsRunning[5]--;
1056         PrintException(&e, "ThreadMapPort()");
1057     } catch (...) {
1058         vnThreadsRunning[5]--;
1059         PrintException(NULL, "ThreadMapPort()");
1060     }
1061     printf("ThreadMapPort exiting\n");
1062 }
1063
1064 void ThreadMapPort2(void* parg)
1065 {
1066     printf("ThreadMapPort started\n");
1067
1068     char port[6];
1069     sprintf(port, "%d", GetListenPort());
1070
1071     const char * rootdescurl = 0;
1072     const char * multicastif = 0;
1073     const char * minissdpdpath = 0;
1074     struct UPNPDev * devlist = 0;
1075     char lanaddr[64];
1076
1077     devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
1078
1079     struct UPNPUrls urls;
1080     struct IGDdatas data;
1081     int r;
1082
1083     r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1084     if (r == 1)
1085     {
1086         char intClient[16];
1087         char intPort[6];
1088
1089 #ifndef __WXMSW__
1090         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1091                                 port, port, lanaddr, 0, "TCP", 0);
1092 #else
1093         r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1094                                 port, port, lanaddr, 0, "TCP", 0, "0");
1095 #endif
1096         if(r!=UPNPCOMMAND_SUCCESS)
1097             printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1098                 port, port, lanaddr, r, strupnperror(r));
1099         else
1100             printf("UPnP Port Mapping successful.\n");
1101         loop {
1102             if (fShutdown || !fUseUPnP)
1103             {
1104                 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0);
1105                 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1106                 freeUPNPDevlist(devlist); devlist = 0;
1107                 FreeUPNPUrls(&urls);
1108                 return;
1109             }
1110             Sleep(2000);
1111         }
1112     } else {
1113         printf("No valid UPnP IGDs found\n");
1114         freeUPNPDevlist(devlist); devlist = 0;
1115         if (r != 0)
1116             FreeUPNPUrls(&urls);
1117         loop {
1118             if (fShutdown || !fUseUPnP)
1119                 return;
1120             Sleep(2000);
1121         }
1122     }
1123 }
1124
1125 void MapPort(bool fMapPort)
1126 {
1127     if (fUseUPnP != fMapPort)
1128     {
1129         fUseUPnP = fMapPort;
1130         WriteSetting("fUseUPnP", fUseUPnP);
1131     }
1132     if (fUseUPnP && vnThreadsRunning[5] < 1)
1133     {
1134         if (!CreateThread(ThreadMapPort, NULL))
1135             printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1136     }
1137 }
1138 #endif
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149 static const char *strDNSSeed[] = {
1150     // "seeds.ppcoin.org"
1151 };
1152
1153 void DNSAddressSeed()
1154 {
1155     int found = 0;
1156
1157     if (!fTestNet)
1158     {
1159         printf("Loading addresses from DNS seeds (could take a while)\n");
1160
1161         for (int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1162             vector<CAddress> vaddr;
1163             if (Lookup(strDNSSeed[seed_idx], vaddr, NODE_NETWORK, -1, true))
1164             {
1165                 BOOST_FOREACH (CAddress& addr, vaddr)
1166                 {
1167                     if (addr.GetByte(3) != 127)
1168                     {
1169                         addr.nTime = 0;
1170                         AddAddress(addr);
1171                         found++;
1172                     }
1173                 }
1174             }
1175         }
1176     }
1177
1178     printf("%d addresses found from DNS seeds\n", found);
1179 }
1180
1181
1182
1183 unsigned int pnSeed[] =
1184 {
1185     0xfc01a8c0
1186 };
1187
1188
1189
1190 void ThreadOpenConnections(void* parg)
1191 {
1192     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
1193     try
1194     {
1195         vnThreadsRunning[1]++;
1196         ThreadOpenConnections2(parg);
1197         vnThreadsRunning[1]--;
1198     }
1199     catch (std::exception& e) {
1200         vnThreadsRunning[1]--;
1201         PrintException(&e, "ThreadOpenConnections()");
1202     } catch (...) {
1203         vnThreadsRunning[1]--;
1204         PrintException(NULL, "ThreadOpenConnections()");
1205     }
1206     printf("ThreadOpenConnections exiting\n");
1207 }
1208
1209 void ThreadOpenConnections2(void* parg)
1210 {
1211     printf("ThreadOpenConnections started\n");
1212
1213     // Connect to specific addresses
1214     if (mapArgs.count("-connect"))
1215     {
1216         for (int64 nLoop = 0;; nLoop++)
1217         {
1218             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1219             {
1220                 CAddress addr(strAddr, fAllowDNS);
1221                 if (addr.IsValid())
1222                     OpenNetworkConnection(addr);
1223                 for (int i = 0; i < 10 && i < nLoop; i++)
1224                 {
1225                     Sleep(500);
1226                     if (fShutdown)
1227                         return;
1228                 }
1229             }
1230         }
1231     }
1232
1233     // Connect to manually added nodes first
1234     if (mapArgs.count("-addnode"))
1235     {
1236         BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
1237         {
1238             CAddress addr(strAddr, fAllowDNS);
1239             if (addr.IsValid())
1240             {
1241                 OpenNetworkConnection(addr);
1242                 Sleep(500);
1243                 if (fShutdown)
1244                     return;
1245             }
1246         }
1247     }
1248
1249     // Initiate network connections
1250     int64 nStart = GetTime();
1251     loop
1252     {
1253         // Limit outbound connections
1254         vnThreadsRunning[1]--;
1255         Sleep(500);
1256         loop
1257         {
1258             int nOutbound = 0;
1259             CRITICAL_BLOCK(cs_vNodes)
1260                 BOOST_FOREACH(CNode* pnode, vNodes)
1261                     if (!pnode->fInbound)
1262                         nOutbound++;
1263             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
1264             nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
1265             if (nOutbound < nMaxOutboundConnections)
1266                 break;
1267             Sleep(2000);
1268             if (fShutdown)
1269                 return;
1270         }
1271         vnThreadsRunning[1]++;
1272         if (fShutdown)
1273             return;
1274
1275         CRITICAL_BLOCK(cs_mapAddresses)
1276         {
1277             // Add seed nodes if IRC isn't working
1278             static bool fSeedUsed;
1279             bool fTOR = (fUseProxy && addrProxy.port == htons(9050));
1280             if (mapAddresses.empty() && (GetTime() - nStart > 60 || fTOR) && !fTestNet)
1281             {
1282                 for (int i = 0; i < ARRAYLEN(pnSeed); i++)
1283                 {
1284                     // It'll only connect to one or two seed nodes because once it connects,
1285                     // it'll get a pile of addresses with newer timestamps.
1286                     CAddress addr;
1287                     addr.ip = pnSeed[i];
1288                     addr.nTime = 0;
1289                     AddAddress(addr);
1290                 }
1291                 fSeedUsed = true;
1292             }
1293
1294             if (fSeedUsed && mapAddresses.size() > ARRAYLEN(pnSeed) + 100)
1295             {
1296                 // Disconnect seed nodes
1297                 set<unsigned int> setSeed(pnSeed, pnSeed + ARRAYLEN(pnSeed));
1298                 static int64 nSeedDisconnected;
1299                 if (nSeedDisconnected == 0)
1300                 {
1301                     nSeedDisconnected = GetTime();
1302                     CRITICAL_BLOCK(cs_vNodes)
1303                         BOOST_FOREACH(CNode* pnode, vNodes)
1304                             if (setSeed.count(pnode->addr.ip))
1305                                 pnode->fDisconnect = true;
1306                 }
1307
1308                 // Keep setting timestamps to 0 so they won't reconnect
1309                 if (GetTime() - nSeedDisconnected < 60 * 60)
1310                 {
1311                     BOOST_FOREACH(PAIRTYPE(const vector<unsigned char>, CAddress)& item, mapAddresses)
1312                     {
1313                         if (setSeed.count(item.second.ip) && item.second.nTime != 0)
1314                         {
1315                             item.second.nTime = 0;
1316                             CAddrDB().WriteAddress(item.second);
1317                         }
1318                     }
1319                 }
1320             }
1321         }
1322
1323
1324         //
1325         // Choose an address to connect to based on most recently seen
1326         //
1327         CAddress addrConnect;
1328         int64 nBest = INT64_MIN;
1329
1330         // Only connect to one address per a.b.?.? range.
1331         // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1332         set<unsigned int> setConnected;
1333         CRITICAL_BLOCK(cs_vNodes)
1334             BOOST_FOREACH(CNode* pnode, vNodes)
1335                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
1336
1337         CRITICAL_BLOCK(cs_mapAddresses)
1338         {
1339             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
1340             {
1341                 const CAddress& addr = item.second;
1342                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
1343                     continue;
1344                 int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
1345                 int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
1346
1347                 // Randomize the order in a deterministic way, putting the standard port first
1348                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
1349                 if (addr.port != htons(GetDefaultPort()))
1350                     nRandomizer += 2 * 60 * 60;
1351
1352                 // Last seen  Base retry frequency
1353                 //   <1 hour   10 min
1354                 //    1 hour    1 hour
1355                 //    4 hours   2 hours
1356                 //   24 hours   5 hours
1357                 //   48 hours   7 hours
1358                 //    7 days   13 hours
1359                 //   30 days   27 hours
1360                 //   90 days   46 hours
1361                 //  365 days   93 hours
1362                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
1363
1364                 // Fast reconnect for one hour after last seen
1365                 if (nSinceLastSeen < 60 * 60)
1366                     nDelay = 10 * 60;
1367
1368                 // Limit retry frequency
1369                 if (nSinceLastTry < nDelay)
1370                     continue;
1371
1372                 // If we have IRC, we'll be notified when they first come online,
1373                 // and again every 24 hours by the refresh broadcast.
1374                 if (nGotIRCAddresses > 0 && vNodes.size() >= 2 && nSinceLastSeen > 24 * 60 * 60)
1375                     continue;
1376
1377                 // Only try the old stuff if we don't have enough connections
1378                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
1379                     continue;
1380
1381                 // If multiple addresses are ready, prioritize by time since
1382                 // last seen and time since last tried.
1383                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
1384                 if (nScore > nBest)
1385                 {
1386                     nBest = nScore;
1387                     addrConnect = addr;
1388                 }
1389             }
1390         }
1391
1392         if (addrConnect.IsValid())
1393             OpenNetworkConnection(addrConnect);
1394     }
1395 }
1396
1397 bool OpenNetworkConnection(const CAddress& addrConnect)
1398 {
1399     //
1400     // Initiate outbound network connection
1401     //
1402     if (fShutdown)
1403         return false;
1404     if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
1405         return false;
1406
1407     vnThreadsRunning[1]--;
1408     CNode* pnode = ConnectNode(addrConnect);
1409     vnThreadsRunning[1]++;
1410     if (fShutdown)
1411         return false;
1412     if (!pnode)
1413         return false;
1414     pnode->fNetworkNode = true;
1415
1416     return true;
1417 }
1418
1419
1420
1421
1422
1423
1424
1425
1426 void ThreadMessageHandler(void* parg)
1427 {
1428     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
1429     try
1430     {
1431         vnThreadsRunning[2]++;
1432         ThreadMessageHandler2(parg);
1433         vnThreadsRunning[2]--;
1434     }
1435     catch (std::exception& e) {
1436         vnThreadsRunning[2]--;
1437         PrintException(&e, "ThreadMessageHandler()");
1438     } catch (...) {
1439         vnThreadsRunning[2]--;
1440         PrintException(NULL, "ThreadMessageHandler()");
1441     }
1442     printf("ThreadMessageHandler exiting\n");
1443 }
1444
1445 void ThreadMessageHandler2(void* parg)
1446 {
1447     printf("ThreadMessageHandler started\n");
1448     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1449     while (!fShutdown)
1450     {
1451         vector<CNode*> vNodesCopy;
1452         CRITICAL_BLOCK(cs_vNodes)
1453         {
1454             vNodesCopy = vNodes;
1455             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1456                 pnode->AddRef();
1457         }
1458
1459         // Poll the connected nodes for messages
1460         CNode* pnodeTrickle = NULL;
1461         if (!vNodesCopy.empty())
1462             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1463         BOOST_FOREACH(CNode* pnode, vNodesCopy)
1464         {
1465             // Receive messages
1466             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
1467                 ProcessMessages(pnode);
1468             if (fShutdown)
1469                 return;
1470
1471             // Send messages
1472             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
1473                 SendMessages(pnode, pnode == pnodeTrickle);
1474             if (fShutdown)
1475                 return;
1476         }
1477
1478         CRITICAL_BLOCK(cs_vNodes)
1479         {
1480             BOOST_FOREACH(CNode* pnode, vNodesCopy)
1481                 pnode->Release();
1482         }
1483
1484         // Wait and allow messages to bunch up.
1485         // Reduce vnThreadsRunning so StopNode has permission to exit while
1486         // we're sleeping, but we must always check fShutdown after doing this.
1487         vnThreadsRunning[2]--;
1488         Sleep(100);
1489         if (fRequestShutdown)
1490             Shutdown(NULL);
1491         vnThreadsRunning[2]++;
1492         if (fShutdown)
1493             return;
1494     }
1495 }
1496
1497
1498
1499
1500
1501
1502 bool BindListenPort(string& strError)
1503 {
1504     strError = "";
1505     int nOne = 1;
1506     addrLocalHost.port = htons(GetListenPort());
1507
1508 #ifdef __WXMSW__
1509     // Initialize Windows Sockets
1510     WSADATA wsadata;
1511     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1512     if (ret != NO_ERROR)
1513     {
1514         strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1515         printf("%s\n", strError.c_str());
1516         return false;
1517     }
1518 #endif
1519
1520     // Create socket for listening for incoming connections
1521     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1522     if (hListenSocket == INVALID_SOCKET)
1523     {
1524         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1525         printf("%s\n", strError.c_str());
1526         return false;
1527     }
1528
1529 #ifdef BSD
1530     // Different way of disabling SIGPIPE on BSD
1531     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1532 #endif
1533
1534 #ifndef __WXMSW__
1535     // Allow binding if the port is still in TIME_WAIT state after
1536     // the program was closed and restarted.  Not an issue on windows.
1537     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1538 #endif
1539
1540 #ifdef __WXMSW__
1541     // Set to nonblocking, incoming connections will also inherit this
1542     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1543 #else
1544     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1545 #endif
1546     {
1547         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1548         printf("%s\n", strError.c_str());
1549         return false;
1550     }
1551
1552     // The sockaddr_in structure specifies the address family,
1553     // IP address, and port for the socket that is being bound
1554     struct sockaddr_in sockaddr;
1555     memset(&sockaddr, 0, sizeof(sockaddr));
1556     sockaddr.sin_family = AF_INET;
1557     sockaddr.sin_addr.s_addr = INADDR_ANY; // bind to all IPs on this computer
1558     sockaddr.sin_port = htons(GetListenPort());
1559     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
1560     {
1561         int nErr = WSAGetLastError();
1562         if (nErr == WSAEADDRINUSE)
1563             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
1564         else
1565             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
1566         printf("%s\n", strError.c_str());
1567         return false;
1568     }
1569     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
1570
1571     // Listen for incoming connections
1572     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1573     {
1574         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1575         printf("%s\n", strError.c_str());
1576         return false;
1577     }
1578
1579     return true;
1580 }
1581
1582 void StartNode(void* parg)
1583 {
1584     if (pnodeLocalHost == NULL)
1585         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
1586
1587 #ifdef __WXMSW__
1588     // Get local host ip
1589     char pszHostName[1000] = "";
1590     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1591     {
1592         vector<CAddress> vaddr;
1593         if (Lookup(pszHostName, vaddr, nLocalServices, -1, true))
1594             BOOST_FOREACH (const CAddress &addr, vaddr)
1595                 if (addr.GetByte(3) != 127)
1596                 {
1597                     addrLocalHost = addr;
1598                     break;
1599                 }
1600     }
1601 #else
1602     // Get local host ip
1603     struct ifaddrs* myaddrs;
1604     if (getifaddrs(&myaddrs) == 0)
1605     {
1606         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1607         {
1608             if (ifa->ifa_addr == NULL) continue;
1609             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1610             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1611             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1612             char pszIP[100];
1613             if (ifa->ifa_addr->sa_family == AF_INET)
1614             {
1615                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1616                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
1617                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
1618
1619                 // Take the first IP that isn't loopback 127.x.x.x
1620                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
1621                 if (addr.IsValid() && addr.GetByte(3) != 127)
1622                 {
1623                     addrLocalHost = addr;
1624                     break;
1625                 }
1626             }
1627             else if (ifa->ifa_addr->sa_family == AF_INET6)
1628             {
1629                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1630                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
1631                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
1632             }
1633         }
1634         freeifaddrs(myaddrs);
1635     }
1636 #endif
1637     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1638
1639     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
1640     {
1641         // Proxies can't take incoming connections
1642         addrLocalHost.ip = CAddress("0.0.0.0").ip;
1643         printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
1644     }
1645     else
1646     {
1647         CreateThread(ThreadGetMyExternalIP, NULL);
1648     }
1649
1650     //
1651     // Start threads
1652     //
1653
1654     // Map ports with UPnP
1655     if (fHaveUPnP)
1656         MapPort(fUseUPnP);
1657
1658     // Get addresses from IRC and advertise ours
1659     if (!CreateThread(ThreadIRCSeed, NULL))
1660         printf("Error: CreateThread(ThreadIRCSeed) failed\n");
1661
1662     // Send and receive from sockets, accept connections
1663     pthread_t hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
1664
1665     // Initiate outbound connections
1666     if (!CreateThread(ThreadOpenConnections, NULL))
1667         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
1668
1669     // Process messages
1670     if (!CreateThread(ThreadMessageHandler, NULL))
1671         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
1672
1673     // Generate coins in the background
1674     GenerateBitcoins(fGenerateBitcoins, pwalletMain);
1675 }
1676
1677 bool StopNode()
1678 {
1679     printf("StopNode()\n");
1680     fShutdown = true;
1681     nTransactionsUpdated++;
1682     int64 nStart = GetTime();
1683     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0
1684 #ifdef USE_UPNP
1685         || vnThreadsRunning[5] > 0
1686 #endif
1687     )
1688     {
1689         if (GetTime() - nStart > 20)
1690             break;
1691         Sleep(20);
1692     }
1693     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
1694     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
1695     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
1696     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
1697     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
1698     if (fHaveUPnP && vnThreadsRunning[5] > 0) printf("ThreadMapPort still running\n");
1699     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
1700         Sleep(20);
1701     Sleep(50);
1702
1703     return true;
1704 }
1705
1706 class CNetCleanup
1707 {
1708 public:
1709     CNetCleanup()
1710     {
1711     }
1712     ~CNetCleanup()
1713     {
1714         // Close sockets
1715         BOOST_FOREACH(CNode* pnode, vNodes)
1716             if (pnode->hSocket != INVALID_SOCKET)
1717                 closesocket(pnode->hSocket);
1718         if (hListenSocket != INVALID_SOCKET)
1719             if (closesocket(hListenSocket) == SOCKET_ERROR)
1720                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1721
1722 #ifdef __WXMSW__
1723         // Shutdown Windows Sockets
1724         WSACleanup();
1725 #endif
1726     }
1727 }
1728 instance_of_cnetcleanup;