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;
asciilifeform_and... 23 bool fCanEat = false;
genesis 24 char pszSetDataDir[MAX_PATH] = "";
genesis 25 bool fRequestShutdown = false;
genesis 26 bool fShutdown = false;
genesis 27 bool fDaemon = false;
genesis 28 bool fServer = false;
genesis 29 bool fCommandLine = false;
genesis 30 string strMiscWarning;
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 static bool pfMkdir[4];
genesis 688 if (!pfMkdir[nVariation])
genesis 689 {
genesis 690 pfMkdir[nVariation] = true;
genesis 691 boost::filesystem::create_directory(pszDir);
genesis 692 }
genesis 693 }
genesis 694
genesis 695 string GetDataDir()
genesis 696 {
genesis 697 char pszDir[MAX_PATH];
genesis 698 GetDataDir(pszDir);
genesis 699 return pszDir;
genesis 700 }
genesis 701
genesis 702 string GetConfigFile()
genesis 703 {
genesis 704 namespace fs = boost::filesystem;
genesis 705 fs::path pathConfig(GetArg("-conf", "bitcoin.conf"));
genesis 706 if (!pathConfig.is_complete())
genesis 707 pathConfig = fs::path(GetDataDir()) / pathConfig;
genesis 708 return pathConfig.string();
genesis 709 }
genesis 710
genesis 711 void ReadConfigFile(map<string, string>& mapSettingsRet,
genesis 712 map<string, vector<string> >& mapMultiSettingsRet)
genesis 713 {
genesis 714 namespace fs = boost::filesystem;
genesis 715 namespace pod = boost::program_options::detail;
genesis 716
genesis 717 fs::ifstream streamConfig(GetConfigFile());
genesis 718 if (!streamConfig.good())
genesis 719 return;
genesis 720
genesis 721 set<string> setOptions;
genesis 722 setOptions.insert("*");
genesis 723
genesis 724 for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
genesis 725 {
genesis 726
genesis 727 string strKey = string("-") + it->string_key;
genesis 728 if (mapSettingsRet.count(strKey) == 0)
genesis 729 mapSettingsRet[strKey] = it->value[0];
genesis 730 mapMultiSettingsRet[strKey].push_back(it->value[0]);
genesis 731 }
genesis 732 }
genesis 733
genesis 734 string GetPidFile()
genesis 735 {
genesis 736 namespace fs = boost::filesystem;
genesis 737 fs::path pathConfig(GetArg("-pid", "bitcoind.pid"));
genesis 738 if (!pathConfig.is_complete())
genesis 739 pathConfig = fs::path(GetDataDir()) / pathConfig;
genesis 740 return pathConfig.string();
genesis 741 }
genesis 742
genesis 743 void CreatePidFile(string pidFile, pid_t pid)
genesis 744 {
genesis 745 FILE* file = fopen(pidFile.c_str(), "w");
genesis 746 if (file)
genesis 747 {
genesis 748 fprintf(file, "%d\n", pid);
genesis 749 fclose(file);
genesis 750 }
genesis 751 }
genesis 752
genesis 753 int GetFilesize(FILE* file)
genesis 754 {
genesis 755 int nSavePos = ftell(file);
genesis 756 int nFilesize = -1;
genesis 757 if (fseek(file, 0, SEEK_END) == 0)
genesis 758 nFilesize = ftell(file);
genesis 759 fseek(file, nSavePos, SEEK_SET);
genesis 760 return nFilesize;
genesis 761 }
genesis 762
genesis 763 void ShrinkDebugFile()
genesis 764 {
genesis 765
genesis 766 string strFile = GetDataDir() + "/debug.log";
genesis 767 FILE* file = fopen(strFile.c_str(), "r");
genesis 768 if (file && GetFilesize(file) > 10 * 1000000)
genesis 769 {
genesis 770
genesis 771 char pch[200000];
genesis 772 fseek(file, -sizeof(pch), SEEK_END);
genesis 773 int nBytes = fread(pch, 1, sizeof(pch), file);
genesis 774 fclose(file);
genesis 775
genesis 776 file = fopen(strFile.c_str(), "w");
genesis 777 if (file)
genesis 778 {
genesis 779 fwrite(pch, 1, nBytes, file);
genesis 780 fclose(file);
genesis 781 }
genesis 782 }
genesis 783 }
genesis 784
genesis 785
genesis 786
genesis 787
genesis 788
genesis 789
genesis 790
genesis 791
genesis 792
genesis 793
genesis 794
genesis 795
genesis 796
genesis 797
genesis 798
genesis 799 static int64 nMockTime = 0;
genesis 800
genesis 801 int64 GetTime()
genesis 802 {
genesis 803 if (nMockTime) return nMockTime;
genesis 804
genesis 805 return time(NULL);
genesis 806 }
genesis 807
genesis 808 void SetMockTime(int64 nMockTimeIn)
genesis 809 {
genesis 810 nMockTime = nMockTimeIn;
genesis 811 }
genesis 812
genesis 813 static int64 nTimeOffset = 0;
genesis 814
genesis 815 int64 GetAdjustedTime()
genesis 816 {
genesis 817 return GetTime() + nTimeOffset;
genesis 818 }
genesis 819
genesis 820 void AddTimeData(unsigned int ip, int64 nTime)
genesis 821 {
genesis 822 int64 nOffsetSample = nTime - GetTime();
genesis 823
genesis 824
genesis 825 static set<unsigned int> setKnown;
genesis 826 if (!setKnown.insert(ip).second)
genesis 827 return;
genesis 828
genesis 829
genesis 830 static vector<int64> vTimeOffsets;
genesis 831 if (vTimeOffsets.empty())
genesis 832 vTimeOffsets.push_back(0);
genesis 833 vTimeOffsets.push_back(nOffsetSample);
genesis 834 printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), vTimeOffsets.back(), vTimeOffsets.back()/60);
genesis 835 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
genesis 836 {
genesis 837 sort(vTimeOffsets.begin(), vTimeOffsets.end());
genesis 838 int64 nMedian = vTimeOffsets[vTimeOffsets.size()/2];
genesis 839
genesis 840 if (abs64(nMedian) < 70 * 60)
genesis 841 {
genesis 842 nTimeOffset = nMedian;
genesis 843 }
genesis 844 else
genesis 845 {
genesis 846 nTimeOffset = 0;
genesis 847
genesis 848 static bool fDone;
genesis 849 if (!fDone)
genesis 850 {
genesis 851
genesis 852 bool fMatch = false;
genesis 853 BOOST_FOREACH(int64 nOffset, vTimeOffsets)
genesis 854 if (nOffset != 0 && abs64(nOffset) < 5 * 60)
genesis 855 fMatch = true;
genesis 856
genesis 857 if (!fMatch)
genesis 858 {
genesis 859 fDone = true;
genesis 860 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 861 strMiscWarning = strMessage;
genesis 862 printf("*** %s\n", strMessage.c_str());
genesis 863 boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
genesis 864 }
genesis 865 }
genesis 866 }
genesis 867 BOOST_FOREACH(int64 n, vTimeOffsets)
genesis 868 printf("%+"PRI64d" ", n);
genesis 869 printf("| nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
genesis 870 }
genesis 871 }
genesis 872
genesis 873
genesis 874
genesis 875
genesis 876
genesis 877
genesis 878
genesis 879
genesis 880
genesis 881 string FormatVersion(int nVersion)
genesis 882 {
genesis 883 if (nVersion%100 == 0)
genesis 884 return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
genesis 885 else
genesis 886 return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
genesis 887 }
genesis 888
genesis 889 string FormatFullVersion()
genesis 890 {
genesis 891 string s = FormatVersion(VERSION) + pszSubVer;
genesis 892 if (VERSION_IS_BETA) {
genesis 893 s += "-";
genesis 894 s += _("beta");
genesis 895 }
genesis 896 return s;
genesis 897 }
genesis 898
genesis 899
genesis 900
genesis 901
genesis 902 #ifdef DEBUG_LOCKORDER
genesis 903
genesis 904
genesis 905
genesis 906
genesis 907
genesis 908
genesis 909
genesis 910
genesis 911
genesis 912
genesis 913
genesis 914 struct CLockLocation
genesis 915 {
genesis 916 CLockLocation(const char* pszName, const char* pszFile, int nLine)
genesis 917 {
genesis 918 mutexName = pszName;
genesis 919 sourceFile = pszFile;
genesis 920 sourceLine = nLine;
genesis 921 }
genesis 922
genesis 923 std::string ToString() const
genesis 924 {
genesis 925 return mutexName+" "+sourceFile+":"+itostr(sourceLine);
genesis 926 }
genesis 927
genesis 928 private:
genesis 929 std::string mutexName;
genesis 930 std::string sourceFile;
genesis 931 int sourceLine;
genesis 932 };
genesis 933
genesis 934 typedef std::vector< std::pair<CCriticalSection*, CLockLocation> > LockStack;
genesis 935
genesis 936 static boost::interprocess::interprocess_mutex dd_mutex;
genesis 937 static std::map<std::pair<CCriticalSection*, CCriticalSection*>, LockStack> lockorders;
genesis 938 static boost::thread_specific_ptr<LockStack> lockstack;
genesis 939
genesis 940
genesis 941 static void potential_deadlock_detected(const std::pair<CCriticalSection*, CCriticalSection*>& mismatch, const LockStack& s1, const LockStack& s2)
genesis 942 {
genesis 943 printf("POTENTIAL DEADLOCK DETECTED\n");
genesis 944 printf("Previous lock order was:\n");
genesis 945 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s2)
genesis 946 {
genesis 947 if (i.first == mismatch.first) printf(" (1)");
genesis 948 if (i.first == mismatch.second) printf(" (2)");
genesis 949 printf(" %s\n", i.second.ToString().c_str());
genesis 950 }
genesis 951 printf("Current lock order is:\n");
genesis 952 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, s1)
genesis 953 {
genesis 954 if (i.first == mismatch.first) printf(" (1)");
genesis 955 if (i.first == mismatch.second) printf(" (2)");
genesis 956 printf(" %s\n", i.second.ToString().c_str());
genesis 957 }
genesis 958 }
genesis 959
genesis 960 static void push_lock(CCriticalSection* c, const CLockLocation& locklocation)
genesis 961 {
genesis 962 bool fOrderOK = true;
genesis 963 if (lockstack.get() == NULL)
genesis 964 lockstack.reset(new LockStack);
genesis 965
genesis 966 if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
genesis 967 dd_mutex.lock();
genesis 968
genesis 969 (*lockstack).push_back(std::make_pair(c, locklocation));
genesis 970
genesis 971 BOOST_FOREACH(const PAIRTYPE(CCriticalSection*, CLockLocation)& i, (*lockstack))
genesis 972 {
genesis 973 if (i.first == c) break;
genesis 974
genesis 975 std::pair<CCriticalSection*, CCriticalSection*> p1 = std::make_pair(i.first, c);
genesis 976 if (lockorders.count(p1))
genesis 977 continue;
genesis 978 lockorders[p1] = (*lockstack);
genesis 979
genesis 980 std::pair<CCriticalSection*, CCriticalSection*> p2 = std::make_pair(c, i.first);
genesis 981 if (lockorders.count(p2))
genesis 982 {
genesis 983 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
genesis 984 break;
genesis 985 }
genesis 986 }
genesis 987 dd_mutex.unlock();
genesis 988 }
genesis 989
genesis 990 static void pop_lock()
genesis 991 {
genesis 992 if (fDebug)
genesis 993 {
genesis 994 const CLockLocation& locklocation = (*lockstack).rbegin()->second;
genesis 995 printf("Unlocked: %s\n", locklocation.ToString().c_str());
genesis 996 }
genesis 997 dd_mutex.lock();
genesis 998 (*lockstack).pop_back();
genesis 999 dd_mutex.unlock();
genesis 1000 }
genesis 1001
genesis 1002 void CCriticalSection::Enter(const char* pszName, const char* pszFile, int nLine)
genesis 1003 {
genesis 1004 push_lock(this, CLockLocation(pszName, pszFile, nLine));
genesis 1005 mutex.lock();
genesis 1006 }
genesis 1007 void CCriticalSection::Leave()
genesis 1008 {
genesis 1009 mutex.unlock();
genesis 1010 pop_lock();
genesis 1011 }
genesis 1012 bool CCriticalSection::TryEnter(const char* pszName, const char* pszFile, int nLine)
genesis 1013 {
genesis 1014 push_lock(this, CLockLocation(pszName, pszFile, nLine));
genesis 1015 bool result = mutex.try_lock();
genesis 1016 if (!result) pop_lock();
genesis 1017 return result;
genesis 1018 }
genesis 1019
genesis 1020 #else
genesis 1021
genesis 1022 void CCriticalSection::Enter(const char*, const char*, int)
genesis 1023 {
genesis 1024 mutex.lock();
genesis 1025 }
genesis 1026
genesis 1027 void CCriticalSection::Leave()
genesis 1028 {
genesis 1029 mutex.unlock();
genesis 1030 }
genesis 1031
genesis 1032 bool CCriticalSection::TryEnter(const char*, const char*, int)
genesis 1033 {
genesis 1034 bool result = mutex.try_lock();
genesis 1035 return result;
genesis 1036 }
genesis 1037
genesis 1038 #endif /* DEBUG_LOCKORDER */