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.
11 #include "ui_interface.h"
20 #include <miniupnpc/miniwget.h>
21 #include <miniupnpc/miniupnpc.h>
22 #include <miniupnpc/upnpcommands.h>
23 #include <miniupnpc/upnperrors.h>
27 using namespace boost;
29 static const int MAX_OUTBOUND_CONNECTIONS = 16;
31 void ThreadMessageHandler2(void* parg);
32 void ThreadSocketHandler2(void* parg);
33 void ThreadOpenConnections2(void* parg);
34 void ThreadOpenAddedConnections2(void* parg);
36 void ThreadMapPort2(void* parg);
38 void ThreadDNSAddressSeed2(void* parg);
40 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
41 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
43 #ifndef PROTECTION_LEVEL_UNRESTRICTED
44 #define PROTECTION_LEVEL_UNRESTRICTED 10
46 #ifndef IPV6_PROTECTION_LEVEL
47 #define IPV6_PROTECTION_LEVEL 23
51 struct LocalServiceInfo {
57 // Global state variables
60 bool fDiscover = true;
61 bool fUseUPnP = false;
62 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
63 static CCriticalSection cs_mapLocalHost;
64 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
65 static bool vfReachable[NET_MAX] = {};
66 static bool vfLimited[NET_MAX] = {};
67 static CNode* pnodeLocalHost = NULL;
68 static CNode* pnodeSync = NULL;
69 CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
70 uint64_t nLocalHostNonce = 0;
71 boost::array<int, THREAD_MAX> vnThreadsRunning;
72 static std::vector<SOCKET> vhListenSocket;
75 vector<CNode*> vNodes;
76 CCriticalSection cs_vNodes;
77 map<CInv, CDataStream> mapRelay;
78 deque<pair<int64_t, CInv> > vRelayExpiration;
79 CCriticalSection cs_mapRelay;
80 map<CInv, int64_t> mapAlreadyAskedFor;
82 static deque<string> vOneShots;
83 CCriticalSection cs_vOneShots;
85 set<CNetAddr> setservAddNodeAddresses;
86 CCriticalSection cs_setservAddNodeAddresses;
88 vector<std::string> vAddedNodes;
89 CCriticalSection cs_vAddedNodes;
91 static CSemaphore *semOutbound = NULL;
93 void AddOneShot(string strDest)
96 vOneShots.push_back(strDest);
99 unsigned short GetListenPort()
101 return (unsigned short)(GetArg("-port", GetDefaultPort()));
104 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
106 // Filter out duplicate requests
107 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
109 pindexLastGetBlocksBegin = pindexBegin;
110 hashLastGetBlocksEnd = hashEnd;
112 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
115 // find 'best' local address for a particular peer
116 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
122 int nBestReachability = -1;
124 LOCK(cs_mapLocalHost);
125 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
127 int nScore = (*it).second.nScore;
128 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
129 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
131 addr = CService((*it).first, (*it).second.nPort);
132 nBestReachability = nReachability;
137 return nBestScore >= 0;
140 // get best local address for a particular peer as a CAddress
141 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
143 CAddress ret(CService("0.0.0.0", nPortZero), 0);
145 if (GetLocal(addr, paddrPeer))
147 ret = CAddress(addr);
148 ret.nServices = nLocalServices;
149 ret.nTime = GetAdjustedTime();
154 bool RecvLine(SOCKET hSocket, string& strLine)
160 int nBytes = recv(hSocket, &c, 1, 0);
168 if (strLine.size() >= 9000)
171 else if (nBytes <= 0)
177 int nErr = WSAGetLastError();
178 if (nErr == WSAEMSGSIZE)
180 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
186 if (!strLine.empty())
191 printf("socket closed\n");
197 int nErr = WSAGetLastError();
198 printf("recv failed: %d\n", nErr);
205 // used when scores of local addresses may have changed
206 // pushes better local address to peers
207 void static AdvertizeLocal()
210 BOOST_FOREACH(CNode* pnode, vNodes)
212 if (pnode->fSuccessfullyConnected)
214 CAddress addrLocal = GetLocalAddress(&pnode->addr);
215 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
217 pnode->PushAddress(addrLocal);
218 pnode->addrLocal = addrLocal;
224 void SetReachable(enum Network net, bool fFlag)
226 LOCK(cs_mapLocalHost);
227 vfReachable[net] = fFlag;
228 if (net == NET_IPV6 && fFlag)
229 vfReachable[NET_IPV4] = true;
232 // learn a new local address
233 bool AddLocal(const CService& addr, int nScore)
235 if (!addr.IsRoutable())
238 if (!fDiscover && nScore < LOCAL_MANUAL)
244 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
247 LOCK(cs_mapLocalHost);
248 bool fAlready = mapLocalHost.count(addr) > 0;
249 LocalServiceInfo &info = mapLocalHost[addr];
250 if (!fAlready || nScore >= info.nScore) {
251 info.nScore = nScore + (fAlready ? 1 : 0);
252 info.nPort = addr.GetPort();
254 SetReachable(addr.GetNetwork());
262 bool AddLocal(const CNetAddr &addr, int nScore)
264 return AddLocal(CService(addr, GetListenPort()), nScore);
267 /** Make a particular network entirely off-limits (no automatic connects to it) */
268 void SetLimited(enum Network net, bool fLimited)
270 if (net == NET_UNROUTABLE)
272 LOCK(cs_mapLocalHost);
273 vfLimited[net] = fLimited;
276 bool IsLimited(enum Network net)
278 LOCK(cs_mapLocalHost);
279 return vfLimited[net];
282 bool IsLimited(const CNetAddr &addr)
284 return IsLimited(addr.GetNetwork());
287 /** vote for a local address */
288 bool SeenLocal(const CService& addr)
291 LOCK(cs_mapLocalHost);
292 if (mapLocalHost.count(addr) == 0)
294 mapLocalHost[addr].nScore++;
302 /** check whether a given address is potentially local */
303 bool IsLocal(const CService& addr)
305 LOCK(cs_mapLocalHost);
306 return mapLocalHost.count(addr) > 0;
309 /** check whether a given address is in a network we can probably connect to */
310 bool IsReachable(const CNetAddr& addr)
312 LOCK(cs_mapLocalHost);
313 enum Network net = addr.GetNetwork();
314 return vfReachable[net] && !vfLimited[net];
317 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
319 // We now get our external IP from the IRC server first and only use this as a backup
320 bool GetMyExternalIP(CNetAddr& ipRet)
322 struct sockaddr_in mapped;
323 uint64_t rnd = std::numeric_limits<uint64_t>::max();
325 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
327 ipRet = CNetAddr(mapped.sin_addr);
328 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
334 void ThreadGetMyExternalIP(void* parg)
336 // Make this thread recognisable as the external IP detection thread
337 RenameThread("novacoin-ext-ip");
339 CNetAddr addrLocalHost;
340 if (GetMyExternalIP(addrLocalHost))
342 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
343 AddLocal(addrLocalHost, LOCAL_HTTP);
351 void AddressCurrentlyConnected(const CService& addr)
353 addrman.Connected(addr);
359 uint64_t CNode::nTotalBytesRecv = 0;
360 uint64_t CNode::nTotalBytesSent = 0;
361 CCriticalSection CNode::cs_totalBytesRecv;
362 CCriticalSection CNode::cs_totalBytesSent;
364 CNode* FindNode(const CNetAddr& ip)
367 BOOST_FOREACH(CNode* pnode, vNodes)
368 if ((CNetAddr)pnode->addr == ip)
373 CNode* FindNode(std::string addrName)
376 BOOST_FOREACH(CNode* pnode, vNodes)
377 if (pnode->addrName == addrName)
382 CNode* FindNode(const CService& addr)
385 BOOST_FOREACH(CNode* pnode, vNodes)
386 if ((CService)pnode->addr == addr)
391 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
393 if (pszDest == NULL) {
394 if (IsLocal(addrConnect))
397 // Look for an existing connection
398 CNode* pnode = FindNode((CService)addrConnect);
402 pnode->AddRef(nTimeout);
411 printf("trying connection %s lastseen=%.1fhrs\n",
412 pszDest ? pszDest : addrConnect.ToString().c_str(),
413 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
417 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
419 addrman.Attempt(addrConnect);
422 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
424 // Set to non-blocking
427 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
428 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
430 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
431 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
435 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
437 pnode->AddRef(nTimeout);
443 vNodes.push_back(pnode);
446 pnode->nTimeConnected = GetTime();
455 void CNode::CloseSocketDisconnect()
458 if (hSocket != INVALID_SOCKET)
460 printf("disconnecting node %s\n", addrName.c_str());
461 closesocket(hSocket);
462 hSocket = INVALID_SOCKET;
466 // in case this fails, we'll empty the recv buffer when the CNode is deleted
467 TRY_LOCK(cs_vRecv, lockRecv);
471 // if this was the sync node, we'll need a new one
472 if (this == pnodeSync)
476 void CNode::Cleanup()
481 void CNode::PushVersion()
483 int64_t nTime = GetAdjustedTime();
484 CAddress addrYou, addrMe;
486 bool fHidden = false;
488 if (mapArgs.count("-torname")) {
489 // Our hidden service address
490 CService addrTorName(mapArgs["-torname"], GetListenPort());
492 if (addrTorName.IsValid()) {
494 addrMe = CAddress(addrTorName);
501 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
502 addrMe = GetLocalAddress(&addr);
505 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
506 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());
507 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
508 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
515 std::map<CNetAddr, int64_t> CNode::setBanned;
516 CCriticalSection CNode::cs_setBanned;
518 void CNode::ClearBanned()
523 bool CNode::IsBanned(CNetAddr ip)
525 bool fResult = false;
528 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
529 if (i != setBanned.end())
531 int64_t t = (*i).second;
539 bool CNode::Misbehaving(int howmuch)
543 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
547 nMisbehavior += howmuch;
548 if (nMisbehavior >= GetArgInt("-banscore", 100))
550 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
551 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
554 if (setBanned[addr] < banTime)
555 setBanned[addr] = banTime;
557 CloseSocketDisconnect();
560 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
565 #define X(name) stats.name = name
566 void CNode::copyStats(CNodeStats &stats)
581 stats.fSyncNode = (this == pnodeSync);
594 void ThreadSocketHandler(void* parg)
596 // Make this thread recognisable as the networking thread
597 RenameThread("novacoin-net");
601 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
602 ThreadSocketHandler2(parg);
603 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
605 catch (std::exception& e) {
606 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
607 PrintException(&e, "ThreadSocketHandler()");
609 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
610 throw; // support pthread_cancel()
612 printf("ThreadSocketHandler exited\n");
615 static list<CNode*> vNodesDisconnected;
617 void ThreadSocketHandler2(void* parg)
619 printf("ThreadSocketHandler started\n");
620 unsigned int nPrevNodeCount = 0;
628 // Disconnect unused nodes
629 vector<CNode*> vNodesCopy = vNodes;
630 BOOST_FOREACH(CNode* pnode, vNodesCopy)
632 if (pnode->fDisconnect ||
633 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
635 // remove from vNodes
636 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
638 // release outbound grant (if any)
639 pnode->grantOutbound.Release();
641 // close socket and cleanup
642 pnode->CloseSocketDisconnect();
645 // hold in disconnected pool until all refs are released
646 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
647 if (pnode->fNetworkNode || pnode->fInbound)
649 vNodesDisconnected.push_back(pnode);
653 // Delete disconnected nodes
654 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
655 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
657 // wait until threads are done using it
658 if (pnode->GetRefCount() <= 0)
660 bool fDelete = false;
662 TRY_LOCK(pnode->cs_vSend, lockSend);
665 TRY_LOCK(pnode->cs_vRecv, lockRecv);
668 TRY_LOCK(pnode->cs_mapRequests, lockReq);
671 TRY_LOCK(pnode->cs_inventory, lockInv);
680 vNodesDisconnected.remove(pnode);
686 if (vNodes.size() != nPrevNodeCount)
688 nPrevNodeCount = vNodes.size();
689 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
694 // Find which sockets have data to receive
696 struct timeval timeout;
698 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
705 FD_ZERO(&fdsetError);
706 SOCKET hSocketMax = 0;
707 bool have_fds = false;
709 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
710 FD_SET(hListenSocket, &fdsetRecv);
711 hSocketMax = max(hSocketMax, hListenSocket);
716 BOOST_FOREACH(CNode* pnode, vNodes)
718 if (pnode->hSocket == INVALID_SOCKET)
720 FD_SET(pnode->hSocket, &fdsetRecv);
721 FD_SET(pnode->hSocket, &fdsetError);
722 hSocketMax = max(hSocketMax, pnode->hSocket);
725 TRY_LOCK(pnode->cs_vSend, lockSend);
726 if (lockSend && !pnode->vSend.empty())
727 FD_SET(pnode->hSocket, &fdsetSend);
732 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
733 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
734 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
735 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
738 if (nSelect == SOCKET_ERROR)
742 int nErr = WSAGetLastError();
743 printf("socket select error %d\n", nErr);
744 for (unsigned int i = 0; i <= hSocketMax; i++)
745 FD_SET(i, &fdsetRecv);
748 FD_ZERO(&fdsetError);
749 Sleep(timeout.tv_usec/1000);
754 // Accept new connections
756 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
757 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
760 struct sockaddr_storage sockaddr;
762 struct sockaddr sockaddr;
764 socklen_t len = sizeof(sockaddr);
765 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
769 if (hSocket != INVALID_SOCKET)
770 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
771 printf("Warning: Unknown socket family\n");
775 BOOST_FOREACH(CNode* pnode, vNodes)
780 if (hSocket == INVALID_SOCKET)
782 int nErr = WSAGetLastError();
783 if (nErr != WSAEWOULDBLOCK)
784 printf("socket error accept failed: %d\n", nErr);
786 else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
789 LOCK(cs_setservAddNodeAddresses);
790 if (!setservAddNodeAddresses.count(addr))
791 closesocket(hSocket);
794 else if (CNode::IsBanned(addr))
796 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
797 closesocket(hSocket);
801 printf("accepted connection %s\n", addr.ToString().c_str());
802 CNode* pnode = new CNode(hSocket, addr, "", true);
806 vNodes.push_back(pnode);
813 // Service each socket
815 vector<CNode*> vNodesCopy;
819 BOOST_FOREACH(CNode* pnode, vNodesCopy)
822 BOOST_FOREACH(CNode* pnode, vNodesCopy)
830 if (pnode->hSocket == INVALID_SOCKET)
832 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
834 TRY_LOCK(pnode->cs_vRecv, lockRecv);
837 CDataStream& vRecv = pnode->vRecv;
838 uint64_t nPos = vRecv.size();
840 if (nPos > ReceiveBufferSize()) {
841 if (!pnode->fDisconnect)
842 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
843 pnode->CloseSocketDisconnect();
846 // typical socket buffer is 8K-64K
847 char pchBuf[0x10000];
848 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
851 vRecv.resize(nPos + nBytes);
852 memcpy(&vRecv[nPos], pchBuf, nBytes);
853 pnode->nLastRecv = GetTime();
854 pnode->nRecvBytes += nBytes;
855 pnode->RecordBytesRecv(nBytes);
857 else if (nBytes == 0)
859 // socket closed gracefully
860 if (!pnode->fDisconnect)
861 printf("socket closed\n");
862 pnode->CloseSocketDisconnect();
867 int nErr = WSAGetLastError();
868 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
870 if (!pnode->fDisconnect)
871 printf("socket recv error %d\n", nErr);
872 pnode->CloseSocketDisconnect();
882 if (pnode->hSocket == INVALID_SOCKET)
884 if (FD_ISSET(pnode->hSocket, &fdsetSend))
886 TRY_LOCK(pnode->cs_vSend, lockSend);
889 CDataStream& vSend = pnode->vSend;
892 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
895 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
896 pnode->nLastSend = GetTime();
897 pnode->nSendBytes += nBytes;
898 pnode->RecordBytesSent(nBytes);
903 int nErr = WSAGetLastError();
904 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
906 printf("socket send error %d\n", nErr);
907 pnode->CloseSocketDisconnect();
915 // Inactivity checking
917 if (pnode->vSend.empty())
918 pnode->nLastSendEmpty = GetTime();
919 if (GetTime() - pnode->nTimeConnected > 60)
921 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
923 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
924 pnode->fDisconnect = true;
926 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
928 printf("socket not sending\n");
929 pnode->fDisconnect = true;
931 else if (GetTime() - pnode->nLastRecv > 90*60)
933 printf("socket inactivity timeout\n");
934 pnode->fDisconnect = true;
940 BOOST_FOREACH(CNode* pnode, vNodesCopy)
957 void ThreadMapPort(void* parg)
959 // Make this thread recognisable as the UPnP thread
960 RenameThread("novacoin-UPnP");
964 vnThreadsRunning[THREAD_UPNP]++;
965 ThreadMapPort2(parg);
966 vnThreadsRunning[THREAD_UPNP]--;
968 catch (std::exception& e) {
969 vnThreadsRunning[THREAD_UPNP]--;
970 PrintException(&e, "ThreadMapPort()");
972 vnThreadsRunning[THREAD_UPNP]--;
973 PrintException(NULL, "ThreadMapPort()");
975 printf("ThreadMapPort exited\n");
978 void ThreadMapPort2(void* parg)
980 printf("ThreadMapPort started\n");
982 std::string port = strprintf("%u", GetListenPort());
983 const char * multicastif = 0;
984 const char * minissdpdpath = 0;
985 struct UPNPDev * devlist = 0;
988 #ifndef UPNPDISCOVER_SUCCESS
990 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
994 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
997 struct UPNPUrls urls;
998 struct IGDdatas data;
1001 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1005 char externalIPAddress[40];
1006 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
1007 if(r != UPNPCOMMAND_SUCCESS)
1008 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
1011 if(externalIPAddress[0])
1013 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1014 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1017 printf("UPnP: GetExternalIPAddress failed.\n");
1021 string strDesc = "NovaCoin " + FormatFullVersion();
1022 #ifndef UPNPDISCOVER_SUCCESS
1024 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1025 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1028 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1029 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1032 if(r!=UPNPCOMMAND_SUCCESS)
1033 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1034 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1036 printf("UPnP Port Mapping successful.\n");
1040 if (fShutdown || !fUseUPnP)
1042 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1043 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1044 freeUPNPDevlist(devlist); devlist = 0;
1045 FreeUPNPUrls(&urls);
1048 if (i % 600 == 0) // Refresh every 20 minutes
1050 #ifndef UPNPDISCOVER_SUCCESS
1052 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1053 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1056 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1057 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1060 if(r!=UPNPCOMMAND_SUCCESS)
1061 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1062 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1064 printf("UPnP Port Mapping successful.\n");;
1070 printf("No valid UPnP IGDs found\n");
1071 freeUPNPDevlist(devlist); devlist = 0;
1073 FreeUPNPUrls(&urls);
1076 if (fShutdown || !fUseUPnP)
1085 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1087 if (!NewThread(ThreadMapPort, NULL))
1088 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1094 // Intentionally left blank.
1107 // Each pair gives a source name and a seed name.
1108 // The first name is used as information source for addrman.
1109 // The second name should resolve to a list of seed addresses.
1110 static const char *strDNSSeed[][2] = {
1111 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1112 {"novacoin.ru", "dnsseed.novacoin.ru"},
1113 {"novacoin.ru", "testseed.novacoin.ru"},
1114 {"novaco.in", "dnsseed.novaco.in"},
1117 void ThreadDNSAddressSeed(void* parg)
1119 // Make this thread recognisable as the DNS seeding thread
1120 RenameThread("novacoin-dnsseed");
1124 vnThreadsRunning[THREAD_DNSSEED]++;
1125 ThreadDNSAddressSeed2(parg);
1126 vnThreadsRunning[THREAD_DNSSEED]--;
1128 catch (std::exception& e) {
1129 vnThreadsRunning[THREAD_DNSSEED]--;
1130 PrintException(&e, "ThreadDNSAddressSeed()");
1132 vnThreadsRunning[THREAD_DNSSEED]--;
1133 throw; // support pthread_cancel()
1135 printf("ThreadDNSAddressSeed exited\n");
1138 void ThreadDNSAddressSeed2(void* parg)
1140 printf("ThreadDNSAddressSeed started\n");
1145 printf("Loading addresses from DNS seeds (could take a while)\n");
1147 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1148 if (HaveNameProxy()) {
1149 AddOneShot(strDNSSeed[seed_idx][1]);
1151 vector<CNetAddr> vaddr;
1152 vector<CAddress> vAdd;
1153 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1155 BOOST_FOREACH(CNetAddr& ip, vaddr)
1157 int nOneDay = 24*3600;
1158 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1159 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1160 vAdd.push_back(addr);
1164 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1169 printf("%d addresses found from DNS seeds\n", found);
1185 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1186 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1187 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1188 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1189 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1190 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1191 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1192 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1193 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1194 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1195 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1196 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1197 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1198 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1199 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1200 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1204 const char* pchTorSeed[] =
1206 "seedp4knqnoei57u.onion",
1207 "seedr3hhlepyi7fd.onion",
1208 "seed3uuomkclbiz4.onion",
1209 "seedeh7qck3ouff5.onion",
1210 "5rg3vq4jagckeckf.onion",
1211 "seedt3sraf53ajiy.onion",
1212 "seedg4qyccsg42oq.onion",
1213 "novaqrtoywpg7jly.onion",
1214 "seed3d5wolqbgrcb.onion",
1215 "seed24u5dwph3qw4.onion",
1216 "mj26ulzbs2oskgym.onion",
1217 "eqon4usunavt76m7.onion",
1218 "seedd3aldwpslzl3.onion"
1221 void DumpAddresses()
1223 int64_t nStart = GetTimeMillis();
1228 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1229 addrman.size(), GetTimeMillis() - nStart);
1232 void ThreadDumpAddress2(void* parg)
1234 printf("ThreadDumpAddress started\n");
1236 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1240 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1242 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1244 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1247 void ThreadDumpAddress(void* parg)
1249 // Make this thread recognisable as the address dumping thread
1250 RenameThread("novacoin-adrdump");
1254 ThreadDumpAddress2(parg);
1256 catch (std::exception& e) {
1257 PrintException(&e, "ThreadDumpAddress()");
1259 printf("ThreadDumpAddress exited\n");
1262 void ThreadOpenConnections(void* parg)
1264 // Make this thread recognisable as the connection opening thread
1265 RenameThread("novacoin-opencon");
1269 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1270 ThreadOpenConnections2(parg);
1271 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1273 catch (std::exception& e) {
1274 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1275 PrintException(&e, "ThreadOpenConnections()");
1277 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1278 PrintException(NULL, "ThreadOpenConnections()");
1280 printf("ThreadOpenConnections exited\n");
1283 void static ProcessOneShot()
1288 if (vOneShots.empty())
1290 strDest = vOneShots.front();
1291 vOneShots.pop_front();
1294 CSemaphoreGrant grant(*semOutbound, true);
1296 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1297 AddOneShot(strDest);
1301 void ThreadOpenConnections2(void* parg)
1303 printf("ThreadOpenConnections started\n");
1305 // Connect to specific addresses
1306 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1308 for (int64_t nLoop = 0;; nLoop++)
1311 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1314 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1315 for (int i = 0; i < 10 && i < nLoop; i++)
1326 // Initiate network connections
1327 int64_t nStart = GetTime();
1332 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1334 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1339 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1340 CSemaphoreGrant grant(*semOutbound);
1341 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1345 // Add seed nodes if IRC isn't working
1346 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1348 std::vector<CAddress> vAdd;
1349 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1351 // It'll only connect to one or two seed nodes because once it connects,
1352 // it'll get a pile of addresses with newer timestamps.
1353 // Seed nodes are given a random 'last seen time' of between one and two
1355 const int64_t nOneWeek = 7*24*60*60;
1357 memcpy(&ip, &pnSeed[i], sizeof(ip));
1358 CAddress addr(CService(ip, GetDefaultPort()));
1359 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1360 vAdd.push_back(addr);
1362 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1365 // Add Tor nodes if we have connection with onion router
1366 if (mapArgs.count("-tor"))
1368 std::vector<CAddress> vAdd;
1369 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1371 const int64_t nOneWeek = 7*24*60*60;
1372 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1373 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1374 vAdd.push_back(addr);
1376 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1380 // Choose an address to connect to based on most recently seen
1382 CAddress addrConnect;
1384 // Only connect out to one peer per network group (/16 for IPv4).
1385 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1387 set<vector<unsigned char> > setConnected;
1390 BOOST_FOREACH(CNode* pnode, vNodes) {
1391 if (!pnode->fInbound) {
1392 setConnected.insert(pnode->addr.GetGroup());
1398 int64_t nANow = GetAdjustedTime();
1403 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1404 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1406 // if we selected an invalid address, restart
1407 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1410 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1411 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1412 // already-connected network ranges, ...) before trying new addrman addresses.
1417 if (IsLimited(addr))
1420 // only consider very recently tried nodes after 30 failed attempts
1421 if (nANow - addr.nLastTry < 600 && nTries < 30)
1424 // do not allow non-default ports, unless after 50 invalid addresses selected already
1425 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1432 if (addrConnect.IsValid())
1433 OpenNetworkConnection(addrConnect, &grant);
1437 void ThreadOpenAddedConnections(void* parg)
1439 // Make this thread recognisable as the connection opening thread
1440 RenameThread("novacoin-opencon");
1444 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1445 ThreadOpenAddedConnections2(parg);
1446 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1448 catch (std::exception& e) {
1449 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1450 PrintException(&e, "ThreadOpenAddedConnections()");
1452 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1453 PrintException(NULL, "ThreadOpenAddedConnections()");
1455 printf("ThreadOpenAddedConnections exited\n");
1458 void ThreadOpenAddedConnections2(void* parg)
1460 printf("ThreadOpenAddedConnections started\n");
1463 LOCK(cs_vAddedNodes);
1464 vAddedNodes = mapMultiArgs["-addnode"];
1467 if (HaveNameProxy()) {
1469 list<string> lAddresses(0);
1471 LOCK(cs_vAddedNodes);
1472 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1473 lAddresses.push_back(strAddNode);
1475 BOOST_FOREACH(string& strAddNode, lAddresses) {
1477 CSemaphoreGrant grant(*semOutbound);
1478 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1481 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1482 Sleep(120000); // Retry every 2 minutes
1483 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1488 for (uint32_t i = 0; true; i++)
1490 list<string> lAddresses(0);
1492 LOCK(cs_vAddedNodes);
1493 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1494 lAddresses.push_back(strAddNode);
1497 list<vector<CService> > lservAddressesToAdd(0);
1498 BOOST_FOREACH(string& strAddNode, lAddresses)
1500 vector<CService> vservNode(0);
1501 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1503 lservAddressesToAdd.push_back(vservNode);
1505 LOCK(cs_setservAddNodeAddresses);
1506 BOOST_FOREACH(CService& serv, vservNode)
1507 setservAddNodeAddresses.insert(serv);
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)
1515 BOOST_FOREACH(CNode* pnode, vNodes)
1516 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1518 BOOST_FOREACH(CService& addrNode, *(it))
1519 if (pnode->addr == addrNode)
1521 it = lservAddressesToAdd.erase(it);
1522 if(it != lservAddressesToAdd.begin())
1526 if (it == lservAddressesToAdd.end())
1530 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1532 if (vserv.size() == 0)
1534 CSemaphoreGrant grant(*semOutbound);
1535 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1542 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1543 Sleep(120000); // Retry every 2 minutes
1544 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1550 // if successful, this moves the passed grant to the constructed node
1551 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1554 // Initiate outbound network connection
1559 if (IsLocal(addrConnect) ||
1560 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1561 FindNode(addrConnect.ToStringIPPort().c_str()))
1563 if (strDest && FindNode(strDest))
1566 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1567 CNode* pnode = ConnectNode(addrConnect, strDest);
1568 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1574 grantOutbound->MoveTo(pnode->grantOutbound);
1575 pnode->fNetworkNode = true;
1577 pnode->fOneShot = true;
1582 // for now, use a very simple selection metric: the node from which we received
1584 static int64_t NodeSyncScore(const CNode *pnode) {
1585 return pnode->nLastRecv;
1588 void static StartSync(const vector<CNode*> &vNodes) {
1589 CNode *pnodeNewSync = NULL;
1590 int64_t nBestScore = 0;
1592 // Iterate over all nodes
1593 BOOST_FOREACH(CNode* pnode, vNodes) {
1594 // check preconditions for allowing a sync
1595 if (!pnode->fClient && !pnode->fOneShot &&
1596 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1597 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1598 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1599 // if ok, compare node's score with the best so far
1600 int64_t nScore = NodeSyncScore(pnode);
1601 if (pnodeNewSync == NULL || nScore > nBestScore) {
1602 pnodeNewSync = pnode;
1603 nBestScore = nScore;
1607 // if a new sync candidate was found, start sync!
1609 pnodeNewSync->fStartSync = true;
1610 pnodeSync = pnodeNewSync;
1614 void ThreadMessageHandler(void* parg)
1616 // Make this thread recognisable as the message handling thread
1617 RenameThread("novacoin-msghand");
1621 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1622 ThreadMessageHandler2(parg);
1623 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1625 catch (std::exception& e) {
1626 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1627 PrintException(&e, "ThreadMessageHandler()");
1629 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1630 PrintException(NULL, "ThreadMessageHandler()");
1632 printf("ThreadMessageHandler exited\n");
1635 void ThreadMessageHandler2(void* parg)
1637 printf("ThreadMessageHandler started\n");
1638 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1641 bool fHaveSyncNode = false;
1642 vector<CNode*> vNodesCopy;
1645 vNodesCopy = vNodes;
1646 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1648 if (pnode == pnodeSync)
1649 fHaveSyncNode = true;
1654 StartSync(vNodesCopy);
1656 // Poll the connected nodes for messages
1657 CNode* pnodeTrickle = NULL;
1658 if (!vNodesCopy.empty())
1659 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1660 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1664 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1666 ProcessMessages(pnode);
1673 TRY_LOCK(pnode->cs_vSend, lockSend);
1675 SendMessages(pnode, pnode == pnodeTrickle);
1683 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1687 // Wait and allow messages to bunch up.
1688 // Reduce vnThreadsRunning so StopNode has permission to exit while
1689 // we're sleeping, but we must always check fShutdown after doing this.
1690 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1692 if (fRequestShutdown)
1694 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1705 bool BindListenPort(const CService &addrBind, string& strError)
1711 // Initialize Windows Sockets
1713 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1714 if (ret != NO_ERROR)
1716 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1717 printf("%s\n", strError.c_str());
1722 // Create socket for listening for incoming connections
1724 struct sockaddr_storage sockaddr;
1726 struct sockaddr sockaddr;
1728 socklen_t len = sizeof(sockaddr);
1729 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1731 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1732 printf("%s\n", strError.c_str());
1736 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1737 if (hListenSocket == INVALID_SOCKET)
1739 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1740 printf("%s\n", strError.c_str());
1746 // Different way of disabling SIGPIPE on BSD
1747 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1749 // Allow binding if the port is still in TIME_WAIT state after
1750 // the program was closed and restarted. Not an issue on windows!
1751 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1755 // Set to non-blocking, incoming connections will also inherit this
1756 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1758 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1761 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1762 printf("%s\n", strError.c_str());
1767 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1768 // and enable it by default or not. Try to enable it, if possible.
1769 if (addrBind.IsIPv6()) {
1772 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1774 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1778 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1779 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1784 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1786 int nErr = WSAGetLastError();
1787 if (nErr == WSAEADDRINUSE)
1788 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1790 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1791 printf("%s\n", strError.c_str());
1792 closesocket(hListenSocket);
1795 printf("Bound to %s\n", addrBind.ToString().c_str());
1797 // Listen for incoming connections
1798 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1800 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1801 printf("%s\n", strError.c_str());
1802 closesocket(hListenSocket);
1806 vhListenSocket.push_back(hListenSocket);
1808 if (addrBind.IsRoutable() && fDiscover)
1809 AddLocal(addrBind, LOCAL_BIND);
1814 void static Discover()
1820 // Get local host IP
1821 char pszHostName[1000] = "";
1822 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1824 vector<CNetAddr> vaddr;
1825 if (LookupHost(pszHostName, vaddr))
1827 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1829 AddLocal(addr, LOCAL_IF);
1834 // Get local host ip
1835 struct ifaddrs* myaddrs;
1836 if (getifaddrs(&myaddrs) == 0)
1838 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1840 if (ifa->ifa_addr == NULL) continue;
1841 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1842 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1843 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1844 if (ifa->ifa_addr->sa_family == AF_INET)
1846 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1847 CNetAddr addr(s4->sin_addr);
1848 if (AddLocal(addr, LOCAL_IF))
1849 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1852 else if (ifa->ifa_addr->sa_family == AF_INET6)
1854 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1855 CNetAddr addr(s6->sin6_addr);
1856 if (AddLocal(addr, LOCAL_IF))
1857 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1861 freeifaddrs(myaddrs);
1865 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1866 if (!IsLimited(NET_IPV4))
1867 NewThread(ThreadGetMyExternalIP, NULL);
1870 void StartNode(void* parg)
1872 // Make this thread recognisable as the startup thread
1873 RenameThread("novacoin-start");
1875 if (semOutbound == NULL) {
1876 // initialize semaphore
1877 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1878 semOutbound = new CSemaphore(nMaxOutbound);
1881 if (pnodeLocalHost == NULL)
1882 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1890 if (!GetBoolArg("-dnsseed", true))
1891 printf("DNS seeding disabled\n");
1893 if (!NewThread(ThreadDNSAddressSeed, NULL))
1894 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1896 // Map ports with UPnP
1898 printf("UPNP port mapping is disabled\n");
1902 // Get addresses from IRC and advertise ours
1903 if (!GetBoolArg("-irc", true))
1904 printf("IRC seeding disabled\n");
1906 if (!NewThread(ThreadIRCSeed, NULL))
1907 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1909 // Send and receive from sockets, accept connections
1910 if (!NewThread(ThreadSocketHandler, NULL))
1911 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1913 // Initiate outbound connections from -addnode
1914 if (!NewThread(ThreadOpenAddedConnections, NULL))
1915 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1917 // Initiate outbound connections
1918 if (!NewThread(ThreadOpenConnections, NULL))
1919 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1922 if (!NewThread(ThreadMessageHandler, NULL))
1923 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1925 // Dump network addresses
1926 if (!NewThread(ThreadDumpAddress, NULL))
1927 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1929 // Mine proof-of-stake blocks in the background
1930 if (!NewThread(ThreadStakeMiner, pwalletMain))
1931 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1933 // Trusted NTP server, it's localhost by default.
1934 strTrustedUpstream = GetArg("-ntp", "localhost");
1936 // Start periodical NTP sampling thread
1937 NewThread(ThreadNtpSamples, NULL);
1943 printf("StopNode()\n");
1945 nTransactionsUpdated++;
1946 int64_t nStart = GetTime();
1949 ThreadScriptCheckQuit();
1952 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1953 semOutbound->post();
1956 int nThreadsRunning = 0;
1957 for (int n = 0; n < THREAD_MAX; n++)
1958 nThreadsRunning += vnThreadsRunning[n];
1959 if (nThreadsRunning == 0)
1961 if (GetTime() - nStart > 20)
1965 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1966 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1967 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1968 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1969 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1971 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1973 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1974 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1975 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1976 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1977 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1978 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1995 BOOST_FOREACH(CNode* pnode, vNodes)
1996 if (pnode->hSocket != INVALID_SOCKET)
1997 closesocket(pnode->hSocket);
1998 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1999 if (hListenSocket != INVALID_SOCKET)
2000 if (closesocket(hListenSocket) == SOCKET_ERROR)
2001 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2003 // clean up some globals (to help leak detection)
2004 BOOST_FOREACH(CNode *pnode, vNodes)
2006 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
2009 vNodesDisconnected.clear();
2012 delete pnodeLocalHost;
2013 pnodeLocalHost = NULL;
2016 // Shutdown Windows Sockets
2021 instance_of_cnetcleanup;
2023 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2025 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2028 RelayTransaction(tx, hash, ss);
2031 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2033 CInv inv(MSG_TX, hash);
2036 // Expire old relay messages
2037 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2039 mapRelay.erase(vRelayExpiration.front().second);
2040 vRelayExpiration.pop_front();
2043 // Save original serialized message so newer versions are preserved
2044 mapRelay.insert(std::make_pair(inv, ss));
2045 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2048 RelayInventory(inv);
2051 void CNode::RecordBytesRecv(uint64_t bytes)
2053 LOCK(cs_totalBytesRecv);
2054 nTotalBytesRecv += bytes;
2057 void CNode::RecordBytesSent(uint64_t bytes)
2059 LOCK(cs_totalBytesSent);
2060 nTotalBytesSent += bytes;
2063 uint64_t CNode::GetTotalBytesRecv()
2065 LOCK(cs_totalBytesRecv);
2066 return nTotalBytesRecv;
2069 uint64_t CNode::GetTotalBytesSent()
2071 LOCK(cs_totalBytesSent);
2072 return nTotalBytesSent;