mirror of https://github.com/oxen-io/oxen-mq.git
Rename LokiMQ to OxenMQ
This commit is contained in:
parent
bd9313bf19
commit
2ae6b96016
142
CMakeLists.txt
142
CMakeLists.txt
|
@ -3,63 +3,63 @@ cmake_minimum_required(VERSION 3.7)
|
||||||
# Has to be set before `project()`, and ignored on non-macos:
|
# Has to be set before `project()`, and ignored on non-macos:
|
||||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "macOS deployment target (Apple clang only)")
|
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.12 CACHE STRING "macOS deployment target (Apple clang only)")
|
||||||
|
|
||||||
project(liblokimq CXX C)
|
project(liboxenmq CXX C)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(LOKIMQ_VERSION_MAJOR 1)
|
set(OXENMQ_VERSION_MAJOR 1)
|
||||||
set(LOKIMQ_VERSION_MINOR 2)
|
set(OXENMQ_VERSION_MINOR 2)
|
||||||
set(LOKIMQ_VERSION_PATCH 3)
|
set(OXENMQ_VERSION_PATCH 3)
|
||||||
set(LOKIMQ_VERSION "${LOKIMQ_VERSION_MAJOR}.${LOKIMQ_VERSION_MINOR}.${LOKIMQ_VERSION_PATCH}")
|
set(OXENMQ_VERSION "${OXENMQ_VERSION_MAJOR}.${OXENMQ_VERSION_MINOR}.${OXENMQ_VERSION_PATCH}")
|
||||||
message(STATUS "lokimq v${LOKIMQ_VERSION}")
|
message(STATUS "oxenmq v${OXENMQ_VERSION}")
|
||||||
|
|
||||||
set(LOKIMQ_LIBVERSION 0)
|
set(OXENMQ_LIBVERSION 0)
|
||||||
|
|
||||||
|
|
||||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||||
set(lokimq_IS_TOPLEVEL_PROJECT TRUE)
|
set(oxenmq_IS_TOPLEVEL_PROJECT TRUE)
|
||||||
else()
|
else()
|
||||||
set(lokimq_IS_TOPLEVEL_PROJECT FALSE)
|
set(oxenmq_IS_TOPLEVEL_PROJECT FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries instead of static ones" ON)
|
option(BUILD_SHARED_LIBS "Build shared libraries instead of static ones" ON)
|
||||||
set(lokimq_INSTALL_DEFAULT OFF)
|
set(oxenmq_INSTALL_DEFAULT OFF)
|
||||||
if(BUILD_SHARED_LIBS OR lokimq_IS_TOPLEVEL_PROJECT)
|
if(BUILD_SHARED_LIBS OR oxenmq_IS_TOPLEVEL_PROJECT)
|
||||||
set(lokimq_INSTALL_DEFAULT ON)
|
set(oxenmq_INSTALL_DEFAULT ON)
|
||||||
endif()
|
endif()
|
||||||
option(LOKIMQ_BUILD_TESTS "Building and perform lokimq tests" ${lokimq_IS_TOPLEVEL_PROJECT})
|
option(OXENMQ_BUILD_TESTS "Building and perform oxenmq tests" ${oxenmq_IS_TOPLEVEL_PROJECT})
|
||||||
option(LOKIMQ_INSTALL "Add lokimq libraries and headers to cmake install target; defaults to ON if BUILD_SHARED_LIBS is enabled or we are the top-level project; OFF for a static subdirectory build" ${lokimq_INSTALL_DEFAULT})
|
option(OXENMQ_INSTALL "Add oxenmq libraries and headers to cmake install target; defaults to ON if BUILD_SHARED_LIBS is enabled or we are the top-level project; OFF for a static subdirectory build" ${oxenmq_INSTALL_DEFAULT})
|
||||||
option(LOKIMQ_INSTALL_CPPZMQ "Install cppzmq header with lokimq/ headers (requires LOKIMQ_INSTALL)" ON)
|
option(OXENMQ_INSTALL_CPPZMQ "Install cppzmq header with oxenmq/ headers (requires OXENMQ_INSTALL)" ON)
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
configure_file(lokimq/version.h.in lokimq/version.h @ONLY)
|
configure_file(oxenmq/version.h.in oxenmq/version.h @ONLY)
|
||||||
configure_file(liblokimq.pc.in liblokimq.pc @ONLY)
|
configure_file(liboxenmq.pc.in liboxenmq.pc @ONLY)
|
||||||
|
|
||||||
add_library(lokimq
|
add_library(oxenmq
|
||||||
lokimq/address.cpp
|
oxenmq/address.cpp
|
||||||
lokimq/auth.cpp
|
oxenmq/auth.cpp
|
||||||
lokimq/bt_serialize.cpp
|
oxenmq/bt_serialize.cpp
|
||||||
lokimq/connections.cpp
|
oxenmq/connections.cpp
|
||||||
lokimq/jobs.cpp
|
oxenmq/jobs.cpp
|
||||||
lokimq/lokimq.cpp
|
oxenmq/oxenmq.cpp
|
||||||
lokimq/proxy.cpp
|
oxenmq/proxy.cpp
|
||||||
lokimq/worker.cpp
|
oxenmq/worker.cpp
|
||||||
)
|
)
|
||||||
set_target_properties(lokimq PROPERTIES SOVERSION ${LOKIMQ_LIBVERSION})
|
set_target_properties(oxenmq PROPERTIES SOVERSION ${OXENMQ_LIBVERSION})
|
||||||
|
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
target_link_libraries(lokimq PRIVATE Threads::Threads)
|
target_link_libraries(oxenmq PRIVATE Threads::Threads)
|
||||||
|
|
||||||
# libzmq is nearly impossible to link statically from a system-installed static library: it depends
|
# libzmq is nearly impossible to link statically from a system-installed static library: it depends
|
||||||
# on a ton of other libraries, some of which are not all statically available. If the caller wants
|
# on a ton of other libraries, some of which are not all statically available. If the caller wants
|
||||||
# to mess with this, so be it: they can set up a libzmq target and we'll use it. Otherwise if they
|
# to mess with this, so be it: they can set up a libzmq target and we'll use it. Otherwise if they
|
||||||
# asked us to do things statically, don't even try to find a system lib and just build it.
|
# asked us to do things statically, don't even try to find a system lib and just build it.
|
||||||
set(lokimq_build_static_libzmq OFF)
|
set(oxenmq_build_static_libzmq OFF)
|
||||||
if(TARGET libzmq)
|
if(TARGET libzmq)
|
||||||
target_link_libraries(lokimq PUBLIC libzmq)
|
target_link_libraries(oxenmq PUBLIC libzmq)
|
||||||
elseif(BUILD_SHARED_LIBS)
|
elseif(BUILD_SHARED_LIBS)
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
pkg_check_modules(libzmq libzmq>=4.3 IMPORTED_TARGET)
|
pkg_check_modules(libzmq libzmq>=4.3 IMPORTED_TARGET)
|
||||||
|
@ -75,30 +75,30 @@ elseif(BUILD_SHARED_LIBS)
|
||||||
set_property(TARGET PkgConfig::libzmq PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${zmq_inc})
|
set_property(TARGET PkgConfig::libzmq PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${zmq_inc})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(lokimq PUBLIC PkgConfig::libzmq)
|
target_link_libraries(oxenmq PUBLIC PkgConfig::libzmq)
|
||||||
else()
|
else()
|
||||||
set(lokimq_build_static_libzmq ON)
|
set(oxenmq_build_static_libzmq ON)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
set(lokimq_build_static_libzmq ON)
|
set(oxenmq_build_static_libzmq ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(lokimq_build_static_libzmq)
|
if(oxenmq_build_static_libzmq)
|
||||||
message(STATUS "libzmq >= 4.3 not found or static build requested, building bundled version")
|
message(STATUS "libzmq >= 4.3 not found or static build requested, building bundled version")
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/local-libzmq")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/local-libzmq")
|
||||||
include(LocalLibzmq)
|
include(LocalLibzmq)
|
||||||
target_link_libraries(lokimq PUBLIC libzmq_vendor)
|
target_link_libraries(oxenmq PUBLIC libzmq_vendor)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(lokimq
|
target_include_directories(oxenmq
|
||||||
PUBLIC
|
PUBLIC
|
||||||
$<INSTALL_INTERFACE:>
|
$<INSTALL_INTERFACE:>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/cppzmq>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/cppzmq>
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_options(lokimq PRIVATE -Wall -Wextra -Werror)
|
target_compile_options(oxenmq PRIVATE -Wall -Wextra -Werror)
|
||||||
set_target_properties(lokimq PROPERTIES
|
set_target_properties(oxenmq PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
CXX_STANDARD_REQUIRED ON
|
CXX_STANDARD_REQUIRED ON
|
||||||
CXX_EXTENSIONS OFF
|
CXX_EXTENSIONS OFF
|
||||||
|
@ -117,8 +117,8 @@ endfunction()
|
||||||
# If the caller has already set up a sodium target then we will just link to it, otherwise we go
|
# If the caller has already set up a sodium target then we will just link to it, otherwise we go
|
||||||
# looking for it.
|
# looking for it.
|
||||||
if(TARGET sodium)
|
if(TARGET sodium)
|
||||||
target_link_libraries(lokimq PUBLIC sodium)
|
target_link_libraries(oxenmq PUBLIC sodium)
|
||||||
if(lokimq_build_static_libzmq)
|
if(oxenmq_build_static_libzmq)
|
||||||
target_link_libraries(libzmq_vendor INTERFACE sodium)
|
target_link_libraries(libzmq_vendor INTERFACE sodium)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
@ -126,67 +126,67 @@ else()
|
||||||
pkg_check_modules(sodium REQUIRED libsodium IMPORTED_TARGET)
|
pkg_check_modules(sodium REQUIRED libsodium IMPORTED_TARGET)
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
target_link_libraries(lokimq PUBLIC PkgConfig::sodium)
|
target_link_libraries(oxenmq PUBLIC PkgConfig::sodium)
|
||||||
if(lokimq_build_static_libzmq)
|
if(oxenmq_build_static_libzmq)
|
||||||
target_link_libraries(libzmq_vendor INTERFACE PkgConfig::sodium)
|
target_link_libraries(libzmq_vendor INTERFACE PkgConfig::sodium)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
link_dep_libs(lokimq PUBLIC "${sodium_STATIC_LIBRARY_DIRS}" ${sodium_STATIC_LIBRARIES})
|
link_dep_libs(oxenmq PUBLIC "${sodium_STATIC_LIBRARY_DIRS}" ${sodium_STATIC_LIBRARIES})
|
||||||
target_include_directories(lokimq PUBLIC ${sodium_STATIC_INCLUDE_DIRS})
|
target_include_directories(oxenmq PUBLIC ${sodium_STATIC_INCLUDE_DIRS})
|
||||||
if(lokimq_build_static_libzmq)
|
if(oxenmq_build_static_libzmq)
|
||||||
link_dep_libs(libzmq_vendor INTERFACE "${sodium_STATIC_LIBRARY_DIRS}" ${sodium_STATIC_LIBRARIES})
|
link_dep_libs(libzmq_vendor INTERFACE "${sodium_STATIC_LIBRARY_DIRS}" ${sodium_STATIC_LIBRARIES})
|
||||||
target_link_libraries(libzmq_vendor INTERFACE ${sodium_STATIC_INCLUDE_DIRS})
|
target_link_libraries(libzmq_vendor INTERFACE ${sodium_STATIC_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(lokimq::lokimq ALIAS lokimq)
|
add_library(oxenmq::oxenmq ALIAS oxenmq)
|
||||||
|
|
||||||
export(
|
export(
|
||||||
TARGETS lokimq
|
TARGETS oxenmq
|
||||||
NAMESPACE lokimq::
|
NAMESPACE oxenmq::
|
||||||
FILE lokimqTargets.cmake
|
FILE oxenmqTargets.cmake
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LOKIMQ_INSTALL)
|
if(OXENMQ_INSTALL)
|
||||||
install(
|
install(
|
||||||
TARGETS lokimq
|
TARGETS oxenmq
|
||||||
EXPORT lokimqConfig
|
EXPORT oxenmqConfig
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
FILES lokimq/address.h
|
FILES oxenmq/address.h
|
||||||
lokimq/auth.h
|
oxenmq/auth.h
|
||||||
lokimq/base32z.h
|
oxenmq/base32z.h
|
||||||
lokimq/base64.h
|
oxenmq/base64.h
|
||||||
lokimq/batch.h
|
oxenmq/batch.h
|
||||||
lokimq/bt_serialize.h
|
oxenmq/bt_serialize.h
|
||||||
lokimq/bt_value.h
|
oxenmq/bt_value.h
|
||||||
lokimq/connections.h
|
oxenmq/connections.h
|
||||||
lokimq/hex.h
|
oxenmq/hex.h
|
||||||
lokimq/lokimq.h
|
oxenmq/oxenmq.h
|
||||||
lokimq/message.h
|
oxenmq/message.h
|
||||||
lokimq/string_view.h
|
oxenmq/string_view.h
|
||||||
lokimq/variant.h
|
oxenmq/variant.h
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/lokimq/version.h
|
${CMAKE_CURRENT_BINARY_DIR}/oxenmq/version.h
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lokimq
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/oxenmq
|
||||||
)
|
)
|
||||||
|
|
||||||
if(LOKIMQ_INSTALL_CPPZMQ)
|
if(OXENMQ_INSTALL_CPPZMQ)
|
||||||
install(
|
install(
|
||||||
FILES cppzmq/zmq.hpp
|
FILES cppzmq/zmq.hpp
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/lokimq
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/oxenmq
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/liblokimq.pc
|
FILES ${CMAKE_CURRENT_BINARY_DIR}/liboxenmq.pc
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(LOKIMQ_BUILD_TESTS)
|
if(OXENMQ_BUILD_TESTS)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -3,11 +3,11 @@ exec_prefix=${prefix}
|
||||||
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||||
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||||
|
|
||||||
Name: liblokimq
|
Name: liboxenmq
|
||||||
Description: ZeroMQ-based communication library for Loki
|
Description: ZeroMQ-based communication library
|
||||||
Version: @LOKIMQ_VERSION@
|
Version: @OXENMQ_VERSION@
|
||||||
|
|
||||||
Libs: -L${libdir} -llokimq
|
Libs: -L${libdir} -loxenmq
|
||||||
Libs.private: @PRIVATE_LIBS@
|
Libs.private: @PRIVATE_LIBS@
|
||||||
Requires.private: libzmq libsodium
|
Requires.private: libzmq libsodium
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
|
@ -1,5 +0,0 @@
|
||||||
namespace lokimq {
|
|
||||||
constexpr int VERSION_MAJOR = @LOKIMQ_VERSION_MAJOR@;
|
|
||||||
constexpr int VERSION_MINOR = @LOKIMQ_VERSION_MINOR@;
|
|
||||||
constexpr int VERSION_PATCH = @LOKIMQ_VERSION_PATCH@;
|
|
||||||
}
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "base32z.h"
|
#include "base32z.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
constexpr size_t enc_length(address::encoding enc) {
|
constexpr size_t enc_length(address::encoding enc) {
|
||||||
return enc == address::encoding::hex ? 64 :
|
return enc == address::encoding::hex ? 64 :
|
||||||
|
@ -23,13 +23,13 @@ constexpr size_t enc_length(address::encoding enc) {
|
||||||
// given: for QR-friendly we only accept hex or base32z (since QR cannot handle base64's alphabet).
|
// given: for QR-friendly we only accept hex or base32z (since QR cannot handle base64's alphabet).
|
||||||
std::string decode_pubkey(std::string_view& in, bool qr) {
|
std::string decode_pubkey(std::string_view& in, bool qr) {
|
||||||
std::string pubkey;
|
std::string pubkey;
|
||||||
if (in.size() >= 64 && lokimq::is_hex(in.substr(0, 64))) {
|
if (in.size() >= 64 && is_hex(in.substr(0, 64))) {
|
||||||
pubkey = from_hex(in.substr(0, 64));
|
pubkey = from_hex(in.substr(0, 64));
|
||||||
in.remove_prefix(64);
|
in.remove_prefix(64);
|
||||||
} else if (in.size() >= 52 && lokimq::is_base32z(in.substr(0, 52))) {
|
} else if (in.size() >= 52 && is_base32z(in.substr(0, 52))) {
|
||||||
pubkey = from_base32z(in.substr(0, 52));
|
pubkey = from_base32z(in.substr(0, 52));
|
||||||
in.remove_prefix(52);
|
in.remove_prefix(52);
|
||||||
} else if (!qr && in.size() >= 43 && lokimq::is_base64(in.substr(0, 43))) {
|
} else if (!qr && in.size() >= 43 && is_base64(in.substr(0, 43))) {
|
||||||
pubkey = from_base64(in.substr(0, 43));
|
pubkey = from_base64(in.substr(0, 43));
|
||||||
in.remove_prefix(43);
|
in.remove_prefix(43);
|
||||||
if (!in.empty() && in.front() == '=')
|
if (!in.empty() && in.front() == '=')
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2020, The Loki Project
|
// Copyright (c) 2020-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -32,11 +32,11 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
/** LokiMQ address abstraction class. This class uses and extends standard ZMQ addresses allowing
|
/** OxenMQ address abstraction class. This class uses and extends standard ZMQ addresses allowing
|
||||||
* extra parameters to be passed in in a relative standard way.
|
* extra parameters to be passed in in a relative standard way.
|
||||||
*
|
*
|
||||||
* External ZMQ addresses generally have two forms that we are concerned with: one for TCP and one
|
* External ZMQ addresses generally have two forms that we are concerned with: one for TCP and one
|
|
@ -1,10 +1,10 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o, AuthLevel a) {
|
std::ostream& operator<<(std::ostream& o, AuthLevel a) {
|
||||||
return o << to_string(a);
|
return o << to_string(a);
|
||||||
|
@ -31,7 +31,7 @@ std::string zmtp_metadata(std::string_view key, std::string_view value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LokiMQ::proxy_check_auth(size_t conn_index, bool outgoing, const peer_info& peer,
|
bool OxenMQ::proxy_check_auth(size_t conn_index, bool outgoing, const peer_info& peer,
|
||||||
zmq::message_t& cmd, const cat_call_t& cat_call, std::vector<zmq::message_t>& data) {
|
zmq::message_t& cmd, const cat_call_t& cat_call, std::vector<zmq::message_t>& data) {
|
||||||
auto command = view(cmd);
|
auto command = view(cmd);
|
||||||
std::string reply;
|
std::string reply;
|
||||||
|
@ -45,7 +45,7 @@ bool LokiMQ::proxy_check_auth(size_t conn_index, bool outgoing, const peer_info&
|
||||||
reply = "FORBIDDEN";
|
reply = "FORBIDDEN";
|
||||||
} else if (cat_call.first->access.local_sn && !local_service_node) {
|
} else if (cat_call.first->access.local_sn && !local_service_node) {
|
||||||
LMQ_LOG(warn, "Access denied to ", command, " for peer [", to_hex(peer.pubkey), "]/", peer_address(cmd),
|
LMQ_LOG(warn, "Access denied to ", command, " for peer [", to_hex(peer.pubkey), "]/", peer_address(cmd),
|
||||||
": that command is only available when this LokiMQ is running in service node mode");
|
": that command is only available when this OxenMQ is running in service node mode");
|
||||||
reply = "NOT_A_SERVICE_NODE";
|
reply = "NOT_A_SERVICE_NODE";
|
||||||
} else if (cat_call.first->access.remote_sn && !peer.service_node) {
|
} else if (cat_call.first->access.remote_sn && !peer.service_node) {
|
||||||
LMQ_LOG(warn, "Access denied to ", command, " for peer [", to_hex(peer.pubkey), "]/", peer_address(cmd),
|
LMQ_LOG(warn, "Access denied to ", command, " for peer [", to_hex(peer.pubkey), "]/", peer_address(cmd),
|
||||||
|
@ -81,7 +81,7 @@ bool LokiMQ::proxy_check_auth(size_t conn_index, bool outgoing, const peer_info&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::set_active_sns(pubkey_set pubkeys) {
|
void OxenMQ::set_active_sns(pubkey_set pubkeys) {
|
||||||
if (proxy_thread.joinable()) {
|
if (proxy_thread.joinable()) {
|
||||||
auto data = bt_serialize(detail::serialize_object(std::move(pubkeys)));
|
auto data = bt_serialize(detail::serialize_object(std::move(pubkeys)));
|
||||||
detail::send_control(get_control_socket(), "SET_SNS", data);
|
detail::send_control(get_control_socket(), "SET_SNS", data);
|
||||||
|
@ -89,10 +89,10 @@ void LokiMQ::set_active_sns(pubkey_set pubkeys) {
|
||||||
proxy_set_active_sns(std::move(pubkeys));
|
proxy_set_active_sns(std::move(pubkeys));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void LokiMQ::proxy_set_active_sns(std::string_view data) {
|
void OxenMQ::proxy_set_active_sns(std::string_view data) {
|
||||||
proxy_set_active_sns(detail::deserialize_object<pubkey_set>(bt_deserialize<uintptr_t>(data)));
|
proxy_set_active_sns(detail::deserialize_object<pubkey_set>(bt_deserialize<uintptr_t>(data)));
|
||||||
}
|
}
|
||||||
void LokiMQ::proxy_set_active_sns(pubkey_set pubkeys) {
|
void OxenMQ::proxy_set_active_sns(pubkey_set pubkeys) {
|
||||||
pubkey_set added, removed;
|
pubkey_set added, removed;
|
||||||
for (auto it = pubkeys.begin(); it != pubkeys.end(); ) {
|
for (auto it = pubkeys.begin(); it != pubkeys.end(); ) {
|
||||||
auto& pk = *it;
|
auto& pk = *it;
|
||||||
|
@ -118,7 +118,7 @@ void LokiMQ::proxy_set_active_sns(pubkey_set pubkeys) {
|
||||||
proxy_update_active_sns_clean(std::move(added), std::move(removed));
|
proxy_update_active_sns_clean(std::move(added), std::move(removed));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::update_active_sns(pubkey_set added, pubkey_set removed) {
|
void OxenMQ::update_active_sns(pubkey_set added, pubkey_set removed) {
|
||||||
LMQ_LOG(info, "uh, ", added.size());
|
LMQ_LOG(info, "uh, ", added.size());
|
||||||
if (proxy_thread.joinable()) {
|
if (proxy_thread.joinable()) {
|
||||||
std::array<uintptr_t, 2> data;
|
std::array<uintptr_t, 2> data;
|
||||||
|
@ -129,12 +129,12 @@ void LokiMQ::update_active_sns(pubkey_set added, pubkey_set removed) {
|
||||||
proxy_update_active_sns(std::move(added), std::move(removed));
|
proxy_update_active_sns(std::move(added), std::move(removed));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void LokiMQ::proxy_update_active_sns(bt_list_consumer data) {
|
void OxenMQ::proxy_update_active_sns(bt_list_consumer data) {
|
||||||
auto added = detail::deserialize_object<pubkey_set>(data.consume_integer<uintptr_t>());
|
auto added = detail::deserialize_object<pubkey_set>(data.consume_integer<uintptr_t>());
|
||||||
auto remed = detail::deserialize_object<pubkey_set>(data.consume_integer<uintptr_t>());
|
auto remed = detail::deserialize_object<pubkey_set>(data.consume_integer<uintptr_t>());
|
||||||
proxy_update_active_sns(std::move(added), std::move(remed));
|
proxy_update_active_sns(std::move(added), std::move(remed));
|
||||||
}
|
}
|
||||||
void LokiMQ::proxy_update_active_sns(pubkey_set added, pubkey_set removed) {
|
void OxenMQ::proxy_update_active_sns(pubkey_set added, pubkey_set removed) {
|
||||||
// We take a caller-provided set of added/removed then filter out any junk (bad pks, conflicting
|
// We take a caller-provided set of added/removed then filter out any junk (bad pks, conflicting
|
||||||
// values, pubkeys that already(added) or do not(removed) exist), then pass the purified lists
|
// values, pubkeys that already(added) or do not(removed) exist), then pass the purified lists
|
||||||
// to the _clean version.
|
// to the _clean version.
|
||||||
|
@ -167,7 +167,7 @@ void LokiMQ::proxy_update_active_sns(pubkey_set added, pubkey_set removed) {
|
||||||
proxy_update_active_sns_clean(std::move(added), std::move(removed));
|
proxy_update_active_sns_clean(std::move(added), std::move(removed));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_update_active_sns_clean(pubkey_set added, pubkey_set removed) {
|
void OxenMQ::proxy_update_active_sns_clean(pubkey_set added, pubkey_set removed) {
|
||||||
LMQ_LOG(debug, "Updating SN auth status with +", added.size(), "/-", removed.size(), " pubkeys");
|
LMQ_LOG(debug, "Updating SN auth status with +", added.size(), "/-", removed.size(), " pubkeys");
|
||||||
|
|
||||||
// For anything we remove we want close the connection to the SN (if outgoing), and remove the
|
// For anything we remove we want close the connection to the SN (if outgoing), and remove the
|
||||||
|
@ -192,7 +192,7 @@ void LokiMQ::proxy_update_active_sns_clean(pubkey_set added, pubkey_set removed)
|
||||||
active_service_nodes.insert(std::move(pk));
|
active_service_nodes.insert(std::move(pk));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::process_zap_requests() {
|
void OxenMQ::process_zap_requests() {
|
||||||
for (std::vector<zmq::message_t> frames; recv_message_parts(zap_auth, frames, zmq::recv_flags::dontwait); frames.clear()) {
|
for (std::vector<zmq::message_t> frames; recv_message_parts(zap_auth, frames, zmq::recv_flags::dontwait); frames.clear()) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (log_level() >= LogLevel::trace) {
|
if (log_level() >= LogLevel::trace) {
|
|
@ -4,7 +4,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
/// Authentication levels for command categories and connections
|
/// Authentication levels for command categories and connections
|
||||||
enum class AuthLevel {
|
enum class AuthLevel {
|
||||||
|
@ -45,7 +45,7 @@ struct already_hashed {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// std::unordered_set specialization for specifying pubkeys (used, in particular, by
|
/// std::unordered_set specialization for specifying pubkeys (used, in particular, by
|
||||||
/// LokiMQ::set_active_sns and LokiMQ::update_active_sns); this is a std::string unordered_set that
|
/// OxenMQ::set_active_sns and OxenMQ::update_active_sns); this is a std::string unordered_set that
|
||||||
/// also uses a specialized trivial hash function that uses part of the value itself (i.e. the
|
/// also uses a specialized trivial hash function that uses part of the value itself (i.e. the
|
||||||
/// pubkey) directly as a hash value. (This is nice and fast for uniformly distributed values like
|
/// pubkey) directly as a hash value. (This is nice and fast for uniformly distributed values like
|
||||||
/// pubkeys and a terrible hash choice for anything else).
|
/// pubkeys and a terrible hash choice for anything else).
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "byte_type.h"
|
#include "byte_type.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "byte_type.h"
|
#include "byte_type.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2020, The Loki Project
|
// Copyright (c) 2020-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ public:
|
||||||
* This is designed to be like a very stripped down version of a std::promise/std::future pair. We
|
* This is designed to be like a very stripped down version of a std::promise/std::future pair. We
|
||||||
* reimplemented it, however, because by ditching all the thread synchronization that promise/future
|
* reimplemented it, however, because by ditching all the thread synchronization that promise/future
|
||||||
* guarantees we can substantially reduce call overhead (by a factor of ~8 according to benchmarking
|
* guarantees we can substantially reduce call overhead (by a factor of ~8 according to benchmarking
|
||||||
* code). Since LokiMQ's proxy<->worker communication channel already gives us thread that overhead
|
* code). Since OxenMQ's proxy<->worker communication channel already gives us thread that overhead
|
||||||
* would just be wasted.
|
* would just be wasted.
|
||||||
*
|
*
|
||||||
* @tparam R the value type held by the result; must be default constructible. Note, however, that
|
* @tparam R the value type held by the result; must be default constructible. Note, however, that
|
||||||
|
@ -135,13 +135,13 @@ public:
|
||||||
void get() { if (exc) std::rethrow_exception(exc); }
|
void get() { if (exc) std::rethrow_exception(exc); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Helper class used to set up batches of jobs to be scheduled via the lokimq job handler.
|
/// Helper class used to set up batches of jobs to be scheduled via the oxenmq job handler.
|
||||||
///
|
///
|
||||||
/// @tparam R - the return type of the individual jobs
|
/// @tparam R - the return type of the individual jobs
|
||||||
///
|
///
|
||||||
template <typename R>
|
template <typename R>
|
||||||
class Batch final : private detail::Batch {
|
class Batch final : private detail::Batch {
|
||||||
friend class LokiMQ;
|
friend class OxenMQ;
|
||||||
public:
|
public:
|
||||||
/// The completion function type, called after all jobs have finished.
|
/// The completion function type, called after all jobs have finished.
|
||||||
using CompletionFunc = std::function<void(std::vector<job_result<R>> results)>;
|
using CompletionFunc = std::function<void(std::vector<job_result<R>> results)>;
|
||||||
|
@ -168,7 +168,7 @@ private:
|
||||||
|
|
||||||
void check_not_started() {
|
void check_not_started() {
|
||||||
if (started)
|
if (started)
|
||||||
throw std::logic_error("Cannot add jobs or completion function after starting a lokimq::Batch!");
|
throw std::logic_error("Cannot add jobs or completion function after starting a oxenmq::Batch!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -202,7 +202,7 @@ public:
|
||||||
/// \param thread - optional tagged thread in which to schedule the completion job. If not
|
/// \param thread - optional tagged thread in which to schedule the completion job. If not
|
||||||
/// provided then the completion job is scheduled in the pool of batch job threads.
|
/// provided then the completion job is scheduled in the pool of batch job threads.
|
||||||
///
|
///
|
||||||
/// `thread` can be provided the value &LokiMQ::run_in_proxy to invoke the completion function
|
/// `thread` can be provided the value &OxenMQ::run_in_proxy to invoke the completion function
|
||||||
/// *IN THE PROXY THREAD* itself after all jobs have finished. Be very, very careful: this
|
/// *IN THE PROXY THREAD* itself after all jobs have finished. Be very, very careful: this
|
||||||
/// should be a nearly trivial job that does not require any substantial CPU time and does not
|
/// should be a nearly trivial job that does not require any substantial CPU time and does not
|
||||||
/// block for any reason. This is only intended for the case where the completion job is so
|
/// block for any reason. This is only intended for the case where the completion job is so
|
||||||
|
@ -268,7 +268,7 @@ private:
|
||||||
|
|
||||||
|
|
||||||
template <typename R>
|
template <typename R>
|
||||||
void LokiMQ::batch(Batch<R>&& batch) {
|
void OxenMQ::batch(Batch<R>&& batch) {
|
||||||
if (batch.size().first == 0)
|
if (batch.size().first == 0)
|
||||||
throw std::logic_error("Cannot batch a a job batch with 0 jobs");
|
throw std::logic_error("Cannot batch a a job batch with 0 jobs");
|
||||||
// Need to send this over to the proxy thread via the base class pointer. It assumes ownership.
|
// Need to send this over to the proxy thread via the base class pointer. It assumes ownership.
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
#include "bt_serialize.h"
|
#include "bt_serialize.h"
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/// Reads digits into an unsigned 64-bit int.
|
/// Reads digits into an unsigned 64-bit int.
|
||||||
|
@ -228,4 +228,4 @@ std::pair<std::string_view, std::string_view> bt_dict_consumer::next_string() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace lokimq
|
} // namespace oxenmq
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2020, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -46,12 +46,12 @@
|
||||||
|
|
||||||
#include "bt_value.h"
|
#include "bt_value.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* LokiMQ serialization for internal commands is very simple: we support two primitive types,
|
* OxenMQ serialization for internal commands is very simple: we support two primitive types,
|
||||||
* strings and integers, and two container types, lists and dicts with string keys. On the wire
|
* strings and integers, and two container types, lists and dicts with string keys. On the wire
|
||||||
* these go in BitTorrent byte encoding as described in BEP-0003
|
* these go in BitTorrent byte encoding as described in BEP-0003
|
||||||
* (https://www.bittorrent.org/beps/bep_0003.html#bencoding).
|
* (https://www.bittorrent.org/beps/bep_0003.html#bencoding).
|
||||||
|
@ -596,7 +596,7 @@ template <typename T, typename It>
|
||||||
void get_tuple_impl_one(T& t, It& it) {
|
void get_tuple_impl_one(T& t, It& it) {
|
||||||
const bt_variant& v = *it++;
|
const bt_variant& v = *it++;
|
||||||
if constexpr (std::is_integral_v<T>) {
|
if constexpr (std::is_integral_v<T>) {
|
||||||
t = lokimq::get_int<T>(v);
|
t = oxenmq::get_int<T>(v);
|
||||||
} else if constexpr (is_bt_tuple<T>) {
|
} else if constexpr (is_bt_tuple<T>) {
|
||||||
if (std::holds_alternative<bt_list>(v))
|
if (std::holds_alternative<bt_list>(v))
|
||||||
throw std::invalid_argument{"Unable to convert tuple: cannot create sub-tuple from non-bt_list"};
|
throw std::invalid_argument{"Unable to convert tuple: cannot create sub-tuple from non-bt_list"};
|
||||||
|
@ -912,4 +912,4 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace lokimq
|
} // namespace oxenmq
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
struct bt_value;
|
struct bt_value;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace lokimq::detail {
|
namespace oxenmq::detail {
|
||||||
|
|
||||||
// Fallback - we just try a char
|
// Fallback - we just try a char
|
||||||
template <typename OutputIt, typename = void>
|
template <typename OutputIt, typename = void>
|
|
@ -1,8 +1,8 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& o, const ConnectionID& conn) {
|
std::ostream& operator<<(std::ostream& o, const ConnectionID& conn) {
|
||||||
if (!conn.pk.empty())
|
if (!conn.pk.empty())
|
||||||
|
@ -24,7 +24,7 @@ void add_pollitem(std::vector<zmq::pollitem_t>& pollitems, zmq::socket_t& sock)
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
void LokiMQ::rebuild_pollitems() {
|
void OxenMQ::rebuild_pollitems() {
|
||||||
pollitems.clear();
|
pollitems.clear();
|
||||||
add_pollitem(pollitems, command);
|
add_pollitem(pollitems, command);
|
||||||
add_pollitem(pollitems, workers_socket);
|
add_pollitem(pollitems, workers_socket);
|
||||||
|
@ -35,7 +35,7 @@ void LokiMQ::rebuild_pollitems() {
|
||||||
pollitems_stale = false;
|
pollitems_stale = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::setup_external_socket(zmq::socket_t& socket) {
|
void OxenMQ::setup_external_socket(zmq::socket_t& socket) {
|
||||||
socket.set(zmq::sockopt::reconnect_ivl, (int) RECONNECT_INTERVAL.count());
|
socket.set(zmq::sockopt::reconnect_ivl, (int) RECONNECT_INTERVAL.count());
|
||||||
socket.set(zmq::sockopt::reconnect_ivl_max, (int) RECONNECT_INTERVAL_MAX.count());
|
socket.set(zmq::sockopt::reconnect_ivl_max, (int) RECONNECT_INTERVAL_MAX.count());
|
||||||
socket.set(zmq::sockopt::handshake_ivl, (int) HANDSHAKE_TIME.count());
|
socket.set(zmq::sockopt::handshake_ivl, (int) HANDSHAKE_TIME.count());
|
||||||
|
@ -47,7 +47,7 @@ void LokiMQ::setup_external_socket(zmq::socket_t& socket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::setup_outgoing_socket(zmq::socket_t& socket, std::string_view remote_pubkey) {
|
void OxenMQ::setup_outgoing_socket(zmq::socket_t& socket, std::string_view remote_pubkey) {
|
||||||
|
|
||||||
setup_external_socket(socket);
|
setup_external_socket(socket);
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ void LokiMQ::setup_outgoing_socket(zmq::socket_t& socket, std::string_view remot
|
||||||
// else let ZMQ pick a random one
|
// else let ZMQ pick a random one
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionID LokiMQ::connect_sn(std::string_view pubkey, std::chrono::milliseconds keep_alive, std::string_view hint) {
|
ConnectionID OxenMQ::connect_sn(std::string_view pubkey, std::chrono::milliseconds keep_alive, std::string_view hint) {
|
||||||
if (!proxy_thread.joinable())
|
if (!proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot call connect_sn() before calling `start()`");
|
throw std::logic_error("Cannot call connect_sn() before calling `start()`");
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ ConnectionID LokiMQ::connect_sn(std::string_view pubkey, std::chrono::millisecon
|
||||||
return pubkey;
|
return pubkey;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionID LokiMQ::connect_remote(const address& remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
ConnectionID OxenMQ::connect_remote(const address& remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
||||||
AuthLevel auth_level, std::chrono::milliseconds timeout) {
|
AuthLevel auth_level, std::chrono::milliseconds timeout) {
|
||||||
if (!proxy_thread.joinable())
|
if (!proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot call connect_remote() before calling `start()`");
|
throw std::logic_error("Cannot call connect_remote() before calling `start()`");
|
||||||
|
@ -96,13 +96,13 @@ ConnectionID LokiMQ::connect_remote(const address& remote, ConnectSuccess on_con
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionID LokiMQ::connect_remote(std::string_view remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
ConnectionID OxenMQ::connect_remote(std::string_view remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
||||||
std::string_view pubkey, AuthLevel auth_level, std::chrono::milliseconds timeout) {
|
std::string_view pubkey, AuthLevel auth_level, std::chrono::milliseconds timeout) {
|
||||||
return connect_remote(address{remote}.set_pubkey(pubkey),
|
return connect_remote(address{remote}.set_pubkey(pubkey),
|
||||||
std::move(on_connect), std::move(on_failure), auth_level, timeout);
|
std::move(on_connect), std::move(on_failure), auth_level, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::disconnect(ConnectionID id, std::chrono::milliseconds linger) {
|
void OxenMQ::disconnect(ConnectionID id, std::chrono::milliseconds linger) {
|
||||||
detail::send_control(get_control_socket(), "DISCONNECT", bt_serialize<bt_dict>({
|
detail::send_control(get_control_socket(), "DISCONNECT", bt_serialize<bt_dict>({
|
||||||
{"conn_id", id.id},
|
{"conn_id", id.id},
|
||||||
{"linger_ms", linger.count()},
|
{"linger_ms", linger.count()},
|
||||||
|
@ -111,7 +111,7 @@ void LokiMQ::disconnect(ConnectionID id, std::chrono::milliseconds linger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<zmq::socket_t *, std::string>
|
std::pair<zmq::socket_t *, std::string>
|
||||||
LokiMQ::proxy_connect_sn(std::string_view remote, std::string_view connect_hint, bool optional, bool incoming_only, bool outgoing_only, std::chrono::milliseconds keep_alive) {
|
OxenMQ::proxy_connect_sn(std::string_view remote, std::string_view connect_hint, bool optional, bool incoming_only, bool outgoing_only, std::chrono::milliseconds keep_alive) {
|
||||||
ConnectionID remote_cid{remote};
|
ConnectionID remote_cid{remote};
|
||||||
auto its = peers.equal_range(remote_cid);
|
auto its = peers.equal_range(remote_cid);
|
||||||
peer_info* peer = nullptr;
|
peer_info* peer = nullptr;
|
||||||
|
@ -186,7 +186,7 @@ LokiMQ::proxy_connect_sn(std::string_view remote, std::string_view connect_hint,
|
||||||
return {&connections.back(), ""s};
|
return {&connections.back(), ""s};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<zmq::socket_t *, std::string> LokiMQ::proxy_connect_sn(bt_dict_consumer data) {
|
std::pair<zmq::socket_t *, std::string> OxenMQ::proxy_connect_sn(bt_dict_consumer data) {
|
||||||
std::string_view hint, remote_pk;
|
std::string_view hint, remote_pk;
|
||||||
std::chrono::milliseconds keep_alive;
|
std::chrono::milliseconds keep_alive;
|
||||||
bool optional = false, incoming_only = false, outgoing_only = false;
|
bool optional = false, incoming_only = false, outgoing_only = false;
|
||||||
|
@ -226,7 +226,7 @@ void update_connection_indices(Container& c, size_t index, AccessIndex get_index
|
||||||
/// Closes outgoing connections and removes all references. Note that this will call `erase()`
|
/// Closes outgoing connections and removes all references. Note that this will call `erase()`
|
||||||
/// which can invalidate iterators on the various connection containers - if you don't want that,
|
/// which can invalidate iterators on the various connection containers - if you don't want that,
|
||||||
/// delete it first so that the container won't contain the element being deleted.
|
/// delete it first so that the container won't contain the element being deleted.
|
||||||
void LokiMQ::proxy_close_connection(size_t index, std::chrono::milliseconds linger) {
|
void OxenMQ::proxy_close_connection(size_t index, std::chrono::milliseconds linger) {
|
||||||
connections[index].set(zmq::sockopt::linger, linger > 0ms ? (int) linger.count() : 0);
|
connections[index].set(zmq::sockopt::linger, linger > 0ms ? (int) linger.count() : 0);
|
||||||
pollitems_stale = true;
|
pollitems_stale = true;
|
||||||
connections.erase(connections.begin() + index);
|
connections.erase(connections.begin() + index);
|
||||||
|
@ -244,7 +244,7 @@ void LokiMQ::proxy_close_connection(size_t index, std::chrono::milliseconds ling
|
||||||
conn_index_to_id.erase(conn_index_to_id.begin() + index);
|
conn_index_to_id.erase(conn_index_to_id.begin() + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_expire_idle_peers() {
|
void OxenMQ::proxy_expire_idle_peers() {
|
||||||
for (auto it = peers.begin(); it != peers.end(); ) {
|
for (auto it = peers.begin(); it != peers.end(); ) {
|
||||||
auto &info = it->second;
|
auto &info = it->second;
|
||||||
if (info.outgoing()) {
|
if (info.outgoing()) {
|
||||||
|
@ -267,7 +267,7 @@ void LokiMQ::proxy_expire_idle_peers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_conn_cleanup() {
|
void OxenMQ::proxy_conn_cleanup() {
|
||||||
LMQ_TRACE("starting proxy connections cleanup");
|
LMQ_TRACE("starting proxy connections cleanup");
|
||||||
|
|
||||||
// Drop idle connections (if we haven't done it in a while)
|
// Drop idle connections (if we haven't done it in a while)
|
||||||
|
@ -307,7 +307,7 @@ void LokiMQ::proxy_conn_cleanup() {
|
||||||
LMQ_TRACE("done proxy connections cleanup");
|
LMQ_TRACE("done proxy connections cleanup");
|
||||||
};
|
};
|
||||||
|
|
||||||
void LokiMQ::proxy_connect_remote(bt_dict_consumer data) {
|
void OxenMQ::proxy_connect_remote(bt_dict_consumer data) {
|
||||||
AuthLevel auth_level = AuthLevel::none;
|
AuthLevel auth_level = AuthLevel::none;
|
||||||
long long conn_id = -1;
|
long long conn_id = -1;
|
||||||
ConnectSuccess on_connect;
|
ConnectSuccess on_connect;
|
||||||
|
@ -372,7 +372,7 @@ void LokiMQ::proxy_connect_remote(bt_dict_consumer data) {
|
||||||
peers.emplace(std::move(conn), std::move(peer));
|
peers.emplace(std::move(conn), std::move(peer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_disconnect(bt_dict_consumer data) {
|
void OxenMQ::proxy_disconnect(bt_dict_consumer data) {
|
||||||
ConnectionID connid{-1};
|
ConnectionID connid{-1};
|
||||||
std::chrono::milliseconds linger = 1s;
|
std::chrono::milliseconds linger = 1s;
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ void LokiMQ::proxy_disconnect(bt_dict_consumer data) {
|
||||||
|
|
||||||
proxy_disconnect(std::move(connid), linger);
|
proxy_disconnect(std::move(connid), linger);
|
||||||
}
|
}
|
||||||
void LokiMQ::proxy_disconnect(ConnectionID conn, std::chrono::milliseconds linger) {
|
void OxenMQ::proxy_disconnect(ConnectionID conn, std::chrono::milliseconds linger) {
|
||||||
LMQ_TRACE("Disconnecting outgoing connection to ", conn);
|
LMQ_TRACE("Disconnecting outgoing connection to ", conn);
|
||||||
auto pr = peers.equal_range(conn);
|
auto pr = peers.equal_range(conn);
|
||||||
for (auto it = pr.first; it != pr.second; ++it) {
|
for (auto it = pr.first; it != pr.second; ++it) {
|
|
@ -8,7 +8,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
struct ConnectionID;
|
struct ConnectionID;
|
||||||
|
|
||||||
|
@ -77,18 +77,18 @@ private:
|
||||||
long long id = 0;
|
long long id = 0;
|
||||||
std::string pk;
|
std::string pk;
|
||||||
std::string route;
|
std::string route;
|
||||||
friend class LokiMQ;
|
friend class OxenMQ;
|
||||||
friend struct std::hash<ConnectionID>;
|
friend struct std::hash<ConnectionID>;
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
friend bt_dict detail::build_send(ConnectionID to, std::string_view cmd, T&&... opts);
|
friend bt_dict detail::build_send(ConnectionID to, std::string_view cmd, T&&... opts);
|
||||||
friend std::ostream& operator<<(std::ostream& o, const ConnectionID& conn);
|
friend std::ostream& operator<<(std::ostream& o, const ConnectionID& conn);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lokimq
|
} // namespace oxenmq
|
||||||
namespace std {
|
namespace std {
|
||||||
template <> struct hash<lokimq::ConnectionID> {
|
template <> struct hash<oxenmq::ConnectionID> {
|
||||||
size_t operator()(const lokimq::ConnectionID &c) const {
|
size_t operator()(const oxenmq::ConnectionID &c) const {
|
||||||
return c.sn() ? lokimq::already_hashed{}(c.pk) :
|
return c.sn() ? oxenmq::already_hashed{}(c.pk) :
|
||||||
std::hash<long long>{}(c.id) + std::hash<std::string>{}(c.route);
|
std::hash<long long>{}(c.id) + std::hash<std::string>{}(c.route);
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "byte_type.h"
|
#include "byte_type.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "batch.h"
|
#include "batch.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
void LokiMQ::proxy_batch(detail::Batch* batch) {
|
void OxenMQ::proxy_batch(detail::Batch* batch) {
|
||||||
batches.insert(batch);
|
batches.insert(batch);
|
||||||
const auto [jobs, tagged_threads] = batch->size();
|
const auto [jobs, tagged_threads] = batch->size();
|
||||||
LMQ_TRACE("proxy queuing batch job with ", jobs, " jobs", tagged_threads ? " (job uses tagged thread(s))" : "");
|
LMQ_TRACE("proxy queuing batch job with ", jobs, " jobs", tagged_threads ? " (job uses tagged thread(s))" : "");
|
||||||
|
@ -26,7 +26,7 @@ void LokiMQ::proxy_batch(detail::Batch* batch) {
|
||||||
proxy_skip_one_poll = true;
|
proxy_skip_one_poll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::job(std::function<void()> f, std::optional<TaggedThreadID> thread) {
|
void OxenMQ::job(std::function<void()> f, std::optional<TaggedThreadID> thread) {
|
||||||
if (thread && thread->_id == -1)
|
if (thread && thread->_id == -1)
|
||||||
throw std::logic_error{"job() cannot be used to queue an in-proxy job"};
|
throw std::logic_error{"job() cannot be used to queue an in-proxy job"};
|
||||||
auto* b = new Batch<void>;
|
auto* b = new Batch<void>;
|
||||||
|
@ -35,7 +35,7 @@ void LokiMQ::job(std::function<void()> f, std::optional<TaggedThreadID> thread)
|
||||||
detail::send_control(get_control_socket(), "BATCH", bt_serialize(reinterpret_cast<uintptr_t>(baseptr)));
|
detail::send_control(get_control_socket(), "BATCH", bt_serialize(reinterpret_cast<uintptr_t>(baseptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_schedule_reply_job(std::function<void()> f) {
|
void OxenMQ::proxy_schedule_reply_job(std::function<void()> f) {
|
||||||
auto* b = new Batch<void>;
|
auto* b = new Batch<void>;
|
||||||
b->add_job(std::move(f));
|
b->add_job(std::move(f));
|
||||||
batches.insert(b);
|
batches.insert(b);
|
||||||
|
@ -43,7 +43,7 @@ void LokiMQ::proxy_schedule_reply_job(std::function<void()> f) {
|
||||||
proxy_skip_one_poll = true;
|
proxy_skip_one_poll = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_run_batch_jobs(std::queue<batch_job>& jobs, const int reserved, int& active, bool reply) {
|
void OxenMQ::proxy_run_batch_jobs(std::queue<batch_job>& jobs, const int reserved, int& active, bool reply) {
|
||||||
while (!jobs.empty() && active_workers() < max_workers &&
|
while (!jobs.empty() && active_workers() < max_workers &&
|
||||||
(active < reserved || active_workers() < general_workers)) {
|
(active < reserved || active_workers() < general_workers)) {
|
||||||
proxy_run_worker(get_idle_worker().load(std::move(jobs.front()), reply));
|
proxy_run_worker(get_idle_worker().load(std::move(jobs.front()), reply));
|
||||||
|
@ -54,20 +54,20 @@ void LokiMQ::proxy_run_batch_jobs(std::queue<batch_job>& jobs, const int reserve
|
||||||
|
|
||||||
// Called either within the proxy thread, or before the proxy thread has been created; actually adds
|
// Called either within the proxy thread, or before the proxy thread has been created; actually adds
|
||||||
// the timer. If the timer object hasn't been set up yet it gets set up here.
|
// the timer. If the timer object hasn't been set up yet it gets set up here.
|
||||||
void LokiMQ::proxy_timer(std::function<void()> job, std::chrono::milliseconds interval, bool squelch, int thread) {
|
void OxenMQ::proxy_timer(std::function<void()> job, std::chrono::milliseconds interval, bool squelch, int thread) {
|
||||||
if (!timers)
|
if (!timers)
|
||||||
timers.reset(zmq_timers_new());
|
timers.reset(zmq_timers_new());
|
||||||
|
|
||||||
int timer_id = zmq_timers_add(timers.get(),
|
int timer_id = zmq_timers_add(timers.get(),
|
||||||
interval.count(),
|
interval.count(),
|
||||||
[](int timer_id, void* self) { static_cast<LokiMQ*>(self)->_queue_timer_job(timer_id); },
|
[](int timer_id, void* self) { static_cast<OxenMQ*>(self)->_queue_timer_job(timer_id); },
|
||||||
this);
|
this);
|
||||||
if (timer_id == -1)
|
if (timer_id == -1)
|
||||||
throw zmq::error_t{};
|
throw zmq::error_t{};
|
||||||
timer_jobs[timer_id] = { std::move(job), squelch, false, thread };
|
timer_jobs[timer_id] = { std::move(job), squelch, false, thread };
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_timer(bt_list_consumer timer_data) {
|
void OxenMQ::proxy_timer(bt_list_consumer timer_data) {
|
||||||
std::unique_ptr<std::function<void()>> func{reinterpret_cast<std::function<void()>*>(timer_data.consume_integer<uintptr_t>())};
|
std::unique_ptr<std::function<void()>> func{reinterpret_cast<std::function<void()>*>(timer_data.consume_integer<uintptr_t>())};
|
||||||
auto interval = std::chrono::milliseconds{timer_data.consume_integer<uint64_t>()};
|
auto interval = std::chrono::milliseconds{timer_data.consume_integer<uint64_t>()};
|
||||||
auto squelch = timer_data.consume_integer<bool>();
|
auto squelch = timer_data.consume_integer<bool>();
|
||||||
|
@ -77,7 +77,7 @@ void LokiMQ::proxy_timer(bt_list_consumer timer_data) {
|
||||||
proxy_timer(std::move(*func), interval, squelch, thread);
|
proxy_timer(std::move(*func), interval, squelch, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::_queue_timer_job(int timer_id) {
|
void OxenMQ::_queue_timer_job(int timer_id) {
|
||||||
auto it = timer_jobs.find(timer_id);
|
auto it = timer_jobs.find(timer_id);
|
||||||
if (it == timer_jobs.end()) {
|
if (it == timer_jobs.end()) {
|
||||||
LMQ_LOG(warn, "Could not find timer job ", timer_id);
|
LMQ_LOG(warn, "Could not find timer job ", timer_id);
|
||||||
|
@ -107,7 +107,7 @@ void LokiMQ::_queue_timer_job(int timer_id) {
|
||||||
auto it = timer_jobs.find(timer_id);
|
auto it = timer_jobs.find(timer_id);
|
||||||
if (it != timer_jobs.end())
|
if (it != timer_jobs.end())
|
||||||
it->second.running = false;
|
it->second.running = false;
|
||||||
}, LokiMQ::run_in_proxy);
|
}, OxenMQ::run_in_proxy);
|
||||||
}
|
}
|
||||||
batches.insert(b);
|
batches.insert(b);
|
||||||
LMQ_TRACE("b: ", b->size().first, ", ", b->size().second, "; thread = ", thread);
|
LMQ_TRACE("b: ", b->size().first, ", ", b->size().second, "; thread = ", thread);
|
||||||
|
@ -118,7 +118,7 @@ void LokiMQ::_queue_timer_job(int timer_id) {
|
||||||
queue.emplace(static_cast<detail::Batch*>(b), 0);
|
queue.emplace(static_cast<detail::Batch*>(b), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::add_timer(std::function<void()> job, std::chrono::milliseconds interval, bool squelch, std::optional<TaggedThreadID> thread) {
|
void OxenMQ::add_timer(std::function<void()> job, std::chrono::milliseconds interval, bool squelch, std::optional<TaggedThreadID> thread) {
|
||||||
int th_id = thread ? thread->_id : 0;
|
int th_id = thread ? thread->_id : 0;
|
||||||
if (proxy_thread.joinable()) {
|
if (proxy_thread.joinable()) {
|
||||||
detail::send_control(get_control_socket(), "TIMER", bt_serialize(bt_list{{
|
detail::send_control(get_control_socket(), "TIMER", bt_serialize(bt_list{{
|
||||||
|
@ -131,9 +131,9 @@ void LokiMQ::add_timer(std::function<void()> job, std::chrono::milliseconds inte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::TimersDeleter::operator()(void* timers) { zmq_timers_destroy(&timers); }
|
void OxenMQ::TimersDeleter::operator()(void* timers) { zmq_timers_destroy(&timers); }
|
||||||
|
|
||||||
TaggedThreadID LokiMQ::add_tagged_thread(std::string name, std::function<void()> start) {
|
TaggedThreadID OxenMQ::add_tagged_thread(std::string name, std::function<void()> start) {
|
||||||
if (proxy_thread.joinable())
|
if (proxy_thread.joinable())
|
||||||
throw std::logic_error{"Cannot add tagged threads after calling `start()`"};
|
throw std::logic_error{"Cannot add tagged threads after calling `start()`"};
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ TaggedThreadID LokiMQ::add_tagged_thread(std::string name, std::function<void()>
|
||||||
run.worker_routing_id = "t" + std::to_string(run.worker_id);
|
run.worker_routing_id = "t" + std::to_string(run.worker_id);
|
||||||
LMQ_TRACE("Created new tagged thread ", name, " with routing id ", run.worker_routing_id);
|
LMQ_TRACE("Created new tagged thread ", name, " with routing id ", run.worker_routing_id);
|
||||||
|
|
||||||
run.worker_thread = std::thread{&LokiMQ::worker_thread, this, run.worker_id, name, std::move(start)};
|
run.worker_thread = std::thread{&OxenMQ::worker_thread, this, run.worker_id, name, std::move(start)};
|
||||||
|
|
||||||
return TaggedThreadID{static_cast<int>(run.worker_id)};
|
return TaggedThreadID{static_cast<int>(run.worker_id)};
|
||||||
}
|
}
|
|
@ -2,16 +2,16 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "connections.h"
|
#include "connections.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
class LokiMQ;
|
class OxenMQ;
|
||||||
|
|
||||||
/// Encapsulates an incoming message from a remote connection with message details plus extra
|
/// Encapsulates an incoming message from a remote connection with message details plus extra
|
||||||
/// info need to send a reply back through the proxy thread via the `reply()` method. Note that
|
/// info need to send a reply back through the proxy thread via the `reply()` method. Note that
|
||||||
/// this object gets reused: callbacks should use but not store any reference beyond the callback.
|
/// this object gets reused: callbacks should use but not store any reference beyond the callback.
|
||||||
class Message {
|
class Message {
|
||||||
public:
|
public:
|
||||||
LokiMQ& lokimq; ///< The owning LokiMQ object
|
OxenMQ& oxenmq; ///< The owning OxenMQ object
|
||||||
std::vector<std::string_view> data; ///< The provided command data parts, if any.
|
std::vector<std::string_view> data; ///< The provided command data parts, if any.
|
||||||
ConnectionID conn; ///< The connection info for routing a reply; also contains the pubkey/sn status.
|
ConnectionID conn; ///< The connection info for routing a reply; also contains the pubkey/sn status.
|
||||||
std::string reply_tag; ///< If the invoked command is a request command this is the required reply tag that will be prepended by `send_reply()`.
|
std::string reply_tag; ///< If the invoked command is a request command this is the required reply tag that will be prepended by `send_reply()`.
|
||||||
|
@ -19,8 +19,8 @@ public:
|
||||||
std::string remote; ///< Some sort of remote address from which the request came. Often "IP" for TCP connections and "localhost:UID:GID:PID" for UDP connections.
|
std::string remote; ///< Some sort of remote address from which the request came. Often "IP" for TCP connections and "localhost:UID:GID:PID" for UDP connections.
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Message(LokiMQ& lmq, ConnectionID cid, Access access, std::string remote)
|
Message(OxenMQ& lmq, ConnectionID cid, Access access, std::string remote)
|
||||||
: lokimq{lmq}, conn{std::move(cid)}, access{std::move(access)}, remote{std::move(remote)} {}
|
: oxenmq{lmq}, conn{std::move(cid)}, access{std::move(access)}, remote{std::move(remote)} {}
|
||||||
|
|
||||||
// Non-copyable
|
// Non-copyable
|
||||||
Message(const Message&) = delete;
|
Message(const Message&) = delete;
|
|
@ -1,5 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
|
|
||||||
// Inside some method:
|
// Inside some method:
|
||||||
// LMQ_LOG(warn, "bad ", 42, " stuff");
|
// LMQ_LOG(warn, "bad ", 42, " stuff");
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
# define LMQ_TRACE(...)
|
# define LMQ_TRACE(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
constexpr char SN_ADDR_COMMAND[] = "inproc://sn-command";
|
constexpr char SN_ADDR_COMMAND[] = "inproc://sn-command";
|
||||||
constexpr char SN_ADDR_WORKERS[] = "inproc://sn-workers";
|
constexpr char SN_ADDR_WORKERS[] = "inproc://sn-workers";
|
|
@ -1,5 +1,5 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
#include "zmq.hpp"
|
#include "zmq.hpp"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
@ -13,7 +13,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -76,20 +76,20 @@ std::pair<std::string, AuthLevel> extract_metadata(zmq::message_t& msg) {
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
void LokiMQ::set_zmq_context_option(zmq::ctxopt option, int value) {
|
void OxenMQ::set_zmq_context_option(zmq::ctxopt option, int value) {
|
||||||
context.set(option, value);
|
context.set(option, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::log_level(LogLevel level) {
|
void OxenMQ::log_level(LogLevel level) {
|
||||||
log_lvl.store(level, std::memory_order_relaxed);
|
log_lvl.store(level, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogLevel LokiMQ::log_level() const {
|
LogLevel OxenMQ::log_level() const {
|
||||||
return log_lvl.load(std::memory_order_relaxed);
|
return log_lvl.load(std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CatHelper LokiMQ::add_category(std::string name, Access access_level, unsigned int reserved_threads, int max_queue) {
|
CatHelper OxenMQ::add_category(std::string name, Access access_level, unsigned int reserved_threads, int max_queue) {
|
||||||
check_not_started(proxy_thread, "add a category");
|
check_not_started(proxy_thread, "add a category");
|
||||||
|
|
||||||
if (name.size() > MAX_CATEGORY_LENGTH)
|
if (name.size() > MAX_CATEGORY_LENGTH)
|
||||||
|
@ -107,7 +107,7 @@ CatHelper LokiMQ::add_category(std::string name, Access access_level, unsigned i
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::add_command(const std::string& category, std::string name, CommandCallback callback) {
|
void OxenMQ::add_command(const std::string& category, std::string name, CommandCallback callback) {
|
||||||
check_not_started(proxy_thread, "add a command");
|
check_not_started(proxy_thread, "add a command");
|
||||||
|
|
||||||
if (name.size() > MAX_COMMAND_LENGTH)
|
if (name.size() > MAX_COMMAND_LENGTH)
|
||||||
|
@ -126,12 +126,12 @@ void LokiMQ::add_command(const std::string& category, std::string name, CommandC
|
||||||
throw std::runtime_error("Cannot add command `" + fullname + "': that command already exists");
|
throw std::runtime_error("Cannot add command `" + fullname + "': that command already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::add_request_command(const std::string& category, std::string name, CommandCallback callback) {
|
void OxenMQ::add_request_command(const std::string& category, std::string name, CommandCallback callback) {
|
||||||
add_command(category, name, std::move(callback));
|
add_command(category, name, std::move(callback));
|
||||||
categories.at(category).commands.at(name).second = true;
|
categories.at(category).commands.at(name).second = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::add_command_alias(std::string from, std::string to) {
|
void OxenMQ::add_command_alias(std::string from, std::string to) {
|
||||||
check_not_started(proxy_thread, "add a command alias");
|
check_not_started(proxy_thread, "add a command alias");
|
||||||
|
|
||||||
if (from.empty())
|
if (from.empty())
|
||||||
|
@ -160,10 +160,10 @@ std::atomic<int> next_id{1};
|
||||||
/// Accesses a thread-local command socket connected to the proxy's command socket used to issue
|
/// Accesses a thread-local command socket connected to the proxy's command socket used to issue
|
||||||
/// commands in a thread-safe manner. A mutex is only required here the first time a thread
|
/// commands in a thread-safe manner. A mutex is only required here the first time a thread
|
||||||
/// accesses the control socket.
|
/// accesses the control socket.
|
||||||
zmq::socket_t& LokiMQ::get_control_socket() {
|
zmq::socket_t& OxenMQ::get_control_socket() {
|
||||||
assert(proxy_thread.joinable());
|
assert(proxy_thread.joinable());
|
||||||
|
|
||||||
// Optimize by caching the last value; LokiMQ is often a singleton and in that case we're
|
// Optimize by caching the last value; OxenMQ is often a singleton and in that case we're
|
||||||
// going to *always* hit this optimization. Even if it isn't, we're probably likely to need the
|
// going to *always* hit this optimization. Even if it isn't, we're probably likely to need the
|
||||||
// same control socket from the same thread multiple times sequentially so this may still help.
|
// same control socket from the same thread multiple times sequentially so this may still help.
|
||||||
static thread_local int last_id = -1;
|
static thread_local int last_id = -1;
|
||||||
|
@ -174,7 +174,7 @@ zmq::socket_t& LokiMQ::get_control_socket() {
|
||||||
std::lock_guard lock{control_sockets_mutex};
|
std::lock_guard lock{control_sockets_mutex};
|
||||||
|
|
||||||
if (proxy_shutting_down)
|
if (proxy_shutting_down)
|
||||||
throw std::runtime_error("Unable to obtain LokiMQ control socket: proxy thread is shutting down");
|
throw std::runtime_error("Unable to obtain OxenMQ control socket: proxy thread is shutting down");
|
||||||
|
|
||||||
auto& socket = control_sockets[std::this_thread::get_id()];
|
auto& socket = control_sockets[std::this_thread::get_id()];
|
||||||
if (!socket) {
|
if (!socket) {
|
||||||
|
@ -188,7 +188,7 @@ zmq::socket_t& LokiMQ::get_control_socket() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LokiMQ::LokiMQ(
|
OxenMQ::OxenMQ(
|
||||||
std::string pubkey_,
|
std::string pubkey_,
|
||||||
std::string privkey_,
|
std::string privkey_,
|
||||||
bool service_node,
|
bool service_node,
|
||||||
|
@ -199,17 +199,17 @@ LokiMQ::LokiMQ(
|
||||||
sn_lookup{std::move(lookup)}, log_lvl{level}, logger{std::move(logger)}
|
sn_lookup{std::move(lookup)}, log_lvl{level}, logger{std::move(logger)}
|
||||||
{
|
{
|
||||||
|
|
||||||
LMQ_TRACE("Constructing LokiMQ, id=", object_id, ", this=", this);
|
LMQ_TRACE("Constructing OxenMQ, id=", object_id, ", this=", this);
|
||||||
|
|
||||||
if (sodium_init() == -1)
|
if (sodium_init() == -1)
|
||||||
throw std::runtime_error{"libsodium initialization failed"};
|
throw std::runtime_error{"libsodium initialization failed"};
|
||||||
|
|
||||||
if (pubkey.empty() != privkey.empty()) {
|
if (pubkey.empty() != privkey.empty()) {
|
||||||
throw std::invalid_argument("LokiMQ construction failed: one (and only one) of pubkey/privkey is empty. Both must be specified, or both empty to generate a key.");
|
throw std::invalid_argument("OxenMQ construction failed: one (and only one) of pubkey/privkey is empty. Both must be specified, or both empty to generate a key.");
|
||||||
} else if (pubkey.empty()) {
|
} else if (pubkey.empty()) {
|
||||||
if (service_node)
|
if (service_node)
|
||||||
throw std::invalid_argument("Cannot construct a service node mode LokiMQ without a keypair");
|
throw std::invalid_argument("Cannot construct a service node mode OxenMQ without a keypair");
|
||||||
LMQ_LOG(debug, "generating x25519 keypair for remote-only LokiMQ instance");
|
LMQ_LOG(debug, "generating x25519 keypair for remote-only OxenMQ instance");
|
||||||
pubkey.resize(crypto_box_PUBLICKEYBYTES);
|
pubkey.resize(crypto_box_PUBLICKEYBYTES);
|
||||||
privkey.resize(crypto_box_SECRETKEYBYTES);
|
privkey.resize(crypto_box_SECRETKEYBYTES);
|
||||||
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
||||||
|
@ -224,11 +224,11 @@ LokiMQ::LokiMQ(
|
||||||
std::string verify_pubkey(crypto_box_PUBLICKEYBYTES, 0);
|
std::string verify_pubkey(crypto_box_PUBLICKEYBYTES, 0);
|
||||||
crypto_scalarmult_base(reinterpret_cast<unsigned char*>(&verify_pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
crypto_scalarmult_base(reinterpret_cast<unsigned char*>(&verify_pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
||||||
if (verify_pubkey != pubkey)
|
if (verify_pubkey != pubkey)
|
||||||
throw std::invalid_argument("Invalid pubkey/privkey values given to LokiMQ construction: pubkey verification failed");
|
throw std::invalid_argument("Invalid pubkey/privkey values given to OxenMQ construction: pubkey verification failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::start() {
|
void OxenMQ::start() {
|
||||||
if (proxy_thread.joinable())
|
if (proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot call start() multiple times!");
|
throw std::logic_error("Cannot call start() multiple times!");
|
||||||
|
|
||||||
|
@ -238,19 +238,19 @@ void LokiMQ::start() {
|
||||||
if (bind.empty() && local_service_node)
|
if (bind.empty() && local_service_node)
|
||||||
throw std::invalid_argument{"Cannot create a service node listener with no address(es) to bind"};
|
throw std::invalid_argument{"Cannot create a service node listener with no address(es) to bind"};
|
||||||
|
|
||||||
LMQ_LOG(info, "Initializing LokiMQ ", bind.empty() ? "remote-only" : "listener", " with pubkey ", to_hex(pubkey));
|
LMQ_LOG(info, "Initializing OxenMQ ", bind.empty() ? "remote-only" : "listener", " with pubkey ", to_hex(pubkey));
|
||||||
|
|
||||||
int zmq_socket_limit = context.get(zmq::ctxopt::socket_limit);
|
int zmq_socket_limit = context.get(zmq::ctxopt::socket_limit);
|
||||||
if (MAX_SOCKETS > 1 && MAX_SOCKETS <= zmq_socket_limit)
|
if (MAX_SOCKETS > 1 && MAX_SOCKETS <= zmq_socket_limit)
|
||||||
context.set(zmq::ctxopt::max_sockets, MAX_SOCKETS);
|
context.set(zmq::ctxopt::max_sockets, MAX_SOCKETS);
|
||||||
else
|
else
|
||||||
LMQ_LOG(error, "Not applying LokiMQ::MAX_SOCKETS setting: ", MAX_SOCKETS, " must be in [1, ", zmq_socket_limit, "]");
|
LMQ_LOG(error, "Not applying OxenMQ::MAX_SOCKETS setting: ", MAX_SOCKETS, " must be in [1, ", zmq_socket_limit, "]");
|
||||||
|
|
||||||
// We bind `command` here so that the `get_control_socket()` below is always connecting to a
|
// We bind `command` here so that the `get_control_socket()` below is always connecting to a
|
||||||
// bound socket, but we do nothing else here: the proxy thread is responsible for everything
|
// bound socket, but we do nothing else here: the proxy thread is responsible for everything
|
||||||
// except binding it.
|
// except binding it.
|
||||||
command.bind(SN_ADDR_COMMAND);
|
command.bind(SN_ADDR_COMMAND);
|
||||||
proxy_thread = std::thread{&LokiMQ::proxy_loop, this};
|
proxy_thread = std::thread{&OxenMQ::proxy_loop, this};
|
||||||
|
|
||||||
LMQ_LOG(debug, "Waiting for proxy thread to get ready...");
|
LMQ_LOG(debug, "Waiting for proxy thread to get ready...");
|
||||||
auto &control = get_control_socket();
|
auto &control = get_control_socket();
|
||||||
|
@ -260,14 +260,14 @@ void LokiMQ::start() {
|
||||||
zmq::message_t ready_msg;
|
zmq::message_t ready_msg;
|
||||||
std::vector<zmq::message_t> parts;
|
std::vector<zmq::message_t> parts;
|
||||||
try { recv_message_parts(control, parts); }
|
try { recv_message_parts(control, parts); }
|
||||||
catch (const zmq::error_t &e) { throw std::runtime_error("Failure reading from LokiMQ::Proxy thread: "s + e.what()); }
|
catch (const zmq::error_t &e) { throw std::runtime_error("Failure reading from OxenMQ::Proxy thread: "s + e.what()); }
|
||||||
|
|
||||||
if (!(parts.size() == 1 && view(parts.front()) == "READY"))
|
if (!(parts.size() == 1 && view(parts.front()) == "READY"))
|
||||||
throw std::runtime_error("Invalid startup message from proxy thread (didn't get expected READY message)");
|
throw std::runtime_error("Invalid startup message from proxy thread (didn't get expected READY message)");
|
||||||
LMQ_LOG(debug, "Proxy thread is ready");
|
LMQ_LOG(debug, "Proxy thread is ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::listen_curve(std::string bind_addr, AllowFunc allow_connection) {
|
void OxenMQ::listen_curve(std::string bind_addr, AllowFunc allow_connection) {
|
||||||
// TODO: there's no particular reason we can't start listening after starting up; just needs to
|
// TODO: there's no particular reason we can't start listening after starting up; just needs to
|
||||||
// be implemented. (But if we can start we'll probably also want to be able to stop, so it's
|
// be implemented. (But if we can start we'll probably also want to be able to stop, so it's
|
||||||
// more than just binding that needs implementing).
|
// more than just binding that needs implementing).
|
||||||
|
@ -276,7 +276,7 @@ void LokiMQ::listen_curve(std::string bind_addr, AllowFunc allow_connection) {
|
||||||
bind.emplace_back(std::move(bind_addr), bind_data{true, std::move(allow_connection)});
|
bind.emplace_back(std::move(bind_addr), bind_data{true, std::move(allow_connection)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::listen_plain(std::string bind_addr, AllowFunc allow_connection) {
|
void OxenMQ::listen_plain(std::string bind_addr, AllowFunc allow_connection) {
|
||||||
// TODO: As above.
|
// TODO: As above.
|
||||||
check_not_started(proxy_thread, "start listening");
|
check_not_started(proxy_thread, "start listening");
|
||||||
|
|
||||||
|
@ -284,7 +284,7 @@ void LokiMQ::listen_plain(std::string bind_addr, AllowFunc allow_connection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::pair<LokiMQ::category*, const std::pair<LokiMQ::CommandCallback, bool>*> LokiMQ::get_command(std::string& command) {
|
std::pair<OxenMQ::category*, const std::pair<OxenMQ::CommandCallback, bool>*> OxenMQ::get_command(std::string& command) {
|
||||||
if (command.size() > MAX_CATEGORY_LENGTH + 1 + MAX_COMMAND_LENGTH) {
|
if (command.size() > MAX_CATEGORY_LENGTH + 1 + MAX_COMMAND_LENGTH) {
|
||||||
LMQ_LOG(warn, "Invalid command '", command, "': command too long");
|
LMQ_LOG(warn, "Invalid command '", command, "': command too long");
|
||||||
return {};
|
return {};
|
||||||
|
@ -320,7 +320,7 @@ std::pair<LokiMQ::category*, const std::pair<LokiMQ::CommandCallback, bool>*> Lo
|
||||||
return {&catit->second, &callback_it->second};
|
return {&catit->second, &callback_it->second};
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::set_batch_threads(int threads) {
|
void OxenMQ::set_batch_threads(int threads) {
|
||||||
if (proxy_thread.joinable())
|
if (proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot change reserved batch threads after calling `start()`");
|
throw std::logic_error("Cannot change reserved batch threads after calling `start()`");
|
||||||
if (threads < -1) // -1 is the default which is based on general threads
|
if (threads < -1) // -1 is the default which is based on general threads
|
||||||
|
@ -328,7 +328,7 @@ void LokiMQ::set_batch_threads(int threads) {
|
||||||
batch_jobs_reserved = threads;
|
batch_jobs_reserved = threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::set_reply_threads(int threads) {
|
void OxenMQ::set_reply_threads(int threads) {
|
||||||
if (proxy_thread.joinable())
|
if (proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot change reserved reply threads after calling `start()`");
|
throw std::logic_error("Cannot change reserved reply threads after calling `start()`");
|
||||||
if (threads < -1) // -1 is the default which is based on general threads
|
if (threads < -1) // -1 is the default which is based on general threads
|
||||||
|
@ -336,7 +336,7 @@ void LokiMQ::set_reply_threads(int threads) {
|
||||||
reply_jobs_reserved = threads;
|
reply_jobs_reserved = threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::set_general_threads(int threads) {
|
void OxenMQ::set_general_threads(int threads) {
|
||||||
if (proxy_thread.joinable())
|
if (proxy_thread.joinable())
|
||||||
throw std::logic_error("Cannot change general thread count after calling `start()`");
|
throw std::logic_error("Cannot change general thread count after calling `start()`");
|
||||||
if (threads < 1)
|
if (threads < 1)
|
||||||
|
@ -344,7 +344,7 @@ void LokiMQ::set_general_threads(int threads) {
|
||||||
general_workers = threads;
|
general_workers = threads;
|
||||||
}
|
}
|
||||||
|
|
||||||
LokiMQ::run_info& LokiMQ::run_info::load(category* cat_, std::string command_, ConnectionID conn_, Access access_, std::string remote_,
|
OxenMQ::run_info& OxenMQ::run_info::load(category* cat_, std::string command_, ConnectionID conn_, Access access_, std::string remote_,
|
||||||
std::vector<zmq::message_t> data_parts_, const std::pair<CommandCallback, bool>* callback_) {
|
std::vector<zmq::message_t> data_parts_, const std::pair<CommandCallback, bool>* callback_) {
|
||||||
reset();
|
reset();
|
||||||
cat = cat_;
|
cat = cat_;
|
||||||
|
@ -357,7 +357,7 @@ LokiMQ::run_info& LokiMQ::run_info::load(category* cat_, std::string command_, C
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
LokiMQ::run_info& LokiMQ::run_info::load(category* cat_, std::string command_, std::string remote_, std::function<void()> callback) {
|
OxenMQ::run_info& OxenMQ::run_info::load(category* cat_, std::string command_, std::string remote_, std::function<void()> callback) {
|
||||||
reset();
|
reset();
|
||||||
is_injected = true;
|
is_injected = true;
|
||||||
cat = cat_;
|
cat = cat_;
|
||||||
|
@ -369,7 +369,7 @@ LokiMQ::run_info& LokiMQ::run_info::load(category* cat_, std::string command_, s
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
LokiMQ::run_info& LokiMQ::run_info::load(pending_command&& pending) {
|
OxenMQ::run_info& OxenMQ::run_info::load(pending_command&& pending) {
|
||||||
if (auto *f = std::get_if<std::function<void()>>(&pending.callback))
|
if (auto *f = std::get_if<std::function<void()>>(&pending.callback))
|
||||||
return load(&pending.cat, std::move(pending.command), std::move(pending.remote), std::move(*f));
|
return load(&pending.cat, std::move(pending.command), std::move(pending.remote), std::move(*f));
|
||||||
|
|
||||||
|
@ -378,7 +378,7 @@ LokiMQ::run_info& LokiMQ::run_info::load(pending_command&& pending) {
|
||||||
std::move(pending.remote), std::move(pending.data_parts), var::get<0>(pending.callback));
|
std::move(pending.remote), std::move(pending.data_parts), var::get<0>(pending.callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
LokiMQ::run_info& LokiMQ::run_info::load(batch_job&& bj, bool reply_job, int tagged_thread) {
|
OxenMQ::run_info& OxenMQ::run_info::load(batch_job&& bj, bool reply_job, int tagged_thread) {
|
||||||
reset();
|
reset();
|
||||||
is_batch_job = true;
|
is_batch_job = true;
|
||||||
is_reply_job = reply_job;
|
is_reply_job = reply_job;
|
||||||
|
@ -389,7 +389,7 @@ LokiMQ::run_info& LokiMQ::run_info::load(batch_job&& bj, bool reply_job, int tag
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LokiMQ::~LokiMQ() {
|
OxenMQ::~OxenMQ() {
|
||||||
if (!proxy_thread.joinable()) {
|
if (!proxy_thread.joinable()) {
|
||||||
if (!tagged_workers.empty()) {
|
if (!tagged_workers.empty()) {
|
||||||
// This is a bit icky: we have tagged workers that are waiting for a signal on
|
// This is a bit icky: we have tagged workers that are waiting for a signal on
|
||||||
|
@ -416,10 +416,10 @@ LokiMQ::~LokiMQ() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LMQ_LOG(info, "LokiMQ shutting down proxy thread");
|
LMQ_LOG(info, "OxenMQ shutting down proxy thread");
|
||||||
detail::send_control(get_control_socket(), "QUIT");
|
detail::send_control(get_control_socket(), "QUIT");
|
||||||
proxy_thread.join();
|
proxy_thread.join();
|
||||||
LMQ_LOG(info, "LokiMQ proxy thread has stopped");
|
LMQ_LOG(info, "OxenMQ proxy thread has stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, LogLevel lvl) {
|
std::ostream &operator<<(std::ostream &os, LogLevel lvl) {
|
||||||
|
@ -443,5 +443,5 @@ std::string make_random_string(size_t size) {
|
||||||
return rando;
|
return rando;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace lokimq
|
} // namespace oxenmq
|
||||||
// vim:sw=4:et
|
// vim:sw=4:et
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2019-2020, The Loki Project
|
// Copyright (c) 2019-2021, The Oxen Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
|
@ -56,7 +56,7 @@
|
||||||
#error "ZMQ >= 4.3.0 required"
|
#error "ZMQ >= 4.3.0 required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
|
@ -95,22 +95,22 @@ struct TaggedThreadID {
|
||||||
private:
|
private:
|
||||||
int _id;
|
int _id;
|
||||||
explicit constexpr TaggedThreadID(int id) : _id{id} {}
|
explicit constexpr TaggedThreadID(int id) : _id{id} {}
|
||||||
friend class LokiMQ;
|
friend class OxenMQ;
|
||||||
template <typename R> friend class Batch;
|
template <typename R> friend class Batch;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that handles LokiMQ listeners, connections, proxying, and workers. An application
|
* Class that handles OxenMQ listeners, connections, proxying, and workers. An application
|
||||||
* typically has just one instance of this class.
|
* typically has just one instance of this class.
|
||||||
*/
|
*/
|
||||||
class LokiMQ {
|
class OxenMQ {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// The global context
|
/// The global context
|
||||||
zmq::context_t context;
|
zmq::context_t context;
|
||||||
|
|
||||||
/// A unique id for this LokiMQ instance, assigned in a thread-safe manner during construction.
|
/// A unique id for this OxenMQ instance, assigned in a thread-safe manner during construction.
|
||||||
const int object_id;
|
const int object_id;
|
||||||
|
|
||||||
/// The x25519 keypair of this connection. For service nodes these are the long-run x25519 keys
|
/// The x25519 keypair of this connection. For service nodes these are the long-run x25519 keys
|
||||||
|
@ -135,10 +135,10 @@ private:
|
||||||
std::mutex control_sockets_mutex;
|
std::mutex control_sockets_mutex;
|
||||||
|
|
||||||
/// Called to obtain a "command" socket that attaches to `control` to send commands to the
|
/// Called to obtain a "command" socket that attaches to `control` to send commands to the
|
||||||
/// proxy thread from other threads. This socket is unique per thread and LokiMQ instance.
|
/// proxy thread from other threads. This socket is unique per thread and OxenMQ instance.
|
||||||
zmq::socket_t& get_control_socket();
|
zmq::socket_t& get_control_socket();
|
||||||
|
|
||||||
/// Per-thread control sockets used by lokimq threads to talk to this object's proxy thread.
|
/// Per-thread control sockets used by oxenmq threads to talk to this object's proxy thread.
|
||||||
std::unordered_map<std::thread::id, std::unique_ptr<zmq::socket_t>> control_sockets;
|
std::unordered_map<std::thread::id, std::unique_ptr<zmq::socket_t>> control_sockets;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -171,7 +171,7 @@ public:
|
||||||
using ReplyCallback = std::function<void(bool success, std::vector<std::string> data)>;
|
using ReplyCallback = std::function<void(bool success, std::vector<std::string> data)>;
|
||||||
|
|
||||||
/// Called to write a log message. This will only be called if the `level` is >= the current
|
/// Called to write a log message. This will only be called if the `level` is >= the current
|
||||||
/// LokiMQ object log level. It must be a raw function pointer (or a capture-less lambda) for
|
/// OxenMQ object log level. It must be a raw function pointer (or a capture-less lambda) for
|
||||||
/// performance reasons. Takes four arguments: the log level of the message, the filename and
|
/// performance reasons. Takes four arguments: the log level of the message, the filename and
|
||||||
/// line number where the log message was invoked, and the log message itself.
|
/// line number where the log message was invoked, and the log message itself.
|
||||||
using Logger = std::function<void(LogLevel level, const char* file, int line, std::string msg)>;
|
using Logger = std::function<void(LogLevel level, const char* file, int line, std::string msg)>;
|
||||||
|
@ -182,12 +182,12 @@ public:
|
||||||
using ConnectFailure = std::function<void(ConnectionID, std::string_view)>;
|
using ConnectFailure = std::function<void(ConnectionID, std::string_view)>;
|
||||||
|
|
||||||
/// Explicitly non-copyable, non-movable because most things here aren't copyable, and a few
|
/// Explicitly non-copyable, non-movable because most things here aren't copyable, and a few
|
||||||
/// things aren't movable, either. If you need to pass the LokiMQ instance around, wrap it
|
/// things aren't movable, either. If you need to pass the OxenMQ instance around, wrap it
|
||||||
/// in a unique_ptr or shared_ptr.
|
/// in a unique_ptr or shared_ptr.
|
||||||
LokiMQ(const LokiMQ&) = delete;
|
OxenMQ(const OxenMQ&) = delete;
|
||||||
LokiMQ& operator=(const LokiMQ&) = delete;
|
OxenMQ& operator=(const OxenMQ&) = delete;
|
||||||
LokiMQ(LokiMQ&&) = delete;
|
OxenMQ(OxenMQ&&) = delete;
|
||||||
LokiMQ& operator=(LokiMQ&&) = delete;
|
OxenMQ& operator=(OxenMQ&&) = delete;
|
||||||
|
|
||||||
/** How long to wait for handshaking to complete on external connections before timing out and
|
/** How long to wait for handshaking to complete on external connections before timing out and
|
||||||
* closing the connection. Setting this only affects new outgoing connections. */
|
* closing the connection. Setting this only affects new outgoing connections. */
|
||||||
|
@ -196,8 +196,8 @@ public:
|
||||||
/** Whether to use a zmq routing ID based on the pubkey for new outgoing connections. This is
|
/** Whether to use a zmq routing ID based on the pubkey for new outgoing connections. This is
|
||||||
* normally desirable as it allows the listener to recognize that the incoming connection is a
|
* normally desirable as it allows the listener to recognize that the incoming connection is a
|
||||||
* reconnection from the same remote and handover routing to the new socket while closing off
|
* reconnection from the same remote and handover routing to the new socket while closing off
|
||||||
* the (likely dead) old socket. This, however, prevents a single LokiMQ instance from
|
* the (likely dead) old socket. This, however, prevents a single OxenMQ instance from
|
||||||
* establishing multiple connections to the same listening LokiMQ, which is sometimes useful
|
* establishing multiple connections to the same listening OxenMQ, which is sometimes useful
|
||||||
* (for example when testing), and so this option can be overridden to `false` to use completely
|
* (for example when testing), and so this option can be overridden to `false` to use completely
|
||||||
* random zmq routing ids on outgoing connections (which will thus allow multiple connections).
|
* random zmq routing ids on outgoing connections (which will thus allow multiple connections).
|
||||||
*/
|
*/
|
||||||
|
@ -214,13 +214,13 @@ public:
|
||||||
|
|
||||||
/** Minimum reconnect interval: when a connection fails or dies, wait this long before
|
/** Minimum reconnect interval: when a connection fails or dies, wait this long before
|
||||||
* attempting to reconnect. (ZMQ may randomize the value somewhat to avoid reconnection
|
* attempting to reconnect. (ZMQ may randomize the value somewhat to avoid reconnection
|
||||||
* storms). See RECONNECT_INTERVAL_MAX as well. The LokiMQ default is 250ms.
|
* storms). See RECONNECT_INTERVAL_MAX as well. The OxenMQ default is 250ms.
|
||||||
*/
|
*/
|
||||||
std::chrono::milliseconds RECONNECT_INTERVAL = 250ms;
|
std::chrono::milliseconds RECONNECT_INTERVAL = 250ms;
|
||||||
|
|
||||||
/** Maximum reconnect interval. When this is set to a value larger than RECONNECT_INTERVAL then
|
/** Maximum reconnect interval. When this is set to a value larger than RECONNECT_INTERVAL then
|
||||||
* ZMQ's reconnection logic uses an exponential backoff: each reconnection attempts waits twice
|
* ZMQ's reconnection logic uses an exponential backoff: each reconnection attempts waits twice
|
||||||
* as long as the previous attempt, up to this maximum. The LokiMQ default is 5 seconds.
|
* as long as the previous attempt, up to this maximum. The OxenMQ default is 5 seconds.
|
||||||
*/
|
*/
|
||||||
std::chrono::milliseconds RECONNECT_INTERVAL_MAX = 5s;
|
std::chrono::milliseconds RECONNECT_INTERVAL_MAX = 5s;
|
||||||
|
|
||||||
|
@ -539,7 +539,7 @@ private:
|
||||||
/// Runs any queued batch jobs
|
/// Runs any queued batch jobs
|
||||||
void proxy_run_batch_jobs(std::queue<batch_job>& jobs, int reserved, int& active, bool reply);
|
void proxy_run_batch_jobs(std::queue<batch_job>& jobs, int reserved, int& active, bool reply);
|
||||||
|
|
||||||
/// BATCH command. Called with a Batch<R> (see lokimq/batch.h) object pointer for the proxy to
|
/// BATCH command. Called with a Batch<R> (see oxenmq/batch.h) object pointer for the proxy to
|
||||||
/// take over and queue batch jobs.
|
/// take over and queue batch jobs.
|
||||||
void proxy_batch(detail::Batch* batch);
|
void proxy_batch(detail::Batch* batch);
|
||||||
|
|
||||||
|
@ -626,7 +626,7 @@ private:
|
||||||
/// Details for a pending command; such a command already has authenticated access and is just
|
/// Details for a pending command; such a command already has authenticated access and is just
|
||||||
/// waiting for a thread to become available to handle it. This also gets used (via the
|
/// waiting for a thread to become available to handle it. This also gets used (via the
|
||||||
/// `callback` variant) for injected external jobs to be able to integrate some external
|
/// `callback` variant) for injected external jobs to be able to integrate some external
|
||||||
/// interface with the lokimq job queue.
|
/// interface with the oxenmq job queue.
|
||||||
struct pending_command {
|
struct pending_command {
|
||||||
category& cat;
|
category& cat;
|
||||||
std::string command;
|
std::string command;
|
||||||
|
@ -721,7 +721,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* LokiMQ constructor. This constructs the object but does not start it; you will typically
|
* OxenMQ constructor. This constructs the object but does not start it; you will typically
|
||||||
* want to first add categories and commands, then finish startup by invoking `start()`.
|
* want to first add categories and commands, then finish startup by invoking `start()`.
|
||||||
* (Categories and commands cannot be added after startup).
|
* (Categories and commands cannot be added after startup).
|
||||||
*
|
*
|
||||||
|
@ -745,7 +745,7 @@ public:
|
||||||
* listening in curve25519 mode (otherwise we couldn't verify its authenticity). Should return
|
* listening in curve25519 mode (otherwise we couldn't verify its authenticity). Should return
|
||||||
* empty for not found or if SN lookups are not supported.
|
* empty for not found or if SN lookups are not supported.
|
||||||
*
|
*
|
||||||
* @param allow_incoming is a callback that LokiMQ can use to determine whether an incoming
|
* @param allow_incoming is a callback that OxenMQ can use to determine whether an incoming
|
||||||
* connection should be allowed at all and, if so, whether the connection is from a known
|
* connection should be allowed at all and, if so, whether the connection is from a known
|
||||||
* service node. Called with the connecting IP, the remote's verified x25519 pubkey, and the
|
* service node. Called with the connecting IP, the remote's verified x25519 pubkey, and the
|
||||||
* called on incoming connections with the (verified) incoming connection
|
* called on incoming connections with the (verified) incoming connection
|
||||||
|
@ -758,7 +758,7 @@ public:
|
||||||
* @param level the initial log level; defaults to warn. The log level can be changed later by
|
* @param level the initial log level; defaults to warn. The log level can be changed later by
|
||||||
* calling log_level(...).
|
* calling log_level(...).
|
||||||
*/
|
*/
|
||||||
LokiMQ( std::string pubkey,
|
OxenMQ( std::string pubkey,
|
||||||
std::string privkey,
|
std::string privkey,
|
||||||
bool service_node,
|
bool service_node,
|
||||||
SNRemoteAddress sn_lookup,
|
SNRemoteAddress sn_lookup,
|
||||||
|
@ -766,26 +766,26 @@ public:
|
||||||
LogLevel level = LogLevel::warn);
|
LogLevel level = LogLevel::warn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplified LokiMQ constructor for a non-listening client or simple listener without any
|
* Simplified OxenMQ constructor for a non-listening client or simple listener without any
|
||||||
* outgoing SN connection lookup capabilities. The LokiMQ object will not be able to establish
|
* outgoing SN connection lookup capabilities. The OxenMQ object will not be able to establish
|
||||||
* new connections (including reconnections) to service nodes by pubkey.
|
* new connections (including reconnections) to service nodes by pubkey.
|
||||||
*/
|
*/
|
||||||
explicit LokiMQ(
|
explicit OxenMQ(
|
||||||
Logger logger = [](LogLevel, const char*, int, std::string) { },
|
Logger logger = [](LogLevel, const char*, int, std::string) { },
|
||||||
LogLevel level = LogLevel::warn)
|
LogLevel level = LogLevel::warn)
|
||||||
: LokiMQ("", "", false, [](auto) { return ""s; /*no peer lookups*/ }, std::move(logger), level) {}
|
: OxenMQ("", "", false, [](auto) { return ""s; /*no peer lookups*/ }, std::move(logger), level) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor; instructs the proxy to quit. The proxy tells all workers to quit, waits for them
|
* Destructor; instructs the proxy to quit. The proxy tells all workers to quit, waits for them
|
||||||
* to quit and rejoins the threads then quits itself. The outer thread (where the destructor is
|
* to quit and rejoins the threads then quits itself. The outer thread (where the destructor is
|
||||||
* running) rejoins the proxy thread.
|
* running) rejoins the proxy thread.
|
||||||
*/
|
*/
|
||||||
~LokiMQ();
|
~OxenMQ();
|
||||||
|
|
||||||
/// Sets the log level of the LokiMQ object.
|
/// Sets the log level of the OxenMQ object.
|
||||||
void log_level(LogLevel level);
|
void log_level(LogLevel level);
|
||||||
|
|
||||||
/// Gets the log level of the LokiMQ object.
|
/// Gets the log level of the OxenMQ object.
|
||||||
LogLevel log_level() const;
|
LogLevel log_level() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -848,7 +848,7 @@ public:
|
||||||
*
|
*
|
||||||
* Aliases should follow the `category.command` format for both the from and to names, and
|
* Aliases should follow the `category.command` format for both the from and to names, and
|
||||||
* should only be called for `to` categories that are already defined. The category name is not
|
* should only be called for `to` categories that are already defined. The category name is not
|
||||||
* currently enforced on the `from` name (for backwards compatility with Loki's quorumnet code)
|
* currently enforced on the `from` name (for backwards compatility with Oxen's quorumnet code)
|
||||||
* but will be at some point.
|
* but will be at some point.
|
||||||
*
|
*
|
||||||
* Access permissions for an aliased command depend only on the mapped-to value; for example, if
|
* Access permissions for an aliased command depend only on the mapped-to value; for example, if
|
||||||
|
@ -871,7 +871,7 @@ public:
|
||||||
* \param name - the name of the thread; will be used in log messages and (if supported by the
|
* \param name - the name of the thread; will be used in log messages and (if supported by the
|
||||||
* OS) as the system thread name.
|
* OS) as the system thread name.
|
||||||
*
|
*
|
||||||
* \param start - an optional callback to invoke from the thread as soon as LokiMQ itself starts
|
* \param start - an optional callback to invoke from the thread as soon as OxenMQ itself starts
|
||||||
* up (i.e. after a call to `start()`).
|
* up (i.e. after a call to `start()`).
|
||||||
*
|
*
|
||||||
* \returns a TaggedThreadID object that can be passed to job(), batch(), or add_timer() to
|
* \returns a TaggedThreadID object that can be passed to job(), batch(), or add_timer() to
|
||||||
|
@ -887,7 +887,7 @@ public:
|
||||||
* Note that some internal jobs are counted as batch jobs: in particular timers added via
|
* Note that some internal jobs are counted as batch jobs: in particular timers added via
|
||||||
* add_timer() are scheduled as batch jobs.
|
* add_timer() are scheduled as batch jobs.
|
||||||
*
|
*
|
||||||
* Cannot be called after start()ing the LokiMQ instance.
|
* Cannot be called after start()ing the OxenMQ instance.
|
||||||
*/
|
*/
|
||||||
void set_batch_threads(int threads);
|
void set_batch_threads(int threads);
|
||||||
|
|
||||||
|
@ -899,7 +899,7 @@ public:
|
||||||
*
|
*
|
||||||
* Defaults to one-eighth of the number of configured general threads, rounded up.
|
* Defaults to one-eighth of the number of configured general threads, rounded up.
|
||||||
*
|
*
|
||||||
* Cannot be changed after start()ing the LokiMQ instance.
|
* Cannot be changed after start()ing the OxenMQ instance.
|
||||||
*/
|
*/
|
||||||
void set_reply_threads(int threads);
|
void set_reply_threads(int threads);
|
||||||
|
|
||||||
|
@ -914,7 +914,7 @@ public:
|
||||||
*
|
*
|
||||||
* Defaults to `std::thread::hardware_concurrency()`.
|
* Defaults to `std::thread::hardware_concurrency()`.
|
||||||
*
|
*
|
||||||
* Cannot be called after start()ing the LokiMQ instance.
|
* Cannot be called after start()ing the OxenMQ instance.
|
||||||
*/
|
*/
|
||||||
void set_general_threads(int threads);
|
void set_general_threads(int threads);
|
||||||
|
|
||||||
|
@ -1006,7 +1006,7 @@ public:
|
||||||
* established or failed to establish.
|
* established or failed to establish.
|
||||||
*
|
*
|
||||||
* @param remote the remote connection address either as implicitly from a string or as a full
|
* @param remote the remote connection address either as implicitly from a string or as a full
|
||||||
* lokimq::address object; see address.h for details. This specifies both the connection
|
* oxenmq::address object; see address.h for details. This specifies both the connection
|
||||||
* address and whether curve encryption should be used.
|
* address and whether curve encryption should be used.
|
||||||
* @param on_connect called with the identifier after the connection has been established.
|
* @param on_connect called with the identifier after the connection has been established.
|
||||||
* @param on_failure called with the identifier and failure message if we fail to connect.
|
* @param on_failure called with the identifier and failure message if we fail to connect.
|
||||||
|
@ -1033,7 +1033,7 @@ public:
|
||||||
/// encryption as separate arguments. New code should either use a pubkey-embedded address
|
/// encryption as separate arguments. New code should either use a pubkey-embedded address
|
||||||
/// string, or specify remote address and pubkey with an `address` object such as:
|
/// string, or specify remote address and pubkey with an `address` object such as:
|
||||||
/// connect_remote(address{remote, pubkey}, ...)
|
/// connect_remote(address{remote, pubkey}, ...)
|
||||||
[[deprecated("use connect_remote() with a lokimq::address instead")]]
|
[[deprecated("use connect_remote() with a oxenmq::address instead")]]
|
||||||
ConnectionID connect_remote(std::string_view remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
ConnectionID connect_remote(std::string_view remote, ConnectSuccess on_connect, ConnectFailure on_failure,
|
||||||
std::string_view pubkey,
|
std::string_view pubkey,
|
||||||
AuthLevel auth_level = AuthLevel::none,
|
AuthLevel auth_level = AuthLevel::none,
|
||||||
|
@ -1058,7 +1058,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue a message to be relayed to the given service node or remote without requiring a reply.
|
* Queue a message to be relayed to the given service node or remote without requiring a reply.
|
||||||
* LokiMQ will attempt to relay the message (first connecting and handshaking to the remote SN
|
* OxenMQ will attempt to relay the message (first connecting and handshaking to the remote SN
|
||||||
* if not already connected).
|
* if not already connected).
|
||||||
*
|
*
|
||||||
* If a new connection is established it will have a relatively short (30s) idle timeout. If
|
* If a new connection is established it will have a relatively short (30s) idle timeout. If
|
||||||
|
@ -1128,10 +1128,10 @@ public:
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void request(ConnectionID to, std::string_view cmd, ReplyCallback callback, const T&... opts);
|
void request(ConnectionID to, std::string_view cmd, ReplyCallback callback, const T&... opts);
|
||||||
|
|
||||||
/** Injects an external task into the lokimq command queue. This is used to allow connecting
|
/** Injects an external task into the oxenmq command queue. This is used to allow connecting
|
||||||
* non-LokiMQ requests into the LokiMQ thread pool as if they were ordinary requests, to be
|
* non-OxenMQ requests into the OxenMQ thread pool as if they were ordinary requests, to be
|
||||||
* scheduled as commands of an individual category. For example, you might support rpc requests
|
* scheduled as commands of an individual category. For example, you might support rpc requests
|
||||||
* via LokiMQ as `rpc.some_command` and *also* accept them over HTTP. Using `inject_task()`
|
* via OxenMQ as `rpc.some_command` and *also* accept them over HTTP. Using `inject_task()`
|
||||||
* allows you to handle processing the request in the same thread pool with the same priority as
|
* allows you to handle processing the request in the same thread pool with the same priority as
|
||||||
* `rpc.*` commands.
|
* `rpc.*` commands.
|
||||||
*
|
*
|
||||||
|
@ -1154,12 +1154,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void inject_task(const std::string& category, std::string command, std::string remote, std::function<void()> callback);
|
void inject_task(const std::string& category, std::string command, std::string remote, std::function<void()> callback);
|
||||||
|
|
||||||
/// The key pair this LokiMQ was created with; if empty keys were given during construction then
|
/// The key pair this OxenMQ was created with; if empty keys were given during construction then
|
||||||
/// this returns the generated keys.
|
/// this returns the generated keys.
|
||||||
const std::string& get_pubkey() const { return pubkey; }
|
const std::string& get_pubkey() const { return pubkey; }
|
||||||
const std::string& get_privkey() const { return privkey; }
|
const std::string& get_privkey() const { return privkey; }
|
||||||
|
|
||||||
/** Updates (or initially sets) LokiMQ's list of service node pubkeys with the given list.
|
/** Updates (or initially sets) OxenMQ's list of service node pubkeys with the given list.
|
||||||
*
|
*
|
||||||
* This has two main effects:
|
* This has two main effects:
|
||||||
*
|
*
|
||||||
|
@ -1182,7 +1182,7 @@ public:
|
||||||
|
|
||||||
/** Updates the list of active pubkeys by adding or removing the given pubkeys from the existing
|
/** Updates the list of active pubkeys by adding or removing the given pubkeys from the existing
|
||||||
* list. This is more efficient when the incremental information is already available; if it
|
* list. This is more efficient when the incremental information is already available; if it
|
||||||
* isn't, simply call set_active_sns with a new list to have LokiMQ figure out what was added or
|
* isn't, simply call set_active_sns with a new list to have OxenMQ figure out what was added or
|
||||||
* removed.
|
* removed.
|
||||||
*
|
*
|
||||||
* \param added new pubkeys that were added since the last set_active_sns or update_active_sns
|
* \param added new pubkeys that were added since the last set_active_sns or update_active_sns
|
||||||
|
@ -1197,7 +1197,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Batches a set of jobs to be executed by workers, optionally followed by a completion function.
|
* Batches a set of jobs to be executed by workers, optionally followed by a completion function.
|
||||||
*
|
*
|
||||||
* Must include lokimq/batch.h to use.
|
* Must include oxenmq/batch.h to use.
|
||||||
*/
|
*/
|
||||||
template <typename R>
|
template <typename R>
|
||||||
void batch(Batch<R>&& batch);
|
void batch(Batch<R>&& batch);
|
||||||
|
@ -1241,18 +1241,18 @@ public:
|
||||||
/// .add_request_command("b", ...)
|
/// .add_request_command("b", ...)
|
||||||
/// ;
|
/// ;
|
||||||
class CatHelper {
|
class CatHelper {
|
||||||
LokiMQ& lmq;
|
OxenMQ& lmq;
|
||||||
std::string cat;
|
std::string cat;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CatHelper(LokiMQ& lmq, std::string cat) : lmq{lmq}, cat{std::move(cat)} {}
|
CatHelper(OxenMQ& lmq, std::string cat) : lmq{lmq}, cat{std::move(cat)} {}
|
||||||
|
|
||||||
CatHelper& add_command(std::string name, LokiMQ::CommandCallback callback) {
|
CatHelper& add_command(std::string name, OxenMQ::CommandCallback callback) {
|
||||||
lmq.add_command(cat, std::move(name), std::move(callback));
|
lmq.add_command(cat, std::move(name), std::move(callback));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CatHelper& add_request_command(std::string name, LokiMQ::CommandCallback callback) {
|
CatHelper& add_request_command(std::string name, OxenMQ::CommandCallback callback) {
|
||||||
lmq.add_request_command(cat, std::move(name), std::move(callback));
|
lmq.add_request_command(cat, std::move(name), std::move(callback));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -1368,7 +1368,7 @@ struct queue_full {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
/// Takes an rvalue reference, moves it into a new instance then returns a uintptr_t value
|
/// Takes an rvalue reference, moves it into a new instance then returns a uintptr_t value
|
||||||
/// containing the pointer to be serialized to pass (via lokimq queues) from one thread to another.
|
/// containing the pointer to be serialized to pass (via oxenmq queues) from one thread to another.
|
||||||
/// Must be matched with a deserializer_pointer on the other side to reconstitute the object and
|
/// Must be matched with a deserializer_pointer on the other side to reconstitute the object and
|
||||||
/// destroy the intermediate pointer.
|
/// destroy the intermediate pointer.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -1468,7 +1468,7 @@ bt_dict build_send(ConnectionID to, std::string_view cmd, T&&... opts) {
|
||||||
|
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void LokiMQ::send(ConnectionID to, std::string_view cmd, const T&... opts) {
|
void OxenMQ::send(ConnectionID to, std::string_view cmd, const T&... opts) {
|
||||||
detail::send_control(get_control_socket(), "SEND",
|
detail::send_control(get_control_socket(), "SEND",
|
||||||
bt_serialize(detail::build_send(std::move(to), cmd, opts...)));
|
bt_serialize(detail::build_send(std::move(to), cmd, opts...)));
|
||||||
}
|
}
|
||||||
|
@ -1476,7 +1476,7 @@ void LokiMQ::send(ConnectionID to, std::string_view cmd, const T&... opts) {
|
||||||
std::string make_random_string(size_t size);
|
std::string make_random_string(size_t size);
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void LokiMQ::request(ConnectionID to, std::string_view cmd, ReplyCallback callback, const T &...opts) {
|
void OxenMQ::request(ConnectionID to, std::string_view cmd, ReplyCallback callback, const T &...opts) {
|
||||||
const auto reply_tag = make_random_string(15); // 15 random bytes is lots and should keep us in most stl implementations' small string optimization
|
const auto reply_tag = make_random_string(15); // 15 random bytes is lots and should keep us in most stl implementations' small string optimization
|
||||||
bt_dict control_data = detail::build_send(std::move(to), cmd, reply_tag, opts...);
|
bt_dict control_data = detail::build_send(std::move(to), cmd, reply_tag, opts...);
|
||||||
control_data["request"] = true;
|
control_data["request"] = true;
|
||||||
|
@ -1487,23 +1487,23 @@ void LokiMQ::request(ConnectionID to, std::string_view cmd, ReplyCallback callba
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void Message::send_back(std::string_view command, Args&&... args) {
|
void Message::send_back(std::string_view command, Args&&... args) {
|
||||||
lokimq.send(conn, command, send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
oxenmq.send(conn, command, send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void Message::send_reply(Args&&... args) {
|
void Message::send_reply(Args&&... args) {
|
||||||
assert(!reply_tag.empty());
|
assert(!reply_tag.empty());
|
||||||
lokimq.send(conn, "REPLY", reply_tag, send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
oxenmq.send(conn, "REPLY", reply_tag, send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callback, typename... Args>
|
template <typename Callback, typename... Args>
|
||||||
void Message::send_request(std::string_view cmd, Callback&& callback, Args&&... args) {
|
void Message::send_request(std::string_view cmd, Callback&& callback, Args&&... args) {
|
||||||
lokimq.request(conn, cmd, std::forward<Callback>(callback),
|
oxenmq.request(conn, cmd, std::forward<Callback>(callback),
|
||||||
send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
send_option::optional{!conn.sn()}, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When log messages are invoked we strip out anything before this in the filename:
|
// When log messages are invoked we strip out anything before this in the filename:
|
||||||
constexpr std::string_view LOG_PREFIX{"lokimq/", 7};
|
constexpr std::string_view LOG_PREFIX{"oxenmq/", 7};
|
||||||
inline std::string_view trim_log_filename(std::string_view local_file) {
|
inline std::string_view trim_log_filename(std::string_view local_file) {
|
||||||
auto chop = local_file.rfind(LOG_PREFIX);
|
auto chop = local_file.rfind(LOG_PREFIX);
|
||||||
if (chop != local_file.npos)
|
if (chop != local_file.npos)
|
||||||
|
@ -1512,7 +1512,7 @@ inline std::string_view trim_log_filename(std::string_view local_file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
void LokiMQ::log(LogLevel lvl, const char* file, int line, const T&... stuff) {
|
void OxenMQ::log(LogLevel lvl, const char* file, int line, const T&... stuff) {
|
||||||
if (log_level() < lvl)
|
if (log_level() < lvl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1523,6 +1523,6 @@ void LokiMQ::log(LogLevel lvl, const char* file, int line, const T&... stuff) {
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &os, LogLevel lvl);
|
std::ostream &operator<<(std::ostream &os, LogLevel lvl);
|
||||||
|
|
||||||
} // namespace lokimq
|
} // namespace oxenmq
|
||||||
|
|
||||||
// vim:sw=4:et
|
// vim:sw=4:et
|
|
@ -1,5 +1,5 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
#include "hex.h"
|
#include "hex.h"
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
@ -17,9 +17,9 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
void LokiMQ::proxy_quit() {
|
void OxenMQ::proxy_quit() {
|
||||||
LMQ_LOG(debug, "Received quit command, shutting down proxy thread");
|
LMQ_LOG(debug, "Received quit command, shutting down proxy thread");
|
||||||
|
|
||||||
assert(std::none_of(workers.begin(), workers.end(), [](auto& worker) { return worker.worker_thread.joinable(); }));
|
assert(std::none_of(workers.begin(), workers.end(), [](auto& worker) { return worker.worker_thread.joinable(); }));
|
||||||
|
@ -41,7 +41,7 @@ void LokiMQ::proxy_quit() {
|
||||||
LMQ_LOG(debug, "Proxy thread teardown complete");
|
LMQ_LOG(debug, "Proxy thread teardown complete");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_send(bt_dict_consumer data) {
|
void OxenMQ::proxy_send(bt_dict_consumer data) {
|
||||||
// NB: bt_dict_consumer goes in alphabetical order
|
// NB: bt_dict_consumer goes in alphabetical order
|
||||||
std::string_view hint;
|
std::string_view hint;
|
||||||
std::chrono::milliseconds keep_alive{DEFAULT_SEND_KEEP_ALIVE};
|
std::chrono::milliseconds keep_alive{DEFAULT_SEND_KEEP_ALIVE};
|
||||||
|
@ -205,7 +205,7 @@ void LokiMQ::proxy_send(bt_dict_consumer data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_reply(bt_dict_consumer data) {
|
void OxenMQ::proxy_reply(bt_dict_consumer data) {
|
||||||
bool have_conn_id = false;
|
bool have_conn_id = false;
|
||||||
ConnectionID conn_id{0};
|
ConnectionID conn_id{0};
|
||||||
if (data.skip_until("conn_id")) {
|
if (data.skip_until("conn_id")) {
|
||||||
|
@ -250,11 +250,11 @@ void LokiMQ::proxy_reply(bt_dict_consumer data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_control_message(std::vector<zmq::message_t>& parts) {
|
void OxenMQ::proxy_control_message(std::vector<zmq::message_t>& parts) {
|
||||||
// We throw an uncaught exception here because we only generate control messages internally in
|
// We throw an uncaught exception here because we only generate control messages internally in
|
||||||
// lokimq code: if one of these condition fail it's a lokimq bug.
|
// oxenmq code: if one of these condition fail it's a oxenmq bug.
|
||||||
if (parts.size() < 2)
|
if (parts.size() < 2)
|
||||||
throw std::logic_error("LokiMQ bug: Expected 2-3 message parts for a proxy control message");
|
throw std::logic_error("OxenMQ bug: Expected 2-3 message parts for a proxy control message");
|
||||||
auto route = view(parts[0]), cmd = view(parts[1]);
|
auto route = view(parts[0]), cmd = view(parts[1]);
|
||||||
LMQ_TRACE("control message: ", cmd);
|
LMQ_TRACE("control message: ", cmd);
|
||||||
if (parts.size() == 3) {
|
if (parts.size() == 3) {
|
||||||
|
@ -306,11 +306,11 @@ void LokiMQ::proxy_control_message(std::vector<zmq::message_t>& parts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw std::runtime_error("LokiMQ bug: Proxy received invalid control command: " +
|
throw std::runtime_error("OxenMQ bug: Proxy received invalid control command: " +
|
||||||
std::string{cmd} + " (" + std::to_string(parts.size()) + ")");
|
std::string{cmd} + " (" + std::to_string(parts.size()) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_loop() {
|
void OxenMQ::proxy_loop() {
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__sun) || defined(__MINGW32__)
|
#if defined(__linux__) || defined(__sun) || defined(__MINGW32__)
|
||||||
pthread_setname_np(pthread_self(), "lmq-proxy");
|
pthread_setname_np(pthread_self(), "lmq-proxy");
|
||||||
|
@ -371,7 +371,7 @@ void LokiMQ::proxy_loop() {
|
||||||
listener.set(zmq::sockopt::router_mandatory, true);
|
listener.set(zmq::sockopt::router_mandatory, true);
|
||||||
|
|
||||||
listener.bind(bind[i].first);
|
listener.bind(bind[i].first);
|
||||||
LMQ_LOG(info, "LokiMQ listening on ", bind[i].first);
|
LMQ_LOG(info, "OxenMQ listening on ", bind[i].first);
|
||||||
|
|
||||||
connections.push_back(std::move(listener));
|
connections.push_back(std::move(listener));
|
||||||
auto conn_id = next_conn_id++;
|
auto conn_id = next_conn_id++;
|
||||||
|
@ -547,7 +547,7 @@ static bool is_error_response(std::string_view cmd) {
|
||||||
|
|
||||||
// Return true if we recognized/handled the builtin command (even if we reject it for whatever
|
// Return true if we recognized/handled the builtin command (even if we reject it for whatever
|
||||||
// reason)
|
// reason)
|
||||||
bool LokiMQ::proxy_handle_builtin(size_t conn_index, std::vector<zmq::message_t>& parts) {
|
bool OxenMQ::proxy_handle_builtin(size_t conn_index, std::vector<zmq::message_t>& parts) {
|
||||||
// Doubling as a bool and an offset:
|
// Doubling as a bool and an offset:
|
||||||
size_t incoming = connections[conn_index].get(zmq::sockopt::type) == ZMQ_ROUTER;
|
size_t incoming = connections[conn_index].get(zmq::sockopt::type) == ZMQ_ROUTER;
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ bool LokiMQ::proxy_handle_builtin(size_t conn_index, std::vector<zmq::message_t>
|
||||||
// pre-1.1.0 sent just a plain UNKNOWNCOMMAND (without the actual command); this was not
|
// pre-1.1.0 sent just a plain UNKNOWNCOMMAND (without the actual command); this was not
|
||||||
// useful, but also this response is *expected* for things 1.0.5 didn't understand, like
|
// useful, but also this response is *expected* for things 1.0.5 didn't understand, like
|
||||||
// FORBIDDEN_SN: so log it only at debug level and move on.
|
// FORBIDDEN_SN: so log it only at debug level and move on.
|
||||||
LMQ_LOG(debug, "Received plain UNKNOWNCOMMAND; remote is probably an older lokimq. Ignoring.");
|
LMQ_LOG(debug, "Received plain UNKNOWNCOMMAND; remote is probably an older oxenmq. Ignoring.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,7 +669,7 @@ bool LokiMQ::proxy_handle_builtin(size_t conn_index, std::vector<zmq::message_t>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_process_queue() {
|
void OxenMQ::proxy_process_queue() {
|
||||||
if (max_workers == 0) // shutting down
|
if (max_workers == 0) // shutting down
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
// Deprecated type alias for std::string_view
|
// Deprecated type alias for std::string_view
|
||||||
using string_view = std::string_view;
|
using string_view = std::string_view;
|
|
@ -0,0 +1,5 @@
|
||||||
|
namespace oxenmq {
|
||||||
|
constexpr int VERSION_MAJOR = @OXENMQ_VERSION_MAJOR@;
|
||||||
|
constexpr int VERSION_MINOR = @OXENMQ_VERSION_MINOR@;
|
||||||
|
constexpr int VERSION_PATCH = @OXENMQ_VERSION_PATCH@;
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#include "lokimq.h"
|
#include "oxenmq.h"
|
||||||
#include "batch.h"
|
#include "batch.h"
|
||||||
#include "lokimq-internal.h"
|
#include "oxenmq-internal.h"
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -9,7 +9,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace lokimq {
|
namespace oxenmq {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ namespace {
|
||||||
// received. If "QUIT" was received, replies with "QUITTING" on the socket and closes it, then
|
// received. If "QUIT" was received, replies with "QUITTING" on the socket and closes it, then
|
||||||
// returns false.
|
// returns false.
|
||||||
[[gnu::always_inline]] inline
|
[[gnu::always_inline]] inline
|
||||||
bool worker_wait_for(LokiMQ& lmq, zmq::socket_t& sock, std::vector<zmq::message_t>& parts, const std::string_view worker_id, const std::string_view expect) {
|
bool worker_wait_for(OxenMQ& lmq, zmq::socket_t& sock, std::vector<zmq::message_t>& parts, const std::string_view worker_id, const std::string_view expect) {
|
||||||
while (true) {
|
while (true) {
|
||||||
lmq.log(LogLevel::debug, __FILE__, __LINE__, "worker ", worker_id, " waiting for ", expect);
|
lmq.log(LogLevel::debug, __FILE__, __LINE__, "worker ", worker_id, " waiting for ", expect);
|
||||||
parts.clear();
|
parts.clear();
|
||||||
|
@ -46,7 +46,7 @@ bool worker_wait_for(LokiMQ& lmq, zmq::socket_t& sock, std::vector<zmq::message_
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::worker_thread(unsigned int index, std::optional<std::string> tagged, std::function<void()> start) {
|
void OxenMQ::worker_thread(unsigned int index, std::optional<std::string> tagged, std::function<void()> start) {
|
||||||
std::string routing_id = (tagged ? "t" : "w") + std::to_string(index); // for routing
|
std::string routing_id = (tagged ? "t" : "w") + std::to_string(index); // for routing
|
||||||
std::string_view worker_id{tagged ? *tagged : routing_id}; // for debug
|
std::string_view worker_id{tagged ? *tagged : routing_id}; // for debug
|
||||||
|
|
||||||
|
@ -72,8 +72,8 @@ void LokiMQ::worker_thread(unsigned int index, std::optional<std::string> tagged
|
||||||
|
|
||||||
bool waiting_for_command;
|
bool waiting_for_command;
|
||||||
if (tagged) {
|
if (tagged) {
|
||||||
// If we're a tagged worker then we got started up before LokiMQ started, so we need to wait
|
// If we're a tagged worker then we got started up before OxenMQ started, so we need to wait
|
||||||
// for an all-clear signal from LokiMQ first, then we fire our `start` callback, then we can
|
// for an all-clear signal from OxenMQ first, then we fire our `start` callback, then we can
|
||||||
// start waiting for commands in the main loop further down. (We also can't get the
|
// start waiting for commands in the main loop further down. (We also can't get the
|
||||||
// reference to our `tagged_workers` element until the main proxy threads is running).
|
// reference to our `tagged_workers` element until the main proxy threads is running).
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ void LokiMQ::worker_thread(unsigned int index, std::optional<std::string> tagged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LokiMQ::run_info& LokiMQ::get_idle_worker() {
|
OxenMQ::run_info& OxenMQ::get_idle_worker() {
|
||||||
if (idle_workers.empty()) {
|
if (idle_workers.empty()) {
|
||||||
size_t id = workers.size();
|
size_t id = workers.size();
|
||||||
assert(workers.capacity() > id);
|
assert(workers.capacity() > id);
|
||||||
|
@ -174,7 +174,7 @@ LokiMQ::run_info& LokiMQ::get_idle_worker() {
|
||||||
return workers[id];
|
return workers[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_worker_message(std::vector<zmq::message_t>& parts) {
|
void OxenMQ::proxy_worker_message(std::vector<zmq::message_t>& parts) {
|
||||||
// Process messages sent by workers
|
// Process messages sent by workers
|
||||||
if (parts.size() != 2) {
|
if (parts.size() != 2) {
|
||||||
LMQ_LOG(error, "Received send invalid ", parts.size(), "-part message");
|
LMQ_LOG(error, "Received send invalid ", parts.size(), "-part message");
|
||||||
|
@ -268,14 +268,14 @@ void LokiMQ::proxy_worker_message(std::vector<zmq::message_t>& parts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_run_worker(run_info& run) {
|
void OxenMQ::proxy_run_worker(run_info& run) {
|
||||||
if (!run.worker_thread.joinable())
|
if (!run.worker_thread.joinable())
|
||||||
run.worker_thread = std::thread{[this, id=run.worker_id] { worker_thread(id); }};
|
run.worker_thread = std::thread{[this, id=run.worker_id] { worker_thread(id); }};
|
||||||
else
|
else
|
||||||
send_routed_message(workers_socket, run.worker_routing_id, "RUN");
|
send_routed_message(workers_socket, run.worker_routing_id, "RUN");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_to_worker(size_t conn_index, std::vector<zmq::message_t>& parts) {
|
void OxenMQ::proxy_to_worker(size_t conn_index, std::vector<zmq::message_t>& parts) {
|
||||||
bool outgoing = connections[conn_index].get(zmq::sockopt::type) == ZMQ_DEALER;
|
bool outgoing = connections[conn_index].get(zmq::sockopt::type) == ZMQ_DEALER;
|
||||||
|
|
||||||
peer_info tmp_peer;
|
peer_info tmp_peer;
|
||||||
|
@ -377,7 +377,7 @@ void LokiMQ::proxy_to_worker(size_t conn_index, std::vector<zmq::message_t>& par
|
||||||
category.active_threads++;
|
category.active_threads++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::inject_task(const std::string& category, std::string command, std::string remote, std::function<void()> callback) {
|
void OxenMQ::inject_task(const std::string& category, std::string command, std::string remote, std::function<void()> callback) {
|
||||||
if (!callback) return;
|
if (!callback) return;
|
||||||
auto it = categories.find(category);
|
auto it = categories.find(category);
|
||||||
if (it == categories.end())
|
if (it == categories.end())
|
||||||
|
@ -386,7 +386,7 @@ void LokiMQ::inject_task(const std::string& category, std::string command, std::
|
||||||
injected_task{it->second, std::move(command), std::move(remote), std::move(callback)})));
|
injected_task{it->second, std::move(command), std::move(remote), std::move(callback)})));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LokiMQ::proxy_inject_task(injected_task task) {
|
void OxenMQ::proxy_inject_task(injected_task task) {
|
||||||
auto& category = task.cat;
|
auto& category = task.cat;
|
||||||
if (category.active_threads >= category.reserved_threads && active_workers() >= general_workers) {
|
if (category.active_threads >= category.reserved_threads && active_workers() >= general_workers) {
|
||||||
// No free worker slot, queue for later
|
// No free worker slot, queue for later
|
|
@ -19,7 +19,7 @@ add_executable(tests ${LMQ_TEST_SRC})
|
||||||
|
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
|
||||||
target_link_libraries(tests Catch2::Catch2 lokimq Threads::Threads)
|
target_link_libraries(tests Catch2::Catch2 oxenmq Threads::Threads)
|
||||||
|
|
||||||
set_target_properties(tests PROPERTIES
|
set_target_properties(tests PROPERTIES
|
||||||
CXX_STANDARD 17
|
CXX_STANDARD 17
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "lokimq/lokimq.h"
|
#include "oxenmq/oxenmq.h"
|
||||||
#include <catch2/catch.hpp>
|
#include <catch2/catch.hpp>
|
||||||
|
|
||||||
using namespace lokimq;
|
using namespace oxenmq;
|
||||||
|
|
||||||
static auto startup = std::chrono::steady_clock::now();
|
static auto startup = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ inline std::unique_lock<std::mutex> catch_lock() {
|
||||||
return std::unique_lock<std::mutex>{mutex};
|
return std::unique_lock<std::mutex>{mutex};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline LokiMQ::Logger get_logger(std::string prefix = "") {
|
inline OxenMQ::Logger get_logger(std::string prefix = "") {
|
||||||
std::string me = "tests/common.h";
|
std::string me = "tests/common.h";
|
||||||
std::string strip = __FILE__;
|
std::string strip = __FILE__;
|
||||||
if (strip.substr(strip.size() - me.size()) == me)
|
if (strip.substr(strip.size() - me.size()) == me)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "lokimq/address.h"
|
#include "oxenmq/address.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
const std::string pk = "\xf1\x6b\xa5\x59\x10\x39\xf0\x89\xb4\x2a\x83\x41\x75\x09\x30\x94\x07\x4d\x0d\x93\x7a\x79\xe5\x3e\x5c\xe7\x30\xf9\x46\xe1\x4b\x88";
|
const std::string pk = "\xf1\x6b\xa5\x59\x10\x39\xf0\x89\xb4\x2a\x83\x41\x75\x09\x30\x94\x07\x4d\x0d\x93\x7a\x79\xe5\x3e\x5c\xe7\x30\xf9\x46\xe1\x4b\x88";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "lokimq/batch.h"
|
#include "oxenmq/batch.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ double do_my_task(int input) {
|
||||||
|
|
||||||
std::promise<std::pair<double, int>> done;
|
std::promise<std::pair<double, int>> done;
|
||||||
|
|
||||||
void continue_big_task(std::vector<lokimq::job_result<double>> results) {
|
void continue_big_task(std::vector<oxenmq::job_result<double>> results) {
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
int exc_count = 0;
|
int exc_count = 0;
|
||||||
for (auto& r : results) {
|
for (auto& r : results) {
|
||||||
|
@ -25,10 +25,10 @@ void continue_big_task(std::vector<lokimq::job_result<double>> results) {
|
||||||
done.set_value({sum, exc_count});
|
done.set_value({sum, exc_count});
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_big_task(lokimq::LokiMQ& lmq) {
|
void start_big_task(oxenmq::OxenMQ& lmq) {
|
||||||
size_t num_jobs = 32;
|
size_t num_jobs = 32;
|
||||||
|
|
||||||
lokimq::Batch<double /*return type*/> batch;
|
oxenmq::Batch<double /*return type*/> batch;
|
||||||
batch.reserve(num_jobs);
|
batch.reserve(num_jobs);
|
||||||
|
|
||||||
for (size_t i = 0; i < num_jobs; i++)
|
for (size_t i = 0; i < num_jobs; i++)
|
||||||
|
@ -41,7 +41,7 @@ void start_big_task(lokimq::LokiMQ& lmq) {
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("batching many small jobs", "[batch-many]") {
|
TEST_CASE("batching many small jobs", "[batch-many]") {
|
||||||
lokimq::LokiMQ lmq{
|
oxenmq::OxenMQ lmq{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -58,7 +58,7 @@ TEST_CASE("batching many small jobs", "[batch-many]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("batch exception propagation", "[batch-exceptions]") {
|
TEST_CASE("batch exception propagation", "[batch-exceptions]") {
|
||||||
lokimq::LokiMQ lmq{
|
oxenmq::OxenMQ lmq{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -73,7 +73,7 @@ TEST_CASE("batch exception propagation", "[batch-exceptions]") {
|
||||||
using Catch::Matchers::Message;
|
using Catch::Matchers::Message;
|
||||||
|
|
||||||
SECTION( "value return" ) {
|
SECTION( "value return" ) {
|
||||||
lokimq::Batch<int> batch;
|
oxenmq::Batch<int> batch;
|
||||||
for (int i : {1, 2})
|
for (int i : {1, 2})
|
||||||
batch.add_job([i]() { if (i == 1) return 42; throw std::domain_error("bad value " + std::to_string(i)); });
|
batch.add_job([i]() { if (i == 1) return 42; throw std::domain_error("bad value " + std::to_string(i)); });
|
||||||
batch.completion([&done_promise](auto results) {
|
batch.completion([&done_promise](auto results) {
|
||||||
|
@ -88,7 +88,7 @@ TEST_CASE("batch exception propagation", "[batch-exceptions]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "lvalue return" ) {
|
SECTION( "lvalue return" ) {
|
||||||
lokimq::Batch<int&> batch;
|
oxenmq::Batch<int&> batch;
|
||||||
int forty_two = 42;
|
int forty_two = 42;
|
||||||
for (int i : {1, 2})
|
for (int i : {1, 2})
|
||||||
batch.add_job([i,&forty_two]() -> int& {
|
batch.add_job([i,&forty_two]() -> int& {
|
||||||
|
@ -110,7 +110,7 @@ TEST_CASE("batch exception propagation", "[batch-exceptions]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION( "void return" ) {
|
SECTION( "void return" ) {
|
||||||
lokimq::Batch<void> batch;
|
oxenmq::Batch<void> batch;
|
||||||
for (int i : {1, 2})
|
for (int i : {1, 2})
|
||||||
batch.add_job([i]() { if (i != 1) throw std::domain_error("bad value " + std::to_string(i)); });
|
batch.add_job([i]() { if (i != 1) throw std::domain_error("bad value " + std::to_string(i)); });
|
||||||
batch.completion([&done_promise](auto results) {
|
batch.completion([&done_promise](auto results) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "lokimq/bt_serialize.h"
|
#include "oxenmq/bt_serialize.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
@ -129,10 +129,10 @@ TEST_CASE("bt_value deserialization", "[bt][deserialization][bt_value]") {
|
||||||
REQUIRE( var::get<int64_t>(dna2) == -42 );
|
REQUIRE( var::get<int64_t>(dna2) == -42 );
|
||||||
REQUIRE_THROWS( var::get<int64_t>(dna1) );
|
REQUIRE_THROWS( var::get<int64_t>(dna1) );
|
||||||
REQUIRE_THROWS( var::get<uint64_t>(dna2) );
|
REQUIRE_THROWS( var::get<uint64_t>(dna2) );
|
||||||
REQUIRE( lokimq::get_int<int>(dna1) == 42 );
|
REQUIRE( oxenmq::get_int<int>(dna1) == 42 );
|
||||||
REQUIRE( lokimq::get_int<int>(dna2) == -42 );
|
REQUIRE( oxenmq::get_int<int>(dna2) == -42 );
|
||||||
REQUIRE( lokimq::get_int<unsigned>(dna1) == 42 );
|
REQUIRE( oxenmq::get_int<unsigned>(dna1) == 42 );
|
||||||
REQUIRE_THROWS( lokimq::get_int<unsigned>(dna2) );
|
REQUIRE_THROWS( oxenmq::get_int<unsigned>(dna2) );
|
||||||
|
|
||||||
bt_value x = bt_deserialize<bt_value>("d3:barle3:foold1:ali1ei2ei3ee1:bleed1:cli-5ei4eeeee");
|
bt_value x = bt_deserialize<bt_value>("d3:barle3:foold1:ali1ei2ei3ee1:bleed1:cli-5ei4eeeee");
|
||||||
REQUIRE( std::holds_alternative<bt_dict>(x) );
|
REQUIRE( std::holds_alternative<bt_dict>(x) );
|
||||||
|
@ -150,9 +150,9 @@ TEST_CASE("bt_value deserialization", "[bt][deserialization][bt_value]") {
|
||||||
bt_list& foo1b = var::get<bt_list>(foo1.at("b"));
|
bt_list& foo1b = var::get<bt_list>(foo1.at("b"));
|
||||||
bt_list& foo2c = var::get<bt_list>(foo2.at("c"));
|
bt_list& foo2c = var::get<bt_list>(foo2.at("c"));
|
||||||
std::list<int> foo1a_vals, foo1b_vals, foo2c_vals;
|
std::list<int> foo1a_vals, foo1b_vals, foo2c_vals;
|
||||||
for (auto& v : foo1a) foo1a_vals.push_back(lokimq::get_int<int>(v));
|
for (auto& v : foo1a) foo1a_vals.push_back(oxenmq::get_int<int>(v));
|
||||||
for (auto& v : foo1b) foo1b_vals.push_back(lokimq::get_int<int>(v));
|
for (auto& v : foo1b) foo1b_vals.push_back(oxenmq::get_int<int>(v));
|
||||||
for (auto& v : foo2c) foo2c_vals.push_back(lokimq::get_int<int>(v));
|
for (auto& v : foo2c) foo2c_vals.push_back(oxenmq::get_int<int>(v));
|
||||||
REQUIRE( foo1a_vals == std::list{{1,2,3}} );
|
REQUIRE( foo1a_vals == std::list{{1,2,3}} );
|
||||||
REQUIRE( foo1b_vals == std::list<int>{} );
|
REQUIRE( foo1b_vals == std::list<int>{} );
|
||||||
REQUIRE( foo2c_vals == std::list{{-5, 4}} );
|
REQUIRE( foo2c_vals == std::list{{-5, 4}} );
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <lokimq/hex.h>
|
#include <oxenmq/hex.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
using namespace lokimq;
|
using namespace oxenmq;
|
||||||
|
|
||||||
TEST_CASE("basic commands", "[commands]") {
|
TEST_CASE("basic commands", "[commands]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -31,7 +31,7 @@ TEST_CASE("basic commands", "[commands]") {
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
|
|
||||||
client.add_category("public", Access{AuthLevel::none});
|
client.add_category("public", Access{AuthLevel::none});
|
||||||
client.add_command("public", "hi", [&](auto&) { his++; });
|
client.add_command("public", "hi", [&](auto&) { his++; });
|
||||||
|
@ -77,7 +77,7 @@ TEST_CASE("basic commands", "[commands]") {
|
||||||
|
|
||||||
TEST_CASE("outgoing auth level", "[commands][auth]") {
|
TEST_CASE("outgoing auth level", "[commands][auth]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -93,7 +93,7 @@ TEST_CASE("outgoing auth level", "[commands][auth]") {
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
|
|
||||||
std::atomic<int> public_hi{0}, basic_hi{0}, admin_hi{0};
|
std::atomic<int> public_hi{0}, basic_hi{0}, admin_hi{0};
|
||||||
client.add_category("public", Access{AuthLevel::none});
|
client.add_category("public", Access{AuthLevel::none});
|
||||||
|
@ -159,7 +159,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
// original node.
|
// original node.
|
||||||
|
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -178,7 +178,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
m.send_reply("Okay, I'll remember that.");
|
m.send_reply("Okay, I'll remember that.");
|
||||||
|
|
||||||
if (backdoor)
|
if (backdoor)
|
||||||
m.lokimq.send(backdoor, "backdoor.data", m.data[0]);
|
m.oxenmq.send(backdoor, "backdoor.data", m.data[0]);
|
||||||
});
|
});
|
||||||
server.add_command("hey google", "recall", [&](Message& m) {
|
server.add_command("hey google", "recall", [&](Message& m) {
|
||||||
auto l = catch_lock();
|
auto l = catch_lock();
|
||||||
|
@ -199,7 +199,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
|
|
||||||
std::set<std::string> backdoor_details;
|
std::set<std::string> backdoor_details;
|
||||||
|
|
||||||
LokiMQ nsa{get_logger("NSA» ")};
|
OxenMQ nsa{get_logger("NSA» ")};
|
||||||
nsa.add_category("backdoor", Access{AuthLevel::admin});
|
nsa.add_category("backdoor", Access{AuthLevel::admin});
|
||||||
nsa.add_command("backdoor", "data", [&](Message& m) {
|
nsa.add_command("backdoor", "data", [&](Message& m) {
|
||||||
auto l = catch_lock();
|
auto l = catch_lock();
|
||||||
|
@ -215,7 +215,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
REQUIRE( backdoor );
|
REQUIRE( backdoor );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<LokiMQ>> clients;
|
std::vector<std::unique_ptr<OxenMQ>> clients;
|
||||||
std::vector<ConnectionID> conns;
|
std::vector<ConnectionID> conns;
|
||||||
std::map<int, std::set<std::string>> personal_details{
|
std::map<int, std::set<std::string>> personal_details{
|
||||||
{0, {"Loretta"s, "photos"s}},
|
{0, {"Loretta"s, "photos"s}},
|
||||||
|
@ -231,7 +231,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
std::map<int, std::set<std::string>> google_knows;
|
std::map<int, std::set<std::string>> google_knows;
|
||||||
int things_remembered{0};
|
int things_remembered{0};
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
clients.push_back(std::make_unique<LokiMQ>(
|
clients.push_back(std::make_unique<OxenMQ>(
|
||||||
get_logger("C" + std::to_string(i) + "» "), LogLevel::trace
|
get_logger("C" + std::to_string(i) + "» "), LogLevel::trace
|
||||||
));
|
));
|
||||||
auto& c = clients.back();
|
auto& c = clients.back();
|
||||||
|
@ -271,7 +271,7 @@ TEST_CASE("deferred replies on incoming connections", "[commands][hey google]")
|
||||||
|
|
||||||
TEST_CASE("send failure callbacks", "[commands][queue_full]") {
|
TEST_CASE("send failure callbacks", "[commands][queue_full]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -298,7 +298,7 @@ TEST_CASE("send failure callbacks", "[commands][queue_full]") {
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
// Use a raw socket here because I want to stall it by not reading from it at all, and that is
|
// Use a raw socket here because I want to stall it by not reading from it at all, and that is
|
||||||
// hard with LokiMQ.
|
// hard with OxenMQ.
|
||||||
zmq::context_t client_ctx;
|
zmq::context_t client_ctx;
|
||||||
zmq::socket_t client{client_ctx, zmq::socket_type::dealer};
|
zmq::socket_t client{client_ctx, zmq::socket_type::dealer};
|
||||||
client.connect(listen);
|
client.connect(listen);
|
||||||
|
@ -365,7 +365,7 @@ TEST_CASE("send failure callbacks", "[commands][queue_full]") {
|
||||||
|
|
||||||
TEST_CASE("data parts", "[send][data_parts]") {
|
TEST_CASE("data parts", "[send][data_parts]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -385,7 +385,7 @@ TEST_CASE("data parts", "[send][data_parts]") {
|
||||||
});
|
});
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
std::atomic<bool> got{false};
|
std::atomic<bool> got{false};
|
||||||
|
@ -406,7 +406,7 @@ TEST_CASE("data parts", "[send][data_parts]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector some_data{{"abc"s, "def"s, "omg123\0zzz"s}};
|
std::vector some_data{{"abc"s, "def"s, "omg123\0zzz"s}};
|
||||||
client.send(c, "public.hello", lokimq::send_option::data_parts(some_data.begin(), some_data.end()));
|
client.send(c, "public.hello", oxenmq::send_option::data_parts(some_data.begin(), some_data.end()));
|
||||||
reply_sleep();
|
reply_sleep();
|
||||||
{
|
{
|
||||||
auto lock = catch_lock();
|
auto lock = catch_lock();
|
||||||
|
@ -418,10 +418,10 @@ TEST_CASE("data parts", "[send][data_parts]") {
|
||||||
std::vector some_data2{{"a"sv, "b"sv, "\0"sv}};
|
std::vector some_data2{{"a"sv, "b"sv, "\0"sv}};
|
||||||
client.send(c, "public.hello",
|
client.send(c, "public.hello",
|
||||||
"hi",
|
"hi",
|
||||||
lokimq::send_option::data_parts(some_data2.begin(), some_data2.end()),
|
oxenmq::send_option::data_parts(some_data2.begin(), some_data2.end()),
|
||||||
"another",
|
"another",
|
||||||
"string"sv,
|
"string"sv,
|
||||||
lokimq::send_option::data_parts(some_data.begin(), some_data.end()));
|
oxenmq::send_option::data_parts(some_data.begin(), some_data.end()));
|
||||||
|
|
||||||
std::vector<std::string> expected;
|
std::vector<std::string> expected;
|
||||||
expected.push_back("hi");
|
expected.push_back("hi");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <lokimq/hex.h>
|
#include <oxenmq/hex.h>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <sodium.h>
|
#include <sodium.h>
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ extern "C" {
|
||||||
|
|
||||||
TEST_CASE("connections with curve authentication", "[curve][connect]") {
|
TEST_CASE("connections with curve authentication", "[curve][connect]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -20,7 +20,7 @@ TEST_CASE("connections with curve authentication", "[curve][connect]") {
|
||||||
server.add_request_command("public", "hello", [&](Message& m) { m.send_reply("hi"); });
|
server.add_request_command("public", "hello", [&](Message& m) { m.send_reply("hi"); });
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
|
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ TEST_CASE("self-connection SN optimization", "[connect][self]") {
|
||||||
REQUIRE(sodium_init() != -1);
|
REQUIRE(sodium_init() != -1);
|
||||||
auto listen_addr = random_localhost();
|
auto listen_addr = random_localhost();
|
||||||
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
||||||
LokiMQ sn{
|
OxenMQ sn{
|
||||||
pubkey, privkey,
|
pubkey, privkey,
|
||||||
true,
|
true,
|
||||||
[&](auto pk) { if (pk == pubkey) return listen_addr; else return ""s; },
|
[&](auto pk) { if (pk == pubkey) return listen_addr; else return ""s; },
|
||||||
|
@ -92,7 +92,7 @@ TEST_CASE("self-connection SN optimization", "[connect][self]") {
|
||||||
|
|
||||||
TEST_CASE("plain-text connections", "[plaintext][connect]") {
|
TEST_CASE("plain-text connections", "[plaintext][connect]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{get_logger("S» "), LogLevel::trace};
|
OxenMQ server{get_logger("S» "), LogLevel::trace};
|
||||||
|
|
||||||
server.add_category("public", Access{AuthLevel::none});
|
server.add_category("public", Access{AuthLevel::none});
|
||||||
server.add_request_command("public", "hello", [&](Message& m) { m.send_reply("hi"); });
|
server.add_request_command("public", "hello", [&](Message& m) { m.send_reply("hi"); });
|
||||||
|
@ -101,7 +101,7 @@ TEST_CASE("plain-text connections", "[plaintext][connect]") {
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
|
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ TEST_CASE("plain-text connections", "[plaintext][connect]") {
|
||||||
|
|
||||||
TEST_CASE("unique connection IDs", "[connect][id]") {
|
TEST_CASE("unique connection IDs", "[connect][id]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{get_logger("S» "), LogLevel::trace};
|
OxenMQ server{get_logger("S» "), LogLevel::trace};
|
||||||
|
|
||||||
ConnectionID first, second;
|
ConnectionID first, second;
|
||||||
server.add_category("x", Access{AuthLevel::none})
|
server.add_category("x", Access{AuthLevel::none})
|
||||||
|
@ -143,8 +143,8 @@ TEST_CASE("unique connection IDs", "[connect][id]") {
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client1{get_logger("C1» "), LogLevel::trace};
|
OxenMQ client1{get_logger("C1» "), LogLevel::trace};
|
||||||
LokiMQ client2{get_logger("C2» "), LogLevel::trace};
|
OxenMQ client2{get_logger("C2» "), LogLevel::trace};
|
||||||
client1.start();
|
client1.start();
|
||||||
client2.start();
|
client2.start();
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ TEST_CASE("unique connection IDs", "[connect][id]") {
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("SN disconnections", "[connect][disconnect]") {
|
TEST_CASE("SN disconnections", "[connect][disconnect]") {
|
||||||
std::vector<std::unique_ptr<LokiMQ>> lmq;
|
std::vector<std::unique_ptr<OxenMQ>> lmq;
|
||||||
std::vector<std::string> pubkey, privkey;
|
std::vector<std::string> pubkey, privkey;
|
||||||
std::unordered_map<std::string, std::string> conn;
|
std::unordered_map<std::string, std::string> conn;
|
||||||
REQUIRE(sodium_init() != -1);
|
REQUIRE(sodium_init() != -1);
|
||||||
|
@ -200,7 +200,7 @@ TEST_CASE("SN disconnections", "[connect][disconnect]") {
|
||||||
}
|
}
|
||||||
std::atomic<int> his{0};
|
std::atomic<int> his{0};
|
||||||
for (int i = 0; i < pubkey.size(); i++) {
|
for (int i = 0; i < pubkey.size(); i++) {
|
||||||
lmq.push_back(std::make_unique<LokiMQ>(
|
lmq.push_back(std::make_unique<OxenMQ>(
|
||||||
pubkey[i], privkey[i], true,
|
pubkey[i], privkey[i], true,
|
||||||
[conn](auto pk) { auto it = conn.find((std::string) pk); if (it != conn.end()) return it->second; return ""s; },
|
[conn](auto pk) { auto it = conn.find((std::string) pk); if (it != conn.end()) return it->second; return ""s; },
|
||||||
get_logger("S" + std::to_string(i) + "» "),
|
get_logger("S" + std::to_string(i) + "» "),
|
||||||
|
@ -238,7 +238,7 @@ TEST_CASE("SN auth checks", "[sandwich][auth]") {
|
||||||
privkey.resize(crypto_box_SECRETKEYBYTES);
|
privkey.resize(crypto_box_SECRETKEYBYTES);
|
||||||
REQUIRE(sodium_init() != -1);
|
REQUIRE(sodium_init() != -1);
|
||||||
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
crypto_box_keypair(reinterpret_cast<unsigned char*>(&pubkey[0]), reinterpret_cast<unsigned char*>(&privkey[0]));
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
pubkey, privkey,
|
pubkey, privkey,
|
||||||
true, // service node
|
true, // service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -265,7 +265,7 @@ TEST_CASE("SN auth checks", "[sandwich][auth]") {
|
||||||
.add_request_command("make", [&](Message& m) { m.send_reply("okay"); });
|
.add_request_command("make", [&](Message& m) { m.send_reply("okay"); });
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{
|
OxenMQ client{
|
||||||
"", "", false,
|
"", "", false,
|
||||||
[&](auto remote_pk) { if (remote_pk == pubkey) return listen; return ""s; },
|
[&](auto remote_pk) { if (remote_pk == pubkey) return listen; return ""s; },
|
||||||
get_logger("B» "), LogLevel::trace};
|
get_logger("B» "), LogLevel::trace};
|
||||||
|
@ -352,7 +352,7 @@ TEST_CASE("SN single worker test", "[connect][worker]") {
|
||||||
// Tests a failure case that could trigger when all workers are allocated (here we make that
|
// Tests a failure case that could trigger when all workers are allocated (here we make that
|
||||||
// simpler by just having one worker).
|
// simpler by just having one worker).
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "",
|
"", "",
|
||||||
false, // service node
|
false, // service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -368,7 +368,7 @@ TEST_CASE("SN single worker test", "[connect][worker]") {
|
||||||
;
|
;
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("B» "), LogLevel::trace};
|
OxenMQ client{get_logger("B» "), LogLevel::trace};
|
||||||
client.start();
|
client.start();
|
||||||
auto conn = client.connect_remote(listen, [](auto) {}, [](auto, auto) {});
|
auto conn = client.connect_remote(listen, [](auto) {}, [](auto, auto) {});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "lokimq/hex.h"
|
#include "oxenmq/hex.h"
|
||||||
#include "lokimq/base32z.h"
|
#include "oxenmq/base32z.h"
|
||||||
#include "lokimq/base64.h"
|
#include "oxenmq/base64.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
@ -12,123 +12,123 @@ const std::string pk_b32z = "6fi4kseo88aeupbkopyzknjo1odw4dcuxjh6kx1hhhax1tzbjqr
|
||||||
const std::string pk_b64 = "8WulWRA58Im0KoNBdQkwlAdNDZN6eeU+XOcw+UbhS4g=";
|
const std::string pk_b64 = "8WulWRA58Im0KoNBdQkwlAdNDZN6eeU+XOcw+UbhS4g=";
|
||||||
|
|
||||||
TEST_CASE("hex encoding/decoding", "[encoding][decoding][hex]") {
|
TEST_CASE("hex encoding/decoding", "[encoding][decoding][hex]") {
|
||||||
REQUIRE( lokimq::to_hex("\xff\x42\x12\x34") == "ff421234"s );
|
REQUIRE( oxenmq::to_hex("\xff\x42\x12\x34") == "ff421234"s );
|
||||||
std::vector<uint8_t> chars{{1, 10, 100, 254}};
|
std::vector<uint8_t> chars{{1, 10, 100, 254}};
|
||||||
std::array<uint8_t, 8> out;
|
std::array<uint8_t, 8> out;
|
||||||
std::array<uint8_t, 8> expected{{'0', '1', '0', 'a', '6', '4', 'f', 'e'}};
|
std::array<uint8_t, 8> expected{{'0', '1', '0', 'a', '6', '4', 'f', 'e'}};
|
||||||
lokimq::to_hex(chars.begin(), chars.end(), out.begin());
|
oxenmq::to_hex(chars.begin(), chars.end(), out.begin());
|
||||||
REQUIRE( out == expected );
|
REQUIRE( out == expected );
|
||||||
|
|
||||||
REQUIRE( lokimq::to_hex(chars.begin(), chars.end()) == "010a64fe" );
|
REQUIRE( oxenmq::to_hex(chars.begin(), chars.end()) == "010a64fe" );
|
||||||
|
|
||||||
REQUIRE( lokimq::from_hex("12345678ffEDbca9") == "\x12\x34\x56\x78\xff\xed\xbc\xa9"s );
|
REQUIRE( oxenmq::from_hex("12345678ffEDbca9") == "\x12\x34\x56\x78\xff\xed\xbc\xa9"s );
|
||||||
|
|
||||||
REQUIRE( lokimq::is_hex("1234567890abcdefABCDEF1234567890abcdefABCDEF") );
|
REQUIRE( oxenmq::is_hex("1234567890abcdefABCDEF1234567890abcdefABCDEF") );
|
||||||
REQUIRE_FALSE( lokimq::is_hex("1234567890abcdefABCDEF1234567890aGcdefABCDEF") );
|
REQUIRE_FALSE( oxenmq::is_hex("1234567890abcdefABCDEF1234567890aGcdefABCDEF") );
|
||||||
// ^
|
// ^
|
||||||
REQUIRE_FALSE( lokimq::is_hex("1234567890abcdefABCDEF1234567890agcdefABCDEF") );
|
REQUIRE_FALSE( oxenmq::is_hex("1234567890abcdefABCDEF1234567890agcdefABCDEF") );
|
||||||
// ^
|
// ^
|
||||||
REQUIRE_FALSE( lokimq::is_hex("\x11\xff") );
|
REQUIRE_FALSE( oxenmq::is_hex("\x11\xff") );
|
||||||
constexpr auto odd_hex = "1234567890abcdefABCDEF1234567890abcdefABCDE"sv;
|
constexpr auto odd_hex = "1234567890abcdefABCDEF1234567890abcdefABCDE"sv;
|
||||||
REQUIRE_FALSE( lokimq::is_hex(odd_hex) );
|
REQUIRE_FALSE( oxenmq::is_hex(odd_hex) );
|
||||||
REQUIRE_FALSE( lokimq::is_hex("0") );
|
REQUIRE_FALSE( oxenmq::is_hex("0") );
|
||||||
|
|
||||||
REQUIRE( std::all_of(odd_hex.begin(), odd_hex.end(), lokimq::is_hex_digit<char>) );
|
REQUIRE( std::all_of(odd_hex.begin(), odd_hex.end(), oxenmq::is_hex_digit<char>) );
|
||||||
|
|
||||||
REQUIRE( lokimq::from_hex(pk_hex) == pk );
|
REQUIRE( oxenmq::from_hex(pk_hex) == pk );
|
||||||
REQUIRE( lokimq::to_hex(pk) == pk_hex );
|
REQUIRE( oxenmq::to_hex(pk) == pk_hex );
|
||||||
|
|
||||||
REQUIRE( lokimq::from_hex(pk_hex.begin(), pk_hex.end()) == pk );
|
REQUIRE( oxenmq::from_hex(pk_hex.begin(), pk_hex.end()) == pk );
|
||||||
|
|
||||||
std::vector<std::byte> bytes{{std::byte{0xff}, std::byte{0x42}, std::byte{0x12}, std::byte{0x34}}};
|
std::vector<std::byte> bytes{{std::byte{0xff}, std::byte{0x42}, std::byte{0x12}, std::byte{0x34}}};
|
||||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::to_hex(b) == "ff421234"s );
|
REQUIRE( oxenmq::to_hex(b) == "ff421234"s );
|
||||||
|
|
||||||
bytes.resize(8);
|
bytes.resize(8);
|
||||||
bytes[0] = std::byte{'f'}; bytes[1] = std::byte{'f'}; bytes[2] = std::byte{'4'}; bytes[3] = std::byte{'2'};
|
bytes[0] = std::byte{'f'}; bytes[1] = std::byte{'f'}; bytes[2] = std::byte{'4'}; bytes[3] = std::byte{'2'};
|
||||||
bytes[4] = std::byte{'1'}; bytes[5] = std::byte{'2'}; bytes[6] = std::byte{'3'}; bytes[7] = std::byte{'4'};
|
bytes[4] = std::byte{'1'}; bytes[5] = std::byte{'2'}; bytes[6] = std::byte{'3'}; bytes[7] = std::byte{'4'};
|
||||||
std::basic_string_view<std::byte> hex_bytes{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> hex_bytes{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::is_hex(hex_bytes) );
|
REQUIRE( oxenmq::is_hex(hex_bytes) );
|
||||||
REQUIRE( lokimq::from_hex(hex_bytes) == "\xff\x42\x12\x34" );
|
REQUIRE( oxenmq::from_hex(hex_bytes) == "\xff\x42\x12\x34" );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("base32z encoding/decoding", "[encoding][decoding][base32z]") {
|
TEST_CASE("base32z encoding/decoding", "[encoding][decoding][base32z]") {
|
||||||
REQUIRE( lokimq::to_base32z("\0\0\0\0\0"s) == "yyyyyyyy" );
|
REQUIRE( oxenmq::to_base32z("\0\0\0\0\0"s) == "yyyyyyyy" );
|
||||||
REQUIRE( lokimq::to_base32z("\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv)
|
REQUIRE( oxenmq::to_base32z("\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv)
|
||||||
== "yrtwk3hjixg66yjdeiuauk6p7hy1gtm8tgih55abrpnsxnpm3zzo");
|
== "yrtwk3hjixg66yjdeiuauk6p7hy1gtm8tgih55abrpnsxnpm3zzo");
|
||||||
|
|
||||||
REQUIRE( lokimq::from_base32z("yrtwk3hjixg66yjdeiuauk6p7hy1gtm8tgih55abrpnsxnpm3zzo")
|
REQUIRE( oxenmq::from_base32z("yrtwk3hjixg66yjdeiuauk6p7hy1gtm8tgih55abrpnsxnpm3zzo")
|
||||||
== "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv);
|
== "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv);
|
||||||
|
|
||||||
REQUIRE( lokimq::from_base32z("YRTWK3HJIXG66YJDEIUAUK6P7HY1GTM8TGIH55ABRPNSXNPM3ZZO")
|
REQUIRE( oxenmq::from_base32z("YRTWK3HJIXG66YJDEIUAUK6P7HY1GTM8TGIH55ABRPNSXNPM3ZZO")
|
||||||
== "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv);
|
== "\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef\x01\x23\x45\x67\x89\xab\xcd\xef"sv);
|
||||||
|
|
||||||
auto five_nulls = lokimq::from_base32z("yyyyyyyy");
|
auto five_nulls = oxenmq::from_base32z("yyyyyyyy");
|
||||||
REQUIRE( five_nulls.size() == 5 );
|
REQUIRE( five_nulls.size() == 5 );
|
||||||
REQUIRE( five_nulls == "\0\0\0\0\0"s );
|
REQUIRE( five_nulls == "\0\0\0\0\0"s );
|
||||||
|
|
||||||
// 00000 00001 00010 00011 00100 00101 00110 00111
|
// 00000 00001 00010 00011 00100 00101 00110 00111
|
||||||
// ==
|
// ==
|
||||||
// 00000000 01000100 00110010 00010100 11000111
|
// 00000000 01000100 00110010 00010100 11000111
|
||||||
REQUIRE( lokimq::from_base32z("ybndrfg8") == "\x00\x44\x32\x14\xc7"s );
|
REQUIRE( oxenmq::from_base32z("ybndrfg8") == "\x00\x44\x32\x14\xc7"s );
|
||||||
|
|
||||||
// Special case 1: 7 base32z digits with 3 trailing 0 bits -> 4 bytes (the trailing 0s are dropped)
|
// Special case 1: 7 base32z digits with 3 trailing 0 bits -> 4 bytes (the trailing 0s are dropped)
|
||||||
// 00000 00001 00010 00011 00100 00101 11000
|
// 00000 00001 00010 00011 00100 00101 11000
|
||||||
// ==
|
// ==
|
||||||
// 00000000 01000100 00110010 00010111
|
// 00000000 01000100 00110010 00010111
|
||||||
REQUIRE( lokimq::from_base32z("ybndrfa") == "\x00\x44\x32\x17"s );
|
REQUIRE( oxenmq::from_base32z("ybndrfa") == "\x00\x44\x32\x17"s );
|
||||||
|
|
||||||
// Round-trip it:
|
// Round-trip it:
|
||||||
REQUIRE( lokimq::from_base32z(lokimq::to_base32z("\x00\x44\x32\x17"sv)) == "\x00\x44\x32\x17"sv );
|
REQUIRE( oxenmq::from_base32z(oxenmq::to_base32z("\x00\x44\x32\x17"sv)) == "\x00\x44\x32\x17"sv );
|
||||||
REQUIRE( lokimq::to_base32z(lokimq::from_base32z("ybndrfa")) == "ybndrfa" );
|
REQUIRE( oxenmq::to_base32z(oxenmq::from_base32z("ybndrfa")) == "ybndrfa" );
|
||||||
|
|
||||||
// Special case 2: 7 base32z digits with 3 trailing bits 010; we just ignore the trailing stuff,
|
// Special case 2: 7 base32z digits with 3 trailing bits 010; we just ignore the trailing stuff,
|
||||||
// as if it was specified as 0. (The last digit here is 11010 instead of 11000).
|
// as if it was specified as 0. (The last digit here is 11010 instead of 11000).
|
||||||
REQUIRE( lokimq::from_base32z("ybndrf4") == "\x00\x44\x32\x17"s );
|
REQUIRE( oxenmq::from_base32z("ybndrf4") == "\x00\x44\x32\x17"s );
|
||||||
// This one won't round-trip to the same value since it has ignored garbage bytes at the end
|
// This one won't round-trip to the same value since it has ignored garbage bytes at the end
|
||||||
REQUIRE( lokimq::to_base32z(lokimq::from_base32z("ybndrf4"s)) == "ybndrfa" );
|
REQUIRE( oxenmq::to_base32z(oxenmq::from_base32z("ybndrf4"s)) == "ybndrfa" );
|
||||||
|
|
||||||
REQUIRE( lokimq::to_base32z(pk) == pk_b32z );
|
REQUIRE( oxenmq::to_base32z(pk) == pk_b32z );
|
||||||
REQUIRE( lokimq::to_base32z(pk.begin(), pk.end()) == pk_b32z );
|
REQUIRE( oxenmq::to_base32z(pk.begin(), pk.end()) == pk_b32z );
|
||||||
REQUIRE( lokimq::from_base32z(pk_b32z) == pk );
|
REQUIRE( oxenmq::from_base32z(pk_b32z) == pk );
|
||||||
REQUIRE( lokimq::from_base32z(pk_b32z.begin(), pk_b32z.end()) == pk );
|
REQUIRE( oxenmq::from_base32z(pk_b32z.begin(), pk_b32z.end()) == pk );
|
||||||
|
|
||||||
std::string pk_b32z_again, pk_again;
|
std::string pk_b32z_again, pk_again;
|
||||||
lokimq::to_base32z(pk.begin(), pk.end(), std::back_inserter(pk_b32z_again));
|
oxenmq::to_base32z(pk.begin(), pk.end(), std::back_inserter(pk_b32z_again));
|
||||||
lokimq::from_base32z(pk_b32z.begin(), pk_b32z.end(), std::back_inserter(pk_again));
|
oxenmq::from_base32z(pk_b32z.begin(), pk_b32z.end(), std::back_inserter(pk_again));
|
||||||
REQUIRE( pk_b32z_again == pk_b32z );
|
REQUIRE( pk_b32z_again == pk_b32z );
|
||||||
REQUIRE( pk_again == pk );
|
REQUIRE( pk_again == pk );
|
||||||
|
|
||||||
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
||||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::to_base32z(b) == "yd9o" );
|
REQUIRE( oxenmq::to_base32z(b) == "yd9o" );
|
||||||
|
|
||||||
bytes.resize(4);
|
bytes.resize(4);
|
||||||
bytes[0] = std::byte{'y'}; bytes[1] = std::byte{'d'}; bytes[2] = std::byte{'9'}; bytes[3] = std::byte{'o'};
|
bytes[0] = std::byte{'y'}; bytes[1] = std::byte{'d'}; bytes[2] = std::byte{'9'}; bytes[3] = std::byte{'o'};
|
||||||
std::basic_string_view<std::byte> b32_bytes{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> b32_bytes{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::is_base32z(b32_bytes) );
|
REQUIRE( oxenmq::is_base32z(b32_bytes) );
|
||||||
REQUIRE( lokimq::from_base32z(b32_bytes) == "\x00\xff"sv );
|
REQUIRE( oxenmq::from_base32z(b32_bytes) == "\x00\xff"sv );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
||||||
// 00000000 00000000 00000000 -> 000000 000000 000000 000000
|
// 00000000 00000000 00000000 -> 000000 000000 000000 000000
|
||||||
REQUIRE( lokimq::to_base64("\0\0\0"s) == "AAAA" );
|
REQUIRE( oxenmq::to_base64("\0\0\0"s) == "AAAA" );
|
||||||
// 00000001 00000002 00000003 -> 000000 010000 000200 000003
|
// 00000001 00000002 00000003 -> 000000 010000 000200 000003
|
||||||
REQUIRE( lokimq::to_base64("\x01\x02\x03"s) == "AQID" );
|
REQUIRE( oxenmq::to_base64("\x01\x02\x03"s) == "AQID" );
|
||||||
REQUIRE( lokimq::to_base64("\0\0\0\0"s) == "AAAAAA==" );
|
REQUIRE( oxenmq::to_base64("\0\0\0\0"s) == "AAAAAA==" );
|
||||||
// 00000000 00000000 00000000 11111111 ->
|
// 00000000 00000000 00000000 11111111 ->
|
||||||
// 000000 000000 000000 000000 111111 110000 (pad) (pad)
|
// 000000 000000 000000 000000 111111 110000 (pad) (pad)
|
||||||
REQUIRE( lokimq::to_base64("a") == "YQ==" );
|
REQUIRE( oxenmq::to_base64("a") == "YQ==" );
|
||||||
REQUIRE( lokimq::to_base64("ab") == "YWI=" );
|
REQUIRE( oxenmq::to_base64("ab") == "YWI=" );
|
||||||
REQUIRE( lokimq::to_base64("abc") == "YWJj" );
|
REQUIRE( oxenmq::to_base64("abc") == "YWJj" );
|
||||||
REQUIRE( lokimq::to_base64("abcd") == "YWJjZA==" );
|
REQUIRE( oxenmq::to_base64("abcd") == "YWJjZA==" );
|
||||||
REQUIRE( lokimq::to_base64("abcde") == "YWJjZGU=" );
|
REQUIRE( oxenmq::to_base64("abcde") == "YWJjZGU=" );
|
||||||
REQUIRE( lokimq::to_base64("abcdef") == "YWJjZGVm" );
|
REQUIRE( oxenmq::to_base64("abcdef") == "YWJjZGVm" );
|
||||||
|
|
||||||
REQUIRE( lokimq::to_base64("\0\0\0\xff"s) == "AAAA/w==" );
|
REQUIRE( oxenmq::to_base64("\0\0\0\xff"s) == "AAAA/w==" );
|
||||||
REQUIRE( lokimq::to_base64("\0\0\0\xff\xff"s) == "AAAA//8=" );
|
REQUIRE( oxenmq::to_base64("\0\0\0\xff\xff"s) == "AAAA//8=" );
|
||||||
REQUIRE( lokimq::to_base64("\0\0\0\xff\xff\xff"s) == "AAAA////" );
|
REQUIRE( oxenmq::to_base64("\0\0\0\xff\xff\xff"s) == "AAAA////" );
|
||||||
REQUIRE( lokimq::to_base64(
|
REQUIRE( oxenmq::to_base64(
|
||||||
"Man is distinguished, not only by his reason, but by this singular passion from other "
|
"Man is distinguished, not only by his reason, but by this singular passion from other "
|
||||||
"animals, which is a lust of the mind, that by a perseverance of delight in the "
|
"animals, which is a lust of the mind, that by a perseverance of delight in the "
|
||||||
"continued and indefatigable generation of knowledge, exceeds the short vehemence of "
|
"continued and indefatigable generation of knowledge, exceeds the short vehemence of "
|
||||||
|
@ -140,33 +140,33 @@ TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
||||||
"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
|
"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
|
||||||
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" );
|
"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" );
|
||||||
|
|
||||||
REQUIRE( lokimq::from_base64("A+/A") == "\x03\xef\xc0" );
|
REQUIRE( oxenmq::from_base64("A+/A") == "\x03\xef\xc0" );
|
||||||
REQUIRE( lokimq::from_base64("YWJj") == "abc" );
|
REQUIRE( oxenmq::from_base64("YWJj") == "abc" );
|
||||||
REQUIRE( lokimq::from_base64("YWJjZA==") == "abcd" );
|
REQUIRE( oxenmq::from_base64("YWJjZA==") == "abcd" );
|
||||||
REQUIRE( lokimq::from_base64("YWJjZA") == "abcd" );
|
REQUIRE( oxenmq::from_base64("YWJjZA") == "abcd" );
|
||||||
REQUIRE( lokimq::from_base64("YWJjZB") == "abcd" ); // ignore superfluous bits
|
REQUIRE( oxenmq::from_base64("YWJjZB") == "abcd" ); // ignore superfluous bits
|
||||||
REQUIRE( lokimq::from_base64("YWJjZB") == "abcd" ); // ignore superfluous bits
|
REQUIRE( oxenmq::from_base64("YWJjZB") == "abcd" ); // ignore superfluous bits
|
||||||
REQUIRE( lokimq::from_base64("YWJj+") == "abc" ); // ignore superfluous bits
|
REQUIRE( oxenmq::from_base64("YWJj+") == "abc" ); // ignore superfluous bits
|
||||||
REQUIRE( lokimq::from_base64("YWJjZGU=") == "abcde" );
|
REQUIRE( oxenmq::from_base64("YWJjZGU=") == "abcde" );
|
||||||
REQUIRE( lokimq::from_base64("YWJjZGU") == "abcde" );
|
REQUIRE( oxenmq::from_base64("YWJjZGU") == "abcde" );
|
||||||
REQUIRE( lokimq::from_base64("YWJjZGVm") == "abcdef" );
|
REQUIRE( oxenmq::from_base64("YWJjZGVm") == "abcdef" );
|
||||||
|
|
||||||
REQUIRE( lokimq::is_base64("YWJjZGVm") );
|
REQUIRE( oxenmq::is_base64("YWJjZGVm") );
|
||||||
REQUIRE( lokimq::is_base64("YWJjZGU") );
|
REQUIRE( oxenmq::is_base64("YWJjZGU") );
|
||||||
REQUIRE( lokimq::is_base64("YWJjZGU=") );
|
REQUIRE( oxenmq::is_base64("YWJjZGU=") );
|
||||||
REQUIRE( lokimq::is_base64("YWJjZA==") );
|
REQUIRE( oxenmq::is_base64("YWJjZA==") );
|
||||||
REQUIRE( lokimq::is_base64("YWJjZA") );
|
REQUIRE( oxenmq::is_base64("YWJjZA") );
|
||||||
REQUIRE( lokimq::is_base64("YWJjZB") ); // not really valid, but we explicitly accept it
|
REQUIRE( oxenmq::is_base64("YWJjZB") ); // not really valid, but we explicitly accept it
|
||||||
|
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJjZ=") ); // invalid padding (padding can only be 4th or 3rd+4th of a 4-char block)
|
REQUIRE_FALSE( oxenmq::is_base64("YWJjZ=") ); // invalid padding (padding can only be 4th or 3rd+4th of a 4-char block)
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJj=") );
|
REQUIRE_FALSE( oxenmq::is_base64("YWJj=") );
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJj=A") );
|
REQUIRE_FALSE( oxenmq::is_base64("YWJj=A") );
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJjA===") );
|
REQUIRE_FALSE( oxenmq::is_base64("YWJjA===") );
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJ[") );
|
REQUIRE_FALSE( oxenmq::is_base64("YWJ[") );
|
||||||
REQUIRE_FALSE( lokimq::is_base64("YWJ.") );
|
REQUIRE_FALSE( oxenmq::is_base64("YWJ.") );
|
||||||
REQUIRE_FALSE( lokimq::is_base64("_YWJ") );
|
REQUIRE_FALSE( oxenmq::is_base64("_YWJ") );
|
||||||
|
|
||||||
REQUIRE( lokimq::from_base64(
|
REQUIRE( oxenmq::from_base64(
|
||||||
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
|
"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
|
||||||
"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
|
"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
|
||||||
"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
|
"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu"
|
||||||
|
@ -178,26 +178,26 @@ TEST_CASE("base64 encoding/decoding", "[encoding][decoding][base64]") {
|
||||||
"continued and indefatigable generation of knowledge, exceeds the short vehemence of "
|
"continued and indefatigable generation of knowledge, exceeds the short vehemence of "
|
||||||
"any carnal pleasure.");
|
"any carnal pleasure.");
|
||||||
|
|
||||||
REQUIRE( lokimq::to_base64(pk) == pk_b64 );
|
REQUIRE( oxenmq::to_base64(pk) == pk_b64 );
|
||||||
REQUIRE( lokimq::to_base64(pk.begin(), pk.end()) == pk_b64 );
|
REQUIRE( oxenmq::to_base64(pk.begin(), pk.end()) == pk_b64 );
|
||||||
REQUIRE( lokimq::from_base64(pk_b64) == pk );
|
REQUIRE( oxenmq::from_base64(pk_b64) == pk );
|
||||||
REQUIRE( lokimq::from_base64(pk_b64.begin(), pk_b64.end()) == pk );
|
REQUIRE( oxenmq::from_base64(pk_b64.begin(), pk_b64.end()) == pk );
|
||||||
|
|
||||||
std::string pk_b64_again, pk_again;
|
std::string pk_b64_again, pk_again;
|
||||||
lokimq::to_base64(pk.begin(), pk.end(), std::back_inserter(pk_b64_again));
|
oxenmq::to_base64(pk.begin(), pk.end(), std::back_inserter(pk_b64_again));
|
||||||
lokimq::from_base64(pk_b64.begin(), pk_b64.end(), std::back_inserter(pk_again));
|
oxenmq::from_base64(pk_b64.begin(), pk_b64.end(), std::back_inserter(pk_again));
|
||||||
REQUIRE( pk_b64_again == pk_b64 );
|
REQUIRE( pk_b64_again == pk_b64 );
|
||||||
REQUIRE( pk_again == pk );
|
REQUIRE( pk_again == pk );
|
||||||
|
|
||||||
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
std::vector<std::byte> bytes{{std::byte{0}, std::byte{255}}};
|
||||||
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> b{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::to_base64(b) == "AP8=" );
|
REQUIRE( oxenmq::to_base64(b) == "AP8=" );
|
||||||
|
|
||||||
bytes.resize(4);
|
bytes.resize(4);
|
||||||
bytes[0] = std::byte{'/'}; bytes[1] = std::byte{'w'}; bytes[2] = std::byte{'A'}; bytes[3] = std::byte{'='};
|
bytes[0] = std::byte{'/'}; bytes[1] = std::byte{'w'}; bytes[2] = std::byte{'A'}; bytes[3] = std::byte{'='};
|
||||||
std::basic_string_view<std::byte> b64_bytes{bytes.data(), bytes.size()};
|
std::basic_string_view<std::byte> b64_bytes{bytes.data(), bytes.size()};
|
||||||
REQUIRE( lokimq::is_base64(b64_bytes) );
|
REQUIRE( oxenmq::is_base64(b64_bytes) );
|
||||||
REQUIRE( lokimq::from_base64(b64_bytes) == "\xff\x00"sv );
|
REQUIRE( oxenmq::from_base64(b64_bytes) == "\xff\x00"sv );
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("std::byte decoding", "[decoding][hex][base32z][base64]") {
|
TEST_CASE("std::byte decoding", "[decoding][hex][base32z][base64]") {
|
||||||
|
@ -208,33 +208,33 @@ TEST_CASE("std::byte decoding", "[decoding][hex][base32z][base64]") {
|
||||||
// hex
|
// hex
|
||||||
auto b_in = "ff42"s;
|
auto b_in = "ff42"s;
|
||||||
std::vector<std::byte> b_out;
|
std::vector<std::byte> b_out;
|
||||||
lokimq::from_hex(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
oxenmq::from_hex(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}} );
|
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}} );
|
||||||
b_out.emplace_back();
|
b_out.emplace_back();
|
||||||
lokimq::from_hex(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
oxenmq::from_hex(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0xff}, std::byte{0x42}} );
|
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0xff}, std::byte{0x42}} );
|
||||||
lokimq::from_hex(b_in.begin(), b_in.end(), b_out.data());
|
oxenmq::from_hex(b_in.begin(), b_in.end(), b_out.data());
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}, std::byte{0x42}} );
|
REQUIRE( b_out == std::vector{std::byte{0xff}, std::byte{0x42}, std::byte{0x42}} );
|
||||||
|
|
||||||
// base32z
|
// base32z
|
||||||
b_in = "yojky"s;
|
b_in = "yojky"s;
|
||||||
b_out.clear();
|
b_out.clear();
|
||||||
lokimq::from_base32z(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
oxenmq::from_base32z(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
||||||
b_out.emplace_back();
|
b_out.emplace_back();
|
||||||
lokimq::from_base32z(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
oxenmq::from_base32z(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}} );
|
||||||
lokimq::from_base32z(b_in.begin(), b_in.end(), b_out.data());
|
oxenmq::from_base32z(b_in.begin(), b_in.end(), b_out.data());
|
||||||
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}, std::byte{0xa0}} );
|
REQUIRE( b_out == std::vector{std::byte{0x04}, std::byte{0x12}, std::byte{0xa0}, std::byte{0xa0}} );
|
||||||
|
|
||||||
// base64
|
// base64
|
||||||
b_in = "yojk"s;
|
b_in = "yojk"s;
|
||||||
b_out.clear();
|
b_out.clear();
|
||||||
lokimq::from_base64(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
oxenmq::from_base64(b_in.begin(), b_in.end(), std::back_inserter(b_out));
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
||||||
b_out.emplace_back();
|
b_out.emplace_back();
|
||||||
lokimq::from_base64(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
oxenmq::from_base64(b_in.begin(), b_in.end(), b_out.begin() + 1);
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}} );
|
||||||
lokimq::from_base64(b_in.begin(), b_in.end(), b_out.data());
|
oxenmq::from_base64(b_in.begin(), b_in.end(), b_out.data());
|
||||||
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}, std::byte{0xe4}} );
|
REQUIRE( b_out == std::vector{std::byte{0xca}, std::byte{0x88}, std::byte{0xe4}, std::byte{0xe4}} );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <lokimq/hex.h>
|
#include <oxenmq/hex.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
using namespace lokimq;
|
using namespace oxenmq;
|
||||||
|
|
||||||
TEST_CASE("failure responses - UNKNOWNCOMMAND", "[failure][UNKNOWNCOMMAND]") {
|
TEST_CASE("failure responses - UNKNOWNCOMMAND", "[failure][UNKNOWNCOMMAND]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -48,7 +48,7 @@ TEST_CASE("failure responses - UNKNOWNCOMMAND", "[failure][UNKNOWNCOMMAND]") {
|
||||||
|
|
||||||
TEST_CASE("failure responses - NO_REPLY_TAG", "[failure][NO_REPLY_TAG]") {
|
TEST_CASE("failure responses - NO_REPLY_TAG", "[failure][NO_REPLY_TAG]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -109,7 +109,7 @@ TEST_CASE("failure responses - NO_REPLY_TAG", "[failure][NO_REPLY_TAG]") {
|
||||||
|
|
||||||
TEST_CASE("failure responses - FORBIDDEN", "[failure][FORBIDDEN]") {
|
TEST_CASE("failure responses - FORBIDDEN", "[failure][FORBIDDEN]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -192,7 +192,7 @@ TEST_CASE("failure responses - FORBIDDEN", "[failure][FORBIDDEN]") {
|
||||||
|
|
||||||
TEST_CASE("failure responses - NOT_A_SERVICE_NODE", "[failure][NOT_A_SERVICE_NODE]") {
|
TEST_CASE("failure responses - NOT_A_SERVICE_NODE", "[failure][NOT_A_SERVICE_NODE]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -259,7 +259,7 @@ TEST_CASE("failure responses - NOT_A_SERVICE_NODE", "[failure][NOT_A_SERVICE_NOD
|
||||||
|
|
||||||
TEST_CASE("failure responses - FORBIDDEN_SN", "[failure][FORBIDDEN_SN]") {
|
TEST_CASE("failure responses - FORBIDDEN_SN", "[failure][FORBIDDEN_SN]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
using namespace lokimq;
|
using namespace oxenmq;
|
||||||
|
|
||||||
TEST_CASE("injected external commands", "[injected]") {
|
TEST_CASE("injected external commands", "[injected]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -24,17 +24,26 @@ TEST_CASE("injected external commands", "[injected]") {
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client{get_logger("C» "), LogLevel::trace};
|
OxenMQ client{get_logger("C» "), LogLevel::trace};
|
||||||
client.start();
|
client.start();
|
||||||
|
|
||||||
std::atomic<bool> got{false};
|
std::atomic<bool> got{false};
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
// Deliberately using a deprecated command here, disable -Wdeprecated-declarations
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||||
|
#endif
|
||||||
auto c = client.connect_remote(listen,
|
auto c = client.connect_remote(listen,
|
||||||
[&](auto conn) { success = true; got = true; },
|
[&](auto conn) { success = true; got = true; },
|
||||||
[&](auto conn, std::string_view) { got = true; },
|
[&](auto conn, std::string_view) { got = true; },
|
||||||
server.get_pubkey());
|
server.get_pubkey());
|
||||||
|
|
||||||
|
#ifdef __GNUG__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
wait_for_conn(got);
|
wait_for_conn(got);
|
||||||
{
|
{
|
||||||
auto lock = catch_lock();
|
auto lock = catch_lock();
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <lokimq/hex.h>
|
#include <oxenmq/hex.h>
|
||||||
|
|
||||||
using namespace lokimq;
|
using namespace oxenmq;
|
||||||
|
|
||||||
TEST_CASE("basic requests", "[requests]") {
|
TEST_CASE("basic requests", "[requests]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -20,7 +20,7 @@ TEST_CASE("basic requests", "[requests]") {
|
||||||
});
|
});
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client(
|
OxenMQ client(
|
||||||
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
||||||
);
|
);
|
||||||
//client.log_level(LogLevel::trace);
|
//client.log_level(LogLevel::trace);
|
||||||
|
@ -62,7 +62,7 @@ TEST_CASE("basic requests", "[requests]") {
|
||||||
|
|
||||||
TEST_CASE("request from server to client", "[requests]") {
|
TEST_CASE("request from server to client", "[requests]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -77,7 +77,7 @@ TEST_CASE("request from server to client", "[requests]") {
|
||||||
});
|
});
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client(
|
OxenMQ client(
|
||||||
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
||||||
);
|
);
|
||||||
//client.log_level(LogLevel::trace);
|
//client.log_level(LogLevel::trace);
|
||||||
|
@ -125,7 +125,7 @@ TEST_CASE("request from server to client", "[requests]") {
|
||||||
|
|
||||||
TEST_CASE("request timeouts", "[requests][timeout]") {
|
TEST_CASE("request timeouts", "[requests][timeout]") {
|
||||||
std::string listen = random_localhost();
|
std::string listen = random_localhost();
|
||||||
LokiMQ server{
|
OxenMQ server{
|
||||||
"", "", // generate ephemeral keys
|
"", "", // generate ephemeral keys
|
||||||
false, // not a service node
|
false, // not a service node
|
||||||
[](auto) { return ""; },
|
[](auto) { return ""; },
|
||||||
|
@ -138,7 +138,7 @@ TEST_CASE("request timeouts", "[requests][timeout]") {
|
||||||
server.add_request_command("public", "blackhole", [&](Message& m) { /* doesn't reply */ });
|
server.add_request_command("public", "blackhole", [&](Message& m) { /* doesn't reply */ });
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
LokiMQ client(
|
OxenMQ client(
|
||||||
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
[](LogLevel, const char* file, int line, std::string msg) { std::cerr << file << ":" << line << " --C-- " << msg << "\n"; }
|
||||||
);
|
);
|
||||||
//client.log_level(LogLevel::trace);
|
//client.log_level(LogLevel::trace);
|
||||||
|
@ -167,7 +167,7 @@ TEST_CASE("request timeouts", "[requests][timeout]") {
|
||||||
success = ok;
|
success = ok;
|
||||||
data = std::move(data_);
|
data = std::move(data_);
|
||||||
},
|
},
|
||||||
lokimq::send_option::request_timeout{10ms}
|
oxenmq::send_option::request_timeout{10ms}
|
||||||
);
|
);
|
||||||
|
|
||||||
std::atomic<bool> got_triggered2{false};
|
std::atomic<bool> got_triggered2{false};
|
||||||
|
@ -176,7 +176,7 @@ TEST_CASE("request timeouts", "[requests][timeout]") {
|
||||||
success = ok;
|
success = ok;
|
||||||
data = std::move(data_);
|
data = std::move(data_);
|
||||||
},
|
},
|
||||||
lokimq::send_option::request_timeout{200ms}
|
oxenmq::send_option::request_timeout{200ms}
|
||||||
);
|
);
|
||||||
|
|
||||||
std::this_thread::sleep_for(100ms);
|
std::this_thread::sleep_for(100ms);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include "lokimq/batch.h"
|
#include "oxenmq/batch.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include <future>
|
#include <future>
|
||||||
|
|
||||||
TEST_CASE("tagged thread start functions", "[tagged][start]") {
|
TEST_CASE("tagged thread start functions", "[tagged][start]") {
|
||||||
lokimq::LokiMQ lmq{get_logger(""), LogLevel::trace};
|
oxenmq::OxenMQ lmq{get_logger(""), LogLevel::trace};
|
||||||
|
|
||||||
lmq.set_general_threads(2);
|
lmq.set_general_threads(2);
|
||||||
lmq.set_batch_threads(2);
|
lmq.set_batch_threads(2);
|
||||||
|
@ -26,13 +26,13 @@ TEST_CASE("tagged thread start functions", "[tagged][start]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("tagged threads quit-before-start", "[tagged][quit]") {
|
TEST_CASE("tagged threads quit-before-start", "[tagged][quit]") {
|
||||||
auto lmq = std::make_unique<lokimq::LokiMQ>(get_logger(""), LogLevel::trace);
|
auto lmq = std::make_unique<oxenmq::OxenMQ>(get_logger(""), LogLevel::trace);
|
||||||
auto t_abc = lmq->add_tagged_thread("abc");
|
auto t_abc = lmq->add_tagged_thread("abc");
|
||||||
REQUIRE_NOTHROW(lmq.reset());
|
REQUIRE_NOTHROW(lmq.reset());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("batch jobs to tagged threads", "[tagged][batch]") {
|
TEST_CASE("batch jobs to tagged threads", "[tagged][batch]") {
|
||||||
lokimq::LokiMQ lmq{get_logger(""), LogLevel::trace};
|
oxenmq::OxenMQ lmq{get_logger(""), LogLevel::trace};
|
||||||
|
|
||||||
lmq.set_general_threads(2);
|
lmq.set_general_threads(2);
|
||||||
lmq.set_batch_threads(2);
|
lmq.set_batch_threads(2);
|
||||||
|
@ -111,7 +111,7 @@ TEST_CASE("batch jobs to tagged threads", "[tagged][batch]") {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("batch job completion on tagged threads", "[tagged][batch-completion]") {
|
TEST_CASE("batch job completion on tagged threads", "[tagged][batch-completion]") {
|
||||||
lokimq::LokiMQ lmq{get_logger(""), LogLevel::trace};
|
oxenmq::OxenMQ lmq{get_logger(""), LogLevel::trace};
|
||||||
|
|
||||||
lmq.set_general_threads(4);
|
lmq.set_general_threads(4);
|
||||||
lmq.set_batch_threads(4);
|
lmq.set_batch_threads(4);
|
||||||
|
@ -119,7 +119,7 @@ TEST_CASE("batch job completion on tagged threads", "[tagged][batch-completion]"
|
||||||
auto t_abc = lmq.add_tagged_thread("abc", [&] { id_abc = std::this_thread::get_id(); });
|
auto t_abc = lmq.add_tagged_thread("abc", [&] { id_abc = std::this_thread::get_id(); });
|
||||||
lmq.start();
|
lmq.start();
|
||||||
|
|
||||||
lokimq::Batch<int> batch;
|
oxenmq::Batch<int> batch;
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
batch.add_job([i, &id_abc]() { if (std::this_thread::get_id() == id_abc) return 0; return i; });
|
batch.add_job([i, &id_abc]() { if (std::this_thread::get_id() == id_abc) return 0; return i; });
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ TEST_CASE("batch job completion on tagged threads", "[tagged][batch-completion]"
|
||||||
|
|
||||||
|
|
||||||
TEST_CASE("timer job completion on tagged threads", "[tagged][timer]") {
|
TEST_CASE("timer job completion on tagged threads", "[tagged][timer]") {
|
||||||
lokimq::LokiMQ lmq{get_logger(""), LogLevel::trace};
|
oxenmq::OxenMQ lmq{get_logger(""), LogLevel::trace};
|
||||||
|
|
||||||
lmq.set_general_threads(4);
|
lmq.set_general_threads(4);
|
||||||
lmq.set_batch_threads(4);
|
lmq.set_batch_threads(4);
|
||||||
|
|
Loading…
Reference in New Issue