bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { vIP.clear(); { CNetAddr addr; if (addr.SetSpecial(std::string(pszName))) { vIP.push_back(addr); return true; } } struct addrinfo aiHint; memset(&aiHint, 0, sizeof(struct addrinfo)); aiHint.ai_socktype = SOCK_STREAM; aiHint.ai_protocol = IPPROTO_TCP; #ifdef USE_IPV6 aiHint.ai_family = AF_UNSPEC; #else aiHint.ai_family = AF_INET; #endif #ifdef WIN32 aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST; #else aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; #endif struct addrinfo *aiRes = NULL; int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes); if (nErr) return false; struct addrinfo *aiTrav = aiRes; while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) { if (aiTrav->ai_family == AF_INET) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); } #ifdef USE_IPV6 if (aiTrav->ai_family == AF_INET6) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); } #endif aiTrav = aiTrav->ai_next; } freeaddrinfo(aiRes); return (vIP.size() > 0); }
int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const { std::vector<unsigned char> vchSourceGroupKey = src.GetGroup(); uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetLow64(); uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetLow64(); return hash2 % ADDRMAN_NEW_BUCKET_COUNT; }
/** Check if a network address is allowed to access the HTTP server */ static bool ClientAllowed(const CNetAddr& netaddr) { if (!netaddr.IsValid()) return false; BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets) if (subnet.Match(netaddr)) return true; return false; }
int CAddrInfo::GetNewBucket(const std::vector<unsigned char>& nKey, const CNetAddr& src) const { CDataStream ss1(SER_GETHASH, 0); std::vector<unsigned char> vchGroupKey = GetGroup(); std::vector<unsigned char> vchSourceGroupKey = src.GetGroup(); ss1 << nKey << vchGroupKey << vchSourceGroupKey; uint64_t hash1 = Hash(ss1.begin(), ss1.end()).GetLow64(); CDataStream ss2(SER_GETHASH, 0); ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP); uint64_t hash2 = Hash(ss2.begin(), ss2.end()).GetLow64(); return hash2 % ADDRMAN_NEW_BUCKET_COUNT; }
int64 NtpGetTime(const std::string &strHostName) { int64 nTime; SOCKET sockfd; socklen_t servlen; struct sockaddr cliaddr; if(!InitWithHost(strHostName, sockfd, servlen, &cliaddr)) return(-1); CNetAddr ip = ((sockaddr_in *) &cliaddr)->sin_addr; printf("NtpGetTime() : querying an NTP server %s\n", ip.ToStringIP().c_str()); nTime = DoReq(sockfd, servlen, cliaddr); closesocket(sockfd); if((nTime > 0) && (nTime != 2085978496)) { printf("NtpGetTime() : time sample %" PRI64d " offset %+" PRI64d " received from %s\n", nTime, nTime - GetTime(), ip.ToStringIP().c_str()); } return(nTime); }
// int CAddrInfo::GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const { // CDataStream ss1(SER_GETHASH, 0); // std::vector<unsigned char> vchGroupKey = GetGroup(); std::vector<unsigned char> vchSourceGroupKey = src.GetGroup(); // ss1 << nKey << vchGroupKey << vchSourceGroupKey; /* ss1 << nKey << vchGroupKey << vchSourceGroupKey; uint64_t hash1 = Hash(ss1.begin(), ss1.end()).GetCheapHash(); CDataStream ss2(SER_GETHASH, 0); // ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP); ss2 << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP); uint64_t hash2 = Hash(ss2.begin(), ss2.end()).GetCheapHash(); */ uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetCheapHash(); uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetCheapHash(); return hash2 % ADDRMAN_NEW_BUCKET_COUNT; }
bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) { SOCKET hSocket; if(!ConnectSocket(addrConnect, hSocket)) return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL); string strLine; while(RecvLine(hSocket, strLine)) { if(strLine.empty()) // HTTP response is separated from headers by blank line { loop { if(!RecvLine(hSocket, strLine)) { closesocket(hSocket); return false; } if(pszKeyword == NULL) break; if(strLine.find(pszKeyword) != string::npos) { strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); break; } } closesocket(hSocket); if(strLine.find("<") != string::npos) strLine = strLine.substr(0, strLine.find("<")); strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); while(strLine.size() > 0 && isspace(strLine[strLine.size()-1])) strLine.resize(strLine.size()-1); CService addr(strLine,0,true); printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); if(!addr.IsValid() || !addr.IsRoutable()) return false; ipRet.SetIP(addr); return true; } }
void ThreadIRCSeed2(void* parg) { // Don't connect to IRC if we won't use IPv4 connections. if (IsLimited(NET_IPV4)) return; // ... or if we won't make outbound connections and won't accept inbound ones. if (mapArgs.count("-connect") && fNoListen) return; // ... or if IRC is not enabled. if (!GetBoolArg("-irc", false)) return; printf("ThreadIRCSeed started\n"); int nErrorWait = 10; int nRetryWait = 10; int nNameRetry = 0; while (!fShutdown) { CService addrConnect("92.243.23.21", 6667); // irc.lfnet.org CService addrIRC("irc.lfnet.org", 6667, true); if (addrIRC.IsValid()) addrConnect = addrIRC; SOCKET hSocket; if (!ConnectSocket(addrConnect, hSocket)) { printf("IRC connect failed\n"); nErrorWait = nErrorWait * 11 / 10; if (Wait(nErrorWait += 60)) continue; else return; } if (!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname")) { closesocket(hSocket); hSocket = INVALID_SOCKET; nErrorWait = nErrorWait * 11 / 10; if (Wait(nErrorWait += 60)) continue; else return; } CNetAddr addrIPv4("1.2.3.4"); // arbitrary IPv4 address to make GetLocal prefer IPv4 addresses CService addrLocal; string strMyName; // Don't use our IP as our nick if we're not listening // or if it keeps failing because the nick is already in use. if (!fNoListen && GetLocal(addrLocal, &addrIPv4) && nNameRetry<3) strMyName = EncodeAddress(GetLocalAddress(&addrConnect)); if (strMyName == "") strMyName = strprintf("x%"PRIu64"", GetRand(1000000000)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str()); int nRet = RecvUntil(hSocket, " 004 ", " 433 "); if (nRet != 1) { closesocket(hSocket); hSocket = INVALID_SOCKET; if (nRet == 2) { printf("IRC name already in use\n"); nNameRetry++; Wait(10); continue; } nErrorWait = nErrorWait * 11 / 10; if (Wait(nErrorWait += 60)) continue; else return; } nNameRetry = 0; MilliSleep(500); // Get our external IP from the IRC server and re-nick before joining the channel CNetAddr addrFromIRC; if (GetIPFromIRC(hSocket, strMyName, addrFromIRC)) { printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str()); // Don't use our IP as our nick if we're not listening if (!fNoListen && addrFromIRC.IsRoutable()) { // IRC lets you to re-nick AddLocal(addrFromIRC, LOCAL_IRC); strMyName = EncodeAddress(GetLocalAddress(&addrConnect)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); } } if (fTestNet) { Send(hSocket, "JOIN #WebcoinTEST\r"); Send(hSocket, "WHO #WebcoinTEST\r"); } else { // randomly join #Webcoin00-#Webcoin05 //int channel_number = GetRandInt(5); int channel_number = 0; // Channel number is always 0 for initial release //int channel_number = 0; Send(hSocket, strprintf("JOIN #Webcoin%02d\r", channel_number).c_str()); Send(hSocket, strprintf("WHO #Webcoin%02d\r", channel_number).c_str()); } int64_t nStart = GetTime(); string strLine; strLine.reserve(10000); while (!fShutdown && RecvLineIRC(hSocket, strLine)) { if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':') continue; vector<string> vWords; ParseString(strLine, ' ', vWords); if (vWords.size() < 2) continue; char pszName[10000]; pszName[0] = '\0'; if (vWords[1] == "352" && vWords.size() >= 8) { // index 7 is limited to 16 characters // could get full length name at index 10, but would be different from join messages strlcpy(pszName, vWords[7].c_str(), sizeof(pszName)); printf("IRC got who\n"); } if (vWords[1] == "JOIN" && vWords[0].size() > 1) { // :[email protected] JOIN :#channelname strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName)); if (strchr(pszName, '!')) *strchr(pszName, '!') = '\0'; printf("IRC got join\n"); } if (pszName[0] == 'u') { CAddress addr; if (DecodeAddress(pszName, addr)) { addr.nTime = GetAdjustedTime(); if (addrman.Add(addr, addrConnect, 51 * 60)) printf("IRC got new address: %s\n", addr.ToString().c_str()); nGotIRCAddresses++; } else { printf("IRC decode failed\n"); } } } closesocket(hSocket); hSocket = INVALID_SOCKET; if (GetTime() - nStart > 20 * 60) { nErrorWait /= 3; nRetryWait /= 3; } nRetryWait = nRetryWait * 11 / 10; if (!Wait(nRetryWait += 60)) return; } }
static UniValue setban(const JSONRPCRequest& request) { std::string strCommand; if (!request.params[1].isNull()) strCommand = request.params[1].get_str(); if (request.fHelp || request.params.size() < 2 || (strCommand != "add" && strCommand != "remove")) throw std::runtime_error( "setban \"subnet\" \"add|remove\" (bantime) (absolute)\n" "\nAttempts to add or remove an IP/Subnet from the banned list.\n" "\nArguments:\n" "1. \"subnet\" (string, required) The IP/Subnet (see getpeerinfo for nodes IP) with an optional netmask (default is /32 = single IP)\n" "2. \"command\" (string, required) 'add' to add an IP/Subnet to the list, 'remove' to remove an IP/Subnet from the list\n" "3. \"bantime\" (numeric, optional) time in seconds how long (or until when if [absolute] is set) the IP is banned (0 or empty means using the default time of 24h which can also be overwritten by the -bantime startup argument)\n" "4. \"absolute\" (boolean, optional) If set, the bantime must be an absolute timestamp in seconds since epoch (Jan 1 1970 GMT)\n" "\nExamples:\n" + HelpExampleCli("setban", "\"192.168.0.6\" \"add\" 86400") + HelpExampleCli("setban", "\"192.168.0.0/24\" \"add\"") + HelpExampleRpc("setban", "\"192.168.0.6\", \"add\", 86400") ); if(!g_connman) throw JSONRPCError(RPC_CLIENT_P2P_DISABLED, "Error: Peer-to-peer functionality missing or disabled"); CSubNet subNet; CNetAddr netAddr; bool isSubnet = false; if (request.params[0].get_str().find('/') != std::string::npos) isSubnet = true; if (!isSubnet) { CNetAddr resolved; LookupHost(request.params[0].get_str().c_str(), resolved, false); netAddr = resolved; } else LookupSubNet(request.params[0].get_str().c_str(), subNet); if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) ) throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Invalid IP/Subnet"); if (strCommand == "add") { if (isSubnet ? g_connman->IsBanned(subNet) : g_connman->IsBanned(netAddr)) throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned"); int64_t banTime = 0; //use standard bantime if not specified if (!request.params[2].isNull()) banTime = request.params[2].get_int64(); bool absolute = false; if (request.params[3].isTrue()) absolute = true; isSubnet ? g_connman->Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : g_connman->Ban(netAddr, BanReasonManuallyAdded, banTime, absolute); } else if(strCommand == "remove") { if (!( isSubnet ? g_connman->Unban(subNet) : g_connman->Unban(netAddr) )) throw JSONRPCError(RPC_CLIENT_INVALID_IP_OR_SUBNET, "Error: Unban failed. Requested address/subnet was not previously banned."); } return NullUniValue; }
bool static LookupIntern(const char* pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { vIP.clear(); { CNetAddr addr; if (addr.SetSpecial(std::string(pszName))) { vIP.push_back(addr); return true; } } #ifdef HAVE_GETADDRINFO_A struct in_addr ipv4_addr; #ifdef HAVE_INET_PTON if (inet_pton(AF_INET, pszName, &ipv4_addr) > 0) { vIP.push_back(CNetAddr(ipv4_addr)); return true; } struct in6_addr ipv6_addr; if (inet_pton(AF_INET6, pszName, &ipv6_addr) > 0) { vIP.push_back(CNetAddr(ipv6_addr)); return true; } #else ipv4_addr.s_addr = inet_addr(pszName); if (ipv4_addr.s_addr != INADDR_NONE) { vIP.push_back(CNetAddr(ipv4_addr)); return true; } #endif #endif struct addrinfo aiHint; memset(&aiHint, 0, sizeof(struct addrinfo)); aiHint.ai_socktype = SOCK_STREAM; aiHint.ai_protocol = IPPROTO_TCP; aiHint.ai_family = AF_UNSPEC; #ifdef WIN32 aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST; #else aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; #endif struct addrinfo* aiRes = NULL; #ifdef HAVE_GETADDRINFO_A struct gaicb gcb, *query = &gcb; memset(query, 0, sizeof(struct gaicb)); gcb.ar_name = pszName; gcb.ar_request = &aiHint; int nErr = getaddrinfo_a(GAI_NOWAIT, &query, 1, NULL); if (nErr) return false; do { // Should set the timeout limit to a resonable value to avoid // generating unnecessary checking call during the polling loop, // while it can still response to stop request quick enough. // 2 seconds looks fine in our situation. struct timespec ts = {2, 0}; gai_suspend(&query, 1, &ts); boost::this_thread::interruption_point(); nErr = gai_error(query); if (0 == nErr) aiRes = query->ar_result; } while (nErr == EAI_INPROGRESS); #else int nErr = getaddrinfo(pszName, NULL, &aiHint, &aiRes); #endif if (nErr) return false; struct addrinfo* aiTrav = aiRes; while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) { if (aiTrav->ai_family == AF_INET) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); } if (aiTrav->ai_family == AF_INET6) { assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); } aiTrav = aiTrav->ai_next; } freeaddrinfo(aiRes); return (vIP.size() > 0); }
static CNetAddr CreateInternal(const char* host) { CNetAddr addr; addr.SetInternal(host); return addr; }
/** check whether a given address is in a network we can probably connect to */ bool IsReachable(const CNetAddr &addr) { LOCK(cs_mapLocalHost); enum Network net = addr.GetNetwork(); return vfReachable[net] && !vfLimited[net]; }
bool IsLimited(const CNetAddr &addr) { return IsLimited(addr.GetNetwork()); }
void ThreadIRCSeed2(void* parg) { /* Dont advertise on IRC if we don't allow incoming connections */ if(mapArgs.count("-connect") || fNoListen) return; if(!GetBoolArg("-irc", false)) return; printf("ThreadIRCSeed started\n"); int nErrorWait = 10; int nRetryWait = 10; bool fNameInUse = false; while(!fShutdown) { CService addrConnect("92.243.23.21", 6667); // irc.lfnet.org CService addrIRC("irc.lfnet.org", 6667, true); if(addrIRC.IsValid()) addrConnect = addrIRC; SOCKET hSocket; if(!ConnectSocket(addrConnect, hSocket)) { printf("IRC connect failed\n"); nErrorWait = nErrorWait * 11 / 10; if(Wait(nErrorWait += 60)) continue; else return; } if(!RecvUntil(hSocket, "Found your hostname", "using your IP address instead", "Couldn't look up your hostname", "ignoring hostname")) { closesocket(hSocket); hSocket = INVALID_SOCKET; nErrorWait = nErrorWait * 11 / 10; if(Wait(nErrorWait += 60)) continue; else return; } string strMyName; if(addrLocalHost.IsRoutable() && !fUseProxy && !fNameInUse) strMyName = EncodeAddress(addrLocalHost); else strMyName = strprintf("x%u", GetRand(1000000000)); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); Send(hSocket, strprintf("USER %s 8 * : %s\r", strMyName.c_str(), strMyName.c_str()).c_str()); int nRet = RecvUntil(hSocket, " 004 ", " 433 "); if(nRet != 1) { closesocket(hSocket); hSocket = INVALID_SOCKET; if(nRet == 2) { printf("IRC name already in use\n"); fNameInUse = true; Wait(10); continue; } nErrorWait = nErrorWait * 11 / 10; if(Wait(nErrorWait += 60)) continue; else return; } Sleep(500); // Get our external IP from the IRC server and re-nick before joining the channel CNetAddr addrFromIRC; if(GetIPFromIRC(hSocket, strMyName, addrFromIRC)) { printf("GetIPFromIRC() returned %s\n", addrFromIRC.ToString().c_str()); if(!fUseProxy && addrFromIRC.IsRoutable()) { // IRC lets you to re-nick fGotExternalIP = true; addrLocalHost.SetIP(addrFromIRC); strMyName = EncodeAddress(addrLocalHost); Send(hSocket, strprintf("NICK %s\r", strMyName.c_str()).c_str()); } } if(fTestNet) { Send(hSocket, "JOIN #bitcoinTEST\r"); Send(hSocket, "WHO #bitcoinTEST\r"); } else { // randomly join #bitcoin00-#bitcoin99 int channel_number = GetRandInt(100); Send(hSocket, strprintf("JOIN #bitcoin%02d\r", channel_number).c_str()); Send(hSocket, strprintf("WHO #bitcoin%02d\r", channel_number).c_str()); } int64 nStart = GetTime(); string strLine; strLine.reserve(10000); while(!fShutdown && RecvLineIRC(hSocket, strLine)) { if(strLine.empty() || strLine.size() > 900 || strLine[0] != ':') continue; vector<string> vWords; ParseString(strLine, ' ', vWords); if(vWords.size() < 2) continue; char pszName[10000]; pszName[0] = '\0'; if(vWords[1] == "352" && vWords.size() >= 8) { // index 7 is limited to 16 characters // could get full length name at index 10, but would be different from join messages strlcpy(pszName, vWords[7].c_str(), sizeof(pszName)); printf("IRC got who\n"); } if(vWords[1] == "JOIN" && vWords[0].size() > 1) { // :[email protected] JOIN :#channelname strlcpy(pszName, vWords[0].c_str() + 1, sizeof(pszName)); if(strchr(pszName, '!')) *strchr(pszName, '!') = '\0'; printf("IRC got join\n"); } if(pszName[0] == 'u') { CAddress addr; if(DecodeAddress(pszName, addr)) { addr.nTime = GetAdjustedTime(); if(addrman.Add(addr, addrConnect, 51 * 60)) printf("IRC got new address: %s\n", addr.ToString().c_str()); nGotIRCAddresses++; } else { printf("IRC decode failed\n"); } } } closesocket(hSocket); hSocket = INVALID_SOCKET; if(GetTime() - nStart > 20 * 60) { nErrorWait /= 3; nRetryWait /= 3; } nRetryWait = nRetryWait * 11 / 10; if(!Wait(nRetryWait += 60)) return; } }
int64_t DoReq(SOCKET sockfd, socklen_t servlen, struct sockaddr cliaddr) { #ifdef WIN32 u_long nOne = 1; if (ioctlsocket(sockfd, FIONBIO, &nOne) == SOCKET_ERROR) { printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError()); #else if (fcntl(sockfd, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) { printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno); #endif return -2; } struct timeval timeout = {10, 0}; struct pkt *msg = new pkt; struct pkt *prt = new pkt; time_t seconds_transmit; int len = 48; msg->li_vn_mode=227; msg->stratum=0; msg->ppoll=4; msg->precision=0; msg->rootdelay=0; msg->rootdispersion=0; msg->ref.Ul_i.Xl_i=0; msg->ref.Ul_f.Xl_f=0; msg->org.Ul_i.Xl_i=0; msg->org.Ul_f.Xl_f=0; msg->rec.Ul_i.Xl_i=0; msg->rec.Ul_f.Xl_f=0; msg->xmt.Ul_i.Xl_i=0; msg->xmt.Ul_f.Xl_f=0; int retcode = sendto(sockfd, (char *) msg, len, 0, &cliaddr, servlen); if (retcode < 0) { printf("sendto() failed: %d\n", retcode); seconds_transmit = -3; goto _end; } fd_set fdset; FD_ZERO(&fdset); FD_SET(sockfd, &fdset); retcode = select(sockfd + 1, &fdset, NULL, NULL, &timeout); if (retcode <= 0) { printf("recvfrom() error\n"); seconds_transmit = -4; goto _end; } recvfrom(sockfd, (char *) msg, len, 0, NULL, NULL); ntohl_fp(&msg->xmt, &prt->xmt); Ntp2Unix(prt->xmt.Ul_i.Xl_ui, seconds_transmit); _end: delete msg; delete prt; return seconds_transmit; } int64_t NtpGetTime(CNetAddr& ip) { struct sockaddr cliaddr; SOCKET sockfd; socklen_t servlen; if (!InitWithRandom(sockfd, servlen, &cliaddr)) return -1; ip = CNetAddr(((sockaddr_in *)&cliaddr)->sin_addr); int64_t nTime = DoReq(sockfd, servlen, cliaddr); closesocket(sockfd); return nTime; } int64_t NtpGetTime(const std::string &strHostName) { struct sockaddr cliaddr; SOCKET sockfd; socklen_t servlen; if (!InitWithHost(strHostName, sockfd, servlen, &cliaddr)) return -1; int64_t nTime = DoReq(sockfd, servlen, cliaddr); closesocket(sockfd); return nTime; } // NTP server, which we unconditionally trust. This may be your own installation of ntpd somewhere, for example. // "localhost" means "trust no one" std::string strTrustedUpstream = "localhost"; // Current offset int64_t nNtpOffset = INT64_MAX; int64_t GetNtpOffset() { return nNtpOffset; } void ThreadNtpSamples(void* parg) { const int64_t nMaxOffset = 86400; // Not a real limit, just sanity threshold. printf("Trying to find NTP server at localhost...\n"); std::string strLocalHost = "127.0.0.1"; if (NtpGetTime(strLocalHost) == GetTime()) { printf("There is NTP server active at localhost, we don't need NTP thread.\n"); nNtpOffset = 0; return; } printf("ThreadNtpSamples started\n"); vnThreadsRunning[THREAD_NTP]++; // Make this thread recognisable as time synchronization thread RenameThread("Chipcoin-ntp-samples"); CMedianFilter<int64_t> vTimeOffsets(200,0); while (!fShutdown) { if (strTrustedUpstream != "localhost") { // Trying to get new offset sample from trusted NTP server. int64_t nClockOffset = NtpGetTime(strTrustedUpstream) - GetTime(); if (abs64(nClockOffset) < nMaxOffset) { // Everything seems right, remember new trusted offset. printf("ThreadNtpSamples: new offset sample from %s, offset=%" PRId64 ".\n", strTrustedUpstream.c_str(), nClockOffset); nNtpOffset = nClockOffset; } else { // Something went wrong, disable trusted offset sampling. nNtpOffset = INT64_MAX; strTrustedUpstream = "localhost"; int nSleepMinutes = 1 + GetRandInt(9); // Sleep for 1-10 minutes. for (int i = 0; i < nSleepMinutes * 60 && !fShutdown; i++) MilliSleep(1000); continue; } } else { // Now, trying to get 2-4 samples from random NTP servers. int nSamplesCount = 2 + GetRandInt(2); for (int i = 0; i < nSamplesCount; i++) { CNetAddr ip; int64_t nClockOffset = NtpGetTime(ip) - GetTime(); if (abs64(nClockOffset) < nMaxOffset) { // Skip the deliberately wrong timestamps printf("ThreadNtpSamples: new offset sample from %s, offset=%" PRId64 ".\n", ip.ToString().c_str(), nClockOffset); vTimeOffsets.input(nClockOffset); } } if (vTimeOffsets.size() > 1) { nNtpOffset = vTimeOffsets.median(); } else { // Not enough offsets yet, try to collect additional samples later. nNtpOffset = INT64_MAX; int nSleepMinutes = 1 + GetRandInt(4); // Sleep for 1-5 minutes. for (int i = 0; i < nSleepMinutes * 60 && !fShutdown; i++) MilliSleep(1000); continue; } } if (GetNodesOffset() == INT_MAX && abs64(nNtpOffset) > 40 * 60) { // If there is not enough node offsets data and NTP time offset is greater than 40 minutes then give a warning. std::string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Chipcoin will not work properly."); strMiscWarning = strMessage; printf("*** %s\n", strMessage.c_str()); uiInterface.ThreadSafeMessageBox(strMessage+" ", std::string("Chipcoin"), CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION); } printf("nNtpOffset = %+" PRId64 " (%+" PRId64 " minutes)\n", nNtpOffset, nNtpOffset/60); int nSleepHours = 1 + GetRandInt(5); // Sleep for 1-6 hours. for (int i = 0; i < nSleepHours * 3600 && !fShutdown; i++) MilliSleep(1000); } vnThreadsRunning[THREAD_NTP]--; printf("ThreadNtpSamples exited\n"); }