X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.cpp;h=f798da67d1969ce1513e38cf05054153ddacef00;hb=f3a7ca84494552ea5ec6469cb0f5149217ce891c;hp=197e5624c31319cedda46639cc708bddd3318e79;hpb=24b2f2d42d10153c24ccef4a14ba57ad24aac183;p=novacoin.git diff --git a/src/util.cpp b/src/util.cpp index 197e562..f798da6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5,39 +5,23 @@ #include "util.h" #include "sync.h" -#include "strlcpy.h" #include "version.h" #include "ui_interface.h" -#include -// Work around clang compilation problem in Boost 1.46: -// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup -// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options -// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION -namespace boost { - namespace program_options { - std::string to_internal(const std::string&); - } -} +#include +#include #include #include #include #include - #include -#include #include + #include #include #ifdef WIN32 -#ifdef _MSC_VER -#pragma warning(disable:4786) -#pragma warning(disable:4804) -#pragma warning(disable:4805) -#pragma warning(disable:4717) -#endif #ifdef _WIN32_WINNT #undef _WIN32_WINNT #endif @@ -53,14 +37,13 @@ namespace boost { #include /* for _commit */ #include "shlobj.h" #elif defined(__linux__) -# include +#include #endif #if !defined(WIN32) && !defined(ANDROID) #include #endif - using namespace std; namespace bt = boost::posix_time; @@ -84,17 +67,17 @@ bool fReopenDebugLog = false; // Extended DecodeDumpTime implementation, see this page for details: // http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost -const std::locale formats[] = { - std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")), - std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")), - std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")), - std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")), - std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d")) +const locale formats[] = { + locale(locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")), + locale(locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")), + locale(locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")), + locale(locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")), + locale(locale::classic(),new bt::time_input_facet("%Y-%m-%d")) }; const size_t formats_n = sizeof(formats)/sizeof(formats[0]); -std::time_t pt_to_time_t(const bt::ptime& pt) +time_t pt_to_time_t(const bt::ptime& pt) { bt::ptime timet_start(boost::gregorian::date(1970,1,1)); bt::time_duration diff = pt - timet_start; @@ -145,13 +128,6 @@ public: } instance_of_cinit; - - - - - - - void RandAddSeed() { // Seed with CPU performance counter @@ -181,7 +157,7 @@ void RandAddSeedPerfmon() if (ret == ERROR_SUCCESS) { RAND_add(pdata, nSize, nSize/100.0); - memset(pdata, 0, nSize); + OPENSSL_cleanse(pdata, nSize); printf("RandAddSeed() %lu bytes\n", nSize); } #endif @@ -194,7 +170,7 @@ uint64_t GetRand(uint64_t nMax) // The range of the random source must be a multiple of the modulus // to give every possible output value an equal possibility - uint64_t nRange = (std::numeric_limits::max() / nMax) * nMax; + uint64_t nRange = (numeric_limits::max() / nMax) * nMax; uint64_t nRand = 0; do RAND_bytes((unsigned char*)&nRand, sizeof(nRand)); @@ -204,20 +180,20 @@ uint64_t GetRand(uint64_t nMax) int GetRandInt(int nMax) { - return GetRand(nMax); + return static_cast(GetRand(nMax)); } uint256 GetRandHash() { uint256 hash; - RAND_bytes((unsigned char*)&hash, sizeof(hash)); + RAND_bytes(hash.begin(), hash.size()); return hash; } - - - - +void FillRand(uint8_t *buffer, size_t nCount) +{ + RAND_bytes(buffer, nCount); +} static FILE* fileout = NULL; @@ -285,15 +261,15 @@ inline int OutputDebugStringF(const char* pszFormat, ...) // accumulate and output a line at a time { LOCK(cs_OutputDebugStringF); - static std::string buffer; + static string buffer; va_list arg_ptr; va_start(arg_ptr, pszFormat); buffer += vstrprintf(pszFormat, arg_ptr); va_end(arg_ptr); - int line_start = 0, line_end; - while((line_end = buffer.find('\n', line_start)) != -1) + size_t line_start = 0, line_end; + while((line_end = buffer.find('\n', line_start)) != string::npos) { OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str()); line_start = line_end + 1; @@ -311,7 +287,7 @@ string vstrprintf(const char *format, va_list ap) char* p = buffer; int limit = sizeof(buffer); int ret; - while (true) + for ( ; ; ) { #ifndef _MSC_VER va_list arg_ptr; @@ -330,9 +306,9 @@ string vstrprintf(const char *format, va_list ap) if (p != buffer) delete[] p; limit *= 2; - p = new char[limit]; + p = new(nothrow) char[limit]; if (p == NULL) - throw std::bad_alloc(); + throw bad_alloc(); } string str(p, p+ret); if (p != buffer) @@ -349,7 +325,7 @@ string real_strprintf(const char *format, int dummy, ...) return str; } -string real_strprintf(const std::string &format, int dummy, ...) +string real_strprintf(const string &format, int dummy, ...) { va_list arg_ptr; va_start(arg_ptr, dummy); @@ -362,7 +338,7 @@ bool error(const char *format, ...) { va_list arg_ptr; va_start(arg_ptr, format); - std::string str = vstrprintf(format, arg_ptr); + string str = vstrprintf(format, arg_ptr); va_end(arg_ptr); printf("ERROR: %s\n", str.c_str()); return false; @@ -375,7 +351,7 @@ void ParseString(const string& str, char c, vector& v) return; string::size_type i1 = 0; string::size_type i2; - while (true) + for ( ; ; ) { i2 = str.find(c, i1); if (i2 == str.npos) @@ -388,7 +364,6 @@ void ParseString(const string& str, char c, vector& v) } } - string FormatMoney(int64_t n, bool fPlus) { // Note: not using straight sprintf here because we do NOT want @@ -399,20 +374,19 @@ string FormatMoney(int64_t n, bool fPlus) string str = strprintf("%" PRId64 ".%06" PRId64, quotient, remainder); // Right-trim excess zeros before the decimal point: - int nTrim = 0; - for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i) + size_t nTrim = 0; + for (size_t i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i) ++nTrim; if (nTrim) str.erase(str.size()-nTrim, nTrim); if (n < 0) - str.insert((unsigned int)0, 1, '-'); + str.insert(0u, 1, '-'); else if (fPlus && n > 0) - str.insert((unsigned int)0, 1, '+'); + str.insert(0u, 1, '+'); return str; } - bool ParseMoney(const string& str, int64_t& nRet) { return ParseMoney(str.c_str(), nRet); @@ -451,35 +425,36 @@ bool ParseMoney(const char* pszIn, int64_t& nRet) return false; if (nUnits < 0 || nUnits > COIN) return false; - int64_t nWhole = atoi64(strWhole); + int64_t nWhole = strtoll(strWhole); int64_t nValue = nWhole*COIN + nUnits; nRet = nValue; return true; } - -static const signed char phexdigit[256] = -{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, - -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; +static const int8_t phexdigit[256] = +{ + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; bool IsHex(const string& str) { - BOOST_FOREACH(unsigned char c, str) + for(unsigned char c : str) { if (phexdigit[c] < 0) return false; @@ -491,16 +466,16 @@ vector ParseHex(const char* psz) { // convert hex dump to vector vector vch; - while (true) + for ( ; ; ) { while (isspace(*psz)) psz++; - signed char c = phexdigit[(unsigned char)*psz++]; + auto c = phexdigit[(unsigned char)*psz++]; if (c == (signed char)-1) break; - unsigned char n = (c << 4); - c = phexdigit[(unsigned char)*psz++]; - if (c == (signed char)-1) + auto n = (c << 4); + c = phexdigit[(uint8_t)*psz++]; + if (c == (int8_t)-1) break; n |= c; vch.push_back(n); @@ -508,17 +483,12 @@ vector ParseHex(const char* psz) return vch; } -vector ParseHex(const string& str) -{ - return ParseHex(str.c_str()); -} - static void InterpretNegativeSetting(string name, map& mapSettingsRet) { // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set if (name.find("-no") == 0) { - std::string positive("-"); + string positive("-"); positive.append(name.begin()+3, name.end()); if (mapSettingsRet.count(positive) == 0) { @@ -534,35 +504,35 @@ void ParseParameters(int argc, const char* const argv[]) mapMultiArgs.clear(); for (int i = 1; i < argc; i++) { - char psz[10000]; - strlcpy(psz, argv[i], sizeof(psz)); - char* pszValue = (char*)""; - if (strchr(psz, '=')) + string str(argv[i]); + string strValue; + size_t is_index = str.find('='); + if (is_index != string::npos) { - pszValue = strchr(psz, '='); - *pszValue++ = '\0'; + strValue = str.substr(is_index+1); + str = str.substr(0, is_index); } - #ifdef WIN32 - _strlwr(psz); - if (psz[0] == '/') - psz[0] = '-'; - #endif - if (psz[0] != '-') +#ifdef WIN32 + transform(str.begin(), str.end(), str.begin(), ::tolower); + if (str.compare(0,1, "/") == 0) + str = "-" + str.substr(1); +#endif + if (str[0] != '-') break; - mapArgs[psz] = pszValue; - mapMultiArgs[psz].push_back(pszValue); + mapArgs[str] = strValue; + mapMultiArgs[str].push_back(strValue); } // New 0.6 features: - BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs) + for(const auto& entry : mapArgs) { string name = entry.first; // interpret --foo as -foo (as long as both are not set) if (name.find("--") == 0) { - std::string singleDash(name.begin()+1, name.end()); + string singleDash(name.begin()+1, name.end()); if (mapArgs.count(singleDash) == 0) mapArgs[singleDash] = entry.second; name = singleDash; @@ -573,21 +543,35 @@ void ParseParameters(int argc, const char* const argv[]) } } -std::string GetArg(const std::string& strArg, const std::string& strDefault) +string GetArg(const string& strArg, const string& strDefault) { if (mapArgs.count(strArg)) return mapArgs[strArg]; return strDefault; } -int64_t GetArg(const std::string& strArg, int64_t nDefault) +int64_t GetArg(const string& strArg, int64_t nDefault) { if (mapArgs.count(strArg)) - return atoi64(mapArgs[strArg]); + return strtoll(mapArgs[strArg]); return nDefault; } -bool GetBoolArg(const std::string& strArg, bool fDefault) +int32_t GetArgInt(const string& strArg, int32_t nDefault) +{ + if (mapArgs.count(strArg)) + return strtol(mapArgs[strArg]); + return nDefault; +} + +uint32_t GetArgUInt(const string& strArg, uint32_t nDefault) +{ + if (mapArgs.count(strArg)) + return strtoul(mapArgs[strArg]); + return nDefault; +} + +bool GetBoolArg(const string& strArg, bool fDefault) { if (mapArgs.count(strArg)) { @@ -598,7 +582,7 @@ bool GetBoolArg(const std::string& strArg, bool fDefault) return fDefault; } -bool SoftSetArg(const std::string& strArg, const std::string& strValue) +bool SoftSetArg(const string& strArg, const string& strValue) { if (mapArgs.count(strArg) || mapMultiArgs.count(strArg)) return false; @@ -608,12 +592,12 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue) return true; } -bool SoftSetBoolArg(const std::string& strArg, bool fValue) +bool SoftSetBoolArg(const string& strArg, bool fValue) { if (fValue) - return SoftSetArg(strArg, std::string("1")); + return SoftSetArg(strArg, string("1")); else - return SoftSetArg(strArg, std::string("0")); + return SoftSetArg(strArg, string("0")); } @@ -696,7 +680,7 @@ vector DecodeBase64(const char* p, bool* pfInvalid) int mode = 0; int left = 0; - while (1) + for ( ; ; ) { int dec = decode64_table[(unsigned char)*p]; if (dec == -1) break; @@ -849,7 +833,7 @@ vector DecodeBase32(const char* p, bool* pfInvalid) int mode = 0; int left = 0; - while (1) + for ( ; ; ) { int dec = decode32_table[(unsigned char)*p]; if (dec == -1) break; @@ -945,13 +929,13 @@ string DecodeBase32(const string& str) } -int64_t DecodeDumpTime(const std::string& s) +int64_t DecodeDumpTime(const string& s) { bt::ptime pt; for(size_t i=0; i> pt; if(pt != bt::ptime()) break; @@ -960,13 +944,13 @@ int64_t DecodeDumpTime(const std::string& s) return pt_to_time_t(pt); } -std::string EncodeDumpTime(int64_t nTime) { +string EncodeDumpTime(int64_t nTime) { return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime); } -std::string EncodeDumpString(const std::string &str) { - std::stringstream ret; - BOOST_FOREACH(unsigned char c, str) { +string EncodeDumpString(const string &str) { + stringstream ret; + for(unsigned char c : str) { if (c <= 32 || c >= 128 || c == '%') { ret << '%' << HexStr(&c, &c + 1); } else { @@ -976,8 +960,8 @@ std::string EncodeDumpString(const std::string &str) { return ret.str(); } -std::string DecodeDumpString(const std::string &str) { - std::stringstream ret; +string DecodeDumpString(const string &str) { + stringstream ret; for (unsigned int pos = 0; pos < str.length(); pos++) { unsigned char c = str[pos]; if (c == '%' && pos+2 < str.length()) { @@ -992,7 +976,7 @@ std::string DecodeDumpString(const std::string &str) { bool WildcardMatch(const char* psz, const char* mask) { - while (true) + for ( ; ; ) { switch (*mask) { @@ -1020,13 +1004,7 @@ bool WildcardMatch(const string& str, const string& mask) } - - - - - - -static std::string FormatException(std::exception* pex, const char* pszThread) +static string FormatException(exception* pex, const char* pszThread) { #ifdef WIN32 char pszModule[MAX_PATH] = ""; @@ -1042,15 +1020,15 @@ static std::string FormatException(std::exception* pex, const char* pszThread) "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread); } -void LogException(std::exception* pex, const char* pszThread) +void LogException(exception* pex, const char* pszThread) { - std::string message = FormatException(pex, pszThread); + string message = FormatException(pex, pszThread); printf("\n%s", message.c_str()); } -void PrintException(std::exception* pex, const char* pszThread) +void PrintException(exception* pex, const char* pszThread) { - std::string message = FormatException(pex, pszThread); + string message = FormatException(pex, pszThread); printf("\n\n************************\n%s\n", message.c_str()); fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); strMiscWarning = message; @@ -1070,9 +1048,9 @@ void LogStackTrace() { } } -void PrintExceptionContinue(std::exception* pex, const char* pszThread) +void PrintExceptionContinue(exception* pex, const char* pszThread) { - std::string message = FormatException(pex, pszThread); + string message = FormatException(pex, pszThread); printf("\n\n************************\n%s\n", message.c_str()); fprintf(stderr, "\n\n************************\n%s\n", message.c_str()); strMiscWarning = message; @@ -1142,6 +1120,36 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific) return path; } +string randomStrGen(size_t length) { + std::mt19937 mtrand; + mtrand.seed(static_cast(time(NULL))); + static const string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + string result; + result.resize(length); + for (size_t i = 0; i < length; ++i) + result[i] = charset[mtrand() % charset.length()]; + return result; +} + +void createConf() +{ + ofstream pConf; +#if BOOST_FILESYSTEM_VERSION >= 3 + pConf.open(GetConfigFile().generic_string().c_str()); +#else + pConf.open(GetConfigFile().string().c_str()); +#endif + pConf << "rpcuser=user\nrpcpassword=" + + randomStrGen(15) + + "\nrpcport=8344" + + "\n#(0=off, 1=on) daemon - run in the background as a daemon and accept commands" + + "\ndaemon=0" + + "\n#(0=off, 1=on) server - accept command line and JSON-RPC commands" + + "\nserver=0" + + "\nrpcallowip=127.0.0.1"; + pConf.close(); +} + boost::filesystem::path GetConfigFile() { boost::filesystem::path pathConfigFile(GetArg("-conf", "novacoin.conf")); @@ -1154,7 +1162,12 @@ void ReadConfigFile(map& mapSettingsRet, { boost::filesystem::ifstream streamConfig(GetConfigFile()); if (!streamConfig.good()) - return; // No bitcoin.conf file is OK + { + createConf(); + new(&streamConfig) boost::filesystem::ifstream(GetConfigFile()); + if(!streamConfig.good()) + return; + } set setOptions; setOptions.insert("*"); @@ -1196,9 +1209,9 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest) { #ifdef WIN32 return MoveFileExA(src.string().c_str(), dest.string().c_str(), - MOVEFILE_REPLACE_EXISTING); + MOVEFILE_REPLACE_EXISTING) != 0; #else - int rc = std::rename(src.string().c_str(), dest.string().c_str()); + int rc = rename(src.string().c_str(), dest.string().c_str()); return (rc == 0); #endif /* WIN32 */ } @@ -1231,27 +1244,28 @@ void ShrinkDebugFile() if (file && GetFilesize(file) > 10 * 1000000) { // Restart the file with some of the end - char pch[200000]; - fseek(file, -sizeof(pch), SEEK_END); - int nBytes = fread(pch, 1, sizeof(pch), file); - fclose(file); - - file = fopen(pathLog.string().c_str(), "w"); - if (file) - { - fwrite(pch, 1, nBytes, file); + try { + vector* vBuf = new vector (200000, 0); + size_t nBytes = 1; //write one byte if fseek failed + if (fseek(file, -((long)(vBuf->size())), SEEK_END) == 0) + nBytes = fread(&vBuf->operator[](0), 1, vBuf->size(), file); + fclose(file); + file = fopen(pathLog.string().c_str(), "w"); + if (file) + { + fwrite(&vBuf->operator[](0), 1, nBytes, file); + fclose(file); + } + delete vBuf; + } + catch (const bad_alloc& e) { + // Bad things happen - no free memory in heap at program startup fclose(file); + printf("Warning: %s in %s:%d\n ShrinkDebugFile failed - debug.log expands further", e.what(), __FILE__, __LINE__); } } } - - - - - - - // // "Never go to sea with two chronometers; take one or three." // Our three time sources are: @@ -1259,25 +1273,38 @@ void ShrinkDebugFile() // - Median of other nodes clocks // - The user (asking the user to fix the system clock if the first two disagree) // -static int64_t nMockTime = 0; // For unit testing +// System clock int64_t GetTime() { - if (nMockTime) return nMockTime; - - return time(NULL); + int64_t now = time(NULL); + assert(now > 0); + return now; } -void SetMockTime(int64_t nMockTimeIn) -{ - nMockTime = nMockTimeIn; -} +// Trusted NTP offset or median of NTP samples. +extern int64_t nNtpOffset; -static int64_t nTimeOffset = 0; +// Median of time samples given by other nodes. +static int64_t nNodesOffset = numeric_limits::max(); +// Select time offset: int64_t GetTimeOffset() { - return nTimeOffset; + // If NTP and system clock are in agreement within 40 minutes, then use NTP. + if (abs(nNtpOffset) < 40 * 60) + return nNtpOffset; + + // If not, then choose between median peer time and system clock. + if (abs(nNodesOffset) < 70 * 60) + return nNodesOffset; + + return 0; +} + +int64_t GetNodesOffset() +{ + return nNodesOffset; } int64_t GetAdjustedTime() @@ -1299,24 +1326,25 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime) printf("Added time data, samples %d, offset %+" PRId64 " (%+" PRId64 " minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60); if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1) { - int64_t nMedian = vTimeOffsets.median(); - std::vector vSorted = vTimeOffsets.sorted(); + auto nMedian = vTimeOffsets.median(); + auto vSorted = vTimeOffsets.sorted(); // Only let other nodes change our time by so much - if (abs64(nMedian) < 70 * 60) + if (abs(nMedian) < 70 * 60) { - nTimeOffset = nMedian; + nNodesOffset = nMedian; } else { - nTimeOffset = 0; + nNodesOffset = numeric_limits::max(); static bool fDone; if (!fDone) { - // If nobody has a time different than ours but within 5 minutes of ours, give a warning bool fMatch = false; - BOOST_FOREACH(int64_t nOffset, vSorted) - if (nOffset != 0 && abs64(nOffset) < 5 * 60) + + // If nobody has a time different than ours but within 5 minutes of ours, give a warning + for(auto nOffset : vSorted) + if (nOffset != 0 && abs(nOffset) < 5 * 60) fMatch = true; if (!fMatch) @@ -1330,21 +1358,15 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime) } } if (fDebug) { - BOOST_FOREACH(int64_t n, vSorted) + for(int64_t n : vSorted) printf("%+" PRId64 " ", n); printf("| "); } - printf("nTimeOffset = %+" PRId64 " (%+" PRId64 " minutes)\n", nTimeOffset, nTimeOffset/60); + if (nNodesOffset != numeric_limits::max()) + printf("nNodesOffset = %+" PRId64 " (%+" PRId64 " minutes)\n", nNodesOffset, nNodesOffset/60); } } - - - - - - - string FormatVersion(int nVersion) { if (nVersion%100 == 0) @@ -1359,9 +1381,9 @@ string FormatFullVersion() } // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014) -std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector& comments) +string FormatSubVersion(const string& name, int nClientVersion, const vector& comments) { - std::ostringstream ss; + ostringstream ss; ss << "/"; ss << name << ":" << FormatVersion(nClientVersion); if (!comments.empty()) @@ -1387,7 +1409,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) } #endif -void runCommand(std::string strCommand) +void runCommand(string strCommand) { int nErr = ::system(strCommand.c_str()); if (nErr) @@ -1426,3 +1448,13 @@ bool NewThread(void(*pfn)(void*), void* parg) } return true; } + +string DateTimeStrFormat(const char* pszFormat, int64_t nTime) +{ + // locale takes ownership of the pointer + locale loc(locale::classic(), new boost::posix_time::time_facet(pszFormat)); + stringstream ss; + ss.imbue(loc); + ss << boost::posix_time::from_time_t(nTime); + return ss.str(); +}