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 vector<std::string> vAddedNodes;
79 CCriticalSection cs_vAddedNodes;
81 static CSemaphore *semOutbound = NULL;
83 void AddOneShot(string strDest)
86 vOneShots.push_back(strDest);
89 unsigned short GetListenPort()
91 return (unsigned short)(GetArg("-port", GetDefaultPort()));
94 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
96 // Filter out duplicate requests
97 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
99 pindexLastGetBlocksBegin = pindexBegin;
100 hashLastGetBlocksEnd = hashEnd;
102 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
105 // find 'best' local address for a particular peer
106 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
112 int nBestReachability = -1;
114 LOCK(cs_mapLocalHost);
115 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
117 int nScore = (*it).second.nScore;
118 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
119 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
121 addr = CService((*it).first, (*it).second.nPort);
122 nBestReachability = nReachability;
127 return nBestScore >= 0;
130 // get best local address for a particular peer as a CAddress
131 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
133 CAddress ret(CService("0.0.0.0",0),0);
135 if (GetLocal(addr, paddrPeer))
137 ret = CAddress(addr);
138 ret.nServices = nLocalServices;
139 ret.nTime = GetAdjustedTime();
144 bool RecvLine(SOCKET hSocket, string& strLine)
150 int nBytes = recv(hSocket, &c, 1, 0);
158 if (strLine.size() >= 9000)
161 else if (nBytes <= 0)
167 int nErr = WSAGetLastError();
168 if (nErr == WSAEMSGSIZE)
170 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
176 if (!strLine.empty())
181 printf("socket closed\n");
187 int nErr = WSAGetLastError();
188 printf("recv failed: %d\n", nErr);
195 // used when scores of local addresses may have changed
196 // pushes better local address to peers
197 void static AdvertizeLocal()
200 BOOST_FOREACH(CNode* pnode, vNodes)
202 if (pnode->fSuccessfullyConnected)
204 CAddress addrLocal = GetLocalAddress(&pnode->addr);
205 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
207 pnode->PushAddress(addrLocal);
208 pnode->addrLocal = addrLocal;
214 void SetReachable(enum Network net, bool fFlag)
216 LOCK(cs_mapLocalHost);
217 vfReachable[net] = fFlag;
218 if (net == NET_IPV6 && fFlag)
219 vfReachable[NET_IPV4] = true;
222 // learn a new local address
223 bool AddLocal(const CService& addr, int nScore)
225 if (!addr.IsRoutable())
228 if (!fDiscover && nScore < LOCAL_MANUAL)
234 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
237 LOCK(cs_mapLocalHost);
238 bool fAlready = mapLocalHost.count(addr) > 0;
239 LocalServiceInfo &info = mapLocalHost[addr];
240 if (!fAlready || nScore >= info.nScore) {
241 info.nScore = nScore + (fAlready ? 1 : 0);
242 info.nPort = addr.GetPort();
244 SetReachable(addr.GetNetwork());
252 bool AddLocal(const CNetAddr &addr, int nScore)
254 return AddLocal(CService(addr, GetListenPort()), nScore);
257 /** Make a particular network entirely off-limits (no automatic connects to it) */
258 void SetLimited(enum Network net, bool fLimited)
260 if (net == NET_UNROUTABLE)
262 LOCK(cs_mapLocalHost);
263 vfLimited[net] = fLimited;
266 bool IsLimited(enum Network net)
268 LOCK(cs_mapLocalHost);
269 return vfLimited[net];
272 bool IsLimited(const CNetAddr &addr)
274 return IsLimited(addr.GetNetwork());
277 /** vote for a local address */
278 bool SeenLocal(const CService& addr)
281 LOCK(cs_mapLocalHost);
282 if (mapLocalHost.count(addr) == 0)
284 mapLocalHost[addr].nScore++;
292 /** check whether a given address is potentially local */
293 bool IsLocal(const CService& addr)
295 LOCK(cs_mapLocalHost);
296 return mapLocalHost.count(addr) > 0;
299 /** check whether a given address is in a network we can probably connect to */
300 bool IsReachable(const CNetAddr& addr)
302 LOCK(cs_mapLocalHost);
303 enum Network net = addr.GetNetwork();
304 return vfReachable[net] && !vfLimited[net];
307 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
309 // We now get our external IP from the IRC server first and only use this as a backup
310 bool GetMyExternalIP(CNetAddr& ipRet)
312 struct sockaddr_in mapped;
313 uint64_t rnd = GetRand(~0LL);
315 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
317 ipRet = CNetAddr(mapped.sin_addr);
318 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
324 void ThreadGetMyExternalIP(void* parg)
326 // Make this thread recognisable as the external IP detection thread
327 RenameThread("novacoin-ext-ip");
329 CNetAddr addrLocalHost;
330 if (GetMyExternalIP(addrLocalHost))
332 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
333 AddLocal(addrLocalHost, LOCAL_HTTP);
341 void AddressCurrentlyConnected(const CService& addr)
343 addrman.Connected(addr);
349 uint64_t CNode::nTotalBytesRecv = 0;
350 uint64_t CNode::nTotalBytesSent = 0;
351 CCriticalSection CNode::cs_totalBytesRecv;
352 CCriticalSection CNode::cs_totalBytesSent;
354 CNode* FindNode(const CNetAddr& ip)
357 BOOST_FOREACH(CNode* pnode, vNodes)
358 if ((CNetAddr)pnode->addr == ip)
363 CNode* FindNode(std::string addrName)
366 BOOST_FOREACH(CNode* pnode, vNodes)
367 if (pnode->addrName == addrName)
372 CNode* FindNode(const CService& addr)
375 BOOST_FOREACH(CNode* pnode, vNodes)
376 if ((CService)pnode->addr == addr)
381 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
383 if (pszDest == NULL) {
384 if (IsLocal(addrConnect))
387 // Look for an existing connection
388 CNode* pnode = FindNode((CService)addrConnect);
392 pnode->AddRef(nTimeout);
401 printf("trying connection %s lastseen=%.1fhrs\n",
402 pszDest ? pszDest : addrConnect.ToString().c_str(),
403 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
407 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
409 addrman.Attempt(addrConnect);
412 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
414 // Set to non-blocking
417 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
418 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
420 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
421 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
425 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
427 pnode->AddRef(nTimeout);
433 vNodes.push_back(pnode);
436 pnode->nTimeConnected = GetTime();
445 void CNode::CloseSocketDisconnect()
448 if (hSocket != INVALID_SOCKET)
450 printf("disconnecting node %s\n", addrName.c_str());
451 closesocket(hSocket);
452 hSocket = INVALID_SOCKET;
456 // in case this fails, we'll empty the recv buffer when the CNode is deleted
457 TRY_LOCK(cs_vRecv, lockRecv);
461 // if this was the sync node, we'll need a new one
462 if (this == pnodeSync)
466 void CNode::Cleanup()
471 void CNode::PushVersion()
473 /// when NTP implemented, change to just nTime = GetAdjustedTime()
474 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
475 CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
476 CAddress addrMe = GetLocalAddress(&addr);
477 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
478 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());
479 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
480 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
487 std::map<CNetAddr, int64_t> CNode::setBanned;
488 CCriticalSection CNode::cs_setBanned;
490 void CNode::ClearBanned()
495 bool CNode::IsBanned(CNetAddr ip)
497 bool fResult = false;
500 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
501 if (i != setBanned.end())
503 int64_t t = (*i).second;
511 bool CNode::Misbehaving(int howmuch)
515 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
519 nMisbehavior += howmuch;
520 if (nMisbehavior >= GetArg("-banscore", 100))
522 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
523 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
526 if (setBanned[addr] < banTime)
527 setBanned[addr] = banTime;
529 CloseSocketDisconnect();
532 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
537 #define X(name) stats.name = name
538 void CNode::copyStats(CNodeStats &stats)
553 stats.fSyncNode = (this == pnodeSync);
566 void ThreadSocketHandler(void* parg)
568 // Make this thread recognisable as the networking thread
569 RenameThread("novacoin-net");
573 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
574 ThreadSocketHandler2(parg);
575 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
577 catch (std::exception& e) {
578 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
579 PrintException(&e, "ThreadSocketHandler()");
581 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
582 throw; // support pthread_cancel()
584 printf("ThreadSocketHandler exited\n");
587 void ThreadSocketHandler2(void* parg)
589 printf("ThreadSocketHandler started\n");
590 list<CNode*> vNodesDisconnected;
591 unsigned int nPrevNodeCount = 0;
600 // Disconnect unused nodes
601 vector<CNode*> vNodesCopy = vNodes;
602 BOOST_FOREACH(CNode* pnode, vNodesCopy)
604 if (pnode->fDisconnect ||
605 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
607 // remove from vNodes
608 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
610 // release outbound grant (if any)
611 pnode->grantOutbound.Release();
613 // close socket and cleanup
614 pnode->CloseSocketDisconnect();
617 // hold in disconnected pool until all refs are released
618 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
619 if (pnode->fNetworkNode || pnode->fInbound)
621 vNodesDisconnected.push_back(pnode);
625 // Delete disconnected nodes
626 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
627 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
629 // wait until threads are done using it
630 if (pnode->GetRefCount() <= 0)
632 bool fDelete = false;
634 TRY_LOCK(pnode->cs_vSend, lockSend);
637 TRY_LOCK(pnode->cs_vRecv, lockRecv);
640 TRY_LOCK(pnode->cs_mapRequests, lockReq);
643 TRY_LOCK(pnode->cs_inventory, lockInv);
652 vNodesDisconnected.remove(pnode);
658 if (vNodes.size() != nPrevNodeCount)
660 nPrevNodeCount = vNodes.size();
661 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
666 // Find which sockets have data to receive
668 struct timeval timeout;
670 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
677 FD_ZERO(&fdsetError);
678 SOCKET hSocketMax = 0;
679 bool have_fds = false;
681 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
682 FD_SET(hListenSocket, &fdsetRecv);
683 hSocketMax = max(hSocketMax, hListenSocket);
688 BOOST_FOREACH(CNode* pnode, vNodes)
690 if (pnode->hSocket == INVALID_SOCKET)
692 FD_SET(pnode->hSocket, &fdsetRecv);
693 FD_SET(pnode->hSocket, &fdsetError);
694 hSocketMax = max(hSocketMax, pnode->hSocket);
697 TRY_LOCK(pnode->cs_vSend, lockSend);
698 if (lockSend && !pnode->vSend.empty())
699 FD_SET(pnode->hSocket, &fdsetSend);
704 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
705 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
706 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
707 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
710 if (nSelect == SOCKET_ERROR)
714 int nErr = WSAGetLastError();
715 printf("socket select error %d\n", nErr);
716 for (unsigned int i = 0; i <= hSocketMax; i++)
717 FD_SET(i, &fdsetRecv);
720 FD_ZERO(&fdsetError);
721 Sleep(timeout.tv_usec/1000);
726 // Accept new connections
728 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
729 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
732 struct sockaddr_storage sockaddr;
734 struct sockaddr sockaddr;
736 socklen_t len = sizeof(sockaddr);
737 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
741 if (hSocket != INVALID_SOCKET)
742 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
743 printf("Warning: Unknown socket family\n");
747 BOOST_FOREACH(CNode* pnode, vNodes)
752 if (hSocket == INVALID_SOCKET)
754 int nErr = WSAGetLastError();
755 if (nErr != WSAEWOULDBLOCK)
756 printf("socket error accept failed: %d\n", nErr);
758 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
761 LOCK(cs_setservAddNodeAddresses);
762 if (!setservAddNodeAddresses.count(addr))
763 closesocket(hSocket);
766 else if (CNode::IsBanned(addr))
768 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
769 closesocket(hSocket);
773 printf("accepted connection %s\n", addr.ToString().c_str());
774 CNode* pnode = new CNode(hSocket, addr, "", true);
778 vNodes.push_back(pnode);
785 // Service each socket
787 vector<CNode*> vNodesCopy;
791 BOOST_FOREACH(CNode* pnode, vNodesCopy)
794 BOOST_FOREACH(CNode* pnode, vNodesCopy)
802 if (pnode->hSocket == INVALID_SOCKET)
804 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
806 TRY_LOCK(pnode->cs_vRecv, lockRecv);
809 CDataStream& vRecv = pnode->vRecv;
810 uint64_t nPos = vRecv.size();
812 if (nPos > ReceiveBufferSize()) {
813 if (!pnode->fDisconnect)
814 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
815 pnode->CloseSocketDisconnect();
818 // typical socket buffer is 8K-64K
819 char pchBuf[0x10000];
820 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
823 vRecv.resize(nPos + nBytes);
824 memcpy(&vRecv[nPos], pchBuf, nBytes);
825 pnode->nLastRecv = GetTime();
826 pnode->nRecvBytes += nBytes;
827 pnode->RecordBytesRecv(nBytes);
829 else if (nBytes == 0)
831 // socket closed gracefully
832 if (!pnode->fDisconnect)
833 printf("socket closed\n");
834 pnode->CloseSocketDisconnect();
839 int nErr = WSAGetLastError();
840 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
842 if (!pnode->fDisconnect)
843 printf("socket recv error %d\n", nErr);
844 pnode->CloseSocketDisconnect();
854 if (pnode->hSocket == INVALID_SOCKET)
856 if (FD_ISSET(pnode->hSocket, &fdsetSend))
858 TRY_LOCK(pnode->cs_vSend, lockSend);
861 CDataStream& vSend = pnode->vSend;
864 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
867 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
868 pnode->nLastSend = GetTime();
869 pnode->nSendBytes += nBytes;
870 pnode->RecordBytesSent(nBytes);
875 int nErr = WSAGetLastError();
876 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
878 printf("socket send error %d\n", nErr);
879 pnode->CloseSocketDisconnect();
887 // Inactivity checking
889 if (pnode->vSend.empty())
890 pnode->nLastSendEmpty = GetTime();
891 if (GetTime() - pnode->nTimeConnected > 60)
893 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
895 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
896 pnode->fDisconnect = true;
898 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
900 printf("socket not sending\n");
901 pnode->fDisconnect = true;
903 else if (GetTime() - pnode->nLastRecv > 90*60)
905 printf("socket inactivity timeout\n");
906 pnode->fDisconnect = true;
912 BOOST_FOREACH(CNode* pnode, vNodesCopy)
929 void ThreadMapPort(void* parg)
931 // Make this thread recognisable as the UPnP thread
932 RenameThread("novacoin-UPnP");
936 vnThreadsRunning[THREAD_UPNP]++;
937 ThreadMapPort2(parg);
938 vnThreadsRunning[THREAD_UPNP]--;
940 catch (std::exception& e) {
941 vnThreadsRunning[THREAD_UPNP]--;
942 PrintException(&e, "ThreadMapPort()");
944 vnThreadsRunning[THREAD_UPNP]--;
945 PrintException(NULL, "ThreadMapPort()");
947 printf("ThreadMapPort exited\n");
950 void ThreadMapPort2(void* parg)
952 printf("ThreadMapPort started\n");
954 std::string port = strprintf("%u", GetListenPort());
955 const char * multicastif = 0;
956 const char * minissdpdpath = 0;
957 struct UPNPDev * devlist = 0;
960 #ifndef UPNPDISCOVER_SUCCESS
962 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
966 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
969 struct UPNPUrls urls;
970 struct IGDdatas data;
973 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
977 char externalIPAddress[40];
978 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
979 if(r != UPNPCOMMAND_SUCCESS)
980 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
983 if(externalIPAddress[0])
985 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
986 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
989 printf("UPnP: GetExternalIPAddress failed.\n");
993 string strDesc = "NovaCoin " + FormatFullVersion();
994 #ifndef UPNPDISCOVER_SUCCESS
996 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
997 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1000 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1001 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1004 if(r!=UPNPCOMMAND_SUCCESS)
1005 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1006 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1008 printf("UPnP Port Mapping successful.\n");
1012 if (fShutdown || !fUseUPnP)
1014 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1015 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1016 freeUPNPDevlist(devlist); devlist = 0;
1017 FreeUPNPUrls(&urls);
1020 if (i % 600 == 0) // Refresh every 20 minutes
1022 #ifndef UPNPDISCOVER_SUCCESS
1024 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1025 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1028 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1029 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1032 if(r!=UPNPCOMMAND_SUCCESS)
1033 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1034 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1036 printf("UPnP Port Mapping successful.\n");;
1042 printf("No valid UPnP IGDs found\n");
1043 freeUPNPDevlist(devlist); devlist = 0;
1045 FreeUPNPUrls(&urls);
1048 if (fShutdown || !fUseUPnP)
1057 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1059 if (!NewThread(ThreadMapPort, NULL))
1060 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1066 // Intentionally left blank.
1079 // Each pair gives a source name and a seed name.
1080 // The first name is used as information source for addrman.
1081 // The second name should resolve to a list of seed addresses.
1082 static const char *strDNSSeed[][2] = {
1083 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1084 {"novacoin.su", "dnsseed.novacoin.su"},
1085 {"novacoin.ru", "dnsseed.novacoin.ru"},
1086 {"novacoin.ru", "testseed.novacoin.ru"},
1087 {"novaco.in", "dnsseed.novaco.in"},
1090 void ThreadDNSAddressSeed(void* parg)
1092 // Make this thread recognisable as the DNS seeding thread
1093 RenameThread("novacoin-dnsseed");
1097 vnThreadsRunning[THREAD_DNSSEED]++;
1098 ThreadDNSAddressSeed2(parg);
1099 vnThreadsRunning[THREAD_DNSSEED]--;
1101 catch (std::exception& e) {
1102 vnThreadsRunning[THREAD_DNSSEED]--;
1103 PrintException(&e, "ThreadDNSAddressSeed()");
1105 vnThreadsRunning[THREAD_DNSSEED]--;
1106 throw; // support pthread_cancel()
1108 printf("ThreadDNSAddressSeed exited\n");
1111 void ThreadDNSAddressSeed2(void* parg)
1113 printf("ThreadDNSAddressSeed started\n");
1118 printf("Loading addresses from DNS seeds (could take a while)\n");
1120 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1121 if (HaveNameProxy()) {
1122 AddOneShot(strDNSSeed[seed_idx][1]);
1124 vector<CNetAddr> vaddr;
1125 vector<CAddress> vAdd;
1126 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1128 BOOST_FOREACH(CNetAddr& ip, vaddr)
1130 int nOneDay = 24*3600;
1131 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1132 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1133 vAdd.push_back(addr);
1137 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1142 printf("%d addresses found from DNS seeds\n", found);
1158 0x5360a653, 0x6c47bb25, 0x52568c5f, 0xc6f5c851, 0x6f17f3a2, 0x1d52a9d5, 0x2c1544c1, 0xb8748368,
1159 0x055d6ac1, 0x2490bb25, 0x614488d5, 0xa463f8a2, 0xc54c1256, 0xf72d9252, 0x548432c6, 0xade08368,
1160 0x02bf8f55, 0x79f81c48, 0xeb44a26d, 0x802c0856, 0xe3a8d772, 0xc661c852, 0xde30d4b0, 0x1044d079,
1161 0xa1e1485d, 0x269d5e02, 0x65ec8b5b, 0x4b78a605, 0xac9a1f5f, 0x307c7db0, 0xb75d4880, 0x31aaef53,
1162 0xe9433eb0, 0x8ce0861f, 0x1874695f, 0x6baef986, 0x06cfbf2e, 0x6c2e0082, 0x15e024b0, 0x0d0986bc,
1163 0xe7002d48, 0x064b2d05, 0xba568c5f, 0x3c93fa18, 0xfae6234d, 0xb06f5d02, 0x34e25d02, 0x559425b0,
1164 0x308eae6e, 0x48e15d02, 0x87fee36d, 0x647f5e02, 0xcbfe61bc, 0x3bf377d4, 0x1543075b, 0x3ee84980,
1165 0xde26482e, 0x66a65e02, 0x60cf0fb0, 0xf74c8e4f, 0x88d39a5e, 0x1c385e02, 0x62c4f460, 0x5b26df48,
1166 0x5249515d, 0x2b353f7d, 0xb6e34980, 0x5e7cd23e, 0x5ecc5e02, 0x9349515d, 0x31abbf2e, 0xa8675cb6,
1167 0xa8ce4762, 0x09e5d4b0, 0x6db26805, 0xb4f45d02, 0xfe07e555, 0xb6ab40bc, 0x8be25d02, 0x92bd345f,
1168 0x7122306c, 0x9254c248, 0x8dcc5e02, 0x0d1d5d02, 0x35a2805f, 0x404ef986, 0x5dab696d, 0xf153ad2e,
1169 0xc5c7a988, 0xfafd6d4a, 0xf172a7be, 0x09627bd9, 0x747d695f, 0xaa4a5d02, 0x4d226805, 0x6bb40ab9,
1173 void DumpAddresses()
1175 int64_t nStart = GetTimeMillis();
1180 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1181 addrman.size(), GetTimeMillis() - nStart);
1184 void ThreadDumpAddress2(void* parg)
1186 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1190 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1192 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1194 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1197 void ThreadDumpAddress(void* parg)
1199 // Make this thread recognisable as the address dumping thread
1200 RenameThread("novacoin-adrdump");
1204 ThreadDumpAddress2(parg);
1206 catch (std::exception& e) {
1207 PrintException(&e, "ThreadDumpAddress()");
1209 printf("ThreadDumpAddress exited\n");
1212 void ThreadOpenConnections(void* parg)
1214 // Make this thread recognisable as the connection opening thread
1215 RenameThread("novacoin-opencon");
1219 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1220 ThreadOpenConnections2(parg);
1221 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1223 catch (std::exception& e) {
1224 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1225 PrintException(&e, "ThreadOpenConnections()");
1227 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1228 PrintException(NULL, "ThreadOpenConnections()");
1230 printf("ThreadOpenConnections exited\n");
1233 void static ProcessOneShot()
1238 if (vOneShots.empty())
1240 strDest = vOneShots.front();
1241 vOneShots.pop_front();
1244 CSemaphoreGrant grant(*semOutbound, true);
1246 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1247 AddOneShot(strDest);
1251 // ppcoin: stake minter thread
1252 void static ThreadStakeMinter(void* parg)
1254 printf("ThreadStakeMinter started\n");
1255 CWallet* pwallet = (CWallet*)parg;
1258 vnThreadsRunning[THREAD_MINTER]++;
1259 StakeMiner(pwallet);
1260 vnThreadsRunning[THREAD_MINTER]--;
1262 catch (std::exception& e) {
1263 vnThreadsRunning[THREAD_MINTER]--;
1264 PrintException(&e, "ThreadStakeMinter()");
1266 vnThreadsRunning[THREAD_MINTER]--;
1267 PrintException(NULL, "ThreadStakeMinter()");
1269 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1272 void ThreadOpenConnections2(void* parg)
1274 printf("ThreadOpenConnections started\n");
1276 // Connect to specific addresses
1277 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1279 for (int64_t nLoop = 0;; nLoop++)
1282 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1285 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1286 for (int i = 0; i < 10 && i < nLoop; i++)
1297 // Initiate network connections
1298 int64_t nStart = GetTime();
1303 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1305 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1310 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1311 CSemaphoreGrant grant(*semOutbound);
1312 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1316 // Add seed nodes if IRC isn't working
1317 if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1319 std::vector<CAddress> vAdd;
1320 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1322 // It'll only connect to one or two seed nodes because once it connects,
1323 // it'll get a pile of addresses with newer timestamps.
1324 // Seed nodes are given a random 'last seen time' of between one and two
1326 const int64_t nOneWeek = 7*24*60*60;
1328 memcpy(&ip, &pnSeed[i], sizeof(ip));
1329 CAddress addr(CService(ip, GetDefaultPort()));
1330 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1331 vAdd.push_back(addr);
1333 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1337 // Choose an address to connect to based on most recently seen
1339 CAddress addrConnect;
1341 // Only connect out to one peer per network group (/16 for IPv4).
1342 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1344 set<vector<unsigned char> > setConnected;
1347 BOOST_FOREACH(CNode* pnode, vNodes) {
1348 if (!pnode->fInbound) {
1349 setConnected.insert(pnode->addr.GetGroup());
1355 int64_t nANow = GetAdjustedTime();
1360 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1361 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1363 // if we selected an invalid address, restart
1364 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1367 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1368 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1369 // already-connected network ranges, ...) before trying new addrman addresses.
1374 if (IsLimited(addr))
1377 // only consider very recently tried nodes after 30 failed attempts
1378 if (nANow - addr.nLastTry < 600 && nTries < 30)
1381 // do not allow non-default ports, unless after 50 invalid addresses selected already
1382 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1389 if (addrConnect.IsValid())
1390 OpenNetworkConnection(addrConnect, &grant);
1394 void ThreadOpenAddedConnections(void* parg)
1396 // Make this thread recognisable as the connection opening thread
1397 RenameThread("novacoin-opencon");
1401 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1402 ThreadOpenAddedConnections2(parg);
1403 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1405 catch (std::exception& e) {
1406 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1407 PrintException(&e, "ThreadOpenAddedConnections()");
1409 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1410 PrintException(NULL, "ThreadOpenAddedConnections()");
1412 printf("ThreadOpenAddedConnections exited\n");
1415 void ThreadOpenAddedConnections2(void* parg)
1417 printf("ThreadOpenAddedConnections started\n");
1419 if (mapArgs.count("-addnode") == 0)
1422 if (HaveNameProxy()) {
1424 BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) {
1426 CSemaphoreGrant grant(*semOutbound);
1427 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1430 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1431 Sleep(120000); // Retry every 2 minutes
1432 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1437 vector<vector<CService> > vservAddressesToAdd(0);
1438 BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"])
1440 vector<CService> vservNode(0);
1441 if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1443 vservAddressesToAdd.push_back(vservNode);
1445 LOCK(cs_setservAddNodeAddresses);
1446 BOOST_FOREACH(CService& serv, vservNode)
1447 setservAddNodeAddresses.insert(serv);
1453 vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd;
1454 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1455 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1458 BOOST_FOREACH(CNode* pnode, vNodes)
1459 for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++)
1460 BOOST_FOREACH(CService& addrNode, *(it))
1461 if (pnode->addr == addrNode)
1463 it = vservConnectAddresses.erase(it);
1468 BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses)
1470 CSemaphoreGrant grant(*semOutbound);
1471 OpenNetworkConnection(CAddress(*(vserv.begin())), &grant);
1478 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1479 Sleep(120000); // Retry every 2 minutes
1480 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1486 // if successful, this moves the passed grant to the constructed node
1487 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1490 // Initiate outbound network connection
1495 if (IsLocal(addrConnect) ||
1496 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1497 FindNode(addrConnect.ToStringIPPort().c_str()))
1499 if (strDest && FindNode(strDest))
1502 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1503 CNode* pnode = ConnectNode(addrConnect, strDest);
1504 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1510 grantOutbound->MoveTo(pnode->grantOutbound);
1511 pnode->fNetworkNode = true;
1513 pnode->fOneShot = true;
1518 // for now, use a very simple selection metric: the node from which we received
1520 double static NodeSyncScore(const CNode *pnode) {
1521 return -pnode->nLastRecv;
1524 void static StartSync(const vector<CNode*> &vNodes) {
1525 CNode *pnodeNewSync = NULL;
1526 double dBestScore = 0;
1528 // Iterate over all nodes
1529 BOOST_FOREACH(CNode* pnode, vNodes) {
1530 // check preconditions for allowing a sync
1531 if (!pnode->fClient && !pnode->fOneShot &&
1532 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1533 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1534 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1535 // if ok, compare node's score with the best so far
1536 double dScore = NodeSyncScore(pnode);
1537 if (pnodeNewSync == NULL || dScore > dBestScore) {
1538 pnodeNewSync = pnode;
1539 dBestScore = dScore;
1543 // if a new sync candidate was found, start sync!
1545 pnodeNewSync->fStartSync = true;
1546 pnodeSync = pnodeNewSync;
1550 void ThreadMessageHandler(void* parg)
1552 // Make this thread recognisable as the message handling thread
1553 RenameThread("novacoin-msghand");
1557 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1558 ThreadMessageHandler2(parg);
1559 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1561 catch (std::exception& e) {
1562 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1563 PrintException(&e, "ThreadMessageHandler()");
1565 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1566 PrintException(NULL, "ThreadMessageHandler()");
1568 printf("ThreadMessageHandler exited\n");
1571 void ThreadMessageHandler2(void* parg)
1573 printf("ThreadMessageHandler started\n");
1574 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1577 bool fHaveSyncNode = false;
1578 vector<CNode*> vNodesCopy;
1581 vNodesCopy = vNodes;
1582 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1584 if (pnode == pnodeSync)
1585 fHaveSyncNode = true;
1590 StartSync(vNodesCopy);
1592 // Poll the connected nodes for messages
1593 CNode* pnodeTrickle = NULL;
1594 if (!vNodesCopy.empty())
1595 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1596 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1600 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1602 ProcessMessages(pnode);
1609 TRY_LOCK(pnode->cs_vSend, lockSend);
1611 SendMessages(pnode, pnode == pnodeTrickle);
1619 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1623 // Wait and allow messages to bunch up.
1624 // Reduce vnThreadsRunning so StopNode has permission to exit while
1625 // we're sleeping, but we must always check fShutdown after doing this.
1626 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1628 if (fRequestShutdown)
1630 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1641 bool BindListenPort(const CService &addrBind, string& strError)
1647 // Initialize Windows Sockets
1649 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1650 if (ret != NO_ERROR)
1652 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1653 printf("%s\n", strError.c_str());
1658 // Create socket for listening for incoming connections
1660 struct sockaddr_storage sockaddr;
1662 struct sockaddr sockaddr;
1664 socklen_t len = sizeof(sockaddr);
1665 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1667 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1668 printf("%s\n", strError.c_str());
1672 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1673 if (hListenSocket == INVALID_SOCKET)
1675 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1676 printf("%s\n", strError.c_str());
1681 // Different way of disabling SIGPIPE on BSD
1682 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1686 // Allow binding if the port is still in TIME_WAIT state after
1687 // the program was closed and restarted. Not an issue on windows.
1688 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1693 // Set to non-blocking, incoming connections will also inherit this
1694 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1696 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1699 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1700 printf("%s\n", strError.c_str());
1705 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1706 // and enable it by default or not. Try to enable it, if possible.
1707 if (addrBind.IsIPv6()) {
1710 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1712 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1716 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1717 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1718 // this call is allowed to fail
1719 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1724 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1726 int nErr = WSAGetLastError();
1727 if (nErr == WSAEADDRINUSE)
1728 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1730 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1731 printf("%s\n", strError.c_str());
1734 printf("Bound to %s\n", addrBind.ToString().c_str());
1736 // Listen for incoming connections
1737 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1739 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1740 printf("%s\n", strError.c_str());
1744 vhListenSocket.push_back(hListenSocket);
1746 if (addrBind.IsRoutable() && fDiscover)
1747 AddLocal(addrBind, LOCAL_BIND);
1752 void static Discover()
1758 // Get local host IP
1759 char pszHostName[1000] = "";
1760 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1762 vector<CNetAddr> vaddr;
1763 if (LookupHost(pszHostName, vaddr))
1765 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1767 AddLocal(addr, LOCAL_IF);
1772 // Get local host ip
1773 struct ifaddrs* myaddrs;
1774 if (getifaddrs(&myaddrs) == 0)
1776 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1778 if (ifa->ifa_addr == NULL) continue;
1779 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1780 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1781 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1782 if (ifa->ifa_addr->sa_family == AF_INET)
1784 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1785 CNetAddr addr(s4->sin_addr);
1786 if (AddLocal(addr, LOCAL_IF))
1787 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1790 else if (ifa->ifa_addr->sa_family == AF_INET6)
1792 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1793 CNetAddr addr(s6->sin6_addr);
1794 if (AddLocal(addr, LOCAL_IF))
1795 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1799 freeifaddrs(myaddrs);
1803 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1804 if (!IsLimited(NET_IPV4))
1805 NewThread(ThreadGetMyExternalIP, NULL);
1808 void StartNode(void* parg)
1810 // Make this thread recognisable as the startup thread
1811 RenameThread("novacoin-start");
1813 if (semOutbound == NULL) {
1814 // initialize semaphore
1815 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1816 semOutbound = new CSemaphore(nMaxOutbound);
1819 if (pnodeLocalHost == NULL)
1820 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1828 if (!GetBoolArg("-dnsseed", true))
1829 printf("DNS seeding disabled\n");
1831 if (!NewThread(ThreadDNSAddressSeed, NULL))
1832 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1834 // Map ports with UPnP
1838 // Get addresses from IRC and advertise ours
1839 if (!NewThread(ThreadIRCSeed, NULL))
1840 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1842 // Send and receive from sockets, accept connections
1843 if (!NewThread(ThreadSocketHandler, NULL))
1844 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1846 // Initiate outbound connections from -addnode
1847 if (!NewThread(ThreadOpenAddedConnections, NULL))
1848 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1850 // Initiate outbound connections
1851 if (!NewThread(ThreadOpenConnections, NULL))
1852 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1855 if (!NewThread(ThreadMessageHandler, NULL))
1856 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1858 // Dump network addresses
1859 if (!NewThread(ThreadDumpAddress, NULL))
1860 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1862 // ppcoin: mint proof-of-stake blocks in the background
1863 if (!NewThread(ThreadStakeMinter, pwalletMain))
1864 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1869 printf("StopNode()\n");
1871 nTransactionsUpdated++;
1872 int64_t nStart = GetTime();
1875 ThreadScriptCheckQuit();
1878 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1879 semOutbound->post();
1882 int nThreadsRunning = 0;
1883 for (int n = 0; n < THREAD_MAX; n++)
1884 nThreadsRunning += vnThreadsRunning[n];
1885 if (nThreadsRunning == 0)
1887 if (GetTime() - nStart > 20)
1891 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1892 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1893 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1894 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1895 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1897 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1899 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1900 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1901 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1902 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1903 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1904 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1920 BOOST_FOREACH(CNode* pnode, vNodes)
1921 if (pnode->hSocket != INVALID_SOCKET)
1922 closesocket(pnode->hSocket);
1923 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1924 if (hListenSocket != INVALID_SOCKET)
1925 if (closesocket(hListenSocket) == SOCKET_ERROR)
1926 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1929 // Shutdown Windows Sockets
1934 instance_of_cnetcleanup;
1936 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1938 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1941 RelayTransaction(tx, hash, ss);
1944 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
1946 CInv inv(MSG_TX, hash);
1949 // Expire old relay messages
1950 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
1952 mapRelay.erase(vRelayExpiration.front().second);
1953 vRelayExpiration.pop_front();
1956 // Save original serialized message so newer versions are preserved
1957 mapRelay.insert(std::make_pair(inv, ss));
1958 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
1961 RelayInventory(inv);
1964 void CNode::RecordBytesRecv(uint64_t bytes)
1966 LOCK(cs_totalBytesRecv);
1967 nTotalBytesRecv += bytes;
1970 void CNode::RecordBytesSent(uint64_t bytes)
1972 LOCK(cs_totalBytesSent);
1973 nTotalBytesSent += bytes;
1976 uint64_t CNode::GetTotalBytesRecv()
1978 LOCK(cs_totalBytesRecv);
1979 return nTotalBytesRecv;
1982 uint64_t CNode::GetTotalBytesSent()
1984 LOCK(cs_totalBytesSent);
1985 return nTotalBytesSent;