Files
neuron/plugins/restful/rw_handle.c
T
2021-12-09 19:07:26 +08:00

343 lines
9.8 KiB
C

#include <pthread.h>
#include <stdlib.h>
#include <sys/queue.h>
#include "neu_log.h"
#include "neu_plugin.h"
#include "json/neu_json_fn.h"
#include "json/neu_json_rw.h"
#include "handle.h"
#include "http.h"
#include "rw_handle.h"
struct cmd_ctx {
uint32_t event_id;
nng_aio *aio;
TAILQ_ENTRY(cmd_ctx) node;
};
TAILQ_HEAD(, cmd_ctx) read_cmd_ctxs;
TAILQ_HEAD(, cmd_ctx) write_cmd_ctxs;
static pthread_mutex_t read_ctx_mtx;
static pthread_mutex_t write_ctx_mtx;
static void read_add_ctx(uint32_t event_id, nng_aio *aio);
static void write_add_ctx(uint32_t event_id, nng_aio *aio);
static struct cmd_ctx *read_find_ctx(uint32_t event_id);
static struct cmd_ctx *write_find_ctx(uint32_t event_id);
void handle_rw_init()
{
TAILQ_INIT(&read_cmd_ctxs);
TAILQ_INIT(&write_cmd_ctxs);
pthread_mutex_init(&read_ctx_mtx, NULL);
pthread_mutex_init(&write_ctx_mtx, NULL);
}
void handle_rw_uninit()
{
struct cmd_ctx *ctx = NULL;
pthread_mutex_lock(&read_ctx_mtx);
ctx = TAILQ_FIRST(&read_cmd_ctxs);
while (ctx != NULL) {
TAILQ_REMOVE(&read_cmd_ctxs, ctx, node);
nng_aio_finish(ctx->aio, 0);
free(ctx);
ctx = TAILQ_FIRST(&read_cmd_ctxs);
}
pthread_mutex_unlock(&read_ctx_mtx);
pthread_mutex_lock(&write_ctx_mtx);
ctx = TAILQ_FIRST(&write_cmd_ctxs);
while (ctx != NULL) {
TAILQ_REMOVE(&write_cmd_ctxs, ctx, node);
nng_aio_finish(ctx->aio, 0);
free(ctx);
ctx = TAILQ_FIRST(&write_cmd_ctxs);
}
pthread_mutex_unlock(&write_ctx_mtx);
pthread_mutex_destroy(&read_ctx_mtx);
pthread_mutex_destroy(&write_ctx_mtx);
}
static void read_add_ctx(uint32_t event_id, nng_aio *aio)
{
struct cmd_ctx *ctx = calloc(1, sizeof(struct cmd_ctx));
pthread_mutex_lock(&read_ctx_mtx);
ctx->aio = aio;
ctx->event_id = event_id;
TAILQ_INSERT_TAIL(&read_cmd_ctxs, ctx, node);
pthread_mutex_unlock(&read_ctx_mtx);
}
static void write_add_ctx(uint32_t event_id, nng_aio *aio)
{
struct cmd_ctx *ctx = calloc(1, sizeof(struct cmd_ctx));
pthread_mutex_lock(&write_ctx_mtx);
ctx->aio = aio;
ctx->event_id = event_id;
TAILQ_INSERT_TAIL(&write_cmd_ctxs, ctx, node);
pthread_mutex_unlock(&write_ctx_mtx);
}
static struct cmd_ctx *read_find_ctx(uint32_t event_id)
{
struct cmd_ctx *ctx = NULL;
struct cmd_ctx *ret = NULL;
pthread_mutex_lock(&read_ctx_mtx);
TAILQ_FOREACH(ctx, &read_cmd_ctxs, node)
{
if (ctx->event_id == event_id) {
TAILQ_REMOVE(&read_cmd_ctxs, ctx, node);
ret = ctx;
break;
}
}
pthread_mutex_unlock(&read_ctx_mtx);
return ret;
}
static struct cmd_ctx *write_find_ctx(uint32_t event_id)
{
struct cmd_ctx *ctx = NULL;
struct cmd_ctx *ret = NULL;
pthread_mutex_lock(&write_ctx_mtx);
TAILQ_FOREACH(ctx, &write_cmd_ctxs, node)
{
if (ctx->event_id == event_id) {
TAILQ_REMOVE(&write_cmd_ctxs, ctx, node);
ret = ctx;
break;
}
}
pthread_mutex_unlock(&write_ctx_mtx);
return ret;
}
void handle_read(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
REST_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_read_req_t, neu_json_decode_read_req, {
neu_taggrp_config_t *config = neu_system_find_group_config(
plugin, req->node_id, req->group_config_name);
uint32_t event_id = neu_plugin_get_event_id(plugin);
read_add_ctx(event_id, aio);
neu_plugin_send_read_cmd(plugin, event_id, req->node_id, config);
})
}
void handle_write(nng_aio *aio)
{
neu_plugin_t *plugin = neu_rest_get_plugin();
REST_PROCESS_HTTP_REQUEST_VALIDATE_JWT(
aio, neu_json_write_req_t, neu_json_decode_write_req, {
neu_taggrp_config_t *config = neu_system_find_group_config(
plugin, req->node_id, req->group_config_name);
neu_data_val_t *data = neu_parse_write_req_to_val(req);
uint32_t event_id = neu_plugin_get_event_id(plugin);
write_add_ctx(event_id, aio);
neu_plugin_send_write_cmd(plugin, event_id, req->node_id, config,
data);
})
}
void handle_read_resp(void *cmd_resp)
{
neu_request_t * req = (neu_request_t *) cmd_resp;
struct cmd_ctx * ctx = read_find_ctx(req->req_id);
neu_reqresp_read_resp_t *resp = (neu_reqresp_read_resp_t *) req->buf;
neu_fixed_array_t * array = NULL;
neu_json_read_resp_t api_res = { 0 };
char * result = NULL;
neu_int_val_t * iv = NULL;
int32_t error = 0;
log_info("read resp id: %d, ctx: %p", req->req_id, ctx);
assert(ctx != NULL);
neu_dvalue_get_ref_array(resp->data_val, &array);
iv = (neu_int_val_t *) neu_fixed_array_get(array, 0);
assert(iv->key == 0);
assert(neu_dvalue_get_value_type(iv->val) == NEU_DTYPE_ERRORCODE);
neu_dvalue_get_errorcode(iv->val, &error);
if (error != 0) {
NEU_JSON_RESPONSE_ERROR(
error, { http_response(ctx->aio, error_code.error, result_error); })
free(ctx);
return;
}
api_res.n_tag = array->length - 1;
api_res.tags = calloc(api_res.n_tag, sizeof(neu_json_read_resp_tag_t));
for (size_t i = 1; i < array->length; i++) {
iv = (neu_int_val_t *) neu_fixed_array_get(array, i);
api_res.tags[i - 1].id = iv->key;
switch (neu_dvalue_get_value_type(iv->val)) {
case NEU_DTYPE_BIT: {
uint8_t bit = 0;
neu_dvalue_get_bit(iv->val, &bit);
api_res.tags[i - 1].t = NEU_JSON_BIT;
api_res.tags[i - 1].value.val_bit = bit;
break;
}
case NEU_DTYPE_INT8: {
int8_t i8 = 0;
neu_dvalue_get_int8(iv->val, &i8);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = i8;
break;
}
case NEU_DTYPE_UINT8: {
uint8_t u8 = 0;
neu_dvalue_get_uint8(iv->val, &u8);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = u8;
break;
}
case NEU_DTYPE_BOOL: {
bool b = true;
neu_dvalue_get_bool(iv->val, &b);
api_res.tags[i - 1].t = NEU_JSON_BOOL;
api_res.tags[i - 1].value.val_bool = b;
break;
}
case NEU_DTYPE_UINT16: {
uint16_t u16 = 0;
neu_dvalue_get_uint16(iv->val, &u16);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = u16;
break;
}
case NEU_DTYPE_INT16: {
int16_t i16 = 0;
neu_dvalue_get_int16(iv->val, &i16);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = i16;
break;
}
case NEU_DTYPE_INT32: {
int32_t i32 = 0;
neu_dvalue_get_int32(iv->val, &i32);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = i32;
break;
}
case NEU_DTYPE_UINT32: {
uint32_t u32 = 0;
neu_dvalue_get_uint32(iv->val, &u32);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = u32;
break;
}
case NEU_DTYPE_INT64: {
int64_t i64 = 0;
neu_dvalue_get_int64(iv->val, &i64);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = i64;
break;
}
case NEU_DTYPE_UINT64: {
uint64_t u64 = 0;
neu_dvalue_get_uint64(iv->val, &u64);
api_res.tags[i - 1].t = NEU_JSON_INT;
api_res.tags[i - 1].value.val_int = u64;
break;
}
case NEU_DTYPE_FLOAT: {
float f32 = 0;
neu_dvalue_get_float(iv->val, &f32);
api_res.tags[i - 1].t = NEU_JSON_FLOAT;
api_res.tags[i - 1].value.val_float = f32;
break;
}
case NEU_DTYPE_DOUBLE: {
double d64 = 0;
neu_dvalue_get_double(iv->val, &d64);
api_res.tags[i - 1].t = NEU_JSON_DOUBLE;
api_res.tags[i - 1].value.val_double = d64;
break;
}
case NEU_DTYPE_CSTR: {
char *cstr = NULL;
neu_dvalue_get_ref_cstr(iv->val, &cstr);
api_res.tags[i - 1].t = NEU_JSON_STR;
api_res.tags[i - 1].value.val_str = cstr;
}
default:
break;
}
}
neu_json_encode_by_fn(&api_res, neu_json_encode_read_resp, &result);
http_ok(ctx->aio, result);
free(ctx);
free(api_res.tags);
free(result);
}
void handle_write_resp(void *cmd_resp)
{
neu_request_t * req = (neu_request_t *) cmd_resp;
struct cmd_ctx * ctx = write_find_ctx(req->req_id);
neu_reqresp_write_resp_t *resp = (neu_reqresp_write_resp_t *) req->buf;
neu_fixed_array_t * array = NULL;
neu_int_val_t * iv = NULL;
int32_t error = 0;
log_info("write resp id: %d, ctx: %p", req->req_id, ctx);
neu_dvalue_get_ref_array(resp->data_val, &array);
iv = (neu_int_val_t *) neu_fixed_array_get(array, 0);
assert(iv->key == 0);
assert(neu_dvalue_get_value_type(iv->val) == NEU_DTYPE_ERRORCODE);
neu_dvalue_get_errorcode(iv->val, &error);
if (ctx != NULL) {
NEU_JSON_RESPONSE_ERROR(
error, { http_response(ctx->aio, error_code.error, result_error); })
free(ctx);
}
assert(ctx != NULL);
}