commits
tags
// Phase 0 toolchain proof: open an lt::session, add a well-known public-domain
// magnet (Sintel, the Blender Foundation's CC-licensed short film, commonly
// used as a test torrent), poll alerts for progress, and shut down cleanly.
#include <libtorrent/alert_types.hpp>
#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/magnet_uri.hpp>
#include <libtorrent/session.hpp>
#include <libtorrent/settings_pack.hpp>
#include <libtorrent/torrent_status.hpp>
#include <chrono>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <thread>
namespace lt = libtorrent;
namespace {
constexpr auto kMagnet =
"magnet:?xt=urn:btih:08ada5a7a6183aae1e09d831df6748d566095a10"
"&dn=Sintel"
"&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce"
"&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce";
}
int main() {
const auto save_path = std::filesystem::temp_directory_path() / "torlink-cpp-phase0";
std::filesystem::create_directories(save_path);
lt::settings_pack pack;
pack.set_int(lt::settings_pack::alert_mask,
lt::alert_category::status | lt::alert_category::error);
lt::session ses(pack);
lt::error_code ec;
lt::add_torrent_params params = lt::parse_magnet_uri(kMagnet, ec);
if (ec) {
std::cerr << "failed to parse magnet: " << ec.message() << "\n";
return 1;
}
params.save_path = save_path.string();
ses.async_add_torrent(std::move(params));
std::cout << "session started, listening on port "
<< ses.listen_port() << "\n";
std::cout << "watching '" << kMagnet << "' for 10s (save path: "
<< save_path << ")\n";
lt::torrent_handle handle;
for (int tick = 0; tick < 20; ++tick) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::vector<lt::alert*> alerts;
ses.pop_alerts(&alerts);
for (lt::alert* a : alerts) {
if (auto* at = lt::alert_cast<lt::add_torrent_alert>(a)) {
handle = at->handle;
std::cout << "[alert] torrent added: " << at->handle.status().name
<< "\n";
} else if (auto* mt = lt::alert_cast<lt::metadata_received_alert>(a)) {
std::cout << "[alert] metadata received: "
<< mt->handle.status().name << "\n";
} else if (auto* st = lt::alert_cast<lt::state_update_alert>(a)) {
for (const lt::torrent_status& s : st->status) {
std::cout << "[status] progress=" << (s.progress * 100.0) << "% "
<< "peers=" << s.num_peers << " "
<< "down=" << s.download_rate << "B/s"
<< "\n";
}
} else if (auto* et = lt::alert_cast<lt::torrent_error_alert>(a)) {
std::cout << "[alert] torrent error: " << et->message() << "\n";
} else if (auto* lf = lt::alert_cast<lt::listen_failed_alert>(a)) {
std::cout << "[alert] listen failed: " << lf->message() << "\n";
}
}
ses.post_torrent_updates();
}
if (handle.is_valid()) {
ses.remove_torrent(handle);
}
std::cout << "shutting down cleanly\n";
return 0;
}