From 2806da3298e716e12aec751f99b2215cbf5bdd62 Mon Sep 17 00:00:00 2001 From: myl7 Date: Sun, 5 Dec 2021 19:36:10 +0800 Subject: [PATCH] Add bt-udp-socks-proxy option with its utilities --- src/DHTSetup.cc | 14 ++++++++++--- src/FeatureConfig.cc | 3 +++ src/OptionHandlerFactory.cc | 31 +++++++++++++++++++++++++++ src/OptionHandlerImpl.cc | 42 +++++++++++++++++++++++++++++++++++++ src/OptionHandlerImpl.h | 14 +++++++++++++ src/option_processing.cc | 1 + src/prefs.cc | 3 +++ src/prefs.h | 3 +++ src/usage_text.h | 7 +++++++ 9 files changed, 115 insertions(+), 3 deletions(-) diff --git a/src/DHTSetup.cc b/src/DHTSetup.cc index 5a773c23..d8cfb8d6 100644 --- a/src/DHTSetup.cc +++ b/src/DHTSetup.cc @@ -141,15 +141,23 @@ DHTSetup::setup(DownloadEngine* e, int family) A2_LOG_DEBUG(fmt("Initialized local node ID=%s", util::toHex(localNode->getID(), DHT_ID_LENGTH).c_str())); { - if (!connection->startProxy("127.0.0.1", 8000, "", "", + const std::string& user = + e->getOption()->get(PREF_BT_UDP_SOCKS_PROXY_USER); + const std::string& passwd = + e->getOption()->get(PREF_BT_UDP_SOCKS_PROXY_PASSWD); + uri::UriStruct us; + uri::parse(us, e->getOption()->get(PREF_BT_UDP_SOCKS_PROXY)); + const std::string& host = us.host; + uint16_t port = us.port; + if (!connection->startProxy(host, port, user, passwd, localNode->getIPAddress(), localNode->getPort())) { throw DL_ABORT_EX("Error occurred while connecting to SOCKS5 relay " "server for UDP proxy for DHT and UDP trackers"); } + A2_LOG_DEBUG(fmt("Connected to SOCKS5 relay server %s:%u for UDP proxy", + host, port)); } - A2_LOG_DEBUG(fmt("Connected to SOCKS5 relay server %s:%u for UDP proxy", - "127.0.0.1", 8000)); auto tracker = std::make_shared(); auto routingTable = make_unique(localNode); auto factory = make_unique(family); diff --git a/src/FeatureConfig.cc b/src/FeatureConfig.cc index 2b43c8b1..98e6b115 100644 --- a/src/FeatureConfig.cc +++ b/src/FeatureConfig.cc @@ -88,6 +88,9 @@ uint16_t getDefaultPort(const std::string& protocol) else if (protocol == "sftp") { return 22; } + else if (protocol == "socks") { + return 1080; + } else { return 0; } diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 6bff4caa..413f01eb 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -1371,6 +1371,37 @@ std::vector OptionHandlerFactory::createOptionHandlers() op->setChangeOptionForReserved(true); handlers.push_back(op); } + { + OptionHandler* op(new SocksProxyOptionHandler( + PREF_BT_UDP_SOCKS_PROXY, TEXT_BT_UDP_SOCKS_PROXY, NO_DEFAULT_VALUE)); + op->addTag(TAG_BITTORRENT); + op->setInitialOption(true); + op->setChangeGlobalOption(true); + op->setChangeOptionForReserved(true); + handlers.push_back(op); + } + { + OptionHandler* op(new DefaultOptionHandler(PREF_BT_UDP_SOCKS_PROXY_PASSWD, + TEXT_BT_UDP_SOCKS_PROXY_PASSWD, + NO_DEFAULT_VALUE)); + op->addTag(TAG_BITTORRENT); + op->setEraseAfterParse(true); + op->setInitialOption(true); + op->setChangeGlobalOption(true); + op->setChangeOptionForReserved(true); + handlers.push_back(op); + } + { + OptionHandler* op(new DefaultOptionHandler(PREF_BT_UDP_SOCKS_PROXY_USER, + TEXT_BT_UDP_SOCKS_PROXY_USER, + NO_DEFAULT_VALUE)); + op->addTag(TAG_BITTORRENT); + op->setEraseAfterParse(true); + op->setInitialOption(true); + op->setChangeGlobalOption(true); + op->setChangeOptionForReserved(true); + handlers.push_back(op); + } { OptionHandler* op(new HttpProxyOptionHandler(PREF_ALL_PROXY, TEXT_ALL_PROXY, NO_DEFAULT_VALUE)); diff --git a/src/OptionHandlerImpl.cc b/src/OptionHandlerImpl.cc index 6214e84b..93c82c7d 100644 --- a/src/OptionHandlerImpl.cc +++ b/src/OptionHandlerImpl.cc @@ -529,6 +529,48 @@ std::string HttpProxyOptionHandler::createPossibleValuesString() const return "[http://][USER:PASSWORD@]HOST[:PORT]"; } +SocksProxyOptionHandler::SocksProxyOptionHandler( + PrefPtr pref, const char* description, const std::string& defaultValue, + char shortName) + : AbstractOptionHandler(pref, description, defaultValue, + OptionHandler::REQ_ARG, shortName), + proxyUserPref_(option::k2p(std::string(pref->k) + "-user")), + proxyPasswdPref_(option::k2p(std::string(pref->k) + "-passwd")) +{ +} + +SocksProxyOptionHandler::~SocksProxyOptionHandler() = default; + +void SocksProxyOptionHandler::parseArg(Option& option, + const std::string& optarg) const +{ + if (optarg.empty()) { + option.put(pref_, optarg); + } + else { + std::string uri; + if (util::startsWith(optarg, "socks://") || + util::startsWith(optarg, "socks5://")) { + uri = optarg; + } + else { + uri = "socks://"; + uri += optarg; + } + uri::UriStruct us; + if (!uri::parse(us, uri)) { + throw DL_ABORT_EX(_("unrecognized proxy format")); + } + us.protocol = "socks"; + option.put(pref_, uri::construct(us)); + } +} + +std::string SocksProxyOptionHandler::createPossibleValuesString() const +{ + return "[socks[5]://][USER:PASSWORD@]HOST[:PORT]"; +} + LocalFilePathOptionHandler::LocalFilePathOptionHandler( PrefPtr pref, const char* description, const std::string& defaultValue, bool acceptStdin, char shortName, bool mustExist, diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index 7846b226..7404e3b6 100644 --- a/src/OptionHandlerImpl.h +++ b/src/OptionHandlerImpl.h @@ -230,6 +230,20 @@ public: virtual std::string createPossibleValuesString() const CXX11_OVERRIDE; }; +class SocksProxyOptionHandler : public AbstractOptionHandler { +private: + PrefPtr proxyUserPref_; + PrefPtr proxyPasswdPref_; + +public: + SocksProxyOptionHandler(PrefPtr pref, const char* description, + const std::string& defaultValue, char shortName = 0); + virtual ~SocksProxyOptionHandler(); + virtual void parseArg(Option& option, + const std::string& optarg) const CXX11_OVERRIDE; + virtual std::string createPossibleValuesString() const CXX11_OVERRIDE; +}; + class LocalFilePathOptionHandler : public AbstractOptionHandler { private: std::string possibleValuesString_; diff --git a/src/option_processing.cc b/src/option_processing.cc index f9891fed..bf4c0196 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -263,6 +263,7 @@ error_code::Value option_processing(Option& op, bool standalone, overrideWithEnv(*confOption, oparser, PREF_HTTP_PROXY, "http_proxy"); overrideWithEnv(*confOption, oparser, PREF_HTTPS_PROXY, "https_proxy"); overrideWithEnv(*confOption, oparser, PREF_FTP_PROXY, "ftp_proxy"); + overrideWithEnv(*confOption, oparser, PREF_BT_UDP_SOCKS_PROXY, "bt_udp_sokcs_proxy"); overrideWithEnv(*confOption, oparser, PREF_ALL_PROXY, "all_proxy"); overrideWithEnv(*confOption, oparser, PREF_NO_PROXY, "no_proxy"); if (!standalone) { diff --git a/src/prefs.cc b/src/prefs.cc index fe982685..0184a163 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -437,6 +437,7 @@ PrefPtr PREF_HTTP_PROXY = makePref("http-proxy"); PrefPtr PREF_HTTPS_PROXY = makePref("https-proxy"); PrefPtr PREF_FTP_PROXY = makePref("ftp-proxy"); PrefPtr PREF_ALL_PROXY = makePref("all-proxy"); +PrefPtr PREF_BT_UDP_SOCKS_PROXY = makePref("bt-udp-socks-proxy"); // values: comma separated hostname or domain PrefPtr PREF_NO_PROXY = makePref("no-proxy"); // values: get | tunnel @@ -447,6 +448,8 @@ PrefPtr PREF_HTTPS_PROXY_USER = makePref("https-proxy-user"); PrefPtr PREF_HTTPS_PROXY_PASSWD = makePref("https-proxy-passwd"); PrefPtr PREF_FTP_PROXY_USER = makePref("ftp-proxy-user"); PrefPtr PREF_FTP_PROXY_PASSWD = makePref("ftp-proxy-passwd"); +PrefPtr PREF_BT_UDP_SOCKS_PROXY_USER = makePref("bt-udp-socks-proxy-user"); +PrefPtr PREF_BT_UDP_SOCKS_PROXY_PASSWD = makePref("bt-udp-socks-proxy-passwd"); PrefPtr PREF_ALL_PROXY_USER = makePref("all-proxy-user"); PrefPtr PREF_ALL_PROXY_PASSWD = makePref("all-proxy-passwd"); diff --git a/src/prefs.h b/src/prefs.h index 9719b3be..35da0406 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -388,6 +388,7 @@ extern PrefPtr PREF_CONTENT_DISPOSITION_DEFAULT_UTF8; extern PrefPtr PREF_HTTP_PROXY; extern PrefPtr PREF_HTTPS_PROXY; extern PrefPtr PREF_FTP_PROXY; +extern PrefPtr PREF_BT_UDP_SOCKS_PROXY; extern PrefPtr PREF_ALL_PROXY; // values: comma separated hostname or domain extern PrefPtr PREF_NO_PROXY; @@ -399,6 +400,8 @@ extern PrefPtr PREF_HTTPS_PROXY_USER; extern PrefPtr PREF_HTTPS_PROXY_PASSWD; extern PrefPtr PREF_FTP_PROXY_USER; extern PrefPtr PREF_FTP_PROXY_PASSWD; +extern PrefPtr PREF_BT_UDP_SOCKS_PROXY_USER; +extern PrefPtr PREF_BT_UDP_SOCKS_PROXY_PASSWD; extern PrefPtr PREF_ALL_PROXY_USER; extern PrefPtr PREF_ALL_PROXY_PASSWD; diff --git a/src/usage_text.h b/src/usage_text.h index ebf67e3d..55f79027 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -83,6 +83,9 @@ " previously defined proxy, use \"\".\n" \ " See also the --all-proxy option.\n" \ " This affects all ftp downloads.") +#define TEXT_BT_UDP_SOCKS_PROXY \ + _(" --bt-udp-socks-proxy=PROXY Use a SOCKS5 proxy server for UDP in BitTorrent.\n"\ + " This affects DHT and connecting UDP trackers in BitTorrent.") #define TEXT_ALL_PROXY \ _(" --all-proxy=PROXY Use a proxy server for all protocols. To override\n" \ " a previously defined proxy, use \"\".\n" \ @@ -690,6 +693,10 @@ _(" --ftp-proxy-user=USER Set user for --ftp-proxy.") #define TEXT_FTP_PROXY_PASSWD \ _(" --ftp-proxy-passwd=PASSWD Set password for --ftp-proxy.") +#define TEXT_BT_UDP_SOCKS_PROXY_USER \ + _(" --bt-udp-socks-proxy-user=USER Set user for --http-proxy.") +#define TEXT_BT_UDP_SOCKS_PROXY_PASSWD \ + _(" --bt-udp-socks-proxy-passwd=PASSWD Set password for --http-proxy.") #define TEXT_REMOVE_CONTROL_FILE \ _(" --remove-control-file[=true|false] Remove control file before download. Using\n" \ " with --allow-overwrite=true, download always\n" \