]> Git Repo - VerusCoin.git/blame - src/util.cpp
Merge pull request #1124 from sipa/rpcobj3
[VerusCoin.git] / src / util.cpp
CommitLineData
2097c09a 1// Copyright (c) 2009-2010 Satoshi Nakamoto
88216419 2// Copyright (c) 2009-2012 The Bitcoin developers
2097c09a
WL
3// Distributed under the MIT/X11 software license, see the accompanying
4// file license.txt or http://www.opensource.org/licenses/mit-license.php.
36949554 5
ed6d0b5f 6#include "util.h"
0eeb4f5d 7#include "strlcpy.h"
ed6d0b5f 8#include "version.h"
6b6aaa16 9#include "ui_interface.h"
f8ded588 10#include <boost/algorithm/string/join.hpp>
1f29d399
WL
11
12// Work around clang compilation problem in Boost 1.46:
13// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
14// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
15// http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
16namespace boost {
17 namespace program_options {
18 std::string to_internal(const std::string&);
19 }
20}
21
0eeb4f5d
WL
22#include <boost/program_options/detail/config_file.hpp>
23#include <boost/program_options/parsers.hpp>
e8ef3da7 24#include <boost/filesystem.hpp>
0eeb4f5d
WL
25#include <boost/filesystem/fstream.hpp>
26#include <boost/interprocess/sync/interprocess_mutex.hpp>
27#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
28#include <boost/foreach.hpp>
ed6d0b5f
PW
29#include <openssl/crypto.h>
30#include <openssl/rand.h>
31
32#ifdef WIN32
33#ifdef _MSC_VER
34#pragma warning(disable:4786)
35#pragma warning(disable:4804)
36#pragma warning(disable:4805)
37#pragma warning(disable:4717)
38#endif
39#ifdef _WIN32_WINNT
40#undef _WIN32_WINNT
41#endif
42#define _WIN32_WINNT 0x0501
43#ifdef _WIN32_IE
44#undef _WIN32_IE
45#endif
46#define _WIN32_IE 0x0400
47#define WIN32_LEAN_AND_MEAN 1
48#ifndef NOMINMAX
49#define NOMINMAX
50#endif
51#include "shlobj.h"
52#include "shlwapi.h"
53#endif
2097c09a
WL
54
55using namespace std;
69d605f4 56using namespace boost;
2097c09a
WL
57
58map<string, string> mapArgs;
59map<string, vector<string> > mapMultiArgs;
60bool fDebug = false;
61bool fPrintToConsole = false;
62bool fPrintToDebugger = false;
2097c09a
WL
63bool fRequestShutdown = false;
64bool fShutdown = false;
65bool fDaemon = false;
66bool fServer = false;
67bool fCommandLine = false;
68string strMiscWarning;
69bool fTestNet = false;
70bool fNoListen = false;
71bool fLogTimestamps = false;
bde280b9 72CMedianFilter<int64> vTimeOffsets(200,0);
2097c09a 73
2097c09a
WL
74// Init openssl library multithreading support
75static boost::interprocess::interprocess_mutex** ppmutexOpenSSL;
76void locking_callback(int mode, int i, const char* file, int line)
77{
78 if (mode & CRYPTO_LOCK)
79 ppmutexOpenSSL[i]->lock();
80 else
81 ppmutexOpenSSL[i]->unlock();
82}
83
84// Init
85class CInit
86{
87public:
88 CInit()
89 {
90 // Init openssl library multithreading support
91 ppmutexOpenSSL = (boost::interprocess::interprocess_mutex**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(boost::interprocess::interprocess_mutex*));
92 for (int i = 0; i < CRYPTO_num_locks(); i++)
93 ppmutexOpenSSL[i] = new boost::interprocess::interprocess_mutex();
94 CRYPTO_set_locking_callback(locking_callback);
95
6853e627 96#ifdef WIN32
2097c09a
WL
97 // Seed random number generator with screen scrape and other hardware sources
98 RAND_screen();
99#endif
100
101 // Seed random number generator with performance counter
102 RandAddSeed();
103 }
104 ~CInit()
105 {
106 // Shutdown openssl library multithreading support
107 CRYPTO_set_locking_callback(NULL);
108 for (int i = 0; i < CRYPTO_num_locks(); i++)
109 delete ppmutexOpenSSL[i];
110 OPENSSL_free(ppmutexOpenSSL);
111 }
112}
113instance_of_cinit;
114
115
116
117
118
119
120
121
122void RandAddSeed()
123{
124 // Seed with CPU performance counter
bde280b9 125 int64 nCounter = GetPerformanceCounter();
2097c09a
WL
126 RAND_add(&nCounter, sizeof(nCounter), 1.5);
127 memset(&nCounter, 0, sizeof(nCounter));
128}
129
130void RandAddSeedPerfmon()
131{
132 RandAddSeed();
133
134 // This can take up to 2 seconds, so only do it every 10 minutes
bde280b9 135 static int64 nLastPerfmon;
2097c09a
WL
136 if (GetTime() < nLastPerfmon + 10 * 60)
137 return;
138 nLastPerfmon = GetTime();
139
6853e627 140#ifdef WIN32
2097c09a
WL
141 // Don't need this on Linux, OpenSSL automatically uses /dev/urandom
142 // Seed with the entire set of perfmon data
143 unsigned char pdata[250000];
144 memset(pdata, 0, sizeof(pdata));
145 unsigned long nSize = sizeof(pdata);
146 long ret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, pdata, &nSize);
147 RegCloseKey(HKEY_PERFORMANCE_DATA);
148 if (ret == ERROR_SUCCESS)
149 {
150 RAND_add(pdata, nSize, nSize/100.0);
151 memset(pdata, 0, nSize);
152 printf("%s RandAddSeed() %d bytes\n", DateTimeStrFormat("%x %H:%M", GetTime()).c_str(), nSize);
153 }
154#endif
155}
156
bde280b9 157uint64 GetRand(uint64 nMax)
2097c09a
WL
158{
159 if (nMax == 0)
160 return 0;
161
162 // The range of the random source must be a multiple of the modulus
163 // to give every possible output value an equal possibility
bde280b9
WL
164 uint64 nRange = (std::numeric_limits<uint64>::max() / nMax) * nMax;
165 uint64 nRand = 0;
2097c09a
WL
166 do
167 RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
168 while (nRand >= nRange);
169 return (nRand % nMax);
170}
171
172int GetRandInt(int nMax)
173{
174 return GetRand(nMax);
175}
176
177
178
179
180
181
182
183
184
185
186
187inline int OutputDebugStringF(const char* pszFormat, ...)
188{
189 int ret = 0;
190 if (fPrintToConsole)
191 {
192 // print to console
193 va_list arg_ptr;
194 va_start(arg_ptr, pszFormat);
195 ret = vprintf(pszFormat, arg_ptr);
196 va_end(arg_ptr);
197 }
198 else
199 {
200 // print to debug.log
201 static FILE* fileout = NULL;
202
203 if (!fileout)
204 {
ee12c3d6
PW
205 boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
206 fileout = fopen(pathDebug.string().c_str(), "a");
2097c09a
WL
207 if (fileout) setbuf(fileout, NULL); // unbuffered
208 }
209 if (fileout)
210 {
211 static bool fStartedNewLine = true;
212
213 // Debug print useful for profiling
214 if (fLogTimestamps && fStartedNewLine)
215 fprintf(fileout, "%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
216 if (pszFormat[strlen(pszFormat) - 1] == '\n')
217 fStartedNewLine = true;
218 else
219 fStartedNewLine = false;
220
221 va_list arg_ptr;
222 va_start(arg_ptr, pszFormat);
223 ret = vfprintf(fileout, pszFormat, arg_ptr);
224 va_end(arg_ptr);
225 }
226 }
227
6853e627 228#ifdef WIN32
2097c09a
WL
229 if (fPrintToDebugger)
230 {
231 static CCriticalSection cs_OutputDebugStringF;
232
233 // accumulate a line at a time
2097c09a 234 {
f8dcd5ca 235 LOCK(cs_OutputDebugStringF);
2097c09a
WL
236 static char pszBuffer[50000];
237 static char* pend;
238 if (pend == NULL)
239 pend = pszBuffer;
240 va_list arg_ptr;
241 va_start(arg_ptr, pszFormat);
242 int limit = END(pszBuffer) - pend - 2;
243 int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);
244 va_end(arg_ptr);
245 if (ret < 0 || ret >= limit)
246 {
247 pend = END(pszBuffer) - 2;
248 *pend++ = '\n';
249 }
250 else
251 pend += ret;
252 *pend = '\0';
253 char* p1 = pszBuffer;
254 char* p2;
255 while (p2 = strchr(p1, '\n'))
256 {
257 p2++;
258 char c = *p2;
259 *p2 = '\0';
260 OutputDebugStringA(p1);
261 *p2 = c;
262 p1 = p2;
263 }
264 if (p1 != pszBuffer)
265 memmove(pszBuffer, p1, pend - p1 + 1);
266 pend -= (p1 - pszBuffer);
267 }
268 }
269#endif
270 return ret;
271}
272
273
274// Safer snprintf
275// - prints up to limit-1 characters
276// - output string is always null terminated even if limit reached
277// - return value is the number of characters actually printed
278int my_snprintf(char* buffer, size_t limit, const char* format, ...)
279{
280 if (limit == 0)
281 return 0;
282 va_list arg_ptr;
283 va_start(arg_ptr, format);
284 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
285 va_end(arg_ptr);
286 if (ret < 0 || ret >= limit)
287 {
288 ret = limit - 1;
289 buffer[limit-1] = 0;
290 }
291 return ret;
292}
293
52d3a481 294string real_strprintf(const std::string &format, int dummy, ...)
2097c09a
WL
295{
296 char buffer[50000];
297 char* p = buffer;
298 int limit = sizeof(buffer);
299 int ret;
300 loop
301 {
302 va_list arg_ptr;
52d3a481 303 va_start(arg_ptr, dummy);
39cf857d 304 ret = _vsnprintf(p, limit, format.c_str(), arg_ptr);
2097c09a
WL
305 va_end(arg_ptr);
306 if (ret >= 0 && ret < limit)
307 break;
308 if (p != buffer)
822f2e3d 309 delete[] p;
2097c09a
WL
310 limit *= 2;
311 p = new char[limit];
312 if (p == NULL)
313 throw std::bad_alloc();
314 }
315 string str(p, p+ret);
316 if (p != buffer)
822f2e3d 317 delete[] p;
2097c09a
WL
318 return str;
319}
320
52d3a481 321bool error(const char *format, ...)
2097c09a
WL
322{
323 char buffer[50000];
324 int limit = sizeof(buffer);
325 va_list arg_ptr;
326 va_start(arg_ptr, format);
52d3a481 327 int ret = _vsnprintf(buffer, limit, format, arg_ptr);
2097c09a
WL
328 va_end(arg_ptr);
329 if (ret < 0 || ret >= limit)
330 {
2097c09a
WL
331 buffer[limit-1] = 0;
332 }
333 printf("ERROR: %s\n", buffer);
334 return false;
335}
336
337
338void ParseString(const string& str, char c, vector<string>& v)
339{
340 if (str.empty())
341 return;
342 string::size_type i1 = 0;
343 string::size_type i2;
344 loop
345 {
346 i2 = str.find(c, i1);
347 if (i2 == str.npos)
348 {
349 v.push_back(str.substr(i1));
350 return;
351 }
352 v.push_back(str.substr(i1, i2-i1));
353 i1 = i2+1;
354 }
355}
356
357
bde280b9 358string FormatMoney(int64 n, bool fPlus)
2097c09a
WL
359{
360 // Note: not using straight sprintf here because we do NOT want
361 // localized number formatting.
bde280b9
WL
362 int64 n_abs = (n > 0 ? n : -n);
363 int64 quotient = n_abs/COIN;
364 int64 remainder = n_abs%COIN;
2097c09a
WL
365 string str = strprintf("%"PRI64d".%08"PRI64d, quotient, remainder);
366
367 // Right-trim excess 0's before the decimal point:
368 int nTrim = 0;
369 for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
370 ++nTrim;
371 if (nTrim)
372 str.erase(str.size()-nTrim, nTrim);
373
2097c09a
WL
374 if (n < 0)
375 str.insert((unsigned int)0, 1, '-');
376 else if (fPlus && n > 0)
377 str.insert((unsigned int)0, 1, '+');
378 return str;
379}
380
381
bde280b9 382bool ParseMoney(const string& str, int64& nRet)
2097c09a
WL
383{
384 return ParseMoney(str.c_str(), nRet);
385}
386
bde280b9 387bool ParseMoney(const char* pszIn, int64& nRet)
2097c09a
WL
388{
389 string strWhole;
bde280b9 390 int64 nUnits = 0;
2097c09a
WL
391 const char* p = pszIn;
392 while (isspace(*p))
393 p++;
394 for (; *p; p++)
395 {
2097c09a
WL
396 if (*p == '.')
397 {
398 p++;
bde280b9 399 int64 nMult = CENT*10;
2097c09a
WL
400 while (isdigit(*p) && (nMult > 0))
401 {
402 nUnits += nMult * (*p++ - '0');
403 nMult /= 10;
404 }
405 break;
406 }
407 if (isspace(*p))
408 break;
409 if (!isdigit(*p))
410 return false;
411 strWhole.insert(strWhole.end(), *p);
412 }
413 for (; *p; p++)
414 if (!isspace(*p))
415 return false;
2f7f2a5f 416 if (strWhole.size() > 10) // guard against 63 bit overflow
2097c09a
WL
417 return false;
418 if (nUnits < 0 || nUnits > COIN)
419 return false;
bde280b9
WL
420 int64 nWhole = atoi64(strWhole);
421 int64 nValue = nWhole*COIN + nUnits;
2097c09a
WL
422
423 nRet = nValue;
424 return true;
425}
426
427
8c8e8c2e 428static signed char phexdigit[256] =
922e8e29
GA
429{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
430 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
431 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
432 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
433 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
434 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
a6fa147c 435 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
922e8e29
GA
436 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
437 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
438 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
439 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
440 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
441 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
442 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
443 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
444 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
445
446bool IsHex(const string& str)
2097c09a 447{
922e8e29
GA
448 BOOST_FOREACH(unsigned char c, str)
449 {
450 if (phexdigit[c] < 0)
451 return false;
452 }
453 return (str.size() > 0) && (str.size()%2 == 0);
454}
2097c09a 455
922e8e29
GA
456vector<unsigned char> ParseHex(const char* psz)
457{
2097c09a
WL
458 // convert hex dump to vector
459 vector<unsigned char> vch;
460 loop
461 {
462 while (isspace(*psz))
463 psz++;
8c8e8c2e
DL
464 signed char c = phexdigit[(unsigned char)*psz++];
465 if (c == (signed char)-1)
2097c09a
WL
466 break;
467 unsigned char n = (c << 4);
468 c = phexdigit[(unsigned char)*psz++];
8c8e8c2e 469 if (c == (signed char)-1)
2097c09a
WL
470 break;
471 n |= c;
472 vch.push_back(n);
473 }
474 return vch;
475}
476
477vector<unsigned char> ParseHex(const string& str)
478{
479 return ParseHex(str.c_str());
480}
481
d64e124c
CM
482static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
483{
484 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
485 if (name.find("-no") == 0)
486 {
487 std::string positive("-");
488 positive.append(name.begin()+3, name.end());
489 if (mapSettingsRet.count(positive) == 0)
490 {
491 bool value = !GetBoolArg(name);
492 mapSettingsRet[positive] = (value ? "1" : "0");
493 }
494 }
495}
496
3ae07355 497void ParseParameters(int argc, const char*const argv[])
2097c09a
WL
498{
499 mapArgs.clear();
500 mapMultiArgs.clear();
501 for (int i = 1; i < argc; i++)
502 {
503 char psz[10000];
504 strlcpy(psz, argv[i], sizeof(psz));
505 char* pszValue = (char*)"";
506 if (strchr(psz, '='))
507 {
508 pszValue = strchr(psz, '=');
509 *pszValue++ = '\0';
510 }
6853e627 511 #ifdef WIN32
2097c09a
WL
512 _strlwr(psz);
513 if (psz[0] == '/')
514 psz[0] = '-';
515 #endif
516 if (psz[0] != '-')
517 break;
3ad9f8a7 518
2097c09a
WL
519 mapArgs[psz] = pszValue;
520 mapMultiArgs[psz].push_back(pszValue);
521 }
3ad9f8a7
GA
522
523 // New 0.6 features:
524 BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
525 {
526 string name = entry.first;
527
528 // interpret --foo as -foo (as long as both are not set)
529 if (name.find("--") == 0)
530 {
531 std::string singleDash(name.begin()+1, name.end());
532 if (mapArgs.count(singleDash) == 0)
533 mapArgs[singleDash] = entry.second;
534 name = singleDash;
535 }
536
d64e124c
CM
537 // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
538 InterpretNegativeSetting(name, mapArgs);
3ad9f8a7 539 }
2097c09a
WL
540}
541
3ae07355
GA
542std::string GetArg(const std::string& strArg, const std::string& strDefault)
543{
544 if (mapArgs.count(strArg))
545 return mapArgs[strArg];
546 return strDefault;
547}
548
549int64 GetArg(const std::string& strArg, int64 nDefault)
550{
551 if (mapArgs.count(strArg))
552 return atoi64(mapArgs[strArg]);
553 return nDefault;
554}
555
556bool GetBoolArg(const std::string& strArg, bool fDefault)
557{
558 if (mapArgs.count(strArg))
559 {
560 if (mapArgs[strArg].empty())
561 return true;
562 return (atoi(mapArgs[strArg]) != 0);
563 }
564 return fDefault;
565}
566
0fcf91ea
GA
567bool SoftSetArg(const std::string& strArg, const std::string& strValue)
568{
569 if (mapArgs.count(strArg))
570 return false;
571 mapArgs[strArg] = strValue;
572 return true;
573}
574
7bf8b7c2 575bool SoftSetBoolArg(const std::string& strArg, bool fValue)
0fcf91ea
GA
576{
577 if (fValue)
578 return SoftSetArg(strArg, std::string("1"));
579 else
580 return SoftSetArg(strArg, std::string("0"));
581}
582
583
4b603f1c 584string EncodeBase64(const unsigned char* pch, size_t len)
4e67a621 585{
4b603f1c
PW
586 static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
587
588 string strRet="";
589 strRet.reserve((len+2)/3*4);
590
591 int mode=0, left=0;
592 const unsigned char *pchEnd = pch+len;
593
594 while (pch<pchEnd)
595 {
596 int enc = *(pch++);
597 switch (mode)
598 {
599 case 0: // we have no bits
600 strRet += pbase64[enc >> 2];
601 left = (enc & 3) << 4;
602 mode = 1;
603 break;
604
605 case 1: // we have two bits
606 strRet += pbase64[left | (enc >> 4)];
607 left = (enc & 15) << 2;
608 mode = 2;
609 break;
610
611 case 2: // we have four bits
612 strRet += pbase64[left | (enc >> 6)];
613 strRet += pbase64[enc & 63];
614 mode = 0;
615 break;
616 }
617 }
618
619 if (mode)
620 {
621 strRet += pbase64[left];
622 strRet += '=';
623 if (mode == 1)
624 strRet += '=';
625 }
626
627 return strRet;
628}
629
630string EncodeBase64(const string& str)
4e67a621 631{
4b603f1c
PW
632 return EncodeBase64((const unsigned char*)str.c_str(), str.size());
633}
4e67a621 634
4b603f1c
PW
635vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
636{
637 static const int decode64_table[256] =
638 {
639 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
640 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
641 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
642 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
643 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
644 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
645 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
646 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
647 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
648 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
649 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
650 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
651 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
652 };
653
654 if (pfInvalid)
655 *pfInvalid = false;
656
657 vector<unsigned char> vchRet;
658 vchRet.reserve(strlen(p)*3/4);
659
660 int mode = 0;
661 int left = 0;
662
663 while (1)
4e67a621 664 {
8add7822 665 int dec = decode64_table[(unsigned char)*p];
4b603f1c
PW
666 if (dec == -1) break;
667 p++;
668 switch (mode)
4e67a621
J
669 {
670 case 0: // we have no bits and get 6
671 left = dec;
672 mode = 1;
673 break;
674
675 case 1: // we have 6 bits and keep 4
4b603f1c 676 vchRet.push_back((left<<2) | (dec>>4));
4e67a621
J
677 left = dec & 15;
678 mode = 2;
679 break;
4b603f1c
PW
680
681 case 2: // we have 4 bits and get 6, we keep 2
682 vchRet.push_back((left<<4) | (dec>>2));
4e67a621
J
683 left = dec & 3;
684 mode = 3;
685 break;
4b603f1c 686
4e67a621 687 case 3: // we have 2 bits and get 6
4b603f1c
PW
688 vchRet.push_back((left<<6) | dec);
689 mode = 0;
4e67a621
J
690 break;
691 }
692 }
693
4b603f1c
PW
694 if (pfInvalid)
695 switch (mode)
696 {
697 case 0: // 4n base64 characters processed: ok
698 break;
699
700 case 1: // 4n+1 base64 character processed: impossible
701 *pfInvalid = true;
702 break;
703
704 case 2: // 4n+2 base64 characters processed: require '=='
8add7822 705 if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1)
4b603f1c
PW
706 *pfInvalid = true;
707 break;
708
709 case 3: // 4n+3 base64 characters processed: require '='
8add7822 710 if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1)
4b603f1c
PW
711 *pfInvalid = true;
712 break;
713 }
714
715 return vchRet;
4e67a621
J
716}
717
4b603f1c
PW
718string DecodeBase64(const string& str)
719{
720 vector<unsigned char> vchRet = DecodeBase64(str.c_str());
721 return string((const char*)&vchRet[0], vchRet.size());
722}
2097c09a 723
2097c09a
WL
724
725bool WildcardMatch(const char* psz, const char* mask)
726{
727 loop
728 {
729 switch (*mask)
730 {
731 case '\0':
732 return (*psz == '\0');
733 case '*':
734 return WildcardMatch(psz, mask+1) || (*psz && WildcardMatch(psz+1, mask));
735 case '?':
736 if (*psz == '\0')
737 return false;
738 break;
739 default:
740 if (*psz != *mask)
741 return false;
742 break;
743 }
744 psz++;
745 mask++;
746 }
747}
748
749bool WildcardMatch(const string& str, const string& mask)
750{
751 return WildcardMatch(str.c_str(), mask.c_str());
752}
753
754
755
756
757
758
759
760
761void FormatException(char* pszMessage, std::exception* pex, const char* pszThread)
762{
6853e627 763#ifdef WIN32
2097c09a
WL
764 char pszModule[MAX_PATH];
765 pszModule[0] = '\0';
766 GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
767#else
768 const char* pszModule = "bitcoin";
769#endif
770 if (pex)
771 snprintf(pszMessage, 1000,
772 "EXCEPTION: %s \n%s \n%s in %s \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
773 else
774 snprintf(pszMessage, 1000,
775 "UNKNOWN EXCEPTION \n%s in %s \n", pszModule, pszThread);
776}
777
778void LogException(std::exception* pex, const char* pszThread)
779{
780 char pszMessage[10000];
781 FormatException(pszMessage, pex, pszThread);
782 printf("\n%s", pszMessage);
783}
784
785void PrintException(std::exception* pex, const char* pszThread)
786{
787 char pszMessage[10000];
788 FormatException(pszMessage, pex, pszThread);
789 printf("\n\n************************\n%s\n", pszMessage);
790 fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
791 strMiscWarning = pszMessage;
2097c09a
WL
792 throw;
793}
794
2097c09a
WL
795void PrintExceptionContinue(std::exception* pex, const char* pszThread)
796{
797 char pszMessage[10000];
798 FormatException(pszMessage, pex, pszThread);
799 printf("\n\n************************\n%s\n", pszMessage);
800 fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
801 strMiscWarning = pszMessage;
2097c09a
WL
802}
803
6853e627 804#ifdef WIN32
ee12c3d6 805boost::filesystem::path MyGetSpecialFolderPath(int nFolder, bool fCreate)
2097c09a 806{
ee12c3d6
PW
807 namespace fs = boost::filesystem;
808
21ae37d2
WL
809 char pszPath[MAX_PATH] = "";
810 if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
2097c09a 811 {
ee12c3d6 812 return fs::path(pszPath);
2097c09a 813 }
21ae37d2 814 else if (nFolder == CSIDL_STARTUP)
2097c09a 815 {
ee12c3d6 816 return fs::path(getenv("USERPROFILE")) / "Start Menu" / "Programs" / "Startup";
2097c09a 817 }
21ae37d2
WL
818 else if (nFolder == CSIDL_APPDATA)
819 {
ee12c3d6 820 return fs::path(getenv("APPDATA"));
21ae37d2 821 }
ee12c3d6 822 return fs::path("");
2097c09a
WL
823}
824#endif
825
ee12c3d6 826boost::filesystem::path GetDefaultDataDir()
2097c09a 827{
ee12c3d6
PW
828 namespace fs = boost::filesystem;
829
2097c09a
WL
830 // Windows: C:\Documents and Settings\username\Application Data\Bitcoin
831 // Mac: ~/Library/Application Support/Bitcoin
832 // Unix: ~/.bitcoin
6853e627 833#ifdef WIN32
2097c09a 834 // Windows
ee12c3d6 835 return MyGetSpecialFolderPath(CSIDL_APPDATA, true) / "Bitcoin";
2097c09a 836#else
ee12c3d6 837 fs::path pathRet;
2097c09a
WL
838 char* pszHome = getenv("HOME");
839 if (pszHome == NULL || strlen(pszHome) == 0)
ee12c3d6
PW
840 pathRet = fs::path("/");
841 else
842 pathRet = fs::path(pszHome);
6853e627 843#ifdef MAC_OSX
2097c09a 844 // Mac
940e22fd 845 pathRet /= "Library/Application Support";
ee12c3d6
PW
846 filesystem::create_directory(pathRet);
847 return pathRet / "Bitcoin";
2097c09a
WL
848#else
849 // Unix
ee12c3d6 850 return pathRet / ".bitcoin";
2097c09a
WL
851#endif
852#endif
853}
854
ee12c3d6 855const boost::filesystem::path &GetDataDir(bool fNetSpecific)
2097c09a 856{
ee12c3d6
PW
857 namespace fs = boost::filesystem;
858
859 static fs::path pathCached[2];
860 static CCriticalSection csPathCached;
861 static bool cachedPath[2] = {false, false};
862
863 fs::path &path = pathCached[fNetSpecific];
864
865 // This can be called during exceptions by printf, so we cache the
866 // value so we don't have to do memory allocations after that.
867 if (cachedPath[fNetSpecific])
868 return path;
869
870 LOCK(csPathCached);
871
872 if (mapArgs.count("-datadir")) {
873 path = mapArgs["-datadir"];
874 } else {
875 path = GetDefaultDataDir();
2097c09a 876 }
7a743148
PW
877 if (fNetSpecific && GetBoolArg("-testnet", false))
878 path /= "testnet";
2097c09a 879
ee12c3d6
PW
880 fs::create_directory(path);
881
882 cachedPath[fNetSpecific]=true;
883 return path;
2097c09a
WL
884}
885
ee12c3d6 886boost::filesystem::path GetConfigFile()
2097c09a
WL
887{
888 namespace fs = boost::filesystem;
36949554
PK
889
890 fs::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
ee12c3d6
PW
891 if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
892 return pathConfigFile;
2097c09a
WL
893}
894
3f8cb2c5 895bool ReadConfigFile(map<string, string>& mapSettingsRet,
2097c09a
WL
896 map<string, vector<string> >& mapMultiSettingsRet)
897{
898 namespace fs = boost::filesystem;
899 namespace pod = boost::program_options::detail;
900
901 fs::ifstream streamConfig(GetConfigFile());
902 if (!streamConfig.good())
3f8cb2c5 903 return true; // No bitcoin.conf file is OK
2097c09a
WL
904
905 set<string> setOptions;
906 setOptions.insert("*");
ee12c3d6 907
2097c09a
WL
908 for (pod::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
909 {
910 // Don't overwrite existing settings so command line settings override bitcoin.conf
911 string strKey = string("-") + it->string_key;
912 if (mapSettingsRet.count(strKey) == 0)
d64e124c 913 {
2097c09a 914 mapSettingsRet[strKey] = it->value[0];
d64e124c
CM
915 // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
916 InterpretNegativeSetting(strKey, mapSettingsRet);
917 }
2097c09a
WL
918 mapMultiSettingsRet[strKey].push_back(it->value[0]);
919 }
3f8cb2c5 920 return true;
2097c09a
WL
921}
922
ee12c3d6 923boost::filesystem::path GetPidFile()
2097c09a
WL
924{
925 namespace fs = boost::filesystem;
36949554
PK
926
927 fs::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
ee12c3d6
PW
928 if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
929 return pathPidFile;
2097c09a
WL
930}
931
ee12c3d6 932void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
2097c09a 933{
ee12c3d6 934 FILE* file = fopen(path.string().c_str(), "w");
f85c0974 935 if (file)
2097c09a
WL
936 {
937 fprintf(file, "%d\n", pid);
938 fclose(file);
939 }
940}
941
942int GetFilesize(FILE* file)
943{
944 int nSavePos = ftell(file);
945 int nFilesize = -1;
946 if (fseek(file, 0, SEEK_END) == 0)
947 nFilesize = ftell(file);
948 fseek(file, nSavePos, SEEK_SET);
949 return nFilesize;
950}
951
952void ShrinkDebugFile()
953{
954 // Scroll debug.log if it's getting too big
ee12c3d6
PW
955 boost::filesystem::path pathLog = GetDataDir() / "debug.log";
956 FILE* file = fopen(pathLog.string().c_str(), "r");
2097c09a
WL
957 if (file && GetFilesize(file) > 10 * 1000000)
958 {
959 // Restart the file with some of the end
960 char pch[200000];
961 fseek(file, -sizeof(pch), SEEK_END);
962 int nBytes = fread(pch, 1, sizeof(pch), file);
963 fclose(file);
f85c0974 964
ee12c3d6 965 file = fopen(pathLog.string().c_str(), "w");
f85c0974 966 if (file)
2097c09a
WL
967 {
968 fwrite(pch, 1, nBytes, file);
969 fclose(file);
970 }
971 }
972}
973
974
975
976
977
978
979
980
981//
982// "Never go to sea with two chronometers; take one or three."
983// Our three time sources are:
984// - System clock
985// - Median of other nodes's clocks
986// - The user (asking the user to fix the system clock if the first two disagree)
987//
bde280b9 988static int64 nMockTime = 0; // For unit testing
54d02f15 989
bde280b9 990int64 GetTime()
2097c09a 991{
54d02f15
GA
992 if (nMockTime) return nMockTime;
993
2097c09a
WL
994 return time(NULL);
995}
996
bde280b9 997void SetMockTime(int64 nMockTimeIn)
54d02f15
GA
998{
999 nMockTime = nMockTimeIn;
1000}
1001
bde280b9 1002static int64 nTimeOffset = 0;
2097c09a 1003
bde280b9 1004int64 GetAdjustedTime()
2097c09a
WL
1005{
1006 return GetTime() + nTimeOffset;
1007}
1008
67a42f92 1009void AddTimeData(const CNetAddr& ip, int64 nTime)
2097c09a 1010{
bde280b9 1011 int64 nOffsetSample = nTime - GetTime();
2097c09a
WL
1012
1013 // Ignore duplicates
67a42f92 1014 static set<CNetAddr> setKnown;
2097c09a
WL
1015 if (!setKnown.insert(ip).second)
1016 return;
1017
1018 // Add data
1c4aab92
MH
1019 vTimeOffsets.input(nOffsetSample);
1020 printf("Added time data, samples %d, offset %+"PRI64d" (%+"PRI64d" minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
2097c09a
WL
1021 if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
1022 {
bde280b9
WL
1023 int64 nMedian = vTimeOffsets.median();
1024 std::vector<int64> vSorted = vTimeOffsets.sorted();
2097c09a
WL
1025 // Only let other nodes change our time by so much
1026 if (abs64(nMedian) < 70 * 60)
1027 {
1028 nTimeOffset = nMedian;
1029 }
1030 else
1031 {
1032 nTimeOffset = 0;
1033
1034 static bool fDone;
1035 if (!fDone)
1036 {
1037 // If nobody has a time different than ours but within 5 minutes of ours, give a warning
1038 bool fMatch = false;
bde280b9 1039 BOOST_FOREACH(int64 nOffset, vSorted)
2097c09a
WL
1040 if (nOffset != 0 && abs64(nOffset) < 5 * 60)
1041 fMatch = true;
1042
1043 if (!fMatch)
1044 {
1045 fDone = true;
1046 string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
1047 strMiscWarning = strMessage;
1048 printf("*** %s\n", strMessage.c_str());
7cfbe1fe 1049 ThreadSafeMessageBox(strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION);
2097c09a
WL
1050 }
1051 }
1052 }
5e1ddc42 1053 if (fDebug) {
bde280b9 1054 BOOST_FOREACH(int64 n, vSorted)
5e1ddc42
MH
1055 printf("%+"PRI64d" ", n);
1056 printf("| ");
1057 }
1058 printf("nTimeOffset = %+"PRI64d" (%+"PRI64d" minutes)\n", nTimeOffset, nTimeOffset/60);
2097c09a
WL
1059 }
1060}
1061
1062
1063
1064
1065
1066
1067
1068
2097c09a
WL
1069string FormatVersion(int nVersion)
1070{
1071 if (nVersion%100 == 0)
1072 return strprintf("%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100);
1073 else
1074 return strprintf("%d.%d.%d.%d", nVersion/1000000, (nVersion/10000)%100, (nVersion/100)%100, nVersion%100);
1075}
1076
1077string FormatFullVersion()
1078{
a20c0d0f 1079 return CLIENT_BUILD;
2097c09a
WL
1080}
1081
f8ded588
GA
1082// Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
1083std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
1084{
1085 std::ostringstream ss;
1086 ss << "/";
1087 ss << name << ":" << FormatVersion(nClientVersion);
1088 if (!comments.empty())
1089 ss << "(" << boost::algorithm::join(comments, "; ") << ")";
1090 ss << "/";
1091 return ss.str();
1092}
2097c09a 1093
ed6d0b5f
PW
1094#ifdef WIN32
1095boost::filesystem::path static StartupShortcutPath()
1096{
1097 return MyGetSpecialFolderPath(CSIDL_STARTUP, true) / "Bitcoin.lnk";
1098}
1099
1100bool GetStartOnSystemStartup()
1101{
1102 return filesystem::exists(StartupShortcutPath());
1103}
1104
1105bool SetStartOnSystemStartup(bool fAutoStart)
1106{
1107 // If the shortcut exists already, remove it for updating
1108 boost::filesystem::remove(StartupShortcutPath());
1109
1110 if (fAutoStart)
1111 {
1112 CoInitialize(NULL);
1113
1114 // Get a pointer to the IShellLink interface.
1115 IShellLink* psl = NULL;
1116 HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL,
1117 CLSCTX_INPROC_SERVER, IID_IShellLink,
1118 reinterpret_cast<void**>(&psl));
1119
1120 if (SUCCEEDED(hres))
1121 {
1122 // Get the current executable path
1123 TCHAR pszExePath[MAX_PATH];
1124 GetModuleFileName(NULL, pszExePath, sizeof(pszExePath));
1125
1126 TCHAR pszArgs[5] = TEXT("-min");
1127
1128 // Set the path to the shortcut target
1129 psl->SetPath(pszExePath);
1130 PathRemoveFileSpec(pszExePath);
1131 psl->SetWorkingDirectory(pszExePath);
1132 psl->SetShowCmd(SW_SHOWMINNOACTIVE);
1133 psl->SetArguments(pszArgs);
1134
1135 // Query IShellLink for the IPersistFile interface for
1136 // saving the shortcut in persistent storage.
1137 IPersistFile* ppf = NULL;
1138 hres = psl->QueryInterface(IID_IPersistFile,
1139 reinterpret_cast<void**>(&ppf));
1140 if (SUCCEEDED(hres))
1141 {
1142 WCHAR pwsz[MAX_PATH];
1143 // Ensure that the string is ANSI.
1144 MultiByteToWideChar(CP_ACP, 0, StartupShortcutPath().string().c_str(), -1, pwsz, MAX_PATH);
1145 // Save the link by calling IPersistFile::Save.
1146 hres = ppf->Save(pwsz, TRUE);
1147 ppf->Release();
1148 psl->Release();
1149 CoUninitialize();
1150 return true;
1151 }
1152 psl->Release();
1153 }
1154 CoUninitialize();
1155 return false;
1156 }
1157 return true;
1158}
1159
1160#elif defined(LINUX)
1161
1162// Follow the Desktop Application Autostart Spec:
1163// http://standards.freedesktop.org/autostart-spec/autostart-spec-latest.html
1164
1165boost::filesystem::path static GetAutostartDir()
1166{
1167 namespace fs = boost::filesystem;
1168
1169 char* pszConfigHome = getenv("XDG_CONFIG_HOME");
1170 if (pszConfigHome) return fs::path(pszConfigHome) / "autostart";
1171 char* pszHome = getenv("HOME");
1172 if (pszHome) return fs::path(pszHome) / ".config" / "autostart";
1173 return fs::path();
1174}
1175
1176boost::filesystem::path static GetAutostartFilePath()
1177{
1178 return GetAutostartDir() / "bitcoin.desktop";
1179}
1180
1181bool GetStartOnSystemStartup()
1182{
1183 boost::filesystem::ifstream optionFile(GetAutostartFilePath());
1184 if (!optionFile.good())
1185 return false;
1186 // Scan through file for "Hidden=true":
1187 string line;
1188 while (!optionFile.eof())
1189 {
1190 getline(optionFile, line);
1191 if (line.find("Hidden") != string::npos &&
1192 line.find("true") != string::npos)
1193 return false;
1194 }
1195 optionFile.close();
1196
1197 return true;
1198}
1199
1200bool SetStartOnSystemStartup(bool fAutoStart)
1201{
1202 if (!fAutoStart)
1203 boost::filesystem::remove(GetAutostartFilePath());
1204 else
1205 {
1206 char pszExePath[MAX_PATH+1];
1207 memset(pszExePath, 0, sizeof(pszExePath));
1208 if (readlink("/proc/self/exe", pszExePath, sizeof(pszExePath)-1) == -1)
1209 return false;
1210
1211 boost::filesystem::create_directories(GetAutostartDir());
1212
1213 boost::filesystem::ofstream optionFile(GetAutostartFilePath(), ios_base::out|ios_base::trunc);
1214 if (!optionFile.good())
1215 return false;
1216 // Write a bitcoin.desktop file to the autostart directory:
1217 optionFile << "[Desktop Entry]\n";
1218 optionFile << "Type=Application\n";
1219 optionFile << "Name=Bitcoin\n";
1220 optionFile << "Exec=" << pszExePath << " -min\n";
1221 optionFile << "Terminal=false\n";
1222 optionFile << "Hidden=false\n";
1223 optionFile.close();
1224 }
1225 return true;
1226}
1227#else
1228
1229// TODO: OSX startup stuff; see:
1230// http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPSystemStartup/Articles/CustomLogin.html
1231
1232bool GetStartOnSystemStartup() { return false; }
1233bool SetStartOnSystemStartup(bool fAutoStart) { return false; }
1234
1235#endif
1236
2097c09a
WL
1237
1238
865ed8a1
GA
1239#ifdef DEBUG_LOCKORDER
1240//
1241// Early deadlock detection.
1242// Problem being solved:
1243// Thread 1 locks A, then B, then C
1244// Thread 2 locks D, then C, then A
1245// --> may result in deadlock between the two threads, depending on when they run.
1246// Solution implemented here:
1247// Keep track of pairs of locks: (A before B), (A before C), etc.
1248// Complain if any thread trys to lock in a different order.
1249//
1250
1251struct CLockLocation
1252{
865ed8a1
GA
1253 CLockLocation(const char* pszName, const char* pszFile, int nLine)
1254 {
1255 mutexName = pszName;
1256 sourceFile = pszFile;
1257 sourceLine = nLine;
1258 }
c591cc50
GA
1259
1260 std::string ToString() const
1261 {
1262 return mutexName+" "+sourceFile+":"+itostr(sourceLine);
1263 }
1264
1265private:
1266 std::string mutexName;
1267 std::string sourceFile;
1268 int sourceLine;
865ed8a1
GA
1269};
1270
908037fe 1271typedef std::vector< std::pair<void*, CLockLocation> > LockStack;
865ed8a1
GA
1272
1273static boost::interprocess::interprocess_mutex dd_mutex;
908037fe 1274static std::map<std::pair<void*, void*>, LockStack> lockorders;
865ed8a1
GA
1275static boost::thread_specific_ptr<LockStack> lockstack;
1276
1277
908037fe 1278static void potential_deadlock_detected(const std::pair<void*, void*>& mismatch, const LockStack& s1, const LockStack& s2)
865ed8a1
GA
1279{
1280 printf("POTENTIAL DEADLOCK DETECTED\n");
1281 printf("Previous lock order was:\n");
908037fe 1282 BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s2)
865ed8a1 1283 {
b0243da7
GA
1284 if (i.first == mismatch.first) printf(" (1)");
1285 if (i.first == mismatch.second) printf(" (2)");
c591cc50 1286 printf(" %s\n", i.second.ToString().c_str());
865ed8a1
GA
1287 }
1288 printf("Current lock order is:\n");
908037fe 1289 BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, s1)
865ed8a1 1290 {
b0243da7
GA
1291 if (i.first == mismatch.first) printf(" (1)");
1292 if (i.first == mismatch.second) printf(" (2)");
c591cc50 1293 printf(" %s\n", i.second.ToString().c_str());
865ed8a1
GA
1294 }
1295}
1296
f342dac1 1297static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
865ed8a1
GA
1298{
1299 bool fOrderOK = true;
1300 if (lockstack.get() == NULL)
1301 lockstack.reset(new LockStack);
1302
c591cc50 1303 if (fDebug) printf("Locking: %s\n", locklocation.ToString().c_str());
865ed8a1
GA
1304 dd_mutex.lock();
1305
1306 (*lockstack).push_back(std::make_pair(c, locklocation));
1307
f342dac1 1308 if (!fTry) BOOST_FOREACH(const PAIRTYPE(void*, CLockLocation)& i, (*lockstack))
865ed8a1
GA
1309 {
1310 if (i.first == c) break;
1311
908037fe 1312 std::pair<void*, void*> p1 = std::make_pair(i.first, c);
865ed8a1
GA
1313 if (lockorders.count(p1))
1314 continue;
1315 lockorders[p1] = (*lockstack);
1316
908037fe 1317 std::pair<void*, void*> p2 = std::make_pair(c, i.first);
865ed8a1
GA
1318 if (lockorders.count(p2))
1319 {
b0243da7 1320 potential_deadlock_detected(p1, lockorders[p2], lockorders[p1]);
865ed8a1
GA
1321 break;
1322 }
1323 }
1324 dd_mutex.unlock();
1325}
1326
1327static void pop_lock()
1328{
c591cc50
GA
1329 if (fDebug)
1330 {
1331 const CLockLocation& locklocation = (*lockstack).rbegin()->second;
1332 printf("Unlocked: %s\n", locklocation.ToString().c_str());
1333 }
1334 dd_mutex.lock();
865ed8a1 1335 (*lockstack).pop_back();
c591cc50 1336 dd_mutex.unlock();
865ed8a1
GA
1337}
1338
f342dac1 1339void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry)
865ed8a1 1340{
f342dac1 1341 push_lock(cs, CLockLocation(pszName, pszFile, nLine), fTry);
865ed8a1
GA
1342}
1343
712fd182 1344void LeaveCritical()
865ed8a1 1345{
712fd182 1346 pop_lock();
865ed8a1 1347}
2097c09a 1348
865ed8a1 1349#endif /* DEBUG_LOCKORDER */
This page took 0.258318 seconds and 4 git commands to generate.