@@ -53,6 +53,7 @@ static const float RECONNECT_TIMEOUT_EXP = 1.5;
5353 * this is belt-and-suspenders sanity limit to prevent memory exhaustion.
5454 */
5555static const int MAX_LINE_LENGTH = 100000 ;
56+ static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050 ;
5657
5758/* ***** Low-level TorControlConnection ********/
5859
@@ -338,6 +339,73 @@ TorController::~TorController()
338339 }
339340}
340341
342+ void TorController::get_socks_cb (TorControlConnection& _conn, const TorControlReply& reply)
343+ {
344+ // NOTE: We can only get here if -onion is unset
345+ std::string socks_location;
346+ if (reply.code == 250 ) {
347+ for (const auto & line : reply.lines ) {
348+ if (0 == line.compare (0 , 20 , " net/listeners/socks=" )) {
349+ const std::string port_list_str = line.substr (20 );
350+ std::vector<std::string> port_list;
351+ boost::split (port_list, port_list_str, boost::is_any_of (" " ));
352+ for (auto & portstr : port_list) {
353+ if (portstr.empty ()) continue ;
354+ if ((portstr[0 ] == ' "' || portstr[0 ] == ' \' ' ) && portstr.size () >= 2 && (*portstr.rbegin () == portstr[0 ])) {
355+ portstr = portstr.substr (1 , portstr.size () - 2 );
356+ if (portstr.empty ()) continue ;
357+ }
358+ socks_location = portstr;
359+ if (0 == portstr.compare (0 , 10 , " 127.0.0.1:" )) {
360+ // Prefer localhost - ignore other ports
361+ break ;
362+ }
363+ }
364+ }
365+ }
366+ if (!socks_location.empty ()) {
367+ LogPrint (BCLog::TOR, " tor: Get SOCKS port command yielded %s\n " , socks_location);
368+ } else {
369+ LogPrintf (" tor: Get SOCKS port command returned nothing\n " );
370+ }
371+ } else if (reply.code == 510 ) { // 510 Unrecognized command
372+ LogPrintf (" tor: Get SOCKS port command failed with unrecognized command (You probably should upgrade Tor)\n " );
373+ } else {
374+ LogPrintf (" tor: Get SOCKS port command failed; error code %d\n " , reply.code );
375+ }
376+
377+ CService resolved;
378+ Assume (!resolved.IsValid ());
379+ if (!socks_location.empty ()) {
380+ resolved = LookupNumeric (socks_location, DEFAULT_TOR_SOCKS_PORT);
381+ }
382+ if (!resolved.IsValid ()) {
383+ // Fallback to old behaviour
384+ resolved = LookupNumeric (" 127.0.0.1" , DEFAULT_TOR_SOCKS_PORT);
385+ }
386+
387+ Assume (resolved.IsValid ());
388+ LogPrint (BCLog::TOR, " tor: Configuring onion proxy for %s\n " , resolved.ToStringIPPort ());
389+ Proxy addrOnion = Proxy (resolved, true );
390+ SetProxy (NET_ONION, addrOnion);
391+
392+ const auto onlynets = gArgs .GetArgs (" -onlynet" );
393+
394+ const bool onion_allowed_by_onlynet{
395+ !gArgs .IsArgSet (" -onlynet" ) ||
396+ std::any_of (onlynets.begin (), onlynets.end (), [](const auto & n) {
397+ return ParseNetwork (n) == NET_ONION;
398+ })};
399+
400+ if (onion_allowed_by_onlynet) {
401+ // If NET_ONION is reachable, then the below is a noop.
402+ //
403+ // If NET_ONION is not reachable, then none of -proxy or -onion was given.
404+ // Since we are here, then -torcontrol and -torpassword were given.
405+ SetReachable (NET_ONION, true );
406+ }
407+ }
408+
341409void TorController::add_onion_cb (TorControlConnection& _conn, const TorControlReply& reply)
342410{
343411 if (reply.code == 250 ) {
@@ -381,25 +449,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
381449 // Now that we know Tor is running setup the proxy for onion addresses
382450 // if -onion isn't set to something else.
383451 if (gArgs .GetArg (" -onion" , " " ) == " " ) {
384- CService resolved (LookupNumeric (" 127.0.0.1" , 9050 ));
385- Proxy addrOnion = Proxy (resolved, true );
386- SetProxy (NET_ONION, addrOnion);
387-
388- const auto onlynets = gArgs .GetArgs (" -onlynet" );
389-
390- const bool onion_allowed_by_onlynet{
391- !gArgs .IsArgSet (" -onlynet" ) ||
392- std::any_of (onlynets.begin (), onlynets.end (), [](const auto & n) {
393- return ParseNetwork (n) == NET_ONION;
394- })};
395-
396- if (onion_allowed_by_onlynet) {
397- // If NET_ONION is reachable, then the below is a noop.
398- //
399- // If NET_ONION is not reachable, then none of -proxy or -onion was given.
400- // Since we are here, then -torcontrol and -torpassword were given.
401- SetReachable (NET_ONION, true );
402- }
452+ _conn.Command (" GETINFO net/listeners/socks" , std::bind (&TorController::get_socks_cb, this , std::placeholders::_1, std::placeholders::_2));
403453 }
404454
405455 // Finally - now create the service
0 commit comments