genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 #include "headers.h"
genesis                 6 #include "strlcpy.h"
genesis                 7 #include <boost/program_options/detail/config_file.hpp>
genesis                 8 #include <boost/program_options/parsers.hpp>
genesis                 9 #include <boost/filesystem.hpp>
genesis                10 #include <boost/filesystem/fstream.hpp>
genesis                11 #include <boost/interprocess/sync/interprocess_mutex.hpp>
genesis                12 #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
genesis                13 #include <boost/foreach.hpp>
genesis                14 
genesis                15 using namespace std;
genesis                16 using namespace boost;
genesis                17 
genesis                18 map<string, string> mapArgs;
genesis                19 map<string, vector<string> > mapMultiArgs;
genesis                20 bool fDebug = false;
genesis                21 bool fPrintToConsole = false;
genesis                22 bool fPrintToDebugger = false;
genesis                23 char pszSetDataDir[MAX_PATH] = "";
genesis                24 bool fRequestShutdown = false;
genesis                25 bool fShutdown = false;
genesis                26 bool fDaemon = false;
genesis                27 bool fServer = false;
genesis                28 bool fCommandLine = false;
genesis                29 string strMiscWarning;
genesis                30 bool fTestNet = false;
genesis                31 bool fNoListen = false;
genesis                32 bool fLogTimestamps = false;
genesis                33 
genesis                34 
genesis                35 
genesis                36 
genesis                37 
genesis                38 
genesis                39 extern "C" void tss_cleanup_implemented() { }
genesis                40 
genesis                41 
genesis                42 
genesis                43 
genesis                44 
genesis                45 
genesis                46 static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
genesis                47 void locking_callback(int mode, int i, const char* file, int line)
genesis                48 {
genesis                49     if (mode & CRYPTO_LOCK)
genesis                50         ppmutexOpenSSL[i]->lock();
genesis                51     else
genesis                52         ppmutexOpenSSL[i]->unlock();
genesis                53 }
genesis                54 
genesis                55 
genesis                56 class CInit
genesis                57 {
genesis                58 public:
genesis                59     CInit()
genesis                60     {
genesis                61         
genesis                62         ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
genesis                63         for (int i = 0; i < CRYPTO_num_locks(); i++)
genesis                64             ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
genesis                65         CRYPTO_set_locking_callback(locking_callback);
genesis                66 
genesis                67 #ifdef WIN32
genesis                68         
genesis                69         RAND_screen();
genesis                70 #endif
genesis                71 
genesis                72         
genesis                73         RandAddSeed();
genesis                74     }
genesis                75     ~CInit()
genesis                76     {
genesis                77         
genesis                78         CRYPTO_set_locking_callback(NULL);
genesis                79         for (int i = 0; i < CRYPTO_num_locks(); i++)
genesis                80             delete ppmutexOpenSSL[i];
genesis                81         OPENSSL_free(ppmutexOpenSSL);
genesis                82     }
genesis                83 }
genesis                84 instance_of_cinit;
genesis                85 
genesis                86 
genesis                87 
genesis                88 
genesis                89 
genesis                90 
genesis                91 
genesis                92 
genesis                93 void RandAddSeed()
genesis                94 {
genesis                95     
genesis                96     int64 nCounter = GetPerformanceCounter();
genesis                97     RAND_add(&nCounter, sizeof(nCounter), 1.5);
genesis                98     memset(&nCounter, 0, sizeof(nCounter));
genesis                99 }
genesis               100 
genesis               101 void RandAddSeedPerfmon()
genesis               102 {
genesis               103     RandAddSeed();
genesis               104 
genesis               105     
genesis               106     static int64 nLastPerfmon;
genesis               107     if (GetTime() < nLastPerfmon + 10 * 60)
genesis               108         return;
genesis               109     nLastPerfmon = GetTime();
genesis               110 
genesis               111 #ifdef WIN32
genesis               112     
genesis               113     
genesis               114     unsigned char pdata[250000];
genesis               115     memset(pdata, 0, sizeof(pdata));
genesis               116     unsigned long nSize = sizeof(pdata);
genesis               117     long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
genesis               118     RegCloseKey(HKEY_PERFORMANCE_DATA);
genesis               119     if (ret == ERROR_SUCCESS)
genesis               120     {
genesis               121         RAND_add(pdata, nSize, nSize/100.0);
genesis               122         memset(pdata, 0, nSize);
genesis               123         printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
genesis               124     }
genesis               125 #endif
genesis               126 }
genesis               127 
genesis               128 uint64 GetRand(uint64 nMax)
genesis               129 {
genesis               130     if (nMax == 0)
genesis               131         return 0;
genesis               132 
genesis               133     
genesis               134     
genesis               135     uint64 nRange = (UINT64_MAX / nMax) * nMax;
genesis               136     uint64 nRand = 0;
genesis               137     do
genesis               138         RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
genesis               139     while (nRand >= nRange);
genesis               140     return (nRand % nMax);
genesis               141 }
genesis               142 
genesis               143 int GetRandInt(int nMax)
genesis               144 {
genesis               145     return GetRand(nMax);
genesis               146 }
genesis               147 
genesis               148 
genesis               149 
genesis               150 
genesis               151 
genesis               152 
genesis               153 
genesis               154 
genesis               155 
genesis               156 
genesis               157 
genesis               158 inline int OutputDebugStringF(const char* pszFormat, ...)
genesis               159 {
genesis               160     int ret = 0;
genesis               161     if (fPrintToConsole)
genesis               162     {
genesis               163         
genesis               164         va_list arg_ptr;
genesis               165         va_start(arg_ptr, pszFormat);
genesis               166         ret = vprintf(pszFormat, arg_ptr);
genesis               167         va_end(arg_ptr);
genesis               168     }
genesis               169     else
genesis               170     {
genesis               171         
genesis               172         static FILE* fileout = NULL;
genesis               173 
genesis               174         if (!fileout)
genesis               175         {
genesis               176             char pszFile[MAX_PATH+100];
genesis               177             GetDataDir(pszFile);
genesis               178             strlcat(pszFile, "/debug.log", sizeof(pszFile));
genesis               179             fileout = fopen(pszFile, "a");
genesis               180             if (fileout) setbuf(fileout, NULL); 
genesis               181         }
genesis               182         if (fileout)
genesis               183         {
genesis               184             static bool fStartedNewLine = true;
genesis               185 
genesis               186             
genesis               187             if (fLogTimestamps && fStartedNewLine)
genesis               188                 fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis               189             if (pszFormat[strlen(pszFormat) - 1] == '\n')
genesis               190                 fStartedNewLine = true;
genesis               191             else
genesis               192                 fStartedNewLine = false;
genesis               193 
genesis               194             va_list arg_ptr;
genesis               195             va_start(arg_ptr, pszFormat);
genesis               196             ret = vfprintf(fileout, pszFormat, arg_ptr);
genesis               197             va_end(arg_ptr);
genesis               198         }
genesis               199     }
genesis               200 
genesis               201 #ifdef WIN32
genesis               202     if (fPrintToDebugger)
genesis               203     {
genesis               204         static CCriticalSection cs_OutputDebugStringF;
genesis               205 
genesis               206         
genesis               207         CRITICAL_BLOCK(cs_OutputDebugStringF)
genesis               208         {
genesis               209             static char pszBuffer[50000];
genesis               210             static char* pend;
genesis               211             if (pend == NULL)
genesis               212                 pend = pszBuffer;
genesis               213             va_list arg_ptr;
genesis               214             va_start(arg_ptr, pszFormat);
genesis               215             int limit = END(pszBuffer) - pend - 2;
genesis               216             int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
genesis               217             va_end(arg_ptr);
genesis               218             if (ret < 0 || ret >= limit)
genesis               219             {
genesis               220                 pend = END(pszBuffer) - 2;
genesis               221                 *pend++ = '\n';
genesis               222             }
genesis               223             else
genesis               224                 pend += ret;
genesis               225             *pend = '\0';
genesis               226             char* p1 = pszBuffer;
genesis               227             char* p2;
genesis               228             while (p2 = strchr(p1, '\n'))
genesis               229             {
genesis               230                 p2++;
genesis               231                 char c = *p2;
genesis               232                 *p2 = '\0';
genesis               233                 OutputDebugStringA(p1);
genesis               234                 *p2 = c;
genesis               235                 p1 = p2;
genesis               236             }
genesis               237             if (p1 != pszBuffer)
genesis               238                 memmove(pszBuffer, p1, pend - p1 + 1);
genesis               239             pend -= (p1 - pszBuffer);
genesis               240         }
genesis               241     }
genesis               242 #endif
genesis               243     return ret;
genesis               244 }
genesis               245 
genesis               246 
genesis               247 
genesis               248 
genesis               249 
genesis               250 
genesis               251 int my_snprintf(char* buffer, size_t limit, const char* format, ...)
genesis               252 {
genesis               253     if (limit == 0)
genesis               254         return 0;
genesis               255     va_list arg_ptr;
genesis               256     va_start(arg_ptr, format);
genesis               257     int ret = _vsnprintf(buffer, limit, format, arg_ptr);
genesis               258     va_end(arg_ptr);
genesis               259     if (ret < 0 || ret >= limit)
genesis               260     {
genesis               261         ret = limit - 1;
genesis               262         buffer[limit-1] = 0;
genesis               263     }
genesis               264     return ret;
genesis               265 }
genesis               266 
genesis               267 string strprintf(const std::string &format, ...)
genesis               268 {
genesis               269     char buffer[50000];
genesis               270     char* p = buffer;
genesis               271     int limit = sizeof(buffer);
genesis               272     int ret;
genesis               273     loop
genesis               274     {
genesis               275         va_list arg_ptr;
genesis               276         va_start(arg_ptr, format);
genesis               277         ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
genesis               278         va_end(arg_ptr);
genesis               279         if (ret >= 0 && ret < limit)
genesis               280             break;
genesis               281         if (p != buffer)
genesis               282             delete[] p;
genesis               283         limit *= 2;
genesis               284         p = new char[limit];
genesis               285         if (p == NULL)
genesis               286             throw std::bad_alloc();
genesis               287     }
genesis               288     string str(p, p+ret);
genesis               289     if (p != buffer)
genesis               290         delete[] p;
genesis               291     return str;
genesis               292 }
genesis               293 
genesis               294 bool error(const std::string &format, ...)
genesis               295 {
genesis               296     char buffer[50000];
genesis               297     int limit = sizeof(buffer);
genesis               298     va_list arg_ptr;
genesis               299     va_start(arg_ptr, format);
genesis               300     int ret = _vsnprintf(buffer, limit, format.c_str(), arg_ptr);
genesis               301     va_end(arg_ptr);
genesis               302     if (ret < 0 || ret >= limit)
genesis               303     {
genesis               304         ret = limit - 1;
genesis               305         buffer[limit-1] = 0;
genesis               306     }
genesis               307     printf("ERROR: %s\n", buffer);
genesis               308     return false;
genesis               309 }
genesis               310 
genesis               311 
genesis               312 void ParseString(const string& str, char c, vector<string>& v)
genesis               313 {
genesis               314     if (str.empty())
genesis               315         return;
genesis               316     string::size_type i1 = 0;
genesis               317     string::size_type i2;
genesis               318     loop
genesis               319     {
genesis               320         i2 = str.find(c, i1);
genesis               321         if (i2 == str.npos)
genesis               322         {
genesis               323             v.push_back(str.substr(i1));
genesis               324             return;
genesis               325         }
genesis               326         v.push_back(str.substr(i1, i2-i1));
genesis               327         i1 = i2+1;
genesis               328     }
genesis               329 }
genesis               330 
genesis               331 
genesis               332 string FormatMoney(int64 n, bool fPlus)
genesis               333 {
genesis               334     
genesis               335     
genesis               336     int64 n_abs = (n > 0 ? n : -n);
genesis               337     int64 quotient = n_abs/COIN;
genesis               338     int64 remainder = n_abs%COIN;
genesis               339     string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder);
genesis               340 
genesis               341     
genesis               342     int nTrim = 0;
genesis               343     for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
genesis               344         ++nTrim;
genesis               345     if (nTrim)
genesis               346         str.erase(str.size()-nTrim, nTrim);
genesis               347 
genesis               348     if (n < 0)
genesis               349         str.insert((unsigned int)0, 1, '-');
genesis               350     else if (fPlus && n > 0)
genesis               351         str.insert((unsigned int)0, 1, '+');
genesis               352     return str;
genesis               353 }
genesis               354 
genesis               355 
genesis               356 bool ParseMoney(const string& str, int64& nRet)
genesis               357 {
genesis               358     return ParseMoney(str.c_str(), nRet);
genesis               359 }
genesis               360 
genesis               361 bool ParseMoney(const char* pszIn, int64& nRet)
genesis               362 {
genesis               363     string strWhole;
genesis               364     int64 nUnits = 0;
genesis               365     const char* p = pszIn;
genesis               366     while (isspace(*p))
genesis               367         p++;
genesis               368     for (; *p; p++)
genesis               369     {
genesis               370         if (*p == '.')
genesis               371         {
genesis               372             p++;
genesis               373             int64 nMult = CENT*10;
genesis               374             while (isdigit(*p) && (nMult > 0))
genesis               375             {
genesis               376                 nUnits += nMult * (*p++ - '0');
genesis               377                 nMult /= 10;
genesis               378             }
genesis               379             break;
genesis               380         }
genesis               381         if (isspace(*p))
genesis               382             break;
genesis               383         if (!isdigit(*p))
genesis               384             return false;
genesis               385         strWhole.insert(strWhole.end(), *p);
genesis               386     }
genesis               387     for (; *p; p++)
genesis               388         if (!isspace(*p))
genesis               389             return false;
genesis               390     if (strWhole.size() > 10) 
genesis               391         return false;
genesis               392     if (nUnits < 0 || nUnits > COIN)
genesis               393         return false;
genesis               394     int64 nWhole = atoi64(strWhole);
genesis               395     int64 nValue = nWhole*COIN + nUnits;
genesis               396 
genesis               397     nRet = nValue;
genesis               398     return true;
genesis               399 }
genesis               400 
genesis               401 
genesis               402 vector<unsigned char> ParseHex(const char* psz)
genesis               403 {
genesis               404     static char phexdigit[256] =
genesis               405     { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               406       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               407       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               408       0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
genesis               409       -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               410       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               411       -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1
genesis               412       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               413       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               414       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               415       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               416       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               417       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               418       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               419       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
genesis               420       -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
genesis               421 
genesis               422     
genesis               423     vector<unsigned char> vch;
genesis               424     loop
genesis               425     {
genesis               426         while (isspace(*psz))
genesis               427             psz++;
genesis               428         char c = phexdigit[(unsigned char)*psz++];
genesis               429         if (c == (char)-1)
genesis               430             break;
genesis               431         unsigned char n = (c << 4);
genesis               432         c = phexdigit[(unsigned char)*psz++];
genesis               433         if (c == (char)-1)
genesis               434             break;
genesis               435         n |= c;
genesis               436         vch.push_back(n);
genesis               437     }
genesis               438     return vch;
genesis               439 }
genesis               440 
genesis               441 vector<unsigned char> ParseHex(const string& str)
genesis               442 {
genesis               443     return ParseHex(str.c_str());
genesis               444 }
genesis               445 
genesis               446 void ParseParameters(int argc, char* argv[])
genesis               447 {
genesis               448     mapArgs.clear();
genesis               449     mapMultiArgs.clear();
genesis               450     for (int i = 1; i < argc; i++)
genesis               451     {
genesis               452         char psz[10000];
genesis               453         strlcpy(psz, argv[i], sizeof(psz));
genesis               454         char* pszValue = (char*)"";
genesis               455         if (strchr(psz, '='))
genesis               456         {
genesis               457             pszValue = strchr(psz, '=');
genesis               458             *pszValue++ = '\0';
genesis               459         }
genesis               460         #ifdef WIN32
genesis               461         _strlwr(psz);
genesis               462         if (psz[0] == '/')
genesis               463             psz[0] = '-';
genesis               464         #endif
genesis               465         if (psz[0] != '-')
genesis               466             break;
genesis               467         mapArgs[psz] = pszValue;
genesis               468         mapMultiArgs[psz].push_back(pszValue);
genesis               469     }
genesis               470 }
genesis               471 
genesis               472 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
genesis               473 {
genesis               474     if (mapArgs.count(strArg))
genesis               475         return false;
genesis               476     mapArgs[strArg] = strValue;
genesis               477     return true;
genesis               478 }
genesis               479 
genesis               480 bool SoftSetArg(const std::string& strArg, bool fValue)
genesis               481 {
genesis               482     if (fValue)
genesis               483         return SoftSetArg(strArg, std::string("1"));
genesis               484     else
genesis               485         return SoftSetArg(strArg, std::string("0"));
genesis               486 }
genesis               487 
genesis               488 
genesis               489 string EncodeBase64(const unsigned char* pch, size_t len)
genesis               490 {
genesis               491     static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
genesis               492 
genesis               493     string strRet="";
genesis               494     strRet.reserve((len+2)/3*4);
genesis               495 
genesis               496     int mode=0, left=0;
genesis               497     const unsigned char *pchEnd = pch+len;
genesis               498 
genesis               499     while (pch<pchEnd)
genesis               500     {
genesis               501         int enc = *(pch++);
genesis               502         switch (mode)
genesis               503         {
genesis               504             case 0: 
genesis               505                 strRet += pbase64[enc >> 2];
genesis               506                 left = (enc & 3) << 4;
genesis               507                 mode = 1;
genesis               508                 break;
genesis               509 
genesis               510             case 1: 
genesis               511                 strRet += pbase64[left | (enc >> 4)];
genesis               512                 left = (enc & 15) << 2;
genesis               513                 mode = 2;
genesis               514                 break;
genesis               515 
genesis               516             case 2: 
genesis               517                 strRet += pbase64[left | (enc >> 6)];
genesis               518                 strRet += pbase64[enc & 63];
genesis               519                 mode = 0;
genesis               520                 break;
genesis               521         }
genesis               522     }
genesis               523 
genesis               524     if (mode)
genesis               525     {
genesis               526         strRet += pbase64[left];
genesis               527         strRet += '=';
genesis               528         if (mode == 1)
genesis               529             strRet += '=';
genesis               530     }
genesis               531 
genesis               532     return strRet;
genesis               533 }
genesis               534 
genesis               535 string EncodeBase64(const string& str)
genesis               536 {
genesis               537     return EncodeBase64((const unsigned char*)str.c_str(), str.size());
genesis               538 }
genesis               539 
genesis               540 vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
genesis               541 {
genesis               542     static const int decode64_table[256] =
genesis               543     {
genesis               544         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               545         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               546         -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
genesis               547         -1, -1, -1, -1, -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
genesis               548         15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
genesis               549         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
genesis               550         49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               551         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               552         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               553         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               554         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               555         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
genesis               556         -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
genesis               557     };
genesis               558 
genesis               559     if (pfInvalid)
genesis               560         *pfInvalid = false;
genesis               561 
genesis               562     vector<unsigned char> vchRet;
genesis               563     vchRet.reserve(strlen(p)*3/4);
genesis               564 
genesis               565     int mode = 0;
genesis               566     int left = 0;
genesis               567 
genesis               568     while (1)
genesis               569     {
genesis               570          int dec = decode64_table[*p];
genesis               571          if (dec == -1) break;
genesis               572          p++;
genesis               573          switch (mode)
genesis               574          {
genesis               575              case 0: 
genesis               576                  left = dec;
genesis               577                  mode = 1;
genesis               578                  break;
genesis               579 
genesis               580               case 1: 
genesis               581                   vchRet.push_back((left<<2) | (dec>>4));
genesis               582                   left = dec & 15;
genesis               583                   mode = 2;
genesis               584                   break;
genesis               585 
genesis               586              case 2: 
genesis               587                  vchRet.push_back((left<<4) | (dec>>2));
genesis               588                  left = dec & 3;
genesis               589                  mode = 3;
genesis               590                  break;
genesis               591 
genesis               592              case 3: 
genesis               593                  vchRet.push_back((left<<6) | dec);
genesis               594                  mode = 0;
genesis               595                  break;
genesis               596          }
genesis               597     }
genesis               598 
genesis               599     if (pfInvalid)
genesis               600         switch (mode)
genesis               601         {
genesis               602             case 0: 
genesis               603                 break;
genesis               604 
genesis               605             case 1: 
genesis               606                 *pfInvalid = true;
genesis               607                 break;
genesis               608 
genesis               609             case 2: 
genesis               610                 if (left || p[0] != '=' || p[1] != '=' || decode64_table[p[2]] != -1)
genesis               611                     *pfInvalid = true;
genesis               612                 break;
genesis               613 
genesis               614             case 3: 
genesis               615                 if (left || p[0] != '=' || decode64_table[p[1]] != -1)
genesis               616                     *pfInvalid = true;
genesis               617                 break;
genesis               618         }
genesis               619 
genesis               620     return vchRet;
genesis               621 }
genesis               622 
genesis               623 string DecodeBase64(const string& str)
genesis               624 {
genesis               625     vector<unsigned char> vchRet = DecodeBase64(str.c_str());
genesis               626     return string((const char*)&vchRet[0], vchRet.size());
genesis               627 }
genesis               628 
genesis               629 
genesis               630 bool WildcardMatch(const char* psz, const char* mask)
genesis               631 {
genesis               632     loop
genesis               633     {
genesis               634         switch (*mask)
genesis               635         {
genesis               636         case '\0':
genesis               637             return (*psz == '\0');
genesis               638         case '*':
genesis               639             return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
genesis               640         case '?':
genesis               641             if (*psz == '\0')
genesis               642                 return false;
genesis               643             break;
genesis               644         default:
genesis               645             if (*psz != *mask)
genesis               646                 return false;
genesis               647             break;
genesis               648         }
genesis               649         psz++;
genesis               650         mask++;
genesis               651     }
genesis               652 }
genesis               653 
genesis               654 bool WildcardMatch(const string& str, const string& mask)
genesis               655 {
genesis               656     return WildcardMatch(str.c_str(), mask.c_str());
genesis               657 }
genesis               658 
genesis               659 
genesis               660 
genesis               661 
genesis               662 
genesis               663 
genesis               664 
genesis               665 
genesis               666 void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
genesis               667 {
genesis               668 #ifdef WIN32
genesis               669     char pszModule[MAX_PATH];
genesis               670     pszModule[0] = '\0';
genesis               671     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
genesis               672 #else
genesis               673     const char* pszModule = "bitcoin";
genesis               674 #endif
genesis               675     if (pex)
genesis               676         snprintf(pszMessage, 1000,
genesis               677             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
genesis               678     else
genesis               679         snprintf(pszMessage, 1000,
genesis               680             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
genesis               681 }
genesis               682 
genesis               683 void LogException(std::exception* pex, const char* pszThread)
genesis               684 {
genesis               685     char pszMessage[10000];
genesis               686     FormatException(pszMessage, pex, pszThread);
genesis               687     printf("\n%s", pszMessage);
genesis               688 }
genesis               689 
genesis               690 void PrintException(std::exception* pex, const char* pszThread)
genesis               691 {
genesis               692     char pszMessage[10000];
genesis               693     FormatException(pszMessage, pex, pszThread);
genesis               694     printf("\n\n************************\n%s\n", pszMessage);
genesis               695     fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
genesis               696     strMiscWarning = pszMessage;
genesis               697     throw;
genesis               698 }
genesis               699 
genesis               700 void ThreadOneMessageBox(string strMessage)
genesis               701 {
genesis               702     
genesis               703     static bool fMessageBoxOpen;
genesis               704     if (fMessageBoxOpen)
genesis               705         return;
genesis               706     fMessageBoxOpen = true;
genesis               707     ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
genesis               708     fMessageBoxOpen = false;
genesis               709 }
genesis               710 
genesis               711 void PrintExceptionContinue(std::exception* pex, const char* pszThread)
genesis               712 {
genesis               713     char pszMessage[10000];
genesis               714     FormatException(pszMessage, pex, pszThread);
genesis               715     printf("\n\n************************\n%s\n", pszMessage);
genesis               716     fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
genesis               717     strMiscWarning = pszMessage;
genesis               718 }
genesis               719 
genesis               720 
genesis               721 
genesis               722 
genesis               723 
genesis               724 
genesis               725 
genesis               726 
genesis               727 #ifdef WIN32
genesis               728 typedef WINSHELLAPI BOOL (WINAPI *PSHGETSPECIALFOLDERPATHA)(HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
genesis               729 
genesis               730 string MyGetSpecialFolderPath(int nFolder, bool fCreate)
genesis               731 {
genesis               732     char pszPath[MAX_PATH+100] = "";
genesis               733 
genesis               734     
genesis               735     HMODULE hShell32 = LoadLibraryA("shell32.dll");
genesis               736     if (hShell32)
genesis               737     {
genesis               738         PSHGETSPECIALFOLDERPATHA pSHGetSpecialFolderPath =
genesis               739             (PSHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
genesis               740         bool fSuccess = false;
genesis               741         if (pSHGetSpecialFolderPath)
genesis               742             fSuccess =
genesis               743             (*pSHGetSpecialFolderPath)(NULL, pszPath, nFolder, fCreate);
genesis               744         FreeModule(hShell32);
genesis               745         if (fSuccess)
genesis               746             return pszPath;
genesis               747     }
genesis               748 
genesis               749     
genesis               750     std::string strPath;
genesis               751     {
genesis               752         const char *pszEnv;
genesis               753         if (nFolder == CSIDL_STARTUP)
genesis               754         {
genesis               755             pszEnv = getenv("USERPROFILE");
genesis               756             if (pszEnv)
genesis               757                 strPath = pszEnv;
genesis               758             strPath += "\\Start Menu\\Programs\\Startup";
genesis               759         }
genesis               760         else if (nFolder == CSIDL_APPDATA)
genesis               761         {
genesis               762             pszEnv = getenv("APPDATA");
genesis               763             if (pszEnv)
genesis               764                 strPath = pszEnv;
genesis               765         }
genesis               766     }
genesis               767 
genesis               768     return strPath;
genesis               769 }
genesis               770 #endif
genesis               771 
genesis               772 string GetDefaultDataDir()
genesis               773 {
genesis               774     
genesis               775     
genesis               776     
genesis               777 #ifdef WIN32
genesis               778     
genesis               779     return MyGetSpecialFolderPath(CSIDL_APPDATA, true) + "\\Bitcoin";
genesis               780 #else
genesis               781     char* pszHome = getenv("HOME");
genesis               782     if (pszHome == NULL || strlen(pszHome) == 0)
genesis               783         pszHome = (char*)"/";
genesis               784     string strHome = pszHome;
genesis               785     if (strHome[strHome.size()-1] != '/')
genesis               786         strHome += '/';
genesis               787 #ifdef MAC_OSX
genesis               788     
genesis               789     strHome += "Library/Application Support/";
genesis               790     filesystem::create_directory(strHome.c_str());
genesis               791     return strHome + "Bitcoin";
genesis               792 #else
genesis               793     
genesis               794     return strHome + ".bitcoin";
genesis               795 #endif
genesis               796 #endif
genesis               797 }
genesis               798 
genesis               799 void GetDataDir(char* pszDir)
genesis               800 {
genesis               801     
genesis               802     int nVariation;
genesis               803     if (pszSetDataDir[0] != 0)
genesis               804     {
genesis               805         strlcpy(pszDir, pszSetDataDir, MAX_PATH);
genesis               806         nVariation = 0;
genesis               807     }
genesis               808     else
genesis               809     {
genesis               810         
genesis               811         
genesis               812         static char pszCachedDir[MAX_PATH];
genesis               813         if (pszCachedDir[0] == 0)
genesis               814             strlcpy(pszCachedDir, GetDefaultDataDir().c_str(), sizeof(pszCachedDir));
genesis               815         strlcpy(pszDir, pszCachedDir, MAX_PATH);
genesis               816         nVariation = 1;
genesis               817     }
genesis               818     if (fTestNet)
genesis               819     {
genesis               820         char* p = pszDir + strlen(pszDir);
genesis               821         if (p > pszDir && p[-1] != '/' && p[-1] != '\\')
genesis               822             *p++ = '/';
genesis               823         strcpy(p, "testnet");
genesis               824         nVariation += 2;
genesis               825     }
genesis               826     static bool pfMkdir[4];
genesis               827     if (!pfMkdir[nVariation])
genesis               828     {
genesis               829         pfMkdir[nVariation] = true;
genesis               830         boost::filesystem::create_directory(pszDir);
genesis               831     }
genesis               832 }
genesis               833 
genesis               834 string GetDataDir()
genesis               835 {
genesis               836     char pszDir[MAX_PATH];
genesis               837     GetDataDir(pszDir);
genesis               838     return pszDir;
genesis               839 }
genesis               840 
genesis               841 string GetConfigFile()
genesis               842 {
genesis               843     namespace fs = boost::filesystem;
genesis               844     fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
genesis               845     if (!pathConfig.is_complete())
genesis               846         pathConfig = fs::path(GetDataDir()) / pathConfig;
genesis               847     return pathConfig.string();
genesis               848 }
genesis               849 
genesis               850 void ReadConfigFile(map<string, string>& mapSettingsRet,
genesis               851                     map<string, vector<string> >& mapMultiSettingsRet)
genesis               852 {
genesis               853     namespace fs = boost::filesystem;
genesis               854     namespace pod = boost::program_options::detail;
genesis               855 
genesis               856     fs::ifstream streamConfig(GetConfigFile());
genesis               857     if (!streamConfig.good())
genesis               858         return;
genesis               859 
genesis               860     set<string> setOptions;
genesis               861     setOptions.insert("*");
genesis               862     
genesis               863     for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
genesis               864     {
genesis               865         
genesis               866         string strKey = string("-") + it->string_key;
genesis               867         if (mapSettingsRet.count(strKey) == 0)
genesis               868             mapSettingsRet[strKey] = it->value[0];
genesis               869         mapMultiSettingsRet[strKey].push_back(it->value[0]);
genesis               870     }
genesis               871 }
genesis               872 
genesis               873 string GetPidFile()
genesis               874 {
genesis               875     namespace fs = boost::filesystem;
genesis               876     fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
genesis               877     if (!pathConfig.is_complete())
genesis               878         pathConfig = fs::path(GetDataDir()) / pathConfig;
genesis               879     return pathConfig.string();
genesis               880 }
genesis               881 
genesis               882 void CreatePidFile(string pidFile, pid_t pid)
genesis               883 {
genesis               884     FILE* file = fopen(pidFile.c_str(), "w");
genesis               885     if (file)
genesis               886     {
genesis               887         fprintf(file, "%d\n", pid);
genesis               888         fclose(file);
genesis               889     }
genesis               890 }
genesis               891 
genesis               892 int GetFilesize(FILE* file)
genesis               893 {
genesis               894     int nSavePos = ftell(file);
genesis               895     int nFilesize = -1;
genesis               896     if (fseek(file, 0, SEEK_END) == 0)
genesis               897         nFilesize = ftell(file);
genesis               898     fseek(file, nSavePos, SEEK_SET);
genesis               899     return nFilesize;
genesis               900 }
genesis               901 
genesis               902 void ShrinkDebugFile()
genesis               903 {
genesis               904     
genesis               905     string strFile = GetDataDir() + "/debug.log";
genesis               906     FILE* file = fopen(strFile.c_str(), "r");
genesis               907     if (file && GetFilesize(file) > 10 * 1000000)
genesis               908     {
genesis               909         
genesis               910         char pch[200000];
genesis               911         fseek(file, -sizeof(pch), SEEK_END);
genesis               912         int nBytes = fread(pch, 1, sizeof(pch), file);
genesis               913         fclose(file);
genesis               914 
genesis               915         file = fopen(strFile.c_str(), "w");
genesis               916         if (file)
genesis               917         {
genesis               918             fwrite(pch, 1, nBytes, file);
genesis               919             fclose(file);
genesis               920         }
genesis               921     }
genesis               922 }
genesis               923 
genesis               924 
genesis               925 
genesis               926 
genesis               927 
genesis               928 
genesis               929 
genesis               930 
genesis               931 
genesis               932 
genesis               933 
genesis               934 
genesis               935 
genesis               936 
genesis               937 
genesis               938 static int64 nMockTime = 0;  
genesis               939 
genesis               940 int64 GetTime()
genesis               941 {
genesis               942     if (nMockTime) return nMockTime;
genesis               943 
genesis               944     return time(NULL);
genesis               945 }
genesis               946 
genesis               947 void SetMockTime(int64 nMockTimeIn)
genesis               948 {
genesis               949     nMockTime = nMockTimeIn;
genesis               950 }
genesis               951 
genesis               952 static int64 nTimeOffset = 0;
genesis               953 
genesis               954 int64 GetAdjustedTime()
genesis               955 {
genesis               956     return GetTime() + nTimeOffset;
genesis               957 }
genesis               958 
genesis               959 void AddTimeData(unsigned int ip, int64 nTime)
genesis               960 {
genesis               961     int64 nOffsetSample = nTime - GetTime();
genesis               962 
genesis               963     
genesis               964     static set<unsigned int> setKnown;
genesis               965     if (!setKnown.insert(ip).second)
genesis               966         return;
genesis               967 
genesis               968     
genesis               969     static vector<int64> vTimeOffsets;
genesis               970     if (vTimeOffsets.empty())
genesis               971         vTimeOffsets.push_back(0);
genesis               972     vTimeOffsets.push_back(nOffsetSample);
genesis               973     printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
genesis               974     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
genesis               975     {
genesis               976         sort(vTimeOffsets.begin(), vTimeOffsets.end());
genesis               977         int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
genesis               978         
genesis               979         if (abs64(nMedian) < 70 * 60)
genesis               980         {
genesis               981             nTimeOffset = nMedian;
genesis               982         }
genesis               983         else
genesis               984         {
genesis               985             nTimeOffset = 0;
genesis               986 
genesis               987             static bool fDone;
genesis               988             if (!fDone)
genesis               989             {
genesis               990                 
genesis               991                 bool fMatch = false;
genesis               992                 BOOST_FOREACH(int64 nOffset, vTimeOffsets)
genesis               993                     if (nOffset != 0 && abs64(nOffset) < 5 * 60)
genesis               994                         fMatch = true;
genesis               995 
genesis               996                 if (!fMatch)
genesis               997                 {
genesis               998                     fDone = true;
genesis               999                     string strMessage = _("Warning: Please check that your computer's date and time are correct.  If your clock is wrong Bitcoin will not work properly.");
genesis              1000                     strMiscWarning = strMessage;
genesis              1001                     printf("*** %s\n", strMessage.c_str());
genesis              1002                     boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
genesis              1003                 }
genesis              1004             }
genesis              1005         }
genesis              1006         BOOST_FOREACH(int64 n, vTimeOffsets)
genesis              1007             printf("%+"PRI64d"  ", n);
genesis              1008         printf("|  nTimeOffset = %+"PRI64d"  (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
genesis              1009     }
genesis              1010 }
genesis              1011 
genesis              1012 
genesis              1013 
genesis              1014 
genesis              1015 
genesis              1016 
genesis              1017 
genesis              1018 
genesis              1019 
genesis              1020 string FormatVersion(int nVersion)
genesis              1021 {
genesis              1022     if (nVersion%100 == 0)
genesis              1023         return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
genesis              1024     else
genesis              1025         return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
genesis              1026 }
genesis              1027 
genesis              1028 string FormatFullVersion()
genesis              1029 {
genesis              1030     string s = FormatVersion(VERSION) + pszSubVer;
genesis              1031     if (VERSION_IS_BETA) {
genesis              1032         s += "-";
genesis              1033         s += _("beta");
genesis              1034     }
genesis              1035     return s;
genesis              1036 }
genesis              1037 
genesis              1038 
genesis              1039 
genesis              1040 
genesis              1041 #ifdef DEBUG_LOCKORDER
genesis              1042 
genesis              1043 
genesis              1044 
genesis              1045 
genesis              1046 
genesis              1047 
genesis              1048 
genesis              1049 
genesis              1050 
genesis              1051 
genesis              1052 
genesis              1053 struct CLockLocation
genesis              1054 {
genesis              1055     CLockLocation(const char* pszName, const char* pszFile, int nLine)
genesis              1056     {
genesis              1057         mutexName = pszName;
genesis              1058         sourceFile = pszFile;
genesis              1059         sourceLine = nLine;
genesis              1060     }
genesis              1061 
genesis              1062     std::string ToString() const
genesis              1063     {
genesis              1064         return mutexName+"  "+sourceFile+":"+itostr(sourceLine);
genesis              1065     }
genesis              1066 
genesis              1067 private:
genesis              1068     std::string mutexName;
genesis              1069     std::string sourceFile;
genesis              1070     int sourceLine;
genesis              1071 };
genesis              1072 
genesis              1073 typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack;
genesis              1074 
genesis              1075 static boost::interprocess::interprocess_mutex dd_mutex;
genesis              1076 static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders;
genesis              1077 static boost::thread_specific_ptr<LockStack> lockstack;
genesis              1078 
genesis              1079 
genesis              1080 static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
genesis              1081 {
genesis              1082     printf("POTENTIAL DEADLOCK DETECTED\n");
genesis              1083     printf("Previous lock order was:\n");
genesis              1084     BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
genesis              1085     {
genesis              1086         if (i.first == mismatch.first) printf(" (1)");
genesis              1087         if (i.first == mismatch.second) printf(" (2)");
genesis              1088         printf(" %s\n", i.second.ToString().c_str());
genesis              1089     }
genesis              1090     printf("Current lock order is:\n");
genesis              1091     BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
genesis              1092     {
genesis              1093         if (i.first == mismatch.first) printf(" (1)");
genesis              1094         if (i.first == mismatch.second) printf(" (2)");
genesis              1095         printf(" %s\n", i.second.ToString().c_str());
genesis              1096     }
genesis              1097 }
genesis              1098 
genesis              1099 static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
genesis              1100 {
genesis              1101     bool fOrderOK = true;
genesis              1102     if (lockstack.get() == NULL)
genesis              1103         lockstack.reset(new LockStack);
genesis              1104 
genesis              1105     if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
genesis              1106     dd_mutex.lock();
genesis              1107 
genesis              1108     (*lockstack).push_back(std::make_pair(c, locklocation));
genesis              1109 
genesis              1110     BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack))
genesis              1111     {
genesis              1112         if (i.first == c) break;
genesis              1113 
genesis              1114         std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c);
genesis              1115         if (lockorders.count(p1))
genesis              1116             continue;
genesis              1117         lockorders[p1] = (*lockstack);
genesis              1118 
genesis              1119         std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
genesis              1120         if (lockorders.count(p2))
genesis              1121         {
genesis              1122             potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
genesis              1123             break;
genesis              1124         }
genesis              1125     }
genesis              1126     dd_mutex.unlock();
genesis              1127 }
genesis              1128 
genesis              1129 static void pop_lock()
genesis              1130 {
genesis              1131     if (fDebug) 
genesis              1132     {
genesis              1133         const CLockLocation& locklocation = (*lockstack).rbegin()->second;
genesis              1134         printf("Unlocked: %s\n", locklocation.ToString().c_str());
genesis              1135     }
genesis              1136     dd_mutex.lock();
genesis              1137     (*lockstack).pop_back();
genesis              1138     dd_mutex.unlock();
genesis              1139 }
genesis              1140 
genesis              1141 void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
genesis              1142 {
genesis              1143     push_lock(this, CLockLocation(pszName, pszFile, nLine));
genesis              1144     mutex.lock();
genesis              1145 }
genesis              1146 void CCriticalSection::Leave()
genesis              1147 {
genesis              1148     mutex.unlock();
genesis              1149     pop_lock();
genesis              1150 }
genesis              1151 bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine)
genesis              1152 {
genesis              1153     push_lock(this, CLockLocation(pszName, pszFile, nLine));
genesis              1154     bool result = mutex.try_lock();
genesis              1155     if (!result) pop_lock();
genesis              1156     return result;
genesis              1157 }
genesis              1158 
genesis              1159 #else
genesis              1160 
genesis              1161 void CCriticalSection::Enter(const char*, const char*, int)
genesis              1162 {
genesis              1163     mutex.lock();
genesis              1164 }
genesis              1165 
genesis              1166 void CCriticalSection::Leave()
genesis              1167 {
genesis              1168     mutex.unlock();
genesis              1169 }
genesis              1170 
genesis              1171 bool CCriticalSection::TryEnter(const char*, const char*, int)
genesis              1172 {
genesis              1173     bool result = mutex.try_lock();
genesis              1174     return result;
genesis              1175 }
genesis              1176 
genesis              1177 #endif /* DEBUG_LOCKORDER */