mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
refactor: move api_buffer to web/buffer
This commit is contained in:
parent
412f7bc24d
commit
6b8b9e5c1f
5 changed files with 201 additions and 50 deletions
|
@ -19,7 +19,6 @@ struct super_node;
|
|||
|
||||
struct api;
|
||||
struct api_ressource;
|
||||
struct api_buffer;
|
||||
struct api_session;
|
||||
|
||||
/** Callback type of command function
|
||||
|
@ -49,12 +48,6 @@ struct api {
|
|||
struct super_node *super_node;
|
||||
};
|
||||
|
||||
struct api_buffer {
|
||||
char *buf; /**< A pointer to the buffer. Usually resized via realloc() */
|
||||
size_t size; /**< The allocated size of the buffer. */
|
||||
size_t len; /**< The used length of the buffer. */
|
||||
};
|
||||
|
||||
/** A connection via HTTP REST or WebSockets to issue API actions. */
|
||||
struct api_session {
|
||||
enum api_mode mode;
|
||||
|
@ -102,12 +95,6 @@ int api_session_destroy(struct api_session *s);
|
|||
|
||||
int api_session_run_command(struct api_session *s, json_t *req, json_t **resp);
|
||||
|
||||
/** Send contents of buffer over libwebsockets connection */
|
||||
int api_buffer_send(struct api_buffer *b, struct lws *w, enum lws_write_protocol prot);
|
||||
|
||||
/** Append received data to buffer. */
|
||||
int api_buffer_append(struct api_buffer *b, const char *in, size_t len);
|
||||
|
||||
/** 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);
|
||||
|
||||
|
|
56
include/villas/web/buffer.h
Normal file
56
include/villas/web/buffer.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/** WebSocket buffer.
|
||||
*
|
||||
* @file
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
*********************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include <libwebsockets.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
struct web_buffer {
|
||||
char *buffer; /**< A pointer to the buffer. Usually resized via realloc() */
|
||||
size_t size; /**< The allocated size of the buffer. */
|
||||
size_t len; /**< The used length of the buffer. */
|
||||
size_t prefix; /**< The used length of the buffer. */
|
||||
|
||||
enum lws_write_protocol protocol;
|
||||
|
||||
enum state state;
|
||||
};
|
||||
|
||||
/** Initialize a libwebsockets buffer. */
|
||||
int web_buffer_init(struct web_buffer *b, enum lws_write_protocol prot);
|
||||
|
||||
/** Destroy a libwebsockets buffer. */
|
||||
int web_buffer_destroy(struct web_buffer *b);
|
||||
|
||||
/** Flush the buffers contents to lws_write() */
|
||||
int web_buffer_write(struct web_buffer *b, struct lws *w);
|
||||
|
||||
/** Copy \p len bytes from the beginning of the buffer and copy them to \p out.
|
||||
*
|
||||
* @param out The destination buffer. If NULL, we just remove \p len bytes from the buffer.
|
||||
*/
|
||||
int web_buffer_read(struct web_buffer *b, char *out, size_t len);
|
||||
|
||||
/** Parse JSON from the beginning of the buffer.
|
||||
*
|
||||
* @retval -1 The buffer is empty.
|
||||
* @retval -2 The buffer contains malformed JSON.
|
||||
*/
|
||||
int web_buffer_read_json(struct web_buffer *b, json_t **req);
|
||||
|
||||
/** Append \p len bytes of \p in at the end of the buffer.
|
||||
*
|
||||
* The buffer is automatically resized.
|
||||
*/
|
||||
int web_buffer_append(struct web_buffer *b, const char *in, size_t len);
|
||||
|
||||
/** Append the serialized represetnation of the JSON object \p res at the end of the buffer. */
|
||||
int web_buffer_append_json(struct web_buffer *b, json_t *res);
|
37
lib/api.c
37
lib/api.c
|
@ -11,46 +11,9 @@
|
|||
#include "log.h"
|
||||
#include "config.h"
|
||||
|
||||
static int api_parse_request(struct api_buffer *b, json_t **req)
|
||||
{
|
||||
json_error_t e;
|
||||
|
||||
if (b->len <= 0)
|
||||
return -1;
|
||||
|
||||
*req = json_loadb(b->buf, b->len, JSON_DISABLE_EOF_CHECK, &e);
|
||||
if (!*req)
|
||||
return -1;
|
||||
|
||||
if (e.position < b->len) {
|
||||
void *dst = (void *) b->buf;
|
||||
void *src = (void *) (b->buf + e.position);
|
||||
|
||||
memmove(dst, src, b->len - e.position);
|
||||
|
||||
b->len -= e.position;
|
||||
}
|
||||
else
|
||||
b->len = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int api_unparse_response(struct api_buffer *b, json_t *res)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
retry: len = json_dumpb(res, b->buf + b->len, b->size - b->len, 0);
|
||||
if (len > b->size - b->len) {
|
||||
b->buf = realloc(b->buf, b->len + len);
|
||||
b->size += len;
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
b->len += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int api_session_run_command(struct api_session *s, json_t *json_in, json_t **json_out)
|
||||
{
|
||||
|
|
1
lib/web/Makefile.inc
Normal file
1
lib/web/Makefile.inc
Normal file
|
@ -0,0 +1 @@
|
|||
LIB_SRCS += $(wildcard lib/web/*.c)
|
144
lib/web/buffer.c
Normal file
144
lib/web/buffer.c
Normal file
|
@ -0,0 +1,144 @@
|
|||
/** API buffer for sending and receiving data from libwebsockets.
|
||||
*
|
||||
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
||||
* @copyright 2017, Institute for Automation of Complex Power Systems, EONERC
|
||||
*********************************************************************************/
|
||||
|
||||
#include <jansson.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "assert.h"
|
||||
#include "utils.h"
|
||||
#include "web/buffer.h"
|
||||
|
||||
int web_buffer_init(struct web_buffer *b, enum lws_write_protocol prot)
|
||||
{
|
||||
assert(b->state == STATE_DESTROYED);
|
||||
|
||||
b->protocol = prot;
|
||||
b->size = 0;
|
||||
b->len = 0;
|
||||
b->buffer = NULL;
|
||||
b->prefix = b->protocol == LWS_WRITE_TEXT || b->protocol == LWS_WRITE_BINARY ? LWS_PRE : 0;
|
||||
|
||||
b->state = STATE_INITIALIZED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int web_buffer_destroy(struct web_buffer *b)
|
||||
{
|
||||
if (b->state == STATE_DESTROYED)
|
||||
return 0;
|
||||
|
||||
if (b->buffer)
|
||||
free(b->buffer);
|
||||
|
||||
b->state = STATE_DESTROYED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int web_buffer_write(struct web_buffer *b, struct lws *w)
|
||||
{
|
||||
int ret, len, sent = 0;
|
||||
unsigned char *chunk;
|
||||
|
||||
assert(b->state == STATE_INITIALIZED);
|
||||
|
||||
if (b->len <= 0)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
chunk = (unsigned char *) b->buffer + b->prefix + sent;
|
||||
len = strlen(b->buffer + b->prefix);
|
||||
|
||||
ret = lws_write(w, chunk, len, b->protocol);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
sent += ret + 1;
|
||||
} while (sent < b->len);
|
||||
|
||||
web_buffer_read(b, NULL, sent); /* drop sent bytes from the buffer*/
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
int web_buffer_read(struct web_buffer *b, char *out, size_t len)
|
||||
{
|
||||
assert(b->state == STATE_INITIALIZED);
|
||||
|
||||
if (len > b->len)
|
||||
len = b->len;
|
||||
|
||||
if (out)
|
||||
memcpy(out, b->buffer + b->prefix, len);
|
||||
|
||||
memmove(b->buffer + b->prefix, b->buffer + b->prefix + len, b->len - len);
|
||||
b->len -= len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int web_buffer_read_json(struct web_buffer *b, json_t **req)
|
||||
{
|
||||
json_error_t e;
|
||||
|
||||
assert(b->state == STATE_INITIALIZED);
|
||||
|
||||
if (b->len <= 0)
|
||||
return -1;
|
||||
|
||||
*req = json_loadb(b->buffer + b->prefix, b->len, JSON_DISABLE_EOF_CHECK, &e);
|
||||
if (!*req)
|
||||
return -2;
|
||||
|
||||
web_buffer_read(b, NULL, e.position);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int web_buffer_append(struct web_buffer *b, const char *in, size_t len)
|
||||
{
|
||||
assert(b->state == STATE_INITIALIZED);
|
||||
|
||||
/* We append a \0 to split messages */
|
||||
len++;
|
||||
|
||||
if (b->size < b->len + len) {
|
||||
b->buffer = realloc(b->buffer, b->prefix + b->len + len);
|
||||
if (!b->buffer)
|
||||
return -1;
|
||||
|
||||
b->size = b->len + len;
|
||||
}
|
||||
|
||||
memcpy(b->buffer + b->prefix + b->len, in, len);
|
||||
b->len += len;
|
||||
b->buffer[b->len+b->prefix] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int web_buffer_append_json(struct web_buffer *b, json_t *res)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
assert(b->state == STATE_INITIALIZED);
|
||||
|
||||
retry: len = json_dumpb(res, b->buffer + b->prefix + b->len, b->size - b->len, 0) + 1;
|
||||
if (b->size < b->len + len) {
|
||||
b->buffer = realloc(b->buffer, b->prefix + b->len + len);
|
||||
if (!b->buffer)
|
||||
return -1;
|
||||
|
||||
b->size = b->len + len;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
b->len += len;
|
||||
b->buffer[b->len+b->prefix] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue