aboutsummaryrefslogtreecommitdiff
path: root/net/nginx-util/src
diff options
context:
space:
mode:
authorPeter Stadler <peter.stadler@student.uibk.ac.at>2020-05-26 16:21:10 +0200
committerPeter Stadler <peter.stadler@student.uibk.ac.at>2020-05-26 18:36:03 +0200
commit2d359a45566ea02792d3f63d7fe4ec1bdb1de2ae (patch)
treedfafc29439d2569fef9a6c5771ace2c76db19659 /net/nginx-util/src
parent5e6b871e9ee1c10337d02f6049bfe780f381e25a (diff)
nginx-util: fix issues and cleanup
* fix regex capture (to conform std) * fix issues for Clang/libcxx (warnings/includes) * fix CONFLICTS in the Makefile * use /bin/sh in host scripts and shellcheck them * add callback for setting arguments in ubus::call Signed-off-by: Peter Stadler <peter.stadler@student.uibk.ac.at>
Diffstat (limited to 'net/nginx-util/src')
-rw-r--r--net/nginx-util/src/CMakeLists.txt19
-rw-r--r--net/nginx-util/src/nginx-ssl-util.hpp22
-rw-r--r--net/nginx-util/src/nginx-util.cpp4
-rw-r--r--net/nginx-util/src/nginx-util.hpp37
-rw-r--r--net/nginx-util/src/px5g-openssl.hpp76
-rw-r--r--net/nginx-util/src/px5g.cpp14
-rw-r--r--net/nginx-util/src/regex-pcre.hpp44
-rw-r--r--net/nginx-util/src/test-nginx-util-root.sh73
-rwxr-xr-xnet/nginx-util/src/test-nginx-util.sh36
-rwxr-xr-xnet/nginx-util/src/test-px5g.sh12
-rw-r--r--net/nginx-util/src/ubus-cxx.cpp148
-rw-r--r--net/nginx-util/src/ubus-cxx.hpp196
12 files changed, 404 insertions, 277 deletions
diff --git a/net/nginx-util/src/CMakeLists.txt b/net/nginx-util/src/CMakeLists.txt
index af1d67ea1..3b06c8537 100644
--- a/net/nginx-util/src/CMakeLists.txt
+++ b/net/nginx-util/src/CMakeLists.txt
@@ -5,15 +5,8 @@ SET(CMAKE_CXX_STANDARD 17)
INCLUDE(CheckFunctionExists)
-IF(UBUS)
-FIND_PATH(ubus_include_dir libubus.h)
-FIND_LIBRARY(ubox NAMES ubox)
-FIND_LIBRARY(ubus NAMES ubus)
-INCLUDE_DIRECTORIES(${ubus_include_dir})
-ENDIF()
-
ADD_DEFINITIONS(-Os -Wall -Werror -Wextra -g3)
-ADD_DEFINITIONS(-Wno-unused-parameter -Wmissing-declarations)
+ADD_DEFINITIONS(-Wno-unused-parameter -Wmissing-declarations -Wshadow)
SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
@@ -22,6 +15,14 @@ IF(UBUS)
ADD_COMPILE_DEFINITIONS(VERSION=${VERSION})
+FIND_PATH(ubus_include_dir libubus.h)
+FIND_LIBRARY(ubus NAMES ubus)
+INCLUDE_DIRECTORIES(${ubus_include_dir})
+
+FIND_PATH(ubox_include_dir libubox/blobmsg.h)
+FIND_LIBRARY(ubox NAMES ubox)
+INCLUDE_DIRECTORIES(${ubox_include_dir})
+
ADD_EXECUTABLE(nginx-util nginx-util.cpp)
TARGET_COMPILE_DEFINITIONS(nginx-util PUBLIC -DNO_SSL)
TARGET_LINK_LIBRARIES(nginx-util ${ubox} ${ubus} pthread)
@@ -38,6 +39,8 @@ INSTALL(TARGETS nginx-ssl-util-nopcre RUNTIME DESTINATION bin)
ELSE()
+ADD_COMPILE_DEFINITIONS(VERSION=0)
+
CONFIGURE_FILE(test-px5g.sh test-px5g.sh COPYONLY)
CONFIGURE_FILE(test-nginx-util.sh test-nginx-util.sh COPYONLY)
CONFIGURE_FILE(test-nginx-util-root.sh test-nginx-util-root.sh COPYONLY)
diff --git a/net/nginx-util/src/nginx-ssl-util.hpp b/net/nginx-util/src/nginx-ssl-util.hpp
index 0fa7009cc..895f9569f 100644
--- a/net/nginx-util/src/nginx-ssl-util.hpp
+++ b/net/nginx-util/src/nginx-ssl-util.hpp
@@ -1,8 +1,6 @@
#ifndef __NGINX_SSL_UTIL_HPP
#define __NGINX_SSL_UTIL_HPP
-#include <thread>
-
#ifdef NO_PCRE
#include <regex>
namespace rgx = std;
@@ -147,7 +145,7 @@ constexpr auto _end = _Line{
template<char clim='\0'>
-constexpr auto _capture = _Line{
+static constexpr auto _capture = _Line{
[](const std::string & param, const std::string & /*begin*/) -> std::string
{ return '\'' + param + '\''; },
@@ -211,8 +209,8 @@ constexpr std::string_view _ssl_session_timeout = "ssl_session_timeout";
// * Use constexpr---not available for strings or char * for now---look at lib.
static const auto CRON_CMD = Line::build
- < _space, _escape<NGINX_UTIL>, _space, _escape<ADD_SSL_FCT,'\''>, _space,
- _capture<>, _newline >();
+ <_space, _escape<NGINX_UTIL>, _space, _escape<ADD_SSL_FCT,'\''>, _space,
+ _capture<>, _newline>();
static const auto NGX_SERVER_NAME =
Line::build<_begin, _escape<_server_name>, _space, _capture<';'>, _end>();
@@ -221,15 +219,15 @@ static const auto NGX_INCLUDE_LAN_LISTEN = Line::build
<_begin, _escape<_include>, _space, _escape<LAN_LISTEN,'\''>, _end>();
static const auto NGX_INCLUDE_LAN_LISTEN_DEFAULT = Line::build
- < _begin, _escape<_include>, _space,
- _escape<LAN_LISTEN_DEFAULT, '\''>, _end >();
+ <_begin, _escape<_include>, _space,
+ _escape<LAN_LISTEN_DEFAULT, '\''>, _end>();
static const auto NGX_INCLUDE_LAN_SSL_LISTEN = Line::build
<_begin, _escape<_include>, _space, _escape<LAN_SSL_LISTEN, '\''>, _end>();
static const auto NGX_INCLUDE_LAN_SSL_LISTEN_DEFAULT = Line::build
- < _begin, _escape<_include>, _space,
- _escape<LAN_SSL_LISTEN_DEFAULT, '\''>, _end >();
+ <_begin, _escape<_include>, _space,
+ _escape<LAN_SSL_LISTEN_DEFAULT, '\''>, _end>();
static const auto NGX_SSL_CRT = Line::build
<_begin, _escape<_ssl_certificate>, _space, _capture<';'>, _end>();
@@ -346,7 +344,7 @@ void add_ssl_directives_to(const std::string & name, const bool isdefault)
auto errmsg = std::string{"add_ssl_directives_to error: "};
errmsg += "cannot add SSL directives to " + name + ".conf, missing: ";
errmsg += NGX_SERVER_NAME.STR(name, "\n ") + "\n";
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
@@ -476,7 +474,7 @@ void use_cron_to_recreate_certificate(const std::string & name)
std::string errmsg{"use_cron_to_recreate_certificate error: "};
errmsg += "Cron unavailable to re-create the ssl certificate for ";
errmsg += name + "\n";
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
} // else active with or without instances:
#endif
@@ -586,7 +584,7 @@ void del_ssl_directives_from(const std::string & name, const bool isdefault)
auto errmsg = std::string{"del_ssl_directives_from error: "};
errmsg += "cannot delete SSL directives from " + name + ".conf, missing: ";
errmsg += NGX_SERVER_NAME.STR(name, "\n ") + "\n";
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
diff --git a/net/nginx-util/src/nginx-util.cpp b/net/nginx-util/src/nginx-util.cpp
index 02aa7013a..b0a724da6 100644
--- a/net/nginx-util/src/nginx-util.cpp
+++ b/net/nginx-util/src/nginx-util.cpp
@@ -1,3 +1,5 @@
+#include <iostream>
+
#include "nginx-util.hpp"
#ifndef NO_SSL
@@ -121,7 +123,7 @@ void get_env()
auto main(int argc, char * argv[]) -> int
{
// TODO(pst): use std::span when available:
- auto args = std::basic_string_view{argv, static_cast<size_t>(argc)};
+ auto args = std::basic_string_view<char *>{argv, static_cast<size_t>(argc)};
auto cmds = std::array{
std::array<std::string_view, 2>{"init_lan", ""},
diff --git a/net/nginx-util/src/nginx-util.hpp b/net/nginx-util/src/nginx-util.hpp
index f3f14ffad..f4999e74f 100644
--- a/net/nginx-util/src/nginx-util.hpp
+++ b/net/nginx-util/src/nginx-util.hpp
@@ -4,12 +4,14 @@
#include <array>
#include <cerrno>
#include <cstdio>
+#include <cstdlib>
#include <cstring>
#include <fstream>
-#include <iostream>
#include <string>
#include <string_view>
+#include <thread>
#include <unistd.h>
+#include <vector>
#ifndef NO_UBUS
#include "ubus-cxx.hpp"
@@ -61,15 +63,34 @@ void get_env();
void write_file(const std::string_view & name, const std::string & str,
const std::ios_base::openmode flag)
{
- std::ofstream file(name.data(), flag);
- if (!file.good()) {
- throw std::ofstream::failure(
- "write_file error: cannot open " + std::string{name});
+ auto tmp = std::string{name};
+
+ if ( (flag & std::ios::ate) == 0 && (flag & std::ios::app) == 0 ) {
+ tmp += ".tmp-XXXXXX";
+ auto fd = mkstemp(&tmp[0]);
+ if (fd==-1 || close(fd)!=0)
+ { throw std::runtime_error("write_file error: cannot access " + tmp); }
}
- file<<str<<std::flush;
+ try {
+ std::ofstream file(tmp.data(), flag);
+ if (!file.good()) {
+ throw std::ofstream::failure
+ ("write_file error: cannot open " + std::string{tmp});
+ }
- file.close();
+ file<<str<<std::flush;
+
+ file.close();
+ } catch(...) {
+ if (tmp!=name) { remove(tmp.c_str()); } //remove can fail.
+ throw;
+ }
+
+ if (rename(tmp.c_str(), name.data()) != 0) {
+ throw std::runtime_error
+ ("write_file error: cannot move " + tmp + " to " + name.data());
+ }
}
@@ -113,7 +134,7 @@ auto call(const char * program, S... args) -> pid_t
std::string errmsg = "call error: cannot fork (";
errmsg += std::to_string(errno) + "): " + std::strerror(errno);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
diff --git a/net/nginx-util/src/px5g-openssl.hpp b/net/nginx-util/src/px5g-openssl.hpp
index 380eba335..1b70dc5b0 100644
--- a/net/nginx-util/src/px5g-openssl.hpp
+++ b/net/nginx-util/src/px5g-openssl.hpp
@@ -8,9 +8,11 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
+#include <stdexcept>
#include <string>
#include <unistd.h>
+
static constexpr auto rsa_min_modulus_bits = 512;
using EVP_PKEY_ptr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
@@ -52,11 +54,20 @@ inline auto print_error(const char * str, const size_t /*len*/, void * errmsg)
}
+// wrapper for clang-tidy:
+inline auto _BIO_new_fp(FILE * stream, const bool use_pem,
+ const bool close=false) -> BIO *
+{
+ return BIO_new_fp( stream, //NOLINTNEXTLINE(hicpp-signed-bitwise) macros:
+ (use_pem ? BIO_FP_TEXT : 0) | (close ? BIO_CLOSE : BIO_NOCLOSE) );
+}
+
+
auto checkend(const std::string & crtpath,
const time_t seconds, const bool use_pem) -> bool
{
BIO * bio = crtpath.empty() ?
- BIO_new_fp(stdin, BIO_NOCLOSE | (use_pem ? BIO_FP_TEXT : 0)) :
+ _BIO_new_fp(stdin, use_pem) :
BIO_new_file(crtpath.c_str(), (use_pem ? "r" : "rb"));
X509 * x509 = nullptr;
@@ -71,7 +82,7 @@ auto checkend(const std::string & crtpath,
if (x509==nullptr) {
std::string errmsg{"checkend error: unable to load certificate\n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
time_t checktime = time(nullptr) + seconds;
@@ -91,7 +102,7 @@ auto gen_eckey(const int curve) -> EVP_PKEY_ptr
std::string errmsg{"gen_eckey error: cannot build group for curve id "};
errmsg += std::to_string(curve) + "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
@@ -115,18 +126,18 @@ auto gen_eckey(const int curve) -> EVP_PKEY_ptr
std::string errmsg{"gen_eckey error: cannot build key with curve id "};
errmsg += std::to_string(curve) + "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
EVP_PKEY_ptr pkey{EVP_PKEY_new(), ::EVP_PKEY_free};
- auto tmp = static_cast<char *>(static_cast<void *>(eckey));
-
- if (!EVP_PKEY_assign_EC_KEY(pkey.get(), tmp)) {
+ // EVP_PKEY_assign_EC_KEY is a macro casting eckey to char *:
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
+ if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey)) {
EC_KEY_free(eckey);
std::string errmsg{"gen_eckey error: cannot assign EC key to EVP\n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
return pkey;
@@ -139,14 +150,14 @@ auto gen_rsakey(const int keysize, const BN_ULONG exponent) -> EVP_PKEY_ptr
std::string errmsg{"gen_rsakey error: RSA keysize ("};
errmsg += std::to_string(keysize) + ") out of range [512..";
errmsg += std::to_string(OPENSSL_RSA_MAX_MODULUS_BITS) + "]";
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
auto bignum = BN_new();
if (bignum == nullptr) {
std::string errmsg{"gen_rsakey error: cannot get big number struct\n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
auto rsa = RSA_new();
@@ -167,18 +178,18 @@ auto gen_rsakey(const int keysize, const BN_ULONG exponent) -> EVP_PKEY_ptr
errmsg += std::to_string(keysize) + " and exponent ";
errmsg += std::to_string(exponent) + "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
EVP_PKEY_ptr pkey{EVP_PKEY_new(), ::EVP_PKEY_free};
- auto tmp = static_cast<char *>(static_cast<void *>(rsa));
-
- if (!EVP_PKEY_assign_RSA(pkey.get(), tmp)) {
+ // EVP_PKEY_assign_RSA is a macro casting rsa to char *:
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
+ if (!EVP_PKEY_assign_RSA(pkey.get(), rsa)) {
RSA_free(rsa);
std::string errmsg{"gen_rsakey error: cannot assign RSA key to EVP\n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
return pkey;
@@ -190,20 +201,21 @@ void write_key(const EVP_PKEY_ptr & pkey,
{
BIO * bio = nullptr;
- if (keypath.empty()) {
- bio = BIO_new_fp( stdout, BIO_NOCLOSE | (use_pem ? BIO_FP_TEXT : 0) );
+ if (keypath.empty()) { bio = _BIO_new_fp(stdout, use_pem); }
- } else { // BIO_new_file(keypath.c_str(), (use_pem ? "w" : "wb") );
+ else { // BIO_new_file(keypath.c_str(), (use_pem ? "w" : "wb") );
static constexpr auto mask = 0600;
// auto fd = open(keypath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, mask);
+ // creat has no cloexec, alt. triggers cppcoreguidelines-pro-type-vararg
+ //NOLINTNEXTLINE(android-cloexec-creat)
auto fd = creat(keypath.c_str(), mask); // the same without va_args.
if (fd >= 0) {
auto fp = fdopen(fd, (use_pem ? "w" : "wb") );
if (fp != nullptr) {
- bio = BIO_new_fp(fp, BIO_CLOSE | (use_pem ? BIO_FP_TEXT : 0));
+ bio = _BIO_new_fp(fp, use_pem, true);
if (bio == nullptr) { fclose(fp); } // (fp owns fd)
}
else { close(fd); }
@@ -216,7 +228,7 @@ void write_key(const EVP_PKEY_ptr & pkey,
errmsg += keypath.empty() ? "stdout" : keypath;
errmsg += "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
int len = 0;
@@ -249,7 +261,7 @@ void write_key(const EVP_PKEY_ptr & pkey,
errmsg += keypath.empty() ? "stdout" : keypath;
errmsg += "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
}
@@ -265,7 +277,7 @@ auto subject2name(const std::string & subject) -> X509_NAME_ptr
if (!name) {
std::string errmsg{"subject2name error: cannot create X509 name \n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
if (subject.empty()) { return name; }
@@ -287,19 +299,21 @@ auto subject2name(const std::string & subject) -> X509_NAME_ptr
if (nid == NID_undef) {
// skip unknown entries (silently?).
} else {
- auto val = static_cast<const unsigned char *>(
- static_cast<const void *>(&subject[prev]) );
+ auto val = // X509_NAME_add_entry_by_NID wants it unsigned:
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+ reinterpret_cast<const unsigned char *>(&subject[prev]);
auto len = i - prev;
- if ( X509_NAME_add_entry_by_NID(name.get(), nid, MBSTRING_ASC,
- val, len, -1, 0)
+ if ( X509_NAME_add_entry_by_NID(name.get(), nid,
+ MBSTRING_ASC, //NOLINT(hicpp-signed-bitwise) is macro
+ val, len, -1, 0)
== 0 )
{
std::string errmsg{"subject2name error: cannot add "};
errmsg += "/" + type +"="+ subject.substr(prev, len) +"\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
}
chr = '=';
@@ -320,7 +334,7 @@ void selfsigned(const EVP_PKEY_ptr & pkey, const int days,
if (x509 == nullptr) {
std::string errmsg{"selfsigned error: cannot create X509 structure\n"};
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
auto freeX509_and_throw = [&x509](const std::string & what)
@@ -329,7 +343,7 @@ void selfsigned(const EVP_PKEY_ptr & pkey, const int days,
std::string errmsg{"selfsigned error: cannot set "};
errmsg += what + " in X509 certificate\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
};
if (X509_set_version(x509, 2) == 0) { freeX509_and_throw("version"); }
@@ -380,7 +394,7 @@ void selfsigned(const EVP_PKEY_ptr & pkey, const int days,
}
BIO * bio = crtpath.empty() ?
- BIO_new_fp(stdout, BIO_NOCLOSE | (use_pem ? BIO_FP_TEXT : 0)) :
+ _BIO_new_fp(stdout, use_pem) :
BIO_new_file(crtpath.c_str(), (use_pem ? "w" : "wb"));
int len = 0;
@@ -399,7 +413,7 @@ void selfsigned(const EVP_PKEY_ptr & pkey, const int days,
errmsg += crtpath.empty() ? "stdout" : crtpath;
errmsg += "\n";
ERR_print_errors_cb(print_error, &errmsg);
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
}
diff --git a/net/nginx-util/src/px5g.cpp b/net/nginx-util/src/px5g.cpp
index 5ad13357b..e2a073d35 100644
--- a/net/nginx-util/src/px5g.cpp
+++ b/net/nginx-util/src/px5g.cpp
@@ -118,7 +118,7 @@ auto checkend(const argv_view & argv) -> int
} catch (...) {
auto errmsg = std::string{"checkend error: invalid time "};
errmsg += argv[i];
- std::throw_with_nested(std::runtime_error(errmsg.c_str()));
+ std::throw_with_nested(std::runtime_error(errmsg));
}
seconds = static_cast<time_t>(num);
@@ -126,7 +126,7 @@ auto checkend(const argv_view & argv) -> int
if (num!=static_cast<intmax_t>(seconds)) {
auto errmsg = std::string{"checkend error: time too big "};
errmsg += argv[i];
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}
}
}
@@ -174,7 +174,7 @@ void eckey(const argv_view & argv)
if (has_main_option) {
throw std::runtime_error
("eckey error: more than one main option");
- } // else:
+ } //else:
has_main_option = true;
curve = parse_curve(argv[i]);
@@ -223,7 +223,7 @@ void rsakey(const argv_view & argv)
if (has_main_option) {
throw std::runtime_error("rsakey error: more than one keysize");
- } // else:
+ } //else:
has_main_option = true;
try {
@@ -231,7 +231,7 @@ void rsakey(const argv_view & argv)
} catch (...) {
std::string errmsg{"rsakey error: invalid keysize "};
errmsg += argv[i];
- std::throw_with_nested(std::runtime_error(errmsg.c_str()));
+ std::throw_with_nested(std::runtime_error(errmsg));
}
}
}
@@ -264,7 +264,7 @@ void selfsigned(const argv_view & argv)
} catch (...) {
std::string errmsg{"selfsigned error: not a number for -days "};
errmsg += argv[i].substr(4);
- std::throw_with_nested(std::runtime_error(errmsg.c_str()));
+ std::throw_with_nested(std::runtime_error(errmsg));
}
}
@@ -287,7 +287,7 @@ void selfsigned(const argv_view & argv)
} catch (...) {
std::string errmsg{"selfsigned error: invalid keysize "};
errmsg += argv[i].substr(4);
- std::throw_with_nested(std::runtime_error(errmsg.c_str()));
+ std::throw_with_nested(std::runtime_error(errmsg));
}
} else {
throw std::runtime_error("selfsigned error: invalid algorithm");
diff --git a/net/nginx-util/src/regex-pcre.hpp b/net/nginx-util/src/regex-pcre.hpp
index 8408b60f4..bfd3a0534 100644
--- a/net/nginx-util/src/regex-pcre.hpp
+++ b/net/nginx-util/src/regex-pcre.hpp
@@ -1,5 +1,3 @@
-// implementing *some* <regex> functions using pcre for performance:
-
#ifndef __REGEXP_PCRE_HPP
#define __REGEXP_PCRE_HPP
@@ -11,6 +9,9 @@
namespace rgx {
+/* partially implement the std::regex interface using PCRE for performance
+ * (=> pass "match" as non-const reference)
+ */
namespace regex_constants {
@@ -130,8 +131,8 @@ class smatch {
friend auto regex_search(std::string::const_iterator begin,
std::string::const_iterator end,
- smatch & match,
- const regex & rgx);
+ smatch & match, //NOLINT(google-runtime-references)
+ const regex & rgx); // match std::regex interface.
private:
@@ -188,14 +189,15 @@ auto regex_replace(const std::string & subj,
const std::string & insert);
-inline auto regex_search(const std::string & subj, smatch & match,
- const regex & rgx);
+inline auto regex_search(const std::string & subj,
+ smatch & match, //NOLINT(google-runtime-references)
+ const regex & rgx); // match std::regex interface.
auto regex_search(std::string::const_iterator begin,
std::string::const_iterator end,
- smatch & match,
- const regex & rgx);
+ smatch & match, //NOLINT(google-runtime-references)
+ const regex & rgx); // match std::regex interface.
@@ -260,12 +262,10 @@ auto smatch::format(const std::string & fmt) const {
index = pos + 1;
char chr = fmt[index++];
- int n = 0;
- static const auto BASE = 10;
switch(chr) {
case '&': // match
- ret += this->str(0);
+ ret += str(0);
break;
case '`': // prefix
@@ -276,14 +276,20 @@ auto smatch::format(const std::string & fmt) const {
ret.append(begin+vec[1], end);
break;
- default: // number => submatch
- while (isdigit(chr) != 0) {
- n = BASE*n + chr - '0';
- chr = fmt[index++];
- }
-
- ret += n>0 ? str(n) : std::string{"$"};
-
+ default:
+ if (isdigit(chr) != 0) { // one or two digits => submatch:
+ int num = chr - '0';
+ chr = fmt[index];
+ if (isdigit(chr) != 0) { // second digit:
+ ++index;
+ static const auto base = 10;
+ num = num*base + chr - '0';
+ }
+ ret += str(num);
+ break;
+ } //else:
+
+ ret += '$';
[[fallthrough]];
case '$': // escaped
diff --git a/net/nginx-util/src/test-nginx-util-root.sh b/net/nginx-util/src/test-nginx-util-root.sh
index a6d78757c..0ce8c9428 100644
--- a/net/nginx-util/src/test-nginx-util-root.sh
+++ b/net/nginx-util/src/test-nginx-util-root.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
PRINT_PASSED=2
@@ -37,7 +37,7 @@ setpoint_add_ssl() {
local indent="\n$1"
local name="$2"
local default=""
- [ "${name}" == "${LAN_NAME}" ] && default=".default"
+ [ "${name}" = "${LAN_NAME}" ] && default=".default"
local prefix="${CONF_DIR}${name}"
local CONF="$(grep -vE "$(_regex "${NGX_INCLUDE}" \
@@ -74,10 +74,17 @@ setpoint_add_ssl() {
# ----------------------------------------------------------------------------
+test_setpoint() {
+ [ "$(cat "$1")" = "$2" ] && return
+ echo "$1:"; cat "$1"
+ echo "differs from setpoint:"; echo "$2"
+ [ "${PRINT_PASSED}" -gt 1 ] && pst_exit 1
+}
+
-function test() {
- eval "$1 2>/dev/null >/dev/null "
- if [ $? -eq $2 ]
+test() {
+ eval "$1 2>/dev/null >/dev/null"
+ if [ "$?" -eq "$2" ]
then
[ "${PRINT_PASSED}" -gt 0 ] \
&& printf "%-72s%-1s\n" "$1" "2>/dev/null >/dev/null (-> $2?) passed."
@@ -88,7 +95,7 @@ function test() {
}
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting ${NGINX_UTIL} get_env ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting %s get_env ...\n" "${NGINX_UTIL}"
eval $("${NGINX_UTIL}" get_env)
test '[ -n "${NGINX_CONF}" ]' 0
@@ -101,21 +108,21 @@ test '[ -n "${SSL_SESSION_TIMEOUT_ARG}" ]' 0
test '[ -n "${ADD_SSL_FCT}" ]' 0
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nPrepare files in ${CONF_DIR} ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nPrepare files in %s ...\n" "${CONF_DIR}"
-mkdir -p ${CONF_DIR}
+mkdir -p "${CONF_DIR}"
-cd ${CONF_DIR}
+cd "${CONF_DIR}" || exit 2
NGX_INCLUDE="include '\$';"
NGX_SERVER_NAME="server_name * '\$' *;"
NGX_SSL_CRT="ssl_certificate '\$.crt';"
NGX_SSL_KEY="ssl_certificate_key '\$.key';"
NGX_SSL_SESSION_CACHE="ssl_session_cache '$(echo "${SSL_SESSION_CACHE_ARG}" \
- | sed -E "s/$(__esc_regex ${LAN_NAME})/\$/")';"
+ | sed -E "s/$(__esc_regex "${LAN_NAME}")/\$/")';"
NGX_SSL_SESSION_TIMEOUT="ssl_session_timeout '${SSL_SESSION_TIMEOUT_ARG}';"
-cat > ${LAN_NAME}.sans <<EOF
+cat > "${LAN_NAME}.sans" <<EOF
# default_server for the LAN addresses getting the IPs by:
# ifstatus lan | jsonfilter -e '@["ipv4-address","ipv6-address"].*.address'
server {
@@ -196,56 +203,44 @@ EOF
CONFS="${CONFS} tab:0"
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting ${NGINX_UTIL} init_lan ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting %s init_lan ...\n" "${NGINX_UTIL}"
mkdir -p "$(dirname "${LAN_LISTEN}")"
-cp ${LAN_NAME}.sans ${LAN_NAME}.conf
+cp "${LAN_NAME}.sans" "${LAN_NAME}.conf"
-test '${NGINX_UTIL} init_lan' 0
+test '"${NGINX_UTIL}" init_lan' 0
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nSetup files in ${CONF_DIR} ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nSetup files in %s ...\n" "${CONF_DIR}"
for conf in ${CONFS}
-do test 'setpoint_add_ssl " " '${conf%:*} ${conf#*:}
+do test 'setpoint_add_ssl " " '"${conf%:*}" "${conf#*:}"
done
test 'setpoint_add_ssl "\t" tab' 0 # fixes wrong indentation.
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting ${NGINX_UTIL} add_ssl ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting %s add_ssl ...\n" "${NGINX_UTIL}"
cp different_name.sans different_name.with
-test '[ "${ADD_SSL_FCT}" == "add_ssl" ] ' 0
+test '[ "${ADD_SSL_FCT}" = "add_ssl" ] ' 0
for conf in ${CONFS}; do
- name=${conf%:*}
- cp ${name}.sans ${name}.conf
- test '${NGINX_UTIL} add_ssl '${name} ${conf#*:}
- (test '[ "$(cat '${name}'.conf)" == "$(cat '${name}'.with)" ]' 0 >/dev/null)
- [ "$?" -gt 0 ] && {
- echo "created ${name}.conf:"; cat "${name}.conf"
- echo "differs from setpoint:"; cat "${name}.with"
- exit 1
- }
+ name="${conf%:*}"
+ cp "${name}.sans" "${name}.conf"
+ test '"${NGINX_UTIL}" add_ssl '"${name}" "${conf#*:}"
+ test_setpoint "${name}.conf" "$(cat "${name}.with")"
done
-
-[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting ${NGINX_UTIL} del_ssl ...\n"
+[ "$PRINT_PASSED" -gt 0 ] && printf "\nTesting %s del_ssl ...\n" "${NGINX_UTIL}"
sed -i "/server {/a\\ include '${LAN_LISTEN}';" minimal.sans
for conf in ${CONFS}; do
- name=${conf%:*}
- cp ${name}.with ${name}.conf
- test '${NGINX_UTIL} del_ssl '${name} ${conf#*:}
- (test '[ "$(cat '${name}'.conf)" == "$(cat '${name}'.sans)" ]' 0 >/dev/null)
- [ "$?" -gt 0 ] && {
- echo "created ${name}.conf:"; cat "${name}.conf"
- echo "differs from setpoint:"; cat "${name}.sans"
- exit 1
- }
+ name="${conf%:*}"
+ cp "${name}.with" "${name}.conf"
+ test '"${NGINX_UTIL}" del_ssl '"${name}" "${conf#*:}"
+ test_setpoint "${name}.conf" "$(cat "${name}.sans")"
done
-
diff --git a/net/nginx-util/src/test-nginx-util.sh b/net/nginx-util/src/test-nginx-util.sh
index 840f6f260..787906350 100755
--- a/net/nginx-util/src/test-nginx-util.sh
+++ b/net/nginx-util/src/test-nginx-util.sh
@@ -1,38 +1,48 @@
-#!/bin/bash
+#!/bin/sh
printf "Initializing tests ...\n"
fakechroot=""
-[ -x /usr/bin/fakechroot ] && fakechroot="/usr/bin/fakechroot" \
+[ -x "/usr/bin/fakechroot" ] && fakechroot="/usr/bin/fakechroot" \
|| [ "$(id -u)" -eq 0 ] || { \
printf "Error: Testing needs fakechroot or whoami=root for chroot."
return 1
}
-TMPROOT=$(mktemp -d /tmp/test-nginx-util-XXXXXX)
+TMPROOT="$(mktemp -d "/tmp/test-nginx-util-XXXXXX")"
-ln -s /bin ${TMPROOT}/bin
+ln -s /bin "${TMPROOT}/bin"
-mkdir -p ${TMPROOT}/usr/bin/
+mkdir -p "${TMPROOT}/usr/bin/"
-cp ./test-nginx-util-root.sh ${TMPROOT}/usr/bin/
+cp "./test-nginx-util-root.sh" "${TMPROOT}/usr/bin/"
printf "\n\n******* Testing nginx-ssl-util-noubus *******\n"
-cp ./nginx-ssl-util-noubus ${TMPROOT}/usr/bin/nginx-util
+cp "./nginx-ssl-util-noubus" "${TMPROOT}/usr/bin/nginx-util"
-${fakechroot} /bin/chroot ${TMPROOT} /bin/sh -c /usr/bin/test-nginx-util-root.sh
-
-echo $?
+"${fakechroot}" /bin/chroot "${TMPROOT}" \
+ /bin/sh -c "/usr/bin/test-nginx-util-root.sh" ||
+{
+ echo "!!! Error: $?"
+ rm -r "${TMPROOT}"
+ exit 1
+}
printf "\n\n******* Testing nginx-ssl-util-nopcre-noubus *******\n"
-cp ./nginx-ssl-util-nopcre-noubus ${TMPROOT}/usr/bin/nginx-util
+cp "./nginx-ssl-util-nopcre-noubus" "${TMPROOT}/usr/bin/nginx-util"
-${fakechroot} /bin/chroot ${TMPROOT} /bin/sh -c /usr/bin/test-nginx-util-root.sh
+"${fakechroot}" /bin/chroot "${TMPROOT}" \
+ /bin/sh -c "/usr/bin/test-nginx-util-root.sh" ||
+{
+ echo "!!! Error: $?"
+ rm -r "${TMPROOT}"
+ exit 1
+}
-rm -r ${TMPROOT}
+rm -r "${TMPROOT}"
diff --git a/net/nginx-util/src/test-px5g.sh b/net/nginx-util/src/test-px5g.sh
index 944464c2a..486b9ae98 100755
--- a/net/nginx-util/src/test-px5g.sh
+++ b/net/nginx-util/src/test-px5g.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
PRINT_PASSED=2
@@ -8,7 +8,7 @@ OPENSSL_PEM="$(mktemp)"
OPENSSL_DER="$(mktemp)"
NONCE=$(dd if=/dev/urandom bs=1 count=4 2>/dev/null | hexdump -e '1/1 "%02x"')
-SUBJECT=/C="ZZ"/ST="Somewhere"/L="None"/O="OpenWrt'$NONCE'"/CN="OpenWrt"
+SUBJECT="/C=ZZ/ST=Somewhere/L=None/O=OpenWrt'$NONCE'/CN=OpenWrt"
openssl req -x509 -nodes -days 1 -keyout /dev/null 2>/dev/null \
-out "$OPENSSL_PEM" -subj "$SUBJECT" \
@@ -18,9 +18,9 @@ openssl req -x509 -nodes -days 1 -keyout /dev/null 2>/dev/null \
|| ( printf "error: generating DER certificate with openssl"; return 1)
-function test() {
+test() {
eval "$1 >/dev/null "
- if [ $? -eq $2 ]
+ if [ $? -eq "$2" ]
then
[ "${PRINT_PASSED}" -gt 0 ] \
&& printf "%-72s%-1s\n" "$1" ">/dev/null (-> $2?) passed."
@@ -130,8 +130,8 @@ test './px5g selfsigned -newkey rsa:666 | openssl x509 -checkend 0 ' 0
test './px5g selfsigned -newkey ec | openssl x509 -checkend 0 ' 0
test './px5g selfsigned -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 \
| openssl x509 -checkend 0 ' 0
-test './px5g selfsigned -subj $SUBJECT | openssl x509 -noout \
- -subject -nameopt compat | grep -q subject=$SUBJECT 2>/dev/null' 0
+test './px5g selfsigned -subj "$SUBJECT" | openssl x509 -noout \
+ -subject -nameopt compat | grep -q subject="$SUBJECT" 2>/dev/null' 0
test './px5g selfsigned -out /dev/null -keyout /proc/self/fd/1 \
| openssl rsa -check 2>/dev/null ' 0
diff --git a/net/nginx-util/src/ubus-cxx.cpp b/net/nginx-util/src/ubus-cxx.cpp
new file mode 100644
index 000000000..7f65813ca
--- /dev/null
+++ b/net/nginx-util/src/ubus-cxx.cpp
@@ -0,0 +1,148 @@
+#include <iostream>
+
+#include "ubus-cxx.hpp"
+
+
+inline void example_for_checking_if_there_is_a_key()
+{
+ if (ubus::call("service", "list").filter("cron")) {
+ std::cout<<"Cron is active (with or without instances) "<<std::endl;
+ }
+}
+
+
+inline void example_for_getting_values()
+{
+ auto lan_status = ubus::call("network.interface.lan", "status");
+ for (auto t : lan_status.filter("ipv6-address", "", "address")) {
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto x = const_cast<blob_attr *>(t);
+ std::cout<<"["<<blobmsg_get_string(x)<<"] ";
+ }
+ for (auto t : lan_status.filter("ipv4-address", "").filter("address")) {
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto x = const_cast<blob_attr *>(t);
+ std::cout<<blobmsg_get_string(x)<<" ";
+ }
+ std::cout<<std::endl;
+}
+
+
+inline void example_for_sending_message()
+{
+ auto set_arg = [](blob_buf * buf) -> int
+ { return blobmsg_add_string(buf, "config", "nginx"); };
+ for (auto t : ubus::call("uci", "get", set_arg).filter("values")) {
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto x = const_cast<blob_attr *>(t);
+ std::cout<<blobmsg_get_string(x)<<"\n";
+ }
+}
+
+
+inline void example_for_exploring()
+{
+ ubus::strings keys{"ipv4-address", "", ""};
+ for (auto t : ubus::call("network.interface.lan", "status").filter(keys)) {
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto x = const_cast<blob_attr *>(t);
+ std::cout<<blobmsg_name(x)<<": ";
+ switch (blob_id(x)) {
+ case BLOBMSG_TYPE_UNSPEC: std::cout<<"[unspecified]"; break;
+ case BLOBMSG_TYPE_ARRAY: std::cout<<"[array]"; break;
+ case BLOBMSG_TYPE_TABLE: std::cout<<"[table]"; break;
+ case BLOBMSG_TYPE_STRING: std::cout<<blobmsg_get_string(x); break;
+ case BLOBMSG_TYPE_INT64: std::cout<<blobmsg_get_u64(x); break;
+ case BLOBMSG_TYPE_INT32: std::cout<<blobmsg_get_u32(x); break;
+ case BLOBMSG_TYPE_INT16: std::cout<<blobmsg_get_u16(x); break;
+ case BLOBMSG_TYPE_BOOL: std::cout<<blobmsg_get_bool(x); break;
+ case BLOBMSG_TYPE_DOUBLE: std::cout<<blobmsg_get_double(x); break;
+ default: std::cout<<"[unknown]";
+ }
+ std::cout<<std::endl;
+ }
+}
+
+
+inline void example_for_recursive_exploring()
+{ // output like from the original ubus call:
+ const auto explore = [](auto message) -> void
+ {
+ auto end = message.end();
+ auto explore_internal =
+ [&end](auto & explore_ref, auto it, size_t depth=1) -> void
+ {
+ std::cout<<std::endl;
+ bool first = true;
+ for (; it!=end; ++it) {
+ //NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
+ auto attr = const_cast<blob_attr *>(*it);
+ if (first) { first = false; }
+ else { std::cout<<",\n"; }
+ std::cout<<std::string(depth, '\t');
+ std::string name = blobmsg_name(attr);
+ if (!name.empty()) { std::cout<<"\""<<name<<"\": "; }
+ switch (blob_id(attr)) {
+ case BLOBMSG_TYPE_UNSPEC: std::cout<<"(unspecified)"; break;
+ case BLOBMSG_TYPE_ARRAY:
+ std::cout<<"[";
+ explore_ref(explore_ref, ubus::iterator{attr}, depth+1);
+ std::cout<<"\n"<<std::string(depth, '\t')<<"]";
+ break;
+ case BLOBMSG_TYPE_TABLE:
+ std::cout<<"{";
+ explore_ref(explore_ref, ubus::iterator{attr}, depth+1);
+ std::cout<<"\n"<<std::string(depth, '\t')<<"}";
+ break;
+ case BLOBMSG_TYPE_STRING:
+ std::cout<<"\""<<blobmsg_get_string(attr)<<"\"";
+ break;
+ case BLOBMSG_TYPE_INT64:
+ std::cout<<blobmsg_get_u64(attr);
+ break;
+ case BLOBMSG_TYPE_INT32:
+ std::cout<<blobmsg_get_u32(attr);
+ break;
+ case BLOBMSG_TYPE_INT16:
+ std::cout<<blobmsg_get_u16(attr);
+ break;
+ case BLOBMSG_TYPE_BOOL:
+ std::cout<<(blobmsg_get_bool(attr) ? "true" : "false");
+ break;
+ case BLOBMSG_TYPE_DOUBLE:
+ std::cout<<blobmsg_get_double(attr);
+ break;
+ default: std::cout<<"(unknown)"; break;
+ }
+ }
+ };
+ std::cout<<"{";
+ explore_internal(explore_internal, message.begin());
+ std::cout<<"\n}"<<std::endl;
+ };
+ explore(ubus::call("network.interface.lan", "status"));
+}
+
+
+auto main() -> int {
+
+ try {
+ example_for_checking_if_there_is_a_key();
+
+ example_for_getting_values();
+
+ example_for_sending_message();
+
+ example_for_exploring();
+
+ example_for_recursive_exploring();
+
+ return 0;
+ }
+
+ catch (const std::exception & e) { std::cerr<<e.what()<<std::endl; }
+
+ catch (...) { perror("main error"); }
+
+ return 1;
+}
diff --git a/net/nginx-util/src/ubus-cxx.hpp b/net/nginx-util/src/ubus-cxx.hpp
index b1a62c6ce..3c0851e2b 100644
--- a/net/nginx-util/src/ubus-cxx.hpp
+++ b/net/nginx-util/src/ubus-cxx.hpp
@@ -1,114 +1,23 @@
#ifndef _UBUS_CXX_HPP
#define _UBUS_CXX_HPP
-extern "C" { //TODO(pst): remove when in upstream
-#include <libubus.h>
-}
#include <cassert>
+#include <libubus.h>
#include <memory>
#include <mutex>
#include <string>
#include <utility>
#include <vector>
+
#ifndef NDEBUG
#include <iostream>
#endif
-// // example for checking if there is a key:
-// if (ubus::call("service", "list", 1000).filter("cron")) {
-// std::cout<<"Cron is active (with or without instances) "<<std::endl;
-// }
-
-// // example for getting values:
-// auto lan_status = ubus::call("network.interface.lan", "status");
-// for (auto x : lan_status.filter("ipv6-address", "", "address")) {
-// std::cout<<"["<<blobmsg_get_string(x)<<"] ";
-// }
-// for (auto x : lan_status.filter("ipv4-address", "").filter("address")) {
-// std::cout<<blobmsg_get_string(x)<<" ";
-// }
-// std::cout<<std::endl;
-
-// // example for exploring:
-// ubus::strings keys{"ipv4-address", "", ""};
-// for (auto x : ubus::call("network.interface.lan", "status").filter(keys)) {
-// std::cout<<blobmsg_name(x)<<": ";
-// switch (blob_id(x)) {
-// case BLOBMSG_TYPE_UNSPEC: std::cout<<"[unspecified]"; break;
-// case BLOBMSG_TYPE_ARRAY: std::cout<<"[array]"; break;
-// case BLOBMSG_TYPE_TABLE: std::cout<<"[table]"; break;
-// case BLOBMSG_TYPE_STRING: std::cout<<blobmsg_get_string(x); break;
-// case BLOBMSG_TYPE_INT64: std::cout<<blobmsg_get_u64(x); break;
-// case BLOBMSG_TYPE_INT32: std::cout<<blobmsg_get_u32(x); break;
-// case BLOBMSG_TYPE_INT16: std::cout<<blobmsg_get_u16(x); break;
-// case BLOBMSG_TYPE_BOOL: std::cout<<blobmsg_get_bool(x); break;
-// case BLOBMSG_TYPE_DOUBLE: std::cout<<blobmsg_get_double(x); break;
-// default: std::cout<<"[unknown]";
-// }
-// std::cout<<std::endl;
-// }
-
-// // example for recursive exploring (output like from the original ubus call)
-// const auto explore = [](auto message) -> void
-// {
-// auto end = message.end();
-// auto explore_internal =
-// [&end](auto & explore_ref, auto it, size_t depth=1) -> void
-// {
-// std::cout<<std::endl;
-// bool first = true;
-// for (; it!=end; ++it) {
-// auto * attr = *it;
-// if (first) { first = false; }
-// else { std::cout<<",\n"; }
-// std::cout<<std::string(depth, '\t');
-// std::string name = blobmsg_name(attr);
-// if (name != "") { std::cout<<"\""<<name<<"\": "; }
-// switch (blob_id(attr)) {
-// case BLOBMSG_TYPE_UNSPEC: std::cout<<"(unspecified)"; break;
-// case BLOBMSG_TYPE_ARRAY:
-// std::cout<<"[";
-// explore_ref(explore_ref, ubus::iterator{attr}, depth+1);
-// std::cout<<"\n"<<std::string(depth, '\t')<<"]";
-// break;
-// case BLOBMSG_TYPE_TABLE:
-// std::cout<<"{";
-// explore_ref(explore_ref, ubus::iterator{attr}, depth+1);
-// std::cout<<"\n"<<std::string(depth, '\t')<<"}";
-// break;
-// case BLOBMSG_TYPE_STRING:
-// std::cout<<"\""<<blobmsg_get_string(attr)<<"\"";
-// break;
-// case BLOBMSG_TYPE_INT64:
-// std::cout<<blobmsg_get_u64(attr);
-// break;
-// case BLOBMSG_TYPE_INT32:
-// std::cout<<blobmsg_get_u32(attr);
-// break;
-// case BLOBMSG_TYPE_INT16:
-// std::cout<<blobmsg_get_u16(attr);
-// break;
-// case BLOBMSG_TYPE_BOOL:
-// std::cout<<(blobmsg_get_bool(attr) ? "true" : "false");
-// break;
-// case BLOBMSG_TYPE_DOUBLE:
-// std::cout<<blobmsg_get_double(attr);
-// break;
-// default: std::cout<<"(unknown)"; break;
-// }
-// }
-// };
-// std::cout<<"{";
-// explore_internal(explore_internal, message.begin());
-// std::cout<<"\n}"<<std::endl;
-// };
-// explore(ubus::call("network.interface.lan", "status"));
-
-
-
namespace ubus {
+static constexpr int call_timeout = 500;
+
using msg_ptr = std::shared_ptr<const blob_attr>;
using strings = std::vector<std::string>;
@@ -130,7 +39,7 @@ inline auto concat(strings dest, strings src, Strings ...more)
template<class S, class ...Strings>
inline auto concat(strings dest, S src, Strings ...more)
{
- dest.push_back(std::move(src));
+ dest.emplace_back(std::move(src));
return concat(std::move(dest), std::move(more)...);
}
@@ -186,7 +95,7 @@ public:
}
- inline iterator(iterator &&) = default;
+ inline iterator(iterator &&) noexcept = default;
inline iterator(const iterator &) = delete;
@@ -208,7 +117,8 @@ public:
auto operator++() -> iterator &;
- inline ~iterator() { if (cur.get()==this) { static_cast<void>(cur.release()); } }
+ inline ~iterator()
+ { if (cur.get()==this) { static_cast<void>(cur.release()); } }
};
@@ -225,8 +135,8 @@ private:
public:
- inline explicit message(msg_ptr message, strings filter={""})
- : msg{std::move(message)}, keys{std::move(filter)} {}
+ inline explicit message(msg_ptr message_ptr, strings filter={""})
+ : msg{std::move(message_ptr)}, keys{std::move(filter)} {}
inline message(message &&) = default;
@@ -268,42 +178,41 @@ public:
-class ubus {
+class lock_shared_resources {
private:
- static std::mutex buffering;
+ static std::mutex inuse;
public:
- inline ubus() = delete;
+ inline lock_shared_resources() { inuse.lock(); }
- inline ubus(ubus &&) = delete;
+ inline lock_shared_resources(lock_shared_resources &&) noexcept = default;
- inline ubus(const ubus &) = delete;
+ inline lock_shared_resources(const lock_shared_resources &) = delete;
- inline auto operator=(ubus &&) -> auto && = delete;
+ inline auto operator=(const lock_shared_resources &) -> auto & = delete;
- inline auto operator=(const ubus &) -> auto & = delete;
+ inline auto operator=(lock_shared_resources &&) -> auto && = delete;
- static auto get_context() -> ubus_context *
+
+ //NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+ inline auto get_context() -> ubus_context * // is member to enforce inuse.
{
static auto ubus_freeing = [] (ubus_context * ctx) { ubus_free(ctx); };
static std::unique_ptr<ubus_context, decltype(ubus_freeing)>
lazy_ctx{ubus_connect(nullptr), ubus_freeing};
if (!lazy_ctx) { // it could be available on a later call:
- static std::mutex connecting;
- connecting.lock();
- if (!lazy_ctx) { lazy_ctx.reset(ubus_connect(nullptr)); }
- connecting.unlock();
+ lazy_ctx.reset(ubus_connect(nullptr));
if (!lazy_ctx) {
throw std::runtime_error("ubus error: cannot connect context");
@@ -314,7 +223,8 @@ public:
}
- static auto lock_and_get_shared_blob_buf() -> blob_buf *
+ //NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+ inline auto get_blob_buf() -> blob_buf * // is member to enforce inuse.
{
static blob_buf buf;
@@ -322,28 +232,37 @@ public:
static std::unique_ptr<blob_buf, decltype(blob_buf_freeing)>
created_to_free_on_the_end_of_life{&buf, blob_buf_freeing};
- buffering.lock();
blob_buf_init(&buf, 0);
+
return &buf;
}
- static void unlock_shared_blob_buf() { buffering.unlock(); }
+ inline ~lock_shared_resources() { inuse.unlock(); }
+};
- inline ~ubus() = delete;
-};
+template<class F>
+auto call(const char * path, const char * method, F set_arguments,
+ int timeout=call_timeout) -> message;
+
+
+inline auto call(const char * path, const char * method,
+ int timeout=call_timeout) -> message
+{ return call(path, method, [](blob_buf * /*buf*/) { return 0; }, timeout); }
+
+inline auto call(const char * path, int timeout=call_timeout) -> message
+{ return call(path, "", timeout); }
-auto call(const char * path, const char * method="", int timeout=500);
// ------------------------- implementation: ----------------------------------
-std::mutex ubus::buffering;
+std::mutex lock_shared_resources::inuse;
inline auto iterator::operator++() -> iterator &
@@ -363,7 +282,10 @@ inline auto iterator::operator++() -> iterator &
++i;
auto tmp = cur.release();
- cur = std::unique_ptr<iterator>{new iterator(tmp)};
+
+ struct new_iterator : public iterator // use private constructor:
+ { explicit new_iterator(iterator * par) : iterator{par} {} };
+ cur = std::make_unique<new_iterator>(tmp);
} else {
while (true) {
@@ -392,31 +314,39 @@ inline auto iterator::operator++() -> iterator &
}
-inline auto call(const char * path, const char * method, const int timeout)
+template<class F>
+inline auto call(const char * path, const char * method, F set_arguments,
+ int timeout) -> message
{
- auto ctx = ubus::get_context();
+
+ auto shared = lock_shared_resources{};
+
+ auto ctx = shared.get_context();
uint32_t id;
int err = ubus_lookup_id(ctx, path, &id);
if (err==0) { // call
- ubus_request req{};
+ ubus_request request{};
- auto buf = ubus::lock_and_get_shared_blob_buf();
- err = ubus_invoke_async(ctx, id, method, buf->head, &req);
- ubus::unlock_shared_blob_buf();
+ auto buf = shared.get_blob_buf();
+ err = set_arguments(buf);
+ if (err==0) {
+ err = ubus_invoke_async(ctx, id, method, buf->head, &request);
+ }
if (err==0) {
- msg_ptr msg;
+ msg_ptr message_ptr;
- /* Cannot capture anything (msg), the lambda would be another type.
+ /* Cannot capture message_ptr, the lambda would be another type.
* Pass a location where to save the message as priv pointer when
* invoking and get it back here:
*/
- req.priv = &msg;
+ request.priv = &message_ptr;
- req.data_cb = [](ubus_request * req, int /*type*/, blob_attr * msg)
+ request.data_cb =
+ [](ubus_request * req, int /*type*/, blob_attr * msg)
{
if (req==nullptr || msg==nullptr) { return; }
@@ -427,15 +357,15 @@ inline auto call(const char * path, const char * method, const int timeout)
if (!*saved) { throw std::bad_alloc(); }
};
- err = ubus_complete_request(ctx, &req, timeout);
+ err = ubus_complete_request(ctx, &request, timeout);
- if (err==0) { return message{msg}; }
+ if (err==0) { return message{message_ptr}; }
}
}
std::string errmsg = "ubus::call error: cannot invoke";
errmsg += " (" + std::to_string(err) + ") " + path + " " + method;
- throw std::runtime_error(errmsg.c_str());
+ throw std::runtime_error(errmsg);
}