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", nPortZero), 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", nPortZero), 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 int64_t nTime = GetAdjustedTime();
482 CAddress addrYou, addrMe;
484 bool fHidden = false;
486 if (mapArgs.count("-torname")) {
487 // Our hidden service address
488 CService addrTorName(mapArgs["-torname"], GetListenPort());
490 if (addrTorName.IsValid()) {
492 addrMe = CAddress(addrTorName);
499 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
500 addrMe = GetLocalAddress(&addr);
503 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
504 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());
505 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
506 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
513 std::map<CNetAddr, int64_t> CNode::setBanned;
514 CCriticalSection CNode::cs_setBanned;
516 void CNode::ClearBanned()
521 bool CNode::IsBanned(CNetAddr ip)
523 bool fResult = false;
526 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
527 if (i != setBanned.end())
529 int64_t t = (*i).second;
537 bool CNode::Misbehaving(int howmuch)
541 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
545 nMisbehavior += howmuch;
546 if (nMisbehavior >= GetArg("-banscore", 100))
548 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
549 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
552 if (setBanned[addr] < banTime)
553 setBanned[addr] = banTime;
555 CloseSocketDisconnect();
558 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
563 #define X(name) stats.name = name
564 void CNode::copyStats(CNodeStats &stats)
579 stats.fSyncNode = (this == pnodeSync);
592 void ThreadSocketHandler(void* parg)
594 // Make this thread recognisable as the networking thread
595 RenameThread("novacoin-net");
599 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
600 ThreadSocketHandler2(parg);
601 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
603 catch (std::exception& e) {
604 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
605 PrintException(&e, "ThreadSocketHandler()");
607 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
608 throw; // support pthread_cancel()
610 printf("ThreadSocketHandler exited\n");
613 static list<CNode*> vNodesDisconnected;
615 void ThreadSocketHandler2(void* parg)
617 printf("ThreadSocketHandler started\n");
618 unsigned int nPrevNodeCount = 0;
626 // Disconnect unused nodes
627 vector<CNode*> vNodesCopy = vNodes;
628 BOOST_FOREACH(CNode* pnode, vNodesCopy)
630 if (pnode->fDisconnect ||
631 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
633 // remove from vNodes
634 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
636 // release outbound grant (if any)
637 pnode->grantOutbound.Release();
639 // close socket and cleanup
640 pnode->CloseSocketDisconnect();
643 // hold in disconnected pool until all refs are released
644 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
645 if (pnode->fNetworkNode || pnode->fInbound)
647 vNodesDisconnected.push_back(pnode);
651 // Delete disconnected nodes
652 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
653 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
655 // wait until threads are done using it
656 if (pnode->GetRefCount() <= 0)
658 bool fDelete = false;
660 TRY_LOCK(pnode->cs_vSend, lockSend);
663 TRY_LOCK(pnode->cs_vRecv, lockRecv);
666 TRY_LOCK(pnode->cs_mapRequests, lockReq);
669 TRY_LOCK(pnode->cs_inventory, lockInv);
678 vNodesDisconnected.remove(pnode);
684 if (vNodes.size() != nPrevNodeCount)
686 nPrevNodeCount = vNodes.size();
687 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
692 // Find which sockets have data to receive
694 struct timeval timeout;
696 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
703 FD_ZERO(&fdsetError);
704 SOCKET hSocketMax = 0;
705 bool have_fds = false;
707 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
708 FD_SET(hListenSocket, &fdsetRecv);
709 hSocketMax = max(hSocketMax, hListenSocket);
714 BOOST_FOREACH(CNode* pnode, vNodes)
716 if (pnode->hSocket == INVALID_SOCKET)
718 FD_SET(pnode->hSocket, &fdsetRecv);
719 FD_SET(pnode->hSocket, &fdsetError);
720 hSocketMax = max(hSocketMax, pnode->hSocket);
723 TRY_LOCK(pnode->cs_vSend, lockSend);
724 if (lockSend && !pnode->vSend.empty())
725 FD_SET(pnode->hSocket, &fdsetSend);
730 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
731 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
732 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
733 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
736 if (nSelect == SOCKET_ERROR)
740 int nErr = WSAGetLastError();
741 printf("socket select error %d\n", nErr);
742 for (unsigned int i = 0; i <= hSocketMax; i++)
743 FD_SET(i, &fdsetRecv);
746 FD_ZERO(&fdsetError);
747 Sleep(timeout.tv_usec/1000);
752 // Accept new connections
754 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
755 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
758 struct sockaddr_storage sockaddr;
760 struct sockaddr sockaddr;
762 socklen_t len = sizeof(sockaddr);
763 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
767 if (hSocket != INVALID_SOCKET)
768 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
769 printf("Warning: Unknown socket family\n");
773 BOOST_FOREACH(CNode* pnode, vNodes)
778 if (hSocket == INVALID_SOCKET)
780 int nErr = WSAGetLastError();
781 if (nErr != WSAEWOULDBLOCK)
782 printf("socket error accept failed: %d\n", nErr);
784 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
787 LOCK(cs_setservAddNodeAddresses);
788 if (!setservAddNodeAddresses.count(addr))
789 closesocket(hSocket);
792 else if (CNode::IsBanned(addr))
794 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
795 closesocket(hSocket);
799 printf("accepted connection %s\n", addr.ToString().c_str());
800 CNode* pnode = new CNode(hSocket, addr, "", true);
804 vNodes.push_back(pnode);
811 // Service each socket
813 vector<CNode*> vNodesCopy;
817 BOOST_FOREACH(CNode* pnode, vNodesCopy)
820 BOOST_FOREACH(CNode* pnode, vNodesCopy)
828 if (pnode->hSocket == INVALID_SOCKET)
830 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
832 TRY_LOCK(pnode->cs_vRecv, lockRecv);
835 CDataStream& vRecv = pnode->vRecv;
836 uint64_t nPos = vRecv.size();
838 if (nPos > ReceiveBufferSize()) {
839 if (!pnode->fDisconnect)
840 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
841 pnode->CloseSocketDisconnect();
844 // typical socket buffer is 8K-64K
845 char pchBuf[0x10000];
846 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
849 vRecv.resize(nPos + nBytes);
850 memcpy(&vRecv[nPos], pchBuf, nBytes);
851 pnode->nLastRecv = GetTime();
852 pnode->nRecvBytes += nBytes;
853 pnode->RecordBytesRecv(nBytes);
855 else if (nBytes == 0)
857 // socket closed gracefully
858 if (!pnode->fDisconnect)
859 printf("socket closed\n");
860 pnode->CloseSocketDisconnect();
865 int nErr = WSAGetLastError();
866 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
868 if (!pnode->fDisconnect)
869 printf("socket recv error %d\n", nErr);
870 pnode->CloseSocketDisconnect();
880 if (pnode->hSocket == INVALID_SOCKET)
882 if (FD_ISSET(pnode->hSocket, &fdsetSend))
884 TRY_LOCK(pnode->cs_vSend, lockSend);
887 CDataStream& vSend = pnode->vSend;
890 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
893 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
894 pnode->nLastSend = GetTime();
895 pnode->nSendBytes += nBytes;
896 pnode->RecordBytesSent(nBytes);
901 int nErr = WSAGetLastError();
902 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
904 printf("socket send error %d\n", nErr);
905 pnode->CloseSocketDisconnect();
913 // Inactivity checking
915 if (pnode->vSend.empty())
916 pnode->nLastSendEmpty = GetTime();
917 if (GetTime() - pnode->nTimeConnected > 60)
919 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
921 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
922 pnode->fDisconnect = true;
924 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
926 printf("socket not sending\n");
927 pnode->fDisconnect = true;
929 else if (GetTime() - pnode->nLastRecv > 90*60)
931 printf("socket inactivity timeout\n");
932 pnode->fDisconnect = true;
938 BOOST_FOREACH(CNode* pnode, vNodesCopy)
955 void ThreadMapPort(void* parg)
957 // Make this thread recognisable as the UPnP thread
958 RenameThread("novacoin-UPnP");
962 vnThreadsRunning[THREAD_UPNP]++;
963 ThreadMapPort2(parg);
964 vnThreadsRunning[THREAD_UPNP]--;
966 catch (std::exception& e) {
967 vnThreadsRunning[THREAD_UPNP]--;
968 PrintException(&e, "ThreadMapPort()");
970 vnThreadsRunning[THREAD_UPNP]--;
971 PrintException(NULL, "ThreadMapPort()");
973 printf("ThreadMapPort exited\n");
976 void ThreadMapPort2(void* parg)
978 printf("ThreadMapPort started\n");
980 std::string port = strprintf("%u", GetListenPort());
981 const char * multicastif = 0;
982 const char * minissdpdpath = 0;
983 struct UPNPDev * devlist = 0;
986 #ifndef UPNPDISCOVER_SUCCESS
988 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
992 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
995 struct UPNPUrls urls;
996 struct IGDdatas data;
999 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
1003 char externalIPAddress[40];
1004 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
1005 if(r != UPNPCOMMAND_SUCCESS)
1006 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
1009 if(externalIPAddress[0])
1011 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1012 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1015 printf("UPnP: GetExternalIPAddress failed.\n");
1019 string strDesc = "NovaCoin " + FormatFullVersion();
1020 #ifndef UPNPDISCOVER_SUCCESS
1022 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1023 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1026 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1027 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1030 if(r!=UPNPCOMMAND_SUCCESS)
1031 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1032 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1034 printf("UPnP Port Mapping successful.\n");
1038 if (fShutdown || !fUseUPnP)
1040 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1041 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1042 freeUPNPDevlist(devlist); devlist = 0;
1043 FreeUPNPUrls(&urls);
1046 if (i % 600 == 0) // Refresh every 20 minutes
1048 #ifndef UPNPDISCOVER_SUCCESS
1050 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1051 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1054 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1055 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1058 if(r!=UPNPCOMMAND_SUCCESS)
1059 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1060 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1062 printf("UPnP Port Mapping successful.\n");;
1068 printf("No valid UPnP IGDs found\n");
1069 freeUPNPDevlist(devlist); devlist = 0;
1071 FreeUPNPUrls(&urls);
1074 if (fShutdown || !fUseUPnP)
1083 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1085 if (!NewThread(ThreadMapPort, NULL))
1086 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1092 // Intentionally left blank.
1105 // Each pair gives a source name and a seed name.
1106 // The first name is used as information source for addrman.
1107 // The second name should resolve to a list of seed addresses.
1108 static const char *strDNSSeed[][2] = {
1109 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1110 {"novacoin.ru", "dnsseed.novacoin.ru"},
1111 {"novacoin.ru", "testseed.novacoin.ru"},
1112 {"novaco.in", "dnsseed.novaco.in"},
1115 void ThreadDNSAddressSeed(void* parg)
1117 // Make this thread recognisable as the DNS seeding thread
1118 RenameThread("novacoin-dnsseed");
1122 vnThreadsRunning[THREAD_DNSSEED]++;
1123 ThreadDNSAddressSeed2(parg);
1124 vnThreadsRunning[THREAD_DNSSEED]--;
1126 catch (std::exception& e) {
1127 vnThreadsRunning[THREAD_DNSSEED]--;
1128 PrintException(&e, "ThreadDNSAddressSeed()");
1130 vnThreadsRunning[THREAD_DNSSEED]--;
1131 throw; // support pthread_cancel()
1133 printf("ThreadDNSAddressSeed exited\n");
1136 void ThreadDNSAddressSeed2(void* parg)
1138 printf("ThreadDNSAddressSeed started\n");
1143 printf("Loading addresses from DNS seeds (could take a while)\n");
1145 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1146 if (HaveNameProxy()) {
1147 AddOneShot(strDNSSeed[seed_idx][1]);
1149 vector<CNetAddr> vaddr;
1150 vector<CAddress> vAdd;
1151 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1153 BOOST_FOREACH(CNetAddr& ip, vaddr)
1155 int nOneDay = 24*3600;
1156 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1157 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1158 vAdd.push_back(addr);
1162 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1167 printf("%d addresses found from DNS seeds\n", found);
1183 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1184 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1185 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1186 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1187 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1188 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1189 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1190 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1191 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1192 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1193 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1194 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1195 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1196 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1197 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1198 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1202 const char* pchTorSeed[] =
1204 "seedp4knqnoei57u.onion",
1205 "seedr3hhlepyi7fd.onion",
1206 "seed3uuomkclbiz4.onion",
1207 "seedeh7qck3ouff5.onion",
1208 "5rg3vq4jagckeckf.onion",
1209 "seedt3sraf53ajiy.onion",
1210 "seedg4qyccsg42oq.onion",
1211 "novaqrtoywpg7jly.onion",
1212 "seed3d5wolqbgrcb.onion",
1213 "seed24u5dwph3qw4.onion",
1214 "mj26ulzbs2oskgym.onion",
1215 "eqon4usunavt76m7.onion",
1218 void DumpAddresses()
1220 int64_t nStart = GetTimeMillis();
1225 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1226 addrman.size(), GetTimeMillis() - nStart);
1229 void ThreadDumpAddress2(void* parg)
1231 printf("ThreadDumpAddress started\n");
1233 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1237 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1239 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1241 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1244 void ThreadDumpAddress(void* parg)
1246 // Make this thread recognisable as the address dumping thread
1247 RenameThread("novacoin-adrdump");
1251 ThreadDumpAddress2(parg);
1253 catch (std::exception& e) {
1254 PrintException(&e, "ThreadDumpAddress()");
1256 printf("ThreadDumpAddress exited\n");
1259 void ThreadOpenConnections(void* parg)
1261 // Make this thread recognisable as the connection opening thread
1262 RenameThread("novacoin-opencon");
1266 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1267 ThreadOpenConnections2(parg);
1268 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1270 catch (std::exception& e) {
1271 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1272 PrintException(&e, "ThreadOpenConnections()");
1274 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1275 PrintException(NULL, "ThreadOpenConnections()");
1277 printf("ThreadOpenConnections exited\n");
1280 void static ProcessOneShot()
1285 if (vOneShots.empty())
1287 strDest = vOneShots.front();
1288 vOneShots.pop_front();
1291 CSemaphoreGrant grant(*semOutbound, true);
1293 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1294 AddOneShot(strDest);
1298 // ppcoin: stake minter thread
1299 void static ThreadStakeMinter(void* parg)
1301 printf("ThreadStakeMinter started\n");
1302 CWallet* pwallet = (CWallet*)parg;
1305 vnThreadsRunning[THREAD_MINTER]++;
1306 StakeMiner(pwallet);
1307 vnThreadsRunning[THREAD_MINTER]--;
1309 catch (std::exception& e) {
1310 vnThreadsRunning[THREAD_MINTER]--;
1311 PrintException(&e, "ThreadStakeMinter()");
1313 vnThreadsRunning[THREAD_MINTER]--;
1314 PrintException(NULL, "ThreadStakeMinter()");
1316 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1319 void ThreadOpenConnections2(void* parg)
1321 printf("ThreadOpenConnections started\n");
1323 // Connect to specific addresses
1324 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1326 for (int64_t nLoop = 0;; nLoop++)
1329 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1332 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1333 for (int i = 0; i < 10 && i < nLoop; i++)
1344 // Initiate network connections
1345 int64_t nStart = GetTime();
1350 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1352 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1357 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1358 CSemaphoreGrant grant(*semOutbound);
1359 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1363 // Add seed nodes if IRC isn't working
1364 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1366 std::vector<CAddress> vAdd;
1367 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1369 // It'll only connect to one or two seed nodes because once it connects,
1370 // it'll get a pile of addresses with newer timestamps.
1371 // Seed nodes are given a random 'last seen time' of between one and two
1373 const int64_t nOneWeek = 7*24*60*60;
1375 memcpy(&ip, &pnSeed[i], sizeof(ip));
1376 CAddress addr(CService(ip, GetDefaultPort()));
1377 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1378 vAdd.push_back(addr);
1380 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1383 // Add Tor nodes if we have connection with onion router
1384 if (mapArgs.count("-tor"))
1386 std::vector<CAddress> vAdd;
1387 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1389 const int64_t nOneWeek = 7*24*60*60;
1390 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1391 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1392 vAdd.push_back(addr);
1394 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1398 // Choose an address to connect to based on most recently seen
1400 CAddress addrConnect;
1402 // Only connect out to one peer per network group (/16 for IPv4).
1403 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1405 set<vector<unsigned char> > setConnected;
1408 BOOST_FOREACH(CNode* pnode, vNodes) {
1409 if (!pnode->fInbound) {
1410 setConnected.insert(pnode->addr.GetGroup());
1416 int64_t nANow = GetAdjustedTime();
1421 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1422 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1424 // if we selected an invalid address, restart
1425 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1428 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1429 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1430 // already-connected network ranges, ...) before trying new addrman addresses.
1435 if (IsLimited(addr))
1438 // only consider very recently tried nodes after 30 failed attempts
1439 if (nANow - addr.nLastTry < 600 && nTries < 30)
1442 // do not allow non-default ports, unless after 50 invalid addresses selected already
1443 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1450 if (addrConnect.IsValid())
1451 OpenNetworkConnection(addrConnect, &grant);
1455 void ThreadOpenAddedConnections(void* parg)
1457 // Make this thread recognisable as the connection opening thread
1458 RenameThread("novacoin-opencon");
1462 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1463 ThreadOpenAddedConnections2(parg);
1464 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1466 catch (std::exception& e) {
1467 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1468 PrintException(&e, "ThreadOpenAddedConnections()");
1470 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1471 PrintException(NULL, "ThreadOpenAddedConnections()");
1473 printf("ThreadOpenAddedConnections exited\n");
1476 void ThreadOpenAddedConnections2(void* parg)
1478 printf("ThreadOpenAddedConnections started\n");
1481 LOCK(cs_vAddedNodes);
1482 vAddedNodes = mapMultiArgs["-addnode"];
1485 if (HaveNameProxy()) {
1487 list<string> lAddresses(0);
1489 LOCK(cs_vAddedNodes);
1490 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1491 lAddresses.push_back(strAddNode);
1493 BOOST_FOREACH(string& strAddNode, lAddresses) {
1495 CSemaphoreGrant grant(*semOutbound);
1496 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1499 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1500 Sleep(120000); // Retry every 2 minutes
1501 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1506 for (uint32_t i = 0; true; i++)
1508 list<string> lAddresses(0);
1510 LOCK(cs_vAddedNodes);
1511 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1512 lAddresses.push_back(strAddNode);
1515 list<vector<CService> > lservAddressesToAdd(0);
1516 BOOST_FOREACH(string& strAddNode, lAddresses)
1518 vector<CService> vservNode(0);
1519 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1521 lservAddressesToAdd.push_back(vservNode);
1523 LOCK(cs_setservAddNodeAddresses);
1524 BOOST_FOREACH(CService& serv, vservNode)
1525 setservAddNodeAddresses.insert(serv);
1529 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1530 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1533 BOOST_FOREACH(CNode* pnode, vNodes)
1534 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1536 BOOST_FOREACH(CService& addrNode, *(it))
1537 if (pnode->addr == addrNode)
1539 it = lservAddressesToAdd.erase(it);
1540 if(it != lservAddressesToAdd.begin())
1544 if (it == lservAddressesToAdd.end())
1548 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1550 if (vserv.size() == 0)
1552 CSemaphoreGrant grant(*semOutbound);
1553 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1560 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1561 Sleep(120000); // Retry every 2 minutes
1562 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1568 // if successful, this moves the passed grant to the constructed node
1569 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1572 // Initiate outbound network connection
1577 if (IsLocal(addrConnect) ||
1578 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1579 FindNode(addrConnect.ToStringIPPort().c_str()))
1581 if (strDest && FindNode(strDest))
1584 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1585 CNode* pnode = ConnectNode(addrConnect, strDest);
1586 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1592 grantOutbound->MoveTo(pnode->grantOutbound);
1593 pnode->fNetworkNode = true;
1595 pnode->fOneShot = true;
1600 // for now, use a very simple selection metric: the node from which we received
1602 static int64_t NodeSyncScore(const CNode *pnode) {
1603 return pnode->nLastRecv;
1606 void static StartSync(const vector<CNode*> &vNodes) {
1607 CNode *pnodeNewSync = NULL;
1608 int64_t nBestScore = 0;
1610 // Iterate over all nodes
1611 BOOST_FOREACH(CNode* pnode, vNodes) {
1612 // check preconditions for allowing a sync
1613 if (!pnode->fClient && !pnode->fOneShot &&
1614 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1615 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1616 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1617 // if ok, compare node's score with the best so far
1618 int64_t nScore = NodeSyncScore(pnode);
1619 if (pnodeNewSync == NULL || nScore > nBestScore) {
1620 pnodeNewSync = pnode;
1621 nBestScore = nScore;
1625 // if a new sync candidate was found, start sync!
1627 pnodeNewSync->fStartSync = true;
1628 pnodeSync = pnodeNewSync;
1632 void ThreadMessageHandler(void* parg)
1634 // Make this thread recognisable as the message handling thread
1635 RenameThread("novacoin-msghand");
1639 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1640 ThreadMessageHandler2(parg);
1641 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1643 catch (std::exception& e) {
1644 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1645 PrintException(&e, "ThreadMessageHandler()");
1647 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1648 PrintException(NULL, "ThreadMessageHandler()");
1650 printf("ThreadMessageHandler exited\n");
1653 void ThreadMessageHandler2(void* parg)
1655 printf("ThreadMessageHandler started\n");
1656 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1659 bool fHaveSyncNode = false;
1660 vector<CNode*> vNodesCopy;
1663 vNodesCopy = vNodes;
1664 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1666 if (pnode == pnodeSync)
1667 fHaveSyncNode = true;
1672 StartSync(vNodesCopy);
1674 // Poll the connected nodes for messages
1675 CNode* pnodeTrickle = NULL;
1676 if (!vNodesCopy.empty())
1677 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1678 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1682 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1684 ProcessMessages(pnode);
1691 TRY_LOCK(pnode->cs_vSend, lockSend);
1693 SendMessages(pnode, pnode == pnodeTrickle);
1701 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1705 // Wait and allow messages to bunch up.
1706 // Reduce vnThreadsRunning so StopNode has permission to exit while
1707 // we're sleeping, but we must always check fShutdown after doing this.
1708 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1710 if (fRequestShutdown)
1712 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1723 bool BindListenPort(const CService &addrBind, string& strError)
1729 // Initialize Windows Sockets
1731 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1732 if (ret != NO_ERROR)
1734 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1735 printf("%s\n", strError.c_str());
1740 // Create socket for listening for incoming connections
1742 struct sockaddr_storage sockaddr;
1744 struct sockaddr sockaddr;
1746 socklen_t len = sizeof(sockaddr);
1747 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1749 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1750 printf("%s\n", strError.c_str());
1754 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1755 if (hListenSocket == INVALID_SOCKET)
1757 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1758 printf("%s\n", strError.c_str());
1764 // Different way of disabling SIGPIPE on BSD
1765 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1767 // Allow binding if the port is still in TIME_WAIT state after
1768 // the program was closed and restarted. Not an issue on windows!
1769 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1773 // Set to non-blocking, incoming connections will also inherit this
1774 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1776 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1779 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1780 printf("%s\n", strError.c_str());
1785 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1786 // and enable it by default or not. Try to enable it, if possible.
1787 if (addrBind.IsIPv6()) {
1790 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1792 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1796 int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
1797 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
1802 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1804 int nErr = WSAGetLastError();
1805 if (nErr == WSAEADDRINUSE)
1806 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1808 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1809 printf("%s\n", strError.c_str());
1810 closesocket(hListenSocket);
1813 printf("Bound to %s\n", addrBind.ToString().c_str());
1815 // Listen for incoming connections
1816 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1818 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1819 printf("%s\n", strError.c_str());
1820 closesocket(hListenSocket);
1824 vhListenSocket.push_back(hListenSocket);
1826 if (addrBind.IsRoutable() && fDiscover)
1827 AddLocal(addrBind, LOCAL_BIND);
1832 void static Discover()
1838 // Get local host IP
1839 char pszHostName[1000] = "";
1840 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1842 vector<CNetAddr> vaddr;
1843 if (LookupHost(pszHostName, vaddr))
1845 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1847 AddLocal(addr, LOCAL_IF);
1852 // Get local host ip
1853 struct ifaddrs* myaddrs;
1854 if (getifaddrs(&myaddrs) == 0)
1856 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1858 if (ifa->ifa_addr == NULL) continue;
1859 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1860 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1861 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1862 if (ifa->ifa_addr->sa_family == AF_INET)
1864 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1865 CNetAddr addr(s4->sin_addr);
1866 if (AddLocal(addr, LOCAL_IF))
1867 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1870 else if (ifa->ifa_addr->sa_family == AF_INET6)
1872 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1873 CNetAddr addr(s6->sin6_addr);
1874 if (AddLocal(addr, LOCAL_IF))
1875 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1879 freeifaddrs(myaddrs);
1883 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1884 if (!IsLimited(NET_IPV4))
1885 NewThread(ThreadGetMyExternalIP, NULL);
1888 void StartNode(void* parg)
1890 // Make this thread recognisable as the startup thread
1891 RenameThread("novacoin-start");
1893 if (semOutbound == NULL) {
1894 // initialize semaphore
1895 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1896 semOutbound = new CSemaphore(nMaxOutbound);
1899 if (pnodeLocalHost == NULL)
1900 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
1908 if (!GetBoolArg("-dnsseed", true))
1909 printf("DNS seeding disabled\n");
1911 if (!NewThread(ThreadDNSAddressSeed, NULL))
1912 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1914 // Map ports with UPnP
1916 printf("UPNP port mapping is disabled\n");
1920 // Get addresses from IRC and advertise ours
1921 if (!GetBoolArg("-irc", true))
1922 printf("IRC seeding disabled\n");
1924 if (!NewThread(ThreadIRCSeed, NULL))
1925 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1927 // Send and receive from sockets, accept connections
1928 if (!NewThread(ThreadSocketHandler, NULL))
1929 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1931 // Initiate outbound connections from -addnode
1932 if (!NewThread(ThreadOpenAddedConnections, NULL))
1933 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1935 // Initiate outbound connections
1936 if (!NewThread(ThreadOpenConnections, NULL))
1937 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1940 if (!NewThread(ThreadMessageHandler, NULL))
1941 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1943 // Dump network addresses
1944 if (!NewThread(ThreadDumpAddress, NULL))
1945 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1947 // ppcoin: mint proof-of-stake blocks in the background
1948 if (!NewThread(ThreadStakeMinter, pwalletMain))
1949 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1954 printf("StopNode()\n");
1956 nTransactionsUpdated++;
1957 int64_t nStart = GetTime();
1960 ThreadScriptCheckQuit();
1963 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1964 semOutbound->post();
1967 int nThreadsRunning = 0;
1968 for (int n = 0; n < THREAD_MAX; n++)
1969 nThreadsRunning += vnThreadsRunning[n];
1970 if (nThreadsRunning == 0)
1972 if (GetTime() - nStart > 20)
1976 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1977 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1978 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1979 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1980 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1982 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1984 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1985 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1986 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1987 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1988 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1989 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
2006 BOOST_FOREACH(CNode* pnode, vNodes)
2007 if (pnode->hSocket != INVALID_SOCKET)
2008 closesocket(pnode->hSocket);
2009 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
2010 if (hListenSocket != INVALID_SOCKET)
2011 if (closesocket(hListenSocket) == SOCKET_ERROR)
2012 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2014 // clean up some globals (to help leak detection)
2015 BOOST_FOREACH(CNode *pnode, vNodes)
2017 BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
2020 vNodesDisconnected.clear();
2023 delete pnodeLocalHost;
2024 pnodeLocalHost = NULL;
2027 // Shutdown Windows Sockets
2032 instance_of_cnetcleanup;
2034 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2036 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2039 RelayTransaction(tx, hash, ss);
2042 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2044 CInv inv(MSG_TX, hash);
2047 // Expire old relay messages
2048 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2050 mapRelay.erase(vRelayExpiration.front().second);
2051 vRelayExpiration.pop_front();
2054 // Save original serialized message so newer versions are preserved
2055 mapRelay.insert(std::make_pair(inv, ss));
2056 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2059 RelayInventory(inv);
2062 void CNode::RecordBytesRecv(uint64_t bytes)
2064 LOCK(cs_totalBytesRecv);
2065 nTotalBytesRecv += bytes;
2068 void CNode::RecordBytesSent(uint64_t bytes)
2070 LOCK(cs_totalBytesSent);
2071 nTotalBytesSent += bytes;
2074 uint64_t CNode::GetTotalBytesRecv()
2076 LOCK(cs_totalBytesRecv);
2077 return nTotalBytesRecv;
2080 uint64_t CNode::GetTotalBytesSent()
2082 LOCK(cs_totalBytesSent);
2083 return nTotalBytesSent;