Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Feat/c api updates #1387

Merged
merged 14 commits into from
Oct 29, 2019
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
33 changes: 31 additions & 2 deletions include/libaktualizr-c.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,57 @@
#ifndef AKTUALIZR_LIBAKTUALIZRC_H
#define AKTUALIZR_LIBAKTUALIZRC_H

#include <stdint.h> // for uint8_t

#ifdef __cplusplus
#include "primary/aktualizr.h"

using Campaign = campaign::Campaign;
using Updates = std::vector<Uptane::Target>;
using Target = Uptane::Target;
using StorageTargetHandle = StorageTargetRHandle;

extern "C" {
#else
typedef struct Aktualizr Aktualizr;
typedef struct Campaign Campaign;
typedef struct Updates Updates;
typedef struct Target Target;
typedef struct StorageTargetHandle StorageTargetHandle;
#endif

Aktualizr *Aktualizr_create(const char *config_path);
Aktualizr *Aktualizr_create_from_cfg(Config *cfg);
Aktualizr *Aktualizr_create_from_path(const char *config_path);
int Aktualizr_initialize(Aktualizr *a);
int Aktualizr_uptane_cycle(Aktualizr *a);
void Aktualizr_destroy(Aktualizr *a);

Campaign *Aktualizr_campaign_check(Aktualizr *a);
int Aktualizr_set_signal_handler(Aktualizr *a, void (*handler)(const char* event_name));

Campaign *Aktualizr_campaigns_check(Aktualizr *a);
int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c);
int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c);
int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c);
void Aktualizr_campaign_free(Campaign *c);

Updates *Aktualizr_updates_check(Aktualizr *a);
void Aktualizr_updates_free(Updates *u);

size_t Aktualizr_get_targets_num(Updates *u);
Target *Aktualizr_get_nth_target(Updates *u, size_t n);
char *Aktualizr_get_target_name(Target *t);

int Aktualizr_download_target(Aktualizr *a, Target *t);

int Aktualizr_install_target(Aktualizr *a, Target *t);

int Aktualizr_send_manifest(Aktualizr *a, const char *manifest);
int Aktualizr_send_device_data(Aktualizr *a);

StorageTargetHandle *Aktualizr_open_stored_target(Aktualizr *a, const Target *t);
size_t Aktualizr_read_stored_target(StorageTargetHandle *handle, uint8_t* buf, size_t size);
int Aktualizr_close_stored_target(StorageTargetHandle *handle);

#ifdef __cplusplus
}
#endif
Expand Down
159 changes: 155 additions & 4 deletions src/libaktualizr-c/libaktualizr-c.cc
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
#include "libaktualizr-c.h"
#include "primary/events.h"

