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