当前位置:bitcoind.cpp=>main=>AppInit(131) 

InitParameterInteraction();

通过其名称我们可以直观的理解该函数的功能是对传入参数的交互处理,也就是根据参数的信息做出相应的操作或执行相应的任务。该函数位于init.cpp文件中(744)。该函数分以下部分。

-bind,绑定监听地址,方式1

-whitebind,绑定监听地址,方式2

-connect,是否连接可信任节点

-proxy,代理模式,不需要监听(listen)

-listen,是否监听默认地址

-externalip,外部IP设置

-blocksonly,区块模式

-whitelistforcerelay,白名单模式

 1、绑定并监听地址

    // when specifying an explicit binding address, you want to listen on it
    // even when -connect or -proxy is specified
    //注释含义:当显示指定了绑定地址后,即使指定了-connect和-proxy参数信息,程序将会接受来自外部的连接,并监听该地址。
    if (gArgs.IsArgSet("-bind")) {
        if (gArgs.SoftSetBoolArg("-listen", true))
            LogPrintf("%s: parameter interaction: -bind set -> setting -listen=1\n", __func__);
    }
    if (gArgs.IsArgSet("-whitebind")) {
        if (gArgs.SoftSetBoolArg("-listen", true))
            LogPrintf("%s: parameter interaction: -whitebind set -> setting -listen=1\n", __func__);
    }

绑定地址的方式有两种参数,分别是“-bind-whitebind,程序对这两种参数的处理方式是一致的,均通过SoftSetBoolArg函数实现“-listen”参数的设置,并将其值设置为true,表示要监听设置的外部连接IP地址。

LogPrintf函数,它在src/util.h(139)中以预编译方式实现的定义。

#define LogPrintf(...) do { \
    std::string _log_msg_; /* Unlikely name to avoid shadowing variables */ \
    try { \
        _log_msg_ = tfm::format(__VA_ARGS__); \
    } catch (tinyformat::format_error &fmterr) { \
        /* Original format string will have newline so don't add one here */ \
        _log_msg_ = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + FormatStringFromLogArgs(__VA_ARGS__); \
    } \
    LogPrintStr(_log_msg_); \
} while(0)

#define LogPrint(category, ...) do { \
    if (LogAcceptCategory((category))) { \
        LogPrintf(__VA_ARGS__); \
    } \
} while(0)
#endif

其本身不实现日志打印功能,而是通过调用LogPrintStr函数实现,该函数在src/util.cpp(328)中进行了实现。

int LogPrintStr(const std::string &str)
{
    int ret = 0; // Returns total number of characters written
    static std::atomic_bool fStartedNewLine(true);

    std::string strTimestamped = LogTimestampStr(str, &fStartedNewLine);

    if (fPrintToConsole)
    {
        // print to console
        ret = fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
        fflush(stdout);
    }
    else if (fPrintToDebugLog)
    {
        boost::call_once(&DebugPrintInit, debugPrintInitFlag);
        boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);

        // buffer if we haven't opened the log yet
        if (fileout == nullptr) {
            assert(vMsgsBeforeOpenLog);
            ret = strTimestamped.length();
            vMsgsBeforeOpenLog->push_back(strTimestamped);
        }
        else
        {
            // reopen the log file, if requested
            if (fReopenDebugLog) {
                fReopenDebugLog = false;
                fs::path pathDebug = GetDataDir() / "debug.log";
                if (fsbridge::freopen(pathDebug,"a",fileout) != nullptr)
                    setbuf(fileout, nullptr); // unbuffered
            }

            ret = FileWriteStr(strTimestamped, fileout);
        }
    }
    return ret;
}

其流程图:

                                                 比特币源代码--8--bitcoind(main函数)参数的初始化设置

 

大概逻辑如下: 

1. 通过调用函数LogTimestampStr为日志加上时间戳;

2. 根据全局变量fPrintToConsole判断是否打印到控制台,默认值为false, 即不打印;

3. 根据全局变量fPrintToDebugLog判断是否打印到日志文件debug.log,默认是true,即打印;

2、连接可信节点

