1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
11 #include "ui_interface.h"
18 #include <miniupnpc/miniwget.h>
19 #include <miniupnpc/miniupnpc.h>
20 #include <miniupnpc/upnpcommands.h>
21 #include <miniupnpc/upnperrors.h>
25 using namespace boost;
27 static const int MAX_OUTBOUND_CONNECTIONS = 16;
29 void ThreadMessageHandler2(void* parg);
30 void ThreadSocketHandler2(void* parg);
31 void ThreadOpenConnections2(void* parg);
32 void ThreadOpenAddedConnections2(void* parg);
34 void ThreadMapPort2(void* parg);
36 void ThreadDNSAddressSeed2(void* parg);
38 // Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
39 // Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
41 #ifndef PROTECTION_LEVEL_UNRESTRICTED
42 #define PROTECTION_LEVEL_UNRESTRICTED 10
44 #ifndef IPV6_PROTECTION_LEVEL
45 #define IPV6_PROTECTION_LEVEL 23
49 struct LocalServiceInfo {
55 // Global state variables
58 bool fDiscover = true;
59 bool fUseUPnP = false;
60 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
61 static CCriticalSection cs_mapLocalHost;
62 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
63 static bool vfReachable[NET_MAX] = {};
64 static bool vfLimited[NET_MAX] = {};
65 static CNode* pnodeLocalHost = NULL;
66 static CNode* pnodeSync = NULL;
67 CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
68 uint64_t nLocalHostNonce = 0;
69 boost::array<int, THREAD_MAX> vnThreadsRunning;
70 static std::vector<SOCKET> vhListenSocket;
73 vector<CNode*> vNodes;
74 CCriticalSection cs_vNodes;
75 map<CInv, CDataStream> mapRelay;
76 deque<pair<int64_t, CInv> > vRelayExpiration;
77 CCriticalSection cs_mapRelay;
78 map<CInv, int64_t> mapAlreadyAskedFor;
80 static deque<string> vOneShots;
81 CCriticalSection cs_vOneShots;
83 set<CNetAddr> setservAddNodeAddresses;
84 CCriticalSection cs_setservAddNodeAddresses;
86 vector<std::string> vAddedNodes;
87 CCriticalSection cs_vAddedNodes;
89 static CSemaphore *semOutbound = NULL;
91 void AddOneShot(string strDest)
94 vOneShots.push_back(strDest);
97 unsigned short GetListenPort()
99 return (unsigned short)(GetArg("-port", GetDefaultPort()));
102 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
104 // Filter out duplicate requests
105 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
107 pindexLastGetBlocksBegin = pindexBegin;
108 hashLastGetBlocksEnd = hashEnd;
110 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
113 // find 'best' local address for a particular peer
114 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
120 int nBestReachability = -1;
122 LOCK(cs_mapLocalHost);
123 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
125 int nScore = (*it).second.nScore;
126 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
127 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
129 addr = CService((*it).first, (*it).second.nPort);
130 nBestReachability = nReachability;
135 return nBestScore >= 0;
138 // get best local address for a particular peer as a CAddress
139 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
141 CAddress ret(CService("0.0.0.0",0),0);
143 if (GetLocal(addr, paddrPeer))
145 ret = CAddress(addr);
146 ret.nServices = nLocalServices;
147 ret.nTime = GetAdjustedTime();
152 bool RecvLine(SOCKET hSocket, string& strLine)
158 int nBytes = recv(hSocket, &c, 1, 0);
166 if (strLine.size() >= 9000)
169 else if (nBytes <= 0)
175 int nErr = WSAGetLastError();
176 if (nErr == WSAEMSGSIZE)
178 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
184 if (!strLine.empty())
189 printf("socket closed\n");
195 int nErr = WSAGetLastError();
196 printf("recv failed: %d\n", nErr);
203 // used when scores of local addresses may have changed
204 // pushes better local address to peers
205 void static AdvertizeLocal()
208 BOOST_FOREACH(CNode* pnode, vNodes)
210 if (pnode->fSuccessfullyConnected)
212 CAddress addrLocal = GetLocalAddress(&pnode->addr);
213 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
215 pnode->PushAddress(addrLocal);
216 pnode->addrLocal = addrLocal;
222 void SetReachable(enum Network net, bool fFlag)
224 LOCK(cs_mapLocalHost);
225 vfReachable[net] = fFlag;
226 if (net == NET_IPV6 && fFlag)
227 vfReachable[NET_IPV4] = true;
230 // learn a new local address
231 bool AddLocal(const CService& addr, int nScore)
233 if (!addr.IsRoutable())
236 if (!fDiscover && nScore < LOCAL_MANUAL)
242 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
245 LOCK(cs_mapLocalHost);
246 bool fAlready = mapLocalHost.count(addr) > 0;
247 LocalServiceInfo &info = mapLocalHost[addr];
248 if (!fAlready || nScore >= info.nScore) {
249 info.nScore = nScore + (fAlready ? 1 : 0);
250 info.nPort = addr.GetPort();
252 SetReachable(addr.GetNetwork());
260 bool AddLocal(const CNetAddr &addr, int nScore)
262 return AddLocal(CService(addr, GetListenPort()), nScore);
265 /** Make a particular network entirely off-limits (no automatic connects to it) */
266 void SetLimited(enum Network net, bool fLimited)
268 if (net == NET_UNROUTABLE)
270 LOCK(cs_mapLocalHost);
271 vfLimited[net] = fLimited;
274 bool IsLimited(enum Network net)
276 LOCK(cs_mapLocalHost);
277 return vfLimited[net];
280 bool IsLimited(const CNetAddr &addr)
282 return IsLimited(addr.GetNetwork());
285 /** vote for a local address */
286 bool SeenLocal(const CService& addr)
289 LOCK(cs_mapLocalHost);
290 if (mapLocalHost.count(addr) == 0)
292 mapLocalHost[addr].nScore++;
300 /** check whether a given address is potentially local */
301 bool IsLocal(const CService& addr)
303 LOCK(cs_mapLocalHost);
304 return mapLocalHost.count(addr) > 0;
307 /** check whether a given address is in a network we can probably connect to */
308 bool IsReachable(const CNetAddr& addr)
310 LOCK(cs_mapLocalHost);
311 enum Network net = addr.GetNetwork();
312 return vfReachable[net] && !vfLimited[net];
315 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
317 // We now get our external IP from the IRC server first and only use this as a backup
318 bool GetMyExternalIP(CNetAddr& ipRet)
320 struct sockaddr_in mapped;
321 uint64_t rnd = std::numeric_limits<uint64_t>::max();
323 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
325 ipRet = CNetAddr(mapped.sin_addr);
326 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
332 void ThreadGetMyExternalIP(void* parg)
334 // Make this thread recognisable as the external IP detection thread
335 RenameThread("novacoin-ext-ip");
337 CNetAddr addrLocalHost;
338 if (GetMyExternalIP(addrLocalHost))
340 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
341 AddLocal(addrLocalHost, LOCAL_HTTP);
349 void AddressCurrentlyConnected(const CService& addr)
351 addrman.Connected(addr);
357 uint64_t CNode::nTotalBytesRecv = 0;
358 uint64_t CNode::nTotalBytesSent = 0;
359 CCriticalSection CNode::cs_totalBytesRecv;
360 CCriticalSection CNode::cs_totalBytesSent;
362 CNode* FindNode(const CNetAddr& ip)
365 BOOST_FOREACH(CNode* pnode, vNodes)
366 if ((CNetAddr)pnode->addr == ip)
371 CNode* FindNode(std::string addrName)
374 BOOST_FOREACH(CNode* pnode, vNodes)
375 if (pnode->addrName == addrName)
380 CNode* FindNode(const CService& addr)
383 BOOST_FOREACH(CNode* pnode, vNodes)
384 if ((CService)pnode->addr == addr)
389 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
391 if (pszDest == NULL) {
392 if (IsLocal(addrConnect))
395 // Look for an existing connection
396 CNode* pnode = FindNode((CService)addrConnect);
400 pnode->AddRef(nTimeout);
409 printf("trying connection %s lastseen=%.1fhrs\n",
410 pszDest ? pszDest : addrConnect.ToString().c_str(),
411 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
415 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
417 addrman.Attempt(addrConnect);
420 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
422 // Set to non-blocking
425 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
426 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
428 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
429 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
433 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
435 pnode->AddRef(nTimeout);
441 vNodes.push_back(pnode);
444 pnode->nTimeConnected = GetTime();
453 void CNode::CloseSocketDisconnect()
456 if (hSocket != INVALID_SOCKET)
458 printf("disconnecting node %s\n", addrName.c_str());
459 closesocket(hSocket);
460 hSocket = INVALID_SOCKET;
464 // in case this fails, we'll empty the recv buffer when the CNode is deleted
465 TRY_LOCK(cs_vRecv, lockRecv);
469 // if this was the sync node, we'll need a new one
470 if (this == pnodeSync)
474 void CNode::Cleanup()
479 void CNode::PushVersion()
481 /// when NTP implemented, change to just nTime = GetAdjustedTime()
482 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
483 CAddress addrYou, addrMe;
485 bool fHidden = false;
487 if (mapArgs.count("-torname")) {
488 // Our hidden service address
489 CService addrTorName(mapArgs["-torname"], GetListenPort());
491 if (addrTorName.IsValid()) {
493 addrMe = CAddress(addrTorName);
500 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
501 addrMe = GetLocalAddress(&addr);
504 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
505 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());
506 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
507 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
514 std::map<CNetAddr, int64_t> CNode::setBanned;
515 CCriticalSection CNode::cs_setBanned;
517 void CNode::ClearBanned()
522 bool CNode::IsBanned(CNetAddr ip)
524 bool fResult = false;
527 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
528 if (i != setBanned.end())
530 int64_t t = (*i).second;
538 bool CNode::Misbehaving(int howmuch)
542 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
546 nMisbehavior += howmuch;
547 if (nMisbehavior >= GetArg("-banscore", 100))
549 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
550 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
553 if (setBanned[addr] < banTime)
554 setBanned[addr] = banTime;
556 CloseSocketDisconnect();
559 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
564 #define X(name) stats.name = name
565 void CNode::copyStats(CNodeStats &stats)
580 stats.fSyncNode = (this == pnodeSync);
593 void ThreadSocketHandler(void* parg)
595 // Make this thread recognisable as the networking thread
596 RenameThread("novacoin-net");
600 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
601 ThreadSocketHandler2(parg);
602 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
604 catch (std::exception& e) {
605 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
606 PrintException(&e, "ThreadSocketHandler()");
608 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
609 throw; // support pthread_cancel()
611 printf("ThreadSocketHandler exited\n");
614 static list<CNode*> vNodesDisconnected;
616 void ThreadSocketHandler2(void* parg)
618 printf("ThreadSocketHandler started\n");
619 unsigned int nPrevNodeCount = 0;
627 // Disconnect unused nodes
628 vector<CNode*> vNodesCopy = vNodes;
629 BOOST_FOREACH(CNode* pnode, vNodesCopy)
631 if (pnode->fDisconnect ||
632 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
634 // remove from vNodes
635 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
637 // release outbound grant (if any)
638 pnode->grantOutbound.Release();
640 // close socket and cleanup
641 pnode->CloseSocketDisconnect();
644 // hold in disconnected pool until all refs are released
645 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
646 if (pnode->fNetworkNode || pnode->fInbound)
648 vNodesDisconnected.push_back(pnode);
652 // Delete disconnected nodes
653 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
654 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
656 // wait until threads are done using it
657 if (pnode->GetRefCount() <= 0)
659 bool fDelete = false;
661 TRY_LOCK(pnode->cs_vSend, lockSend);
664 TRY_LOCK(pnode->cs_vRecv, lockRecv);
667 TRY_LOCK(pnode->cs_mapRequests, lockReq);
670 TRY_LOCK(pnode->cs_inventory, lockInv);
679 vNodesDisconnected.remove(pnode);
685 if (vNodes.size() != nPrevNodeCount)
687 nPrevNodeCount = vNodes.size();
688 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
693 // Find which sockets have data to receive
695 struct timeval timeout;
697 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
704 FD_ZERO(&fdsetError);
705 SOCKET hSocketMax = 0;
706 bool have_fds = false;
708 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
709 FD_SET(hListenSocket, &fdsetRecv);
710 hSocketMax = max(hSocketMax, hListenSocket);
715 BOOST_FOREACH(CNode* pnode, vNodes)
717 if (pnode->hSocket == INVALID_SOCKET)
719 FD_SET(pnode->hSocket, &fdsetRecv);
720 FD_SET(pnode->hSocket, &fdsetError);
721 hSocketMax = max(hSocketMax, pnode->hSocket);
724 TRY_LOCK(pnode->cs_vSend, lockSend);
725 if (lockSend && !pnode->vSend.empty())
726 FD_SET(pnode->hSocket, &fdsetSend);
731 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
732 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
733 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
734 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
737 if (nSelect == SOCKET_ERROR)
741 int nErr = WSAGetLastError();
742 printf("socket select error %d\n", nErr);
743 for (unsigned int i = 0; i <= hSocketMax; i++)
744 FD_SET(i, &fdsetRecv);
747 FD_ZERO(&fdsetError);
748 Sleep(timeout.tv_usec/1000);
753 // Accept new connections
755 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
756 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
759 struct sockaddr_storage sockaddr;
761 struct sockaddr sockaddr;
763 socklen_t len = sizeof(sockaddr);
764 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
768 if (hSocket != INVALID_SOCKET)
769 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
770 printf("Warning: Unknown socket family\n");
774 BOOST_FOREACH(CNode* pnode, vNodes)
779 if (hSocket == INVALID_SOCKET)
781 int nErr = WSAGetLastError();
782 if (nErr != WSAEWOULDBLOCK)
783 printf("socket error accept failed: %d\n", nErr);
785 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
788 LOCK(cs_setservAddNodeAddresses);
789 if (!setservAddNodeAddresses.count(addr))
790 closesocket(hSocket);
793 else if (CNode::IsBanned(addr))
795 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
796 closesocket(hSocket);
800 printf("accepted connection %s\n", addr.ToString().c_str());
801 CNode* pnode = new CNode(hSocket, addr, "", true);
805 vNodes.push_back(pnode);
812 // Service each socket
814 vector<CNode*> vNodesCopy;
818 BOOST_FOREACH(CNode* pnode, vNodesCopy)
821 BOOST_FOREACH(CNode* pnode, vNodesCopy)
829 if (pnode->hSocket == INVALID_SOCKET)
831 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
833 TRY_LOCK(pnode->cs_vRecv, lockRecv);
836 CDataStream& vRecv = pnode->vRecv;
837 uint64_t nPos = vRecv.size();
839 if (nPos > ReceiveBufferSize()) {
840 if (!pnode->fDisconnect)
841 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
842 pnode->CloseSocketDisconnect();
845 // typical socket buffer is 8K-64K
846 char pchBuf[0x10000];
847 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
850 vRecv.resize(nPos + nBytes);
851 memcpy(&vRecv[nPos], pchBuf, nBytes);
852 pnode->nLastRecv = GetTime();
853 pnode->nRecvBytes += nBytes;
854 pnode->RecordBytesRecv(nBytes);
856 else if (nBytes == 0)
858 // socket closed gracefully
859 if (!pnode->fDisconnect)
860 printf("socket closed\n");
861 pnode->CloseSocketDisconnect();
866 int nErr = WSAGetLastError();
867 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
869 if (!pnode->fDisconnect)
870 printf("socket recv error %d\n", nErr);
871 pnode->CloseSocketDisconnect();
881 if (pnode->hSocket == INVALID_SOCKET)
883 if (FD_ISSET(pnode->hSocket, &fdsetSend))
885 TRY_LOCK(pnode->cs_vSend, lockSend);
888 CDataStream& vSend = pnode->vSend;
891 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
894 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
895 pnode->nLastSend = GetTime();
896 pnode->nSendBytes += nBytes;
897 pnode->RecordBytesSent(nBytes);
902 int nErr = WSAGetLastError();
903 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
905 printf("socket send error %d\n", nErr);
906 pnode->CloseSocketDisconnect();
914 // Inactivity checking
916 if (pnode->vSend.empty())
917 pnode->nLastSendEmpty = GetTime();
918 if (GetTime() - pnode->nTimeConnected > 60)
920 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
922 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
923 pnode->fDisconnect = true;
925 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
927 printf("socket not sending\n");
928 pnode->fDisconnect = true;
930 else if (GetTime() - pnode->nLastRecv > 90*60)
932 printf("socket inactivity timeout\n");
933 pnode->fDisconnect = true;
939 BOOST_FOREACH(CNode* pnode, vNodesCopy)
956 void ThreadMapPort(void* parg)
958 // Make this thread recognisable as the UPnP thread
959 RenameThread("novacoin-UPnP");
963 vnThreadsRunning[THREAD_UPNP]++;
964 ThreadMapPort2(parg);
965 vnThreadsRunning[THREAD_UPNP]--;
967 catch (std::exception& e) {
968 vnThreadsRunning[THREAD_UPNP]--;
969 PrintException(&e, "ThreadMapPort()");
971 vnThreadsRunning[THREAD_UPNP]--;
972 PrintException(NULL, "ThreadMapPort()");
974 printf("ThreadMapPort exited\n");
977 void ThreadMapPort2(void* parg)
979 printf("ThreadMapPort started\n");
981 std::string port = strprintf("%u", GetListenPort());
982 const char * multicastif = 0;
983 const char * minissdpdpath = 0;
984 struct UPNPDev * devlist = 0;
987 #ifndef UPNPDISCOVER_SUCCESS
989 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
993 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
996 struct UPNPUrls urls;
997 struct IGDdatas data;
1000 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1004 char externalIPAddress[40];
1005 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
1006 if(r != UPNPCOMMAND_SUCCESS)
1007 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
1010 if(externalIPAddress[0])
1012 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1013 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1016 printf("UPnP: GetExternalIPAddress failed.\n");
1020 string strDesc = "NovaCoin " + FormatFullVersion();
1021 #ifndef UPNPDISCOVER_SUCCESS
1023 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1024 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1027 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1028 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1031 if(r!=UPNPCOMMAND_SUCCESS)
1032 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1033 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1035 printf("UPnP Port Mapping successful.\n");
1039 if (fShutdown || !fUseUPnP)
1041 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1042 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1043 freeUPNPDevlist(devlist); devlist = 0;
1044 FreeUPNPUrls(&urls);
1047 if (i % 600 == 0) // Refresh every 20 minutes
1049 #ifndef UPNPDISCOVER_SUCCESS
1051 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1052 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1055 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1056 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1059 if(r!=UPNPCOMMAND_SUCCESS)
1060 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1061 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1063 printf("UPnP Port Mapping successful.\n");;
1069 printf("No valid UPnP IGDs found\n");
1070 freeUPNPDevlist(devlist); devlist = 0;
1072 FreeUPNPUrls(&urls);
1075 if (fShutdown || !fUseUPnP)
1084 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1086 if (!NewThread(ThreadMapPort, NULL))
1087 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1093 // Intentionally left blank.
1106 // Each pair gives a source name and a seed name.
1107 // The first name is used as information source for addrman.
1108 // The second name should resolve to a list of seed addresses.
1109 static const char *strDNSSeed[][2] = {
1110 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1111 {"novacoin.ru", "dnsseed.novacoin.ru"},
1112 {"novacoin.ru", "testseed.novacoin.ru"},
1113 {"novaco.in", "dnsseed.novaco.in"},
1116 void ThreadDNSAddressSeed(void* parg)
1118 // Make this thread recognisable as the DNS seeding thread
1119 RenameThread("novacoin-dnsseed");
1123 vnThreadsRunning[THREAD_DNSSEED]++;
1124 ThreadDNSAddressSeed2(parg);
1125 vnThreadsRunning[THREAD_DNSSEED]--;
1127 catch (std::exception& e) {
1128 vnThreadsRunning[THREAD_DNSSEED]--;
1129 PrintException(&e, "ThreadDNSAddressSeed()");
1131 vnThreadsRunning[THREAD_DNSSEED]--;
1132 throw; // support pthread_cancel()
1134 printf("ThreadDNSAddressSeed exited\n");
1137 void ThreadDNSAddressSeed2(void* parg)
1139 printf("ThreadDNSAddressSeed started\n");
1144 printf("Loading addresses from DNS seeds (could take a while)\n");
1146 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1147 if (HaveNameProxy()) {
1148 AddOneShot(strDNSSeed[seed_idx][1]);
1150 vector<CNetAddr> vaddr;
1151 vector<CAddress> vAdd;
1152 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1154 BOOST_FOREACH(CNetAddr& ip, vaddr)
1156 int nOneDay = 24*3600;
1157 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1158 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1159 vAdd.push_back(addr);
1163 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1168 printf("%d addresses found from DNS seeds\n", found);
1184 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1185 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1186 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1187 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1188 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1189 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1190 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1191 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1192 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1193 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1194 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1195 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1196 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1197 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1198 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1199 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1203 const char* pchTorSeed[] =
1205 "seedp4knqnoei57u.onion",
1206 "seedr3hhlepyi7fd.onion",
1207 "seed3uuomkclbiz4.onion",
1208 "seedeh7qck3ouff5.onion",
1209 "5rg3vq4jagckeckf.onion",
1210 "seedt3sraf53ajiy.onion",
1211 "seedg4qyccsg42oq.onion",
1212 "novaqrtoywpg7jly.onion",
1213 "seed3d5wolqbgrcb.onion",
1214 "seed24u5dwph3qw4.onion",
1215 "mj26ulzbs2oskgym.onion",
1216 "eqon4usunavt76m7.onion",
1219 void DumpAddresses()
1221 int64_t nStart = GetTimeMillis();
1226 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1227 addrman.size(), GetTimeMillis() - nStart);
1230 void ThreadDumpAddress2(void* parg)
1232 printf("ThreadDumpAddress started\n");
1234 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1238 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1240 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1242 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1245 void ThreadDumpAddress(void* parg)
1247 // Make this thread recognisable as the address dumping thread
1248 RenameThread("novacoin-adrdump");
1252 ThreadDumpAddress2(parg);
1254 catch (std::exception& e) {
1255 PrintException(&e, "ThreadDumpAddress()");
1257 printf("ThreadDumpAddress exited\n");
1260 void ThreadOpenConnections(void* parg)
1262 // Make this thread recognisable as the connection opening thread
1263 RenameThread("novacoin-opencon");
1267 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1268 ThreadOpenConnections2(parg);
1269 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1271 catch (std::exception& e) {
1272 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1273 PrintException(&e, "ThreadOpenConnections()");
1275 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1276 PrintException(NULL, "ThreadOpenConnections()");
1278 printf("ThreadOpenConnections exited\n");
1281 void static ProcessOneShot()
1286 if (vOneShots.empty())
1288 strDest = vOneShots.front();
1289 vOneShots.pop_front();
1292 CSemaphoreGrant grant(*semOutbound, true);
1294 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1295 AddOneShot(strDest);
1299 // ppcoin: stake minter thread
1300 void static ThreadStakeMinter(void* parg)
1302 printf("ThreadStakeMinter started\n");
1303 CWallet* pwallet = (CWallet*)parg;
1306 vnThreadsRunning[THREAD_MINTER]++;
1307 StakeMiner(pwallet);
1308 vnThreadsRunning[THREAD_MINTER]--;
1310 catch (std::exception& e) {
1311 vnThreadsRunning[THREAD_MINTER]--;
1312 PrintException(&e, "ThreadStakeMinter()");
1314 vnThreadsRunning[THREAD_MINTER]--;
1315 PrintException(NULL, "ThreadStakeMinter()");
1317 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1320 void ThreadOpenConnections2(void* parg)
1322 printf("ThreadOpenConnections started\n");
1324 // Connect to specific addresses
1325 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1327 for (int64_t nLoop = 0;; nLoop++)
1330 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1333 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1334 for (int i = 0; i < 10 && i < nLoop; i++)
1345 // Initiate network connections
1346 int64_t nStart = GetTime();
1351 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1353 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1358 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1359 CSemaphoreGrant grant(*semOutbound);
1360 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1364 // Add seed nodes if IRC isn't working
1365 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1367 std::vector<CAddress> vAdd;
1368 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1370 // It'll only connect to one or two seed nodes because once it connects,
1371 // it'll get a pile of addresses with newer timestamps.
1372 // Seed nodes are given a random 'last seen time' of between one and two
1374 const int64_t nOneWeek = 7*24*60*60;
1376 memcpy(&ip, &pnSeed[i], sizeof(ip));
1377 CAddress addr(CService(ip, GetDefaultPort()));
1378 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1379 vAdd.push_back(addr);
1381 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1384 // Add Tor nodes if we have connection with onion router
1385 if (mapArgs.count("-tor"))
1387 std::vector<CAddress> vAdd;
1388 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1390 const int64_t nOneWeek = 7*24*60*60;
1391 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1392 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1393 vAdd.push_back(addr);
1395 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1399 // Choose an address to connect to based on most recently seen
1401 CAddress addrConnect;
1403 // Only connect out to one peer per network group (/16 for IPv4).
1404 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1406 set<vector<unsigned char> > setConnected;
1409 BOOST_FOREACH(CNode* pnode, vNodes) {
1410 if (!pnode->fInbound) {
1411 setConnected.insert(pnode->addr.GetGroup());
1417 int64_t nANow = GetAdjustedTime();
1422 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1423 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1425 // if we selected an invalid address, restart
1426 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1429 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1430 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1431 // already-connected network ranges, ...) before trying new addrman addresses.
1436 if (IsLimited(addr))
1439 // only consider very recently tried nodes after 30 failed attempts
1440 if (nANow - addr.nLastTry < 600 && nTries < 30)
1443 // do not allow non-default ports, unless after 50 invalid addresses selected already
1444 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1451 if (addrConnect.IsValid())
1452 OpenNetworkConnection(addrConnect, &grant);
1456 void ThreadOpenAddedConnections(void* parg)
1458 // Make this thread recognisable as the connection opening thread
1459 RenameThread("novacoin-opencon");
1463 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1464 ThreadOpenAddedConnections2(parg);
1465 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1467 catch (std::exception& e) {
1468 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1469 PrintException(&e, "ThreadOpenAddedConnections()");
1471 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1472 PrintException(NULL, "ThreadOpenAddedConnections()");
1474 printf("ThreadOpenAddedConnections exited\n");
1477 void ThreadOpenAddedConnections2(void* parg)
1479 printf("ThreadOpenAddedConnections started\n");
1482 LOCK(cs_vAddedNodes);
1483 vAddedNodes = mapMultiArgs["-addnode"];
1486 if (HaveNameProxy()) {
1488 list<string> lAddresses(0);
1490 LOCK(cs_vAddedNodes);
1491 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1492 lAddresses.push_back(strAddNode);
1494 BOOST_FOREACH(string& strAddNode, lAddresses) {
1496 CSemaphoreGrant grant(*semOutbound);
1497 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1500 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1501 Sleep(120000); // Retry every 2 minutes
1502 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1507 for (uint32_t i = 0; true; i++)
1509 list<string> lAddresses(0);
1511 LOCK(cs_vAddedNodes);
1512 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1513 lAddresses.push_back(strAddNode);
1516 list<vector<CService> > lservAddressesToAdd(0);
1517 BOOST_FOREACH(string& strAddNode, lAddresses)
1519 vector<CService> vservNode(0);
1520 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1522 lservAddressesToAdd.push_back(vservNode);
1524 LOCK(cs_setservAddNodeAddresses);
1525 BOOST_FOREACH(CService& serv, vservNode)
1526 setservAddNodeAddresses.insert(serv);
1530 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1531 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1534 BOOST_FOREACH(CNode* pnode, vNodes)
1535 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1537 BOOST_FOREACH(CService& addrNode, *(it))
1538 if (pnode->addr == addrNode)
1540 it = lservAddressesToAdd.erase(it);
1541 if(it != lservAddressesToAdd.begin())
1545 if (it == lservAddressesToAdd.end())
1549 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1551 if (vserv.size() == 0)
1553 CSemaphoreGrant grant(*semOutbound);
1554 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1561 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1562 Sleep(120000); // Retry every 2 minutes
1563 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1569 // if successful, this moves the passed grant to the constructed node
1570 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1573 // Initiate outbound network connection
1578 if (IsLocal(addrConnect) ||
1579 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1580 FindNode(addrConnect.ToStringIPPort().c_str()))
1582 if (strDest && FindNode(strDest))
1585 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1586 CNode* pnode = ConnectNode(addrConnect, strDest);
1587 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1593 grantOutbound->MoveTo(pnode->grantOutbound);
1594 pnode->fNetworkNode = true;
1596 pnode->fOneShot = true;
1601 // for now, use a very simple selection metric: the node from which we received
1603 double static NodeSyncScore(const CNode *pnode) {
1604 return -pnode->nLastRecv;
1607 void static StartSync(const vector<CNode*> &vNodes) {
1608 CNode *pnodeNewSync = NULL;
1609 double dBestScore = 0;
1611 // Iterate over all nodes
1612 BOOST_FOREACH(CNode* pnode, vNodes) {
1613 // check preconditions for allowing a sync
1614 if (!pnode->fClient && !pnode->fOneShot &&
1615 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1616 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1617 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1618 // if ok, compare node's score with the best so far
1619 double dScore = NodeSyncScore(pnode);
1620 if (pnodeNewSync == NULL || dScore > dBestScore) {
1621 pnodeNewSync = pnode;
1622 dBestScore = dScore;
1626 // if a new sync candidate was found, start sync!
1628 pnodeNewSync->fStartSync = true;
1629 pnodeSync = pnodeNewSync;
1633 void ThreadMessageHandler(void* parg)
1635 // Make this thread recognisable as the message handling thread
1636 RenameThread("novacoin-msghand");
1640 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1641 ThreadMessageHandler2(parg);
1642 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1644 catch (std::exception& e) {
1645 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1646 PrintException(&e, "ThreadMessageHandler()");
1648 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1649 PrintException(NULL, "ThreadMessageHandler()");
1651 printf("ThreadMessageHandler exited\n");
1654 void ThreadMessageHandler2(void* parg)
1656 printf("ThreadMessageHandler started\n");
1657 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1660 bool fHaveSyncNode = false;
1661 vector<CNode*> vNodesCopy;
1664 vNodesCopy = vNodes;
1665 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1667 if (pnode == pnodeSync)
1668 fHaveSyncNode = true;
1673 StartSync(vNodesCopy);
1675 // Poll the connected nodes for messages
1676 CNode* pnodeTrickle = NULL;
1677 if (!vNodesCopy.empty())
1678 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1679 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1683 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1685 ProcessMessages(pnode);
1692 TRY_LOCK(pnode->cs_vSend, lockSend);
1694 SendMessages(pnode, pnode == pnodeTrickle);
1702 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1706 // Wait and allow messages to bunch up.
1707 // Reduce vnThreadsRunning so StopNode has permission to exit while
1708 // we're sleeping, but we must always check fShutdown after doing this.
1709 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1711 if (fRequestShutdown)
1713 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1724 bool BindListenPort(const CService &addrBind, string& strError)
1730 // Initialize Windows Sockets
1732 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1733 if (ret != NO_ERROR)
1735 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1736 printf("%s\n", strError.c_str());
1741 // Create socket for listening for incoming connections
1743 struct sockaddr_storage sockaddr;
1745 struct sockaddr sockaddr;
1747 socklen_t len = sizeof(sockaddr);
1748 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1750 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1751 printf("%s\n", strError.c_str());
1755 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1756 if (hListenSocket == INVALID_SOCKET)
1758 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1759 printf("%s\n", strError.c_str());
1765 // Different way of disabling SIGPIPE on BSD
1766 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1768 // Allow binding if the port is still in TIME_WAIT state after
1769 // the program was closed and restarted. Not an issue on windows!
1770 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1774 // Set to non-blocking, incoming connections will also inherit this
1775 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1777 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1780 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1781 printf("%s\n", strError.c_str());
1786 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1787 // and enable it by default or not. Try to enable it, if possible.
1788 if (addrBind.IsIPv6()) {
1791 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1793 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1797 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1798 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1803 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1805 int nErr = WSAGetLastError();
1806 if (nErr == WSAEADDRINUSE)
1807 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1809 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1810 printf("%s\n", strError.c_str());
1811 closesocket(hListenSocket);
1814 printf("Bound to %s\n", addrBind.ToString().c_str());
1816 // Listen for incoming connections
1817 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1819 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1820 printf("%s\n", strError.c_str());
1821 closesocket(hListenSocket);
1825 vhListenSocket.push_back(hListenSocket);
1827 if (addrBind.IsRoutable() && fDiscover)
1828 AddLocal(addrBind, LOCAL_BIND);
1833 void static Discover()
1839 // Get local host IP
1840 char pszHostName[1000] = "";
1841 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1843 vector<CNetAddr> vaddr;
1844 if (LookupHost(pszHostName, vaddr))
1846 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1848 AddLocal(addr, LOCAL_IF);
1853 // Get local host ip
1854 struct ifaddrs* myaddrs;
1855 if (getifaddrs(&myaddrs) == 0)
1857 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1859 if (ifa->ifa_addr == NULL) continue;
1860 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1861 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1862 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1863 if (ifa->ifa_addr->sa_family == AF_INET)
1865 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1866 CNetAddr addr(s4->sin_addr);
1867 if (AddLocal(addr, LOCAL_IF))
1868 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1871 else if (ifa->ifa_addr->sa_family == AF_INET6)
1873 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1874 CNetAddr addr(s6->sin6_addr);
1875 if (AddLocal(addr, LOCAL_IF))
1876 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1880 freeifaddrs(myaddrs);
1884 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1885 if (!IsLimited(NET_IPV4))
1886 NewThread(ThreadGetMyExternalIP, NULL);
1889 void StartNode(void* parg)
1891 // Make this thread recognisable as the startup thread
1892 RenameThread("novacoin-start");
1894 if (semOutbound == NULL) {
1895 // initialize semaphore
1896 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1897 semOutbound = new CSemaphore(nMaxOutbound);
1900 if (pnodeLocalHost == NULL)
1901 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1909 if (!GetBoolArg("-dnsseed", true))
1910 printf("DNS seeding disabled\n");
1912 if (!NewThread(ThreadDNSAddressSeed, NULL))
1913 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1915 // Map ports with UPnP
1917 printf("UPNP port mapping is disabled\n");
1921 // Get addresses from IRC and advertise ours
1922 if (!GetBoolArg("-irc", true))
1923 printf("IRC seeding disabled\n");
1925 if (!NewThread(ThreadIRCSeed, NULL))
1926 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1928 // Send and receive from sockets, accept connections
1929 if (!NewThread(ThreadSocketHandler, NULL))
1930 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1932 // Initiate outbound connections from -addnode
1933 if (!NewThread(ThreadOpenAddedConnections, NULL))
1934 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1936 // Initiate outbound connections
1937 if (!NewThread(ThreadOpenConnections, NULL))
1938 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1941 if (!NewThread(ThreadMessageHandler, NULL))
1942 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1944 // Dump network addresses
1945 if (!NewThread(ThreadDumpAddress, NULL))
1946 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1948 // ppcoin: mint proof-of-stake blocks in the background
1949 if (!NewThread(ThreadStakeMinter, pwalletMain))
1950 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1955 printf("StopNode()\n");
1957 nTransactionsUpdated++;
1958 int64_t nStart = GetTime();
1961 ThreadScriptCheckQuit();
1964 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1965 semOutbound->post();
1968 int nThreadsRunning = 0;
1969 for (int n = 0; n < THREAD_MAX; n++)
1970 nThreadsRunning += vnThreadsRunning[n];
1971 if (nThreadsRunning == 0)
1973 if (GetTime() - nStart > 20)
1977 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1978 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1979 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1980 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1981 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1983 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1985 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1986 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1987 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1988 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1989 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1990 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2007 BOOST_FOREACH(CNode* pnode, vNodes)
2008 if (pnode->hSocket != INVALID_SOCKET)
2009 closesocket(pnode->hSocket);
2010 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2011 if (hListenSocket != INVALID_SOCKET)
2012 if (closesocket(hListenSocket) == SOCKET_ERROR)
2013 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2015 // clean up some globals (to help leak detection)
2016 BOOST_FOREACH(CNode *pnode, vNodes)
2018 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
2021 vNodesDisconnected.clear();
2024 delete pnodeLocalHost;
2025 pnodeLocalHost = NULL;
2028 // Shutdown Windows Sockets
2033 instance_of_cnetcleanup;
2035 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2037 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2040 RelayTransaction(tx, hash, ss);
2043 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2045 CInv inv(MSG_TX, hash);
2048 // Expire old relay messages
2049 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2051 mapRelay.erase(vRelayExpiration.front().second);
2052 vRelayExpiration.pop_front();
2055 // Save original serialized message so newer versions are preserved
2056 mapRelay.insert(std::make_pair(inv, ss));
2057 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2060 RelayInventory(inv);
2063 void CNode::RecordBytesRecv(uint64_t bytes)
2065 LOCK(cs_totalBytesRecv);
2066 nTotalBytesRecv += bytes;
2069 void CNode::RecordBytesSent(uint64_t bytes)
2071 LOCK(cs_totalBytesSent);
2072 nTotalBytesSent += bytes;
2075 uint64_t CNode::GetTotalBytesRecv()
2077 LOCK(cs_totalBytesRecv);
2078 return nTotalBytesRecv;
2081 uint64_t CNode::GetTotalBytesSent()
2083 LOCK(cs_totalBytesSent);
2084 return nTotalBytesSent;