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 struct LocalServiceInfo {
44 // Global state variables
47 bool fDiscover = true;
48 bool fUseUPnP = false;
49 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
50 static CCriticalSection cs_mapLocalHost;
51 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
52 static bool vfReachable[NET_MAX] = {};
53 static bool vfLimited[NET_MAX] = {};
54 static CNode* pnodeLocalHost = NULL;
55 static CNode* pnodeSync = NULL;
56 CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
57 uint64_t nLocalHostNonce = 0;
58 boost::array<int, THREAD_MAX> vnThreadsRunning;
59 static std::vector<SOCKET> vhListenSocket;
62 vector<CNode*> vNodes;
63 CCriticalSection cs_vNodes;
64 map<CInv, CDataStream> mapRelay;
65 deque<pair<int64_t, CInv> > vRelayExpiration;
66 CCriticalSection cs_mapRelay;
67 map<CInv, int64_t> mapAlreadyAskedFor;
69 static deque<string> vOneShots;
70 CCriticalSection cs_vOneShots;
72 set<CNetAddr> setservAddNodeAddresses;
73 CCriticalSection cs_setservAddNodeAddresses;
75 vector<std::string> vAddedNodes;
76 CCriticalSection cs_vAddedNodes;
78 static CSemaphore *semOutbound = NULL;
80 void AddOneShot(string strDest)
83 vOneShots.push_back(strDest);
86 unsigned short GetListenPort()
88 return (unsigned short)(GetArg("-port", GetDefaultPort()));
91 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
93 // Filter out duplicate requests
94 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
96 pindexLastGetBlocksBegin = pindexBegin;
97 hashLastGetBlocksEnd = hashEnd;
99 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
102 // find 'best' local address for a particular peer
103 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
109 int nBestReachability = -1;
111 LOCK(cs_mapLocalHost);
112 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
114 int nScore = (*it).second.nScore;
115 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
116 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
118 addr = CService((*it).first, (*it).second.nPort);
119 nBestReachability = nReachability;
124 return nBestScore >= 0;
127 // get best local address for a particular peer as a CAddress
128 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
130 CAddress ret(CService("0.0.0.0",0),0);
132 if (GetLocal(addr, paddrPeer))
134 ret = CAddress(addr);
135 ret.nServices = nLocalServices;
136 ret.nTime = GetAdjustedTime();
141 bool RecvLine(SOCKET hSocket, string& strLine)
147 int nBytes = recv(hSocket, &c, 1, 0);
155 if (strLine.size() >= 9000)
158 else if (nBytes <= 0)
164 int nErr = WSAGetLastError();
165 if (nErr == WSAEMSGSIZE)
167 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
173 if (!strLine.empty())
178 printf("socket closed\n");
184 int nErr = WSAGetLastError();
185 printf("recv failed: %d\n", nErr);
192 // used when scores of local addresses may have changed
193 // pushes better local address to peers
194 void static AdvertizeLocal()
197 BOOST_FOREACH(CNode* pnode, vNodes)
199 if (pnode->fSuccessfullyConnected)
201 CAddress addrLocal = GetLocalAddress(&pnode->addr);
202 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
204 pnode->PushAddress(addrLocal);
205 pnode->addrLocal = addrLocal;
211 void SetReachable(enum Network net, bool fFlag)
213 LOCK(cs_mapLocalHost);
214 vfReachable[net] = fFlag;
215 if (net == NET_IPV6 && fFlag)
216 vfReachable[NET_IPV4] = true;
219 // learn a new local address
220 bool AddLocal(const CService& addr, int nScore)
222 if (!addr.IsRoutable())
225 if (!fDiscover && nScore < LOCAL_MANUAL)
231 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
234 LOCK(cs_mapLocalHost);
235 bool fAlready = mapLocalHost.count(addr) > 0;
236 LocalServiceInfo &info = mapLocalHost[addr];
237 if (!fAlready || nScore >= info.nScore) {
238 info.nScore = nScore + (fAlready ? 1 : 0);
239 info.nPort = addr.GetPort();
241 SetReachable(addr.GetNetwork());
249 bool AddLocal(const CNetAddr &addr, int nScore)
251 return AddLocal(CService(addr, GetListenPort()), nScore);
254 /** Make a particular network entirely off-limits (no automatic connects to it) */
255 void SetLimited(enum Network net, bool fLimited)
257 if (net == NET_UNROUTABLE)
259 LOCK(cs_mapLocalHost);
260 vfLimited[net] = fLimited;
263 bool IsLimited(enum Network net)
265 LOCK(cs_mapLocalHost);
266 return vfLimited[net];
269 bool IsLimited(const CNetAddr &addr)
271 return IsLimited(addr.GetNetwork());
274 /** vote for a local address */
275 bool SeenLocal(const CService& addr)
278 LOCK(cs_mapLocalHost);
279 if (mapLocalHost.count(addr) == 0)
281 mapLocalHost[addr].nScore++;
289 /** check whether a given address is potentially local */
290 bool IsLocal(const CService& addr)
292 LOCK(cs_mapLocalHost);
293 return mapLocalHost.count(addr) > 0;
296 /** check whether a given address is in a network we can probably connect to */
297 bool IsReachable(const CNetAddr& addr)
299 LOCK(cs_mapLocalHost);
300 enum Network net = addr.GetNetwork();
301 return vfReachable[net] && !vfLimited[net];
304 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
306 // We now get our external IP from the IRC server first and only use this as a backup
307 bool GetMyExternalIP(CNetAddr& ipRet)
309 struct sockaddr_in mapped;
310 uint64_t rnd = std::numeric_limits<uint64_t>::max();
312 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
314 ipRet = CNetAddr(mapped.sin_addr);
315 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
321 void ThreadGetMyExternalIP(void* parg)
323 // Make this thread recognisable as the external IP detection thread
324 RenameThread("novacoin-ext-ip");
326 CNetAddr addrLocalHost;
327 if (GetMyExternalIP(addrLocalHost))
329 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
330 AddLocal(addrLocalHost, LOCAL_HTTP);
338 void AddressCurrentlyConnected(const CService& addr)
340 addrman.Connected(addr);
346 uint64_t CNode::nTotalBytesRecv = 0;
347 uint64_t CNode::nTotalBytesSent = 0;
348 CCriticalSection CNode::cs_totalBytesRecv;
349 CCriticalSection CNode::cs_totalBytesSent;
351 CNode* FindNode(const CNetAddr& ip)
354 BOOST_FOREACH(CNode* pnode, vNodes)
355 if ((CNetAddr)pnode->addr == ip)
360 CNode* FindNode(std::string addrName)
363 BOOST_FOREACH(CNode* pnode, vNodes)
364 if (pnode->addrName == addrName)
369 CNode* FindNode(const CService& addr)
372 BOOST_FOREACH(CNode* pnode, vNodes)
373 if ((CService)pnode->addr == addr)
378 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
380 if (pszDest == NULL) {
381 if (IsLocal(addrConnect))
384 // Look for an existing connection
385 CNode* pnode = FindNode((CService)addrConnect);
389 pnode->AddRef(nTimeout);
398 printf("trying connection %s lastseen=%.1fhrs\n",
399 pszDest ? pszDest : addrConnect.ToString().c_str(),
400 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
404 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
406 addrman.Attempt(addrConnect);
409 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
411 // Set to non-blocking
414 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
415 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
417 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
418 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
422 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
424 pnode->AddRef(nTimeout);
430 vNodes.push_back(pnode);
433 pnode->nTimeConnected = GetTime();
442 void CNode::CloseSocketDisconnect()
445 if (hSocket != INVALID_SOCKET)
447 printf("disconnecting node %s\n", addrName.c_str());
448 closesocket(hSocket);
449 hSocket = INVALID_SOCKET;
453 // in case this fails, we'll empty the recv buffer when the CNode is deleted
454 TRY_LOCK(cs_vRecv, lockRecv);
458 // if this was the sync node, we'll need a new one
459 if (this == pnodeSync)
463 void CNode::Cleanup()
468 void CNode::PushVersion()
470 /// when NTP implemented, change to just nTime = GetAdjustedTime()
471 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
472 CAddress addrYou, addrMe;
474 bool fHidden = false;
476 if (mapArgs.count("-torname")) {
477 // Our hidden service address
478 CService addrTorName(mapArgs["-torname"], GetListenPort());
480 if (addrTorName.IsValid()) {
482 addrMe = CAddress(addrTorName);
489 addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
490 addrMe = GetLocalAddress(&addr);
493 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
494 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());
495 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
496 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
503 std::map<CNetAddr, int64_t> CNode::setBanned;
504 CCriticalSection CNode::cs_setBanned;
506 void CNode::ClearBanned()
511 bool CNode::IsBanned(CNetAddr ip)
513 bool fResult = false;
516 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
517 if (i != setBanned.end())
519 int64_t t = (*i).second;
527 bool CNode::Misbehaving(int howmuch)
531 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
535 nMisbehavior += howmuch;
536 if (nMisbehavior >= GetArg("-banscore", 100))
538 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
539 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
542 if (setBanned[addr] < banTime)
543 setBanned[addr] = banTime;
545 CloseSocketDisconnect();
548 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
553 #define X(name) stats.name = name
554 void CNode::copyStats(CNodeStats &stats)
569 stats.fSyncNode = (this == pnodeSync);
582 void ThreadSocketHandler(void* parg)
584 // Make this thread recognisable as the networking thread
585 RenameThread("novacoin-net");
589 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
590 ThreadSocketHandler2(parg);
591 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
593 catch (std::exception& e) {
594 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
595 PrintException(&e, "ThreadSocketHandler()");
597 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
598 throw; // support pthread_cancel()
600 printf("ThreadSocketHandler exited\n");
603 void ThreadSocketHandler2(void* parg)
605 printf("ThreadSocketHandler started\n");
606 list<CNode*> vNodesDisconnected;
607 unsigned int nPrevNodeCount = 0;
616 // Disconnect unused nodes
617 vector<CNode*> vNodesCopy = vNodes;
618 BOOST_FOREACH(CNode* pnode, vNodesCopy)
620 if (pnode->fDisconnect ||
621 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
623 // remove from vNodes
624 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
626 // release outbound grant (if any)
627 pnode->grantOutbound.Release();
629 // close socket and cleanup
630 pnode->CloseSocketDisconnect();
633 // hold in disconnected pool until all refs are released
634 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
635 if (pnode->fNetworkNode || pnode->fInbound)
637 vNodesDisconnected.push_back(pnode);
641 // Delete disconnected nodes
642 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
643 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
645 // wait until threads are done using it
646 if (pnode->GetRefCount() <= 0)
648 bool fDelete = false;
650 TRY_LOCK(pnode->cs_vSend, lockSend);
653 TRY_LOCK(pnode->cs_vRecv, lockRecv);
656 TRY_LOCK(pnode->cs_mapRequests, lockReq);
659 TRY_LOCK(pnode->cs_inventory, lockInv);
668 vNodesDisconnected.remove(pnode);
674 if (vNodes.size() != nPrevNodeCount)
676 nPrevNodeCount = vNodes.size();
677 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
682 // Find which sockets have data to receive
684 struct timeval timeout;
686 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
693 FD_ZERO(&fdsetError);
694 SOCKET hSocketMax = 0;
695 bool have_fds = false;
697 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
698 FD_SET(hListenSocket, &fdsetRecv);
699 hSocketMax = max(hSocketMax, hListenSocket);
704 BOOST_FOREACH(CNode* pnode, vNodes)
706 if (pnode->hSocket == INVALID_SOCKET)
708 FD_SET(pnode->hSocket, &fdsetRecv);
709 FD_SET(pnode->hSocket, &fdsetError);
710 hSocketMax = max(hSocketMax, pnode->hSocket);
713 TRY_LOCK(pnode->cs_vSend, lockSend);
714 if (lockSend && !pnode->vSend.empty())
715 FD_SET(pnode->hSocket, &fdsetSend);
720 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
721 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
722 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
723 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
726 if (nSelect == SOCKET_ERROR)
730 int nErr = WSAGetLastError();
731 printf("socket select error %d\n", nErr);
732 for (unsigned int i = 0; i <= hSocketMax; i++)
733 FD_SET(i, &fdsetRecv);
736 FD_ZERO(&fdsetError);
737 Sleep(timeout.tv_usec/1000);
742 // Accept new connections
744 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
745 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
748 struct sockaddr_storage sockaddr;
750 struct sockaddr sockaddr;
752 socklen_t len = sizeof(sockaddr);
753 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
757 if (hSocket != INVALID_SOCKET)
758 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
759 printf("Warning: Unknown socket family\n");
763 BOOST_FOREACH(CNode* pnode, vNodes)
768 if (hSocket == INVALID_SOCKET)
770 int nErr = WSAGetLastError();
771 if (nErr != WSAEWOULDBLOCK)
772 printf("socket error accept failed: %d\n", nErr);
774 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
777 LOCK(cs_setservAddNodeAddresses);
778 if (!setservAddNodeAddresses.count(addr))
779 closesocket(hSocket);
782 else if (CNode::IsBanned(addr))
784 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
785 closesocket(hSocket);
789 printf("accepted connection %s\n", addr.ToString().c_str());
790 CNode* pnode = new CNode(hSocket, addr, "", true);
794 vNodes.push_back(pnode);
801 // Service each socket
803 vector<CNode*> vNodesCopy;
807 BOOST_FOREACH(CNode* pnode, vNodesCopy)
810 BOOST_FOREACH(CNode* pnode, vNodesCopy)
818 if (pnode->hSocket == INVALID_SOCKET)
820 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
822 TRY_LOCK(pnode->cs_vRecv, lockRecv);
825 CDataStream& vRecv = pnode->vRecv;
826 uint64_t nPos = vRecv.size();
828 if (nPos > ReceiveBufferSize()) {
829 if (!pnode->fDisconnect)
830 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
831 pnode->CloseSocketDisconnect();
834 // typical socket buffer is 8K-64K
835 char pchBuf[0x10000];
836 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
839 vRecv.resize(nPos + nBytes);
840 memcpy(&vRecv[nPos], pchBuf, nBytes);
841 pnode->nLastRecv = GetTime();
842 pnode->nRecvBytes += nBytes;
843 pnode->RecordBytesRecv(nBytes);
845 else if (nBytes == 0)
847 // socket closed gracefully
848 if (!pnode->fDisconnect)
849 printf("socket closed\n");
850 pnode->CloseSocketDisconnect();
855 int nErr = WSAGetLastError();
856 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
858 if (!pnode->fDisconnect)
859 printf("socket recv error %d\n", nErr);
860 pnode->CloseSocketDisconnect();
870 if (pnode->hSocket == INVALID_SOCKET)
872 if (FD_ISSET(pnode->hSocket, &fdsetSend))
874 TRY_LOCK(pnode->cs_vSend, lockSend);
877 CDataStream& vSend = pnode->vSend;
880 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
883 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
884 pnode->nLastSend = GetTime();
885 pnode->nSendBytes += nBytes;
886 pnode->RecordBytesSent(nBytes);
891 int nErr = WSAGetLastError();
892 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
894 printf("socket send error %d\n", nErr);
895 pnode->CloseSocketDisconnect();
903 // Inactivity checking
905 if (pnode->vSend.empty())
906 pnode->nLastSendEmpty = GetTime();
907 if (GetTime() - pnode->nTimeConnected > 60)
909 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
911 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
912 pnode->fDisconnect = true;
914 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
916 printf("socket not sending\n");
917 pnode->fDisconnect = true;
919 else if (GetTime() - pnode->nLastRecv > 90*60)
921 printf("socket inactivity timeout\n");
922 pnode->fDisconnect = true;
928 BOOST_FOREACH(CNode* pnode, vNodesCopy)
945 void ThreadMapPort(void* parg)
947 // Make this thread recognisable as the UPnP thread
948 RenameThread("novacoin-UPnP");
952 vnThreadsRunning[THREAD_UPNP]++;
953 ThreadMapPort2(parg);
954 vnThreadsRunning[THREAD_UPNP]--;
956 catch (std::exception& e) {
957 vnThreadsRunning[THREAD_UPNP]--;
958 PrintException(&e, "ThreadMapPort()");
960 vnThreadsRunning[THREAD_UPNP]--;
961 PrintException(NULL, "ThreadMapPort()");
963 printf("ThreadMapPort exited\n");
966 void ThreadMapPort2(void* parg)
968 printf("ThreadMapPort started\n");
970 std::string port = strprintf("%u", GetListenPort());
971 const char * multicastif = 0;
972 const char * minissdpdpath = 0;
973 struct UPNPDev * devlist = 0;
976 #ifndef UPNPDISCOVER_SUCCESS
978 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
982 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
985 struct UPNPUrls urls;
986 struct IGDdatas data;
989 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
993 char externalIPAddress[40];
994 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
995 if(r != UPNPCOMMAND_SUCCESS)
996 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
999 if(externalIPAddress[0])
1001 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
1002 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
1005 printf("UPnP: GetExternalIPAddress failed.\n");
1009 string strDesc = "NovaCoin " + FormatFullVersion();
1010 #ifndef UPNPDISCOVER_SUCCESS
1012 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1013 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1016 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1017 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1020 if(r!=UPNPCOMMAND_SUCCESS)
1021 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1022 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1024 printf("UPnP Port Mapping successful.\n");
1028 if (fShutdown || !fUseUPnP)
1030 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1031 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1032 freeUPNPDevlist(devlist); devlist = 0;
1033 FreeUPNPUrls(&urls);
1036 if (i % 600 == 0) // Refresh every 20 minutes
1038 #ifndef UPNPDISCOVER_SUCCESS
1040 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1041 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1044 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1045 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1048 if(r!=UPNPCOMMAND_SUCCESS)
1049 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1050 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1052 printf("UPnP Port Mapping successful.\n");;
1058 printf("No valid UPnP IGDs found\n");
1059 freeUPNPDevlist(devlist); devlist = 0;
1061 FreeUPNPUrls(&urls);
1064 if (fShutdown || !fUseUPnP)
1073 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1075 if (!NewThread(ThreadMapPort, NULL))
1076 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1082 // Intentionally left blank.
1095 // Each pair gives a source name and a seed name.
1096 // The first name is used as information source for addrman.
1097 // The second name should resolve to a list of seed addresses.
1098 static const char *strDNSSeed[][2] = {
1099 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1100 {"novacoin.ru", "dnsseed.novacoin.ru"},
1101 {"novacoin.ru", "testseed.novacoin.ru"},
1102 {"novaco.in", "dnsseed.novaco.in"},
1105 void ThreadDNSAddressSeed(void* parg)
1107 // Make this thread recognisable as the DNS seeding thread
1108 RenameThread("novacoin-dnsseed");
1112 vnThreadsRunning[THREAD_DNSSEED]++;
1113 ThreadDNSAddressSeed2(parg);
1114 vnThreadsRunning[THREAD_DNSSEED]--;
1116 catch (std::exception& e) {
1117 vnThreadsRunning[THREAD_DNSSEED]--;
1118 PrintException(&e, "ThreadDNSAddressSeed()");
1120 vnThreadsRunning[THREAD_DNSSEED]--;
1121 throw; // support pthread_cancel()
1123 printf("ThreadDNSAddressSeed exited\n");
1126 void ThreadDNSAddressSeed2(void* parg)
1128 printf("ThreadDNSAddressSeed started\n");
1133 printf("Loading addresses from DNS seeds (could take a while)\n");
1135 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1136 if (HaveNameProxy()) {
1137 AddOneShot(strDNSSeed[seed_idx][1]);
1139 vector<CNetAddr> vaddr;
1140 vector<CAddress> vAdd;
1141 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1143 BOOST_FOREACH(CNetAddr& ip, vaddr)
1145 int nOneDay = 24*3600;
1146 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1147 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1148 vAdd.push_back(addr);
1152 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1157 printf("%d addresses found from DNS seeds\n", found);
1173 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1174 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1175 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1176 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1177 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1178 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1179 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1180 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1181 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1182 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1183 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1184 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1185 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1186 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1187 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1188 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1192 const char* pchTorSeed[] =
1194 "seedp4knqnoei57u.onion",
1195 "seedr3hhlepyi7fd.onion",
1196 "seed3uuomkclbiz4.onion",
1197 "seedeh7qck3ouff5.onion",
1198 "5rg3vq4jagckeckf.onion",
1199 "seedt3sraf53ajiy.onion",
1200 "seedg4qyccsg42oq.onion",
1201 "novaqrtoywpg7jly.onion",
1202 "seed3d5wolqbgrcb.onion",
1203 "seed24u5dwph3qw4.onion",
1204 "mj26ulzbs2oskgym.onion",
1205 "eqon4usunavt76m7.onion",
1208 void DumpAddresses()
1210 int64_t nStart = GetTimeMillis();
1215 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1216 addrman.size(), GetTimeMillis() - nStart);
1219 void ThreadDumpAddress2(void* parg)
1221 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1225 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1227 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1229 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1232 void ThreadDumpAddress(void* parg)
1234 // Make this thread recognisable as the address dumping thread
1235 RenameThread("novacoin-adrdump");
1239 ThreadDumpAddress2(parg);
1241 catch (std::exception& e) {
1242 PrintException(&e, "ThreadDumpAddress()");
1244 printf("ThreadDumpAddress exited\n");
1247 void ThreadOpenConnections(void* parg)
1249 // Make this thread recognisable as the connection opening thread
1250 RenameThread("novacoin-opencon");
1254 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1255 ThreadOpenConnections2(parg);
1256 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1258 catch (std::exception& e) {
1259 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1260 PrintException(&e, "ThreadOpenConnections()");
1262 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1263 PrintException(NULL, "ThreadOpenConnections()");
1265 printf("ThreadOpenConnections exited\n");
1268 void static ProcessOneShot()
1273 if (vOneShots.empty())
1275 strDest = vOneShots.front();
1276 vOneShots.pop_front();
1279 CSemaphoreGrant grant(*semOutbound, true);
1281 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1282 AddOneShot(strDest);
1286 // ppcoin: stake minter thread
1287 void static ThreadStakeMinter(void* parg)
1289 printf("ThreadStakeMinter started\n");
1290 CWallet* pwallet = (CWallet*)parg;
1293 vnThreadsRunning[THREAD_MINTER]++;
1294 StakeMiner(pwallet);
1295 vnThreadsRunning[THREAD_MINTER]--;
1297 catch (std::exception& e) {
1298 vnThreadsRunning[THREAD_MINTER]--;
1299 PrintException(&e, "ThreadStakeMinter()");
1301 vnThreadsRunning[THREAD_MINTER]--;
1302 PrintException(NULL, "ThreadStakeMinter()");
1304 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1307 void ThreadOpenConnections2(void* parg)
1309 printf("ThreadOpenConnections started\n");
1311 // Connect to specific addresses
1312 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1314 for (int64_t nLoop = 0;; nLoop++)
1317 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1320 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1321 for (int i = 0; i < 10 && i < nLoop; i++)
1332 // Initiate network connections
1333 int64_t nStart = GetTime();
1338 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1340 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1345 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1346 CSemaphoreGrant grant(*semOutbound);
1347 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1351 // Add seed nodes if IRC isn't working
1352 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1354 std::vector<CAddress> vAdd;
1355 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1357 // It'll only connect to one or two seed nodes because once it connects,
1358 // it'll get a pile of addresses with newer timestamps.
1359 // Seed nodes are given a random 'last seen time' of between one and two
1361 const int64_t nOneWeek = 7*24*60*60;
1363 memcpy(&ip, &pnSeed[i], sizeof(ip));
1364 CAddress addr(CService(ip, GetDefaultPort()));
1365 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1366 vAdd.push_back(addr);
1368 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1371 // Add Tor nodes if we have connection with onion router
1372 if (mapArgs.count("-tor"))
1374 std::vector<CAddress> vAdd;
1375 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1377 const int64_t nOneWeek = 7*24*60*60;
1378 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1379 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1380 vAdd.push_back(addr);
1382 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1386 // Choose an address to connect to based on most recently seen
1388 CAddress addrConnect;
1390 // Only connect out to one peer per network group (/16 for IPv4).
1391 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1393 set<vector<unsigned char> > setConnected;
1396 BOOST_FOREACH(CNode* pnode, vNodes) {
1397 if (!pnode->fInbound) {
1398 setConnected.insert(pnode->addr.GetGroup());
1404 int64_t nANow = GetAdjustedTime();
1409 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1410 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1412 // if we selected an invalid address, restart
1413 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1416 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1417 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1418 // already-connected network ranges, ...) before trying new addrman addresses.
1423 if (IsLimited(addr))
1426 // only consider very recently tried nodes after 30 failed attempts
1427 if (nANow - addr.nLastTry < 600 && nTries < 30)
1430 // do not allow non-default ports, unless after 50 invalid addresses selected already
1431 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1438 if (addrConnect.IsValid())
1439 OpenNetworkConnection(addrConnect, &grant);
1443 void ThreadOpenAddedConnections(void* parg)
1445 // Make this thread recognisable as the connection opening thread
1446 RenameThread("novacoin-opencon");
1450 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1451 ThreadOpenAddedConnections2(parg);
1452 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1454 catch (std::exception& e) {
1455 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1456 PrintException(&e, "ThreadOpenAddedConnections()");
1458 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1459 PrintException(NULL, "ThreadOpenAddedConnections()");
1461 printf("ThreadOpenAddedConnections exited\n");
1464 void ThreadOpenAddedConnections2(void* parg)
1466 printf("ThreadOpenAddedConnections started\n");
1469 LOCK(cs_vAddedNodes);
1470 vAddedNodes = mapMultiArgs["-addnode"];
1473 if (HaveNameProxy()) {
1475 list<string> lAddresses(0);
1477 LOCK(cs_vAddedNodes);
1478 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1479 lAddresses.push_back(strAddNode);
1481 BOOST_FOREACH(string& strAddNode, lAddresses) {
1483 CSemaphoreGrant grant(*semOutbound);
1484 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1487 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1488 Sleep(120000); // Retry every 2 minutes
1489 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1494 for (uint32_t i = 0; true; i++)
1496 list<string> lAddresses(0);
1498 LOCK(cs_vAddedNodes);
1499 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1500 lAddresses.push_back(strAddNode);
1503 list<vector<CService> > lservAddressesToAdd(0);
1504 BOOST_FOREACH(string& strAddNode, lAddresses)
1506 vector<CService> vservNode(0);
1507 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1509 lservAddressesToAdd.push_back(vservNode);
1511 LOCK(cs_setservAddNodeAddresses);
1512 BOOST_FOREACH(CService& serv, vservNode)
1513 setservAddNodeAddresses.insert(serv);
1517 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1518 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1521 BOOST_FOREACH(CNode* pnode, vNodes)
1522 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1524 BOOST_FOREACH(CService& addrNode, *(it))
1525 if (pnode->addr == addrNode)
1527 it = lservAddressesToAdd.erase(it);
1528 if(it != lservAddressesToAdd.begin())
1532 if (it == lservAddressesToAdd.end())
1536 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1538 if (vserv.size() == 0)
1540 CSemaphoreGrant grant(*semOutbound);
1541 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1548 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1549 Sleep(120000); // Retry every 2 minutes
1550 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1556 // if successful, this moves the passed grant to the constructed node
1557 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1560 // Initiate outbound network connection
1565 if (IsLocal(addrConnect) ||
1566 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1567 FindNode(addrConnect.ToStringIPPort().c_str()))
1569 if (strDest && FindNode(strDest))
1572 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1573 CNode* pnode = ConnectNode(addrConnect, strDest);
1574 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1580 grantOutbound->MoveTo(pnode->grantOutbound);
1581 pnode->fNetworkNode = true;
1583 pnode->fOneShot = true;
1588 // for now, use a very simple selection metric: the node from which we received
1590 double static NodeSyncScore(const CNode *pnode) {
1591 return -pnode->nLastRecv;
1594 void static StartSync(const vector<CNode*> &vNodes) {
1595 CNode *pnodeNewSync = NULL;
1596 double dBestScore = 0;
1598 // Iterate over all nodes
1599 BOOST_FOREACH(CNode* pnode, vNodes) {
1600 // check preconditions for allowing a sync
1601 if (!pnode->fClient && !pnode->fOneShot &&
1602 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1603 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1604 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1605 // if ok, compare node's score with the best so far
1606 double dScore = NodeSyncScore(pnode);
1607 if (pnodeNewSync == NULL || dScore > dBestScore) {
1608 pnodeNewSync = pnode;
1609 dBestScore = dScore;
1613 // if a new sync candidate was found, start sync!
1615 pnodeNewSync->fStartSync = true;
1616 pnodeSync = pnodeNewSync;
1620 void ThreadMessageHandler(void* parg)
1622 // Make this thread recognisable as the message handling thread
1623 RenameThread("novacoin-msghand");
1627 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1628 ThreadMessageHandler2(parg);
1629 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1631 catch (std::exception& e) {
1632 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1633 PrintException(&e, "ThreadMessageHandler()");
1635 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1636 PrintException(NULL, "ThreadMessageHandler()");
1638 printf("ThreadMessageHandler exited\n");
1641 void ThreadMessageHandler2(void* parg)
1643 printf("ThreadMessageHandler started\n");
1644 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1647 bool fHaveSyncNode = false;
1648 vector<CNode*> vNodesCopy;
1651 vNodesCopy = vNodes;
1652 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1654 if (pnode == pnodeSync)
1655 fHaveSyncNode = true;
1660 StartSync(vNodesCopy);
1662 // Poll the connected nodes for messages
1663 CNode* pnodeTrickle = NULL;
1664 if (!vNodesCopy.empty())
1665 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1666 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1670 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1672 ProcessMessages(pnode);
1679 TRY_LOCK(pnode->cs_vSend, lockSend);
1681 SendMessages(pnode, pnode == pnodeTrickle);
1689 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1693 // Wait and allow messages to bunch up.
1694 // Reduce vnThreadsRunning so StopNode has permission to exit while
1695 // we're sleeping, but we must always check fShutdown after doing this.
1696 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1698 if (fRequestShutdown)
1700 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1711 bool BindListenPort(const CService &addrBind, string& strError)
1717 // Initialize Windows Sockets
1719 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1720 if (ret != NO_ERROR)
1722 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1723 printf("%s\n", strError.c_str());
1728 // Create socket for listening for incoming connections
1730 struct sockaddr_storage sockaddr;
1732 struct sockaddr sockaddr;
1734 socklen_t len = sizeof(sockaddr);
1735 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1737 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1738 printf("%s\n", strError.c_str());
1742 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1743 if (hListenSocket == INVALID_SOCKET)
1745 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1746 printf("%s\n", strError.c_str());
1751 // Different way of disabling SIGPIPE on BSD
1752 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1756 // Allow binding if the port is still in TIME_WAIT state after
1757 // the program was closed and restarted. Not an issue on windows.
1758 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1763 // Set to non-blocking, incoming connections will also inherit this
1764 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1766 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1769 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1770 printf("%s\n", strError.c_str());
1775 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1776 // and enable it by default or not. Try to enable it, if possible.
1777 if (addrBind.IsIPv6()) {
1780 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1782 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1786 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1787 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1788 // this call is allowed to fail
1789 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1794 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1796 int nErr = WSAGetLastError();
1797 if (nErr == WSAEADDRINUSE)
1798 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1800 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1801 printf("%s\n", strError.c_str());
1804 printf("Bound to %s\n", addrBind.ToString().c_str());
1806 // Listen for incoming connections
1807 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1809 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1810 printf("%s\n", strError.c_str());
1814 vhListenSocket.push_back(hListenSocket);
1816 if (addrBind.IsRoutable() && fDiscover)
1817 AddLocal(addrBind, LOCAL_BIND);
1822 void static Discover()
1828 // Get local host IP
1829 char pszHostName[1000] = "";
1830 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1832 vector<CNetAddr> vaddr;
1833 if (LookupHost(pszHostName, vaddr))
1835 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1837 AddLocal(addr, LOCAL_IF);
1842 // Get local host ip
1843 struct ifaddrs* myaddrs;
1844 if (getifaddrs(&myaddrs) == 0)
1846 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1848 if (ifa->ifa_addr == NULL) continue;
1849 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1850 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1851 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1852 if (ifa->ifa_addr->sa_family == AF_INET)
1854 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1855 CNetAddr addr(s4->sin_addr);
1856 if (AddLocal(addr, LOCAL_IF))
1857 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1860 else if (ifa->ifa_addr->sa_family == AF_INET6)
1862 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1863 CNetAddr addr(s6->sin6_addr);
1864 if (AddLocal(addr, LOCAL_IF))
1865 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1869 freeifaddrs(myaddrs);
1873 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1874 if (!IsLimited(NET_IPV4))
1875 NewThread(ThreadGetMyExternalIP, NULL);
1878 void StartNode(void* parg)
1880 // Make this thread recognisable as the startup thread
1881 RenameThread("novacoin-start");
1883 if (semOutbound == NULL) {
1884 // initialize semaphore
1885 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1886 semOutbound = new CSemaphore(nMaxOutbound);
1889 if (pnodeLocalHost == NULL)
1890 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1898 if (!GetBoolArg("-dnsseed", true))
1899 printf("DNS seeding disabled\n");
1901 if (!NewThread(ThreadDNSAddressSeed, NULL))
1902 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1904 // Map ports with UPnP
1906 printf("UPNP port mapping is disabled\n");
1910 // Get addresses from IRC and advertise ours
1911 if (!GetBoolArg("-irc", true))
1912 printf("IRC seeding disabled\n");
1914 if (!NewThread(ThreadIRCSeed, NULL))
1915 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1917 // Send and receive from sockets, accept connections
1918 if (!NewThread(ThreadSocketHandler, NULL))
1919 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1921 // Initiate outbound connections from -addnode
1922 if (!NewThread(ThreadOpenAddedConnections, NULL))
1923 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1925 // Initiate outbound connections
1926 if (!NewThread(ThreadOpenConnections, NULL))
1927 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1930 if (!NewThread(ThreadMessageHandler, NULL))
1931 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1933 // Dump network addresses
1934 if (!NewThread(ThreadDumpAddress, NULL))
1935 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1937 // ppcoin: mint proof-of-stake blocks in the background
1938 if (!NewThread(ThreadStakeMinter, pwalletMain))
1939 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1944 printf("StopNode()\n");
1946 nTransactionsUpdated++;
1947 int64_t nStart = GetTime();
1950 ThreadScriptCheckQuit();
1953 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1954 semOutbound->post();
1957 int nThreadsRunning = 0;
1958 for (int n = 0; n < THREAD_MAX; n++)
1959 nThreadsRunning += vnThreadsRunning[n];
1960 if (nThreadsRunning == 0)
1962 if (GetTime() - nStart > 20)
1966 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1967 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1968 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1969 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1970 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1972 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1974 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1975 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1976 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1977 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1978 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1979 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1995 BOOST_FOREACH(CNode* pnode, vNodes)
1996 if (pnode->hSocket != INVALID_SOCKET)
1997 closesocket(pnode->hSocket);
1998 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1999 if (hListenSocket != INVALID_SOCKET)
2000 if (closesocket(hListenSocket) == SOCKET_ERROR)
2001 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
2004 // Shutdown Windows Sockets
2009 instance_of_cnetcleanup;
2011 void RelayTransaction(const CTransaction& tx, const uint256& hash)
2013 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
2016 RelayTransaction(tx, hash, ss);
2019 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2021 CInv inv(MSG_TX, hash);
2024 // Expire old relay messages
2025 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2027 mapRelay.erase(vRelayExpiration.front().second);
2028 vRelayExpiration.pop_front();
2031 // Save original serialized message so newer versions are preserved
2032 mapRelay.insert(std::make_pair(inv, ss));
2033 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2036 RelayInventory(inv);
2039 void CNode::RecordBytesRecv(uint64_t bytes)
2041 LOCK(cs_totalBytesRecv);
2042 nTotalBytesRecv += bytes;
2045 void CNode::RecordBytesSent(uint64_t bytes)
2047 LOCK(cs_totalBytesSent);
2048 nTotalBytesSent += bytes;
2051 uint64_t CNode::GetTotalBytesRecv()
2053 LOCK(cs_totalBytesRecv);
2054 return nTotalBytesRecv;
2057 uint64_t CNode::GetTotalBytesSent()
2059 LOCK(cs_totalBytesSent);
2060 return nTotalBytesSent;