merge bitcoin#19991: Use alternative port for incoming Tor connections

This commit is contained in:
Kittywhiskers Van Gogh 2023-04-17 08:27:07 +00:00
parent 95d462d01d
commit c89cac5783
8 changed files with 125 additions and 54 deletions

View File

@ -53,11 +53,12 @@ config file): *Needed for Tor version 0.2.7.0 and older versions of Tor only. Fo
versions of Tor see [Section 4](#4-automatically-listen-on-tor).* versions of Tor see [Section 4](#4-automatically-listen-on-tor).*
HiddenServiceDir /var/lib/tor/dashcore-service/ HiddenServiceDir /var/lib/tor/dashcore-service/
HiddenServicePort 9999 127.0.0.1:9999 HiddenServicePort 9999 127.0.0.1:9996
HiddenServicePort 19999 127.0.0.1:19999 HiddenServicePort 19999 127.0.0.1:19996
The directory can be different of course, but (both) port numbers should be equal to The directory can be different of course, but virtual port numbers should be equal to
your dashd's P2P listen port (9999 by default). your dashd's P2P listen port (9999 by default), and target addresses and ports
should be equal to binding address and port for inbound Tor connections (127.0.0.1:9996 by default).
-externalip=X You can tell Dash Core about its publicly reachable address using -externalip=X You can tell Dash Core about its publicly reachable address using
this option, and this can be a .onion address. Given the above this option, and this can be a .onion address. Given the above

View File

@ -49,16 +49,20 @@ const CBaseChainParams& BaseParams()
return *globalChainBaseParams; return *globalChainBaseParams;
} }
/**
* Port numbers for incoming Tor connections (9996, 19996, 19796, 19896) have
* been chosen arbitrarily to keep ranges of used ports tight.
*/
std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain) std::unique_ptr<CBaseChainParams> CreateBaseChainParams(const std::string& chain)
{ {
if (chain == CBaseChainParams::MAIN) if (chain == CBaseChainParams::MAIN)
return std::make_unique<CBaseChainParams>("", 9998); return std::make_unique<CBaseChainParams>("", 9998, 9996);
else if (chain == CBaseChainParams::TESTNET) else if (chain == CBaseChainParams::TESTNET)
return std::make_unique<CBaseChainParams>("testnet3", 19998); return std::make_unique<CBaseChainParams>("testnet3", 19998, 19996);
else if (chain == CBaseChainParams::DEVNET) else if (chain == CBaseChainParams::DEVNET)
return std::make_unique<CBaseChainParams>(gArgs.GetDevNetName(), 19798); return std::make_unique<CBaseChainParams>(gArgs.GetDevNetName(), 19798, 19796);
else if (chain == CBaseChainParams::REGTEST) else if (chain == CBaseChainParams::REGTEST)
return std::make_unique<CBaseChainParams>("regtest", 19898); return std::make_unique<CBaseChainParams>("regtest", 19898, 19896);
else else
throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain)); throw std::runtime_error(strprintf("%s: Unknown chain %s.", __func__, chain));
} }

View File

@ -26,13 +26,16 @@ public:
///@} ///@}
const std::string& DataDir() const { return strDataDir; } const std::string& DataDir() const { return strDataDir; }
uint16_t RPCPort() const { return nRPCPort; } uint16_t RPCPort() const { return m_rpc_port; }
uint16_t OnionServiceTargetPort() const { return m_onion_service_target_port; }
CBaseChainParams() = delete; CBaseChainParams() = delete;
CBaseChainParams(const std::string& data_dir, int rpc_port) : nRPCPort(rpc_port), strDataDir(data_dir) {} CBaseChainParams(const std::string& data_dir, uint16_t rpc_port, uint16_t onion_service_target_port)
: m_rpc_port(rpc_port), m_onion_service_target_port(onion_service_target_port), strDataDir(data_dir) {}
private: private:
uint16_t nRPCPort; const uint16_t m_rpc_port;
const uint16_t m_onion_service_target_port;
std::string strDataDir; std::string strDataDir;
}; };

View File

