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