1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

refactor: api_ressource => api_action and introduced new subdirectories

This commit is contained in:
Steffen Vogel 2017-04-09 16:24:00 +02:00
parent 5c6188ccc2
commit 580189b678
8 changed files with 106 additions and 243 deletions

View file

@ -20,7 +20,7 @@ struct lws;
struct super_node;
struct api;
struct api_ressource;
struct api_action;
/** Callback type of command function
*
@ -29,7 +29,7 @@ struct api_ressource;
* @param[out] resp JSON command response.
* @param[in] i Execution context.
*/
typedef int (*api_cb_t)(struct api_ressource *c, json_t *args, json_t **resp, struct api_session *s);
typedef int (*api_cb_t)(struct api_action *c, json_t *args, json_t **resp, struct api_session *s);
struct api {
struct list sessions; /**< List of currently active connections */
@ -39,11 +39,8 @@ struct api {
struct super_node *super_node;
};
/** Command descriptor
*
* Every command is described by a descriptor.
*/
struct api_ressource {
/** API action descriptor */
struct api_action {
api_cb_t cb;
};
@ -59,12 +56,6 @@ int api_start(struct api *a);
int api_stop(struct api *a);
int api_session_init(struct api_session *s, struct api *a, enum api_mode m);
int api_session_destroy(struct api_session *s);
int api_session_run_command(struct api_session *s, json_t *req, json_t **resp);
/** Libwebsockets callback for "api" endpoint */
int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);

View file

@ -48,7 +48,7 @@ struct plugin {
int (*unload)(struct plugin *p);
union {
struct api_ressource api;
struct api_action api;
struct node_type node;
struct fpga_ip_type ip;
struct hook_type hook;

219
lib/api.c
View file

@ -6,109 +6,70 @@
#include <libwebsockets.h>
#include "plugin.h"
#include "api.h"
#include "log.h"
#include "web.h"
#include "config.h"
{
#include "assert.h"
#include "compat.h"
int api_ws_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
//struct api_session *s = (struct api_session *) user;
switch (reason) {
default:
break;
}
return 0;
}
int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
int ret;
struct web *w = lws_context_user(lws_get_context(wsi));
struct api_session *s = (struct api_session *) user;
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: {
struct web *w = (struct web *) lws_context_user(lws_get_context(wsi));
if (w->api == NULL)
return -1; /** @todo return error message */
api_session_init(s, w->api, API_MODE_WS);
break;
}
case LWS_CALLBACK_HTTP: {
struct web *w = (struct web *) lws_context_user(lws_get_context(wsi));
char *uri = (char *) in;
case LWS_CALLBACK_ESTABLISHED:
if (w->api == NULL) {
lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *) "API disabled", strlen("API disabled"));
return -1;
}
/* Parse request URI */
ret = sscanf(uri, "/api/v%d", (int *) &s->version);
char uri[64];
lws_hdr_copy(wsi, uri, sizeof(uri), WSI_TOKEN_GET_URI); /* The path component of the*/
ret = sscanf(uri, "/v%d", (int *) &s->version);
if (ret != 1)
return -1;
debug(LOG_API, "New REST API session initiated: version = %d", s->version);
api_session_init(s, w->api, API_MODE_HTTP);
/* Prepare HTTP response header */
const char headers[] = "HTTP/1.1 200 OK\r\n"
"Content-type: application/json\r\n"
"User-agent: " USER_AGENT "\r\n"
"\r\n";
api_buffer_append(&s->response.headers, headers, sizeof(headers)-1);
/* book us a LWS_CALLBACK_HTTP_WRITEABLE callback */
lws_callback_on_writable(wsi);
ret = api_session_init(s, w->api, API_MODE_WS);
if (ret)
return -1;
debug(LOG_API, "New API session initiated: version=%d, mode=websocket", s->version);
break;
}
case LWS_CALLBACK_CLIENT_RECEIVE:
case LWS_CALLBACK_RECEIVE:
case LWS_CALLBACK_HTTP_BODY: {
api_buffer_append(&s->request.body, in, len);
case LWS_CALLBACK_CLOSED:
ret = api_session_destroy(s);
if (ret)
return -1;
json_t *req, *resp;
while (api_parse_request(&s->request.body, &req) == 1) {
api_session_run_command(s, req, &resp);
api_unparse_response(&s->response.body, resp);
lws_callback_on_writable(wsi);
}
debug(LOG_API, "Closed API session");
break;
}
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
s->completed = true;
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
case LWS_CALLBACK_HTTP_WRITEABLE:
/* We send headers only in HTTP mode */
if (s->mode == API_MODE_HTTP)
api_buffer_send(&s->response.headers, wsi, LWS_WRITE_HTTP_HEADERS);
web_buffer_write(&s->response.body, wsi);
api_buffer_send(&s->response.body, wsi, LWS_WRITE_HTTP);
if (s->completed && s->response.body.len == 0)
return -1;
break;
case LWS_CALLBACK_RECEIVE:
web_buffer_append(&s->request.body, in, len);
json_t *req, *resp;
while (web_buffer_read_json(&s->request.body, &req) >= 0) {
api_session_run_command(s, req, &resp);
web_buffer_append_json(&s->response.body, resp);
lws_callback_on_writable(wsi);
}
break;
default:
return 0;
@ -117,32 +78,75 @@ int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void
return 0;
}
int api_buffer_send(struct api_buffer *b, struct lws *w, enum lws_write_protocol prot)
int api_http_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
{
int sent;
if (b->len <= 0)
return 0;
int ret;
sent = lws_write(w, (unsigned char *) b->buf, b->len, prot);
if (sent > 0) {
memmove(b->buf, b->buf + sent, sent);
b->len -= sent;
struct web *w = lws_context_user(lws_get_context(wsi));
struct api_session *s = (struct api_session *) user;
switch (reason) {
case LWS_CALLBACK_HTTP:
if (w->api == NULL) {
lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *) "API disabled", strlen("API disabled"));
return -1;
}
/* Parse request URI */
ret = sscanf(in, "/api/v%d", (int *) &s->version);
if (ret != 1)
return -1;
ret = api_session_init(s, w->api, API_MODE_HTTP);
if (ret)
return -1;
debug(LOG_API, "New API session initiated: version=%d, mode=http", s->version);
/* Prepare HTTP response header */
const char headers[] = "HTTP/1.1 200 OK\r\n"
"Content-type: application/json\r\n"
"User-agent: " USER_AGENT "\r\n"
"\r\n";
web_buffer_append(&s->response.headers, headers, sizeof(headers)-1);
lws_callback_on_writable(wsi);
break;
case LWS_CALLBACK_CLOSED_HTTP:
ret = api_session_destroy(s);
if (ret)
return -1;
break;
case LWS_CALLBACK_HTTP_BODY:
web_buffer_append(&s->request.body, in, len);
json_t *req, *resp;
while (web_buffer_read_json(&s->request.body, &req) == 1) {
api_session_run_command(s, req, &resp);
web_buffer_append_json(&s->response.body, resp);
lws_callback_on_writable(wsi);
}
break;
case LWS_CALLBACK_HTTP_BODY_COMPLETION:
s->completed = true;
break;
case LWS_CALLBACK_HTTP_WRITEABLE:
web_buffer_write(&s->response.headers, wsi);
web_buffer_write(&s->response.body, wsi);
if (s->completed && s->response.body.len == 0)
return -1;
break;
default:
return 0;
}
return sent;
}
int api_buffer_append(struct api_buffer *b, const char *in, size_t len)
{
b->buf = realloc(b->buf, b->len + len);
if (!b->buf)
return -1;
memcpy(b->buf + b->len, in, len);
b->len += len;
return 0;
}
@ -186,26 +190,3 @@ int api_stop(struct api *a)
return 0;
}
int api_session_init(struct api_session *s, struct api *a, enum api_mode m)
{
s->mode = m;
s->api = a;
s->completed = false;
s->request.body =
s->response.body =
s->response.headers = (struct api_buffer) {
.buf = NULL,
.size = 0,
.len = 0
};
return 0;
}
int api_session_destroy(struct api_session *s)
{
return 0;
}

