mirror of
https://github.com/transmission/transmission.git
synced 2026-04-02 00:27:38 +01:00
refactor: C++ify tr_torrentPeers() (#8253)
* refactor: tr_torrentPeers() now returns a std::vector<tr_peer_stat> * refactor: make tr_peer_stat.client a std::string_view * refactor: make tr_peer_stat.flag_str a std::string * refactor: make tr_peer_stat.addr a std::string * refactor: rename tr_peer_stat field names to camel_case * refactor: use Speed type for tr_peer_stat speed fields * refactor: add default initializers to tr_peer_stat fields * refactor: order tr_peer_stat fields to reduce padding * fix: typo in [Torrent peers] getter * refactor: make tr_peer_stat.user_agent a std::string * refactor: pass by reference instead of by pointer in DetailsDialog * fixup! refactor: add default initializers to tr_peer_stat fields
This commit is contained in:
@@ -1088,17 +1088,17 @@ public:
|
||||
Gtk::TreeModelColumn<Glib::ustring> upload_rate_string;
|
||||
Gtk::TreeModelColumn<Glib::ustring> client;
|
||||
Gtk::TreeModelColumn<int> progress;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::activeReqsToClient)> upload_request_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::active_reqs_to_client)> upload_request_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> upload_request_count_string;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::activeReqsToPeer)> download_request_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::active_reqs_to_peer)> download_request_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> download_request_count_string;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::blocksToClient)> blocks_downloaded_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::blocks_to_client)> blocks_downloaded_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> blocks_downloaded_count_string;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::blocksToPeer)> blocks_uploaded_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::blocks_to_peer)> blocks_uploaded_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> blocks_uploaded_count_string;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::cancelsToPeer)> reqs_cancelled_by_client_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::cancels_to_peer)> reqs_cancelled_by_client_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> reqs_cancelled_by_client_count_string;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::cancelsToClient)> reqs_cancelled_by_peer_count_number;
|
||||
Gtk::TreeModelColumn<decltype(tr_peer_stat::cancels_to_client)> reqs_cancelled_by_peer_count_number;
|
||||
Gtk::TreeModelColumn<Glib::ustring> reqs_cancelled_by_peer_count_string;
|
||||
Gtk::TreeModelColumn<Glib::ustring> encryption_stock_id;
|
||||
Gtk::TreeModelColumn<Glib::ustring> flags;
|
||||
@@ -1111,21 +1111,13 @@ void initPeerRow(
|
||||
Gtk::TreeModel::iterator const& iter,
|
||||
std::string_view const key,
|
||||
std::string_view const torrent_name,
|
||||
tr_peer_stat const* peer)
|
||||
tr_peer_stat const& peer)
|
||||
{
|
||||
g_return_if_fail(peer != nullptr);
|
||||
|
||||
char const* client = peer->client;
|
||||
if (client == nullptr || g_strcmp0(client, "Unknown Client") == 0)
|
||||
{
|
||||
client = "";
|
||||
}
|
||||
|
||||
auto peer_addr4 = in_addr();
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
|
||||
auto const* const peer_addr4_octets = reinterpret_cast<uint8_t const*>(&peer_addr4.s_addr);
|
||||
auto const collated_name = inet_pton(AF_INET, std::data(peer->addr), &peer_addr4) != 1 ?
|
||||
std::data(peer->addr) :
|
||||
auto const collated_name = inet_pton(AF_INET, peer.addr.c_str(), &peer_addr4) != 1 ?
|
||||
peer.addr :
|
||||
fmt::format(
|
||||
"{:03}",
|
||||
fmt::join(
|
||||
@@ -1134,20 +1126,18 @@ void initPeerRow(
|
||||
peer_addr4_octets + sizeof(peer_addr4.s_addr), // TODO(C++20): Use std::span
|
||||
"."));
|
||||
|
||||
(*iter)[peer_cols.address] = std::data(peer->addr);
|
||||
(*iter)[peer_cols.address] = peer.addr;
|
||||
(*iter)[peer_cols.address_collated] = collated_name;
|
||||
(*iter)[peer_cols.client] = client;
|
||||
(*iter)[peer_cols.encryption_stock_id] = peer->isEncrypted ? "lock" : "";
|
||||
(*iter)[peer_cols.client] = peer.user_agent;
|
||||
(*iter)[peer_cols.encryption_stock_id] = peer.is_encrypted ? "lock" : "";
|
||||
(*iter)[peer_cols.key] = std::string(key);
|
||||
(*iter)[peer_cols.torrent_name] = std::string(torrent_name);
|
||||
}
|
||||
|
||||
void refreshPeerRow(Gtk::TreeModel::iterator const& iter, tr_peer_stat const* peer)
|
||||
void refreshPeerRow(Gtk::TreeModel::iterator const& iter, tr_peer_stat const& peer)
|
||||
{
|
||||
g_return_if_fail(peer != nullptr);
|
||||
|
||||
auto const down_speed = Speed{ peer->rateToClient_KBps, Speed::Units::KByps };
|
||||
auto const up_speed = Speed{ peer->rateToPeer_KBps, Speed::Units::KByps };
|
||||
auto const down_speed = peer.rate_to_client;
|
||||
auto const up_speed = peer.rate_to_peer;
|
||||
|
||||
auto blocks_to_client = std::string{};
|
||||
auto blocks_to_peer = std::string{};
|
||||
@@ -1158,64 +1148,64 @@ void refreshPeerRow(Gtk::TreeModel::iterator const& iter, tr_peer_stat const* pe
|
||||
auto up_count = std::string{};
|
||||
auto up_speed_string = std::string{};
|
||||
|
||||
if (peer->rateToPeer_KBps > 0.01)
|
||||
if (peer.rate_to_peer.base_quantity() > 0U)
|
||||
{
|
||||
up_speed_string = up_speed.to_string();
|
||||
}
|
||||
|
||||
if (peer->rateToClient_KBps > 0)
|
||||
if (peer.rate_to_client.base_quantity() > 0U)
|
||||
{
|
||||
down_speed_string = down_speed.to_string();
|
||||
}
|
||||
|
||||
if (peer->activeReqsToPeer > 0)
|
||||
if (peer.active_reqs_to_peer > 0)
|
||||
{
|
||||
down_count = std::to_string(peer->activeReqsToPeer);
|
||||
down_count = std::to_string(peer.active_reqs_to_peer);
|
||||
}
|
||||
|
||||
if (peer->activeReqsToClient > 0)
|
||||
if (peer.active_reqs_to_client > 0)
|
||||
{
|
||||
up_count = std::to_string(peer->activeReqsToClient);
|
||||
up_count = std::to_string(peer.active_reqs_to_client);
|
||||
}
|
||||
|
||||
if (peer->blocksToPeer > 0)
|
||||
if (peer.blocks_to_peer > 0)
|
||||
{
|
||||
blocks_to_peer = std::to_string(peer->blocksToPeer);
|
||||
blocks_to_peer = std::to_string(peer.blocks_to_peer);
|
||||
}
|
||||
|
||||
if (peer->blocksToClient > 0)
|
||||
if (peer.blocks_to_client > 0)
|
||||
{
|
||||
blocks_to_client = std::to_string(peer->blocksToClient);
|
||||
blocks_to_client = std::to_string(peer.blocks_to_client);
|
||||
}
|
||||
|
||||
if (peer->cancelsToPeer > 0)
|
||||
if (peer.cancels_to_peer > 0)
|
||||
{
|
||||
cancelled_by_client = std::to_string(peer->cancelsToPeer);
|
||||
cancelled_by_client = std::to_string(peer.cancels_to_peer);
|
||||
}
|
||||
|
||||
if (peer->cancelsToClient > 0)
|
||||
if (peer.cancels_to_client > 0)
|
||||
{
|
||||
cancelled_by_peer = std::to_string(peer->cancelsToClient);
|
||||
cancelled_by_peer = std::to_string(peer.cancels_to_client);
|
||||
}
|
||||
|
||||
(*iter)[peer_cols.progress] = static_cast<int>(100.0 * peer->progress);
|
||||
(*iter)[peer_cols.upload_request_count_number] = peer->activeReqsToClient;
|
||||
(*iter)[peer_cols.progress] = static_cast<int>(100.0 * peer.progress);
|
||||
(*iter)[peer_cols.upload_request_count_number] = peer.active_reqs_to_client;
|
||||
(*iter)[peer_cols.upload_request_count_string] = up_count;
|
||||
(*iter)[peer_cols.download_request_count_number] = peer->activeReqsToPeer;
|
||||
(*iter)[peer_cols.download_request_count_number] = peer.active_reqs_to_peer;
|
||||
(*iter)[peer_cols.download_request_count_string] = down_count;
|
||||
(*iter)[peer_cols.download_rate_speed] = down_speed;
|
||||
(*iter)[peer_cols.download_rate_string] = down_speed_string;
|
||||
(*iter)[peer_cols.upload_rate_speed] = up_speed;
|
||||
(*iter)[peer_cols.upload_rate_string] = up_speed_string;
|
||||
(*iter)[peer_cols.flags] = std::data(peer->flagStr);
|
||||
(*iter)[peer_cols.flags] = peer.flag_str;
|
||||
(*iter)[peer_cols.was_updated] = true;
|
||||
(*iter)[peer_cols.blocks_downloaded_count_number] = peer->blocksToClient;
|
||||
(*iter)[peer_cols.blocks_downloaded_count_number] = peer.blocks_to_client;
|
||||
(*iter)[peer_cols.blocks_downloaded_count_string] = blocks_to_client;
|
||||
(*iter)[peer_cols.blocks_uploaded_count_number] = peer->blocksToPeer;
|
||||
(*iter)[peer_cols.blocks_uploaded_count_number] = peer.blocks_to_peer;
|
||||
(*iter)[peer_cols.blocks_uploaded_count_string] = blocks_to_peer;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_client_count_number] = peer->cancelsToPeer;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_client_count_number] = peer.cancels_to_peer;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_client_count_string] = cancelled_by_client;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_peer_count_number] = peer->cancelsToClient;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_peer_count_number] = peer.cancels_to_client;
|
||||
(*iter)[peer_cols.reqs_cancelled_by_peer_count_string] = cancelled_by_peer;
|
||||
}
|
||||
|
||||
@@ -1227,16 +1217,12 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
|
||||
auto const& store = peer_store_;
|
||||
|
||||
/* step 1: get all the peers */
|
||||
std::vector<tr_peer_stat*> peers;
|
||||
std::vector<size_t> peerCount;
|
||||
std::vector<std::vector<tr_peer_stat>> peers;
|
||||
|
||||
peers.reserve(torrents.size());
|
||||
peerCount.reserve(torrents.size());
|
||||
for (auto const* const torrent : torrents)
|
||||
{
|
||||
size_t count = 0;
|
||||
peers.push_back(tr_torrentPeers(torrent, &count));
|
||||
peerCount.push_back(count);
|
||||
peers.push_back(tr_torrentPeers(torrent));
|
||||
}
|
||||
|
||||
/* step 2: mark all the peers in the list as not-updated */
|
||||
@@ -1245,25 +1231,25 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
|
||||
row[peer_cols.was_updated] = false;
|
||||
}
|
||||
|
||||
auto make_key = [](tr_torrent const* tor, tr_peer_stat const* ps)
|
||||
auto make_key = [](tr_torrent const* tor, tr_peer_stat const& ps)
|
||||
{
|
||||
return fmt::format("{:d}.{:s}", tr_torrentId(tor), ps->addr);
|
||||
return fmt::format("{:d}.{:s}", tr_torrentId(tor), ps.addr);
|
||||
};
|
||||
|
||||
/* step 3: add any new peers */
|
||||
for (size_t i = 0; i < torrents.size(); ++i)
|
||||
{
|
||||
auto const* tor = torrents.at(i);
|
||||
auto const& torrent_peers = peers.at(i);
|
||||
|
||||
for (size_t j = 0; j < peerCount[i]; ++j)
|
||||
for (auto const& peer : torrent_peers)
|
||||
{
|
||||
auto const* s = &peers.at(i)[j];
|
||||
auto const key = make_key(tor, s);
|
||||
auto const key = make_key(tor, peer);
|
||||
|
||||
if (hash.find(key) == hash.end())
|
||||
{
|
||||
auto const iter = store->append();
|
||||
initPeerRow(iter, key, tr_torrentName(tor), s);
|
||||
initPeerRow(iter, key, tr_torrentName(tor), peer);
|
||||
hash.try_emplace(key, Gtk::TreeRowReference(store, store->get_path(iter)));
|
||||
}
|
||||
}
|
||||
@@ -1273,12 +1259,12 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
|
||||
for (size_t i = 0; i < torrents.size(); ++i)
|
||||
{
|
||||
auto const* tor = torrents.at(i);
|
||||
auto const& torrent_peers = peers.at(i);
|
||||
|
||||
for (size_t j = 0; j < peerCount[i]; ++j)
|
||||
for (auto const& peer : torrent_peers)
|
||||
{
|
||||
auto const* s = &peers.at(i)[j];
|
||||
auto const key = make_key(tor, s);
|
||||
refreshPeerRow(store->get_iter(hash.at(key).get_path()), s);
|
||||
auto const key = make_key(tor, peer);
|
||||
refreshPeerRow(store->get_iter(hash.at(key).get_path()), peer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1299,12 +1285,6 @@ void DetailsDialog::Impl::refreshPeerList(std::vector<tr_torrent*> const& torren
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* step 6: cleanup */
|
||||
for (size_t i = 0; i < peers.size(); ++i)
|
||||
{
|
||||
tr_torrentPeersFree(peers[i], peerCount[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void DetailsDialog::Impl::refreshWebseedList(std::vector<tr_torrent*> const& torrents)
|
||||
|
||||
@@ -234,16 +234,14 @@ void announce_url_new(tr_urlbuf& url, tr_session const* session, tr_announce_req
|
||||
|
||||
if (auto ipv4_addr = session->global_address(TR_AF_INET); ipv4_addr)
|
||||
{
|
||||
auto buf = std::array<char, INET_ADDRSTRLEN>{};
|
||||
auto const display_name = ipv4_addr->display_name(std::data(buf), std::size(buf));
|
||||
auto const display_name = ipv4_addr->display_name();
|
||||
fmt::format_to(out, "&ipv4=");
|
||||
tr_urlPercentEncode(out, display_name);
|
||||
}
|
||||
|
||||
if (auto ipv6_addr = session->global_address(TR_AF_INET6); ipv6_addr)
|
||||
{
|
||||
auto buf = std::array<char, INET6_ADDRSTRLEN>{};
|
||||
auto const display_name = ipv6_addr->display_name(std::data(buf), std::size(buf));
|
||||
auto const display_name = ipv6_addr->display_name();
|
||||
fmt::format_to(out, "&ipv6=");
|
||||
tr_urlPercentEncode(out, display_name);
|
||||
}
|
||||
|
||||
@@ -472,20 +472,15 @@ std::optional<tr_address> tr_address::from_string(std::string_view address_sv)
|
||||
}
|
||||
}
|
||||
|
||||
std::string_view tr_address::display_name(char* out, size_t outlen) const
|
||||
{
|
||||
TR_ASSERT(is_valid());
|
||||
if (auto* name = evutil_inet_ntop(tr_ip_protocol_to_af(type), &addr, out, outlen))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
return "Invalid address"sv;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string tr_address::display_name() const
|
||||
{
|
||||
auto buf = std::array<char, std::max(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)>{};
|
||||
return std::string{ display_name(std::data(buf), std::size(buf)) };
|
||||
TR_ASSERT(is_valid());
|
||||
if (auto* name = evutil_inet_ntop(tr_ip_protocol_to_af(type), &addr, std::data(buf), std::size(buf)))
|
||||
{
|
||||
return std::string{ name };
|
||||
}
|
||||
return std::string{ "Invalid address" };
|
||||
}
|
||||
|
||||
std::pair<tr_address, std::byte const*> tr_address::from_compact_ipv4(std::byte const* compact) noexcept
|
||||
|
||||
@@ -159,7 +159,6 @@ struct tr_address
|
||||
[[nodiscard]] static std::pair<tr_address, std::byte const*> from_compact_ipv6(std::byte const* compact) noexcept;
|
||||
|
||||
// --- write the text form of the address, e.g. inet_ntop()
|
||||
std::string_view display_name(char* out, size_t outlen) const;
|
||||
[[nodiscard]] std::string display_name() const;
|
||||
|
||||
// ---
|
||||
|
||||
@@ -1831,121 +1831,118 @@ namespace peer_stat_helpers
|
||||
|
||||
auto const [addr, port] = peer->socket_address();
|
||||
|
||||
addr.display_name(stats.addr, sizeof(stats.addr));
|
||||
stats.client = peer->user_agent().c_str();
|
||||
stats.addr = addr.display_name();
|
||||
stats.user_agent = peer->user_agent();
|
||||
stats.peer_id = peer->peer_id();
|
||||
stats.port = port.host();
|
||||
stats.from = peer->peer_info->from_first();
|
||||
stats.progress = peer->percent_done();
|
||||
stats.isUTP = peer->is_utp_connection();
|
||||
stats.isEncrypted = peer->is_encrypted();
|
||||
stats.rateToPeer_KBps = peer->get_piece_speed(now_msec, tr_direction::ClientToPeer).count(Speed::Units::KByps);
|
||||
stats.rateToClient_KBps = peer->get_piece_speed(now_msec, tr_direction::PeerToClient).count(Speed::Units::KByps);
|
||||
stats.peerIsChoked = peer->peer_is_choked();
|
||||
stats.peerIsInterested = peer->peer_is_interested();
|
||||
stats.clientIsChoked = peer->client_is_choked();
|
||||
stats.clientIsInterested = peer->client_is_interested();
|
||||
stats.isIncoming = peer->is_incoming_connection();
|
||||
stats.isDownloadingFrom = peer->is_active(tr_direction::PeerToClient);
|
||||
stats.isUploadingTo = peer->is_active(tr_direction::ClientToPeer);
|
||||
stats.isSeed = peer->is_seed();
|
||||
stats.is_utp = peer->is_utp_connection();
|
||||
stats.is_encrypted = peer->is_encrypted();
|
||||
stats.rate_to_peer = peer->get_piece_speed(now_msec, tr_direction::ClientToPeer);
|
||||
stats.rate_to_client = peer->get_piece_speed(now_msec, tr_direction::PeerToClient);
|
||||
stats.peer_is_choked = peer->peer_is_choked();
|
||||
stats.peer_is_interested = peer->peer_is_interested();
|
||||
stats.client_is_choked = peer->client_is_choked();
|
||||
stats.client_is_interested = peer->client_is_interested();
|
||||
stats.is_incoming = peer->is_incoming_connection();
|
||||
stats.is_downloading_from = peer->is_active(tr_direction::PeerToClient);
|
||||
stats.is_uploading_to = peer->is_active(tr_direction::ClientToPeer);
|
||||
stats.is_seed = peer->is_seed();
|
||||
|
||||
stats.blocksToPeer = peer->blocks_sent_to_peer.count(now, CancelHistorySec);
|
||||
stats.blocksToClient = peer->blocks_sent_to_client.count(now, CancelHistorySec);
|
||||
stats.cancelsToPeer = peer->cancels_sent_to_peer.count(now, CancelHistorySec);
|
||||
stats.cancelsToClient = peer->cancels_sent_to_client.count(now, CancelHistorySec);
|
||||
stats.blocks_to_peer = peer->blocks_sent_to_peer.count(now, CancelHistorySec);
|
||||
stats.blocks_to_client = peer->blocks_sent_to_client.count(now, CancelHistorySec);
|
||||
stats.cancels_to_peer = peer->cancels_sent_to_peer.count(now, CancelHistorySec);
|
||||
stats.cancels_to_client = peer->cancels_sent_to_client.count(now, CancelHistorySec);
|
||||
|
||||
stats.bytes_to_peer = peer->bytes_sent_to_peer.count(now, CancelHistorySec);
|
||||
stats.bytes_to_client = peer->bytes_sent_to_client.count(now, CancelHistorySec);
|
||||
|
||||
stats.activeReqsToPeer = peer->active_req_count(tr_direction::ClientToPeer);
|
||||
stats.activeReqsToClient = peer->active_req_count(tr_direction::PeerToClient);
|
||||
stats.active_reqs_to_peer = peer->active_req_count(tr_direction::ClientToPeer);
|
||||
stats.active_reqs_to_client = peer->active_req_count(tr_direction::PeerToClient);
|
||||
|
||||
char* pch = stats.flagStr;
|
||||
stats.flag_str.clear();
|
||||
stats.flag_str.reserve(9);
|
||||
|
||||
if (stats.isUTP)
|
||||
if (stats.is_utp)
|
||||
{
|
||||
*pch++ = 'T';
|
||||
stats.flag_str.push_back('T');
|
||||
}
|
||||
|
||||
if (peer->swarm->optimistic == peer)
|
||||
{
|
||||
*pch++ = 'O';
|
||||
stats.flag_str.push_back('O');
|
||||
}
|
||||
|
||||
if (stats.isDownloadingFrom)
|
||||
if (stats.is_downloading_from)
|
||||
{
|
||||
*pch++ = 'D';
|
||||
stats.flag_str.push_back('D');
|
||||
}
|
||||
else if (stats.clientIsInterested)
|
||||
else if (stats.client_is_interested)
|
||||
{
|
||||
*pch++ = 'd';
|
||||
stats.flag_str.push_back('d');
|
||||
}
|
||||
|
||||
if (stats.isUploadingTo)
|
||||
if (stats.is_uploading_to)
|
||||
{
|
||||
*pch++ = 'U';
|
||||
stats.flag_str.push_back('U');
|
||||
}
|
||||
else if (stats.peerIsInterested)
|
||||
else if (stats.peer_is_interested)
|
||||
{
|
||||
*pch++ = 'u';
|
||||
stats.flag_str.push_back('u');
|
||||
}
|
||||
|
||||
if (!stats.clientIsChoked && !stats.clientIsInterested)
|
||||
if (!stats.client_is_choked && !stats.client_is_interested)
|
||||
{
|
||||
*pch++ = 'K';
|
||||
stats.flag_str.push_back('K');
|
||||
}
|
||||
|
||||
if (!stats.peerIsChoked && !stats.peerIsInterested)
|
||||
if (!stats.peer_is_choked && !stats.peer_is_interested)
|
||||
{
|
||||
*pch++ = '?';
|
||||
stats.flag_str.push_back('?');
|
||||
}
|
||||
|
||||
if (stats.isEncrypted)
|
||||
if (stats.is_encrypted)
|
||||
{
|
||||
*pch++ = 'E';
|
||||
stats.flag_str.push_back('E');
|
||||
}
|
||||
|
||||
if (stats.from == TR_PEER_FROM_DHT)
|
||||
{
|
||||
*pch++ = 'H';
|
||||
stats.flag_str.push_back('H');
|
||||
}
|
||||
else if (stats.from == TR_PEER_FROM_PEX)
|
||||
{
|
||||
*pch++ = 'X';
|
||||
stats.flag_str.push_back('X');
|
||||
}
|
||||
|
||||
if (stats.isIncoming)
|
||||
if (stats.is_incoming)
|
||||
{
|
||||
*pch++ = 'I';
|
||||
stats.flag_str.push_back('I');
|
||||
}
|
||||
|
||||
*pch = '\0';
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
} // namespace peer_stat_helpers
|
||||
} // namespace
|
||||
|
||||
tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, size_t* setme_count)
|
||||
std::vector<tr_peer_stat> tr_peerMgrPeerStats(tr_torrent const* tor)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
TR_ASSERT(tor->swarm->manager != nullptr);
|
||||
|
||||
auto const peers = tor->swarm->peers;
|
||||
auto const n = std::size(peers);
|
||||
auto* const ret = new tr_peer_stat[n];
|
||||
auto ret = std::vector<tr_peer_stat>(std::size(peers));
|
||||
|
||||
auto const lock = tor->unique_lock();
|
||||
auto const now = tr_time();
|
||||
auto const now_msec = tr_time_msec();
|
||||
std::ranges::transform(
|
||||
peers,
|
||||
ret,
|
||||
std::data(ret),
|
||||
[&now, &now_msec](auto const& peer) { return peer_stat_helpers::get_peer_stats(peer.get(), now, now_msec); });
|
||||
|
||||
*setme_count = n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -716,7 +716,7 @@ void tr_peerMgrTorrentAvailability(tr_torrent const* tor, int8_t* tab, unsigned
|
||||
|
||||
[[nodiscard]] uint64_t tr_peerMgrGetDesiredAvailable(tr_torrent const* tor);
|
||||
|
||||
[[nodiscard]] struct tr_peer_stat* tr_peerMgrPeerStats(tr_torrent const* tor, size_t* setme_count);
|
||||
[[nodiscard]] std::vector<tr_peer_stat> tr_peerMgrPeerStats(tr_torrent const* tor);
|
||||
|
||||
[[nodiscard]] tr_webseed_view tr_peerMgrWebseed(tr_torrent const* tor, size_t i);
|
||||
|
||||
|
||||
@@ -613,36 +613,33 @@ namespace make_torrent_field_helpers
|
||||
|
||||
[[nodiscard]] auto make_peer_vec(tr_torrent const& tor)
|
||||
{
|
||||
auto n_peers = size_t{};
|
||||
auto* const peers = tr_torrentPeers(&tor, &n_peers);
|
||||
auto const peers = tr_torrentPeers(&tor);
|
||||
auto peers_vec = tr_variant::Vector{};
|
||||
peers_vec.reserve(n_peers);
|
||||
for (size_t idx = 0U; idx != n_peers; ++idx)
|
||||
peers_vec.reserve(std::size(peers));
|
||||
for (auto const& peer : peers)
|
||||
{
|
||||
auto const& peer = peers[idx];
|
||||
auto peer_map = tr_variant::Map{ 19U };
|
||||
peer_map.try_emplace(TR_KEY_address, peer.addr);
|
||||
peer_map.try_emplace(TR_KEY_client_is_choked, peer.clientIsChoked);
|
||||
peer_map.try_emplace(TR_KEY_client_is_interested, peer.clientIsInterested);
|
||||
peer_map.try_emplace(TR_KEY_client_name, peer.client);
|
||||
peer_map.try_emplace(TR_KEY_client_is_choked, peer.client_is_choked);
|
||||
peer_map.try_emplace(TR_KEY_client_is_interested, peer.client_is_interested);
|
||||
peer_map.try_emplace(TR_KEY_client_name, peer.user_agent);
|
||||
peer_map.try_emplace(TR_KEY_peer_id, tr_base64_encode(std::string_view{ peer.peer_id.data(), peer.peer_id.size() }));
|
||||
peer_map.try_emplace(TR_KEY_flag_str, peer.flagStr);
|
||||
peer_map.try_emplace(TR_KEY_is_downloading_from, peer.isDownloadingFrom);
|
||||
peer_map.try_emplace(TR_KEY_is_encrypted, peer.isEncrypted);
|
||||
peer_map.try_emplace(TR_KEY_is_incoming, peer.isIncoming);
|
||||
peer_map.try_emplace(TR_KEY_is_utp, peer.isUTP);
|
||||
peer_map.try_emplace(TR_KEY_is_uploading_to, peer.isUploadingTo);
|
||||
peer_map.try_emplace(TR_KEY_peer_is_choked, peer.peerIsChoked);
|
||||
peer_map.try_emplace(TR_KEY_peer_is_interested, peer.peerIsInterested);
|
||||
peer_map.try_emplace(TR_KEY_flag_str, peer.flag_str);
|
||||
peer_map.try_emplace(TR_KEY_is_downloading_from, peer.is_downloading_from);
|
||||
peer_map.try_emplace(TR_KEY_is_encrypted, peer.is_encrypted);
|
||||
peer_map.try_emplace(TR_KEY_is_incoming, peer.is_incoming);
|
||||
peer_map.try_emplace(TR_KEY_is_utp, peer.is_utp);
|
||||
peer_map.try_emplace(TR_KEY_is_uploading_to, peer.is_uploading_to);
|
||||
peer_map.try_emplace(TR_KEY_peer_is_choked, peer.peer_is_choked);
|
||||
peer_map.try_emplace(TR_KEY_peer_is_interested, peer.peer_is_interested);
|
||||
peer_map.try_emplace(TR_KEY_port, peer.port);
|
||||
peer_map.try_emplace(TR_KEY_progress, peer.progress);
|
||||
peer_map.try_emplace(TR_KEY_rate_to_client, Speed{ peer.rateToClient_KBps, Speed::Units::KByps }.base_quantity());
|
||||
peer_map.try_emplace(TR_KEY_rate_to_peer, Speed{ peer.rateToPeer_KBps, Speed::Units::KByps }.base_quantity());
|
||||
peer_map.try_emplace(TR_KEY_rate_to_client, peer.rate_to_client.base_quantity());
|
||||
peer_map.try_emplace(TR_KEY_rate_to_peer, peer.rate_to_peer.base_quantity());
|
||||
peer_map.try_emplace(TR_KEY_bytes_to_peer, peer.bytes_to_peer);
|
||||
peer_map.try_emplace(TR_KEY_bytes_to_client, peer.bytes_to_client);
|
||||
peers_vec.emplace_back(std::move(peer_map));
|
||||
}
|
||||
tr_torrentPeersFree(peers, n_peers);
|
||||
return tr_variant{ std::move(peers_vec) };
|
||||
}
|
||||
|
||||
|
||||
@@ -1491,16 +1491,11 @@ std::string tr_torrentFilename(tr_torrent const* tor)
|
||||
|
||||
// ---
|
||||
|
||||
tr_peer_stat* tr_torrentPeers(tr_torrent const* tor, size_t* peer_count)
|
||||
std::vector<tr_peer_stat> tr_torrentPeers(tr_torrent const* tor)
|
||||
{
|
||||
TR_ASSERT(tr_isTorrent(tor));
|
||||
|
||||
return tr_peerMgrPeerStats(tor, peer_count);
|
||||
}
|
||||
|
||||
void tr_torrentPeersFree(tr_peer_stat* peer_stats, size_t /*peer_count*/)
|
||||
{
|
||||
delete[] peer_stats;
|
||||
return tr_peerMgrPeerStats(tor);
|
||||
}
|
||||
|
||||
void tr_torrentAvailability(tr_torrent const* tor, int8_t* tab, int size)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "libtransmission/tr-macros.h"
|
||||
#include "libtransmission/values.h"
|
||||
|
||||
using tr_file_index_t = size_t;
|
||||
using tr_piece_index_t = uint32_t;
|
||||
@@ -1139,60 +1140,58 @@ bool tr_torrentCanManualUpdate(tr_torrent const* torrent);
|
||||
|
||||
// --- tr_peer_stat
|
||||
|
||||
// NOLINTBEGIN(modernize-avoid-c-arrays)
|
||||
struct tr_peer_stat
|
||||
{
|
||||
bool isUTP;
|
||||
std::string addr;
|
||||
std::string flag_str;
|
||||
|
||||
bool isEncrypted;
|
||||
bool isDownloadingFrom;
|
||||
bool isUploadingTo;
|
||||
bool isSeed;
|
||||
// The user agent, e.g. `BitTorrent 7.9.1`.
|
||||
// Will be an empty string if the agent cannot be determined.
|
||||
std::string user_agent;
|
||||
|
||||
bool peerIsChoked;
|
||||
bool peerIsInterested;
|
||||
bool clientIsChoked;
|
||||
bool clientIsInterested;
|
||||
bool isIncoming;
|
||||
libtransmission::Values::Speed rate_to_peer;
|
||||
libtransmission::Values::Speed rate_to_client;
|
||||
|
||||
uint8_t from;
|
||||
uint16_t port;
|
||||
// how many requests the peer has made that we haven't responded to yet
|
||||
size_t active_reqs_to_client = {};
|
||||
|
||||
char addr[TrInet6AddrStrlen];
|
||||
char flagStr[32];
|
||||
char const* client;
|
||||
// how many requests we've made and are currently awaiting a response for
|
||||
size_t active_reqs_to_peer = {};
|
||||
|
||||
tr_peer_id_t peer_id;
|
||||
size_t bytes_to_peer = {};
|
||||
size_t bytes_to_client = {};
|
||||
|
||||
float progress;
|
||||
double rateToPeer_KBps;
|
||||
double rateToClient_KBps;
|
||||
tr_peer_id_t peer_id = {};
|
||||
|
||||
float progress = {};
|
||||
|
||||
// THESE NEXT FOUR FIELDS ARE EXPERIMENTAL.
|
||||
// Don't rely on them; they'll probably go away
|
||||
/* how many blocks we've sent to this peer in the last 120 seconds */
|
||||
uint32_t blocksToPeer;
|
||||
/* how many blocks this client's sent to us in the last 120 seconds */
|
||||
uint32_t blocksToClient;
|
||||
/* how many requests to this peer that we've cancelled in the last 120 seconds */
|
||||
uint32_t cancelsToPeer;
|
||||
/* how many requests this peer made of us, then cancelled, in the last 120 seconds */
|
||||
uint32_t cancelsToClient;
|
||||
// how many blocks we've sent to this peer in the last 120 seconds
|
||||
uint32_t blocks_to_peer = {};
|
||||
// how many blocks this client's sent to us in the last 120 seconds
|
||||
uint32_t blocks_to_client = {};
|
||||
// how many requests to this peer that we've cancelled in the last 120 seconds
|
||||
uint32_t cancels_to_peer = {};
|
||||
// how many requests this peer made of us, then cancelled, in the last 120 seconds
|
||||
uint32_t cancels_to_client = {};
|
||||
|
||||
/* how many requests the peer has made that we haven't responded to yet */
|
||||
size_t activeReqsToClient;
|
||||
uint16_t port = {};
|
||||
uint8_t from = {};
|
||||
|
||||
/* how many requests we've made and are currently awaiting a response for */
|
||||
size_t activeReqsToPeer;
|
||||
|
||||
size_t bytes_to_peer;
|
||||
size_t bytes_to_client;
|
||||
bool client_is_choked = {};
|
||||
bool client_is_interested = {};
|
||||
bool is_downloading_from = {};
|
||||
bool is_encrypted = {};
|
||||
bool is_incoming = {};
|
||||
bool is_seed = {};
|
||||
bool is_uploading_to = {};
|
||||
bool is_utp = {};
|
||||
bool peer_is_choked = {};
|
||||
bool peer_is_interested = {};
|
||||
};
|
||||
// NOLINTEND(modernize-avoid-c-arrays)
|
||||
|
||||
tr_peer_stat* tr_torrentPeers(tr_torrent const* torrent, size_t* peer_count);
|
||||
|
||||
void tr_torrentPeersFree(tr_peer_stat* peer_stats, size_t peer_count);
|
||||
std::vector<tr_peer_stat> tr_torrentPeers(tr_torrent const* torrent);
|
||||
|
||||
// --- tr_tracker_stat
|
||||
|
||||
|
||||
@@ -1006,41 +1006,38 @@ bool trashDataFile(std::string_view const filename, tr_error* error)
|
||||
|
||||
- (NSArray<NSDictionary*>*)peers
|
||||
{
|
||||
size_t totalPeers;
|
||||
tr_peer_stat* peers = tr_torrentPeers(self.fHandle, &totalPeers);
|
||||
auto const peers = tr_torrentPeers(self.fHandle);
|
||||
size_t const totalPeers = peers.size();
|
||||
|
||||
NSMutableArray* peerDicts = [NSMutableArray arrayWithCapacity:totalPeers];
|
||||
|
||||
for (size_t i = 0; i < totalPeers; i++)
|
||||
for (auto const& peer : peers)
|
||||
{
|
||||
tr_peer_stat* peer = &peers[i];
|
||||
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithCapacity:12];
|
||||
|
||||
dict[@"Name"] = self.name;
|
||||
dict[@"From"] = @(peer->from);
|
||||
dict[@"IP"] = @(peer->addr);
|
||||
dict[@"Port"] = @(peer->port);
|
||||
dict[@"Progress"] = @(peer->progress);
|
||||
dict[@"Seed"] = @(peer->isSeed);
|
||||
dict[@"Encryption"] = @(peer->isEncrypted);
|
||||
dict[@"uTP"] = @(peer->isUTP);
|
||||
dict[@"Client"] = @(peer->client);
|
||||
dict[@"Flags"] = @(peer->flagStr);
|
||||
dict[@"From"] = @(peer.from);
|
||||
dict[@"IP"] = tr_strv_to_utf8_nsstring(peer.addr);
|
||||
dict[@"Port"] = @(peer.port);
|
||||
dict[@"Progress"] = @(peer.progress);
|
||||
dict[@"Seed"] = @(peer.is_seed);
|
||||
dict[@"Encryption"] = @(peer.is_encrypted);
|
||||
dict[@"uTP"] = @(peer.is_utp);
|
||||
dict[@"Client"] = tr_strv_to_utf8_nsstring(peer.user_agent);
|
||||
dict[@"Flags"] = tr_strv_to_utf8_nsstring(peer.flag_str);
|
||||
|
||||
if (peer->isUploadingTo)
|
||||
if (peer.is_uploading_to)
|
||||
{
|
||||
dict[@"UL To Rate"] = @(peer->rateToPeer_KBps);
|
||||
dict[@"UL To Rate"] = @(peer.rate_to_peer.count(libtransmission::Values::Speed::Units::KByps));
|
||||
}
|
||||
if (peer->isDownloadingFrom)
|
||||
if (peer.is_downloading_from)
|
||||
{
|
||||
dict[@"DL From Rate"] = @(peer->rateToClient_KBps);
|
||||
dict[@"DL From Rate"] = @(peer.rate_to_client.count(libtransmission::Values::Speed::Units::KByps));
|
||||
}
|
||||
|
||||
[peerDicts addObject:dict];
|
||||
}
|
||||
|
||||
tr_torrentPeersFree(peers, totalPeers);
|
||||
|
||||
return peerDicts;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user