@ -552,7 +552,7 @@ void SetupServerArgs(NodeContext& node)
argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-allowprivatenet", strprintf("Allow RFC1918 addresses to be relayed and connected to (default: %u)", DEFAULT_ALLOWPRIVATENET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting and discouraging misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-banscore=<n>", strprintf("Threshold for disconnecting and discouraging misbehaving peers (default: %u)", DEFAULT_BANSCORE_THRESHOLD), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-bind=<addr>", "Bind to given address and always listen on it. Use [host]:port notation for IPv6", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultBaseParams->OnionServiceTargetPort(), testnetBaseParams->OnionServiceTargetPort(), regtestBaseParams->OnionServiceTargetPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION); argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
@ -2480,8 +2480,6 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
} }
} }
LogPrintf("::ChainActive().Height() = %d\n", chain_active_height); LogPrintf("::ChainActive().Height() = %d\n", chain_active_height);
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION))
StartTorControl();
Discover(); Discover();
@ -2506,13 +2504,39 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET); connOptions.nMaxOutboundLimit = 1024 * 1024 * args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET);
connOptions.m_peer_connect_timeout = peer_connect_timeout; connOptions.m_peer_connect_timeout = peer_connect_timeout;
for (const std::string& strBind : args.GetArgs("-bind")) { for (const std::string& bind_arg : args.GetArgs("-bind")) {
CService addrBind; CService bind_addr;
if (!Lookup(strBind, addrBind, GetListenPort(), false)) { const size_t index = bind_arg.rfind('=');
return InitError(ResolveErrMsg("bind", strBind)); if (index == std::string::npos) {
if (Lookup(bind_arg, bind_addr, GetListenPort(), false)) {
connOptions.vBinds.push_back(bind_addr);
continue;
}
} else {
const std::string network_type = bind_arg.substr(index + 1);
if (network_type == "onion") {
const std::string truncated_bind_arg = bind_arg.substr(0, index);
if (Lookup(truncated_bind_arg, bind_addr, BaseParams().OnionServiceTargetPort(), false)) {
connOptions.onion_binds.push_back(bind_addr);
continue;
}
}
} }
connOptions.vBinds.push_back(addrBind); return InitError(ResolveErrMsg("bind", bind_arg));
} }
if (connOptions.onion_binds.empty()) {
connOptions.onion_binds.push_back(DefaultOnionServiceTarget());
}
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
const auto bind_addr = connOptions.onion_binds.front();
if (connOptions.onion_binds.size() > 1) {
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s for the automatically created Tor onion service."), bind_addr.ToStringIPPort()));
}
StartTorControl(bind_addr);
}
for (const std::string& strBind : args.GetArgs("-whitebind")) { for (const std::string& strBind : args.GetArgs("-whitebind")) {
NetWhitebindPermissions whitebind; NetWhitebindPermissions whitebind;
bilingual_str error; bilingual_str error;

View File

@ -99,6 +99,11 @@ enum BindFlags {
BF_NONE = 0, BF_NONE = 0,
BF_EXPLICIT = (1U << 0), BF_EXPLICIT = (1U << 0),
BF_REPORT_ERROR = (1U << 1), BF_REPORT_ERROR = (1U << 1),
/**
* Do not call AddLocal() for our special addresses, e.g., for incoming
* Tor connections, to prevent gossiping them over the network.
*/
BF_DONT_ADVERTISE = (1U << 2),
}; };
#ifndef USE_WAKEUP_PIPE #ifndef USE_WAKEUP_PIPE
@ -2875,9 +2880,6 @@ bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError,
vhListenSocket.push_back(ListenSocket(sock->Release(), permissions)); vhListenSocket.push_back(ListenSocket(sock->Release(), permissions));
if (addrBind.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0)
AddLocal(addrBind, LOCAL_BIND);
return true; return true;
} }
@ -2974,10 +2976,18 @@ bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags
} }
return false; return false;
} }
if (addr.IsRoutable() && fDiscover && !(flags & BF_DONT_ADVERTISE) && !(permissions & PF_NOBAN)) {
AddLocal(addr, LOCAL_BIND);
}
return true; return true;
} }
bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds) bool CConnman::InitBinds(
const std::vector<CService>& binds,
const std::vector<NetWhitebindPermissions>& whiteBinds,
const std::vector<CService>& onion_binds)
{ {
bool fBound = false; bool fBound = false;
for (const auto& addrBind : binds) { for (const auto& addrBind : binds) {
@ -2988,11 +2998,16 @@ bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<N
} }
if (binds.empty() && whiteBinds.empty()) { if (binds.empty() && whiteBinds.empty()) {
struct in_addr inaddr_any; struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY; inaddr_any.s_addr = htonl(INADDR_ANY);
struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT; struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE); fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE);
fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE); fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE);
} }
for (const auto& addr_bind : onion_binds) {
fBound |= Bind(addr_bind, BF_EXPLICIT | BF_DONT_ADVERTISE, NetPermissionFlags::PF_NONE);
}
return fBound; return fBound;
} }
@ -3031,7 +3046,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
} }
#endif #endif
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds, connOptions.onion_binds)) {
if (clientInterface) { if (clientInterface) {
clientInterface->ThreadSafeMessageBox( clientInterface->ThreadSafeMessageBox(
_("Failed to listen on any port. Use -listen=0 if you want this."), _("Failed to listen on any port. Use -listen=0 if you want this."),

View File

@ -178,6 +178,7 @@ public:
std::vector<NetWhitelistPermissions> vWhitelistedRange; std::vector<NetWhitelistPermissions> vWhitelistedRange;
std::vector<NetWhitebindPermissions> vWhiteBinds; std::vector<NetWhitebindPermissions> vWhiteBinds;
std::vector<CService> vBinds; std::vector<CService> vBinds;
std::vector<CService> onion_binds;
bool m_use_addrman_outgoing = true; bool m_use_addrman_outgoing = true;
std::vector<std::string> m_specified_outgoing; std::vector<std::string> m_specified_outgoing;
std::vector<std::string> m_added_nodes; std::vector<std::string> m_added_nodes;
@ -496,7 +497,11 @@ private:
bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions); bool BindListenPort(const CService& bindAddr, bilingual_str& strError, NetPermissionFlags permissions);
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions); bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
bool InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds); bool InitBinds(
const std::vector<CService>& binds,
const std::vector<NetWhitebindPermissions>& whiteBinds,
const std::vector<CService>& onion_binds);
void ThreadOpenAddedConnections(); void ThreadOpenAddedConnections();
void AddOneShot(const std::string& strDest); void AddOneShot(const std::string& strDest);
void ProcessOneShot(); void ProcessOneShot();

View File

@ -3,14 +3,17 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
#include <torcontrol.h> #include <torcontrol.h>
#include <util/strencodings.h>
#include <netbase.h> #include <chainparams.h>
#include <chainparamsbase.h>
#include <crypto/hmac_sha256.h>
#include <net.h> #include <net.h>
#include <netaddress.h>
#include <netbase.h>
#include <util/strencodings.h>
#include <util/system.h> #include <util/system.h>
#include <util/time.h> #include <util/time.h>
#include <crypto/hmac_sha256.h>
#include <vector> #include <vector>
#include <deque> #include <deque>
@ -79,12 +82,12 @@ public:
/** /**
* Connect to a Tor control port. * Connect to a Tor control port.
* target is address of the form host:port. * tor_control_center is address of the form host:port.
* connected is the handler that is called when connection is successfully established. * connected is the handler that is called when connection is successfully established.
* disconnected is a handler that is called when the connection is broken. * disconnected is a handler that is called when the connection is broken.
* Return true on success. * Return true on success.
*/ */
bool Connect(const std::string &target, const ConnectionCB& connected, const ConnectionCB& disconnected); bool Connect(const std::string& tor_control_center, const ConnectionCB& connected, const ConnectionCB& disconnected);
/** /**
* Disconnect from Tor control port. * Disconnect from Tor control port.
@ -191,16 +194,16 @@ void TorControlConnection::eventcb(struct bufferevent *bev, short what, void *ct
} }
} }
bool TorControlConnection::Connect(const std::string &target, const ConnectionCB& _connected, const ConnectionCB& _disconnected) bool TorControlConnection::Connect(const std::string& tor_control_center, const ConnectionCB& _connected, const ConnectionCB& _disconnected)
{ {
if (b_conn) if (b_conn)
Disconnect(); Disconnect();
// Parse target address:port // Parse tor_control_center address:port
struct sockaddr_storage connect_to_addr; struct sockaddr_storage connect_to_addr;
int connect_to_addrlen = sizeof(connect_to_addr); int connect_to_addrlen = sizeof(connect_to_addr);
if (evutil_parse_sockaddr_port(target.c_str(), if (evutil_parse_sockaddr_port(tor_control_center.c_str(),
(struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) { (struct sockaddr*)&connect_to_addr, &connect_to_addrlen)<0) {
LogPrintf("tor: Error parsing socket address %s\n", target); LogPrintf("tor: Error parsing socket address %s\n", tor_control_center);
return false; return false;
} }
@ -213,9 +216,9 @@ bool TorControlConnection::Connect(const std::string &target, const ConnectionCB
this->connected = _connected; this->connected = _connected;
this->disconnected = _disconnected; this->disconnected = _disconnected;
// Finally, connect to target // Finally, connect to tor_control_center
if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) { if (bufferevent_socket_connect(b_conn, (struct sockaddr*)&connect_to_addr, connect_to_addrlen) < 0) {
LogPrintf("tor: Error connecting to address %s\n", target); LogPrintf("tor: Error connecting to address %s\n", tor_control_center);
return false; return false;
} }
return true; return true;
@ -408,7 +411,7 @@ static bool WriteBinaryFile(const fs::path &filename, const std::string &data)
class TorController class TorController
{ {
public: public:
TorController(struct event_base* base, const std::string& target); TorController(struct event_base* base, const std::string& tor_control_center, const CService& target);
~TorController(); ~TorController();
/** Get name of file to store private key in */ /** Get name of file to store private key in */
@ -418,7 +421,7 @@ public:
void Reconnect(); void Reconnect();
private: private:
struct event_base* base; struct event_base* base;
std::string target; const std::string m_tor_control_center;
TorControlConnection conn; TorControlConnection conn;
std::string private_key; std::string private_key;
std::string service_id; std::string service_id;
@ -426,6 +429,7 @@ private:
struct event *reconnect_ev; struct event *reconnect_ev;
float reconnect_timeout; float reconnect_timeout;
CService service; CService service;
const CService m_target;
/** Cookie for SAFECOOKIE auth */ /** Cookie for SAFECOOKIE auth */
std::vector<uint8_t> cookie; std::vector<uint8_t> cookie;
/** ClientNonce for SAFECOOKIE auth */ /** ClientNonce for SAFECOOKIE auth */
@ -448,18 +452,19 @@ private:
static void reconnect_cb(evutil_socket_t fd, short what, void *arg); static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
}; };
TorController::TorController(struct event_base* _base, const std::string& _target): TorController::TorController(struct event_base* _base, const std::string& tor_control_center, const CService& target):
base(_base), base(_base),
target(_target), conn(base), reconnect(true), reconnect_ev(0), m_tor_control_center(tor_control_center), conn(base), reconnect(true), reconnect_ev(0),
reconnect_timeout(RECONNECT_TIMEOUT_START) reconnect_timeout(RECONNECT_TIMEOUT_START),
m_target(target)
{ {
reconnect_ev = event_new(base, -1, 0, reconnect_cb, this); reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
if (!reconnect_ev) if (!reconnect_ev)
LogPrintf("tor: Failed to create event for reconnection: out of memory?\n"); LogPrintf("tor: Failed to create event for reconnection: out of memory?\n");
// Start connection attempts immediately // Start connection attempts immediately
if (!conn.Connect(_target, std::bind(&TorController::connected_cb, this, std::placeholders::_1), if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
LogPrintf("tor: Initiating connection to Tor control port %s failed\n", _target); LogPrintf("tor: Initiating connection to Tor control port %s failed\n", m_tor_control_center);
} }
// Read service private key if cached // Read service private key if cached
std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile()); std::pair<bool,std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
@ -535,7 +540,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
} }
// Request hidden service, redirect port. // Request hidden service, redirect port.
// Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports. // Note that the 'virtual' port is always the default port to avoid decloaking nodes using other ports.
_conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i", private_key, Params().GetDefaultPort(), GetListenPort()), _conn.Command(strprintf("ADD_ONION %s Port=%i,%s", private_key, Params().GetDefaultPort(), m_target.ToStringIPPort()),
std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2)); std::bind(&TorController::add_onion_cb, this, std::placeholders::_1, std::placeholders::_2));
} else { } else {
LogPrintf("tor: Authentication failed\n"); LogPrintf("tor: Authentication failed\n");
@ -697,7 +702,7 @@ void TorController::disconnected_cb(TorControlConnection& _conn)
if (!reconnect) if (!reconnect)
return; return;
LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", target); LogPrint(BCLog::TOR, "tor: Not connected to Tor control port %s, trying to reconnect\n", m_tor_control_center);
// Single-shot timer for reconnect. Use exponential backoff. // Single-shot timer for reconnect. Use exponential backoff.
struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0)); struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0));
@ -711,9 +716,9 @@ void TorController::Reconnect()
/* Try to reconnect and reestablish if we get booted - for example, Tor /* Try to reconnect and reestablish if we get booted - for example, Tor
* may be restarting. * may be restarting.
*/ */
if (!conn.Connect(target, std::bind(&TorController::connected_cb, this, std::placeholders::_1), if (!conn.Connect(m_tor_control_center, std::bind(&TorController::connected_cb, this, std::placeholders::_1),
std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) { std::bind(&TorController::disconnected_cb, this, std::placeholders::_1) )) {
LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", target); LogPrintf("tor: Re-initiating connection to Tor control port %s failed\n", m_tor_control_center);
} }
} }
@ -732,14 +737,14 @@ void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg)
static struct event_base *gBase; static struct event_base *gBase;
static std::thread torControlThread; static std::thread torControlThread;
static void TorControlThread() static void TorControlThread(CService onion_service_target)
{ {
TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL)); TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL), onion_service_target);
event_base_dispatch(gBase); event_base_dispatch(gBase);
} }
void StartTorControl() void StartTorControl(CService onion_service_target)
{ {
assert(!gBase); assert(!gBase);
#ifdef WIN32 #ifdef WIN32
@ -753,7 +758,9 @@ void StartTorControl()
return; return;
} }
torControlThread = std::thread(std::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread)); torControlThread = std::thread(&TraceThread<std::function<void()>>, "torcontrol", [onion_service_target] {
TorControlThread(onion_service_target);
});
} }
void InterruptTorControl() void InterruptTorControl()
@ -774,3 +781,10 @@ void StopTorControl()
gBase = nullptr; gBase = nullptr;
} }
} }
CService DefaultOnionServiceTarget()
{
struct in_addr onion_service_target;
onion_service_target.s_addr = htonl(INADDR_LOOPBACK);
return {onion_service_target, BaseParams().OnionServiceTargetPort()};
}

View File

@ -8,12 +8,17 @@
#ifndef BITCOIN_TORCONTROL_H #ifndef BITCOIN_TORCONTROL_H
#define BITCOIN_TORCONTROL_H #define BITCOIN_TORCONTROL_H
#include <string>
class CService;
extern const std::string DEFAULT_TOR_CONTROL; extern const std::string DEFAULT_TOR_CONTROL;
static const bool DEFAULT_LISTEN_ONION = true; static const bool DEFAULT_LISTEN_ONION = true;
void StartTorControl(); void StartTorControl(CService onion_service_target);
void InterruptTorControl(); void InterruptTorControl();
void StopTorControl(); void StopTorControl();
CService DefaultOnionServiceTarget();
#endif /* BITCOIN_TORCONTROL_H */ #endif /* BITCOIN_TORCONTROL_H */