@@ -53,6 +53,7 @@ static const float RECONNECT_TIMEOUT_EXP = 1.5;
53
53
* this is belt-and-suspenders sanity limit to prevent memory exhaustion.
54
54
*/
55
55
static const int MAX_LINE_LENGTH = 100000 ;
56
+ static const uint16_t DEFAULT_TOR_SOCKS_PORT = 9050 ;
56
57
57
58
/* ***** Low-level TorControlConnection ********/
58
59
@@ -338,6 +339,73 @@ TorController::~TorController()
338
339
}
339
340
}
340
341
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
+
341
409
void TorController::add_onion_cb (TorControlConnection& _conn, const TorControlReply& reply)
342
410
{
343
411
if (reply.code == 250 ) {
@@ -381,25 +449,7 @@ void TorController::auth_cb(TorControlConnection& _conn, const TorControlReply&
381
449
// Now that we know Tor is running setup the proxy for onion addresses
382
450
// if -onion isn't set to something else.
383
451
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));
403
453
}
404
454
405
455
// Finally - now create the service
0 commit comments