X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Futil.cpp;h=18d0ce862df8e6b75556d5dbfe0b1909faf761aa;hb=09f2a990950512cbe418526d91838887a0dded2a;hp=24c7ed4487fd40e835fa93db730610d394c9a070;hpb=865ed8a1e5c587468a40756d46bcbc1c5a12bb06;p=novacoin.git diff --git a/src/util.cpp b/src/util.cpp index 24c7ed4..18d0ce8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2011-2012 The PPCoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. #include "headers.h" @@ -12,6 +13,10 @@ #include #include +#ifndef WIN32 +#include +#endif + using namespace std; using namespace boost; @@ -64,7 +69,7 @@ public: ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex(); CRYPTO_set_locking_callback(locking_callback); -#ifdef __WXMSW__ +#ifdef WIN32 // Seed random number generator with screen scrape and other hardware sources RAND_screen(); #endif @@ -108,7 +113,7 @@ void RandAddSeedPerfmon() return; nLastPerfmon = GetTime(); -#ifdef __WXMSW__ +#ifdef WIN32 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom // Seed with the entire set of perfmon data unsigned char pdata[250000]; @@ -153,7 +158,7 @@ int GetRandInt(int nMax) - +static FILE* fileout = NULL; inline int OutputDebugStringF(const char* pszFormat, ...) { @@ -169,8 +174,6 @@ inline int OutputDebugStringF(const char* pszFormat, ...) else { // print to debug.log - static FILE* fileout = NULL; - if (!fileout) { char pszFile[MAX_PATH+100]; @@ -198,7 +201,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...) } } -#ifdef __WXMSW__ +#ifdef WIN32 if (fPrintToDebugger) { static CCriticalSection cs_OutputDebugStringF; @@ -264,8 +267,7 @@ int my_snprintf(char* buffer, size_t limit, const char* format, ...) return ret; } - -string strprintf(const char* format, ...) +string strprintf(const std::string &format, ...) { char buffer[50000]; char* p = buffer; @@ -275,7 +277,7 @@ string strprintf(const char* format, ...) { va_list arg_ptr; va_start(arg_ptr, format); - ret = _vsnprintf(p, limit, format, arg_ptr); + ret = _vsnprintf(p, limit, format.c_str(), arg_ptr); va_end(arg_ptr); if (ret >= 0 && ret < limit) break; @@ -292,14 +294,13 @@ string strprintf(const char* format, ...) return str; } - -bool error(const char* format, ...) +bool error(const std::string &format, ...) { char buffer[50000]; int limit = sizeof(buffer); va_list arg_ptr; va_start(arg_ptr, format); - int ret = _vsnprintf(buffer, limit, format, arg_ptr); + int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr); va_end(arg_ptr); if (ret < 0 || ret >= limit) { @@ -338,7 +339,7 @@ string FormatMoney(int64 n, bool fPlus) int64 n_abs = (n > 0 ? n : -n); int64 quotient = n_abs/COIN; int64 remainder = n_abs%COIN; - string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder); + string str = strprintf("%"PRI64d".%06"PRI64d, quotient, remainder); // Right-trim excess 0's before the decimal point: int nTrim = 0; @@ -389,7 +390,7 @@ bool ParseMoney(const char* pszIn, int64& nRet) for (; *p; p++) if (!isspace(*p)) return false; - if (strWhole.size() > 14) + if (strWhole.size() > 10) // guard against 63 bit overflow return false; if (nUnits < 0 || nUnits > COIN) return false; @@ -445,7 +446,6 @@ vector ParseHex(const string& str) return ParseHex(str.c_str()); } - void ParseParameters(int argc, char* argv[]) { mapArgs.clear(); @@ -460,7 +460,7 @@ void ParseParameters(int argc, char* argv[]) pszValue = strchr(psz, '='); *pszValue++ = '\0'; } - #ifdef __WXMSW__ + #ifdef WIN32 _strlwr(psz); if (psz[0] == '/') psz[0] = '-'; @@ -472,39 +472,144 @@ void ParseParameters(int argc, char* argv[]) } } +string EncodeBase64(const unsigned char* pch, size_t len) +{ + static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + string strRet=""; + strRet.reserve((len+2)/3*4); + + int mode=0, left=0; + const unsigned char *pchEnd = pch+len; + + while (pch> 2]; + left = (enc & 3) << 4; + mode = 1; + break; + + case 1: // we have two bits + strRet += pbase64[left | (enc >> 4)]; + left = (enc & 15) << 2; + mode = 2; + break; + + case 2: // we have four bits + strRet += pbase64[left | (enc >> 6)]; + strRet += pbase64[enc & 63]; + mode = 0; + break; + } + } -const char* wxGetTranslation(const char* pszEnglish) + if (mode) + { + strRet += pbase64[left]; + strRet += '='; + if (mode == 1) + strRet += '='; + } + + return strRet; +} + +string EncodeBase64(const string& str) +{ + return EncodeBase64((const unsigned char*)str.c_str(), str.size()); +} + +vector DecodeBase64(const char* p, bool* pfInvalid) { -#ifdef GUI - // Wrapper of wxGetTranslation returning the same const char* type as was passed in - static CCriticalSection cs; - CRITICAL_BLOCK(cs) + static const int decode64_table[256] = { - // Look in cache - static map mapCache; - map::iterator mi = mapCache.find(pszEnglish); - if (mi != mapCache.end()) - return (*mi).second; - - // wxWidgets translation - wxString strTranslated = wxGetTranslation(wxString(pszEnglish, wxConvUTF8)); - - // We don't cache unknown strings because caller might be passing in a - // dynamic string and we would keep allocating memory for each variation. - if (strcmp(pszEnglish, strTranslated.utf8_str()) == 0) - return pszEnglish; - - // Add to cache, memory doesn't need to be freed. We only cache because - // we must pass back a pointer to permanently allocated memory. - char* pszCached = new char[strlen(strTranslated.utf8_str())+1]; - strcpy(pszCached, strTranslated.utf8_str()); - mapCache[pszEnglish] = pszCached; - return pszCached; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, + -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; + + if (pfInvalid) + *pfInvalid = false; + + vector vchRet; + vchRet.reserve(strlen(p)*3/4); + + int mode = 0; + int left = 0; + + while (1) + { + int dec = decode64_table[*p]; + if (dec == -1) break; + p++; + switch (mode) + { + case 0: // we have no bits and get 6 + left = dec; + mode = 1; + break; + + case 1: // we have 6 bits and keep 4 + vchRet.push_back((left<<2) | (dec>>4)); + left = dec & 15; + mode = 2; + break; + + case 2: // we have 4 bits and get 6, we keep 2 + vchRet.push_back((left<<4) | (dec>>2)); + left = dec & 3; + mode = 3; + break; + + case 3: // we have 2 bits and get 6 + vchRet.push_back((left<<6) | dec); + mode = 0; + break; + } } - return NULL; -#else - return pszEnglish; -#endif + + if (pfInvalid) + switch (mode) + { + case 0: // 4n base64 characters processed: ok + break; + + case 1: // 4n+1 base64 character processed: impossible + *pfInvalid = true; + break; + + case 2: // 4n+2 base64 characters processed: require '==' + if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1) + *pfInvalid = true; + break; + + case 3: // 4n+3 base64 characters processed: require '=' + if (left || p[0] != '=' || decode64_table[p[1]] != -1) + *pfInvalid = true; + break; + } + + return vchRet; +} + +string DecodeBase64(const string& str) +{ + vector vchRet = DecodeBase64(str.c_str()); + return string((const char*)&vchRet[0], vchRet.size()); } @@ -546,7 +651,7 @@ bool WildcardMatch(const string& str, const string& mask) void FormatException(char* pszMessage, std::exception* pex, const char* pszThread) { -#ifdef __WXMSW__ +#ifdef WIN32 char pszModule[MAX_PATH]; pszModule[0] = '\0'; GetModuleFileNameA(NULL, pszModule, sizeof(pszModule)); @@ -575,13 +680,22 @@ void PrintException(std::exception* pex, const char* pszThread) printf("\n\n************************\n%s\n", pszMessage); fprintf(stderr, "\n\n************************\n%s\n", pszMessage); strMiscWarning = pszMessage; -#ifdef GUI - if (wxTheApp && !fDaemon) - MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR); -#endif throw; } +void LogStackTrace() { + printf("\n\n******* exception encountered *******\n"); + if (fileout) + { +#ifndef WIN32 + void* pszBuffer[32]; + size_t size; + size = backtrace(pszBuffer, 32); + backtrace_symbols_fd(pszBuffer, size, fileno(fileout)); +#endif + } +} + void ThreadOneMessageBox(string strMessage) { // Skip message boxes if one is already open @@ -600,10 +714,6 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) printf("\n\n************************\n%s\n", pszMessage); fprintf(stderr, "\n\n************************\n%s\n", pszMessage); strMiscWarning = pszMessage; -#ifdef GUI - if (wxTheApp && !fDaemon) - boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage))); -#endif } @@ -613,7 +723,7 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread) -#ifdef __WXMSW__ +#ifdef WIN32 typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate); string MyGetSpecialFolderPath(int nFolder, bool fCreate) @@ -651,12 +761,12 @@ string MyGetSpecialFolderPath(int nFolder, bool fCreate) string GetDefaultDataDir() { - // Windows: C:\Documents and Settings\username\Application Data\Bitcoin - // Mac: ~/Library/Application Support/Bitcoin - // Unix: ~/.bitcoin -#ifdef __WXMSW__ + // Windows: C:\Documents and Settings\username\Application Data\PPCoin + // Mac: ~/Library/Application Support/PPCoin + // Unix: ~/.ppcoin +#ifdef WIN32 // Windows - return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin"; + return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\PPCoin"; #else char* pszHome = getenv("HOME"); if (pszHome == NULL || strlen(pszHome) == 0) @@ -664,14 +774,14 @@ string GetDefaultDataDir() string strHome = pszHome; if (strHome[strHome.size()-1] != '/') strHome += '/'; -#ifdef __WXMAC_OSX__ +#ifdef MAC_OSX // Mac strHome += "Library/Application Support/"; filesystem::create_directory(strHome.c_str()); - return strHome + "Bitcoin"; + return strHome + "PPCoin"; #else // Unix - return strHome + ".bitcoin"; + return strHome + ".ppcoin"; #endif #endif } @@ -721,7 +831,7 @@ string GetDataDir() string GetConfigFile() { namespace fs = boost::filesystem; - fs::path pathConfig(GetArg("-conf", "bitcoin.conf")); + fs::path pathConfig(GetArg("-conf", "ppcoin.conf")); if (!pathConfig.is_complete()) pathConfig = fs::path(GetDataDir()) / pathConfig; return pathConfig.string(); @@ -753,7 +863,7 @@ void ReadConfigFile(map& mapSettingsRet, string GetPidFile() { namespace fs = boost::filesystem; - fs::path pathConfig(GetArg("-pid", "bitcoind.pid")); + fs::path pathConfig(GetArg("-pid", "ppcoind.pid")); if (!pathConfig.is_complete()) pathConfig = fs::path(GetDataDir()) / pathConfig; return pathConfig.string(); @@ -815,11 +925,20 @@ void ShrinkDebugFile() // - Median of other nodes's clocks // - The user (asking the user to fix the system clock if the first two disagree) // +static int64 nMockTime = 0; // For unit testing + int64 GetTime() { + if (nMockTime) return nMockTime; + return time(NULL); } +void SetMockTime(int64 nMockTimeIn) +{ + nMockTime = nMockTimeIn; +} + static int64 nTimeOffset = 0; int64 GetAdjustedTime() @@ -898,7 +1017,7 @@ string FormatVersion(int nVersion) string FormatFullVersion() { - string s = FormatVersion(VERSION) + pszSubVer; + string s = FormatVersion(PPCOIN_VERSION) + pszSubVer; if (VERSION_IS_BETA) { s += "-"; s += _("beta"); @@ -923,16 +1042,22 @@ string FormatFullVersion() struct CLockLocation { - std::string mutexName; - std::string sourceFile; - int sourceLine; - CLockLocation(const char* pszName, const char* pszFile, int nLine) { mutexName = pszName; sourceFile = pszFile; sourceLine = nLine; } + + std::string ToString() const + { + return mutexName+" "+sourceFile+":"+itostr(sourceLine); + } + +private: + std::string mutexName; + std::string sourceFile; + int sourceLine; }; typedef std::vector< std::pair > LockStack; @@ -942,18 +1067,22 @@ static std::map, LockStack> lock static boost::thread_specific_ptr lockstack; -static void potential_deadlock_detected(const LockStack& s1, const LockStack& s2) +static void potential_deadlock_detected(const std::pair& mismatch, const LockStack& s1, const LockStack& s2) { printf("POTENTIAL DEADLOCK DETECTED\n"); printf("Previous lock order was:\n"); BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2) { - printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine); + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); } printf("Current lock order is:\n"); BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1) { - printf(" %s %s:%d\n", i.second.mutexName.c_str(), i.second.sourceFile.c_str(), i.second.sourceLine); + if (i.first == mismatch.first) printf(" (1)"); + if (i.first == mismatch.second) printf(" (2)"); + printf(" %s\n", i.second.ToString().c_str()); } } @@ -963,6 +1092,7 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) if (lockstack.get() == NULL) lockstack.reset(new LockStack); + if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str()); dd_mutex.lock(); (*lockstack).push_back(std::make_pair(c, locklocation)); @@ -979,7 +1109,7 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) std::pair p2 = std::make_pair(c, i.first); if (lockorders.count(p2)) { - potential_deadlock_detected(lockorders[p2], lockorders[p1]); + potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]); break; } } @@ -988,7 +1118,14 @@ static void push_lock(CCriticalSection* c, const CLockLocation& locklocation) static void pop_lock() { + if (fDebug) + { + const CLockLocation& locklocation = (*lockstack).rbegin()->second; + printf("Unlocked: %s\n", locklocation.ToString().c_str()); + } + dd_mutex.lock(); (*lockstack).pop_back(); + dd_mutex.unlock(); } void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)