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);
39 struct LocalServiceInfo {
45 // Global state variables
48 bool fDiscover = true;
49 bool fUseUPnP = false;
50 uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
51 static CCriticalSection cs_mapLocalHost;
52 static map<CNetAddr, LocalServiceInfo> mapLocalHost;
53 static bool vfReachable[NET_MAX] = {};
54 static bool vfLimited[NET_MAX] = {};
55 static CNode* pnodeLocalHost = NULL;
56 static CNode* pnodeSync = NULL;
57 CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
58 uint64_t nLocalHostNonce = 0;
59 boost::array<int, THREAD_MAX> vnThreadsRunning;
60 static std::vector<SOCKET> vhListenSocket;
63 vector<CNode*> vNodes;
64 CCriticalSection cs_vNodes;
65 map<CInv, CDataStream> mapRelay;
66 deque<pair<int64_t, CInv> > vRelayExpiration;
67 CCriticalSection cs_mapRelay;
68 map<CInv, int64_t> mapAlreadyAskedFor;
70 static deque<string> vOneShots;
71 CCriticalSection cs_vOneShots;
73 set<CNetAddr> setservAddNodeAddresses;
74 CCriticalSection cs_setservAddNodeAddresses;
76 vector<std::string> vAddedNodes;
77 CCriticalSection cs_vAddedNodes;
79 static CSemaphore *semOutbound = NULL;
81 void AddOneShot(string strDest)
84 vOneShots.push_back(strDest);
87 unsigned short GetListenPort()
89 return (unsigned short)(GetArg("-port", GetDefaultPort()));
92 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
94 // Filter out duplicate requests
95 if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
97 pindexLastGetBlocksBegin = pindexBegin;
98 hashLastGetBlocksEnd = hashEnd;
100 PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
103 // find 'best' local address for a particular peer
104 bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
110 int nBestReachability = -1;
112 LOCK(cs_mapLocalHost);
113 for (map<CNetAddr, LocalServiceInfo>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++)
115 int nScore = (*it).second.nScore;
116 int nReachability = (*it).first.GetReachabilityFrom(paddrPeer);
117 if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
119 addr = CService((*it).first, (*it).second.nPort);
120 nBestReachability = nReachability;
125 return nBestScore >= 0;
128 // get best local address for a particular peer as a CAddress
129 CAddress GetLocalAddress(const CNetAddr *paddrPeer)
131 CAddress ret(CService("0.0.0.0",0),0);
133 if (GetLocal(addr, paddrPeer))
135 ret = CAddress(addr);
136 ret.nServices = nLocalServices;
137 ret.nTime = GetAdjustedTime();
142 bool RecvLine(SOCKET hSocket, string& strLine)
148 int nBytes = recv(hSocket, &c, 1, 0);
156 if (strLine.size() >= 9000)
159 else if (nBytes <= 0)
165 int nErr = WSAGetLastError();
166 if (nErr == WSAEMSGSIZE)
168 if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS)
174 if (!strLine.empty())
179 printf("socket closed\n");
185 int nErr = WSAGetLastError();
186 printf("recv failed: %d\n", nErr);
193 // used when scores of local addresses may have changed
194 // pushes better local address to peers
195 void static AdvertizeLocal()
198 BOOST_FOREACH(CNode* pnode, vNodes)
200 if (pnode->fSuccessfullyConnected)
202 CAddress addrLocal = GetLocalAddress(&pnode->addr);
203 if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal)
205 pnode->PushAddress(addrLocal);
206 pnode->addrLocal = addrLocal;
212 void SetReachable(enum Network net, bool fFlag)
214 LOCK(cs_mapLocalHost);
215 vfReachable[net] = fFlag;
216 if (net == NET_IPV6 && fFlag)
217 vfReachable[NET_IPV4] = true;
220 // learn a new local address
221 bool AddLocal(const CService& addr, int nScore)
223 if (!addr.IsRoutable())
226 if (!fDiscover && nScore < LOCAL_MANUAL)
232 printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
235 LOCK(cs_mapLocalHost);
236 bool fAlready = mapLocalHost.count(addr) > 0;
237 LocalServiceInfo &info = mapLocalHost[addr];
238 if (!fAlready || nScore >= info.nScore) {
239 info.nScore = nScore + (fAlready ? 1 : 0);
240 info.nPort = addr.GetPort();
242 SetReachable(addr.GetNetwork());
250 bool AddLocal(const CNetAddr &addr, int nScore)
252 return AddLocal(CService(addr, GetListenPort()), nScore);
255 /** Make a particular network entirely off-limits (no automatic connects to it) */
256 void SetLimited(enum Network net, bool fLimited)
258 if (net == NET_UNROUTABLE)
260 LOCK(cs_mapLocalHost);
261 vfLimited[net] = fLimited;
264 bool IsLimited(enum Network net)
266 LOCK(cs_mapLocalHost);
267 return vfLimited[net];
270 bool IsLimited(const CNetAddr &addr)
272 return IsLimited(addr.GetNetwork());
275 /** vote for a local address */
276 bool SeenLocal(const CService& addr)
279 LOCK(cs_mapLocalHost);
280 if (mapLocalHost.count(addr) == 0)
282 mapLocalHost[addr].nScore++;
290 /** check whether a given address is potentially local */
291 bool IsLocal(const CService& addr)
293 LOCK(cs_mapLocalHost);
294 return mapLocalHost.count(addr) > 0;
297 /** check whether a given address is in a network we can probably connect to */
298 bool IsReachable(const CNetAddr& addr)
300 LOCK(cs_mapLocalHost);
301 enum Network net = addr.GetNetwork();
302 return vfReachable[net] && !vfLimited[net];
305 extern int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv);
307 // We now get our external IP from the IRC server first and only use this as a backup
308 bool GetMyExternalIP(CNetAddr& ipRet)
310 struct sockaddr_in mapped;
311 uint64_t rnd = GetRand(~0LL);
313 int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
315 ipRet = CNetAddr(mapped.sin_addr);
316 printf("GetExternalIPbySTUN(%" PRIu64 ") returned %s in attempt %d; Server=%s\n", rnd, ipRet.ToStringIP().c_str(), rc, srv);
322 void ThreadGetMyExternalIP(void* parg)
324 // Make this thread recognisable as the external IP detection thread
325 RenameThread("novacoin-ext-ip");
327 CNetAddr addrLocalHost;
328 if (GetMyExternalIP(addrLocalHost))
330 printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
331 AddLocal(addrLocalHost, LOCAL_HTTP);
339 void AddressCurrentlyConnected(const CService& addr)
341 addrman.Connected(addr);
347 uint64_t CNode::nTotalBytesRecv = 0;
348 uint64_t CNode::nTotalBytesSent = 0;
349 CCriticalSection CNode::cs_totalBytesRecv;
350 CCriticalSection CNode::cs_totalBytesSent;
352 CNode* FindNode(const CNetAddr& ip)
355 BOOST_FOREACH(CNode* pnode, vNodes)
356 if ((CNetAddr)pnode->addr == ip)
361 CNode* FindNode(std::string addrName)
364 BOOST_FOREACH(CNode* pnode, vNodes)
365 if (pnode->addrName == addrName)
370 CNode* FindNode(const CService& addr)
373 BOOST_FOREACH(CNode* pnode, vNodes)
374 if ((CService)pnode->addr == addr)
379 CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64_t nTimeout)
381 if (pszDest == NULL) {
382 if (IsLocal(addrConnect))
385 // Look for an existing connection
386 CNode* pnode = FindNode((CService)addrConnect);
390 pnode->AddRef(nTimeout);
399 printf("trying connection %s lastseen=%.1fhrs\n",
400 pszDest ? pszDest : addrConnect.ToString().c_str(),
401 pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
405 if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
407 addrman.Attempt(addrConnect);
410 printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
412 // Set to non-blocking
415 if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
416 printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
418 if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
419 printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
423 CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false);
425 pnode->AddRef(nTimeout);
431 vNodes.push_back(pnode);
434 pnode->nTimeConnected = GetTime();
443 void CNode::CloseSocketDisconnect()
446 if (hSocket != INVALID_SOCKET)
448 printf("disconnecting node %s\n", addrName.c_str());
449 closesocket(hSocket);
450 hSocket = INVALID_SOCKET;
454 // in case this fails, we'll empty the recv buffer when the CNode is deleted
455 TRY_LOCK(cs_vRecv, lockRecv);
459 // if this was the sync node, we'll need a new one
460 if (this == pnodeSync)
464 void CNode::Cleanup()
469 void CNode::PushVersion()
471 /// when NTP implemented, change to just nTime = GetAdjustedTime()
472 int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
473 CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
474 CAddress addrMe = GetLocalAddress(&addr);
475 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
476 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());
477 PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
478 nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
485 std::map<CNetAddr, int64_t> CNode::setBanned;
486 CCriticalSection CNode::cs_setBanned;
488 void CNode::ClearBanned()
493 bool CNode::IsBanned(CNetAddr ip)
495 bool fResult = false;
498 std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
499 if (i != setBanned.end())
501 int64_t t = (*i).second;
509 bool CNode::Misbehaving(int howmuch)
513 printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
517 nMisbehavior += howmuch;
518 if (nMisbehavior >= GetArg("-banscore", 100))
520 int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
521 printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
524 if (setBanned[addr] < banTime)
525 setBanned[addr] = banTime;
527 CloseSocketDisconnect();
530 printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
535 #define X(name) stats.name = name
536 void CNode::copyStats(CNodeStats &stats)
551 stats.fSyncNode = (this == pnodeSync);
564 void ThreadSocketHandler(void* parg)
566 // Make this thread recognisable as the networking thread
567 RenameThread("novacoin-net");
571 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
572 ThreadSocketHandler2(parg);
573 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
575 catch (std::exception& e) {
576 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
577 PrintException(&e, "ThreadSocketHandler()");
579 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
580 throw; // support pthread_cancel()
582 printf("ThreadSocketHandler exited\n");
585 void ThreadSocketHandler2(void* parg)
587 printf("ThreadSocketHandler started\n");
588 list<CNode*> vNodesDisconnected;
589 unsigned int nPrevNodeCount = 0;
598 // Disconnect unused nodes
599 vector<CNode*> vNodesCopy = vNodes;
600 BOOST_FOREACH(CNode* pnode, vNodesCopy)
602 if (pnode->fDisconnect ||
603 (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
605 // remove from vNodes
606 vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
608 // release outbound grant (if any)
609 pnode->grantOutbound.Release();
611 // close socket and cleanup
612 pnode->CloseSocketDisconnect();
615 // hold in disconnected pool until all refs are released
616 pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
617 if (pnode->fNetworkNode || pnode->fInbound)
619 vNodesDisconnected.push_back(pnode);
623 // Delete disconnected nodes
624 list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
625 BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
627 // wait until threads are done using it
628 if (pnode->GetRefCount() <= 0)
630 bool fDelete = false;
632 TRY_LOCK(pnode->cs_vSend, lockSend);
635 TRY_LOCK(pnode->cs_vRecv, lockRecv);
638 TRY_LOCK(pnode->cs_mapRequests, lockReq);
641 TRY_LOCK(pnode->cs_inventory, lockInv);
650 vNodesDisconnected.remove(pnode);
656 if (vNodes.size() != nPrevNodeCount)
658 nPrevNodeCount = vNodes.size();
659 uiInterface.NotifyNumConnectionsChanged(vNodes.size());
664 // Find which sockets have data to receive
666 struct timeval timeout;
668 timeout.tv_usec = 50000; // frequency to poll pnode->vSend
675 FD_ZERO(&fdsetError);
676 SOCKET hSocketMax = 0;
677 bool have_fds = false;
679 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) {
680 FD_SET(hListenSocket, &fdsetRecv);
681 hSocketMax = max(hSocketMax, hListenSocket);
686 BOOST_FOREACH(CNode* pnode, vNodes)
688 if (pnode->hSocket == INVALID_SOCKET)
690 FD_SET(pnode->hSocket, &fdsetRecv);
691 FD_SET(pnode->hSocket, &fdsetError);
692 hSocketMax = max(hSocketMax, pnode->hSocket);
695 TRY_LOCK(pnode->cs_vSend, lockSend);
696 if (lockSend && !pnode->vSend.empty())
697 FD_SET(pnode->hSocket, &fdsetSend);
702 vnThreadsRunning[THREAD_SOCKETHANDLER]--;
703 int nSelect = select(have_fds ? hSocketMax + 1 : 0,
704 &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
705 vnThreadsRunning[THREAD_SOCKETHANDLER]++;
708 if (nSelect == SOCKET_ERROR)
712 int nErr = WSAGetLastError();
713 printf("socket select error %d\n", nErr);
714 for (unsigned int i = 0; i <= hSocketMax; i++)
715 FD_SET(i, &fdsetRecv);
718 FD_ZERO(&fdsetError);
719 Sleep(timeout.tv_usec/1000);
724 // Accept new connections
726 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
727 if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
730 struct sockaddr_storage sockaddr;
732 struct sockaddr sockaddr;
734 socklen_t len = sizeof(sockaddr);
735 SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
739 if (hSocket != INVALID_SOCKET)
740 if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
741 printf("Warning: Unknown socket family\n");
745 BOOST_FOREACH(CNode* pnode, vNodes)
750 if (hSocket == INVALID_SOCKET)
752 int nErr = WSAGetLastError();
753 if (nErr != WSAEWOULDBLOCK)
754 printf("socket error accept failed: %d\n", nErr);
756 else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
759 LOCK(cs_setservAddNodeAddresses);
760 if (!setservAddNodeAddresses.count(addr))
761 closesocket(hSocket);
764 else if (CNode::IsBanned(addr))
766 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
767 closesocket(hSocket);
771 printf("accepted connection %s\n", addr.ToString().c_str());
772 CNode* pnode = new CNode(hSocket, addr, "", true);
776 vNodes.push_back(pnode);
783 // Service each socket
785 vector<CNode*> vNodesCopy;
789 BOOST_FOREACH(CNode* pnode, vNodesCopy)
792 BOOST_FOREACH(CNode* pnode, vNodesCopy)
800 if (pnode->hSocket == INVALID_SOCKET)
802 if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
804 TRY_LOCK(pnode->cs_vRecv, lockRecv);
807 CDataStream& vRecv = pnode->vRecv;
808 uint64_t nPos = vRecv.size();
810 if (nPos > ReceiveBufferSize()) {
811 if (!pnode->fDisconnect)
812 printf("socket recv flood control disconnect (%" PRIszu " bytes)\n", vRecv.size());
813 pnode->CloseSocketDisconnect();
816 // typical socket buffer is 8K-64K
817 char pchBuf[0x10000];
818 int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
821 vRecv.resize(nPos + nBytes);
822 memcpy(&vRecv[nPos], pchBuf, nBytes);
823 pnode->nLastRecv = GetTime();
824 pnode->nRecvBytes += nBytes;
825 pnode->RecordBytesRecv(nBytes);
827 else if (nBytes == 0)
829 // socket closed gracefully
830 if (!pnode->fDisconnect)
831 printf("socket closed\n");
832 pnode->CloseSocketDisconnect();
837 int nErr = WSAGetLastError();
838 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
840 if (!pnode->fDisconnect)
841 printf("socket recv error %d\n", nErr);
842 pnode->CloseSocketDisconnect();
852 if (pnode->hSocket == INVALID_SOCKET)
854 if (FD_ISSET(pnode->hSocket, &fdsetSend))
856 TRY_LOCK(pnode->cs_vSend, lockSend);
859 CDataStream& vSend = pnode->vSend;
862 int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
865 vSend.erase(vSend.begin(), vSend.begin() + nBytes);
866 pnode->nLastSend = GetTime();
867 pnode->nSendBytes += nBytes;
868 pnode->RecordBytesSent(nBytes);
873 int nErr = WSAGetLastError();
874 if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
876 printf("socket send error %d\n", nErr);
877 pnode->CloseSocketDisconnect();
885 // Inactivity checking
887 if (pnode->vSend.empty())
888 pnode->nLastSendEmpty = GetTime();
889 if (GetTime() - pnode->nTimeConnected > 60)
891 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
893 printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
894 pnode->fDisconnect = true;
896 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
898 printf("socket not sending\n");
899 pnode->fDisconnect = true;
901 else if (GetTime() - pnode->nLastRecv > 90*60)
903 printf("socket inactivity timeout\n");
904 pnode->fDisconnect = true;
910 BOOST_FOREACH(CNode* pnode, vNodesCopy)
927 void ThreadMapPort(void* parg)
929 // Make this thread recognisable as the UPnP thread
930 RenameThread("novacoin-UPnP");
934 vnThreadsRunning[THREAD_UPNP]++;
935 ThreadMapPort2(parg);
936 vnThreadsRunning[THREAD_UPNP]--;
938 catch (std::exception& e) {
939 vnThreadsRunning[THREAD_UPNP]--;
940 PrintException(&e, "ThreadMapPort()");
942 vnThreadsRunning[THREAD_UPNP]--;
943 PrintException(NULL, "ThreadMapPort()");
945 printf("ThreadMapPort exited\n");
948 void ThreadMapPort2(void* parg)
950 printf("ThreadMapPort started\n");
952 std::string port = strprintf("%u", GetListenPort());
953 const char * multicastif = 0;
954 const char * minissdpdpath = 0;
955 struct UPNPDev * devlist = 0;
958 #ifndef UPNPDISCOVER_SUCCESS
960 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
964 devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
967 struct UPNPUrls urls;
968 struct IGDdatas data;
971 r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
975 char externalIPAddress[40];
976 r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
977 if(r != UPNPCOMMAND_SUCCESS)
978 printf("UPnP: GetExternalIPAddress() returned %d\n", r);
981 if(externalIPAddress[0])
983 printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
984 AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
987 printf("UPnP: GetExternalIPAddress failed.\n");
991 string strDesc = "NovaCoin " + FormatFullVersion();
992 #ifndef UPNPDISCOVER_SUCCESS
994 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
995 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
998 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
999 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1002 if(r!=UPNPCOMMAND_SUCCESS)
1003 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1004 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1006 printf("UPnP Port Mapping successful.\n");
1010 if (fShutdown || !fUseUPnP)
1012 r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
1013 printf("UPNP_DeletePortMapping() returned : %d\n", r);
1014 freeUPNPDevlist(devlist); devlist = 0;
1015 FreeUPNPUrls(&urls);
1018 if (i % 600 == 0) // Refresh every 20 minutes
1020 #ifndef UPNPDISCOVER_SUCCESS
1022 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1023 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
1026 r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
1027 port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
1030 if(r!=UPNPCOMMAND_SUCCESS)
1031 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
1032 port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
1034 printf("UPnP Port Mapping successful.\n");;
1040 printf("No valid UPnP IGDs found\n");
1041 freeUPNPDevlist(devlist); devlist = 0;
1043 FreeUPNPUrls(&urls);
1046 if (fShutdown || !fUseUPnP)
1055 if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
1057 if (!NewThread(ThreadMapPort, NULL))
1058 printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
1064 // Intentionally left blank.
1077 // Each pair gives a source name and a seed name.
1078 // The first name is used as information source for addrman.
1079 // The second name should resolve to a list of seed addresses.
1080 static const char *strDNSSeed[][2] = {
1081 {"novacoin.karelia.pro", "dnsseed.novacoin.karelia.pro"},
1082 {"novacoin.su", "dnsseed.novacoin.su"},
1083 {"novacoin.ru", "dnsseed.novacoin.ru"},
1084 {"novacoin.ru", "testseed.novacoin.ru"},
1085 {"novaco.in", "dnsseed.novaco.in"},
1088 void ThreadDNSAddressSeed(void* parg)
1090 // Make this thread recognisable as the DNS seeding thread
1091 RenameThread("novacoin-dnsseed");
1095 vnThreadsRunning[THREAD_DNSSEED]++;
1096 ThreadDNSAddressSeed2(parg);
1097 vnThreadsRunning[THREAD_DNSSEED]--;
1099 catch (std::exception& e) {
1100 vnThreadsRunning[THREAD_DNSSEED]--;
1101 PrintException(&e, "ThreadDNSAddressSeed()");
1103 vnThreadsRunning[THREAD_DNSSEED]--;
1104 throw; // support pthread_cancel()
1106 printf("ThreadDNSAddressSeed exited\n");
1109 void ThreadDNSAddressSeed2(void* parg)
1111 printf("ThreadDNSAddressSeed started\n");
1116 printf("Loading addresses from DNS seeds (could take a while)\n");
1118 for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) {
1119 if (HaveNameProxy()) {
1120 AddOneShot(strDNSSeed[seed_idx][1]);
1122 vector<CNetAddr> vaddr;
1123 vector<CAddress> vAdd;
1124 if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
1126 BOOST_FOREACH(CNetAddr& ip, vaddr)
1128 int nOneDay = 24*3600;
1129 CAddress addr = CAddress(CService(ip, GetDefaultPort()));
1130 addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
1131 vAdd.push_back(addr);
1135 addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
1140 printf("%d addresses found from DNS seeds\n", found);
1156 0xa52bf0da, 0x30aa43d8, 0x614488d5, 0x517b6fd5, 0xd4bf62d4, 0xb7d638d4, 0xbc12bcd1, 0xa2501bc6,
1157 0xfde617c6, 0x3337b1c6, 0x1dcd71c3, 0x2c1544c1, 0xe05f6ac1, 0x852f63c0, 0x3e2363c0, 0x15f563c0,
1158 0x430d63c0, 0x50d6a9c0, 0xf0a679c0, 0xefdeedbf, 0x7aaee8bc, 0x3a3dbbbc, 0xef218abc, 0x0bef78bc,
1159 0x8baa3eb2, 0x2bf913b2, 0x24ed9fb2, 0xb42289b2, 0x718a09b0, 0xe9433eb0, 0x559425b0, 0xc97e1fb0,
1160 0x18e1d4b0, 0x8f6cc1b0, 0xac3838ae, 0x86c0ffad, 0x6b0272a7, 0xa463f8a2, 0x6f17f3a2, 0xb3d6f3a2,
1161 0x9cd8f997, 0xd513fb94, 0x39e64880, 0x3859dd6f, 0x0b08fe6d, 0xe601fe6d, 0xeb44a26d, 0xfe53186c,
1162 0x203c2e68, 0x1c542868, 0x0caa8368, 0xb8748368, 0xccca4762, 0xc637555f, 0x638a545f, 0x59b2205f,
1163 0x52568c5f, 0xba568c5f, 0x8a568c5f, 0x31b0f45e, 0x54a0f45e, 0x37d6f15e, 0xc520175e, 0x7620175e,
1164 0xc310175e, 0x8e33b45e, 0x7abb5f5d, 0xd3014c5d, 0xa1e1485d, 0x9947645d, 0xfab8ff5c, 0xa979e65b,
1165 0xa879e65b, 0x9f79e65b, 0x9fa3d25b, 0x112a925b, 0x7b92905b, 0x60647a5b, 0x1e389d5a, 0x851afa59,
1166 0x0185ef59, 0x26549b59, 0x1c9efe57, 0xc54c1256, 0x1ad51955, 0x19d21955, 0x73c41955, 0x3f74ee55,
1167 0x633eea55, 0x6883d655, 0xfb72c655, 0x5360a653, 0x17c1ea52, 0xc661c852, 0x1ecdc852, 0x006a9752,
1168 0xf72d9252, 0x82650551, 0x36f1c851, 0x33f1c851, 0xd5c1864f, 0xb6bf1b4e, 0x96da184e, 0x40d0234d,
1169 0x9a96ab4c, 0x8fc2a84c, 0xb5dbd048, 0xf4644447, 0x2d51af47, 0xa9625445, 0x83f05243, 0x89672941,
1170 0x3a8bad3e, 0xf0a05436, 0x6ab7c936, 0x49971d32, 0xadd4482e, 0xcffd212e, 0x6730bc2e, 0x839aa12e,
1171 0x68d9692e, 0xc7183b25, 0x6c47bb25, 0x2490bb25, 0xad651c1f, 0x048a861f, 0x6937811f, 0x064b2d05,
1175 const char* pchTorSeed[] =
1177 "seedp4knqnoei57u.onion",
1178 "seedr3hhlepyi7fd.onion",
1179 "seed3uuomkclbiz4.onion",
1180 "seedeh7qck3ouff5.onion",
1181 "5rg3vq4jagckeckf.onion",
1182 "seedt3sraf53ajiy.onion",
1183 "seedg4qyccsg42oq.onion",
1184 "novaqrtoywpg7jly.onion",
1185 "seed3d5wolqbgrcb.onion",
1186 "seed24u5dwph3qw4.onion",
1187 "mj26ulzbs2oskgym.onion",
1188 "eqon4usunavt76m7.onion",
1191 void DumpAddresses()
1193 int64_t nStart = GetTimeMillis();
1198 printf("Flushed %d addresses to peers.dat %" PRId64 "ms\n",
1199 addrman.size(), GetTimeMillis() - nStart);
1202 void ThreadDumpAddress2(void* parg)
1204 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1208 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1210 vnThreadsRunning[THREAD_DUMPADDRESS]++;
1212 vnThreadsRunning[THREAD_DUMPADDRESS]--;
1215 void ThreadDumpAddress(void* parg)
1217 // Make this thread recognisable as the address dumping thread
1218 RenameThread("novacoin-adrdump");
1222 ThreadDumpAddress2(parg);
1224 catch (std::exception& e) {
1225 PrintException(&e, "ThreadDumpAddress()");
1227 printf("ThreadDumpAddress exited\n");
1230 void ThreadOpenConnections(void* parg)
1232 // Make this thread recognisable as the connection opening thread
1233 RenameThread("novacoin-opencon");
1237 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1238 ThreadOpenConnections2(parg);
1239 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1241 catch (std::exception& e) {
1242 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1243 PrintException(&e, "ThreadOpenConnections()");
1245 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1246 PrintException(NULL, "ThreadOpenConnections()");
1248 printf("ThreadOpenConnections exited\n");
1251 void static ProcessOneShot()
1256 if (vOneShots.empty())
1258 strDest = vOneShots.front();
1259 vOneShots.pop_front();
1262 CSemaphoreGrant grant(*semOutbound, true);
1264 if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true))
1265 AddOneShot(strDest);
1269 // ppcoin: stake minter thread
1270 void static ThreadStakeMinter(void* parg)
1272 printf("ThreadStakeMinter started\n");
1273 CWallet* pwallet = (CWallet*)parg;
1276 vnThreadsRunning[THREAD_MINTER]++;
1277 StakeMiner(pwallet);
1278 vnThreadsRunning[THREAD_MINTER]--;
1280 catch (std::exception& e) {
1281 vnThreadsRunning[THREAD_MINTER]--;
1282 PrintException(&e, "ThreadStakeMinter()");
1284 vnThreadsRunning[THREAD_MINTER]--;
1285 PrintException(NULL, "ThreadStakeMinter()");
1287 printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
1290 void ThreadOpenConnections2(void* parg)
1292 printf("ThreadOpenConnections started\n");
1294 // Connect to specific addresses
1295 if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
1297 for (int64_t nLoop = 0;; nLoop++)
1300 BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
1303 OpenNetworkConnection(addr, NULL, strAddr.c_str());
1304 for (int i = 0; i < 10 && i < nLoop; i++)
1315 // Initiate network connections
1316 int64_t nStart = GetTime();
1321 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1323 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1328 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1329 CSemaphoreGrant grant(*semOutbound);
1330 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1334 // Add seed nodes if IRC isn't working
1335 if (!IsLimited(NET_IPV4) && addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
1337 std::vector<CAddress> vAdd;
1338 for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
1340 // It'll only connect to one or two seed nodes because once it connects,
1341 // it'll get a pile of addresses with newer timestamps.
1342 // Seed nodes are given a random 'last seen time' of between one and two
1344 const int64_t nOneWeek = 7*24*60*60;
1346 memcpy(&ip, &pnSeed[i], sizeof(ip));
1347 CAddress addr(CService(ip, GetDefaultPort()));
1348 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1349 vAdd.push_back(addr);
1351 addrman.Add(vAdd, CNetAddr("127.0.0.1"));
1354 // Add Tor nodes if we have connection with onion router
1355 if (mapArgs.count("-tor"))
1357 std::vector<CAddress> vAdd;
1358 for (unsigned int i = 0; i < ARRAYLEN(pchTorSeed); i++)
1360 const int64_t nOneWeek = 7*24*60*60;
1361 CAddress addr(CService(pchTorSeed[i], GetDefaultPort()));
1362 addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
1363 vAdd.push_back(addr);
1365 addrman.Add(vAdd, CNetAddr("dummyaddress.onion"));
1369 // Choose an address to connect to based on most recently seen
1371 CAddress addrConnect;
1373 // Only connect out to one peer per network group (/16 for IPv4).
1374 // Do this here so we don't have to critsect vNodes inside mapAddresses critsect.
1376 set<vector<unsigned char> > setConnected;
1379 BOOST_FOREACH(CNode* pnode, vNodes) {
1380 if (!pnode->fInbound) {
1381 setConnected.insert(pnode->addr.GetGroup());
1387 int64_t nANow = GetAdjustedTime();
1392 // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
1393 CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
1395 // if we selected an invalid address, restart
1396 if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr))
1399 // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
1400 // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
1401 // already-connected network ranges, ...) before trying new addrman addresses.
1406 if (IsLimited(addr))
1409 // only consider very recently tried nodes after 30 failed attempts
1410 if (nANow - addr.nLastTry < 600 && nTries < 30)
1413 // do not allow non-default ports, unless after 50 invalid addresses selected already
1414 if (addr.GetPort() != GetDefaultPort() && nTries < 50)
1421 if (addrConnect.IsValid())
1422 OpenNetworkConnection(addrConnect, &grant);
1426 void ThreadOpenAddedConnections(void* parg)
1428 // Make this thread recognisable as the connection opening thread
1429 RenameThread("novacoin-opencon");
1433 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1434 ThreadOpenAddedConnections2(parg);
1435 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1437 catch (std::exception& e) {
1438 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1439 PrintException(&e, "ThreadOpenAddedConnections()");
1441 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1442 PrintException(NULL, "ThreadOpenAddedConnections()");
1444 printf("ThreadOpenAddedConnections exited\n");
1447 void ThreadOpenAddedConnections2(void* parg)
1449 printf("ThreadOpenAddedConnections started\n");
1452 LOCK(cs_vAddedNodes);
1453 vAddedNodes = mapMultiArgs["-addnode"];
1456 if (HaveNameProxy()) {
1458 list<string> lAddresses(0);
1460 LOCK(cs_vAddedNodes);
1461 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1462 lAddresses.push_back(strAddNode);
1464 BOOST_FOREACH(string& strAddNode, lAddresses) {
1466 CSemaphoreGrant grant(*semOutbound);
1467 OpenNetworkConnection(addr, &grant, strAddNode.c_str());
1470 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1471 Sleep(120000); // Retry every 2 minutes
1472 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1477 for (uint32_t i = 0; true; i++)
1479 list<string> lAddresses(0);
1481 LOCK(cs_vAddedNodes);
1482 BOOST_FOREACH(string& strAddNode, vAddedNodes)
1483 lAddresses.push_back(strAddNode);
1486 list<vector<CService> > lservAddressesToAdd(0);
1487 BOOST_FOREACH(string& strAddNode, lAddresses)
1489 vector<CService> vservNode(0);
1490 if (Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
1492 lservAddressesToAdd.push_back(vservNode);
1494 LOCK(cs_setservAddNodeAddresses);
1495 BOOST_FOREACH(CService& serv, vservNode)
1496 setservAddNodeAddresses.insert(serv);
1500 // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry
1501 // (keeping in mind that addnode entries can have many IPs if fNameLookup)
1504 BOOST_FOREACH(CNode* pnode, vNodes)
1505 for (list<vector<CService> >::iterator it = lservAddressesToAdd.begin(); it != lservAddressesToAdd.end(); it++)
1507 BOOST_FOREACH(CService& addrNode, *(it))
1508 if (pnode->addr == addrNode)
1510 it = lservAddressesToAdd.erase(it);
1511 if(it != lservAddressesToAdd.begin())
1515 if (it == lservAddressesToAdd.end())
1519 BOOST_FOREACH(vector<CService>& vserv, lservAddressesToAdd)
1521 if (vserv.size() == 0)
1523 CSemaphoreGrant grant(*semOutbound);
1524 OpenNetworkConnection(CAddress(vserv[i % vserv.size()]), &grant);
1531 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--;
1532 Sleep(120000); // Retry every 2 minutes
1533 vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++;
1539 // if successful, this moves the passed grant to the constructed node
1540 bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
1543 // Initiate outbound network connection
1548 if (IsLocal(addrConnect) ||
1549 FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
1550 FindNode(addrConnect.ToStringIPPort().c_str()))
1552 if (strDest && FindNode(strDest))
1555 vnThreadsRunning[THREAD_OPENCONNECTIONS]--;
1556 CNode* pnode = ConnectNode(addrConnect, strDest);
1557 vnThreadsRunning[THREAD_OPENCONNECTIONS]++;
1563 grantOutbound->MoveTo(pnode->grantOutbound);
1564 pnode->fNetworkNode = true;
1566 pnode->fOneShot = true;
1571 // for now, use a very simple selection metric: the node from which we received
1573 double static NodeSyncScore(const CNode *pnode) {
1574 return -pnode->nLastRecv;
1577 void static StartSync(const vector<CNode*> &vNodes) {
1578 CNode *pnodeNewSync = NULL;
1579 double dBestScore = 0;
1581 // Iterate over all nodes
1582 BOOST_FOREACH(CNode* pnode, vNodes) {
1583 // check preconditions for allowing a sync
1584 if (!pnode->fClient && !pnode->fOneShot &&
1585 !pnode->fDisconnect && pnode->fSuccessfullyConnected &&
1586 (pnode->nStartingHeight > (nBestHeight - 144)) &&
1587 (pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
1588 // if ok, compare node's score with the best so far
1589 double dScore = NodeSyncScore(pnode);
1590 if (pnodeNewSync == NULL || dScore > dBestScore) {
1591 pnodeNewSync = pnode;
1592 dBestScore = dScore;
1596 // if a new sync candidate was found, start sync!
1598 pnodeNewSync->fStartSync = true;
1599 pnodeSync = pnodeNewSync;
1603 void ThreadMessageHandler(void* parg)
1605 // Make this thread recognisable as the message handling thread
1606 RenameThread("novacoin-msghand");
1610 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1611 ThreadMessageHandler2(parg);
1612 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1614 catch (std::exception& e) {
1615 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1616 PrintException(&e, "ThreadMessageHandler()");
1618 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1619 PrintException(NULL, "ThreadMessageHandler()");
1621 printf("ThreadMessageHandler exited\n");
1624 void ThreadMessageHandler2(void* parg)
1626 printf("ThreadMessageHandler started\n");
1627 SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
1630 bool fHaveSyncNode = false;
1631 vector<CNode*> vNodesCopy;
1634 vNodesCopy = vNodes;
1635 BOOST_FOREACH(CNode* pnode, vNodesCopy) {
1637 if (pnode == pnodeSync)
1638 fHaveSyncNode = true;
1643 StartSync(vNodesCopy);
1645 // Poll the connected nodes for messages
1646 CNode* pnodeTrickle = NULL;
1647 if (!vNodesCopy.empty())
1648 pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
1649 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1653 TRY_LOCK(pnode->cs_vRecv, lockRecv);
1655 ProcessMessages(pnode);
1662 TRY_LOCK(pnode->cs_vSend, lockSend);
1664 SendMessages(pnode, pnode == pnodeTrickle);
1672 BOOST_FOREACH(CNode* pnode, vNodesCopy)
1676 // Wait and allow messages to bunch up.
1677 // Reduce vnThreadsRunning so StopNode has permission to exit while
1678 // we're sleeping, but we must always check fShutdown after doing this.
1679 vnThreadsRunning[THREAD_MESSAGEHANDLER]--;
1681 if (fRequestShutdown)
1683 vnThreadsRunning[THREAD_MESSAGEHANDLER]++;
1694 bool BindListenPort(const CService &addrBind, string& strError)
1700 // Initialize Windows Sockets
1702 int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
1703 if (ret != NO_ERROR)
1705 strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
1706 printf("%s\n", strError.c_str());
1711 // Create socket for listening for incoming connections
1713 struct sockaddr_storage sockaddr;
1715 struct sockaddr sockaddr;
1717 socklen_t len = sizeof(sockaddr);
1718 if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
1720 strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
1721 printf("%s\n", strError.c_str());
1725 SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
1726 if (hListenSocket == INVALID_SOCKET)
1728 strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
1729 printf("%s\n", strError.c_str());
1734 // Different way of disabling SIGPIPE on BSD
1735 setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
1739 // Allow binding if the port is still in TIME_WAIT state after
1740 // the program was closed and restarted. Not an issue on windows.
1741 setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
1746 // Set to non-blocking, incoming connections will also inherit this
1747 if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
1749 if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
1752 strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
1753 printf("%s\n", strError.c_str());
1758 // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
1759 // and enable it by default or not. Try to enable it, if possible.
1760 if (addrBind.IsIPv6()) {
1763 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&nOne, sizeof(int));
1765 setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int));
1769 int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
1770 int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
1771 // this call is allowed to fail
1772 setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
1777 if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
1779 int nErr = WSAGetLastError();
1780 if (nErr == WSAEADDRINUSE)
1781 strError = strprintf(_("Unable to bind to %s on this computer. NovaCoin is probably already running."), addrBind.ToString().c_str());
1783 strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
1784 printf("%s\n", strError.c_str());
1787 printf("Bound to %s\n", addrBind.ToString().c_str());
1789 // Listen for incoming connections
1790 if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
1792 strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
1793 printf("%s\n", strError.c_str());
1797 vhListenSocket.push_back(hListenSocket);
1799 if (addrBind.IsRoutable() && fDiscover)
1800 AddLocal(addrBind, LOCAL_BIND);
1805 void static Discover()
1811 // Get local host IP
1812 char pszHostName[1000] = "";
1813 if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
1815 vector<CNetAddr> vaddr;
1816 if (LookupHost(pszHostName, vaddr))
1818 BOOST_FOREACH (const CNetAddr &addr, vaddr)
1820 AddLocal(addr, LOCAL_IF);
1825 // Get local host ip
1826 struct ifaddrs* myaddrs;
1827 if (getifaddrs(&myaddrs) == 0)
1829 for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
1831 if (ifa->ifa_addr == NULL) continue;
1832 if ((ifa->ifa_flags & IFF_UP) == 0) continue;
1833 if (strcmp(ifa->ifa_name, "lo") == 0) continue;
1834 if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
1835 if (ifa->ifa_addr->sa_family == AF_INET)
1837 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
1838 CNetAddr addr(s4->sin_addr);
1839 if (AddLocal(addr, LOCAL_IF))
1840 printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1843 else if (ifa->ifa_addr->sa_family == AF_INET6)
1845 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
1846 CNetAddr addr(s6->sin6_addr);
1847 if (AddLocal(addr, LOCAL_IF))
1848 printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
1852 freeifaddrs(myaddrs);
1856 // Don't use external IPv4 discovery, when -onlynet="IPv6"
1857 if (!IsLimited(NET_IPV4))
1858 NewThread(ThreadGetMyExternalIP, NULL);
1861 void StartNode(void* parg)
1863 // Make this thread recognisable as the startup thread
1864 RenameThread("novacoin-start");
1866 if (semOutbound == NULL) {
1867 // initialize semaphore
1868 int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
1869 semOutbound = new CSemaphore(nMaxOutbound);
1872 if (pnodeLocalHost == NULL)
1873 pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
1881 if (!GetBoolArg("-dnsseed", true))
1882 printf("DNS seeding disabled\n");
1884 if (!NewThread(ThreadDNSAddressSeed, NULL))
1885 printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
1887 // Map ports with UPnP
1889 printf("UPNP port mapping is disabled\n");
1893 // Get addresses from IRC and advertise ours
1894 if (!GetBoolArg("-irc", true))
1895 printf("IRC seeding disabled\n");
1897 if (!NewThread(ThreadIRCSeed, NULL))
1898 printf("Error: NewThread(ThreadIRCSeed) failed\n");
1900 // Send and receive from sockets, accept connections
1901 if (!NewThread(ThreadSocketHandler, NULL))
1902 printf("Error: NewThread(ThreadSocketHandler) failed\n");
1904 // Initiate outbound connections from -addnode
1905 if (!NewThread(ThreadOpenAddedConnections, NULL))
1906 printf("Error: NewThread(ThreadOpenAddedConnections) failed\n");
1908 // Initiate outbound connections
1909 if (!NewThread(ThreadOpenConnections, NULL))
1910 printf("Error: NewThread(ThreadOpenConnections) failed\n");
1913 if (!NewThread(ThreadMessageHandler, NULL))
1914 printf("Error: NewThread(ThreadMessageHandler) failed\n");
1916 // Dump network addresses
1917 if (!NewThread(ThreadDumpAddress, NULL))
1918 printf("Error; NewThread(ThreadDumpAddress) failed\n");
1920 // ppcoin: mint proof-of-stake blocks in the background
1921 if (!NewThread(ThreadStakeMinter, pwalletMain))
1922 printf("Error: NewThread(ThreadStakeMinter) failed\n");
1927 printf("StopNode()\n");
1929 nTransactionsUpdated++;
1930 int64_t nStart = GetTime();
1933 ThreadScriptCheckQuit();
1936 for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
1937 semOutbound->post();
1940 int nThreadsRunning = 0;
1941 for (int n = 0; n < THREAD_MAX; n++)
1942 nThreadsRunning += vnThreadsRunning[n];
1943 if (nThreadsRunning == 0)
1945 if (GetTime() - nStart > 20)
1949 if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n");
1950 if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n");
1951 if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
1952 if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
1953 if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
1955 if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
1957 if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
1958 if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
1959 if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
1960 if (vnThreadsRunning[THREAD_MINTER] > 0) printf("ThreadStakeMinter still running\n");
1961 if (vnThreadsRunning[THREAD_SCRIPTCHECK] > 0) printf("ThreadScriptCheck still running\n");
1962 while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0 || vnThreadsRunning[THREAD_SCRIPTCHECK] > 0)
1978 BOOST_FOREACH(CNode* pnode, vNodes)
1979 if (pnode->hSocket != INVALID_SOCKET)
1980 closesocket(pnode->hSocket);
1981 BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
1982 if (hListenSocket != INVALID_SOCKET)
1983 if (closesocket(hListenSocket) == SOCKET_ERROR)
1984 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
1987 // Shutdown Windows Sockets
1992 instance_of_cnetcleanup;
1994 void RelayTransaction(const CTransaction& tx, const uint256& hash)
1996 CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
1999 RelayTransaction(tx, hash, ss);
2002 void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
2004 CInv inv(MSG_TX, hash);
2007 // Expire old relay messages
2008 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
2010 mapRelay.erase(vRelayExpiration.front().second);
2011 vRelayExpiration.pop_front();
2014 // Save original serialized message so newer versions are preserved
2015 mapRelay.insert(std::make_pair(inv, ss));
2016 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
2019 RelayInventory(inv);
2022 void CNode::RecordBytesRecv(uint64_t bytes)
2024 LOCK(cs_totalBytesRecv);
2025 nTotalBytesRecv += bytes;
2028 void CNode::RecordBytesSent(uint64_t bytes)
2030 LOCK(cs_totalBytesSent);
2031 nTotalBytesSent += bytes;
2034 uint64_t CNode::GetTotalBytesRecv()
2036 LOCK(cs_totalBytesRecv);
2037 return nTotalBytesRecv;
2040 uint64_t CNode::GetTotalBytesSent()
2042 LOCK(cs_totalBytesSent);
2043 return nTotalBytesSent;