View file

@ -1 +0,0 @@
LIB_SRCS += $(wildcard lib/apis/*.c)

View file

@ -1,31 +0,0 @@
/** The "config" command
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
*********************************************************************************/
#include <libconfig.h>
#include "api.h"
#include "utils.h"
#include "plugin.h"
static int api_config(struct api_ressource *h, json_t *args, json_t **resp, struct api_session *s)
{
config_setting_t *cfg_root = config_root_setting(&s->api->super_node->cfg);
*resp = cfg_root ? config_to_json(cfg_root) : json_object();
return 0;
}
static struct plugin p = {
.name = "config",
.description = "retrieve current VILLASnode configuration",
.type = PLUGIN_TYPE_API,
.api.cb = api_config
};
REGISTER_PLUGIN(&p)

View file

@ -1,52 +0,0 @@
/** The "nodes" command
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
*********************************************************************************/
#include <jansson.h>
#include "plugin.h"
#include "api.h"
#include "node.h"
#include "utils.h"
extern struct list nodes;
static int api_nodes(struct api_ressource *r, json_t *args, json_t **resp, struct api_session *s)
{
json_t *json_nodes = json_array();
for (size_t i = 0; i < list_length(&s->api->super_node->nodes); i++) {
struct node *n = list_at(&s->api->super_node->nodes, i);
json_t *json_node = json_pack("{ s: s, s: i, s: i, s: i, s: i }",
"name", node_name_short(n),
"state", n->state,
"vectorize", n->vectorize,
"affinity", n->affinity,
"id", i
);
/* Add all additional fields of node here.
* This can be used for metadata */
json_object_update(json_node, config_to_json(n->cfg));
json_array_append_new(json_nodes, json_node);
}
*resp = json_nodes;
return 0;
}
static struct plugin p = {
.name = "nodes",
.description = "retrieve list of all known nodes",
.type = PLUGIN_TYPE_API,
.api.cb = api_nodes
};
REGISTER_PLUGIN(&p)

View file

@ -1,25 +0,0 @@
/** The "reload" command
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
* Unauthorized copying of this file, via any medium is strictly prohibited.
*********************************************************************************/
#include "plugin.h"
#include "api.h"
/** @todo not implemented yet */
static int api_reload(struct api_ressource *h, json_t *args, json_t **resp, struct api_session *s)
{
return -1;
}
static struct plugin p = {
.name = "reload",
.description = "restart VILLASnode with new configuration",
.type = PLUGIN_TYPE_API,
.api.cb = api_reload
};
REGISTER_PLUGIN(&p)

View file

@ -12,7 +12,7 @@
#include "utils.h"
#include "log.h"
#include "web.h"
#include "api.h"
#include "api/session.h"
#include "nodes/websocket.h"