refactor: use tr_web instead of curl in transmission-show (#4281)

This commit is contained in:
Charles Kerr 2022-11-29 21:53:28 -06:00 committed by GitHub
parent 595d0ac14a
commit a0b5623769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 25 additions and 46 deletions

View File

@ -5,14 +5,13 @@
#include <algorithm>
#include <array>
#include <condition_variable>
#include <ctime>
#include <chrono>
#include <mutex>
#include <string>
#include <string_view>
#include <curl/curl.h>
#include <event2/buffer.h>
#include <fmt/chrono.h>
#include <fmt/core.h>
#include <fmt/format.h>
@ -28,6 +27,7 @@
#include <libtransmission/utils.h>
#include <libtransmission/variant.h>
#include <libtransmission/version.h>
#include <libtransmission/web.h>
#include <libtransmission/web-utils.h>
#include "units.h"
@ -37,11 +37,10 @@ using namespace std::literals;
namespace
{
auto constexpr TimeoutSecs = long{ 30 };
auto constexpr TimeoutSecs = std::chrono::seconds{ 30 };
char constexpr MyName[] = "transmission-show";
char constexpr Usage[] = "Usage: transmission-show [options] <torrent-file>";
char constexpr UserAgent[] = "transmission-show/" LONG_VERSION_STRING;
auto options = std::array<tr_option, 14>{
{ { 'd', "header", "Show only header section", "d", false, nullptr },
@ -304,30 +303,10 @@ void showInfo(app_opts const& opts, tr_torrent_metainfo const& metainfo)
}
}
size_t writeFunc(void* ptr, size_t size, size_t nmemb, void* vbuf)
{
auto* buf = static_cast<evbuffer*>(vbuf);
size_t const byteCount = size * nmemb;
evbuffer_add(buf, ptr, byteCount);
return byteCount;
}
CURL* tr_curl_easy_init(struct evbuffer* writebuf)
{
CURL* curl = curl_easy_init();
(void)curl_easy_setopt(curl, CURLOPT_USERAGENT, UserAgent);
(void)curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc);
(void)curl_easy_setopt(curl, CURLOPT_WRITEDATA, writebuf);
(void)curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
(void)curl_easy_setopt(curl, CURLOPT_VERBOSE, tr_env_key_exists("TR_CURL_VERBOSE"));
(void)curl_easy_setopt(curl, CURLOPT_ENCODING, "");
return curl;
}
void doScrape(tr_torrent_metainfo const& metainfo)
{
auto* const buf = evbuffer_new();
auto* const curl = tr_curl_easy_init(buf);
auto mediator = tr_web::Mediator{};
auto web = tr_web::create(mediator);
for (auto const& tracker : metainfo.announceList())
{
@ -345,28 +324,30 @@ void doScrape(tr_torrent_metainfo const& metainfo)
fflush(stdout);
// execute the http scrape
(void)curl_easy_setopt(curl, CURLOPT_URL, scrape_url.c_str());
(void)curl_easy_setopt(curl, CURLOPT_TIMEOUT, TimeoutSecs);
if (auto const res = curl_easy_perform(curl); res != CURLE_OK)
{
fmt::print("error: {:s}\n", curl_easy_strerror(res));
continue;
}
auto response = tr_web::FetchResponse{};
auto response_mutex = std::mutex{};
auto response_cv = std::condition_variable{};
auto lock = std::unique_lock(response_mutex);
web->fetch({ scrape_url,
[&response, &response_cv](tr_web::FetchResponse const& resp)
{
response = resp;
response_cv.notify_one();
},
nullptr,
TimeoutSecs });
response_cv.wait(lock);
// check the response code
long response;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response);
if (response != 200 /*HTTP OK*/)
if (auto const code = response.status; code != 200 /*HTTP OK*/)
{
fmt::print("error: unexpected response {:d} '{:s}'\n", response, tr_webGetResponseStr(response));
fmt::print("error: unexpected response {:d} '{:s}'\n", code, tr_webGetResponseStr(code));
continue;
}
// print it out
tr_variant top;
auto* const begin = (char const*)evbuffer_pullup(buf, -1);
if (auto sv = std::string_view{ begin, evbuffer_get_length(buf) };
!tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, sv))
auto top = tr_variant{};
if (!tr_variantFromBuf(&top, TR_VARIANT_PARSE_BENC | TR_VARIANT_PARSE_INPLACE, response.body))
{
fmt::print("error parsing scrape response\n");
continue;
@ -404,15 +385,13 @@ void doScrape(tr_torrent_metainfo const& metainfo)
fmt::print("no match\n");
}
}
curl_easy_cleanup(curl);
evbuffer_free(buf);
}
} // namespace
int tr_main(int argc, char* argv[])
{
tr_logSetQueueEnabled(false);
tr_logSetLevel(TR_LOG_ERROR);
tr_formatter_mem_init(MemK, MemKStr, MemMStr, MemGStr, MemTStr);
tr_formatter_size_init(DiskK, DiskKStr, DiskMStr, DiskGStr, DiskTStr);