#include "init.h"
#include "addrman.h"
#include "ui_interface.h"
+#include "miner.h"
+#include "ntp.h"
#ifdef WIN32
#include <string.h>
#endif
-#ifdef USE_UPNP
-#include <miniupnpc/miniwget.h>
-#include <miniupnpc/miniupnpc.h>
-#include <miniupnpc/upnpcommands.h>
-#include <miniupnpc/upnperrors.h>
-#endif
-
using namespace std;
using namespace boost;
void ThreadSocketHandler2(void* parg);
void ThreadOpenConnections2(void* parg);
void ThreadOpenAddedConnections2(void* parg);
-#ifdef USE_UPNP
-void ThreadMapPort2(void* parg);
-#endif
void ThreadDNSAddressSeed2(void* parg);
+// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
+// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
+#ifdef WIN32
+#ifndef PROTECTION_LEVEL_UNRESTRICTED
+#define PROTECTION_LEVEL_UNRESTRICTED 10
+#endif
+#ifndef IPV6_PROTECTION_LEVEL
+#define IPV6_PROTECTION_LEVEL 23
+#endif
+#endif
+
struct LocalServiceInfo {
int nScore;
- int nPort;
+ uint16_t nPort;
};
//
//
bool fClient = false;
bool fDiscover = true;
-bool fUseUPnP = false;
uint64_t nLocalServices = (fClient ? 0 : NODE_NETWORK);
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
static CNode* pnodeSync = NULL;
-CAddress addrSeenByPeer(CService("0.0.0.0", 0), nLocalServices);
+CAddress addrSeenByPeer(CService("0.0.0.0", nPortZero), nLocalServices);
uint64_t nLocalHostNonce = 0;
boost::array<int, THREAD_MAX> vnThreadsRunning;
static std::vector<SOCKET> vhListenSocket;
// get best local address for a particular peer as a CAddress
CAddress GetLocalAddress(const CNetAddr *paddrPeer)
{
- CAddress ret(CService("0.0.0.0",0),0);
+ CAddress ret(CService("0.0.0.0", nPortZero), 0);
CService addr;
if (GetLocal(addr, paddrPeer))
{
bool GetMyExternalIP(CNetAddr& ipRet)
{
struct sockaddr_in mapped;
- uint64_t rnd = UINT64_MAX;
+ uint64_t rnd = std::numeric_limits<uint64_t>::max();
const char *srv;
int rc = GetExternalIPbySTUN(rnd, &mapped, &srv);
if(rc >= 0) {
void CNode::PushVersion()
{
- /// when NTP implemented, change to just nTime = GetAdjustedTime()
- int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
+ int64_t nTime = GetAdjustedTime();
CAddress addrYou, addrMe;
bool fHidden = false;
}
if (!fHidden) {
- addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
+ addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0", nPortZero)));
addrMe = GetLocalAddress(&addr);
}
}
nMisbehavior += howmuch;
- if (nMisbehavior >= GetArg("-banscore", 100))
+ if (nMisbehavior >= GetArgInt("-banscore", 100))
{
- int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
+ int64_t banTime = GetTime()+GetArg("-bantime", nOneDay); // Default 24-hour ban
printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
{
LOCK(cs_setBanned);
printf("ThreadSocketHandler exited\n");
}
+static list<CNode*> vNodesDisconnected;
+
void ThreadSocketHandler2(void* parg)
{
printf("ThreadSocketHandler started\n");
- list<CNode*> vNodesDisconnected;
- unsigned int nPrevNodeCount = 0;
-
+ size_t nPrevNodeCount = 0;
while (true)
{
//
if (nErr != WSAEWOULDBLOCK)
printf("socket error accept failed: %d\n", nErr);
}
- else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
+ else if (nInbound >= GetArgInt("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
{
{
LOCK(cs_setservAddNodeAddresses);
}
}
-
-
-
-
-
-
-
-
-#ifdef USE_UPNP
-void ThreadMapPort(void* parg)
-{
- // Make this thread recognisable as the UPnP thread
- RenameThread("novacoin-UPnP");
-
- try
- {
- vnThreadsRunning[THREAD_UPNP]++;
- ThreadMapPort2(parg);
- vnThreadsRunning[THREAD_UPNP]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_UPNP]--;
- PrintException(&e, "ThreadMapPort()");
- } catch (...) {
- vnThreadsRunning[THREAD_UPNP]--;
- PrintException(NULL, "ThreadMapPort()");
- }
- printf("ThreadMapPort exited\n");
-}
-
-void ThreadMapPort2(void* parg)
-{
- printf("ThreadMapPort started\n");
-
- std::string port = strprintf("%u", GetListenPort());
- const char * multicastif = 0;
- const char * minissdpdpath = 0;
- struct UPNPDev * devlist = 0;
- char lanaddr[64];
-
-#ifndef UPNPDISCOVER_SUCCESS
- /* miniupnpc 1.5 */
- devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0);
-#else
- /* miniupnpc 1.6 */
- int error = 0;
- devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
-#endif
-
- struct UPNPUrls urls;
- struct IGDdatas data;
- int r;
-
- r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
- if (r == 1)
- {
- if (fDiscover) {
- char externalIPAddress[40];
- r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
- if(r != UPNPCOMMAND_SUCCESS)
- printf("UPnP: GetExternalIPAddress() returned %d\n", r);
- else
- {
- if(externalIPAddress[0])
- {
- printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
- AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
- }
- else
- printf("UPnP: GetExternalIPAddress failed.\n");
- }
- }
-
- string strDesc = "NovaCoin " + FormatFullVersion();
-#ifndef UPNPDISCOVER_SUCCESS
- /* miniupnpc 1.5 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
-#else
- /* miniupnpc 1.6 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
-#endif
-
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
- else
- printf("UPnP Port Mapping successful.\n");
- int i = 1;
- while (true)
- {
- if (fShutdown || !fUseUPnP)
- {
- r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
- printf("UPNP_DeletePortMapping() returned : %d\n", r);
- freeUPNPDevlist(devlist); devlist = 0;
- FreeUPNPUrls(&urls);
- return;
- }
- if (i % 600 == 0) // Refresh every 20 minutes
- {
-#ifndef UPNPDISCOVER_SUCCESS
- /* miniupnpc 1.5 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0);
-#else
- /* miniupnpc 1.6 */
- r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
- port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
-#endif
-
- if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
- else
- printf("UPnP Port Mapping successful.\n");;
- }
- Sleep(2000);
- i++;
- }
- } else {
- printf("No valid UPnP IGDs found\n");
- freeUPNPDevlist(devlist); devlist = 0;
- if (r != 0)
- FreeUPNPUrls(&urls);
- while (true)
- {
- if (fShutdown || !fUseUPnP)
- return;
- Sleep(2000);
- }
- }
-}
-
-void MapPort()
-{
- if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1)
- {
- if (!NewThread(ThreadMapPort, NULL))
- printf("Error: ThreadMapPort(ThreadMapPort) failed\n");
- }
-}
-#else
-void MapPort()
-{
- // Intentionally left blank.
-}
-#endif
-
-
-
-
-
-
-
-
-
// DNS seeds
// Each pair gives a source name and a seed name.
// The first name is used as information source for addrman.
{
BOOST_FOREACH(CNetAddr& ip, vaddr)
{
- int nOneDay = 24*3600;
CAddress addr = CAddress(CService(ip, GetDefaultPort()));
addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
"seed24u5dwph3qw4.onion",
"mj26ulzbs2oskgym.onion",
"eqon4usunavt76m7.onion",
+ "seedd3aldwpslzl3.onion"
};
void DumpAddresses()
void ThreadDumpAddress2(void* parg)
{
+ printf("ThreadDumpAddress started\n");
+
vnThreadsRunning[THREAD_DUMPADDRESS]++;
while (!fShutdown)
{
}
}
-// ppcoin: stake minter thread
-void static ThreadStakeMinter(void* parg)
-{
- printf("ThreadStakeMinter started\n");
- CWallet* pwallet = (CWallet*)parg;
- try
- {
- vnThreadsRunning[THREAD_MINTER]++;
- StakeMiner(pwallet);
- vnThreadsRunning[THREAD_MINTER]--;
- }
- catch (std::exception& e) {
- vnThreadsRunning[THREAD_MINTER]--;
- PrintException(&e, "ThreadStakeMinter()");
- } catch (...) {
- vnThreadsRunning[THREAD_MINTER]--;
- PrintException(NULL, "ThreadStakeMinter()");
- }
- printf("ThreadStakeMinter exiting, %d threads remaining\n", vnThreadsRunning[THREAD_MINTER]);
-}
-
void ThreadOpenConnections2(void* parg)
{
printf("ThreadOpenConnections started\n");
// for now, use a very simple selection metric: the node from which we received
// most recently
-double static NodeSyncScore(const CNode *pnode) {
- return -pnode->nLastRecv;
+static int64_t NodeSyncScore(const CNode *pnode) {
+ return pnode->nLastRecv;
}
void static StartSync(const vector<CNode*> &vNodes) {
CNode *pnodeNewSync = NULL;
- double dBestScore = 0;
+ int64_t nBestScore = 0;
// Iterate over all nodes
BOOST_FOREACH(CNode* pnode, vNodes) {
(pnode->nStartingHeight > (nBestHeight - 144)) &&
(pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) {
// if ok, compare node's score with the best so far
- double dScore = NodeSyncScore(pnode);
- if (pnodeNewSync == NULL || dScore > dBestScore) {
+ int64_t nScore = NodeSyncScore(pnode);
+ if (pnodeNewSync == NULL || nScore > nBestScore) {
pnodeNewSync = pnode;
- dBestScore = dScore;
+ nBestScore = nScore;
}
}
}
strError = "";
int nOne = 1;
-#ifdef WIN32
- // Initialize Windows Sockets
- WSADATA wsadata;
- int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
- if (ret != NO_ERROR)
- {
- strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret);
- printf("%s\n", strError.c_str());
- return false;
- }
-#endif
-
// Create socket for listening for incoming connections
#ifdef USE_IPV6
struct sockaddr_storage sockaddr;
return false;
}
+#ifndef WIN32
#ifdef SO_NOSIGPIPE
// Different way of disabling SIGPIPE on BSD
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
#endif
-
-#ifndef WIN32
// Allow binding if the port is still in TIME_WAIT state after
- // the program was closed and restarted. Not an issue on windows.
+ // the program was closed and restarted. Not an issue on windows!
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif
-
#ifdef WIN32
// Set to non-blocking, incoming connections will also inherit this
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
#endif
#endif
#ifdef WIN32
- int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
- int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
- // this call is allowed to fail
- setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
+ int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
+ setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
#endif
}
#endif
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
printf("%s\n", strError.c_str());
+ closesocket(hListenSocket);
return false;
}
printf("Bound to %s\n", addrBind.ToString().c_str());
{
strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
+ closesocket(hListenSocket);
return false;
}
if (semOutbound == NULL) {
// initialize semaphore
- int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125));
+ int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, GetArgInt("-maxconnections", 125));
semOutbound = new CSemaphore(nMaxOutbound);
}
if (pnodeLocalHost == NULL)
- pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
+ pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", nPortZero), nLocalServices));
Discover();
if (!NewThread(ThreadDNSAddressSeed, NULL))
printf("Error: NewThread(ThreadDNSAddressSeed) failed\n");
- // Map ports with UPnP
- if (!fUseUPnP)
- printf("UPNP port mapping is disabled\n");
- else
- MapPort();
-
// Get addresses from IRC and advertise ours
if (!GetBoolArg("-irc", true))
printf("IRC seeding disabled\n");
if (!NewThread(ThreadDumpAddress, NULL))
printf("Error; NewThread(ThreadDumpAddress) failed\n");
- // ppcoin: mint proof-of-stake blocks in the background
- if (!NewThread(ThreadStakeMinter, pwalletMain))
- printf("Error: NewThread(ThreadStakeMinter) failed\n");
+ // Mine proof-of-stake blocks in the background
+ if (!NewThread(ThreadStakeMiner, pwalletMain))
+ printf("Error: NewThread(ThreadStakeMiner) failed\n");
+
+ // Trusted NTP server, it's localhost by default.
+ strTrustedUpstream = GetArg("-ntp", "localhost");
+
+ // Start periodical NTP sampling thread
+ NewThread(ThreadNtpSamples, NULL);
+
}
bool StopNode()
if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n");
if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n");
if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n");
-#ifdef USE_UPNP
- if (vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n");
-#endif
if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n");
if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n");
if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n");
Sleep(20);
Sleep(50);
DumpAddresses();
+
return true;
}
if (closesocket(hListenSocket) == SOCKET_ERROR)
printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
+ // clean up some globals (to help leak detection)
+ BOOST_FOREACH(CNode *pnode, vNodes)
+ delete pnode;
+ BOOST_FOREACH(CNode *pnode, vNodesDisconnected)
+ delete pnode;
+ vNodes.clear();
+ vNodesDisconnected.clear();
+ delete semOutbound;
+ semOutbound = NULL;
+ delete pnodeLocalHost;
+ pnodeLocalHost = NULL;
+
#ifdef WIN32
// Shutdown Windows Sockets
WSACleanup();