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