Compare commits

..
Author SHA1 Message Date
Adrien Beraud 370f619ac4 python: support DESTDIR in pip install step
Use --root $DESTDIR when the environment variable is set so that
staged installs (e.g. 'make DESTDIR=/tmp/pkg install') place the
Python package under the staging root.

Also pass --no-build-isolation and --prefix to avoid rebuilding in an
isolated venv and to honour CMAKE_INSTALL_PREFIX.
2026-05-25 13:40:55 -04:00
10 changed files with 55 additions and 148 deletions

No files matched your search

-6
View File
@@ -159,13 +159,7 @@ public:
{}
static Value::Filter getFilter() { return EncryptedValue::getFilter(); }
virtual void unpackValue(const dht::Value& v) override
{
BaseClass::unpackValue(v);
id = v.id;
}
dht::Value::Id id {0}; /// Value ID of the trust request, used for deserialization only.
std::string service;
std::string conversationId;
Blob payload;
-20
View File
@@ -146,26 +146,6 @@ public:
std::shared_ptr<DhtRunner> getNode() const { return dht_; }
#ifdef OPENDHT_PUSH_NOTIFICATIONS
/**
* Decide whether a batch of values notified to a push listener must be
* delivered as a high (urgent) priority push notification.
*
* Only real-time call signaling — values whose pushType is "audioCall" or
* "videoCall", published at high priority (priority == 0) — warrants an
* urgent push. Every other notification (presence/connection-request
* refreshes carrying an empty pushType, value expirations, etc.) is sent at
* normal priority so it does not saturate the mobile platform's adaptive
* high-priority quota; once that quota is tripped, the platform silently
* drops genuine call pushes.
*
* @param values the values being notified to the listener.
* @param expired whether this notification is for expired (removed) values.
* @return true if the notification must be sent at high priority.
*/
static bool isHighPriorityPush(const std::vector<std::shared_ptr<Value>>& values, bool expired) noexcept;
#endif // OPENDHT_PUSH_NOTIFICATIONS
private:
class ConnectionListener;
struct RestRouterTraitsTls;
+14 -8
View File
@@ -51,11 +51,11 @@ using ConnectHandlerCb = std::function<void(const asio::error_code& ec, const as
using ssl_socket_t = restinio::impl::tls_socket_t;
using socket_t = asio::ip::tcp::socket;
struct OPENDHT_PUBLIC Url
class OPENDHT_PUBLIC Url
{
public:
Url() = default;
Url(std::string url);
Url(std::string_view url);
std::string url;
std::string protocol {"http"};
std::string_view user;
@@ -149,7 +149,7 @@ public:
using ResolverCb
= std::function<void(const asio::error_code& ec, const std::vector<asio::ip::tcp::endpoint>& endpoints)>;
Resolver(asio::io_context& ctx, std::string url, std::shared_ptr<log::Logger> logger = {});
Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<log::Logger> logger = {});
Resolver(asio::io_context& ctx,
std::string_view host,
std::string_view service,
@@ -161,6 +161,10 @@ public:
std::vector<asio::ip::tcp::endpoint> endpoints,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
Resolver(asio::io_context& ctx,
const std::string& url,
std::vector<asio::ip::tcp::endpoint> endpoints,
std::shared_ptr<log::Logger> logger = {});
~Resolver();
@@ -212,19 +216,19 @@ public:
// resolves implicitly
Request(asio::io_context& ctx,
std::string url,
const std::string& url,
const Json::Value& json,
OnJsonCb jsoncb,
std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, std::string url, OnJsonCb jsoncb, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, std::string url, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx,
std::string_view host,
std::string_view service,
const bool ssl = false,
std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, std::string url, OnDoneCb onDone, std::shared_ptr<log::Logger> logger = {});
Request(asio::io_context& ctx, const std::string& url, OnDoneCb onDone, std::shared_ptr<log::Logger> logger = {});
// user defined resolver
Request(asio::io_context& ctx, std::shared_ptr<Resolver> resolver, sa_family_t family = AF_UNSPEC);
@@ -340,6 +344,8 @@ private:
dht::crypto::Identity client_identity_;
std::shared_ptr<dht::crypto::Certificate> server_ca_;
std::string service_;
std::string host_;
unsigned int id_;
static std::atomic_uint ids_;
+11 -1
View File
@@ -28,8 +28,18 @@ install(CODE [[
if(NOT _pip_check EQUAL 0)
message(WARNING "Skipping Python package install: pip not available for ${Python3_EXECUTABLE}.")
else()
set(_pip_install_args
install
--no-deps
--no-build-isolation
--break-system-packages
--prefix ${CMAKE_INSTALL_PREFIX})
if(DEFINED ENV{DESTDIR} AND NOT "$ENV{DESTDIR}" STREQUAL "")
list(APPEND _pip_install_args --root "$ENV{DESTDIR}")
endif()
list(APPEND _pip_install_args .)
execute_process(
COMMAND ${Python3_EXECUTABLE} -m pip install --no-deps --break-system-packages .
COMMAND ${Python3_EXECUTABLE} -m pip ${_pip_install_args}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/python
OUTPUT_VARIABLE _pip_output
ERROR_VARIABLE _pip_error
-15
View File
@@ -36,19 +36,4 @@ base64_decode(std::string_view str)
return buffer;
}
std::vector<unsigned char>
base64_default_or_url_decode(std::string_view str)
{
std::vector<unsigned char> buffer(simdutf::maximal_binary_length_from_base64(str.data(), str.size()));
simdutf::result r = simdutf::base64_to_binary(str.data(),
str.size(),
(char*) buffer.data(),
simdutf::base64_options::base64_default_or_url);
if (r.error) {
throw std::invalid_argument(concat("Invalid base64 input: "sv, simdutf::error_to_string(r.error)));
} else {
buffer.resize(r.count);
}
return buffer;
}
} // namespace dht
+1 -8
View File
@@ -21,12 +21,5 @@ std::string base64_encode(const std::vector<unsigned char>& str);
* @return a base64-decoded buffer
*/
std::vector<unsigned char> base64_decode(std::string_view str);
/**
* Decode a buffer in base64 or url style base64 (including '-' '_' ).
*
* @param str the input buffer
* @return a base64-decoded buffer
*/
std::vector<unsigned char> base64_default_or_url_decode(std::string_view str);
} // namespace dht
} // namespace dht
+16 -31
View File
@@ -1134,25 +1134,6 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code& ec,
pushListeners_.erase(pushListener);
}
bool
DhtProxyServer::isHighPriorityPush(const std::vector<std::shared_ptr<Value>>& values, bool expired) noexcept
{
// Expired-value notifications (de-registration) are never time-critical.
if (expired)
return false;
// Promote to high (urgent) push priority only for real-time call signaling.
// Background traffic — most notably connection-request refreshes, which
// carry an empty pushType — stays at normal priority so it does not trip the
// mobile platform's adaptive high-priority quota, which would otherwise
// silently drop genuine call pushes once the high-priority noise ratio gets
// too high.
for (const auto& v : values) {
if (v->priority == 0 and (v->pushType == "videoCall" or v->pushType == "audioCall"))
return true;
}
return false;
}
bool
DhtProxyServer::handlePushListen(const InfoHash& infoHash,
const std::string& pushToken,
@@ -1195,23 +1176,20 @@ DhtProxyServer::handlePushListen(const InfoHash& infoHash,
json["exp"] = json["ids"];
}
const bool highPriority = isHighPriorityPush(values, expired);
auto minPriority = 1000u;
for (const auto& v : values)
minPriority = std::min(minPriority, v->priority);
if (logger_) {
auto minPriority = 1000u;
for (const auto& v : values)
minPriority = std::min(minPriority, v->priority);
logger_->debug("[proxy:server] [listen {}] [client {}] [session {}] [expired {}] [priority {}] [high {}] [values {}]",
if (logger_)
logger_->debug("[proxy:server] [listen {}] [client {}] [session {}] [expired {}] [priority {}] [values {}]",
infoHash,
clientId,
sessionCtx->sessionId,
expired,
minPriority,
highPriority,
values.size());
}
sendPushNotification(pushToken, std::move(json), type, highPriority, topic);
sendPushNotification(pushToken, std::move(json), type, !expired and minPriority == 0, topic);
return true;
}
@@ -1227,7 +1205,14 @@ DhtProxyServer::sendPushNotification(
try {
std::shared_ptr<http::Request> request;
if (type == PushType::UnifiedPush) {
request = std::make_shared<http::Request>(io_context(), token, logger_);
http::Url tokenUrl(token);
request = std::make_shared<http::Request>(io_context(),
concat(tokenUrl.protocol, "://"sv, tokenUrl.host),
tokenUrl.service,
tokenUrl.protocol.find("https") == 0,
logger_);
request->set_target(tokenUrl.target);
request->set_header_field(restinio::http_field_t::host, std::string(tokenUrl.host));
} else {
request = std::make_shared<http::Request>(io_context(),
pushHostPort_.first,
@@ -1246,8 +1231,8 @@ DhtProxyServer::sendPushNotification(
Blob auth; ///< Auth secret
auto delim = topicView.find('|');
if (delim != std::string_view::npos) {
pubKey = base64_default_or_url_decode(topicView.substr(0, delim));
auth = base64_default_or_url_decode(topicView.substr(delim + 1));
pubKey = base64_decode(topicView.substr(0, delim));
auth = base64_decode(topicView.substr(delim + 1));
}
request->set_header_field(restinio::http_field_t::ttl, "86400");
+13 -12
View File
@@ -42,8 +42,8 @@ constexpr std::string_view ORIGIN_PROTOCOL {"//"sv};
constexpr const char HTTP_HEADER_DELIM[] = "\r\n\r\n";
constexpr unsigned MAX_REDIRECTS {5};
Url::Url(std::string url_str)
: url(std::move(url_str))
Url::Url(std::string_view url_str)
: url(url_str)
{
std::string_view u = url;
if (u.empty())
@@ -830,8 +830,8 @@ Connection::timeout(const std::chrono::seconds& timeout, HandlerCb cb)
// Resolver
Resolver::Resolver(asio::io_context& ctx, std::string url, std::shared_ptr<dht::Logger> logger)
: url_(std::move(url))
Resolver::Resolver(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger)
: url_(url)
, resolver_(ctx)
, destroyed_(std::make_shared<bool>(false))
, logger_(logger)
@@ -967,14 +967,14 @@ Resolver::resolve(std::string_view host, std::string_view service)
std::atomic_uint Request::ids_ {1};
Request::Request(asio::io_context& ctx,
std::string url,
const std::string& url,
const Json::Value& json,
OnJsonCb jsoncb,
std::shared_ptr<dht::Logger> logger)
: logger_(std::move(logger))
, id_(Request::ids_++)
, ctx_(ctx)
, resolver_(std::make_shared<Resolver>(ctx, std::move(url), logger))
, resolver_(std::make_shared<Resolver>(ctx, url, logger))
{
init_default_headers();
set_header_field(restinio::http_field_t::content_type, std::string(HTTP_HEADER_CONTENT_TYPE_JSON));
@@ -997,11 +997,11 @@ Request::Request(asio::io_context& ctx,
});
}
Request::Request(asio::io_context& ctx, std::string url, OnJsonCb jsoncb, std::shared_ptr<dht::Logger> logger)
Request::Request(asio::io_context& ctx, const std::string& url, OnJsonCb jsoncb, std::shared_ptr<dht::Logger> logger)
: logger_(std::move(logger))
, id_(Request::ids_++)
, ctx_(ctx)
, resolver_(std::make_shared<Resolver>(ctx, std::move(url), logger))
, resolver_(std::make_shared<Resolver>(ctx, url, logger))
{
init_default_headers();
set_header_field(restinio::http_field_t::accept, std::string(HTTP_HEADER_CONTENT_TYPE_JSON));
@@ -1022,20 +1022,20 @@ Request::Request(asio::io_context& ctx, std::string url, OnJsonCb jsoncb, std::s
});
}
Request::Request(asio::io_context& ctx, std::string url, std::shared_ptr<dht::Logger> logger)
Request::Request(asio::io_context& ctx, const std::string& url, std::shared_ptr<dht::Logger> logger)
: logger_(logger)
, id_(Request::ids_++)
, ctx_(ctx)
, resolver_(std::make_shared<Resolver>(ctx, std::move(url), logger))
, resolver_(std::make_shared<Resolver>(ctx, url, logger))
{
init_default_headers();
}
Request::Request(asio::io_context& ctx, std::string url, OnDoneCb onDone, std::shared_ptr<dht::Logger> logger)
Request::Request(asio::io_context& ctx, const std::string& url, OnDoneCb onDone, std::shared_ptr<dht::Logger> logger)
: logger_(logger)
, id_(Request::ids_++)
, ctx_(ctx)
, resolver_(std::make_shared<Resolver>(ctx, std::move(url), logger))
, resolver_(std::make_shared<Resolver>(ctx, url, logger))
{
init_default_headers();
add_on_done_callback(std::move(onDone));
@@ -1086,6 +1086,7 @@ Request::Request(asio::io_context& ctx,
, family_(family)
, resolver_(resolver)
{
set_header_field(restinio::http_field_t::host, concat(get_url().host, ":", get_url().service));
set_target(Url(target).target);
}
-35
View File
@@ -327,39 +327,4 @@ DhtProxyTester::testShutdownStop()
CPPUNIT_ASSERT_EQUAL(2 * C, callback_count.load());
}
#ifdef OPENDHT_PUSH_NOTIFICATIONS
void
DhtProxyTester::testPushNotificationPriority()
{
auto mkValue = [](unsigned priority, const std::string& pushType) {
auto v = std::make_shared<dht::Value>();
v->priority = priority;
v->pushType = pushType;
return v;
};
// Real-time call signaling at high priority => urgent push.
CPPUNIT_ASSERT(dht::DhtProxyServer::isHighPriorityPush({mkValue(0, "videoCall")}, false));
CPPUNIT_ASSERT(dht::DhtProxyServer::isHighPriorityPush({mkValue(0, "audioCall")}, false));
// Connection-request refresh (empty pushType) is noise => normal push.
CPPUNIT_ASSERT(!dht::DhtProxyServer::isHighPriorityPush({mkValue(0, "")}, false));
// Any other pushType is not a call => normal push.
CPPUNIT_ASSERT(!dht::DhtProxyServer::isHighPriorityPush({mkValue(0, "message")}, false));
// Expired (de-registration) notifications are never urgent, even for calls.
CPPUNIT_ASSERT(!dht::DhtProxyServer::isHighPriorityPush({mkValue(0, "videoCall")}, true));
// A call value explicitly published at normal priority stays normal.
CPPUNIT_ASSERT(!dht::DhtProxyServer::isHighPriorityPush({mkValue(1, "videoCall")}, false));
// Mixed batch: a single high-priority call value is enough to make it urgent.
CPPUNIT_ASSERT(dht::DhtProxyServer::isHighPriorityPush({mkValue(0, ""), mkValue(0, "videoCall")}, false));
// Empty batch => normal.
CPPUNIT_ASSERT(!dht::DhtProxyServer::isHighPriorityPush({}, false));
}
#endif // OPENDHT_PUSH_NOTIFICATIONS
} // namespace test
-12
View File
@@ -21,9 +21,6 @@ class DhtProxyTester : public CppUnit::TestFixture
CPPUNIT_TEST(testPutGet40KChars);
CPPUNIT_TEST(testFuzzy);
CPPUNIT_TEST(testShutdownStop);
#ifdef OPENDHT_PUSH_NOTIFICATIONS
CPPUNIT_TEST(testPushNotificationPriority);
#endif
CPPUNIT_TEST_SUITE_END();
public:
@@ -58,15 +55,6 @@ public:
void testShutdownStop();
#ifdef OPENDHT_PUSH_NOTIFICATIONS
/**
* The proxy must only request a high-priority push for real-time call
* signaling (audioCall/videoCall at priority 0); everything else stays at
* normal priority.
*/
void testPushNotificationPriority();
#endif
private:
dht::DhtRunner::Config clientConfig {};
dht::DhtRunner nodePeer;