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