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