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