if (gArgs.IsArgSet("-connect")) {
        // when only connecting to trusted nodes, do not seed via DNS, or listen by default
        if (gArgs.SoftSetBoolArg("-dnsseed", false))
            LogPrintf("%s: parameter interaction: -connect set -> setting -dnsseed=0\n", __func__);
        if (gArgs.SoftSetBoolArg("-listen", false))
            LogPrintf("%s: parameter interaction: -connect set -> setting -listen=0\n", __func__);
    }

判断gArgs中,是否包含-connect参数,如果包括,切没用绑定地址,则将-dnsseed与-listen设置为0,如果绑定了地址,则listen仍为1。

3、代理模式

if (gArgs.IsArgSet("-proxy")) {
        // to protect privacy, do not listen by default if a default proxy server is specified
        if (gArgs.SoftSetBoolArg("-listen", false))
            LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__);
        // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1
        // to listen locally, so don't rely on this happening through -listen below.
        if (gArgs.SoftSetBoolArg("-upnp", false))
            LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__);
        // to protect privacy, do not discover addresses by default
        if (gArgs.SoftSetBoolArg("-discover", false))
            LogPrintf("%s: parameter interaction: -proxy set -> setting -discover=0\n", __func__);
    }

这是设置代理参数,目的是保护隐私,如果设置了设置了代理模式,-listen,upnp,以及discover均设置为false,即比特币后台进程只使用代理提供的监听地址与端口,并且不去查找默认的监听地址,这里upnp代表的意思是使用全局即插即用(upnp)映射监听端口,默认不使用。

4、监听设置处理

if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
        // do not map ports or try to retrieve public IP when not listening (pointless)
        if (gArgs.SoftSetBoolArg("-upnp", false))
            LogPrintf("%s: parameter interaction: -listen=0 -> setting -upnp=0\n", __func__);
        if (gArgs.SoftSetBoolArg("-discover", false))
            LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__);
        if (gArgs.SoftSetBoolArg("-listenonion", false))
            LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__);
    }

监听处理,DEFAULT_LISTEN默认为true。如果监听设置为false,即不实施监听,则端口upnp,discover,listenonion均设置为false。Listenonion匿名地址监听,此处涉及通信机制的一个概念,第二代洋葱路由(onion routing),其解释如下:

Tor(The Onion Router)是第二代洋葱路由(onion routing)的一种实现,用户通过Tor可以在因特网上进行匿名交流。Tor专门防范流量过滤、嗅探分析,让用户免受其害。最初该项目由美国海军研究实验室赞助。2004年后期,Tor成为电子前哨基金会的一个项目。2005年后期,EFF不再赞助Tor项目,但他们继续维持Tor的官方网站。

5、外部IP处理

  if (gArgs.IsArgSet("-externalip")) {
        // if an explicit public IP is specified, do not try to find others
        if (gArgs.SoftSetBoolArg("-discover", false))
            LogPrintf("%s: parameter interaction: -externalip set -> setting -discover=0\n", __func__);
    }

如果显示指定了公共IP地址,那么bitcoind就不需要查找其他监听地址了。

6、区块模式设置

    // disable whitelistrelay in blocksonly mode
    if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
        if (gArgs.SoftSetBoolArg("-whitelistrelay", false))
            LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n", __func__);
    }

全局变量DEFAULT_BLOCKSONLY默认值为False,只有DEFAULT_BLOCKSONLY的值为true,GetBoolArg才为true,这时才会将"-whitelistrelay"设置为false,即区块模式下白名单列表失效。

blocksonly参数为比特币客户端以调试状态启动时才会使用的。

7、强制白名单节点连接参数设置

if (gArgs.IsArgSet("-blockmaxsize")) {
        unsigned int max_size = gArgs.GetArg("-blockmaxsize", 0);
        if (gArgs.SoftSetArg("blockmaxweight", strprintf("%d", max_size * WITNESS_SCALE_FACTOR))) {
            LogPrintf("%s: parameter interaction: -blockmaxsize=%d -> setting -blockmaxweight=%d (-blockmaxsize is deprecated!)\n", __func__, max_size, max_size * WITNESS_SCALE_FACTOR);
        } else {
            LogPrintf("%s: Ignoring blockmaxsize setting which is overridden by blockmaxweight", __func__);
        }
    }

DEFAULT_WHITELISTFORCERELAY默认true,如果设置了whitelistforcerelay参数,则whitelistrelay为true,表示优先处理白名单节点。

 

相关文章: