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