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