Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ec61c17
Add basic C++ HTTP framework, which currently uses ulfius
Oct 5, 2018
5aa6c20
Move HTTP framework
Oct 5, 2018
52ba37f
Fix obvious bugs (list below)
Oct 9, 2018
697fac2
Add plugin manager, and lwm2m framework, implement http framework wra…
Oct 19, 2018
9127b49
Merge branch 'plugin-manager' of https://github.com/8devices/wakaama …
Oct 19, 2018
4bd15fc
Implement plugin destruction function in plugin API
Oct 19, 2018
6e32f88
Change json_string_length() call to strnlen(json_string_value())
Oct 19, 2018
5f1f2d2
Clean up http framework, separate headers and source files
Oct 22, 2018
25ed008
Changed request and response object initialization for easier object …
taubel Oct 22, 2018
436266c
Improve ulfius http framework names, clean up interfaces
Oct 23, 2018
c863153
Clean-up lwm2m framework interface, update basic lwm2m framework
Oct 23, 2018
e8980f0
Update plugins lifetime, change lwm2m context (&rest to rest.lwm2m)
Oct 23, 2018
8a17a54
Add test plugin to test GET, PUT & POST requests
Oct 24, 2018
8c86225
Merge branch 'plugin-manager' of https://github.com/8devices/wakaama …
Oct 24, 2018
3efe2f5
Fix merge conflict
Oct 24, 2018
1ce6554
Remove debug prints
Oct 26, 2018
6b36e7f
Update test plugin response headers
Oct 26, 2018
9039298
Add plugins manager coverage tests
Oct 26, 2018
22ee26e
Remove debug code fragment
Oct 26, 2018
0bc231d
Go to BASE_DIR in beggining of every function that depends on path
Oct 26, 2018
8cfbf4f
Fix tests (base dir now is full path), add plugins.cfg
Oct 26, 2018
2c38f26
Add more directory paths
Oct 26, 2018
48fad35
Add done() calls to before and after sections
Oct 26, 2018
2aa67c2
Do not set status code multiple times
Oct 26, 2018
2e5aeb1
Build plugins in separate directory instead main plugin directory
Oct 26, 2018
5a20a22
Do not return status code 500 on all errors
Oct 26, 2018
4346945
Copy server object instead of modifying original
Oct 26, 2018
781f3c9
Change mkdir -P flag to valid lowercase -p flag
Oct 26, 2018
6a7cc24
Fix plugins tests
Oct 26, 2018
5f54f39
Remove hardcoded GCOV strip value to improve flexibility
Oct 29, 2018
4fb35f9
Add some invalid plugin configurations to increase coverage
Oct 29, 2018
69f7a5d
Add some invalid plugin configurations to increase coverage
Oct 29, 2018
dbd3ba7
Do not stop loading plugins after one plugin failure
Oct 29, 2018
3a8af5c
Modify plugins section error descriptions
Oct 29, 2018
851e0f1
Remove comments from test plugin CMakeLists.txt
Oct 29, 2018
7d19296
Build all test plugins instead one
Oct 29, 2018
bb54e79
Add more plugins for tests
Oct 29, 2018
a22d336
Add new test plugins to configuration file
Oct 29, 2018
354de3b
Abort tests if any test plugin build fails
Oct 29, 2018
42bd611
Check if create() and delete() pointers aren't NULL in plugin api
Oct 29, 2018
97a9dd0
Add test plugin without destroy() in plugin api
Oct 29, 2018
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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ script:
after_script:
- bash <(curl -s https://codecov.io/bash) -cZF secure -p secure -s ./
- bash <(curl -s https://codecov.io/bash) -cZF regular -p regular -s ./
- bash <(curl -s https://codecov.io/bash) -cZF plugins -p plugins -s ./
10 changes: 9 additions & 1 deletion examples/rest-server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ if(DTLS)
message(FATAL_ERROR "DTLS option is not supported." )
endif()

include(${CMAKE_CURRENT_LIST_DIR}/../../plugin-manager/plugin-manager.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/../../core/wakaama.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/../shared/shared.cmake)

Expand Down Expand Up @@ -42,14 +43,21 @@ SET(SOURCES
${CMAKE_CURRENT_LIST_DIR}/logging.c
${CMAKE_CURRENT_LIST_DIR}/settings.c
${CMAKE_CURRENT_LIST_DIR}/security.c
${PLUGIN_MANAGER_SOURCES}
)

add_executable(${PROJECT_NAME} ${SOURCES} ${WAKAAMA_SOURCES} ${SHARED_SOURCES})
find_library(ULFIUS_LIB ulfius)
find_library(JANSSON_LIB jansson)
find_library(JWT_LIB jwt)
target_compile_options(restserver PRIVATE "-Wall" "-pthread")
target_link_libraries(restserver pthread "${ULFIUS_LIB}" "${JANSSON_LIB}" "${JWT_LIB}")
target_link_libraries(restserver
pthread
${ULFIUS_LIB}
${JANSSON_LIB}
${JWT_LIB}
${PLUGIN_MANAGER_LIBRARIES}
)


if(CODE_COVERAGE)
Expand Down
50 changes: 49 additions & 1 deletion examples/rest-server/restserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#include "rest-list.h"
#include "rest-authentication.h"

#include "../../plugin-manager/include/basic_plugin_manager.h"
#include "../../plugin-manager/include/basic_plugin_manager_core.h"

static volatile int restserver_quit;
static void sigint_handler(int signo)
{
Expand Down Expand Up @@ -95,6 +98,41 @@ static void init_signals(void)
}
}

static int load_plugins(CBasicPluginManager *plugin_manager, rest_list_t *plugins_list)
{
rest_list_entry_t *entry;
plugin_settings_t *plugin;
int load_is_successful;

for (entry = plugins_list->head; entry != NULL; entry = entry->next)
{
plugin = entry->data;
load_is_successful = BasicPluginManager_loadPlugin(plugin_manager, plugin->path, plugin->name);

if (load_is_successful)
{
log_message(LOG_LEVEL_INFO, "Successfuly loaded plugin: \"%s\"\n", plugin->name);
}
else
{
log_message(LOG_LEVEL_ERROR, "Failed to load plugin: \"%s\"\n", plugin->name);
}
}

return 0;
}
void plugins_cleanup(plugins_settings_t *plugins_settings)
{
rest_list_entry_t *entry;
plugin_settings_t *plugin;

for (entry = plugins_settings->plugins_list->head; entry != NULL; entry = entry->next)
{
plugin = entry->data;
free(plugin);
}
free(plugins_settings->plugins_list);
}

const char *binding_to_string(lwm2m_binding_t bind)
{
Expand Down Expand Up @@ -295,6 +333,7 @@ int main(int argc, char *argv[])
},
};

settings.plugins.plugins_list = rest_list_new();
settings.http.security.jwt.users_list = rest_list_new();
settings.http.security.jwt.secret_key = (unsigned char *) malloc(
settings.http.security.jwt.secret_key_length * sizeof(unsigned char));
Expand Down Expand Up @@ -332,9 +371,11 @@ int main(int argc, char *argv[])

lwm2m_set_monitoring_callback(rest.lwm2m, client_monitor_cb, &rest);

/* REST server section */
struct _u_instance instance;

CBasicPluginManagerCore *plugin_manager_core = new_BasicPluginManagerCore(&instance, rest.lwm2m);
CBasicPluginManager *plugin_manager = new_BasicPluginManager(plugin_manager_core);

log_message(LOG_LEVEL_INFO, "Creating http socket on port %u\n", settings.http.port);
if (ulfius_init_instance(&instance, settings.http.port, NULL, NULL) != U_OK)
{
Expand All @@ -347,6 +388,9 @@ int main(int argc, char *argv[])
* https://docs.mbed.com/docs/mbed-device-connector-web-interfaces/en/latest/api-reference/
*/

// Plugins
load_plugins(plugin_manager, settings.plugins.plugins_list);

// Endpoints
ulfius_add_endpoint_by_val(&instance, "GET", "/endpoints", NULL, 10,
&rest_endpoints_cb, &rest);
Expand Down Expand Up @@ -498,10 +542,14 @@ int main(int argc, char *argv[])
ulfius_stop_framework(&instance);
ulfius_clean_instance(&instance);

delete_BasicPluginManager(plugin_manager);
delete_BasicPluginManagerCore(plugin_manager_core);

lwm2m_close(rest.lwm2m);
rest_cleanup(&rest);

jwt_cleanup(&settings.http.security.jwt);
plugins_cleanup(&settings.plugins);

return 0;
}
Expand Down
90 changes: 90 additions & 0 deletions examples/rest-server/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,92 @@ static void set_logging_settings(json_t *j_section, logging_settings_t *settings
}
}

