1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
12 #include "ui_interface.h"
19 #include <miniupnpc/miniwget.h>
20 #include <miniupnpc/miniupnpc.h>
21 #include <miniupnpc/upnpcommands.h>
22 #include <miniupnpc/upnperrors.h>
26 using namespace boost;
28 static const int MAX_OUTBOUND_CONNECTIONS = 16;
30 void ThreadMessageHandler2(void* parg);
31 void ThreadSocketHandler2(void* parg);
32 void ThreadOpenConnections2(void* parg);
33 void ThreadOpenAddedConnections2(void* parg);
35 void ThreadMapPort2(void* parg);
37 void ThreadDNSAddressSeed2(void* parg);
38 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
41 struct LocalServiceInfo {
47 // Global state variables
50 bool fDiscover = true;
51 bool fUseUPnP = false;
52 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
53 static CCriticalSection cs_mapLocalHost;
54 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
55 static bool vfReachable[NET_MAX] = {};
56 static bool vfLimited[NET_MAX] = {};
57 static CNode* pnodeLocalHost = NULL;
58 static CNode* pnodeSync = NULL;
59 CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
60 uint64_t nLocalHostNonce = 0;
61 boost::array<int, THREAD_MAX> vnThreadsRunning;
62 static std::vector<SOCKET> vhListenSocket;
65 vector<CNode*> vNodes;
66 CCriticalSection cs_vNodes;
67 map<CInv, CDataStream> mapRelay;
68 deque<pair<int64_t, CInv> > vRelayExpiration;
69 CCriticalSection cs_mapRelay;
70 map<CInv, int64_t> mapAlreadyAskedFor;
72 static deque<string> vOneShots;
73 CCriticalSection cs_vOneShots;
75 set<CNetAddr> setservAddNodeAddresses;
76 CCriticalSection cs_setservAddNodeAddresses;
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 = GetRand(~0LL);
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 = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
473 CAddress addrMe = GetLocalAddress(&addr);
474 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
475 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());
476 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
477 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
484 std::map<CNetAddr, int64_t> CNode::setBanned;
485 CCriticalSection CNode::cs_setBanned;
487 void CNode::ClearBanned()
492 bool CNode::IsBanned(CNetAddr ip)
494 bool fResult = false;
497 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
498 if (i != setBanned.end())
500 int64_t t = (*i).second;
508 bool CNode::Misbehaving(int howmuch)
512 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
516 nMisbehavior += howmuch;
517 if (nMisbehavior >= GetArg("-banscore", 100))
519 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
520 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
523 if (setBanned[addr] < banTime)
524 setBanned[addr] = banTime;
526 CloseSocketDisconnect();
529 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
534 #define X(name) stats.name = name
535 void CNode::copyStats(CNodeStats &stats)
550 stats.fSyncNode = (this == pnodeSync);
563 void ThreadSocketHandler(void* parg)
565 // Make this thread recognisable as the networking thread
566 RenameThread("novacoin-net");
570 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
571 ThreadSocketHandler2(parg);
572 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
574 catch (std::exception& e) {
575 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
576 PrintException(&e, "ThreadSocketHandler()");
578 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
579 throw; // support pthread_cancel()
581 printf("ThreadSocketHandler exited\n");
584 void ThreadSocketHandler2(void* parg)
586 printf("ThreadSocketHandler started\n");
587 list<CNode*> vNodesDisconnected;
588 unsigned int nPrevNodeCount = 0;
597 // Disconnect unused nodes
598 vector<CNode*> vNodesCopy = vNodes;
599 BOOST_FOREACH(CNode* pnode, vNodesCopy)
601 if (pnode->fDisconnect ||
602 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
604 // remove from vNodes
605 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
607 // release outbound grant (if any)
608 pnode->grantOutbound.Release();
610 // close socket and cleanup
611 pnode->CloseSocketDisconnect();
614 // hold in disconnected pool until all refs are released
615 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
616 if (pnode->fNetworkNode || pnode->fInbound)
618 vNodesDisconnected.push_back(pnode);
622 // Delete disconnected nodes
623 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
624 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
626 // wait until threads are done using it
627 if (pnode->GetRefCount() <= 0)
629 bool fDelete = false;
631 TRY_LOCK(pnode->cs_vSend, lockSend);
634 TRY_LOCK(pnode->cs_vRecv, lockRecv);
637 TRY_LOCK(pnode->cs_mapRequests, lockReq);
640 TRY_LOCK(pnode->cs_inventory, lockInv);
649 vNodesDisconnected.remove(pnode);
655 if (vNodes.size() != nPrevNodeCount)
657 nPrevNodeCount = vNodes.size();
658 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
663 // Find which sockets have data to receive
665 struct timeval timeout;
667 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
674 FD_ZERO(&fdsetError);
675 SOCKET hSocketMax = 0;
676 bool have_fds = false;
678 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
679 FD_SET(hListenSocket, &fdsetRecv);
680 hSocketMax = max(hSocketMax, hListenSocket);
685 BOOST_FOREACH(CNode* pnode, vNodes)
687 if (pnode->hSocket == INVALID_SOCKET)
689 FD_SET(pnode->hSocket, &fdsetRecv);
690 FD_SET(pnode->hSocket, &fdsetError);
691 hSocketMax = max(hSocketMax, pnode->hSocket);
694 TRY_LOCK(pnode->cs_vSend, lockSend);
695 if (lockSend && !pnode->vSend.empty())
696 FD_SET(pnode->hSocket, &fdsetSend);
701 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
702 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
703 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
704 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
707 if (nSelect == SOCKET_ERROR)
711 int nErr = WSAGetLastError();
712 printf("socket select error %d\n", nErr);
713 for (unsigned int i = 0; i <= hSocketMax; i++)
714 FD_SET(i, &fdsetRecv);
717 FD_ZERO(&fdsetError);
718 Sleep(timeout.tv_usec/1000);
723 // Accept new connections
725 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
726 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
729 struct sockaddr_storage sockaddr;
731 struct sockaddr sockaddr;
733 socklen_t len = sizeof(sockaddr);
734 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
738 if (hSocket != INVALID_SOCKET)
739 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
740 printf("Warning: Unknown socket family\n");
744 BOOST_FOREACH(CNode* pnode, vNodes)
749 if (hSocket == INVALID_SOCKET)
751 int nErr = WSAGetLastError();
752 if (nErr != WSAEWOULDBLOCK)
753 printf("socket error accept failed: %d\n", nErr);
755 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
758 LOCK(cs_setservAddNodeAddresses);
759 if (!setservAddNodeAddresses.count(addr))
760 closesocket(hSocket);
763 else if (CNode::IsBanned(addr))
765 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
766 closesocket(hSocket);
770 printf("accepted connection %s\n", addr.ToString().c_str());
771 CNode* pnode = new CNode(hSocket, addr, "", true);
775 vNodes.push_back(pnode);
782 // Service each socket
784 vector<CNode*> vNodesCopy;
788 BOOST_FOREACH(CNode* pnode, vNodesCopy)
791 BOOST_FOREACH(CNode* pnode, vNodesCopy)
799 if (pnode->hSocket == INVALID_SOCKET)
801 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
803 TRY_LOCK(pnode->cs_vRecv, lockRecv);
806 CDataStream& vRecv = pnode->vRecv;
807 unsigned int nPos = vRecv.size();
809 if (nPos > ReceiveBufferSize()) {
810 if (!pnode->fDisconnect)
811 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
812 pnode->CloseSocketDisconnect();
815 // typical socket buffer is 8K-64K
816 char pchBuf[0x10000];
817 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
820 vRecv.resize(nPos + nBytes);
821 memcpy(&vRecv[nPos], pchBuf, nBytes);
822 pnode->nLastRecv = GetTime();
823 pnode->nRecvBytes += nBytes;
824 pnode->RecordBytesRecv(nBytes);
826 else if (nBytes == 0)
828 // socket closed gracefully
829 if (!pnode->fDisconnect)
830 printf("socket closed\n");
831 pnode->CloseSocketDisconnect();
836 int nErr = WSAGetLastError();
837 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
839 if (!pnode->fDisconnect)
840 printf("socket recv error %d\n", nErr);
841 pnode->CloseSocketDisconnect();
851 if (pnode->hSocket == INVALID_SOCKET)
853 if (FD_ISSET(pnode->hSocket, &fdsetSend))
855 TRY_LOCK(pnode->cs_vSend, lockSend);
858 CDataStream& vSend = pnode->vSend;
861 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
864 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
865 pnode->nLastSend = GetTime();
866 pnode->nSendBytes += nBytes;
867 pnode->RecordBytesSent(nBytes);
872 int nErr = WSAGetLastError();
873 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
875 printf("socket send error %d\n", nErr);
876 pnode->CloseSocketDisconnect();
884 // Inactivity checking
886 if (pnode->vSend.empty())
887 pnode->nLastSendEmpty = GetTime();
888 if (GetTime() - pnode->nTimeConnected > 60)
890 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
892 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
893 pnode->fDisconnect = true;
895 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
897 printf("socket not sending\n");
898 pnode->fDisconnect = true;
900 else if (GetTime() - pnode->nLastRecv > 90*60)
902 printf("socket inactivity timeout\n");
903 pnode->fDisconnect = true;
909 BOOST_FOREACH(CNode* pnode, vNodesCopy)
926 void ThreadMapPort(void* parg)
928 // Make this thread recognisable as the UPnP thread
929 RenameThread("novacoin-UPnP");
933 vnThreadsRunning[THREAD_UPNP]++;
934 ThreadMapPort2(parg);
935 vnThreadsRunning[THREAD_UPNP]--;
937 catch (std::exception& e) {
938 vnThreadsRunning[THREAD_UPNP]--;
939 PrintException(&e, "ThreadMapPort()");
941 vnThreadsRunning[THREAD_UPNP]--;
942 PrintException(NULL, "ThreadMapPort()");
944 printf("ThreadMapPort exited\n");
947 void ThreadMapPort2(void* parg)
949 printf("ThreadMapPort started\n");
951 std::string port = strprintf("%u", GetListenPort());
952 const char * multicastif = 0;
953 const char * minissdpdpath = 0;
954 struct UPNPDev * devlist = 0;
957 #ifndef UPNPDISCOVER_SUCCESS
959 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
963 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
966 struct UPNPUrls urls;
967 struct IGDdatas data;
970 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
974 char externalIPAddress[40];
975 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
976 if(r != UPNPCOMMAND_SUCCESS)
977 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
980 if(externalIPAddress[0])
982 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
983 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
986 printf("UPnP: GetExternalIPAddress failed.\n");
990 string strDesc = "NovaCoin " + FormatFullVersion();
991 #ifndef UPNPDISCOVER_SUCCESS
993 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
994 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
997 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
998 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1001 if(r!=UPNPCOMMAND_SUCCESS)
1002 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1003 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1005 printf("UPnP Port Mapping successful.\n");
1009 if (fShutdown || !fUseUPnP)
1011 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1012 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1013 freeUPNPDevlist(devlist); devlist = 0;
1014 FreeUPNPUrls(&urls);
1017 if (i % 600 == 0) // Refresh every 20 minutes
1019 #ifndef UPNPDISCOVER_SUCCESS
1021 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1022 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1025 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1026 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1029 if(r!=UPNPCOMMAND_SUCCESS)
1030 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1031 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1033 printf("UPnP Port Mapping successful.\n");;
1039 printf("No valid UPnP IGDs found\n");
1040 freeUPNPDevlist(devlist); devlist = 0;
1042 FreeUPNPUrls(&urls);
1045 if (fShutdown || !fUseUPnP)
1054 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1056 if (!NewThread(ThreadMapPort, NULL))
1057 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1063 // Intentionally left blank.
1076 // Each pair gives a source name and a seed name.
1077 // The first name is used as information source for addrman.
1078 // The second name should resolve to a list of seed addresses.
1079 static const char *strDNSSeed[][2] = {
1080 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1081 {"novacoin.su", "dnsseed.novacoin.su"},
1082 {"novacoin.ru", "dnsseed.novacoin.ru"},
1083 {"novacoin.ru", "testseed.novacoin.ru"},
1084 {"novaco.in", "dnsseed.novaco.in"},
1087 void ThreadDNSAddressSeed(void* parg)
1089 // Make this thread recognisable as the DNS seeding thread
1090 RenameThread("novacoin-dnsseed");
1094 vnThreadsRunning[THREAD_DNSSEED]++;
1095 ThreadDNSAddressSeed2(parg);
1096 vnThreadsRunning[THREAD_DNSSEED]--;
1098 catch (std::exception& e) {
1099 vnThreadsRunning[THREAD_DNSSEED]--;
1100 PrintException(&e, "ThreadDNSAddressSeed()");
1102 vnThreadsRunning[THREAD_DNSSEED]--;
1103 throw; // support pthread_cancel()
1105 printf("ThreadDNSAddressSeed exited\n");
1108 void ThreadDNSAddressSeed2(void* parg)
1110 printf("ThreadDNSAddressSeed started\n");
1115 printf("Loading addresses from DNS seeds (could take a while)\n");
1117 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1118 if (HaveNameProxy()) {
1119 AddOneShot(strDNSSeed[seed_idx][1]);
1121 vector<CNetAddr> vaddr;
1122 vector<CAddress> vAdd;
1123 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1125 BOOST_FOREACH(CNetAddr& ip, vaddr)
1127 int nOneDay = 24*3600;
1128 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1129 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1130 vAdd.push_back(addr);
1134 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1139 printf("%d addresses found from DNS seeds\n", found);
1153 unsigned int pnSeed[] =
1155 0x5360a653, 0x6c47bb25, 0x52568c5f, 0xc6f5c851, 0x6f17f3a2, 0x1d52a9d5, 0x2c1544c1, 0xb8748368,
1156 0x055d6ac1, 0x2490bb25, 0x614488d5, 0xa463f8a2, 0xc54c1256, 0xf72d9252, 0x548432c6, 0xade08368,
1157 0x02bf8f55, 0x79f81c48, 0xeb44a26d, 0x802c0856, 0xe3a8d772, 0xc661c852, 0xde30d4b0, 0x1044d079,
1158 0xa1e1485d, 0x269d5e02, 0x65ec8b5b, 0x4b78a605, 0xac9a1f5f, 0x307c7db0, 0xb75d4880, 0x31aaef53,
1159 0xe9433eb0, 0x8ce0861f, 0x1874695f, 0x6baef986, 0x06cfbf2e, 0x6c2e0082, 0x15e024b0, 0x0d0986bc,
1160 0xe7002d48, 0x064b2d05, 0xba568c5f, 0x3c93fa18, 0xfae6234d, 0xb06f5d02, 0x34e25d02, 0x559425b0,
1161 0x308eae6e, 0x48e15d02, 0x87fee36d, 0x647f5e02, 0xcbfe61bc, 0x3bf377d4, 0x1543075b, 0x3ee84980,
1162 0xde26482e, 0x66a65e02, 0x60cf0fb0, 0xf74c8e4f, 0x88d39a5e, 0x1c385e02, 0x62c4f460, 0x5b26df48,
1163 0x5249515d, 0x2b353f7d, 0xb6e34980, 0x5e7cd23e, 0x5ecc5e02, 0x9349515d, 0x31abbf2e, 0xa8675cb6,
1164 0xa8ce4762, 0x09e5d4b0, 0x6db26805, 0xb4f45d02, 0xfe07e555, 0xb6ab40bc, 0x8be25d02, 0x92bd345f,
1165 0x7122306c, 0x9254c248, 0x8dcc5e02, 0x0d1d5d02, 0x35a2805f, 0x404ef986, 0x5dab696d, 0xf153ad2e,
1166 0xc5c7a988, 0xfafd6d4a, 0xf172a7be, 0x09627bd9, 0x747d695f, 0xaa4a5d02, 0x4d226805, 0x6bb40ab9,
1170 void DumpAddresses()
1172 int64_t nStart = GetTimeMillis();
1177 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1178 addrman.size(), GetTimeMillis() - nStart);
1181 void ThreadDumpAddress2(void* parg)
1183 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1187 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1189 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1191 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1194 void ThreadDumpAddress(void* parg)
1196 // Make this thread recognisable as the address dumping thread
1197 RenameThread("novacoin-adrdump");
1201 ThreadDumpAddress2(parg);
1203 catch (std::exception& e) {
1204 PrintException(&e, "ThreadDumpAddress()");
1206 printf("ThreadDumpAddress exited\n");
1209 void ThreadOpenConnections(void* parg)
1211 // Make this thread recognisable as the connection opening thread
1212 RenameThread("novacoin-opencon");
1216 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1217 ThreadOpenConnections2(parg);
1218 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1220 catch (std::exception& e) {
1221 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1222 PrintException(&e, "ThreadOpenConnections()");
1224 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1225 PrintException(NULL, "ThreadOpenConnections()");
1227 printf("ThreadOpenConnections exited\n");
1230 void static ProcessOneShot()
1235 if (vOneShots.empty())
1237 strDest = vOneShots.front();
1238 vOneShots.pop_front();
1241 CSemaphoreGrant grant(*semOutbound, true);
1243 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1244 AddOneShot(strDest);
1248 // ppcoin: stake minter thread
1249 void static ThreadStakeMinter(void* parg)
1251 printf("ThreadStakeMinter started\n");
1252 CWallet* pwallet = (CWallet*)parg;
1255 vnThreadsRunning[THREAD_MINTER]++;
1256 StakeMiner(pwallet);
1257 vnThreadsRunning[THREAD_MINTER]--;
1259 catch (std::exception& e) {
1260 vnThreadsRunning[THREAD_MINTER]--;
1261 PrintException(&e, "ThreadStakeMinter()");
1263 vnThreadsRunning[THREAD_MINTER]--;
1264 PrintException(NULL, "ThreadStakeMinter()");
1266 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1269 void ThreadOpenConnections2(void* parg)
1271 printf("ThreadOpenConnections started\n");
1273 // Connect to specific addresses
1274 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1276 for (int64_t nLoop = 0;; nLoop++)
1279 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1282 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1283 for (int i = 0; i < 10 && i < nLoop; i++)
1294 // Initiate network connections
1295 int64_t nStart = GetTime();
1300 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1302 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1307 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1308 CSemaphoreGrant grant(*semOutbound);
1309 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1313 // Add seed nodes if IRC isn't working
1314 if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1316 std::vector<CAddress> vAdd;
1317 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1319 // It'll only connect to one or two seed nodes because once it connects,
1320 // it'll get a pile of addresses with newer timestamps.
1321 // Seed nodes are given a random 'last seen time' of between one and two
1323 const int64_t nOneWeek = 7*24*60*60;
1325 memcpy(&ip, &pnSeed[i], sizeof(ip));
1326 CAddress addr(CService(ip, GetDefaultPort()));
1327 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1328 vAdd.push_back(addr);
1330 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1334 // Choose an address to connect to based on most recently seen
1336 CAddress addrConnect;
1338 // Only connect out to one peer per network group (/16 for IPv4).
1339 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1341 set<vector<unsigned char> > setConnected;
1344 BOOST_FOREACH(CNode* pnode, vNodes) {
1345 if (!pnode->fInbound) {
1346 setConnected.insert(pnode->addr.GetGroup());
1352 int64_t nANow = GetAdjustedTime();
1357 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1358 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1360 // if we selected an invalid address, restart
1361 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1364 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1365 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1366 // already-connected network ranges, ...) before trying new addrman addresses.
1371 if (IsLimited(addr))
1374 // only consider very recently tried nodes after 30 failed attempts
1375 if (nANow - addr.nLastTry < 600 && nTries < 30)
1378 // do not allow non-default ports, unless after 50 invalid addresses selected already
1379 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1386 if (addrConnect.IsValid())
1387 OpenNetworkConnection(addrConnect, &grant);
1391 void ThreadOpenAddedConnections(void* parg)
1393 // Make this thread recognisable as the connection opening thread
1394 RenameThread("novacoin-opencon");
1398 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1399 ThreadOpenAddedConnections2(parg);
1400 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1402 catch (std::exception& e) {
1403 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1404 PrintException(&e, "ThreadOpenAddedConnections()");
1406 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1407 PrintException(NULL, "ThreadOpenAddedConnections()");
1409 printf("ThreadOpenAddedConnections exited\n");
1412 void ThreadOpenAddedConnections2(void* parg)
1414 printf("ThreadOpenAddedConnections started\n");
1416 if (mapArgs.count("-addnode") == 0)
1419 if (HaveNameProxy()) {
1421 BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) {
1423 CSemaphoreGrant grant(*semOutbound);
1424 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1427 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1428 Sleep(120000); // Retry every 2 minutes
1429 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1434 vector<vector<CService> > vservAddressesToAdd(0);
1435 BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
1437 vector<CService> vservNode(0);
1438 if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1440 vservAddressesToAdd.push_back(vservNode);
1442 LOCK(cs_setservAddNodeAddresses);
1443 BOOST_FOREACH(CService& serv, vservNode)
1444 setservAddNodeAddresses.insert(serv);
1450 vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
1451 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1452 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1455 BOOST_FOREACH(CNode* pnode, vNodes)
1456 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
1457 BOOST_FOREACH(CService& addrNode, *(it))
1458 if (pnode->addr == addrNode)
1460 it = vservConnectAddresses.erase(it);
1465 BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
1467 CSemaphoreGrant grant(*semOutbound);
1468 OpenNetworkConnection(CAddress(*(vserv.begin())), &grant);
1475 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1476 Sleep(120000); // Retry every 2 minutes
1477 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1483 // if successful, this moves the passed grant to the constructed node
1484 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1487 // Initiate outbound network connection
1492 if (IsLocal(addrConnect) ||
1493 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1494 FindNode(addrConnect.ToStringIPPort().c_str()))
1496 if (strDest && FindNode(strDest))
1499 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1500 CNode* pnode = ConnectNode(addrConnect, strDest);
1501 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1507 grantOutbound->MoveTo(pnode->grantOutbound);
1508 pnode->fNetworkNode = true;
1510 pnode->fOneShot = true;
1515 // for now, use a very simple selection metric: the node from which we received
1517 double static NodeSyncScore(const CNode *pnode) {
1518 return -pnode->nLastRecv;
1521 void static StartSync(const vector<CNode*> &vNodes) {
1522 CNode *pnodeNewSync = NULL;
1523 double dBestScore = 0;
1525 // Iterate over all nodes
1526 BOOST_FOREACH(CNode* pnode, vNodes) {
1527 // check preconditions for allowing a sync
1528 if (!pnode->fClient && !pnode->fOneShot &&
1529 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1530 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1531 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1532 // if ok, compare node's score with the best so far
1533 double dScore = NodeSyncScore(pnode);
1534 if (pnodeNewSync == NULL || dScore > dBestScore) {
1535 pnodeNewSync = pnode;
1536 dBestScore = dScore;
1540 // if a new sync candidate was found, start sync!
1542 pnodeNewSync->fStartSync = true;
1543 pnodeSync = pnodeNewSync;
1547 void ThreadMessageHandler(void* parg)
1549 // Make this thread recognisable as the message handling thread
1550 RenameThread("novacoin-msghand");
1554 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1555 ThreadMessageHandler2(parg);
1556 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1558 catch (std::exception& e) {
1559 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1560 PrintException(&e, "ThreadMessageHandler()");
1562 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1563 PrintException(NULL, "ThreadMessageHandler()");
1565 printf("ThreadMessageHandler exited\n");
1568 void ThreadMessageHandler2(void* parg)
1570 printf("ThreadMessageHandler started\n");
1571 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1574 bool fHaveSyncNode = false;
1575 vector<CNode*> vNodesCopy;
1578 vNodesCopy = vNodes;
1579 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1581 if (pnode == pnodeSync)
1582 fHaveSyncNode = true;
1587 StartSync(vNodesCopy);
1589 // Poll the connected nodes for messages
1590 CNode* pnodeTrickle = NULL;
1591 if (!vNodesCopy.empty())
1592 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1593 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1597 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1599 ProcessMessages(pnode);
1606 TRY_LOCK(pnode->cs_vSend, lockSend);
1608 SendMessages(pnode, pnode == pnodeTrickle);
1616 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1620 // Wait and allow messages to bunch up.
1621 // Reduce vnThreadsRunning so StopNode has permission to exit while
1622 // we're sleeping, but we must always check fShutdown after doing this.
1623 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1625 if (fRequestShutdown)
1627 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1638 bool BindListenPort(const CService &addrBind, string& strError)
1644 // Initialize Windows Sockets
1646 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1647 if (ret != NO_ERROR)
1649 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1650 printf("%s\n", strError.c_str());
1655 // Create socket for listening for incoming connections
1657 struct sockaddr_storage sockaddr;
1659 struct sockaddr sockaddr;
1661 socklen_t len = sizeof(sockaddr);
1662 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1664 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1665 printf("%s\n", strError.c_str());
1669 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1670 if (hListenSocket == INVALID_SOCKET)
1672 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1673 printf("%s\n", strError.c_str());
1678 // Different way of disabling SIGPIPE on BSD
1679 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1683 // Allow binding if the port is still in TIME_WAIT state after
1684 // the program was closed and restarted. Not an issue on windows.
1685 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1690 // Set to non-blocking, incoming connections will also inherit this
1691 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1693 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1696 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1697 printf("%s\n", strError.c_str());
1702 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1703 // and enable it by default or not. Try to enable it, if possible.
1704 if (addrBind.IsIPv6()) {
1707 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1709 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1713 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1714 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1715 // this call is allowed to fail
1716 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1721 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1723 int nErr = WSAGetLastError();
1724 if (nErr == WSAEADDRINUSE)
1725 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1727 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1728 printf("%s\n", strError.c_str());
1731 printf("Bound to %s\n", addrBind.ToString().c_str());
1733 // Listen for incoming connections
1734 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1736 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1737 printf("%s\n", strError.c_str());
1741 vhListenSocket.push_back(hListenSocket);
1743 if (addrBind.IsRoutable() && fDiscover)
1744 AddLocal(addrBind, LOCAL_BIND);
1749 void static Discover()
1755 // Get local host IP
1756 char pszHostName[1000] = "";
1757 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1759 vector<CNetAddr> vaddr;
1760 if (LookupHost(pszHostName, vaddr))
1762 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1764 AddLocal(addr, LOCAL_IF);
1769 // Get local host ip
1770 struct ifaddrs* myaddrs;
1771 if (getifaddrs(&myaddrs) == 0)
1773 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1775 if (ifa->ifa_addr == NULL) continue;
1776 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1777 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1778 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1779 if (ifa->ifa_addr->sa_family == AF_INET)
1781 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1782 CNetAddr addr(s4->sin_addr);
1783 if (AddLocal(addr, LOCAL_IF))
1784 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1787 else if (ifa->ifa_addr->sa_family == AF_INET6)
1789 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1790 CNetAddr addr(s6->sin6_addr);
1791 if (AddLocal(addr, LOCAL_IF))
1792 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1796 freeifaddrs(myaddrs);
1800 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1801 if (!IsLimited(NET_IPV4))
1802 NewThread(ThreadGetMyExternalIP, NULL);
1805 void StartNode(void* parg)
1807 // Make this thread recognisable as the startup thread
1808 RenameThread("novacoin-start");
1810 if (semOutbound == NULL) {
1811 // initialize semaphore
1812 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1813 semOutbound = new CSemaphore(nMaxOutbound);
1816 if (pnodeLocalHost == NULL)
1817 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1825 if (!GetBoolArg("-dnsseed", true))
1826 printf("DNS seeding disabled\n");
1828 if (!NewThread(ThreadDNSAddressSeed, NULL))
1829 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1831 // Map ports with UPnP
1835 // Get addresses from IRC and advertise ours
1836 if (!NewThread(ThreadIRCSeed, NULL))
1837 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1839 // Send and receive from sockets, accept connections
1840 if (!NewThread(ThreadSocketHandler, NULL))
1841 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1843 // Initiate outbound connections from -addnode
1844 if (!NewThread(ThreadOpenAddedConnections, NULL))
1845 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1847 // Initiate outbound connections
1848 if (!NewThread(ThreadOpenConnections, NULL))
1849 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1852 if (!NewThread(ThreadMessageHandler, NULL))
1853 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1855 // Dump network addresses
1856 if (!NewThread(ThreadDumpAddress, NULL))
1857 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1859 // ppcoin: mint proof-of-stake blocks in the background
1860 if (!NewThread(ThreadStakeMinter, pwalletMain))
1861 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1866 printf("StopNode()\n");
1868 nTransactionsUpdated++;
1869 int64_t nStart = GetTime();
1872 ThreadScriptCheckQuit();
1875 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1876 semOutbound->post();
1879 int nThreadsRunning = 0;
1880 for (int n = 0; n < THREAD_MAX; n++)
1881 nThreadsRunning += vnThreadsRunning[n];
1882 if (nThreadsRunning == 0)
1884 if (GetTime() - nStart > 20)
1888 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1889 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1890 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1891 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1892 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1894 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1896 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1897 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1898 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1899 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1900 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1901 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1917 BOOST_FOREACH(CNode* pnode, vNodes)
1918 if (pnode->hSocket != INVALID_SOCKET)
1919 closesocket(pnode->hSocket);
1920 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1921 if (hListenSocket != INVALID_SOCKET)
1922 if (closesocket(hListenSocket) == SOCKET_ERROR)
1923 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1926 // Shutdown Windows Sockets
1931 instance_of_cnetcleanup;
1933 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1935 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1938 RelayTransaction(tx, hash, ss);
1941 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1943 CInv inv(MSG_TX, hash);
1946 // Expire old relay messages
1947 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1949 mapRelay.erase(vRelayExpiration.front().second);
1950 vRelayExpiration.pop_front();
1953 // Save original serialized message so newer versions are preserved
1954 mapRelay.insert(std::make_pair(inv, ss));
1955 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1958 RelayInventory(inv);
1961 void CNode::RecordBytesRecv(uint64_t bytes)
1963 LOCK(cs_totalBytesRecv);
1964 nTotalBytesRecv += bytes;
1967 void CNode::RecordBytesSent(uint64_t bytes)
1969 LOCK(cs_totalBytesSent);
1970 nTotalBytesSent += bytes;
1973 uint64_t CNode::GetTotalBytesRecv()
1975 LOCK(cs_totalBytesRecv);
1976 return nTotalBytesRecv;
1979 uint64_t CNode::GetTotalBytesSent()
1981 LOCK(cs_totalBytesSent);
1982 return nTotalBytesSent;