X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fntp.cpp;h=2ce65e1cd847e3921b8515ef8a27aa77e47b1151;hb=0c15e9be384df1db22a714c3ec77e9902df0492f;hp=943b2b5d760143ee8b6c64408b9e96e4c50c1e9c;hpb=a383831a846ae659de7cada6f0e5345f9420f3d6;p=novacoin.git diff --git a/src/ntp.cpp b/src/ntp.cpp index 943b2b5..2ce65e1 100644 --- a/src/ntp.cpp +++ b/src/ntp.cpp @@ -1,4 +1,3 @@ - #ifdef WIN32 #include #else @@ -13,8 +12,8 @@ #endif #include "netbase.h" -#include "util.h" #include "net.h" +#include "util.h" extern int GetRandInt(int nMax); @@ -80,9 +79,9 @@ struct pkt { uint8_t mac[5 * sizeof(uint32_t)]; /* mac */ }; -int nServersCount = 112; +const int nServersCount = 147; -std::string NtpServers[112] = { +std::string NtpServers[147] = { // Microsoft "time.windows.com", @@ -92,6 +91,16 @@ std::string NtpServers[112] = { "time3.google.com", "time4.google.com", + // Hurricane Electric + "clock.sjc.he.net", + "clock.nyc.he.net", + + // SixXS + "ntp.sixxs.net", + "ntp.eu.sixxs.net", + "ntp.us.sixxs.net", + "ntp.ap.sixxs.net", + // Russian Federation "ntp.karelia.pro", "ntp.alpet.me", @@ -127,6 +136,15 @@ std::string NtpServers[112] = { "3.ru.pool.ntp.org", // United States + "tock.cs.unlv.edu", + "timex.cs.columbia.edu", + "tick.cs.unlv.edu", + "sundial.columbia.edu", + "ntp-1.ece.cmu.edu", + "ntp-2.ece.cmu.edu", + "ntp1.cs.wisc.edu", + "ntp2.cs.wisc.edu", + "ntp3.cs.wisc.edu", "ntp-01.caltech.edu", "ntp-02.caltech.edu", "ntp-03.caltech.edu", @@ -198,6 +216,7 @@ std::string NtpServers[112] = { // United Kingdom "ntp2d.mcc.ac.uk", "ntp2c.mcc.ac.uk", + "ntp2b.mcc.ac.uk", "ntp.exnet.com", "ntp.cis.strath.ac.uk", "ntppub.le.ac.uk", @@ -206,6 +225,19 @@ std::string NtpServers[112] = { "2.uk.pool.ntp.org", "3.uk.pool.ntp.org", + // Canada + "chime.utoronto.ca", + "tick.utoronto.ca", + "time.nrc.ca", + "timelord.uregina.ca", + "tock.utoronto.ca", + "www1.cmc.ec.gc.ca", + "www2.cmc.ec.gc.ca", + "0.ca.pool.ntp.org", + "1.ca.pool.ntp.org", + "2.ca.pool.ntp.org", + "3.ca.pool.ntp.org", + // Japan "ntp.nict.jp", "0.jp.pool.ntp.org", @@ -213,53 +245,22 @@ std::string NtpServers[112] = { "2.jp.pool.ntp.org", "3.jp.pool.ntp.org", - // ... To be continued -}; - -bool InitWithRandom(SOCKET &sockfd, socklen_t &servlen, struct sockaddr *pcliaddr) { - int nAttempt = 0; - - while(nAttempt < 100) { - sockfd = -1; - nAttempt++; - - int nServerNum = GetRandInt(nServersCount); - - std::vector vIP; - bool fRet = LookupHost(NtpServers[nServerNum].c_str(), vIP, 10, true); - if (!fRet) - continue; - - struct sockaddr_in servaddr; - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(123); - - bool found = false; - for(unsigned int i = 0; i < vIP.size(); i++) { - if ((found = vIP[i].GetInAddr(&servaddr.sin_addr))) { - break; - } - } - - if (!found) - continue; - - sockfd = socket(AF_INET, SOCK_DGRAM, 0); + // Australia + "ntp.cs.mu.oz.au", + "augean.eleceng.adelaide.edu.au", + "0.au.pool.ntp.org", + "1.au.pool.ntp.org", + "2.au.pool.ntp.org", + "3.au.pool.ntp.org", - if (sockfd == INVALID_SOCKET) - continue; // socket initialization error + // Slovenia + "time.ijs.si", - if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1 ) { - continue; // "connection" error - } - - *pcliaddr = *((struct sockaddr *) &servaddr); - servlen = sizeof(servaddr); - return true; - } + // ??? + "clepsydra.dec.com", - return false; -} + // ... To be continued +}; bool InitWithHost(std::string &strHostName, SOCKET &sockfd, socklen_t &servlen, struct sockaddr *pcliaddr) { sockfd = -1; @@ -301,6 +302,17 @@ bool InitWithHost(std::string &strHostName, SOCKET &sockfd, socklen_t &servlen, return true; } +bool InitWithRandom(SOCKET &sockfd, socklen_t &servlen, struct sockaddr *pcliaddr) { + + for (int nAttempt = 0; nAttempt < nServersCount; nAttempt++) { + int nServerNum = GetRandInt(nServersCount); + if (InitWithHost(NtpServers[nServerNum], sockfd, servlen, pcliaddr)) { + return true; + } + } + + return false; +} int64_t DoReq(SOCKET sockfd, socklen_t servlen, struct sockaddr cliaddr) { #ifdef WIN32 @@ -352,36 +364,14 @@ int64_t DoReq(SOCKET sockfd, socklen_t servlen, struct sockaddr cliaddr) { } recvfrom(sockfd, (char *) msg, len, 0, NULL, NULL); - - ntohl_fp(&msg->rec, &prt->rec); ntohl_fp(&msg->xmt, &prt->xmt); - - time_t seconds_receive; time_t seconds_transmit; - - Ntp2Unix(prt->rec.Ul_i.Xl_ui, seconds_receive); Ntp2Unix(prt->xmt.Ul_i.Xl_ui, seconds_transmit); delete msg; delete prt; - return (seconds_receive + seconds_transmit) / 2; -} - -int64_t NtpGetTime() { - struct sockaddr cliaddr; - - SOCKET sockfd; - socklen_t servlen; - - if (!InitWithRandom(sockfd, servlen, &cliaddr)) - return -1; - - int64_t nTime = DoReq(sockfd, servlen, cliaddr); - - closesocket(sockfd); - - return nTime; + return seconds_transmit; } int64_t NtpGetTime(CNetAddr& ip) { @@ -418,27 +408,82 @@ int64_t NtpGetTime(std::string &strHostName) return nTime; } -void ThreadNtpSamples(void* parg) -{ +// 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) { + + // Maximum offset is 2 hours. + const int64_t nMaxOffset = 7200; + printf("ThreadNtpSamples started\n"); vnThreadsRunning[THREAD_NTP]++; // Make this thread recognisable as time synchronization thread RenameThread("novacoin-ntp-samples"); + CMedianFilter vTimeOffsets(200,0); + while (!fShutdown) { - CNetAddr ip; - int64_t nTime = NtpGetTime(ip); + 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. + nNtpOffset = nClockOffset; + } + else { + // Something went wrong, disable trusted offset sampling. + nNtpOffset = INT64_MAX; + strTrustedUpstream = "localhost"; - if (nTime > 0 && nTime != 2085978496) { // Skip the deliberately wrong timestamps - AddTimeData(ip, nTime); + int nSleepMinutes = 1 + GetRandInt(9); // Sleep for 1-10 minutes. + for (int i = 0; i < nSleepMinutes * 60 && !fShutdown; i++) + Sleep(1000); + + continue; + } } else { - Sleep(600000); // In case of failure wait 600 seconds and then try again - continue; + // 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 + vTimeOffsets.input(nClockOffset); + } + } + + if (vTimeOffsets.size() > 2) { + nNtpOffset = vTimeOffsets.median(); + } + else { + // Not enough offsets yet, try again later. + nNtpOffset = INT64_MAX; + int nSleepMinutes = 1 + GetRandInt(4); // Sleep for 1-5 minutes. + for (int i = 0; i < nSleepMinutes * 60 && !fShutdown; i++) + Sleep(1000); + continue; + } } - Sleep(43200000); // Sleep for 12 hours + 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++) + Sleep(1000); } vnThreadsRunning[THREAD_NTP]--;