static int set_plugin_settings(json_t *j_plugin_settings, rest_list_t *plugins_list)
{
rest_list_entry_t *entry;
plugin_settings_t *plugin, *plugin_entry;
size_t plugin_name_length, plugin_path_length;
json_t *j_name, *j_path;

j_name = json_object_get(j_plugin_settings, "name");
j_path = json_object_get(j_plugin_settings, "path");

if (!json_is_string(j_name))
{
fprintf(stdout, "Plugin configured without name.\n");
return 1;
}
plugin_name_length = strnlen(json_string_value(j_name), J_MAX_LENGTH_PLUGIN_NAME);
if (plugin_name_length == 0 || plugin_name_length == J_MAX_LENGTH_PLUGIN_NAME)
{
fprintf(stdout, "Plugin name length is invalid\n");
return 1;
}

if (!json_is_string(j_path))
{
fprintf(stdout, "Plugin configured without path.\n");
return 1;
}
plugin_path_length = strnlen(json_string_value(j_path), J_MAX_LENGTH_PLUGIN_NAME);
if (plugin_path_length == 0 || plugin_path_length == J_MAX_LENGTH_PLUGIN_PATH)
{
fprintf(stdout, "Plugin path length is invalid\n");
return 1;
}

plugin = malloc(sizeof(plugin_settings_t));

plugin->name = json_string_value(j_name);
plugin->path = json_string_value(j_path);

for (entry = plugins_list->head; entry != NULL; entry = entry->next)
{
plugin_entry = entry->data;
if (strncmp(plugin_entry->name, plugin->name, J_MAX_LENGTH_PLUGIN_NAME) == 0)
{
fprintf(stdout, "Duplicate plugin name \"%s\" entry found.\n", plugin->name);

free(plugin);
return 1;
}
}

rest_list_add(plugins_list, plugin);

return 0;
}

