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: move api_buffer to web/buffer

This commit is contained in:
Steffen Vogel 2017-04-09 16:20:39 +02:00
parent 412f7bc24d
commit 6b8b9e5c1f
5 changed files with 201 additions and 50 deletions

View file

@ -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);

View 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);

View file

@ -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
View file

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

144
lib/web/buffer.c Normal file
View 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;
}