Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General tidy up #361

Merged
merged 5 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,10 @@ jobs:
run: |
echo "CMAKE_EXTRA_ARGS=${{ env.CMAKE_EXTRA_ARGS }} -DNMOS_CPP_CONAN_OPTIONS:STRING=\"cpprestsdk:http_client_impl=asio;cpprestsdk:http_listener_impl=asio\"" >> $GITHUB_ENV

- uses: ilammy/msvc-dev-cmd@v1
- name: setup developer command prompt for Microsoft Visual C++
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: build
uses: lukka/run-cmake@v3.4
with:
Expand Down Expand Up @@ -833,7 +836,10 @@ jobs:
run: |
echo "CMAKE_EXTRA_ARGS=${{ env.CMAKE_EXTRA_ARGS }} -DNMOS_CPP_CONAN_OPTIONS:STRING=\"cpprestsdk:http_client_impl=asio;cpprestsdk:http_listener_impl=asio\"" >> $GITHUB_ENV

- uses: ilammy/msvc-dev-cmd@v1
- name: setup developer command prompt for Microsoft Visual C++
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: build
uses: lukka/run-cmake@v3.4
with:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/src/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
- uses: ilammy/msvc-dev-cmd@v1
- name: setup developer command prompt for Microsoft Visual C++
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: build
uses: lukka/run-cmake@v3.4
with:
Expand Down
6 changes: 3 additions & 3 deletions Development/cmake/NmosCppDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ add_library(nmos-cpp::OpenSSL ALIAS OpenSSL)

if(NMOS_CPP_USE_CONAN)
set(JSON_SCHEMA_VALIDATOR_VERSION_MIN "2.1.0")
set(JSON_SCHEMA_VALIDATOR_VERSION_CUR "2.2.0")
set(JSON_SCHEMA_VALIDATOR_VERSION_CUR "2.3.0")
find_package(nlohmann_json_schema_validator REQUIRED)
if(NOT nlohmann_json_schema_validator_VERSION)
message(STATUS "Found nlohmann_json_schema_validator unknown version; minimum version: " ${JSON_SCHEMA_VALIDATOR_VERSION_MIN})
Expand All @@ -202,7 +202,7 @@ if(NMOS_CPP_USE_CONAN)
endif()

set(NLOHMANN_JSON_VERSION_MIN "3.6.0")
set(NLOHMANN_JSON_VERSION_CUR "3.11.2")
set(NLOHMANN_JSON_VERSION_CUR "3.11.3")
find_package(nlohmann_json REQUIRED)
if(NOT nlohmann_json_VERSION)
message(STATUS "Found nlohmann_json unknown version; minimum version: " ${NLOHMANN_JSON_VERSION_MIN})
Expand Down Expand Up @@ -461,7 +461,7 @@ endif()

if(NMOS_CPP_USE_CONAN)
set(JWT_VERSION_MIN "0.5.1")
set(JWT_VERSION_CUR "0.6.0")
set(JWT_VERSION_CUR "0.7.0")
find_package(jwt-cpp REQUIRED)
if(NOT jwt-cpp_VERSION)
message(STATUS "Found jwt-cpp unknown version; minimum version: " ${JWT_VERSION_MIN})
Expand Down
4 changes: 2 additions & 2 deletions Development/conanfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ boost/1.80.0
cpprestsdk/2.10.18
websocketpp/0.8.2
openssl/1.1.1s
json-schema-validator/2.2.0
nlohmann_json/3.11.2
json-schema-validator/2.3.0
nlohmann_json/3.11.3
zlib/1.2.13
jwt-cpp/0.7.0

Expand Down
2 changes: 1 addition & 1 deletion Development/nmos-cpp-registry/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ int main(int argc, char* argv[])
#endif

// only implement communication with Authorization server if IS-10/BCP-003-02 is required
// cf. preprocessor conditions in nmos::make_registration_api, nmos::make_query_api, make_query_ws_validate_handler
// cf. preprocessor conditions in nmos::make_registration_api, nmos::make_query_api, nmos::make_query_ws_validate_handler, nmos::make_events_ws_validate_handler
nmos::experimental::authorization_state authorization_state;
if (nmos::experimental::fields::server_authorization(registry_model.settings))
{
Expand Down
69 changes: 0 additions & 69 deletions Development/nmos/events_ws_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,75 +62,6 @@ namespace nmos
};
}

