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", nOneDay); // 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 size_t 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 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1158 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1159 vAdd.push_back(addr);
1163 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1168 printf("%d addresses found from DNS seeds\n", found);
1184 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1185 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1186 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1187 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1188 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1189 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1190 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1191 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1192 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1193 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1194 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1195 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1196 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1197 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1198 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1199 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1203 const char* pchTorSeed[] =
1205 "seedp4knqnoei57u.onion",
1206 "seedr3hhlepyi7fd.onion",
1207 "seed3uuomkclbiz4.onion",
1208 "seedeh7qck3ouff5.onion",
1209 "5rg3vq4jagckeckf.onion",
1210 "seedt3sraf53ajiy.onion",
1211 "seedg4qyccsg42oq.onion",
1212 "novaqrtoywpg7jly.onion",
1213 "seed3d5wolqbgrcb.onion",
1214 "seed24u5dwph3qw4.onion",
1215 "mj26ulzbs2oskgym.onion",
1216 "eqon4usunavt76m7.onion",
1217 "seedd3aldwpslzl3.onion"
1220 void DumpAddresses()
1222 int64_t nStart = GetTimeMillis();
1227 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1228 addrman.size(), GetTimeMillis() - nStart);
1231 void ThreadDumpAddress2(void* parg)
1233 printf("ThreadDumpAddress started\n");
1235 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1239 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1241 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1243 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1246 void ThreadDumpAddress(void* parg)
1248 // Make this thread recognisable as the address dumping thread
1249 RenameThread("novacoin-adrdump");
1253 ThreadDumpAddress2(parg);
1255 catch (std::exception& e) {
1256 PrintException(&e, "ThreadDumpAddress()");
1258 printf("ThreadDumpAddress exited\n");
1261 void ThreadOpenConnections(void* parg)
1263 // Make this thread recognisable as the connection opening thread
1264 RenameThread("novacoin-opencon");
1268 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1269 ThreadOpenConnections2(parg);
1270 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1272 catch (std::exception& e) {
1273 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1274 PrintException(&e, "ThreadOpenConnections()");
1276 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1277 PrintException(NULL, "ThreadOpenConnections()");
1279 printf("ThreadOpenConnections exited\n");
1282 void static ProcessOneShot()
1287 if (vOneShots.empty())
1289 strDest = vOneShots.front();
1290 vOneShots.pop_front();
1293 CSemaphoreGrant grant(*semOutbound, true);
1295 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1296 AddOneShot(strDest);
1300 void ThreadOpenConnections2(void* parg)
1302 printf("ThreadOpenConnections started\n");
1304 // Connect to specific addresses
1305 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1307 for (int64_t nLoop = 0;; nLoop++)
1310 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1313 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1314 for (int i = 0; i < 10 && i < nLoop; i++)
1325 // Initiate network connections
1326 int64_t nStart = GetTime();
1331 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1333 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1338 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1339 CSemaphoreGrant grant(*semOutbound);
1340 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1344 // Add seed nodes if IRC isn't working
1345 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1347 std::vector<CAddress> vAdd;
1348 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1350 // It'll only connect to one or two seed nodes because once it connects,
1351 // it'll get a pile of addresses with newer timestamps.
1352 // Seed nodes are given a random 'last seen time' of between one and two
1354 const int64_t nOneWeek = 7*24*60*60;
1356 memcpy(&ip, &pnSeed[i], sizeof(ip));
1357 CAddress addr(CService(ip, GetDefaultPort()));
1358 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1359 vAdd.push_back(addr);
1361 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1364 // Add Tor nodes if we have connection with onion router
1365 if (mapArgs.count("-tor"))
1367 std::vector<CAddress> vAdd;
1368 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1370 const int64_t nOneWeek = 7*24*60*60;
1371 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1372 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1373 vAdd.push_back(addr);
1375 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1379 // Choose an address to connect to based on most recently seen
1381 CAddress addrConnect;
1383 // Only connect out to one peer per network group (/16 for IPv4).
1384 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1386 set<vector<unsigned char> > setConnected;
1389 BOOST_FOREACH(CNode* pnode, vNodes) {
1390 if (!pnode->fInbound) {
1391 setConnected.insert(pnode->addr.GetGroup());
1397 int64_t nANow = GetAdjustedTime();
1402 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1403 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1405 // if we selected an invalid address, restart
1406 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1409 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1410 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1411 // already-connected network ranges, ...) before trying new addrman addresses.
1416 if (IsLimited(addr))
1419 // only consider very recently tried nodes after 30 failed attempts
1420 if (nANow - addr.nLastTry < 600 && nTries < 30)
1423 // do not allow non-default ports, unless after 50 invalid addresses selected already
1424 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1431 if (addrConnect.IsValid())
1432 OpenNetworkConnection(addrConnect, &grant);
1436 void ThreadOpenAddedConnections(void* parg)
1438 // Make this thread recognisable as the connection opening thread
1439 RenameThread("novacoin-opencon");
1443 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1444 ThreadOpenAddedConnections2(parg);
1445 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1447 catch (std::exception& e) {
1448 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1449 PrintException(&e, "ThreadOpenAddedConnections()");
1451 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1452 PrintException(NULL, "ThreadOpenAddedConnections()");
1454 printf("ThreadOpenAddedConnections exited\n");
1457 void ThreadOpenAddedConnections2(void* parg)
1459 printf("ThreadOpenAddedConnections started\n");
1462 LOCK(cs_vAddedNodes);
1463 vAddedNodes = mapMultiArgs["-addnode"];
1466 if (HaveNameProxy()) {
1468 list<string> lAddresses(0);
1470 LOCK(cs_vAddedNodes);
1471 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1472 lAddresses.push_back(strAddNode);
1474 BOOST_FOREACH(string& strAddNode, lAddresses) {
1476 CSemaphoreGrant grant(*semOutbound);
1477 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1480 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1481 Sleep(120000); // Retry every 2 minutes
1482 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1487 for (uint32_t i = 0; true; i++)
1489 list<string> lAddresses(0);
1491 LOCK(cs_vAddedNodes);
1492 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1493 lAddresses.push_back(strAddNode);
1496 list<vector<CService> > lservAddressesToAdd(0);
1497 BOOST_FOREACH(string& strAddNode, lAddresses)
1499 vector<CService> vservNode(0);
1500 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1502 lservAddressesToAdd.push_back(vservNode);
1504 LOCK(cs_setservAddNodeAddresses);
1505 BOOST_FOREACH(CService& serv, vservNode)
1506 setservAddNodeAddresses.insert(serv);
1510 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1511 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1514 BOOST_FOREACH(CNode* pnode, vNodes)
1515 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1517 BOOST_FOREACH(CService& addrNode, *(it))
1518 if (pnode->addr == addrNode)
1520 it = lservAddressesToAdd.erase(it);
1521 if(it != lservAddressesToAdd.begin())
1525 if (it == lservAddressesToAdd.end())
1529 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1531 if (vserv.size() == 0)
1533 CSemaphoreGrant grant(*semOutbound);
1534 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1541 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1542 Sleep(120000); // Retry every 2 minutes
1543 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1549 // if successful, this moves the passed grant to the constructed node
1550 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1553 // Initiate outbound network connection
1558 if (IsLocal(addrConnect) ||
1559 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1560 FindNode(addrConnect.ToStringIPPort().c_str()))
1562 if (strDest && FindNode(strDest))
1565 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1566 CNode* pnode = ConnectNode(addrConnect, strDest);
1567 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1573 grantOutbound->MoveTo(pnode->grantOutbound);
1574 pnode->fNetworkNode = true;
1576 pnode->fOneShot = true;
1581 // for now, use a very simple selection metric: the node from which we received
1583 static int64_t NodeSyncScore(const CNode *pnode) {
1584 return pnode->nLastRecv;
1587 void static StartSync(const vector<CNode*> &vNodes) {
1588 CNode *pnodeNewSync = NULL;
1589 int64_t nBestScore = 0;
1591 // Iterate over all nodes
1592 BOOST_FOREACH(CNode* pnode, vNodes) {
1593 // check preconditions for allowing a sync
1594 if (!pnode->fClient && !pnode->fOneShot &&
1595 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1596 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1597 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1598 // if ok, compare node's score with the best so far
1599 int64_t nScore = NodeSyncScore(pnode);
1600 if (pnodeNewSync == NULL || nScore > nBestScore) {
1601 pnodeNewSync = pnode;
1602 nBestScore = nScore;
1606 // if a new sync candidate was found, start sync!
1608 pnodeNewSync->fStartSync = true;
1609 pnodeSync = pnodeNewSync;
1613 void ThreadMessageHandler(void* parg)
1615 // Make this thread recognisable as the message handling thread
1616 RenameThread("novacoin-msghand");
1620 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1621 ThreadMessageHandler2(parg);
1622 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1624 catch (std::exception& e) {
1625 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1626 PrintException(&e, "ThreadMessageHandler()");
1628 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1629 PrintException(NULL, "ThreadMessageHandler()");
1631 printf("ThreadMessageHandler exited\n");
1634 void ThreadMessageHandler2(void* parg)
1636 printf("ThreadMessageHandler started\n");
1637 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1640 bool fHaveSyncNode = false;
1641 vector<CNode*> vNodesCopy;
1644 vNodesCopy = vNodes;
1645 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1647 if (pnode == pnodeSync)
1648 fHaveSyncNode = true;
1653 StartSync(vNodesCopy);
1655 // Poll the connected nodes for messages
1656 CNode* pnodeTrickle = NULL;
1657 if (!vNodesCopy.empty())
1658 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1659 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1663 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1665 ProcessMessages(pnode);
1672 TRY_LOCK(pnode->cs_vSend, lockSend);
1674 SendMessages(pnode, pnode == pnodeTrickle);
1682 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1686 // Wait and allow messages to bunch up.
1687 // Reduce vnThreadsRunning so StopNode has permission to exit while
1688 // we're sleeping, but we must always check fShutdown after doing this.
1689 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1691 if (fRequestShutdown)
1693 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1704 bool BindListenPort(const CService &addrBind, string& strError)
1710 // Initialize Windows Sockets
1712 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1713 if (ret != NO_ERROR)
1715 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1716 printf("%s\n", strError.c_str());
1721 // Create socket for listening for incoming connections
1723 struct sockaddr_storage sockaddr;
1725 struct sockaddr sockaddr;
1727 socklen_t len = sizeof(sockaddr);
1728 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1730 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1731 printf("%s\n", strError.c_str());
1735 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1736 if (hListenSocket == INVALID_SOCKET)
1738 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1739 printf("%s\n", strError.c_str());
1745 // Different way of disabling SIGPIPE on BSD
1746 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1748 // Allow binding if the port is still in TIME_WAIT state after
1749 // the program was closed and restarted. Not an issue on windows!
1750 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1754 // Set to non-blocking, incoming connections will also inherit this
1755 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1757 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1760 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1761 printf("%s\n", strError.c_str());
1766 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1767 // and enable it by default or not. Try to enable it, if possible.
1768 if (addrBind.IsIPv6()) {
1771 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1773 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1777 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1778 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1783 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1785 int nErr = WSAGetLastError();
1786 if (nErr == WSAEADDRINUSE)
1787 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1789 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1790 printf("%s\n", strError.c_str());
1791 closesocket(hListenSocket);
1794 printf("Bound to %s\n", addrBind.ToString().c_str());
1796 // Listen for incoming connections
1797 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1799 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1800 printf("%s\n", strError.c_str());
1801 closesocket(hListenSocket);
1805 vhListenSocket.push_back(hListenSocket);
1807 if (addrBind.IsRoutable() && fDiscover)
1808 AddLocal(addrBind, LOCAL_BIND);
1813 void static Discover()
1819 // Get local host IP
1820 char pszHostName[1000] = "";
1821 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1823 vector<CNetAddr> vaddr;
1824 if (LookupHost(pszHostName, vaddr))
1826 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1828 AddLocal(addr, LOCAL_IF);
1833 // Get local host ip
1834 struct ifaddrs* myaddrs;
1835 if (getifaddrs(&myaddrs) == 0)
1837 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1839 if (ifa->ifa_addr == NULL) continue;
1840 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1841 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1842 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1843 if (ifa->ifa_addr->sa_family == AF_INET)
1845 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1846 CNetAddr addr(s4->sin_addr);
1847 if (AddLocal(addr, LOCAL_IF))
1848 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1851 else if (ifa->ifa_addr->sa_family == AF_INET6)
1853 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1854 CNetAddr addr(s6->sin6_addr);
1855 if (AddLocal(addr, LOCAL_IF))
1856 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1860 freeifaddrs(myaddrs);
1864 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1865 if (!IsLimited(NET_IPV4))
1866 NewThread(ThreadGetMyExternalIP, NULL);
1869 void StartNode(void* parg)
1871 // Make this thread recognisable as the startup thread
1872 RenameThread("novacoin-start");
1874 if (semOutbound == NULL) {
1875 // initialize semaphore
1876 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
1877 semOutbound = new CSemaphore(nMaxOutbound);
1880 if (pnodeLocalHost == NULL)
1881 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1889 if (!GetBoolArg("-dnsseed", true))
1890 printf("DNS seeding disabled\n");
1892 if (!NewThread(ThreadDNSAddressSeed, NULL))
1893 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1895 // Map ports with UPnP
1897 printf("UPNP port mapping is disabled\n");
1901 // Get addresses from IRC and advertise ours
1902 if (!GetBoolArg("-irc", true))
1903 printf("IRC seeding disabled\n");
1905 if (!NewThread(ThreadIRCSeed, NULL))
1906 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1908 // Send and receive from sockets, accept connections
1909 if (!NewThread(ThreadSocketHandler, NULL))
1910 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1912 // Initiate outbound connections from -addnode
1913 if (!NewThread(ThreadOpenAddedConnections, NULL))
1914 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1916 // Initiate outbound connections
1917 if (!NewThread(ThreadOpenConnections, NULL))
1918 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1921 if (!NewThread(ThreadMessageHandler, NULL))
1922 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1924 // Dump network addresses
1925 if (!NewThread(ThreadDumpAddress, NULL))
1926 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1928 // Mine proof-of-stake blocks in the background
1929 if (!NewThread(ThreadStakeMiner, pwalletMain))
1930 printf("Error: NewThread(ThreadStakeMiner) failed\n");
1932 // Trusted NTP server, it's localhost by default.
1933 strTrustedUpstream = GetArg("-ntp", "localhost");
1935 // Start periodical NTP sampling thread
1936 NewThread(ThreadNtpSamples, NULL);
1942 printf("StopNode()\n");
1944 nTransactionsUpdated++;
1945 int64_t nStart = GetTime();
1948 ThreadScriptCheckQuit();
1951 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1952 semOutbound->post();
1955 int nThreadsRunning = 0;
1956 for (int n = 0; n < THREAD_MAX; n++)
1957 nThreadsRunning += vnThreadsRunning[n];
1958 if (nThreadsRunning == 0)
1960 if (GetTime() - nStart > 20)
1964 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1965 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1966 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1967 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1968 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1970 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1972 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1973 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1974 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1975 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1976 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1977 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1994 BOOST_FOREACH(CNode* pnode, vNodes)
1995 if (pnode->hSocket != INVALID_SOCKET)
1996 closesocket(pnode->hSocket);
1997 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1998 if (hListenSocket != INVALID_SOCKET)
1999 if (closesocket(hListenSocket) == SOCKET_ERROR)
2000 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2002 // clean up some globals (to help leak detection)
2003 BOOST_FOREACH(CNode *pnode, vNodes)
2005 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
2008 vNodesDisconnected.clear();
2011 delete pnodeLocalHost;
2012 pnodeLocalHost = NULL;
2015 // Shutdown Windows Sockets
2020 instance_of_cnetcleanup;
2022 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2024 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2027 RelayTransaction(tx, hash, ss);
2030 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2032 CInv inv(MSG_TX, hash);
2035 // Expire old relay messages
2036 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2038 mapRelay.erase(vRelayExpiration.front().second);
2039 vRelayExpiration.pop_front();
2042 // Save original serialized message so newer versions are preserved
2043 mapRelay.insert(std::make_pair(inv, ss));
2044 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2047 RelayInventory(inv);
2050 void CNode::RecordBytesRecv(uint64_t bytes)
2052 LOCK(cs_totalBytesRecv);
2053 nTotalBytesRecv += bytes;
2056 void CNode::RecordBytesSent(uint64_t bytes)
2058 LOCK(cs_totalBytesSent);
2059 nTotalBytesSent += bytes;
2062 uint64_t CNode::GetTotalBytesRecv()
2064 LOCK(cs_totalBytesRecv);
2065 return nTotalBytesRecv;
2068 uint64_t CNode::GetTotalBytesSent()
2070 LOCK(cs_totalBytesSent);
2071 return nTotalBytesSent;