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 = GetRand(~0LL);
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.su", "dnsseed.novacoin.su"},
1102 {"novacoin.ru", "dnsseed.novacoin.ru"},
1103 {"novacoin.ru", "testseed.novacoin.ru"},
1104 {"novaco.in", "dnsseed.novaco.in"},
1107 void ThreadDNSAddressSeed(void* parg)
1109 // Make this thread recognisable as the DNS seeding thread
1110 RenameThread("novacoin-dnsseed");
1114 vnThreadsRunning[THREAD_DNSSEED]++;
1115 ThreadDNSAddressSeed2(parg);
1116 vnThreadsRunning[THREAD_DNSSEED]--;
1118 catch (std::exception& e) {
1119 vnThreadsRunning[THREAD_DNSSEED]--;
1120 PrintException(&e, "ThreadDNSAddressSeed()");
1122 vnThreadsRunning[THREAD_DNSSEED]--;
1123 throw; // support pthread_cancel()
1125 printf("ThreadDNSAddressSeed exited\n");
1128 void ThreadDNSAddressSeed2(void* parg)
1130 printf("ThreadDNSAddressSeed started\n");
1135 printf("Loading addresses from DNS seeds (could take a while)\n");
1137 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1138 if (HaveNameProxy()) {
1139 AddOneShot(strDNSSeed[seed_idx][1]);
1141 vector<CNetAddr> vaddr;
1142 vector<CAddress> vAdd;
1143 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1145 BOOST_FOREACH(CNetAddr& ip, vaddr)
1147 int nOneDay = 24*3600;
1148 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1149 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1150 vAdd.push_back(addr);
1154 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1159 printf("%d addresses found from DNS seeds\n", found);
1175 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1176 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1177 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1178 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1179 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1180 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1181 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1182 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1183 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1184 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1185 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1186 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1187 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1188 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1189 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1190 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1194 const char* pchTorSeed[] =
1196 "seedp4knqnoei57u.onion",
1197 "seedr3hhlepyi7fd.onion",
1198 "seed3uuomkclbiz4.onion",
1199 "seedeh7qck3ouff5.onion",
1200 "5rg3vq4jagckeckf.onion",
1201 "seedt3sraf53ajiy.onion",
1202 "seedg4qyccsg42oq.onion",
1203 "novaqrtoywpg7jly.onion",
1204 "seed3d5wolqbgrcb.onion",
1205 "seed24u5dwph3qw4.onion",
1206 "mj26ulzbs2oskgym.onion",
1207 "eqon4usunavt76m7.onion",
1210 void DumpAddresses()
1212 int64_t nStart = GetTimeMillis();
1217 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1218 addrman.size(), GetTimeMillis() - nStart);
1221 void ThreadDumpAddress2(void* parg)
1223 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1227 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1229 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1231 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1234 void ThreadDumpAddress(void* parg)
1236 // Make this thread recognisable as the address dumping thread
1237 RenameThread("novacoin-adrdump");
1241 ThreadDumpAddress2(parg);
1243 catch (std::exception& e) {
1244 PrintException(&e, "ThreadDumpAddress()");
1246 printf("ThreadDumpAddress exited\n");
1249 void ThreadOpenConnections(void* parg)
1251 // Make this thread recognisable as the connection opening thread
1252 RenameThread("novacoin-opencon");
1256 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1257 ThreadOpenConnections2(parg);
1258 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1260 catch (std::exception& e) {
1261 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1262 PrintException(&e, "ThreadOpenConnections()");
1264 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1265 PrintException(NULL, "ThreadOpenConnections()");
1267 printf("ThreadOpenConnections exited\n");
1270 void static ProcessOneShot()
1275 if (vOneShots.empty())
1277 strDest = vOneShots.front();
1278 vOneShots.pop_front();
1281 CSemaphoreGrant grant(*semOutbound, true);
1283 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1284 AddOneShot(strDest);
1288 // ppcoin: stake minter thread
1289 void static ThreadStakeMinter(void* parg)
1291 printf("ThreadStakeMinter started\n");
1292 CWallet* pwallet = (CWallet*)parg;
1295 vnThreadsRunning[THREAD_MINTER]++;
1296 StakeMiner(pwallet);
1297 vnThreadsRunning[THREAD_MINTER]--;
1299 catch (std::exception& e) {
1300 vnThreadsRunning[THREAD_MINTER]--;
1301 PrintException(&e, "ThreadStakeMinter()");
1303 vnThreadsRunning[THREAD_MINTER]--;
1304 PrintException(NULL, "ThreadStakeMinter()");
1306 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1309 void ThreadOpenConnections2(void* parg)
1311 printf("ThreadOpenConnections started\n");
1313 // Connect to specific addresses
1314 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1316 for (int64_t nLoop = 0;; nLoop++)
1319 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1322 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1323 for (int i = 0; i < 10 && i < nLoop; i++)
1334 // Initiate network connections
1335 int64_t nStart = GetTime();
1340 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1342 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1347 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1348 CSemaphoreGrant grant(*semOutbound);
1349 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1353 // Add seed nodes if IRC isn't working
1354 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1356 std::vector<CAddress> vAdd;
1357 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1359 // It'll only connect to one or two seed nodes because once it connects,
1360 // it'll get a pile of addresses with newer timestamps.
1361 // Seed nodes are given a random 'last seen time' of between one and two
1363 const int64_t nOneWeek = 7*24*60*60;
1365 memcpy(&ip, &pnSeed[i], sizeof(ip));
1366 CAddress addr(CService(ip, GetDefaultPort()));
1367 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1368 vAdd.push_back(addr);
1370 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1373 // Add Tor nodes if we have connection with onion router
1374 if (mapArgs.count("-tor"))
1376 std::vector<CAddress> vAdd;
1377 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1379 const int64_t nOneWeek = 7*24*60*60;
1380 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1381 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1382 vAdd.push_back(addr);
1384 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1388 // Choose an address to connect to based on most recently seen
1390 CAddress addrConnect;
1392 // Only connect out to one peer per network group (/16 for IPv4).
1393 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1395 set<vector<unsigned char> > setConnected;
1398 BOOST_FOREACH(CNode* pnode, vNodes) {
1399 if (!pnode->fInbound) {
1400 setConnected.insert(pnode->addr.GetGroup());
1406 int64_t nANow = GetAdjustedTime();
1411 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1412 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1414 // if we selected an invalid address, restart
1415 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1418 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1419 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1420 // already-connected network ranges, ...) before trying new addrman addresses.
1425 if (IsLimited(addr))
1428 // only consider very recently tried nodes after 30 failed attempts
1429 if (nANow - addr.nLastTry < 600 && nTries < 30)
1432 // do not allow non-default ports, unless after 50 invalid addresses selected already
1433 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1440 if (addrConnect.IsValid())
1441 OpenNetworkConnection(addrConnect, &grant);
1445 void ThreadOpenAddedConnections(void* parg)
1447 // Make this thread recognisable as the connection opening thread
1448 RenameThread("novacoin-opencon");
1452 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1453 ThreadOpenAddedConnections2(parg);
1454 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1456 catch (std::exception& e) {
1457 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1458 PrintException(&e, "ThreadOpenAddedConnections()");
1460 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1461 PrintException(NULL, "ThreadOpenAddedConnections()");
1463 printf("ThreadOpenAddedConnections exited\n");
1466 void ThreadOpenAddedConnections2(void* parg)
1468 printf("ThreadOpenAddedConnections started\n");
1471 LOCK(cs_vAddedNodes);
1472 vAddedNodes = mapMultiArgs["-addnode"];
1475 if (HaveNameProxy()) {
1477 list<string> lAddresses(0);
1479 LOCK(cs_vAddedNodes);
1480 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1481 lAddresses.push_back(strAddNode);
1483 BOOST_FOREACH(string& strAddNode, lAddresses) {
1485 CSemaphoreGrant grant(*semOutbound);
1486 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1489 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1490 Sleep(120000); // Retry every 2 minutes
1491 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1496 for (uint32_t i = 0; true; i++)
1498 list<string> lAddresses(0);
1500 LOCK(cs_vAddedNodes);
1501 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1502 lAddresses.push_back(strAddNode);
1505 list<vector<CService> > lservAddressesToAdd(0);
1506 BOOST_FOREACH(string& strAddNode, lAddresses)
1508 vector<CService> vservNode(0);
1509 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1511 lservAddressesToAdd.push_back(vservNode);
1513 LOCK(cs_setservAddNodeAddresses);
1514 BOOST_FOREACH(CService& serv, vservNode)
1515 setservAddNodeAddresses.insert(serv);
1519 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1520 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1523 BOOST_FOREACH(CNode* pnode, vNodes)
1524 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1526 BOOST_FOREACH(CService& addrNode, *(it))
1527 if (pnode->addr == addrNode)
1529 it = lservAddressesToAdd.erase(it);
1530 if(it != lservAddressesToAdd.begin())
1534 if (it == lservAddressesToAdd.end())
1538 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1540 if (vserv.size() == 0)
1542 CSemaphoreGrant grant(*semOutbound);
1543 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1550 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1551 Sleep(120000); // Retry every 2 minutes
1552 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1558 // if successful, this moves the passed grant to the constructed node
1559 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1562 // Initiate outbound network connection
1567 if (IsLocal(addrConnect) ||
1568 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1569 FindNode(addrConnect.ToStringIPPort().c_str()))
1571 if (strDest && FindNode(strDest))
1574 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1575 CNode* pnode = ConnectNode(addrConnect, strDest);
1576 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1582 grantOutbound->MoveTo(pnode->grantOutbound);
1583 pnode->fNetworkNode = true;
1585 pnode->fOneShot = true;
1590 // for now, use a very simple selection metric: the node from which we received
1592 double static NodeSyncScore(const CNode *pnode) {
1593 return -pnode->nLastRecv;
1596 void static StartSync(const vector<CNode*> &vNodes) {
1597 CNode *pnodeNewSync = NULL;
1598 double dBestScore = 0;
1600 // Iterate over all nodes
1601 BOOST_FOREACH(CNode* pnode, vNodes) {
1602 // check preconditions for allowing a sync
1603 if (!pnode->fClient && !pnode->fOneShot &&
1604 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1605 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1606 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1607 // if ok, compare node's score with the best so far
1608 double dScore = NodeSyncScore(pnode);
1609 if (pnodeNewSync == NULL || dScore > dBestScore) {
1610 pnodeNewSync = pnode;
1611 dBestScore = dScore;
1615 // if a new sync candidate was found, start sync!
1617 pnodeNewSync->fStartSync = true;
1618 pnodeSync = pnodeNewSync;
1622 void ThreadMessageHandler(void* parg)
1624 // Make this thread recognisable as the message handling thread
1625 RenameThread("novacoin-msghand");
1629 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1630 ThreadMessageHandler2(parg);
1631 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1633 catch (std::exception& e) {
1634 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1635 PrintException(&e, "ThreadMessageHandler()");
1637 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1638 PrintException(NULL, "ThreadMessageHandler()");
1640 printf("ThreadMessageHandler exited\n");
1643 void ThreadMessageHandler2(void* parg)
1645 printf("ThreadMessageHandler started\n");
1646 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1649 bool fHaveSyncNode = false;
1650 vector<CNode*> vNodesCopy;
1653 vNodesCopy = vNodes;
1654 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1656 if (pnode == pnodeSync)
1657 fHaveSyncNode = true;
1662 StartSync(vNodesCopy);
1664 // Poll the connected nodes for messages
1665 CNode* pnodeTrickle = NULL;
1666 if (!vNodesCopy.empty())
1667 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1668 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1672 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1674 ProcessMessages(pnode);
1681 TRY_LOCK(pnode->cs_vSend, lockSend);
1683 SendMessages(pnode, pnode == pnodeTrickle);
1691 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1695 // Wait and allow messages to bunch up.
1696 // Reduce vnThreadsRunning so StopNode has permission to exit while
1697 // we're sleeping, but we must always check fShutdown after doing this.
1698 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1700 if (fRequestShutdown)
1702 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1713 bool BindListenPort(const CService &addrBind, string& strError)
1719 // Initialize Windows Sockets
1721 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1722 if (ret != NO_ERROR)
1724 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1725 printf("%s\n", strError.c_str());
1730 // Create socket for listening for incoming connections
1732 struct sockaddr_storage sockaddr;
1734 struct sockaddr sockaddr;
1736 socklen_t len = sizeof(sockaddr);
1737 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1739 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1740 printf("%s\n", strError.c_str());
1744 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1745 if (hListenSocket == INVALID_SOCKET)
1747 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1748 printf("%s\n", strError.c_str());
1753 // Different way of disabling SIGPIPE on BSD
1754 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1758 // Allow binding if the port is still in TIME_WAIT state after
1759 // the program was closed and restarted. Not an issue on windows.
1760 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1765 // Set to non-blocking, incoming connections will also inherit this
1766 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1768 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1771 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1772 printf("%s\n", strError.c_str());
1777 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1778 // and enable it by default or not. Try to enable it, if possible.
1779 if (addrBind.IsIPv6()) {
1782 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1784 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1788 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1789 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1790 // this call is allowed to fail
1791 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1796 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1798 int nErr = WSAGetLastError();
1799 if (nErr == WSAEADDRINUSE)
1800 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1802 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1803 printf("%s\n", strError.c_str());
1806 printf("Bound to %s\n", addrBind.ToString().c_str());
1808 // Listen for incoming connections
1809 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1811 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1812 printf("%s\n", strError.c_str());
1816 vhListenSocket.push_back(hListenSocket);
1818 if (addrBind.IsRoutable() && fDiscover)
1819 AddLocal(addrBind, LOCAL_BIND);
1824 void static Discover()
1830 // Get local host IP
1831 char pszHostName[1000] = "";
1832 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1834 vector<CNetAddr> vaddr;
1835 if (LookupHost(pszHostName, vaddr))
1837 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1839 AddLocal(addr, LOCAL_IF);
1844 // Get local host ip
1845 struct ifaddrs* myaddrs;
1846 if (getifaddrs(&myaddrs) == 0)
1848 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1850 if (ifa->ifa_addr == NULL) continue;
1851 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1852 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1853 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1854 if (ifa->ifa_addr->sa_family == AF_INET)
1856 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1857 CNetAddr addr(s4->sin_addr);
1858 if (AddLocal(addr, LOCAL_IF))
1859 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1862 else if (ifa->ifa_addr->sa_family == AF_INET6)
1864 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1865 CNetAddr addr(s6->sin6_addr);
1866 if (AddLocal(addr, LOCAL_IF))
1867 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1871 freeifaddrs(myaddrs);
1875 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1876 if (!IsLimited(NET_IPV4))
1877 NewThread(ThreadGetMyExternalIP, NULL);
1880 void StartNode(void* parg)
1882 // Make this thread recognisable as the startup thread
1883 RenameThread("novacoin-start");
1885 if (semOutbound == NULL) {
1886 // initialize semaphore
1887 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1888 semOutbound = new CSemaphore(nMaxOutbound);
1891 if (pnodeLocalHost == NULL)
1892 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1900 if (!GetBoolArg("-dnsseed", true))
1901 printf("DNS seeding disabled\n");
1903 if (!NewThread(ThreadDNSAddressSeed, NULL))
1904 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1906 // Map ports with UPnP
1908 printf("UPNP port mapping is disabled\n");
1912 // Get addresses from IRC and advertise ours
1913 if (!GetBoolArg("-irc", true))
1914 printf("IRC seeding disabled\n");
1916 if (!NewThread(ThreadIRCSeed, NULL))
1917 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1919 // Send and receive from sockets, accept connections
1920 if (!NewThread(ThreadSocketHandler, NULL))
1921 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1923 // Initiate outbound connections from -addnode
1924 if (!NewThread(ThreadOpenAddedConnections, NULL))
1925 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1927 // Initiate outbound connections
1928 if (!NewThread(ThreadOpenConnections, NULL))
1929 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1932 if (!NewThread(ThreadMessageHandler, NULL))
1933 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1935 // Dump network addresses
1936 if (!NewThread(ThreadDumpAddress, NULL))
1937 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1939 // ppcoin: mint proof-of-stake blocks in the background
1940 if (!NewThread(ThreadStakeMinter, pwalletMain))
1941 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1946 printf("StopNode()\n");
1948 nTransactionsUpdated++;
1949 int64_t nStart = GetTime();
1952 ThreadScriptCheckQuit();
1955 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1956 semOutbound->post();
1959 int nThreadsRunning = 0;
1960 for (int n = 0; n < THREAD_MAX; n++)
1961 nThreadsRunning += vnThreadsRunning[n];
1962 if (nThreadsRunning == 0)
1964 if (GetTime() - nStart > 20)
1968 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1969 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1970 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1971 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1972 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1974 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1976 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1977 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1978 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1979 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1980 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1981 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1997 BOOST_FOREACH(CNode* pnode, vNodes)
1998 if (pnode->hSocket != INVALID_SOCKET)
1999 closesocket(pnode->hSocket);
2000 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2001 if (hListenSocket != INVALID_SOCKET)
2002 if (closesocket(hListenSocket) == SOCKET_ERROR)
2003 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2006 // Shutdown Windows Sockets
2011 instance_of_cnetcleanup;
2013 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2015 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2018 RelayTransaction(tx, hash, ss);
2021 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2023 CInv inv(MSG_TX, hash);
2026 // Expire old relay messages
2027 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2029 mapRelay.erase(vRelayExpiration.front().second);
2030 vRelayExpiration.pop_front();
2033 // Save original serialized message so newer versions are preserved
2034 mapRelay.insert(std::make_pair(inv, ss));
2035 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2038 RelayInventory(inv);
2041 void CNode::RecordBytesRecv(uint64_t bytes)
2043 LOCK(cs_totalBytesRecv);
2044 nTotalBytesRecv += bytes;
2047 void CNode::RecordBytesSent(uint64_t bytes)
2049 LOCK(cs_totalBytesSent);
2050 nTotalBytesSent += bytes;
2053 uint64_t CNode::GetTotalBytesRecv()
2055 LOCK(cs_totalBytesRecv);
2056 return nTotalBytesRecv;
2059 uint64_t CNode::GetTotalBytesSent()
2061 LOCK(cs_totalBytesSent);
2062 return nTotalBytesSent;