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.
12 #include "ui_interface.h"
19 #include <miniupnpc/miniwget.h>
20 #include <miniupnpc/miniupnpc.h>
21 #include <miniupnpc/upnpcommands.h>
22 #include <miniupnpc/upnperrors.h>
26 using namespace boost;
28 static const int MAX_OUTBOUND_CONNECTIONS = 16;
30 void ThreadMessageHandler2(void* parg);
31 void ThreadSocketHandler2(void* parg);
32 void ThreadOpenConnections2(void* parg);
33 void ThreadOpenAddedConnections2(void* parg);
35 void ThreadMapPort2(void* parg);
37 void ThreadDNSAddressSeed2(void* parg);
39 struct LocalServiceInfo {
45 // Global state variables
48 bool fDiscover = true;
49 bool fUseUPnP = false;
50 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
51 static CCriticalSection cs_mapLocalHost;
52 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
53 static bool vfReachable[NET_MAX] = {};
54 static bool vfLimited[NET_MAX] = {};
55 static CNode* pnodeLocalHost = NULL;
56 static CNode* pnodeSync = NULL;
57 CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
58 uint64_t nLocalHostNonce = 0;
59 boost::array<int, THREAD_MAX> vnThreadsRunning;
60 static std::vector<SOCKET> vhListenSocket;
63 vector<CNode*> vNodes;
64 CCriticalSection cs_vNodes;
65 map<CInv, CDataStream> mapRelay;
66 deque<pair<int64_t, CInv> > vRelayExpiration;
67 CCriticalSection cs_mapRelay;
68 map<CInv, int64_t> mapAlreadyAskedFor;
70 static deque<string> vOneShots;
71 CCriticalSection cs_vOneShots;
73 set<CNetAddr> setservAddNodeAddresses;
74 CCriticalSection cs_setservAddNodeAddresses;
76 vector<std::string> vAddedNodes;
77 CCriticalSection cs_vAddedNodes;
79 static CSemaphore *semOutbound = NULL;
81 void AddOneShot(string strDest)
84 vOneShots.push_back(strDest);
87 unsigned short GetListenPort()
89 return (unsigned short)(GetArg("-port", GetDefaultPort()));
92 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
94 // Filter out duplicate requests
95 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
97 pindexLastGetBlocksBegin = pindexBegin;
98 hashLastGetBlocksEnd = hashEnd;
100 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
103 // find 'best' local address for a particular peer
104 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
110 int nBestReachability = -1;
112 LOCK(cs_mapLocalHost);
113 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
115 int nScore = (*it).second.nScore;
116 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
117 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
119 addr = CService((*it).first, (*it).second.nPort);
120 nBestReachability = nReachability;
125 return nBestScore >= 0;
128 // get best local address for a particular peer as a CAddress
129 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
131 CAddress ret(CService("0.0.0.0",0),0);
133 if (GetLocal(addr, paddrPeer))
135 ret = CAddress(addr);
136 ret.nServices = nLocalServices;
137 ret.nTime = GetAdjustedTime();
142 bool RecvLine(SOCKET hSocket, string& strLine)
148 int nBytes = recv(hSocket, &c, 1, 0);
156 if (strLine.size() >= 9000)
159 else if (nBytes <= 0)
165 int nErr = WSAGetLastError();
166 if (nErr == WSAEMSGSIZE)
168 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
174 if (!strLine.empty())
179 printf("socket closed\n");
185 int nErr = WSAGetLastError();
186 printf("recv failed: %d\n", nErr);
193 // used when scores of local addresses may have changed
194 // pushes better local address to peers
195 void static AdvertizeLocal()
198 BOOST_FOREACH(CNode* pnode, vNodes)
200 if (pnode->fSuccessfullyConnected)
202 CAddress addrLocal = GetLocalAddress(&pnode->addr);
203 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
205 pnode->PushAddress(addrLocal);
206 pnode->addrLocal = addrLocal;
212 void SetReachable(enum Network net, bool fFlag)
214 LOCK(cs_mapLocalHost);
215 vfReachable[net] = fFlag;
216 if (net == NET_IPV6 && fFlag)
217 vfReachable[NET_IPV4] = true;
220 // learn a new local address
221 bool AddLocal(const CService& addr, int nScore)
223 if (!addr.IsRoutable())
226 if (!fDiscover && nScore < LOCAL_MANUAL)
232 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
235 LOCK(cs_mapLocalHost);
236 bool fAlready = mapLocalHost.count(addr) > 0;
237 LocalServiceInfo &info = mapLocalHost[addr];
238 if (!fAlready || nScore >= info.nScore) {
239 info.nScore = nScore + (fAlready ? 1 : 0);
240 info.nPort = addr.GetPort();
242 SetReachable(addr.GetNetwork());
250 bool AddLocal(const CNetAddr &addr, int nScore)
252 return AddLocal(CService(addr, GetListenPort()), nScore);
255 /** Make a particular network entirely off-limits (no automatic connects to it) */
256 void SetLimited(enum Network net, bool fLimited)
258 if (net == NET_UNROUTABLE)
260 LOCK(cs_mapLocalHost);
261 vfLimited[net] = fLimited;
264 bool IsLimited(enum Network net)
266 LOCK(cs_mapLocalHost);
267 return vfLimited[net];
270 bool IsLimited(const CNetAddr &addr)
272 return IsLimited(addr.GetNetwork());
275 /** vote for a local address */
276 bool SeenLocal(const CService& addr)
279 LOCK(cs_mapLocalHost);
280 if (mapLocalHost.count(addr) == 0)
282 mapLocalHost[addr].nScore++;
290 /** check whether a given address is potentially local */
291 bool IsLocal(const CService& addr)
293 LOCK(cs_mapLocalHost);
294 return mapLocalHost.count(addr) > 0;
297 /** check whether a given address is in a network we can probably connect to */
298 bool IsReachable(const CNetAddr& addr)
300 LOCK(cs_mapLocalHost);
301 enum Network net = addr.GetNetwork();
302 return vfReachable[net] && !vfLimited[net];
305 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
307 // We now get our external IP from the IRC server first and only use this as a backup
308 bool GetMyExternalIP(CNetAddr& ipRet)
310 struct sockaddr_in mapped;
311 uint64_t rnd = UINT64_MAX;
313 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
315 ipRet = CNetAddr(mapped.sin_addr);
316 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
322 void ThreadGetMyExternalIP(void* parg)
324 // Make this thread recognisable as the external IP detection thread
325 RenameThread("novacoin-ext-ip");
327 CNetAddr addrLocalHost;
328 if (GetMyExternalIP(addrLocalHost))
330 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
331 AddLocal(addrLocalHost, LOCAL_HTTP);
339 void AddressCurrentlyConnected(const CService& addr)
341 addrman.Connected(addr);
347 uint64_t CNode::nTotalBytesRecv = 0;
348 uint64_t CNode::nTotalBytesSent = 0;
349 CCriticalSection CNode::cs_totalBytesRecv;
350 CCriticalSection CNode::cs_totalBytesSent;
352 CNode* FindNode(const CNetAddr& ip)
355 BOOST_FOREACH(CNode* pnode, vNodes)
356 if ((CNetAddr)pnode->addr == ip)
361 CNode* FindNode(std::string addrName)
364 BOOST_FOREACH(CNode* pnode, vNodes)
365 if (pnode->addrName == addrName)
370 CNode* FindNode(const CService& addr)
373 BOOST_FOREACH(CNode* pnode, vNodes)
374 if ((CService)pnode->addr == addr)
379 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
381 if (pszDest == NULL) {
382 if (IsLocal(addrConnect))
385 // Look for an existing connection
386 CNode* pnode = FindNode((CService)addrConnect);
390 pnode->AddRef(nTimeout);
399 printf("trying connection %s lastseen=%.1fhrs\n",
400 pszDest ? pszDest : addrConnect.ToString().c_str(),
401 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
405 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
407 addrman.Attempt(addrConnect);
410 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
412 // Set to non-blocking
415 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
416 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
418 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
419 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
423 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
425 pnode->AddRef(nTimeout);
431 vNodes.push_back(pnode);
434 pnode->nTimeConnected = GetTime();
443 void CNode::CloseSocketDisconnect()
446 if (hSocket != INVALID_SOCKET)
448 printf("disconnecting node %s\n", addrName.c_str());
449 closesocket(hSocket);
450 hSocket = INVALID_SOCKET;
454 // in case this fails, we'll empty the recv buffer when the CNode is deleted
455 TRY_LOCK(cs_vRecv, lockRecv);
459 // if this was the sync node, we'll need a new one
460 if (this == pnodeSync)
464 void CNode::Cleanup()
469 void CNode::PushVersion()
471 /// when NTP implemented, change to just nTime = GetAdjustedTime()
472 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
473 CAddress addrYou, addrMe;
475 bool fHidden = false;
477 if (mapArgs.count("-torname")) {
478 // Our hidden service address
479 CService addrTorName(mapArgs["-torname"], GetListenPort());
481 if (addrTorName.IsValid()) {
483 addrMe = CAddress(addrTorName);
490 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
491 addrMe = GetLocalAddress(&addr);
494 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
495 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());
496 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
497 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
504 std::map<CNetAddr, int64_t> CNode::setBanned;
505 CCriticalSection CNode::cs_setBanned;
507 void CNode::ClearBanned()
512 bool CNode::IsBanned(CNetAddr ip)
514 bool fResult = false;
517 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
518 if (i != setBanned.end())
520 int64_t t = (*i).second;
528 bool CNode::Misbehaving(int howmuch)
532 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
536 nMisbehavior += howmuch;
537 if (nMisbehavior >= GetArg("-banscore", 100))
539 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
540 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
543 if (setBanned[addr] < banTime)
544 setBanned[addr] = banTime;
546 CloseSocketDisconnect();
549 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
554 #define X(name) stats.name = name
555 void CNode::copyStats(CNodeStats &stats)
570 stats.fSyncNode = (this == pnodeSync);
583 void ThreadSocketHandler(void* parg)
585 // Make this thread recognisable as the networking thread
586 RenameThread("novacoin-net");
590 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
591 ThreadSocketHandler2(parg);
592 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
594 catch (std::exception& e) {
595 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
596 PrintException(&e, "ThreadSocketHandler()");
598 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
599 throw; // support pthread_cancel()
601 printf("ThreadSocketHandler exited\n");
604 void ThreadSocketHandler2(void* parg)
606 printf("ThreadSocketHandler started\n");
607 list<CNode*> vNodesDisconnected;
608 unsigned int nPrevNodeCount = 0;
617 // Disconnect unused nodes
618 vector<CNode*> vNodesCopy = vNodes;
619 BOOST_FOREACH(CNode* pnode, vNodesCopy)
621 if (pnode->fDisconnect ||
622 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
624 // remove from vNodes
625 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
627 // release outbound grant (if any)
628 pnode->grantOutbound.Release();
630 // close socket and cleanup
631 pnode->CloseSocketDisconnect();
634 // hold in disconnected pool until all refs are released
635 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
636 if (pnode->fNetworkNode || pnode->fInbound)
638 vNodesDisconnected.push_back(pnode);
642 // Delete disconnected nodes
643 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
644 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
646 // wait until threads are done using it
647 if (pnode->GetRefCount() <= 0)
649 bool fDelete = false;
651 TRY_LOCK(pnode->cs_vSend, lockSend);
654 TRY_LOCK(pnode->cs_vRecv, lockRecv);
657 TRY_LOCK(pnode->cs_mapRequests, lockReq);
660 TRY_LOCK(pnode->cs_inventory, lockInv);
669 vNodesDisconnected.remove(pnode);
675 if (vNodes.size() != nPrevNodeCount)
677 nPrevNodeCount = vNodes.size();
678 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
683 // Find which sockets have data to receive
685 struct timeval timeout;
687 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
694 FD_ZERO(&fdsetError);
695 SOCKET hSocketMax = 0;
696 bool have_fds = false;
698 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
699 FD_SET(hListenSocket, &fdsetRecv);
700 hSocketMax = max(hSocketMax, hListenSocket);
705 BOOST_FOREACH(CNode* pnode, vNodes)
707 if (pnode->hSocket == INVALID_SOCKET)
709 FD_SET(pnode->hSocket, &fdsetRecv);
710 FD_SET(pnode->hSocket, &fdsetError);
711 hSocketMax = max(hSocketMax, pnode->hSocket);
714 TRY_LOCK(pnode->cs_vSend, lockSend);
715 if (lockSend && !pnode->vSend.empty())
716 FD_SET(pnode->hSocket, &fdsetSend);
721 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
722 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
723 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
724 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
727 if (nSelect == SOCKET_ERROR)
731 int nErr = WSAGetLastError();
732 printf("socket select error %d\n", nErr);
733 for (unsigned int i = 0; i <= hSocketMax; i++)
734 FD_SET(i, &fdsetRecv);
737 FD_ZERO(&fdsetError);
738 Sleep(timeout.tv_usec/1000);
743 // Accept new connections
745 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
746 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
749 struct sockaddr_storage sockaddr;
751 struct sockaddr sockaddr;
753 socklen_t len = sizeof(sockaddr);
754 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
758 if (hSocket != INVALID_SOCKET)
759 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
760 printf("Warning: Unknown socket family\n");
764 BOOST_FOREACH(CNode* pnode, vNodes)
769 if (hSocket == INVALID_SOCKET)
771 int nErr = WSAGetLastError();
772 if (nErr != WSAEWOULDBLOCK)
773 printf("socket error accept failed: %d\n", nErr);
775 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
778 LOCK(cs_setservAddNodeAddresses);
779 if (!setservAddNodeAddresses.count(addr))
780 closesocket(hSocket);
783 else if (CNode::IsBanned(addr))
785 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
786 closesocket(hSocket);
790 printf("accepted connection %s\n", addr.ToString().c_str());
791 CNode* pnode = new CNode(hSocket, addr, "", true);
795 vNodes.push_back(pnode);
802 // Service each socket
804 vector<CNode*> vNodesCopy;
808 BOOST_FOREACH(CNode* pnode, vNodesCopy)
811 BOOST_FOREACH(CNode* pnode, vNodesCopy)
819 if (pnode->hSocket == INVALID_SOCKET)
821 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
823 TRY_LOCK(pnode->cs_vRecv, lockRecv);
826 CDataStream& vRecv = pnode->vRecv;
827 uint64_t nPos = vRecv.size();
829 if (nPos > ReceiveBufferSize()) {
830 if (!pnode->fDisconnect)
831 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
832 pnode->CloseSocketDisconnect();
835 // typical socket buffer is 8K-64K
836 char pchBuf[0x10000];
837 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
840 vRecv.resize(nPos + nBytes);
841 memcpy(&vRecv[nPos], pchBuf, nBytes);
842 pnode->nLastRecv = GetTime();
843 pnode->nRecvBytes += nBytes;
844 pnode->RecordBytesRecv(nBytes);
846 else if (nBytes == 0)
848 // socket closed gracefully
849 if (!pnode->fDisconnect)
850 printf("socket closed\n");
851 pnode->CloseSocketDisconnect();
856 int nErr = WSAGetLastError();
857 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
859 if (!pnode->fDisconnect)
860 printf("socket recv error %d\n", nErr);
861 pnode->CloseSocketDisconnect();
871 if (pnode->hSocket == INVALID_SOCKET)
873 if (FD_ISSET(pnode->hSocket, &fdsetSend))
875 TRY_LOCK(pnode->cs_vSend, lockSend);
878 CDataStream& vSend = pnode->vSend;
881 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
884 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
885 pnode->nLastSend = GetTime();
886 pnode->nSendBytes += nBytes;
887 pnode->RecordBytesSent(nBytes);
892 int nErr = WSAGetLastError();
893 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
895 printf("socket send error %d\n", nErr);
896 pnode->CloseSocketDisconnect();
904 // Inactivity checking
906 if (pnode->vSend.empty())
907 pnode->nLastSendEmpty = GetTime();
908 if (GetTime() - pnode->nTimeConnected > 60)
910 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
912 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
913 pnode->fDisconnect = true;
915 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
917 printf("socket not sending\n");
918 pnode->fDisconnect = true;
920 else if (GetTime() - pnode->nLastRecv > 90*60)
922 printf("socket inactivity timeout\n");
923 pnode->fDisconnect = true;
929 BOOST_FOREACH(CNode* pnode, vNodesCopy)
946 void ThreadMapPort(void* parg)
948 // Make this thread recognisable as the UPnP thread
949 RenameThread("novacoin-UPnP");
953 vnThreadsRunning[THREAD_UPNP]++;
954 ThreadMapPort2(parg);
955 vnThreadsRunning[THREAD_UPNP]--;
957 catch (std::exception& e) {
958 vnThreadsRunning[THREAD_UPNP]--;
959 PrintException(&e, "ThreadMapPort()");
961 vnThreadsRunning[THREAD_UPNP]--;
962 PrintException(NULL, "ThreadMapPort()");
964 printf("ThreadMapPort exited\n");
967 void ThreadMapPort2(void* parg)
969 printf("ThreadMapPort started\n");
971 std::string port = strprintf("%u", GetListenPort());
972 const char * multicastif = 0;
973 const char * minissdpdpath = 0;
974 struct UPNPDev * devlist = 0;
977 #ifndef UPNPDISCOVER_SUCCESS
979 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
983 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
986 struct UPNPUrls urls;
987 struct IGDdatas data;
990 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
994 char externalIPAddress[40];
995 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
996 if(r != UPNPCOMMAND_SUCCESS)
997 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
1000 if(externalIPAddress[0])
1002 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1003 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1006 printf("UPnP: GetExternalIPAddress failed.\n");
1010 string strDesc = "NovaCoin " + FormatFullVersion();
1011 #ifndef UPNPDISCOVER_SUCCESS
1013 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1014 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1017 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1018 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1021 if(r!=UPNPCOMMAND_SUCCESS)
1022 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1023 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1025 printf("UPnP Port Mapping successful.\n");
1029 if (fShutdown || !fUseUPnP)
1031 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1032 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1033 freeUPNPDevlist(devlist); devlist = 0;
1034 FreeUPNPUrls(&urls);
1037 if (i % 600 == 0) // Refresh every 20 minutes
1039 #ifndef UPNPDISCOVER_SUCCESS
1041 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1042 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1045 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1046 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1049 if(r!=UPNPCOMMAND_SUCCESS)
1050 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1051 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1053 printf("UPnP Port Mapping successful.\n");;
1059 printf("No valid UPnP IGDs found\n");
1060 freeUPNPDevlist(devlist); devlist = 0;
1062 FreeUPNPUrls(&urls);
1065 if (fShutdown || !fUseUPnP)
1074 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1076 if (!NewThread(ThreadMapPort, NULL))
1077 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1083 // Intentionally left blank.
1096 // Each pair gives a source name and a seed name.
1097 // The first name is used as information source for addrman.
1098 // The second name should resolve to a list of seed addresses.
1099 static const char *strDNSSeed[][2] = {
1100 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1101 {"novacoin.ru", "dnsseed.novacoin.ru"},
1102 {"novacoin.ru", "testseed.novacoin.ru"},
1103 {"novaco.in", "dnsseed.novaco.in"},
1106 void ThreadDNSAddressSeed(void* parg)
1108 // Make this thread recognisable as the DNS seeding thread
1109 RenameThread("novacoin-dnsseed");
1113 vnThreadsRunning[THREAD_DNSSEED]++;
1114 ThreadDNSAddressSeed2(parg);
1115 vnThreadsRunning[THREAD_DNSSEED]--;
1117 catch (std::exception& e) {
1118 vnThreadsRunning[THREAD_DNSSEED]--;
1119 PrintException(&e, "ThreadDNSAddressSeed()");
1121 vnThreadsRunning[THREAD_DNSSEED]--;
1122 throw; // support pthread_cancel()
1124 printf("ThreadDNSAddressSeed exited\n");
1127 void ThreadDNSAddressSeed2(void* parg)
1129 printf("ThreadDNSAddressSeed started\n");
1134 printf("Loading addresses from DNS seeds (could take a while)\n");
1136 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1137 if (HaveNameProxy()) {
1138 AddOneShot(strDNSSeed[seed_idx][1]);
1140 vector<CNetAddr> vaddr;
1141 vector<CAddress> vAdd;
1142 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1144 BOOST_FOREACH(CNetAddr& ip, vaddr)
1146 int nOneDay = 24*3600;
1147 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1148 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1149 vAdd.push_back(addr);
1153 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1158 printf("%d addresses found from DNS seeds\n", found);
1174 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1175 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1176 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1177 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1178 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1179 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1180 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1181 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1182 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1183 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1184 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1185 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1186 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1187 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1188 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1189 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1193 const char* pchTorSeed[] =
1195 "seedp4knqnoei57u.onion",
1196 "seedr3hhlepyi7fd.onion",
1197 "seed3uuomkclbiz4.onion",
1198 "seedeh7qck3ouff5.onion",
1199 "5rg3vq4jagckeckf.onion",
1200 "seedt3sraf53ajiy.onion",
1201 "seedg4qyccsg42oq.onion",
1202 "novaqrtoywpg7jly.onion",
1203 "seed3d5wolqbgrcb.onion",
1204 "seed24u5dwph3qw4.onion",
1205 "mj26ulzbs2oskgym.onion",
1206 "eqon4usunavt76m7.onion",
1209 void DumpAddresses()
1211 int64_t nStart = GetTimeMillis();
1216 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1217 addrman.size(), GetTimeMillis() - nStart);
1220 void ThreadDumpAddress2(void* parg)
1222 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1226 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1228 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1230 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1233 void ThreadDumpAddress(void* parg)
1235 // Make this thread recognisable as the address dumping thread
1236 RenameThread("novacoin-adrdump");
1240 ThreadDumpAddress2(parg);
1242 catch (std::exception& e) {
1243 PrintException(&e, "ThreadDumpAddress()");
1245 printf("ThreadDumpAddress exited\n");
1248 void ThreadOpenConnections(void* parg)
1250 // Make this thread recognisable as the connection opening thread
1251 RenameThread("novacoin-opencon");
1255 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1256 ThreadOpenConnections2(parg);
1257 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1259 catch (std::exception& e) {
1260 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1261 PrintException(&e, "ThreadOpenConnections()");
1263 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1264 PrintException(NULL, "ThreadOpenConnections()");
1266 printf("ThreadOpenConnections exited\n");
1269 void static ProcessOneShot()
1274 if (vOneShots.empty())
1276 strDest = vOneShots.front();
1277 vOneShots.pop_front();
1280 CSemaphoreGrant grant(*semOutbound, true);
1282 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1283 AddOneShot(strDest);
1287 // ppcoin: stake minter thread
1288 void static ThreadStakeMinter(void* parg)
1290 printf("ThreadStakeMinter started\n");
1291 CWallet* pwallet = (CWallet*)parg;
1294 vnThreadsRunning[THREAD_MINTER]++;
1295 StakeMiner(pwallet);
1296 vnThreadsRunning[THREAD_MINTER]--;
1298 catch (std::exception& e) {
1299 vnThreadsRunning[THREAD_MINTER]--;
1300 PrintException(&e, "ThreadStakeMinter()");
1302 vnThreadsRunning[THREAD_MINTER]--;
1303 PrintException(NULL, "ThreadStakeMinter()");
1305 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1308 void ThreadOpenConnections2(void* parg)
1310 printf("ThreadOpenConnections started\n");
1312 // Connect to specific addresses
1313 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1315 for (int64_t nLoop = 0;; nLoop++)
1318 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1321 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1322 for (int i = 0; i < 10 && i < nLoop; i++)
1333 // Initiate network connections
1334 int64_t nStart = GetTime();
1339 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1341 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1346 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1347 CSemaphoreGrant grant(*semOutbound);
1348 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1352 // Add seed nodes if IRC isn't working
1353 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1355 std::vector<CAddress> vAdd;
1356 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1358 // It'll only connect to one or two seed nodes because once it connects,
1359 // it'll get a pile of addresses with newer timestamps.
1360 // Seed nodes are given a random 'last seen time' of between one and two
1362 const int64_t nOneWeek = 7*24*60*60;
1364 memcpy(&ip, &pnSeed[i], sizeof(ip));
1365 CAddress addr(CService(ip, GetDefaultPort()));
1366 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1367 vAdd.push_back(addr);
1369 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1372 // Add Tor nodes if we have connection with onion router
1373 if (mapArgs.count("-tor"))
1375 std::vector<CAddress> vAdd;
1376 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1378 const int64_t nOneWeek = 7*24*60*60;
1379 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1380 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1381 vAdd.push_back(addr);
1383 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1387 // Choose an address to connect to based on most recently seen
1389 CAddress addrConnect;
1391 // Only connect out to one peer per network group (/16 for IPv4).
1392 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1394 set<vector<unsigned char> > setConnected;
1397 BOOST_FOREACH(CNode* pnode, vNodes) {
1398 if (!pnode->fInbound) {
1399 setConnected.insert(pnode->addr.GetGroup());
1405 int64_t nANow = GetAdjustedTime();
1410 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1411 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1413 // if we selected an invalid address, restart
1414 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1417 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1418 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1419 // already-connected network ranges, ...) before trying new addrman addresses.
1424 if (IsLimited(addr))
1427 // only consider very recently tried nodes after 30 failed attempts
1428 if (nANow - addr.nLastTry < 600 && nTries < 30)
1431 // do not allow non-default ports, unless after 50 invalid addresses selected already
1432 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1439 if (addrConnect.IsValid())
1440 OpenNetworkConnection(addrConnect, &grant);
1444 void ThreadOpenAddedConnections(void* parg)
1446 // Make this thread recognisable as the connection opening thread
1447 RenameThread("novacoin-opencon");
1451 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1452 ThreadOpenAddedConnections2(parg);
1453 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1455 catch (std::exception& e) {
1456 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1457 PrintException(&e, "ThreadOpenAddedConnections()");
1459 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1460 PrintException(NULL, "ThreadOpenAddedConnections()");
1462 printf("ThreadOpenAddedConnections exited\n");
1465 void ThreadOpenAddedConnections2(void* parg)
1467 printf("ThreadOpenAddedConnections started\n");
1470 LOCK(cs_vAddedNodes);
1471 vAddedNodes = mapMultiArgs["-addnode"];
1474 if (HaveNameProxy()) {
1476 list<string> lAddresses(0);
1478 LOCK(cs_vAddedNodes);
1479 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1480 lAddresses.push_back(strAddNode);
1482 BOOST_FOREACH(string& strAddNode, lAddresses) {
1484 CSemaphoreGrant grant(*semOutbound);
1485 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1488 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1489 Sleep(120000); // Retry every 2 minutes
1490 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1495 for (uint32_t i = 0; true; i++)
1497 list<string> lAddresses(0);
1499 LOCK(cs_vAddedNodes);
1500 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1501 lAddresses.push_back(strAddNode);
1504 list<vector<CService> > lservAddressesToAdd(0);
1505 BOOST_FOREACH(string& strAddNode, lAddresses)
1507 vector<CService> vservNode(0);
1508 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1510 lservAddressesToAdd.push_back(vservNode);
1512 LOCK(cs_setservAddNodeAddresses);
1513 BOOST_FOREACH(CService& serv, vservNode)
1514 setservAddNodeAddresses.insert(serv);
1518 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1519 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1522 BOOST_FOREACH(CNode* pnode, vNodes)
1523 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1525 BOOST_FOREACH(CService& addrNode, *(it))
1526 if (pnode->addr == addrNode)
1528 it = lservAddressesToAdd.erase(it);
1529 if(it != lservAddressesToAdd.begin())
1533 if (it == lservAddressesToAdd.end())
1537 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1539 if (vserv.size() == 0)
1541 CSemaphoreGrant grant(*semOutbound);
1542 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1549 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1550 Sleep(120000); // Retry every 2 minutes
1551 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1557 // if successful, this moves the passed grant to the constructed node
1558 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1561 // Initiate outbound network connection
1566 if (IsLocal(addrConnect) ||
1567 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1568 FindNode(addrConnect.ToStringIPPort().c_str()))
1570 if (strDest && FindNode(strDest))
1573 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1574 CNode* pnode = ConnectNode(addrConnect, strDest);
1575 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1581 grantOutbound->MoveTo(pnode->grantOutbound);
1582 pnode->fNetworkNode = true;
1584 pnode->fOneShot = true;
1589 // for now, use a very simple selection metric: the node from which we received
1591 double static NodeSyncScore(const CNode *pnode) {
1592 return -pnode->nLastRecv;
1595 void static StartSync(const vector<CNode*> &vNodes) {
1596 CNode *pnodeNewSync = NULL;
1597 double dBestScore = 0;
1599 // Iterate over all nodes
1600 BOOST_FOREACH(CNode* pnode, vNodes) {
1601 // check preconditions for allowing a sync
1602 if (!pnode->fClient && !pnode->fOneShot &&
1603 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1604 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1605 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1606 // if ok, compare node's score with the best so far
1607 double dScore = NodeSyncScore(pnode);
1608 if (pnodeNewSync == NULL || dScore > dBestScore) {
1609 pnodeNewSync = pnode;
1610 dBestScore = dScore;
1614 // if a new sync candidate was found, start sync!
1616 pnodeNewSync->fStartSync = true;
1617 pnodeSync = pnodeNewSync;
1621 void ThreadMessageHandler(void* parg)
1623 // Make this thread recognisable as the message handling thread
1624 RenameThread("novacoin-msghand");
1628 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1629 ThreadMessageHandler2(parg);
1630 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1632 catch (std::exception& e) {
1633 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1634 PrintException(&e, "ThreadMessageHandler()");
1636 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1637 PrintException(NULL, "ThreadMessageHandler()");
1639 printf("ThreadMessageHandler exited\n");
1642 void ThreadMessageHandler2(void* parg)
1644 printf("ThreadMessageHandler started\n");
1645 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1648 bool fHaveSyncNode = false;
1649 vector<CNode*> vNodesCopy;
1652 vNodesCopy = vNodes;
1653 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1655 if (pnode == pnodeSync)
1656 fHaveSyncNode = true;
1661 StartSync(vNodesCopy);
1663 // Poll the connected nodes for messages
1664 CNode* pnodeTrickle = NULL;
1665 if (!vNodesCopy.empty())
1666 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1667 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1671 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1673 ProcessMessages(pnode);
1680 TRY_LOCK(pnode->cs_vSend, lockSend);
1682 SendMessages(pnode, pnode == pnodeTrickle);
1690 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1694 // Wait and allow messages to bunch up.
1695 // Reduce vnThreadsRunning so StopNode has permission to exit while
1696 // we're sleeping, but we must always check fShutdown after doing this.
1697 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1699 if (fRequestShutdown)
1701 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1712 bool BindListenPort(const CService &addrBind, string& strError)
1718 // Initialize Windows Sockets
1720 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1721 if (ret != NO_ERROR)
1723 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1724 printf("%s\n", strError.c_str());
1729 // Create socket for listening for incoming connections
1731 struct sockaddr_storage sockaddr;
1733 struct sockaddr sockaddr;
1735 socklen_t len = sizeof(sockaddr);
1736 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1738 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1739 printf("%s\n", strError.c_str());
1743 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1744 if (hListenSocket == INVALID_SOCKET)
1746 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1747 printf("%s\n", strError.c_str());
1752 // Different way of disabling SIGPIPE on BSD
1753 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1757 // Allow binding if the port is still in TIME_WAIT state after
1758 // the program was closed and restarted. Not an issue on windows.
1759 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1764 // Set to non-blocking, incoming connections will also inherit this
1765 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1767 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1770 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1771 printf("%s\n", strError.c_str());
1776 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1777 // and enable it by default or not. Try to enable it, if possible.
1778 if (addrBind.IsIPv6()) {
1781 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1783 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1787 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1788 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1789 // this call is allowed to fail
1790 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1795 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1797 int nErr = WSAGetLastError();
1798 if (nErr == WSAEADDRINUSE)
1799 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1801 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1802 printf("%s\n", strError.c_str());
1805 printf("Bound to %s\n", addrBind.ToString().c_str());
1807 // Listen for incoming connections
1808 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1810 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1811 printf("%s\n", strError.c_str());
1815 vhListenSocket.push_back(hListenSocket);
1817 if (addrBind.IsRoutable() && fDiscover)
1818 AddLocal(addrBind, LOCAL_BIND);
1823 void static Discover()
1829 // Get local host IP
1830 char pszHostName[1000] = "";
1831 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1833 vector<CNetAddr> vaddr;
1834 if (LookupHost(pszHostName, vaddr))
1836 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1838 AddLocal(addr, LOCAL_IF);
1843 // Get local host ip
1844 struct ifaddrs* myaddrs;
1845 if (getifaddrs(&myaddrs) == 0)
1847 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1849 if (ifa->ifa_addr == NULL) continue;
1850 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1851 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1852 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1853 if (ifa->ifa_addr->sa_family == AF_INET)
1855 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1856 CNetAddr addr(s4->sin_addr);
1857 if (AddLocal(addr, LOCAL_IF))
1858 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1861 else if (ifa->ifa_addr->sa_family == AF_INET6)
1863 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1864 CNetAddr addr(s6->sin6_addr);
1865 if (AddLocal(addr, LOCAL_IF))
1866 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1870 freeifaddrs(myaddrs);
1874 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1875 if (!IsLimited(NET_IPV4))
1876 NewThread(ThreadGetMyExternalIP, NULL);
1879 void StartNode(void* parg)
1881 // Make this thread recognisable as the startup thread
1882 RenameThread("novacoin-start");
1884 if (semOutbound == NULL) {
1885 // initialize semaphore
1886 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1887 semOutbound = new CSemaphore(nMaxOutbound);
1890 if (pnodeLocalHost == NULL)
1891 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1899 if (!GetBoolArg("-dnsseed", true))
1900 printf("DNS seeding disabled\n");
1902 if (!NewThread(ThreadDNSAddressSeed, NULL))
1903 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1905 // Map ports with UPnP
1907 printf("UPNP port mapping is disabled\n");
1911 // Get addresses from IRC and advertise ours
1912 if (!GetBoolArg("-irc", true))
1913 printf("IRC seeding disabled\n");
1915 if (!NewThread(ThreadIRCSeed, NULL))
1916 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1918 // Send and receive from sockets, accept connections
1919 if (!NewThread(ThreadSocketHandler, NULL))
1920 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1922 // Initiate outbound connections from -addnode
1923 if (!NewThread(ThreadOpenAddedConnections, NULL))
1924 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1926 // Initiate outbound connections
1927 if (!NewThread(ThreadOpenConnections, NULL))
1928 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1931 if (!NewThread(ThreadMessageHandler, NULL))
1932 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1934 // Dump network addresses
1935 if (!NewThread(ThreadDumpAddress, NULL))
1936 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1938 // ppcoin: mint proof-of-stake blocks in the background
1939 if (!NewThread(ThreadStakeMinter, pwalletMain))
1940 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1945 printf("StopNode()\n");
1947 nTransactionsUpdated++;
1948 int64_t nStart = GetTime();
1951 ThreadScriptCheckQuit();
1954 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1955 semOutbound->post();
1958 int nThreadsRunning = 0;
1959 for (int n = 0; n < THREAD_MAX; n++)
1960 nThreadsRunning += vnThreadsRunning[n];
1961 if (nThreadsRunning == 0)
1963 if (GetTime() - nStart > 20)
1967 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1968 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1969 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1970 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1971 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1973 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1975 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1976 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1977 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1978 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1979 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1980 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1996 BOOST_FOREACH(CNode* pnode, vNodes)
1997 if (pnode->hSocket != INVALID_SOCKET)
1998 closesocket(pnode->hSocket);
1999 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2000 if (hListenSocket != INVALID_SOCKET)
2001 if (closesocket(hListenSocket) == SOCKET_ERROR)
2002 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2005 // Shutdown Windows Sockets
2010 instance_of_cnetcleanup;
2012 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2014 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2017 RelayTransaction(tx, hash, ss);
2020 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2022 CInv inv(MSG_TX, hash);
2025 // Expire old relay messages
2026 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2028 mapRelay.erase(vRelayExpiration.front().second);
2029 vRelayExpiration.pop_front();
2032 // Save original serialized message so newer versions are preserved
2033 mapRelay.insert(std::make_pair(inv, ss));
2034 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2037 RelayInventory(inv);
2040 void CNode::RecordBytesRecv(uint64_t bytes)
2042 LOCK(cs_totalBytesRecv);
2043 nTotalBytesRecv += bytes;
2046 void CNode::RecordBytesSent(uint64_t bytes)
2048 LOCK(cs_totalBytesSent);
2049 nTotalBytesSent += bytes;
2052 uint64_t CNode::GetTotalBytesRecv()
2054 LOCK(cs_totalBytesRecv);
2055 return nTotalBytesRecv;
2058 uint64_t CNode::GetTotalBytesSent()
2060 LOCK(cs_totalBytesSent);
2061 return nTotalBytesSent;