Aktualizr *Aktualizr_create(const char *config_path) {
Aktualizr *Aktualizr_create_from_cfg(Config *cfg) {
Aktualizr *a;
try {
Config cfg(config_path);
a = new Aktualizr(cfg);
a = new Aktualizr(*cfg);
} catch (const std::exception &e) {
std::cerr << "Aktualizr_create exception: " << e.what() << std::endl;
return nullptr;
}
return a;
}

Aktualizr *Aktualizr_create_from_path(const char *config_path) {
try {
Config cfg(config_path);
return Aktualizr_create_from_cfg(&cfg);
} catch (const std::exception &e) {
std::cerr << "Aktualizr_create exception: " << e.what() << std::endl;
return nullptr;
}
}

int Aktualizr_initialize(Aktualizr *a) {
try {
a->Initialize();
Expand All @@ -34,7 +44,28 @@ int Aktualizr_uptane_cycle(Aktualizr *a) {

void Aktualizr_destroy(Aktualizr *a) { delete a; }

Campaign *Aktualizr_campaign_check(Aktualizr *a) {
static void handler_wrapper(const std::shared_ptr<event::BaseEvent> &event, void (*handler)(const char *)) {
if (handler == nullptr) {
std::cerr << "handler_wrapper error: no external handler" << std::endl;
return;
}

(*handler)(event->variant.c_str());
}

int Aktualizr_set_signal_handler(Aktualizr *a, void (*handler)(const char *event_name)) {
try {
auto functor = std::bind(handler_wrapper, std::placeholders::_1, handler);
a->SetSignalHandler(functor);

} catch (const std::exception &e) {
std::cerr << "Aktualizr_set_signal_handler exception: " << e.what() << std::endl;
return -1;
}
return 0;
}

Campaign *Aktualizr_campaigns_check(Aktualizr *a) {
try {
auto r = a->CampaignCheck().get();
if (!r.campaigns.empty()) {
Expand All @@ -47,6 +78,7 @@ Campaign *Aktualizr_campaign_check(Aktualizr *a) {
}
return nullptr;
}

int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c) {
try {
a->CampaignControl(c->id, campaign::Cmd::Accept).get();
Expand All @@ -56,6 +88,7 @@ int Aktualizr_campaign_accept(Aktualizr *a, Campaign *c) {
}
return 0;
}

int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c) {
try {
a->CampaignControl(c->id, campaign::Cmd::Postpone).get();
Expand All @@ -65,6 +98,7 @@ int Aktualizr_campaign_postpone(Aktualizr *a, Campaign *c) {
}
return 0;
}

int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c) {
try {
a->CampaignControl(c->id, campaign::Cmd::Decline).get();
Expand All @@ -74,4 +108,121 @@ int Aktualizr_campaign_decline(Aktualizr *a, Campaign *c) {
}
return 0;
}

void Aktualizr_campaign_free(Campaign *c) { delete c; }

Updates *Aktualizr_updates_check(Aktualizr *a) {
try {
auto r = a->CheckUpdates().get();
return (r.updates.size() > 0) ? new Updates(std::move(r.updates)) : nullptr;
} catch (const std::exception &e) {
std::cerr << "Campaign decline exception: " << e.what() << std::endl;
return nullptr;
}
}

void Aktualizr_updates_free(Updates *u) { delete u; }

size_t Aktualizr_get_targets_num(Updates *u) { return (u == nullptr) ? 0 : u->size(); }

Target *Aktualizr_get_nth_target(Updates *u, size_t n) {
try {
if (u != nullptr) {
return &u->at(n);
} else {
return nullptr;
}
} catch (const std::exception &e) {
std::cerr << "Exception: " << e.what() << std::endl;
return nullptr;
}
}

// TODO: Would it be nicer if t->filename returned const ref?
char *Aktualizr_get_target_name(Target *t) {
if (t != nullptr) {
void *name_ptr = malloc(sizeof(char) * (t->filename().size() + 1));
auto *name = static_cast<char *>(name_ptr);
strncpy(name, t->filename().c_str(), t->filename().size() + 1);
return name;
} else {
return nullptr;
}
}

int Aktualizr_download_target(Aktualizr *a, Target *t) {
try {
a->Download(std::vector<Uptane::Target>({*t})).get();
} catch (const std::exception &e) {
std::cerr << "Campaign decline exception: " << e.what() << std::endl;
return -1;
}
return 0;
}

int Aktualizr_install_target(Aktualizr *a, Target *t) {
try {
a->Install(std::vector<Uptane::Target>({*t})).get();
} catch (const std::exception &e) {
std::cerr << "Campaign decline exception: " << e.what() << std::endl;
return -1;
}
return 0;
}

int Aktualizr_send_manifest(Aktualizr *a, const char *manifest) {
try {
Json::Value custom = Utils::parseJSON(manifest);
bool r = a->SendManifest(custom).get();
return r ? 0 : -1;
} catch (const std::exception &e) {
std::cerr << "Aktualizr_send_manifest exception: " << e.what() << std::endl;
return -1;
}
}

int Aktualizr_send_device_data(Aktualizr *a) {
try {
a->SendDeviceData();
return 0;
} catch (const std::exception &e) {
std::cerr << "Aktualizr_send_device_data exception: " << e.what() << std::endl;
return -1;
}
}

StorageTargetHandle *Aktualizr_open_stored_target(Aktualizr *a, const Target *t) {
if (t == nullptr) {
std::cerr << "Aktualizr_open_stored_target failed: invalid input" << std::endl;
return nullptr;
}

try {
auto handle = a->OpenStoredTarget(*t);
return handle.release();
} catch (const std::exception &e) {
std::cerr << "Aktualizr_open_stored_target exception: " << e.what() << std::endl;
return nullptr;
}
}

size_t Aktualizr_read_stored_target(StorageTargetHandle *handle, uint8_t *buf, size_t size) {
if (handle != nullptr && buf != nullptr) {
return handle->rread(buf, size);
} else {
std::cerr << "Aktualizr_read_stored_target failed: invalid input " << (handle == nullptr ? "handle" : "buffer")
<< std::endl;
return 0;
}
}

int Aktualizr_close_stored_target(StorageTargetHandle *handle) {
if (handle != nullptr) {
handle->rclose();
delete handle;
return 0;
} else {
std::cerr << "Aktualizr_close_stored_target failed: no input handle" << std::endl;
return -1;
}
}
12 changes: 11 additions & 1 deletion src/libaktualizr-c/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ SET(CMAKE_SKIP_RPATH TRUE)

add_executable(${TARGET_NAME} EXCLUDE_FROM_ALL ${SOURCES})
add_dependencies(build_tests ${TARGET_NAME})
target_link_libraries(${TARGET_NAME} aktualizr-c)
target_link_libraries(${TARGET_NAME} aktualizr-c api-test-utils)

aktualizr_source_file_checks(${SOURCES})

add_test(NAME t_c_api_test COMMAND ${TARGET_NAME}
${PROJECT_SOURCE_DIR}/tests/fake_http_server/fake_test_server.py
${PROJECT_BINARY_DIR}/c-api-test-repo
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
set_tests_properties(t_c_api_test PROPERTIES FIXTURES_REQUIRED c_api_test)
set_tests_properties(t_c_api_test PROPERTIES
ENVIRONMENT LD_PRELOAD=${PROJECT_BINARY_DIR}/src/libaktualizr-c/test/api-test-utils/libapi-test-utils.so:${PROJECT_BINARY_DIR}/src/libaktualizr-c/libaktualizr-c.so)

add_subdirectory(api-test-utils EXCLUDE_FROM_ALL)
35 changes: 35 additions & 0 deletions src/libaktualizr-c/test/api-test-utils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
SET(TARGET_NAME api-test-utils)
SET(SOURCES api-test-utils.cc)
SET(HEADERS api-test-utils.h)

SET(CMAKE_SKIP_RPATH TRUE)

add_library(${TARGET_NAME} SHARED ${SOURCES})
target_include_directories(${TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/tests)
target_link_libraries(${TARGET_NAME} testutilities)
add_dependencies(build_tests ${TARGET_NAME})

aktualizr_source_file_checks(${SOURCES} ${HEADERS})



add_executable(uptane_generator_utils uptane-generator-utils.cc)
target_include_directories(uptane_generator_utils PUBLIC ${PROJECT_SOURCE_DIR}/tests)
target_link_libraries(uptane_generator_utils
aktualizr_static_lib
testutilities
uptane_generator_lib
${TEST_LIBS})
add_dependencies(build_tests uptane_generator_utils)

aktualizr_source_file_checks(uptane-generator-utils.cc)

add_test(NAME t_uptane_generator_setup COMMAND uptane_generator_utils
${PROJECT_BINARY_DIR}/src/uptane_generator/uptane-generator
${PROJECT_BINARY_DIR}/c-api-test-repo
${PROJECT_SOURCE_DIR}/tests/test_data/firmware.txt)
set_tests_properties(t_uptane_generator_setup PROPERTIES FIXTURES_SETUP c_api_test)

add_test(NAME t_uptane_generator_cleanup COMMAND uptane_generator_utils
${PROJECT_BINARY_DIR}/c-api-test-repo)
set_tests_properties(t_uptane_generator_cleanup PROPERTIES FIXTURES_CLEANUP c_api_test)
42 changes: 42 additions & 0 deletions src/libaktualizr-c/test/api-test-utils/api-test-utils.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "api-test-utils.h"

#include <boost/process.hpp>
#include "config/config.h"
#include "test_utils.h"

std::string serverAddress;

FakeHttpServer *Run_fake_http_server(const char *serverPath, const char *metaPath) {
std::string port = TestUtils::getFreePort();
serverAddress = "http://127.0.0.1:" + port;

auto *server_handle = new boost::process::child(serverPath, port, "-f", "-m", metaPath);
TestUtils::waitForServer(serverAddress + "/");

return server_handle;
}

void Stop_fake_http_server(FakeHttpServer *server) {
if (server != nullptr && server->valid()) {
delete server;
}
}

Config *Get_test_config(const char *storagePath) {
auto *config = new Config();

config->tls.server = serverAddress;

config->provision.primary_ecu_serial = "CA:FE:A6:D2:84:9D";
config->provision.primary_ecu_hardware_id = "primary_hw";
config->provision.server = serverAddress;
config->provision.provision_path = "tests/test_data/cred.zip";

config->storage.path = storagePath;
config->pacman.type = PackageManager::kNone;

config->postUpdateValues();
return config;
}

void Remove_test_config(Config *config) { delete config; }
27 changes: 27 additions & 0 deletions src/libaktualizr-c/test/api-test-utils/api-test-utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef API_TEST_UTILS_H
#define API_TEST_UTILS_H

#ifdef __cplusplus
#include <boost/process.hpp>
#include "config/config.h"

using Config = Config;
using FakeHttpServer = boost::process::child;

extern "C" {
#else
typedef struct Config Config;
typedef struct FakeHttpServer FakeHttpServer;
#endif

FakeHttpServer* Run_fake_http_server(const char* serverPath, const char* metaPath);
void Stop_fake_http_server(FakeHttpServer* server);

Config* Get_test_config(const char* storagePath);
void Remove_test_config(Config* config);

#ifdef __cplusplus
}
#endif

#endif // API_TEST_UTILS_H
Loading