Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 4b9b992
Author: Charles Kerr <charles@charleskerr.com>
Date:   Mon Jun 19 16:51:34 2023 -0500

    refactor: prefer std::map over QMap in transmission-qt (#5641)

    * refactor: use std::map instead of QMap in PrefsDialog.cc

    * refactor: use std::map instead of QMap in DetailsDialog.cc

    * refactor: use std::map instead of QMap in OptionsDialog.cc

    * refactor: use std::map instead of QMap in FileTreeModel.cc

commit 040bc8a
Author: Dmitry Antipov <dmantipov@yandex.ru>
Date:   Tue Jun 20 00:22:54 2023 +0300

    fix: Qt 6.5 deprecation warning (#5552)

commit 23a52fa
Author: LaserEyess <16581533+LaserEyess@users.noreply.github.com>
Date:   Mon Jun 19 16:51:20 2023 -0400

    fixup: dedup tr_rpc_address with tr_address (#5523)

    * fixup: dedup tr_rpc_address with tr_address

    tr_rpc_address was duplicating a lot of work that tr_address was doing a
    lot better. Fall back to using tr_address for ipv4/ipv6 connections and
    make a tr_unix_addr for handling unix sockets.

    * remove unnecessary functions

commit ddac059
Author: Василий Чай <basilefff@gmail.com>
Date:   Mon Jun 19 09:30:55 2023 +0400

    fix: return error when renaming into existing file (#5563)

commit b8ff35c
Author: tearfur <46261767+tearfur@users.noreply.github.com>
Date:   Mon Jun 19 08:06:31 2023 +0800

    handle IPv6 NAT during LTEP handshake (#5565)

    * fix: peer handshake reported wrong ipv6 address

    #5542 (comment)

commit fd583ac
Author: Charles Kerr <charles@charleskerr.com>
Date:   Sun Jun 18 17:36:39 2023 -0500

    deps: bump libfmt to v10.0.0 (#5635)

    seems to be semver/minor safe for our API use

    Fixes #5511.

    Possibly fixes #5627.

commit 1664088
Author: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Date:   Sun Jun 18 15:55:43 2023 -0500

    chore: update generated transmission-web files (#5588)

commit 0fd7989
Author: Gary Elshaw <69029666+GaryElshaw@users.noreply.github.com>
Date:   Mon Jun 19 07:11:56 2023 +1200

    fix: restore png files that were corrupted in recent "compression" script

commit bd9d110
Author: Cœur <coeur@gmx.fr>
Date:   Sun Jun 18 20:32:34 2023 +0200

    fix 'setNeedsDisplay' is deprecated: first deprecated in macOS 10.14 (#5633)

commit 76166d8
Author: Cœur <coeur@gmx.fr>
Date:   Mon Jun 12 18:03:22 2023 +0200

    refactor: replace NSMutableDictionary with constant attributes (#5221)

commit c379cd7
Author: Robin Seth Ekman <robin.seth.ekman@gmail.com>
Date:   Mon Jun 12 03:19:54 2023 +0200

    fix: transmission-remote only list every other label (fixes #5571) (#5572)

commit 87f254a
Author: Charles Kerr <charles@charleskerr.com>
Date:   Sun Jun 11 18:52:45 2023 -0500

    chore: bump fast_float snaapshot to 5.2.0 (#5605)

commit 802619e
Author: tearfur <46261767+tearfur@users.noreply.github.com>
Date:   Mon Jun 12 07:27:01 2023 +0800

    fix: fixes and improvements to global IP query (#5510)

commit c8e84f8
Author: Charles Kerr <charles@charleskerr.com>
Date:   Sun Jun 11 16:28:43 2023 -0500

    ci: remove "brew update" step (#5606)

commit 60c68af
Author: Charles Kerr <charles@charleskerr.com>
Date:   Sun Jun 11 11:25:35 2023 -0500

    Revert "fix: some labels not displayed in transmission-remote (#5600)"

    This reverts commit ebd5080.

commit ebd5080
Author: Charles Kerr <charles@charleskerr.com>
Date:   Sat Jun 10 19:01:32 2023 -0500

    fix: some labels not displayed in transmission-remote (#5600)

    Fixes #5571.

commit 8ca02b8
Author: Mike Gelfand <mikedld@users.noreply.github.com>
Date:   Sun Jun 11 02:09:18 2023 +0400

    Avoid locale use in `tr_truncd()` (#5587)

    `tr_parseNum<>()` is implemented with `fast_float::from_chars()`, and
    the latter is documented as "expecting a locale-indepent format
    equivalent to what is used by std::strtod in the default ("C") locale".
    To accomodate locale independent number parsing, switch back to
    locale-independent number formatting in `tr_truncd()` by both removing a
    `L` format specifier from `fmt::format_to_n()` call and using a fixed
    "." decimal separator when truncating the value.

commit 0ef58c2
Author: Charles Kerr <charles@charleskerr.com>
Date:   Mon Jun 5 17:03:11 2023 -0500

    chore: improve lossless compression of png files (#5586)

commit c1c27f3
Author: Daniel Kamil Kozar <dkk089@gmail.com>
Date:   Mon Jun 5 20:15:32 2023 +0200

    Expose files' begin and end pieces via RPC (#5578)

    * Expose files' begin and end pieces via RPC

    This adds two arguments, `beginPiece` and `endPiece`, for each of the entries
    in the `files` array of the RPC's `torrent-`get` method.

    The point is to allow RPC clients to display a file's completion progress as
    piece-based in addition to byte-based.

commit 61679e1
Author: Cœur <coeur@gmx.fr>
Date:   Mon May 29 15:43:43 2023 +0200

    Support localized punctuation for "Port:" (#4452)

    * Support localized punctuation for "Port:"

    * Code review: adopting "Port: %@"

    * updating other locales for "Port" -> "Port: %@"
  • Loading branch information
ckerr committed Jun 19, 2023
1 parent a91372e commit 3519acf
Show file tree
Hide file tree
Showing 157 changed files with 678 additions and 465 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/actions.yml
Expand Up @@ -239,7 +239,6 @@ jobs:
sw_vers
- name: Get Dependencies
run: |
brew update
brew install cmake gettext libdeflate libevent libpsl miniupnpc ninja node pkg-config
- name: Get Dependencies (GTK)
if: ${{ needs.what-to-make.outputs.make-gtk == 'true' }}
Expand Down Expand Up @@ -513,7 +512,6 @@ jobs:
sw_vers
- name: Get Dependencies
run: |
brew update
brew install cmake gettext ninja node pkg-config
- name: Get Dependencies (GTK)
if: ${{ needs.what-to-make.outputs.make-gtk == 'true' }}
Expand Down
Binary file modified docs/resources/QT-Enable-Web-Lnx-1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/QT-Enable-Web-Lnx-2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/QT-Enable-Web-Lnx-3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/QT-Enable-Web-Win-1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/QT-Enable-Web-Win-2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-adding-torrent.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-display-filters-panel.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-list-of-added-torrents.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-main-screen.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-torrent-inspector-files-tab.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-torrent-inspector-peers-tab.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-torrent-inspector-trackers-tab.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-torrent-inspector.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/WI-torrent-management-panel.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/resources/mac-enable-web-2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions docs/rpc-spec.md
Expand Up @@ -294,6 +294,8 @@ The 'source' column here corresponds to the data structure there.
| `bytesCompleted` | number | tr_file_view
| `length` | number | tr_file_view
| `name` | string | tr_file_view
| `beginPiece` | number | tr_file_view
| `endPiece` | number | tr_file_view


`fileStats`: a file's non-constant properties. An array of `tr_info.filecount` objects, each containing:
Expand Down Expand Up @@ -1009,3 +1011,5 @@ Transmission 4.1.0 (`rpc-version-semver` 5.4.0, `rpc-version`: 18)
|:---|:---
| `torrent-get` | new arg `sequentialDownload`
| `torrent-set` | new arg `sequentialDownload`
| `torrent-get` | new arg `files.beginPiece`
| `torrent-get` | new arg `files.endPiece`
2 changes: 1 addition & 1 deletion gtk/Application.cc
Expand Up @@ -395,7 +395,7 @@ void register_magnet_link_handler()
_("Couldn't register Transmission as a {content_type} handler: {error} ({error_code})"),
fmt::arg("content_type", content_type),
fmt::arg("error", e.what()),
fmt::arg("error_code", e.code())));
fmt::arg("error_code", static_cast<int>(e.code()))));
}
}

Expand Down
Binary file modified icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion libtransmission/file-posix.cc
Expand Up @@ -556,7 +556,7 @@ tr_sys_file_t tr_sys_file_get_std(tr_std_sys_file_t std_file, tr_error** error)
break;

default:
TR_ASSERT_MSG(false, fmt::format(FMT_STRING("unknown standard file {:d}"), std_file));
TR_ASSERT_MSG(false, fmt::format(FMT_STRING("unknown standard file {:d}"), static_cast<int>(std_file)));
tr_error_set_from_errno(error, EINVAL);
}

Expand Down
185 changes: 100 additions & 85 deletions libtransmission/global-ip-cache.cc
Expand Up @@ -28,19 +28,37 @@ namespace

using namespace std::literals;

auto constexpr IPQueryServices = std::array{ "https://icanhazip.com"sv, "https://api64.ipify.org"sv };
static_assert(TR_AF_INET == 0);
static_assert(TR_AF_INET6 == 1);

auto constexpr protocol_str(tr_address_type type) noexcept
{
/* TODO: very slight performance nit
* - If upgrading to C++20, change Map to a consteval lambda:
* auto map = []() consteval { return std::array{ "IPv4"sv, "IPv6"sv }; };
* - If upgrading to C++23, change Map to static constexpr
*
* Ref: https://wg21.link/p2647r1
*/
auto constexpr Map = std::array{ "IPv4"sv, "IPv6"sv };
return Map[type];
}

auto constexpr IPQueryServices = std::array{ std::array{ "https://ip4.transmissionbt.com/"sv },
std::array{ "https://ip6.transmissionbt.com/"sv } };

auto constexpr UpkeepInterval = 30min;
auto constexpr RetryUpkeepInterval = 30s;

} // namespace

namespace
{
// Functions contained in external_source_ip_helpers are modified from code
// Functions contained in global_source_ip_helpers are modified from code
// by Juliusz Chroboczek and is covered under the same license as dht.cc.
// Please feel free to copy them into your software if it can help
// unbreaking the double-stack Internet.
namespace external_source_ip_helpers
namespace global_source_ip_helpers
{

// Get the source address used for a given destination address.
Expand Down Expand Up @@ -109,12 +127,12 @@ namespace external_source_ip_helpers
return {};
}

} // namespace external_source_ip_helpers
} // namespace global_source_ip_helpers
} // namespace

tr_global_ip_cache::tr_global_ip_cache(tr_web& web_in, libtransmission::TimerMaker& timer_maker_in)
: web_{ web_in }
, upkeep_timers_{ timer_maker_in.create(), timer_maker_in.create() }
tr_global_ip_cache::tr_global_ip_cache(Mediator& mediator_in)
: mediator_{ mediator_in }
, upkeep_timers_{ mediator_in.timer_maker().create(), mediator_in.timer_maker().create() }
{
static_assert(TR_AF_INET == 0);
static_assert(TR_AF_INET6 == 1);
Expand All @@ -132,6 +150,11 @@ tr_global_ip_cache::tr_global_ip_cache(tr_web& web_in, libtransmission::TimerMak
}
}

std::unique_ptr<tr_global_ip_cache> tr_global_ip_cache::create(tr_global_ip_cache::Mediator& mediator_in)
{
return std::unique_ptr<tr_global_ip_cache>(new tr_global_ip_cache(mediator_in));
}

tr_global_ip_cache::~tr_global_ip_cache()
{
// Destroying mutex while someone owns it is undefined behaviour, so we acquire it first
Expand Down Expand Up @@ -164,37 +187,21 @@ bool tr_global_ip_cache::try_shutdown() noexcept
return true;
}

void tr_global_ip_cache::set_settings_bind_addr(tr_address_type type, std::string_view bind_address) noexcept
{
settings_bind_addr_[type] = tr_address::from_string(bind_address);
if (settings_bind_addr_[type] && type != settings_bind_addr_[type]->type)
{
settings_bind_addr_[type].reset();
}
update_addr(type);
}

tr_address tr_global_ip_cache::bind_addr(tr_address_type type) const noexcept
{
if (type == TR_AF_INET || type == TR_AF_INET6)
{
return settings_bind_addr_[type].value_or(type == TR_AF_INET ? tr_address::any_ipv4() : tr_address::any_ipv6());
if (auto const addr = tr_address::from_string(mediator_.settings_bind_addr(type)); addr && type == addr->type)
{
return *addr;
}
return type == TR_AF_INET ? tr_address::any_ipv4() : tr_address::any_ipv6();
}

TR_ASSERT_MSG(false, "invalid type");
return {};
}

void tr_global_ip_cache::update_addr(tr_address_type type) noexcept
{
update_source_addr(type);
/* TODO: Temporarily disable because there is currently no way for this to work without using third party services */
// if (global_source_addr(type))
// {
// update_global_addr(type);
// }
}

bool tr_global_ip_cache::set_global_addr(tr_address_type type, tr_address const& addr) noexcept
{
if (type == addr.type && addr.is_global_unicast_address())
Expand All @@ -207,60 +214,19 @@ bool tr_global_ip_cache::set_global_addr(tr_address_type type, tr_address const&
return false;
}

void tr_global_ip_cache::unset_global_addr(tr_address_type type) noexcept
{
auto const lock = std::lock_guard{ global_addr_mutex_[type] };
global_addr_[type].reset();
tr_logAddTrace(fmt::format("Unset {} global address cache", type == TR_AF_INET ? "IPv4"sv : "IPv6"sv));
}

void tr_global_ip_cache::set_source_addr(tr_address const& addr) noexcept
{
auto const lock = std::lock_guard{ source_addr_mutex_[addr.type] };
source_addr_[addr.type] = addr;
tr_logAddTrace(fmt::format("Cached source address {}", addr.display_name()));
}

void tr_global_ip_cache::unset_addr(tr_address_type type) noexcept
{
auto const lock = std::lock_guard{ source_addr_mutex_[type] };
source_addr_[type].reset();
tr_logAddTrace(fmt::format("Unset {} source address cache", type == TR_AF_INET ? "IPv4"sv : "IPv6"sv));

// No public internet connectivity means no global IP address
unset_global_addr(type);
}

bool tr_global_ip_cache::set_is_updating(tr_address_type type) noexcept
void tr_global_ip_cache::update_addr(tr_address_type type) noexcept
{
auto lock = std::unique_lock{ is_updating_mutex_[type] };
is_updating_cv_[type].wait(
lock,
[this, type]() { return is_updating_[type] == is_updating_t::NO || is_updating_[type] == is_updating_t::ABORT; });
if (is_updating_[type] != is_updating_t::NO)
update_source_addr(type);
if (global_source_addr(type))
{
return false;
update_global_addr(type);
}
is_updating_[type] = is_updating_t::YES;
lock.unlock();
is_updating_cv_[type].notify_one();
return true;
}

void tr_global_ip_cache::unset_is_updating(tr_address_type type) noexcept
{
TR_ASSERT(is_updating_[type] == is_updating_t::YES);
auto lock = std::unique_lock{ is_updating_mutex_[type] };
is_updating_[type] = is_updating_t::NO;
lock.unlock();
is_updating_cv_[type].notify_one();
}

void tr_global_ip_cache::update_global_addr(tr_address_type type) noexcept
{
TR_ASSERT(has_ip_protocol_[type]);
TR_ASSERT(global_source_addr(type));
TR_ASSERT(ix_service_[type] < std::size(IPQueryServices));
TR_ASSERT(ix_service_[type] < std::size(IPQueryServices[type]));

if (ix_service_[type] == 0U && !set_is_updating(type))
{
Expand All @@ -269,19 +235,19 @@ void tr_global_ip_cache::update_global_addr(tr_address_type type) noexcept
TR_ASSERT(is_updating_[type] == is_updating_t::YES);

// Update global address
auto options = tr_web::FetchOptions{ IPQueryServices[ix_service_[type]],
auto options = tr_web::FetchOptions{ IPQueryServices[type][ix_service_[type]],
[this, type](tr_web::FetchResponse const& response)
{ this->on_response_ip_query(type, response); },
nullptr };
options.ip_proto = type == TR_AF_INET ? tr_web::FetchOptions::IPProtocol::V4 : tr_web::FetchOptions::IPProtocol::V6;
options.sndbuf = 4096;
options.rcvbuf = 4096;
web_.fetch(std::move(options));
mediator_.fetch(std::move(options));
}

void tr_global_ip_cache::update_source_addr(tr_address_type type) noexcept
{
using namespace external_source_ip_helpers;
using namespace global_source_ip_helpers;

TR_ASSERT(has_ip_protocol_[type]);

Expand All @@ -291,9 +257,9 @@ void tr_global_ip_cache::update_source_addr(tr_address_type type) noexcept
}
TR_ASSERT(is_updating_[type] == is_updating_t::YES);

auto const protocol = type == TR_AF_INET ? "IPv4"sv : "IPv6"sv;
auto const protocol = protocol_str(type);

auto err = int{};
auto err = int{ 0 };
auto const& source_addr = get_global_source_address(bind_addr(type), err);
if (source_addr)
{
Expand All @@ -308,7 +274,7 @@ void tr_global_ip_cache::update_source_addr(tr_address_type type) noexcept
// Stop the update process since we have no public internet connectivity
unset_addr(type);
upkeep_timers_[type]->set_interval(RetryUpkeepInterval);
tr_logAddDebug(fmt::format(_("Couldn't obtain source {protocol} address"), fmt::arg("protocol", protocol)));
tr_logAddDebug(fmt::format("Couldn't obtain source {} address", protocol));
if (err == EAFNOSUPPORT)
{
stop_timer(type); // No point in retrying
Expand All @@ -323,10 +289,10 @@ void tr_global_ip_cache::update_source_addr(tr_address_type type) noexcept
void tr_global_ip_cache::on_response_ip_query(tr_address_type type, tr_web::FetchResponse const& response) noexcept
{
TR_ASSERT(is_updating_[type] == is_updating_t::YES);
TR_ASSERT(ix_service_[type] < std::size(IPQueryServices));
TR_ASSERT(ix_service_[type] < std::size(IPQueryServices[type]));

auto const protocol = type == TR_AF_INET ? "IPv4"sv : "IPv6"sv;
auto success = bool{ false };
auto const protocol = protocol_str(type);
auto success = false;

if (response.status == 200 /* HTTP_OK */)
{
Expand All @@ -340,12 +306,12 @@ void tr_global_ip_cache::on_response_ip_query(tr_address_type type, tr_web::Fetc
_("Successfully updated global {type} address to {ip} using {url}"),
fmt::arg("type", protocol),
fmt::arg("ip", addr->display_name()),
fmt::arg("url", IPQueryServices[ix_service_[type]])));
fmt::arg("url", IPQueryServices[type][ix_service_[type]])));
}
}

// Try next IP query URL
if (!success && ++ix_service_[type] < std::size(IPQueryServices))
if (!success && ++ix_service_[type] < std::size(IPQueryServices[type]))
{
update_global_addr(type);
return;
Expand All @@ -361,3 +327,52 @@ void tr_global_ip_cache::on_response_ip_query(tr_address_type type, tr_web::Fetc
ix_service_[type] = 0U;
unset_is_updating(type);
}

void tr_global_ip_cache::unset_global_addr(tr_address_type type) noexcept
{
auto const lock = std::lock_guard{ global_addr_mutex_[type] };
global_addr_[type].reset();
tr_logAddTrace(fmt::format("Unset {} global address cache", protocol_str(type)));
}

void tr_global_ip_cache::set_source_addr(tr_address const& addr) noexcept
{
auto const lock = std::lock_guard{ source_addr_mutex_[addr.type] };
source_addr_[addr.type] = addr;
tr_logAddTrace(fmt::format("Cached source address {}", addr.display_name()));
}

void tr_global_ip_cache::unset_addr(tr_address_type type) noexcept
{
auto const lock = std::lock_guard{ source_addr_mutex_[type] };
source_addr_[type].reset();
tr_logAddTrace(fmt::format("Unset {} source address cache", protocol_str(type)));

// No public internet connectivity means no global IP address
unset_global_addr(type);
}

bool tr_global_ip_cache::set_is_updating(tr_address_type type) noexcept
{
auto lock = std::unique_lock{ is_updating_mutex_[type] };
is_updating_cv_[type].wait(
lock,
[this, type]() { return is_updating_[type] == is_updating_t::NO || is_updating_[type] == is_updating_t::ABORT; });
if (is_updating_[type] != is_updating_t::NO)
{
return false;
}
is_updating_[type] = is_updating_t::YES;
lock.unlock();
is_updating_cv_[type].notify_one();
return true;
}

void tr_global_ip_cache::unset_is_updating(tr_address_type type) noexcept
{
TR_ASSERT(is_updating_[type] == is_updating_t::YES);
auto lock = std::unique_lock{ is_updating_mutex_[type] };
is_updating_[type] = is_updating_t::NO;
lock.unlock();
is_updating_cv_[type].notify_one();
}

0 comments on commit 3519acf

Please sign in to comment.