diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f7068ec..dc74af4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,16 +44,6 @@ jobs: uses: microsoft/setup-msbuild@v1.3.1 if: runner.os == 'Windows' - # Note: we will be able to get rid of this once the whole tree of submodules has the latest version of oxen-logging - # We'd need oxen-libquic to be updated to have the commit `bc7167f90e71643b43c2ea9cf7d1fefa5045f8d4`, but we don't want to - # update libquic that late. - # We will soon, though :tm: - - name: Apply patches - if: runner.os == 'Windows' - shell: bash - run: | - yarn naughty-patch - - name: generate fake src/version.h so we can try to build shell: bash run: yarn update_version diff --git a/libsession-util b/libsession-util index 35e300d..e2eed34 160000 --- a/libsession-util +++ b/libsession-util @@ -1 +1 @@ -Subproject commit 35e300d0d67d56d42a76e11e3f8bdbb5145b8a92 +Subproject commit e2eed34ef25b3076a29000e43163bda832793159 diff --git a/package.json b/package.json index de26d2a..9161d81 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "update_version": "sh update_version.sh", "clean": "rimraf .cache build", "install": "cmake-js compile --runtime=electron --runtime-version=34.2.0 --CDSUBMODULE_CHECK=OFF --CDLOCAL_MIRROR=https://oxen.rocks/deps --CDENABLE_ONIONREQ=OFF --CDWITH_TESTS=OFF", - "naughty-patch": "git apply patches/oxen-libquic.patch", "prepare_release": "sh prepare_release.sh" }, "devDependencies": { diff --git a/patches/oxen-libquic.patch b/patches/oxen-libquic.patch deleted file mode 100644 index d0dad67..0000000 --- a/patches/oxen-libquic.patch +++ /dev/null @@ -1,16 +0,0 @@ -Submodule libsession-util contains modified content -Submodule external/oxen-libquic contains modified content -Submodule external/oxen-logging contains modified content -diff --git a/libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt b/libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt -index c8d0960..3b2d573 100644 ---- a/libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt -+++ b/libsession-util/external/oxen-libquic/external/oxen-logging/CMakeLists.txt -@@ -91,7 +91,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GRE - endif() - - add_library(oxen-logging-warnings INTERFACE) --target_compile_options(oxen-logging-warnings INTERFACE "$<$,$>:${warning_flags}>") -+#target_compile_options(oxen-logging-warnings INTERFACE "$<$,$>:${warning_flags}>") - target_link_libraries(oxen-logging INTERFACE oxen-logging-warnings) - - set(oxen_logging_source_roots "" CACHE INTERNAL "") diff --git a/prepare_release.sh b/prepare_release.sh index 3acee6c..0cf9079 100755 --- a/prepare_release.sh +++ b/prepare_release.sh @@ -13,8 +13,6 @@ rm -f ./libsession_util_nodejs*.tar.gz python -m venv .venv . .venv/bin/activate pip install git-archive-all -# see .github/workflows/test.yml for more info -yarn naughty-patch || true PACKAGE_VERSION=$(node -p "require('./package.json').version") yarn update_version echo "PACKAGE_VERSION: $PACKAGE_VERSION" diff --git a/src/base_config.cpp b/src/base_config.cpp index 57163f8..fe832d7 100644 --- a/src/base_config.cpp +++ b/src/base_config.cpp @@ -61,7 +61,7 @@ Napi::Value ConfigBaseImpl::merge(const Napi::CallbackInfo& info) { assertIsArray(info[0]); Napi::Array asArray = info[0].As(); - std::vector> conf_strs; + std::vector>> conf_strs; conf_strs.reserve(asArray.Length()); for (uint32_t i = 0; i < asArray.Length(); i++) { diff --git a/src/base_config.hpp b/src/base_config.hpp index e970936..6499da5 100644 --- a/src/base_config.hpp +++ b/src/base_config.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -13,8 +14,6 @@ #include "session/types.hpp" #include "utilities.hpp" -using ustring_view = std::basic_string_view; - namespace session::nodeapi { class ConfigBaseImpl; @@ -95,9 +94,9 @@ class ConfigBaseImpl { // we should get secret key as first arg and optional dumped as second argument assertIsUInt8Array(info[0], "base construct"); assertIsUInt8ArrayOrNull(info[1]); - ustring_view secretKey = toCppBufferView(info[0], class_name + ".new"); + std::span secretKey = toCppBufferView(info[0], class_name + ".new"); - std::optional dump; + std::optional> dump; auto second = info[1]; if (!second.IsEmpty() && !second.IsNull() && !second.IsUndefined()) dump = toCppBufferView(second, class_name + ".new"); diff --git a/src/blinding/blinding.hpp b/src/blinding/blinding.hpp index 39cc242..20bff52 100644 --- a/src/blinding/blinding.hpp +++ b/src/blinding/blinding.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "../meta/meta_base_wrapper.hpp" #include "../utilities.hpp" @@ -58,8 +59,7 @@ class BlindingWrapper : public Napi::ObjectWrap { auto keypair = session::blind_version_key_pair(ed25519_secret_key); session::uc32 pk_arr = std::get<0>(keypair); - ustring blinded_pk = session::ustring( - session::to_unsigned_sv(std::string(pk_arr.begin(), pk_arr.end()))); + std::vector blinded_pk = session::to_vector(pk_arr); std::string blinded_pk_hex; blinded_pk_hex.reserve(66); blinded_pk_hex += "07"; diff --git a/src/groups/meta_group.hpp b/src/groups/meta_group.hpp index a11d7be..18c53bf 100644 --- a/src/groups/meta_group.hpp +++ b/src/groups/meta_group.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "session/config/groups/info.hpp" #include "session/config/groups/keys.hpp" @@ -32,12 +33,12 @@ class MetaGroup { shared_ptr info, shared_ptr members, shared_ptr keys, - session::ustring edGroupPubKey, - std::optional edGroupSecKey) : - info{info}, members{members}, keys{keys}, edGroupPubKey{oxenc::to_hex(edGroupPubKey)} { + std::vector edGroupPubKey, + std::optional> edGroupSecKey) : + info{info}, members{members}, keys{keys}, edGroupPubKey{oxenc::to_hex(edGroupPubKey.begin(), edGroupPubKey.end())} { if (edGroupSecKey.has_value()) { - this->edGroupSecKey = oxenc::to_hex(*edGroupSecKey); + this->edGroupSecKey = oxenc::to_hex(edGroupSecKey->begin(), edGroupSecKey->end()); } else { this->edGroupSecKey = std::nullopt; } diff --git a/src/groups/meta_group_wrapper.cpp b/src/groups/meta_group_wrapper.cpp index 37deb0c..23561ad 100644 --- a/src/groups/meta_group_wrapper.cpp +++ b/src/groups/meta_group_wrapper.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include "oxenc/bt_producer.h" #include "session/types.hpp" @@ -208,12 +210,12 @@ Napi::Value MetaGroupWrapper::metaDump(const Napi::CallbackInfo& info) { oxenc::bt_dict_producer combined; // NOTE: the keys have to be in ascii-sorted order: - combined.append("info", session::from_unsigned_sv(this->meta_group->info->dump())); - combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->dump())); - combined.append("members", session::from_unsigned_sv(this->meta_group->members->dump())); + combined.append("info", session::to_string(this->meta_group->info->dump())); + combined.append("keys", session::to_string(this->meta_group->keys->dump())); + combined.append("members", session::to_string(this->meta_group->members->dump())); auto to_dump = std::move(combined).str(); - return session::ustring{to_unsigned_sv(to_dump)}; + return session::to_vector(to_dump); }); } @@ -222,13 +224,13 @@ Napi::Value MetaGroupWrapper::metaMakeDump(const Napi::CallbackInfo& info) { oxenc::bt_dict_producer combined; // NOTE: the keys have to be in ascii-sorted order: - combined.append("info", session::from_unsigned_sv(this->meta_group->info->make_dump())); - combined.append("keys", session::from_unsigned_sv(this->meta_group->keys->make_dump())); + combined.append("info", session::to_string(this->meta_group->info->make_dump())); + combined.append("keys", session::to_string(this->meta_group->keys->make_dump())); combined.append( - "members", session::from_unsigned_sv(this->meta_group->members->make_dump())); + "members", session::to_string(this->meta_group->members->make_dump())); auto to_dump = std::move(combined).str(); - return ustring{to_unsigned_sv(to_dump)}; + return session::to_vector(to_dump); }); } @@ -326,7 +328,7 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { assertIsArray(groupInfo); auto asArr = groupInfo.As(); - std::vector> conf_strs; + std::vector>> conf_strs; conf_strs.reserve(asArr.Length()); for (uint32_t i = 0; i < asArr.Length(); i++) { @@ -353,7 +355,7 @@ Napi::Value MetaGroupWrapper::metaMerge(const Napi::CallbackInfo& info) { assertIsArray(groupMember); auto asArr = groupMember.As(); - std::vector> conf_strs; + std::vector>> conf_strs; conf_strs.reserve(asArr.Length()); for (uint32_t i = 0; i < asArr.Length(); i++) { @@ -790,7 +792,7 @@ Napi::Value MetaGroupWrapper::encryptMessages(const Napi::CallbackInfo& info) { auto plaintextsJS = info[0].As(); uint32_t arrayLength = plaintextsJS.Length(); - std::vector encryptedMessages; + std::vector> encryptedMessages; encryptedMessages.reserve(arrayLength); for (uint32_t i = 0; i < plaintextsJS.Length(); i++) { @@ -820,10 +822,10 @@ Napi::Value MetaGroupWrapper::makeSwarmSubAccount(const Napi::CallbackInfo& info assertIsString(info[0]); auto memberPk = toCppString(info[0], "makeSwarmSubAccount"); - ustring subaccount = this->meta_group->keys->swarm_make_subaccount(memberPk); + std::vector subaccount = this->meta_group->keys->swarm_make_subaccount(memberPk); session::nodeapi::checkOrThrow( - subaccount.length() == 100, "expected subaccount to be 100 bytes long"); + subaccount.size() == 100, "expected subaccount to be 100 bytes long"); return subaccount; }); @@ -835,12 +837,12 @@ Napi::Value MetaGroupWrapper::swarmSubAccountToken(const Napi::CallbackInfo& inf assertIsString(info[0]); auto memberPk = toCppString(info[0], "swarmSubAccountToken"); - ustring subaccount = this->meta_group->keys->swarm_subaccount_token(memberPk); + std::vector subaccount = this->meta_group->keys->swarm_subaccount_token(memberPk); session::nodeapi::checkOrThrow( - subaccount.length() == 36, "expected subaccount token to be 36 bytes long"); + subaccount.size() == 36, "expected subaccount token to be 36 bytes long"); - return oxenc::to_hex(subaccount); + return oxenc::to_hex(subaccount.begin(), subaccount.end()); }); } diff --git a/src/meta/meta_base_wrapper.hpp b/src/meta/meta_base_wrapper.hpp index 75e71e9..83bbeae 100644 --- a/src/meta/meta_base_wrapper.hpp +++ b/src/meta/meta_base_wrapper.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include "../base_config.hpp" #include "../groups/meta_group.hpp" @@ -56,33 +58,33 @@ class MetaBaseWrapper { obj.Get("groupEd25519Pubkey"), class_name + ":constructGroupWrapper.groupEd25519Pubkey"); - std::optional group_ed25519_secretkey = maybeNonemptyBuffer( + std::optional> group_ed25519_secretkey = maybeNonemptyBuffer( obj.Get("groupEd25519Secretkey"), class_name + ":constructGroupWrapper.groupEd25519Secretkey"); - std::optional dumped_meta = maybeNonemptyBuffer( + std::optional> dumped_meta = maybeNonemptyBuffer( obj.Get("metaDumped"), class_name + ":constructGroupWrapper.metaDumped"); - std::optional dumped_info; - std::optional dumped_members; - std::optional dumped_keys; + std::optional> dumped_info; + std::optional> dumped_members; + std::optional> dumped_keys; if (dumped_meta) { - auto dumped_meta_str = from_unsigned_sv(*dumped_meta); + auto dumped_meta_str = to_string(*dumped_meta); oxenc::bt_dict_consumer combined{dumped_meta_str}; // NB: must read in ascii-sorted order: if (!combined.skip_until("info")) throw std::runtime_error{"info dump not found in combined dump!"}; - dumped_info = session::to_unsigned_sv(combined.consume_string_view()); + dumped_info = session::to_span(combined.consume_string_view()); if (!combined.skip_until("keys")) throw std::runtime_error{"keys dump not found in combined dump!"}; - dumped_keys = session::to_unsigned_sv(combined.consume_string_view()); + dumped_keys = session::to_span(combined.consume_string_view()); if (!combined.skip_until("members")) throw std::runtime_error{"members dump not found in combined dump!"}; - dumped_members = session::to_unsigned_sv(combined.consume_string_view()); + dumped_members = session::to_span(combined.consume_string_view()); } // Note, we keep shared_ptr for those as the Keys one need a reference to Members and diff --git a/src/multi_encrypt/multi_encrypt.hpp b/src/multi_encrypt/multi_encrypt.hpp index 6816fda..5980346 100644 --- a/src/multi_encrypt/multi_encrypt.hpp +++ b/src/multi_encrypt/multi_encrypt.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include @@ -58,7 +60,7 @@ class MultiEncryptWrapper : public Napi::ObjectWrap { auto messagesJSValue = obj.Get("messages"); assertIsArray(messagesJSValue); auto messagesJS = messagesJSValue.As(); - std::vector messages; + std::vector> messages; messages.reserve(messagesJS.Length()); for (uint32_t i = 0; i < messagesJS.Length(); i++) { auto itemValue = messagesJS.Get(i); @@ -71,7 +73,7 @@ class MultiEncryptWrapper : public Napi::ObjectWrap { auto recipientsJSValue = obj.Get("recipients"); assertIsArray(recipientsJSValue); auto recipientsJS = recipientsJSValue.As(); - std::vector recipients; + std::vector> recipients; recipients.reserve(recipientsJS.Length()); for (uint32_t i = 0; i < recipientsJS.Length(); i++) { auto itemValue = recipientsJS.Get(i); @@ -79,10 +81,10 @@ class MultiEncryptWrapper : public Napi::ObjectWrap { auto item = toCppBuffer(itemValue, "multiEncrypt.itemValue.recipient"); recipients.push_back(item); } - ustring random_nonce = session::random::random(24); + std::vector random_nonce = session::random::random(24); - std::vector messages_sv(messages.begin(), messages.end()); - std::vector recipients_sv(recipients.begin(), recipients.end()); + std::vector> messages_sv(messages.begin(), messages.end()); + std::vector> recipients_sv(recipients.begin(), recipients.end()); // Note: this function needs the first 2 args to be vector of sv explicitly return session::encrypt_for_multiple_simple( diff --git a/src/user_groups_config.cpp b/src/user_groups_config.cpp index 5ba47ea..f4d8424 100644 --- a/src/user_groups_config.cpp +++ b/src/user_groups_config.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "base_config.hpp" #include "community.hpp" @@ -158,7 +159,7 @@ Napi::Value UserGroupsWrapper::buildFullUrlFromDetails(const Napi::CallbackInfo& return wrapResult(env, [&]() { auto [baseUrl, roomId, pubkeyHex] = getStringArgs<3>(info); - ustring pubkey_bytes; + std::vector pubkey_bytes; if (!oxenc::is_hex(pubkeyHex.begin(), pubkeyHex.end())) throw std::invalid_argument{"community pubkey is not hex!"}; oxenc::from_hex(pubkeyHex.begin(), pubkeyHex.end(), std::back_inserter(pubkey_bytes)); diff --git a/src/utilities.cpp b/src/utilities.cpp index c130180..609503b 100644 --- a/src/utilities.cpp +++ b/src/utilities.cpp @@ -5,6 +5,7 @@ #include #include "session/config/namespaces.hpp" +#include "session/util.hpp" namespace session::nodeapi { @@ -87,9 +88,9 @@ std::optional maybeNonemptyString(Napi::Value x, const std::string& throw std::invalid_argument{"maybeNonemptyString with invalid type, called from " + identifier}; } -// Converts to a ustring_view that views directly into the Uint8Array data of `x`. Throws if x is -// not a Uint8Array. The view must not be used beyond the lifetime of `x`. -ustring_view toCppBufferView(Napi::Value x, const std::string& identifier) { +// Converts to a std::span that views directly into the Uint8Array data of `x`. +// Throws if x is not a Uint8Array. The view must not be used beyond the lifetime of `x`. +std::span toCppBufferView(Napi::Value x, const std::string& identifier) { if (x.IsNull() || x.IsUndefined()) throw std::invalid_argument( "toCppBuffer called with null or undefined with identifier: " + identifier); @@ -101,15 +102,16 @@ ustring_view toCppBufferView(Napi::Value x, const std::string& identifier) { return {u8Array.Data(), u8Array.ByteLength()}; } -ustring toCppBuffer(Napi::Value x, const std::string& identifier) { - return ustring{toCppBufferView(x, std::move(identifier))}; +std::vector toCppBuffer(Napi::Value x, const std::string& identifier) { + return session::to_vector(toCppBufferView(x, std::move(identifier))); } -std::optional maybeNonemptyBuffer(Napi::Value x, const std::string& identifier) { +std::optional> maybeNonemptyBuffer( + Napi::Value x, const std::string& identifier) { if (x.IsNull() || x.IsUndefined()) return std::nullopt; - std::optional buf{toCppBuffer(x, identifier)}; + std::optional> buf{toCppBuffer(x, identifier)}; if (buf->empty()) buf.reset(); return buf; @@ -172,7 +174,7 @@ std::string printable(const char* x, size_t n) { return printable(std::string_view{x, n}); } -std::string printable(ustring_view x) { +std::string printable(std::span x) { return printable(reinterpret_cast(x.data()), x.size()); } @@ -208,7 +210,7 @@ Napi::Object push_result_to_JS( Napi::Object push_key_entry_to_JS( const Napi::Env& env, - const session::ustring_view& key_data, + const std::span& key_data, const session::config::Namespace& push_namespace) { auto obj = Napi::Object::New(env); @@ -219,7 +221,7 @@ Napi::Object push_key_entry_to_JS( }; Napi::Object decrypt_result_to_JS( - const Napi::Env& env, const std::pair decrypted) { + const Napi::Env& env, const std::pair> decrypted) { auto obj = Napi::Object::New(env); obj["pubkeyHex"] = toJs(env, decrypted.first); diff --git a/src/utilities.hpp b/src/utilities.hpp index 1a0d8bd..1d26799 100644 --- a/src/utilities.hpp +++ b/src/utilities.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -53,8 +54,8 @@ auto getStringArgs(const Napi::CallbackInfo& info) { } std::string toCppString(Napi::Value x, const std::string& identifier); -ustring toCppBuffer(Napi::Value x, const std::string& identifier); -ustring_view toCppBufferView(Napi::Value x, const std::string& identifier); +std::vector toCppBuffer(Napi::Value x, const std::string& identifier); +std::span toCppBufferView(Napi::Value x, const std::string& identifier); int64_t toCppInteger(Napi::Value x, const std::string& identifier, bool allowUndefined = false); std::optional maybeNonemptyInt(Napi::Value x, const std::string& identifier); std::optional maybeNonemptyBoolean(Napi::Value x, const std::string& identifier); @@ -65,9 +66,10 @@ bool toCppBoolean(Napi::Value x, const std::string& identifier); // the value. Throws if something else. std::optional maybeNonemptyString(Napi::Value x, const std::string& identifier); -// If the object is null/undef/empty returns nullopt, otherwise if a Uint8Array returns a ustring of -// the value. Throws if something else. -std::optional maybeNonemptyBuffer(Napi::Value x, const std::string& identifier); +// If the object is null/undef/empty returns nullopt, otherwise if a Uint8Array returns a +// std::vector of the value. Throws if something else. +std::optional> maybeNonemptyBuffer( + Napi::Value x, const std::string& identifier); // Implementation struct of toJs(); we add specializations of this for any C++ types we want to be // able to convert into JS types. @@ -83,7 +85,7 @@ struct toJs_impl { // - bool -> Boolean // - other arithmetic types -> Number // - string, string_view -> String -// - ustring, ustring_view -> Buffer +// - std::vector, std::span -> Buffer // - std::vector -> Array, where elements are created via toJs calls on the vector elements. // - std::optional -> Null if empty, otherwise the result of toJs on the contained value // - Napi::Value (or derived) -> itself (this is mainly so that you can return a std::vector or @@ -120,8 +122,20 @@ struct toJs_impl> }; template -struct toJs_impl>> { - auto operator()(const Napi::Env& env, ustring_view b) const { +struct toJs_impl< + T, + std::enable_if_t< + std::is_convertible_v> && + !std::is_same_v, std::vector>>> { + auto operator()(const Napi::Env& env, std::span b) const { + return Napi::Buffer::Copy(env, b.data(), b.size()); + } +}; + +// this wrap std::vector to Uint8array in the js world +template <> +struct toJs_impl> { + auto operator()(const Napi::Env& env, std::vector b) const { return Napi::Buffer::Copy(env, b.data(), b.size()); } }; @@ -192,7 +206,7 @@ inline std::optional maybe_string(std::string_view val) { // - The return value will be returned as-is if it is already a Napi::Value (or subtype) // - The return will be void if void // - Otherwise the return value will be passed through toJs() to convert it to a Napi::Value. -// See toJs below, but generally this supports numeric types, bools, strings, ustrings, and vectors +// See toJs below, but generally this supports numeric types, bools, strings, spans, and vectors // of any of those primitives. // // General use is: @@ -242,7 +256,7 @@ auto wrapExceptions(const Napi::CallbackInfo& info, Call&& call) { std::string printable(std::string_view x); std::string printable(const char* x) = delete; std::string printable(const char* x, size_t n); -std::string printable(ustring_view x); +std::string printable(std::span x); /** * Keep the current priority if a wrapper @@ -253,7 +267,7 @@ int64_t unix_timestamp_now(); using push_entry_t = std::tuple< session::config::seqno_t, - session::ustring, + std::vector, std::vector>>; Napi::Object push_result_to_JS( @@ -263,10 +277,10 @@ Napi::Object push_result_to_JS( Napi::Object push_key_entry_to_JS( const Napi::Env& env, - const session::ustring_view& key_data, + const std::span& key_data, const session::config::Namespace& push_namespace); Napi::Object decrypt_result_to_JS( - const Napi::Env& env, const std::pair decrypted); + const Napi::Env& env, const std::pair> decrypted); } // namespace session::nodeapi