-
+ 4B0F7B3A7757336B6E5C349D89170BFC4B4C40A04E0EC3FCCF0B155314689C781DEB9590AB05DAA8AF20A123E2F3CAD55C5AF1244700197A3530D0D4699D32C5
bitcoin/src/util.cpp
(0 . 0)(1 . 1177)
22664 // Copyright (c) 2009-2010 Satoshi Nakamoto
22665 // Copyright (c) 2009-2012 The Bitcoin developers
22666 // Distributed under the MIT/X11 software license, see the accompanying
22667 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
22668 #include "headers.h"
22669 #include "strlcpy.h"
22670 #include <boost/program_options/detail/config_file.hpp>
22671 #include <boost/program_options/parsers.hpp>
22672 #include <boost/filesystem.hpp>
22673 #include <boost/filesystem/fstream.hpp>
22674 #include <boost/interprocess/sync/interprocess_mutex.hpp>
22675 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
22676 #include <boost/foreach.hpp>
22677
22678 using namespace std;
22679 using namespace boost;
22680
22681 map<string, string> mapArgs;
22682 map<string, vector<string> > mapMultiArgs;
22683 bool fDebug = false;
22684 bool fPrintToConsole = false;
22685 bool fPrintToDebugger = false;
22686 char pszSetDataDir[MAX_PATH] = "";
22687 bool fRequestShutdown = false;
22688 bool fShutdown = false;
22689 bool fDaemon = false;
22690 bool fServer = false;
22691 bool fCommandLine = false;
22692 string strMiscWarning;
22693 bool fTestNet = false;
22694 bool fNoListen = false;
22695 bool fLogTimestamps = false;
22696
22697
22698
22699
22700 // Workaround for "multiple definition of `_tls_used'"
22701 // http://svn.boost.org/trac/boost/ticket/4258
22702 extern "C" void tss_cleanup_implemented() { }
22703
22704
22705
22706
22707
22708 // Init openssl library multithreading support
22709 static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
22710 void locking_callback(int mode, int i, const char* file, int line)
22711 {
22712 if (mode & CRYPTO_LOCK)
22713 ppmutexOpenSSL[i]->lock();
22714 else
22715 ppmutexOpenSSL[i]->unlock();
22716 }
22717
22718 // Init
22719 class CInit
22720 {
22721 public:
22722 CInit()
22723 {
22724 // Init openssl library multithreading support
22725 ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
22726 for (int i = 0; i < CRYPTO_num_locks(); i++)
22727 ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
22728 CRYPTO_set_locking_callback(locking_callback);
22729
22730 #ifdef WIN32
22731 // Seed random number generator with screen scrape and other hardware sources
22732 RAND_screen();
22733 #endif
22734
22735 // Seed random number generator with performance counter
22736 RandAddSeed();
22737 }
22738 ~CInit()
22739 {
22740 // Shutdown openssl library multithreading support
22741 CRYPTO_set_locking_callback(NULL);
22742 for (int i = 0; i < CRYPTO_num_locks(); i++)
22743 delete ppmutexOpenSSL[i];
22744 OPENSSL_free(ppmutexOpenSSL);
22745 }
22746 }
22747 instance_of_cinit;
22748
22749
22750
22751
22752
22753
22754
22755
22756 void RandAddSeed()
22757 {
22758 // Seed with CPU performance counter
22759 int64 nCounter = GetPerformanceCounter();
22760 RAND_add(&nCounter, sizeof(nCounter), 1.5);
22761 memset(&nCounter, 0, sizeof(nCounter));
22762 }
22763
22764 void RandAddSeedPerfmon()
22765 {
22766 RandAddSeed();
22767
22768 // This can take up to 2 seconds, so only do it every 10 minutes
22769 static int64 nLastPerfmon;
22770 if (GetTime() < nLastPerfmon + 10 * 60)
22771 return;
22772 nLastPerfmon = GetTime();
22773
22774 #ifdef WIN32
22775 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
22776 // Seed with the entire set of perfmon data
22777 unsigned char pdata[250000];
22778 memset(pdata, 0, sizeof(pdata));
22779 unsigned long nSize = sizeof(pdata);
22780 long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
22781 RegCloseKey(HKEY_PERFORMANCE_DATA);
22782 if (ret == ERROR_SUCCESS)
22783 {
22784 RAND_add(pdata, nSize, nSize/100.0);
22785 memset(pdata, 0, nSize);
22786 printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
22787 }
22788 #endif
22789 }
22790
22791 uint64 GetRand(uint64 nMax)
22792 {
22793 if (nMax == 0)
22794 return 0;
22795
22796 // The range of the random source must be a multiple of the modulus
22797 // to give every possible output value an equal possibility
22798 uint64 nRange = (UINT64_MAX / nMax) * nMax;
22799 uint64 nRand = 0;
22800 do
22801 RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
22802 while (nRand >= nRange);
22803 return (nRand % nMax);
22804 }
22805
22806 int GetRandInt(int nMax)
22807 {
22808 return GetRand(nMax);
22809 }
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821 inline int OutputDebugStringF(const char* pszFormat, ...)
22822 {
22823 int ret = 0;
22824 if (fPrintToConsole)
22825 {
22826 // print to console
22827 va_list arg_ptr;
22828 va_start(arg_ptr, pszFormat);
22829 ret = vprintf(pszFormat, arg_ptr);
22830 va_end(arg_ptr);
22831 }
22832 else
22833 {
22834 // print to debug.log
22835 static FILE* fileout = NULL;
22836
22837 if (!fileout)
22838 {
22839 char pszFile[MAX_PATH+100];
22840 GetDataDir(pszFile);
22841 strlcat(pszFile, "/debug.log", sizeof(pszFile));
22842 fileout = fopen(pszFile, "a");
22843 if (fileout) setbuf(fileout, NULL); // unbuffered
22844 }
22845 if (fileout)
22846 {
22847 static bool fStartedNewLine = true;
22848
22849 // Debug print useful for profiling
22850 if (fLogTimestamps && fStartedNewLine)
22851 fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
22852 if (pszFormat[strlen(pszFormat) - 1] == '\n')
22853 fStartedNewLine = true;
22854 else
22855 fStartedNewLine = false;
22856
22857 va_list arg_ptr;
22858 va_start(arg_ptr, pszFormat);
22859 ret = vfprintf(fileout, pszFormat, arg_ptr);
22860 va_end(arg_ptr);
22861 }
22862 }
22863
22864 #ifdef WIN32
22865 if (fPrintToDebugger)
22866 {
22867 static CCriticalSection cs_OutputDebugStringF;
22868
22869 // accumulate a line at a time
22870 CRITICAL_BLOCK(cs_OutputDebugStringF)
22871 {
22872 static char pszBuffer[50000];
22873 static char* pend;
22874 if (pend == NULL)
22875 pend = pszBuffer;
22876 va_list arg_ptr;
22877 va_start(arg_ptr, pszFormat);
22878 int limit = END(pszBuffer) - pend - 2;
22879 int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
22880 va_end(arg_ptr);
22881 if (ret < 0 || ret >= limit)
22882 {
22883 pend = END(pszBuffer) - 2;
22884 *pend++ = '\n';
22885 }
22886 else
22887 pend += ret;
22888 *pend = '\0';
22889 char* p1 = pszBuffer;
22890 char* p2;
22891 while (p2 = strchr(p1, '\n'))
22892 {
22893 p2++;
22894 char c = *p2;
22895 *p2 = '\0';
22896 OutputDebugStringA(p1);
22897 *p2 = c;
22898 p1 = p2;
22899 }
22900 if (p1 != pszBuffer)
22901 memmove(pszBuffer, p1, pend - p1 + 1);
22902 pend -= (p1 - pszBuffer);
22903 }
22904 }
22905 #endif
22906 return ret;
22907 }
22908
22909
22910 // Safer snprintf
22911 // - prints up to limit-1 characters
22912 // - output string is always null terminated even if limit reached
22913 // - return value is the number of characters actually printed
22914 int my_snprintf(char* buffer, size_t limit, const char* format, ...)
22915 {
22916 if (limit == 0)
22917 return 0;
22918 va_list arg_ptr;
22919 va_start(arg_ptr, format);
22920 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
22921 va_end(arg_ptr);
22922 if (ret < 0 || ret >= limit)
22923 {
22924 ret = limit - 1;
22925 buffer[limit-1] = 0;
22926 }
22927 return ret;
22928 }
22929
22930 string strprintf(const std::string &format, ...)
22931 {
22932 char buffer[50000];
22933 char* p = buffer;
22934 int limit = sizeof(buffer);
22935 int ret;
22936 loop
22937 {
22938 va_list arg_ptr;
22939 va_start(arg_ptr, format);
22940 ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
22941 va_end(arg_ptr);
22942 if (ret >= 0 && ret < limit)
22943 break;
22944 if (p != buffer)
22945 delete[] p;
22946 limit *= 2;
22947 p = new char[limit];
22948 if (p == NULL)
22949 throw std::bad_alloc();
22950 }
22951 string str(p, p+ret);
22952 if (p != buffer)
22953 delete[] p;
22954 return str;
22955 }
22956
22957 bool error(const std::string &format, ...)
22958 {
22959 char buffer[50000];
22960 int limit = sizeof(buffer);
22961 va_list arg_ptr;
22962 va_start(arg_ptr, format);
22963 int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
22964 va_end(arg_ptr);
22965 if (ret < 0 || ret >= limit)
22966 {
22967 ret = limit - 1;
22968 buffer[limit-1] = 0;
22969 }
22970 printf("ERROR: %s\n", buffer);
22971 return false;
22972 }
22973
22974
22975 void ParseString(const string& str, char c, vector<string>& v)
22976 {
22977 if (str.empty())
22978 return;
22979 string::size_type i1 = 0;
22980 string::size_type i2;
22981 loop
22982 {
22983 i2 = str.find(c, i1);
22984 if (i2 == str.npos)
22985 {
22986 v.push_back(str.substr(i1));
22987 return;
22988 }
22989 v.push_back(str.substr(i1, i2-i1));
22990 i1 = i2+1;
22991 }
22992 }
22993
22994
22995 string FormatMoney(int64 n, bool fPlus)
22996 {
22997 // Note: not using straight sprintf here because we do NOT want
22998 // localized number formatting.
22999 int64 n_abs = (n > 0 ? n : -n);
23000 int64 quotient = n_abs/COIN;
23001 int64 remainder = n_abs%COIN;
23002 string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder);
23003
23004 // Right-trim excess 0's before the decimal point:
23005 int nTrim = 0;
23006 for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
23007 ++nTrim;
23008 if (nTrim)
23009 str.erase(str.size()-nTrim, nTrim);
23010
23011 if (n < 0)
23012 str.insert((unsigned int)0, 1, '-');
23013 else if (fPlus && n > 0)
23014 str.insert((unsigned int)0, 1, '+');
23015 return str;
23016 }
23017
23018
23019 bool ParseMoney(const string& str, int64& nRet)
23020 {
23021 return ParseMoney(str.c_str(), nRet);
23022 }
23023
23024 bool ParseMoney(const char* pszIn, int64& nRet)
23025 {
23026 string strWhole;
23027 int64 nUnits = 0;
23028 const char* p = pszIn;
23029 while (isspace(*p))
23030 p++;
23031 for (; *p; p++)
23032 {
23033 if (*p == '.')
23034 {
23035 p++;
23036 int64 nMult = CENT*10;
23037 while (isdigit(*p) && (nMult > 0))
23038 {
23039 nUnits += nMult * (*p++ - '0');
23040 nMult /= 10;
23041 }
23042 break;
23043 }
23044 if (isspace(*p))
23045 break;
23046 if (!isdigit(*p))
23047 return false;
23048 strWhole.insert(strWhole.end(), *p);
23049 }
23050 for (; *p; p++)
23051 if (!isspace(*p))
23052 return false;
23053 if (strWhole.size() > 10) // guard against 63 bit overflow
23054 return false;
23055 if (nUnits < 0 || nUnits > COIN)
23056 return false;
23057 int64 nWhole = atoi64(strWhole);
23058 int64 nValue = nWhole*COIN + nUnits;
23059
23060 nRet = nValue;
23061 return true;
23062 }
23063
23064
23065 vector<unsigned char> ParseHex(const char* psz)
23066 {
23067 static char phexdigit[256] =
23068 { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23069 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23070 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23071 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
23072 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23073 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23074 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1
23075 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23076 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23077 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23078 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23079 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23080 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23081 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23082 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
23083 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
23084
23085 // convert hex dump to vector
23086 vector<unsigned char> vch;
23087 loop
23088 {
23089 while (isspace(*psz))
23090 psz++;
23091 char c = phexdigit[(unsigned char)*psz++];
23092 if (c == (char)-1)
23093 break;
23094 unsigned char n = (c << 4);
23095 c = phexdigit[(unsigned char)*psz++];
23096 if (c == (char)-1)
23097 break;
23098 n |= c;
23099 vch.push_back(n);
23100 }
23101 return vch;
23102 }
23103
23104 vector<unsigned char> ParseHex(const string& str)
23105 {
23106 return ParseHex(str.c_str());
23107 }
23108
23109 void ParseParameters(int argc, char* argv[])
23110 {
23111 mapArgs.clear();
23112 mapMultiArgs.clear();
23113 for (int i = 1; i < argc; i++)
23114 {
23115 char psz[10000];
23116 strlcpy(psz, argv[i], sizeof(psz));
23117 char* pszValue = (char*)"";
23118 if (strchr(psz, '='))
23119 {
23120 pszValue = strchr(psz, '=');
23121 *pszValue++ = '\0';
23122 }
23123 #ifdef WIN32
23124 _strlwr(psz);
23125 if (psz[0] == '/')
23126 psz[0] = '-';
23127 #endif
23128 if (psz[0] != '-')
23129 break;
23130 mapArgs[psz] = pszValue;
23131 mapMultiArgs[psz].push_back(pszValue);
23132 }
23133 }
23134
23135 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
23136 {
23137 if (mapArgs.count(strArg))
23138 return false;
23139 mapArgs[strArg] = strValue;
23140 return true;
23141 }
23142
23143 bool SoftSetArg(const std::string& strArg, bool fValue)
23144 {
23145 if (fValue)
23146 return SoftSetArg(strArg, std::string("1"));
23147 else
23148 return SoftSetArg(strArg, std::string("0"));
23149 }
23150
23151
23152 string EncodeBase64(const unsigned char* pch, size_t len)
23153 {
23154 static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
23155
23156 string strRet="";
23157 strRet.reserve((len+2)/3*4);
23158
23159 int mode=0, left=0;
23160 const unsigned char *pchEnd = pch+len;
23161
23162 while (pch<pchEnd)
23163 {
23164 int enc = *(pch++);
23165 switch (mode)
23166 {
23167 case 0: // we have no bits
23168 strRet += pbase64[enc >> 2];
23169 left = (enc & 3) << 4;
23170 mode = 1;
23171 break;
23172
23173 case 1: // we have two bits
23174 strRet += pbase64[left | (enc >> 4)];
23175 left = (enc & 15) << 2;
23176 mode = 2;
23177 break;
23178
23179 case 2: // we have four bits
23180 strRet += pbase64[left | (enc >> 6)];
23181 strRet += pbase64[enc & 63];
23182 mode = 0;
23183 break;
23184 }
23185 }
23186
23187 if (mode)
23188 {
23189 strRet += pbase64[left];
23190 strRet += '=';
23191 if (mode == 1)
23192 strRet += '=';
23193 }
23194
23195 return strRet;
23196 }
23197
23198 string EncodeBase64(const string& str)
23199 {
23200 return EncodeBase64((const unsigned char*)str.c_str(), str.size());
23201 }
23202
23203 vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
23204 {
23205 static const int decode64_table[256] =
23206 {
23207 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23208 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23209 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
23210 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
23211 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
23212 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
23213 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23214 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23215 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23216 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23217 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
23219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
23220 };
23221
23222 if (pfInvalid)
23223 *pfInvalid = false;
23224
23225 vector<unsigned char> vchRet;
23226 vchRet.reserve(strlen(p)*3/4);
23227
23228 int mode = 0;
23229 int left = 0;
23230
23231 while (1)
23232 {
23233 int dec = decode64_table[*p];
23234 if (dec == -1) break;
23235 p++;
23236 switch (mode)
23237 {
23238 case 0: // we have no bits and get 6
23239 left = dec;
23240 mode = 1;
23241 break;
23242
23243 case 1: // we have 6 bits and keep 4
23244 vchRet.push_back((left<<2) | (dec>>4));
23245 left = dec & 15;
23246 mode = 2;
23247 break;
23248
23249 case 2: // we have 4 bits and get 6, we keep 2
23250 vchRet.push_back((left<<4) | (dec>>2));
23251 left = dec & 3;
23252 mode = 3;
23253 break;
23254
23255 case 3: // we have 2 bits and get 6
23256 vchRet.push_back((left<<6) | dec);
23257 mode = 0;
23258 break;
23259 }
23260 }
23261
23262 if (pfInvalid)
23263 switch (mode)
23264 {
23265 case 0: // 4n base64 characters processed: ok
23266 break;
23267
23268 case 1: // 4n+1 base64 character processed: impossible
23269 *pfInvalid = true;
23270 break;
23271
23272 case 2: // 4n+2 base64 characters processed: require '=='
23273 if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1)
23274 *pfInvalid = true;
23275 break;
23276
23277 case 3: // 4n+3 base64 characters processed: require '='
23278 if (left || p[0] != '=' || decode64_table[p[1]] != -1)
23279 *pfInvalid = true;
23280 break;
23281 }
23282
23283 return vchRet;
23284 }
23285
23286 string DecodeBase64(const string& str)
23287 {
23288 vector<unsigned char> vchRet = DecodeBase64(str.c_str());
23289 return string((const char*)&vchRet[0], vchRet.size());
23290 }
23291
23292
23293 bool WildcardMatch(const char* psz, const char* mask)
23294 {
23295 loop
23296 {
23297 switch (*mask)
23298 {
23299 case '\0':
23300 return (*psz == '\0');
23301 case '*':
23302 return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
23303 case '?':
23304 if (*psz == '\0')
23305 return false;
23306 break;
23307 default:
23308 if (*psz != *mask)
23309 return false;
23310 break;
23311 }
23312 psz++;
23313 mask++;
23314 }
23315 }
23316
23317 bool WildcardMatch(const string& str, const string& mask)
23318 {
23319 return WildcardMatch(str.c_str(), mask.c_str());
23320 }
23321
23322
23323
23324
23325
23326
23327
23328
23329 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
23330 {
23331 #ifdef WIN32
23332 char pszModule[MAX_PATH];
23333 pszModule[0] = '\0';
23334 GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
23335 #else
23336 const char* pszModule = "bitcoin";
23337 #endif
23338 if (pex)
23339 snprintf(pszMessage, 1000,
23340 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
23341 else
23342 snprintf(pszMessage, 1000,
23343 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
23344 }
23345
23346 void LogException(std::exception* pex, const char* pszThread)
23347 {
23348 char pszMessage[10000];
23349 FormatException(pszMessage, pex, pszThread);
23350 printf("\n%s", pszMessage);
23351 }
23352
23353 void PrintException(std::exception* pex, const char* pszThread)
23354 {
23355 char pszMessage[10000];
23356 FormatException(pszMessage, pex, pszThread);
23357 printf("\n\n************************\n%s\n", pszMessage);
23358 fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
23359 strMiscWarning = pszMessage;
23360 throw;
23361 }
23362
23363 void ThreadOneMessageBox(string strMessage)
23364 {
23365 // Skip message boxes if one is already open
23366 static bool fMessageBoxOpen;
23367 if (fMessageBoxOpen)
23368 return;
23369 fMessageBoxOpen = true;
23370 ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
23371 fMessageBoxOpen = false;
23372 }
23373
23374 void PrintExceptionContinue(std::exception* pex, const char* pszThread)
23375 {
23376 char pszMessage[10000];
23377 FormatException(pszMessage, pex, pszThread);
23378 printf("\n\n************************\n%s\n", pszMessage);
23379 fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
23380 strMiscWarning = pszMessage;
23381 }
23382
23383
23384
23385
23386
23387
23388
23389
23390 #ifdef WIN32
23391 typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
23392
23393 string MyGetSpecialFolderPath(int nFolder, bool fCreate)
23394 {
23395 char pszPath[MAX_PATH+100] = "";
23396
23397 // SHGetSpecialFolderPath isn't always available on old Windows versions
23398 HMODULE hShell32 = LoadLibraryA("shell32.dll");
23399 if (hShell32)
23400 {
23401 PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
23402 (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
23403 bool fSuccess = false;
23404 if (pSHGetSpecialFolderPath)
23405 fSuccess =
23406 (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
23407 FreeModule(hShell32);
23408 if (fSuccess)
23409 return pszPath;
23410 }
23411
23412 // Backup option
23413 std::string strPath;
23414 {
23415 const char *pszEnv;
23416 if (nFolder == CSIDL_STARTUP)
23417 {
23418 pszEnv = getenv("USERPROFILE");
23419 if (pszEnv)
23420 strPath = pszEnv;
23421 strPath += "\\Start Menu\\Programs\\Startup";
23422 }
23423 else if (nFolder == CSIDL_APPDATA)
23424 {
23425 pszEnv = getenv("APPDATA");
23426 if (pszEnv)
23427 strPath = pszEnv;
23428 }
23429 }
23430
23431 return strPath;
23432 }
23433 #endif
23434
23435 string GetDefaultDataDir()
23436 {
23437 // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
23438 // Mac: ~/Library/Application Support/Bitcoin
23439 // Unix: ~/.bitcoin
23440 #ifdef WIN32
23441 // Windows
23442 return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
23443 #else
23444 char* pszHome = getenv("HOME");
23445 if (pszHome == NULL || strlen(pszHome) == 0)
23446 pszHome = (char*)"/";
23447 string strHome = pszHome;
23448 if (strHome[strHome.size()-1] != '/')
23449 strHome += '/';
23450 #ifdef MAC_OSX
23451 // Mac
23452 strHome += "Library/Application Support/";
23453 filesystem::create_directory(strHome.c_str());
23454 return strHome + "Bitcoin";
23455 #else
23456 // Unix
23457 return strHome + ".bitcoin";
23458 #endif
23459 #endif
23460 }
23461
23462 void GetDataDir(char* pszDir)
23463 {
23464 // pszDir must be at least MAX_PATH length.
23465 int nVariation;
23466 if (pszSetDataDir[0] != 0)
23467 {
23468 strlcpy(pszDir, pszSetDataDir, MAX_PATH);
23469 nVariation = 0;
23470 }
23471 else
23472 {
23473 // This can be called during exceptions by printf, so we cache the
23474 // value so we don't have to do memory allocations after that.
23475 static char pszCachedDir[MAX_PATH];
23476 if (pszCachedDir[0] == 0)
23477 strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir));
23478 strlcpy(pszDir, pszCachedDir, MAX_PATH);
23479 nVariation = 1;
23480 }
23481 if (fTestNet)
23482 {
23483 char* p = pszDir + strlen(pszDir);
23484 if (p > pszDir && p[-1] != '/' && p[-1] != '\\')
23485 *p++ = '/';
23486 strcpy(p, "testnet");
23487 nVariation += 2;
23488 }
23489 static bool pfMkdir[4];
23490 if (!pfMkdir[nVariation])
23491 {
23492 pfMkdir[nVariation] = true;
23493 boost::filesystem::create_directory(pszDir);
23494 }
23495 }
23496
23497 string GetDataDir()
23498 {
23499 char pszDir[MAX_PATH];
23500 GetDataDir(pszDir);
23501 return pszDir;
23502 }
23503
23504 string GetConfigFile()
23505 {
23506 namespace fs = boost::filesystem;
23507 fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
23508 if (!pathConfig.is_complete())
23509 pathConfig = fs::path(GetDataDir()) / pathConfig;
23510 return pathConfig.string();
23511 }
23512
23513 void ReadConfigFile(map<string, string>& mapSettingsRet,
23514 map<string, vector<string> >& mapMultiSettingsRet)
23515 {
23516 namespace fs = boost::filesystem;
23517 namespace pod = boost::program_options::detail;
23518
23519 fs::ifstream streamConfig(GetConfigFile());
23520 if (!streamConfig.good())
23521 return;
23522
23523 set<string> setOptions;
23524 setOptions.insert("*");
23525
23526 for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
23527 {
23528 // Don't overwrite existing settings so command line settings override bitcoin.conf
23529 string strKey = string("-") + it->string_key;
23530 if (mapSettingsRet.count(strKey) == 0)
23531 mapSettingsRet[strKey] = it->value[0];
23532 mapMultiSettingsRet[strKey].push_back(it->value[0]);
23533 }
23534 }
23535
23536 string GetPidFile()
23537 {
23538 namespace fs = boost::filesystem;
23539 fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
23540 if (!pathConfig.is_complete())
23541 pathConfig = fs::path(GetDataDir()) / pathConfig;
23542 return pathConfig.string();
23543 }
23544
23545 void CreatePidFile(string pidFile, pid_t pid)
23546 {
23547 FILE* file = fopen(pidFile.c_str(), "w");
23548 if (file)
23549 {
23550 fprintf(file, "%d\n", pid);
23551 fclose(file);
23552 }
23553 }
23554
23555 int GetFilesize(FILE* file)
23556 {
23557 int nSavePos = ftell(file);
23558 int nFilesize = -1;
23559 if (fseek(file, 0, SEEK_END) == 0)
23560 nFilesize = ftell(file);
23561 fseek(file, nSavePos, SEEK_SET);
23562 return nFilesize;
23563 }
23564
23565 void ShrinkDebugFile()
23566 {
23567 // Scroll debug.log if it's getting too big
23568 string strFile = GetDataDir() + "/debug.log";
23569 FILE* file = fopen(strFile.c_str(), "r");
23570 if (file && GetFilesize(file) > 10 * 1000000)
23571 {
23572 // Restart the file with some of the end
23573 char pch[200000];
23574 fseek(file, -sizeof(pch), SEEK_END);
23575 int nBytes = fread(pch, 1, sizeof(pch), file);
23576 fclose(file);
23577
23578 file = fopen(strFile.c_str(), "w");
23579 if (file)
23580 {
23581 fwrite(pch, 1, nBytes, file);
23582 fclose(file);
23583 }
23584 }
23585 }
23586
23587
23588
23589
23590
23591
23592
23593
23594 //
23595 // "Never go to sea with two chronometers; take one or three."
23596 // Our three time sources are:
23597 // - System clock
23598 // - Median of other nodes's clocks
23599 // - The user (asking the user to fix the system clock if the first two disagree)
23600 //
23601 static int64 nMockTime = 0; // For unit testing
23602
23603 int64 GetTime()
23604 {
23605 if (nMockTime) return nMockTime;
23606
23607 return time(NULL);
23608 }
23609
23610 void SetMockTime(int64 nMockTimeIn)
23611 {
23612 nMockTime = nMockTimeIn;
23613 }
23614
23615 static int64 nTimeOffset = 0;
23616
23617 int64 GetAdjustedTime()
23618 {
23619 return GetTime() + nTimeOffset;
23620 }
23621
23622 void AddTimeData(unsigned int ip, int64 nTime)
23623 {
23624 int64 nOffsetSample = nTime - GetTime();
23625
23626 // Ignore duplicates
23627 static set<unsigned int> setKnown;
23628 if (!setKnown.insert(ip).second)
23629 return;
23630
23631 // Add data
23632 static vector<int64> vTimeOffsets;
23633 if (vTimeOffsets.empty())
23634 vTimeOffsets.push_back(0);
23635 vTimeOffsets.push_back(nOffsetSample);
23636 printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
23637 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
23638 {
23639 sort(vTimeOffsets.begin(), vTimeOffsets.end());
23640 int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
23641 // Only let other nodes change our time by so much
23642 if (abs64(nMedian) < 70 * 60)
23643 {
23644 nTimeOffset = nMedian;
23645 }
23646 else
23647 {
23648 nTimeOffset = 0;
23649
23650 static bool fDone;
23651 if (!fDone)
23652 {
23653 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
23654 bool fMatch = false;
23655 BOOST_FOREACH(int64 nOffset, vTimeOffsets)
23656 if (nOffset != 0 && abs64(nOffset) < 5 * 60)
23657 fMatch = true;
23658
23659 if (!fMatch)
23660 {
23661 fDone = true;
23662 string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
23663 strMiscWarning = strMessage;
23664 printf("*** %s\n", strMessage.c_str());
23665 boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
23666 }
23667 }
23668 }
23669 BOOST_FOREACH(int64 n, vTimeOffsets)
23670 printf("%+"PRI64d" ", n);
23671 printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
23672 }
23673 }
23674
23675
23676
23677
23678
23679
23680
23681
23682
23683 string FormatVersion(int nVersion)
23684 {
23685 if (nVersion%100 == 0)
23686 return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
23687 else
23688 return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
23689 }
23690
23691 string FormatFullVersion()
23692 {
23693 string s = FormatVersion(VERSION) + pszSubVer;
23694 if (VERSION_IS_BETA) {
23695 s += "-";
23696 s += _("beta");
23697 }
23698 return s;
23699 }
23700
23701
23702
23703
23704 #ifdef DEBUG_LOCKORDER
23705 //
23706 // Early deadlock detection.
23707 // Problem being solved:
23708 // Thread 1 locks A, then B, then C
23709 // Thread 2 locks D, then C, then A
23710 // --> may result in deadlock between the two threads, depending on when they run.
23711 // Solution implemented here:
23712 // Keep track of pairs of locks: (A before B), (A before C), etc.
23713 // Complain if any thread trys to lock in a different order.
23714 //
23715
23716 struct CLockLocation
23717 {
23718 CLockLocation(const char* pszName, const char* pszFile, int nLine)
23719 {
23720 mutexName = pszName;
23721 sourceFile = pszFile;
23722 sourceLine = nLine;
23723 }
23724
23725 std::string ToString() const
23726 {
23727 return mutexName+" "+sourceFile+":"+itostr(sourceLine);
23728 }
23729
23730 private:
23731 std::string mutexName;
23732 std::string sourceFile;
23733 int sourceLine;
23734 };
23735
23736 typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack;
23737
23738 static boost::interprocess::interprocess_mutex dd_mutex;
23739 static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders;
23740 static boost::thread_specific_ptr<LockStack> lockstack;
23741
23742
23743 static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
23744 {
23745 printf("POTENTIAL DEADLOCK DETECTED\n");
23746 printf("Previous lock order was:\n");
23747 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
23748 {
23749 if (i.first == mismatch.first) printf(" (1)");
23750 if (i.first == mismatch.second) printf(" (2)");
23751 printf(" %s\n", i.second.ToString().c_str());
23752 }
23753 printf("Current lock order is:\n");
23754 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
23755 {
23756 if (i.first == mismatch.first) printf(" (1)");
23757 if (i.first == mismatch.second) printf(" (2)");
23758 printf(" %s\n", i.second.ToString().c_str());
23759 }
23760 }
23761
23762 static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
23763 {
23764 bool fOrderOK = true;
23765 if (lockstack.get() == NULL)
23766 lockstack.reset(new LockStack);
23767
23768 if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
23769 dd_mutex.lock();
23770
23771 (*lockstack).push_back(std::make_pair(c, locklocation));
23772
23773 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack))
23774 {
23775 if (i.first == c) break;
23776
23777 std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c);
23778 if (lockorders.count(p1))
23779 continue;
23780 lockorders[p1] = (*lockstack);
23781
23782 std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
23783 if (lockorders.count(p2))
23784 {
23785 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
23786 break;
23787 }
23788 }
23789 dd_mutex.unlock();
23790 }
23791
23792 static void pop_lock()
23793 {
23794 if (fDebug)
23795 {
23796 const CLockLocation& locklocation = (*lockstack).rbegin()->second;
23797 printf("Unlocked: %s\n", locklocation.ToString().c_str());
23798 }
23799 dd_mutex.lock();
23800 (*lockstack).pop_back();
23801 dd_mutex.unlock();
23802 }
23803
23804 void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
23805 {
23806 push_lock(this, CLockLocation(pszName, pszFile, nLine));
23807 mutex.lock();
23808 }
23809 void CCriticalSection::Leave()
23810 {
23811 mutex.unlock();
23812 pop_lock();
23813 }
23814 bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine)
23815 {
23816 push_lock(this, CLockLocation(pszName, pszFile, nLine));
23817 bool result = mutex.try_lock();
23818 if (!result) pop_lock();
23819 return result;
23820 }
23821
23822 #else
23823
23824 void CCriticalSection::Enter(const char*, const char*, int)
23825 {
23826 mutex.lock();
23827 }
23828
23829 void CCriticalSection::Leave()
23830 {
23831 mutex.unlock();
23832 }
23833
23834 bool CCriticalSection::TryEnter(const char*, const char*, int)
23835 {
23836 bool result = mutex.try_lock();
23837 return result;
23838 }
23839
23840 #endif /* DEBUG_LOCKORDER */