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 */