static int set_plugins_settings(json_t *j_section, plugins_settings_t *plugins_settings)
{
int plugin_status, plugins_status = 0;
size_t plugin_index;
const char *section_name = "plugins";
json_t *j_plugin_settings;

json_array_foreach(j_section, plugin_index, j_plugin_settings)
{
if (!json_is_object(j_plugin_settings))
{
fprintf(stdout, "\"%s\" section contains invalid type value\n", section_name);
plugins_status = 1;
}

plugin_status = set_plugin_settings(j_plugin_settings, plugins_settings->plugins_list);
if (plugin_status != 0)
{
plugins_status = plugin_status;
}
}

if (plugins_status != 0)
{
fprintf(stdout, "Not all entries in \"%s\" section were configured corretly!\n", section_name);
}

return plugins_status;
}

int read_config(char *config_name, settings_t *settings)
{
json_error_t error;
Expand Down Expand Up @@ -361,6 +447,10 @@ int read_config(char *config_name, settings_t *settings)
{
set_logging_settings(j_value, &settings->logging);
}
else if (strcasecmp(section, "plugins") == 0)
{
set_plugins_settings(j_value, &settings->plugins);
}
else
{
fprintf(stdout, "Unrecognised configuration file section: %s\n", section);
Expand Down
14 changes: 14 additions & 0 deletions examples/rest-server/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "logging.h"
#include "security.h"

#include "../../plugin-manager/include/basic_plugin_manager.h"

typedef struct
{
uint16_t port;
Expand All @@ -44,11 +46,23 @@ typedef struct
uint16_t port;
} coap_settings_t;

typedef struct
{
const char *name;
const char *path;
} plugin_settings_t;

typedef struct
{
rest_list_t *plugins_list;
} plugins_settings_t;

typedef struct
{
http_settings_t http;
coap_settings_t coap;
logging_settings_t logging;
plugins_settings_t plugins;
} settings_t;

int read_config(char *config_name, settings_t *settings);
Expand Down
12 changes: 12 additions & 0 deletions http-framework/http-framework.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Provides HTTP_FRAMEWORK_SOURCES_DIR, HTTP_FRAMEWORK_SOURCES and HTTP_FRAMEWORK_LIBRARIES variables.

set(HTTP_FRAMEWORK_SOURCES_DIR ${CMAKE_CURRENT_LIST_DIR}/src)
set(HTTP_FRAMEWORK_SOURCES
${HTTP_FRAMEWORK_SOURCES_DIR}/ulfius_request.cpp
${HTTP_FRAMEWORK_SOURCES_DIR}/ulfius_response.cpp
${HTTP_FRAMEWORK_SOURCES_DIR}/ulfius_http_framework.cpp
)

find_library(ULFIUS_LIB ulfius)

set (HTTP_FRAMEWORK_LIBRARIES ${ULFIUS_LIB})
41 changes: 41 additions & 0 deletions http-framework/include/callback_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* MIT License
*
* Copyright (c) 2018 8devices
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/


#ifndef CALLBACK_HANDLER_HPP
#define CALLBACK_HANDLER_HPP

typedef int (*ulfius_callback_function_t)(const struct _u_request *, struct _u_response *, void *);

class CallbackHandler
{
public:
CallbackHandler(callback_function_t handler_function, void *handler_context)
: function(handler_function), context(handler_context)
{ }
callback_function_t function;
void *context;
};

#endif // CALLBACK_HANDLER_HPP
51 changes: 51 additions & 0 deletions http-framework/include/http_framework.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* MIT License
*
* Copyright (c) 2018 8devices
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef HTTP_FRAMEWORK_H
#define HTTP_FRAMEWORK_H

#ifdef __cplusplus
extern "C" {
#endif

#include "request.h"
#include "response.h"

typedef CStatusCode (*c_callback_function_t)(CRequest *, CResponse *, void*);

struct CHttpFramework;
typedef struct CHttpFramework CHttpFramework;

void HttpFramework_addHandler(CHttpFramework *c_http_framework,
const char *method,
const char *url_prefix,
const unsigned int priority,
c_callback_function_t c_handler_function,
void *handler_context);

#ifdef __cplusplus
}
#endif

#endif // HTTP_FRAMEWORK_H
Loading