web::websockets::experimental::listener::validate_handler make_events_ws_validate_handler(nmos::node_model& model, nmos::experimental::authorization_state& authorization_state, nmos::experimental::validate_authorization_token_handler access_token_validation, slog::base_gate& gate_)
{
return [&model, &authorization_state, access_token_validation, &gate_](web::http::http_request req)
{
nmos::ws_api_gate gate(gate_, req.request_uri());
auto lock = model.write_lock();
auto& resources = model.connection_resources;

// RFC 6750 defines two methods of sending bearer access tokens which are applicable to WebSocket
// Clients SHOULD use the "Authorization Request Header Field" method.
// Clients MAY use a "URI Query Parameter".
// See https://tools.ietf.org/html/rfc6750#section-2
if (web::http::methods::OPTIONS != req.method() && nmos::experimental::fields::server_authorization(model.settings))
{
const auto& settings = model.settings;

web::uri token_issuer;
// note: ws_validate_authorization returns the token_issuer via function parameter
const auto result = nmos::experimental::ws_validate_authorization(req, nmos::experimental::scopes::events, nmos::get_host_name(settings), token_issuer, access_token_validation, gate_);
if (!result)
{
// set error repsonse
auto realm = web::http::get_host_port(req).first;
if (realm.empty()) { realm = nmos::get_host(settings); }
web::http::http_response res;
const auto retry_after = nmos::experimental::fields::service_unavailable_retry_after(settings);
nmos::experimental::details::set_error_reply(res, realm, retry_after, result);
req.reply(res);

// if no matching public keys caused the error, trigger a re-fetch to obtain public keys from the token issuer (authorization_state.token_issuer)
if (result.value == nmos::experimental::authorization_error::no_matching_keys)
{
slog::log<slog::severities::warning>(gate, SLOG_FLF) << "Invalid websocket connection to: " << req.request_uri().path() << ": " << result.message;

with_write_lock(authorization_state.mutex, [&authorization_state, token_issuer]
{
authorization_state.fetch_token_issuer_pubkeys = true;
authorization_state.token_issuer = token_issuer;
});

model.notify();
}
else
{
slog::log<slog::severities::error>(gate, SLOG_FLF) << "Invalid websocket connection to: " << req.request_uri().path() << ": " << result.message;
}
return false;
}
}

// For now, to determine whether the "resource name" is valid, only look at the path, and ignore any query parameters
const auto& ws_resource_path = req.request_uri().path();
slog::log<slog::severities::more_info>(gate, SLOG_FLF) << "Validating websocket connection to: " << ws_resource_path;

const bool has_ws_resource_path = resources.end() != find_resource_if(resources, nmos::types::sender, [&ws_resource_path](const nmos::resource& resource)
{
auto active = nmos::fields::master_enable(nmos::fields::endpoint_active(resource.data));
auto& transport_params = nmos::fields::transport_params(nmos::fields::endpoint_active(resource.data));
auto& connection_uri = nmos::fields::connection_uri(transport_params.at(0));
return active
&& !connection_uri.is_null()
&& ws_resource_path == web::uri(connection_uri.as_string()).path();
});

if (!has_ws_resource_path) slog::log<slog::severities::error>(gate, SLOG_FLF) << "Invalid websocket connection to: " << ws_resource_path;
return has_ws_resource_path;
};
}

web::websockets::experimental::listener::open_handler make_events_ws_open_handler(nmos::node_model& model, nmos::websockets& websockets, slog::base_gate& gate_)
{
using web::json::value;
Expand Down
5 changes: 4 additions & 1 deletion Development/third_party/nlohmann/json-patch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ class json_patch
json_patch &replace(const json::json_pointer &, json value);
json_patch &remove(const json::json_pointer &);

json &get_json() { return j_; }
const json &get_json() const { return j_; }

operator json() const { return j_; }

private:
json j_;
json j_ = nlohmann::json::array();

static void validateJsonPatch(json const &patch);
};
Expand Down
20 changes: 19 additions & 1 deletion Development/third_party/nlohmann/json-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,12 @@ class logical_combination : public schema

for (auto &s : subschemata_) {
first_error_handler esub;
auto oldPatchSize = patch.get_json().size();
s->validate(ptr, instance, patch, esub);
if (!esub)
count++;
else
patch.get_json().get_ref<nlohmann::json::array_t &>().resize(oldPatchSize);

if (is_validate_complete(instance, ptr, e, esub, count))
return;
Expand Down Expand Up @@ -553,6 +556,9 @@ class type_schema : public schema
else_->validate(ptr, instance, patch, e);
}
}
if (instance.is_null()) {
patch.add(nlohmann::json::json_pointer{}, default_value_);
}
}

protected:
Expand Down Expand Up @@ -601,10 +607,12 @@ class type_schema : public schema
} break;

case json::value_t::array: // "type": ["type1", "type2"]
for (auto &schema_type : attr.value())
for (auto &array_value : attr.value()) {
auto schema_type = array_value.get<std::string>();
for (auto &t : schema_types)
if (t.first == schema_type)
type_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);
}
break;

default:
Expand Down Expand Up @@ -856,7 +864,12 @@ class numeric : public schema
bool violates_multiple_of(T x) const
{
double res = std::remainder(x, multipleOf_.second);
double multiple = std::fabs(x / multipleOf_.second);
if (multiple > 1) {
res = res / multiple;
}
double eps = std::nextafter(x, 0) - static_cast<double>(x);

return std::fabs(res) > std::fabs(eps);
}

Expand Down Expand Up @@ -1134,6 +1147,11 @@ class object : public schema
propertyNames_ = schema::make(attr.value(), root, {"propertyNames"}, uris);
sch.erase(attr);
}

attr = sch.find("default");
if (attr != sch.end()) {
set_default_value(*attr);
}
}
};

Expand Down
Loading
Loading