mirror of
https://github.com/emqx/neuron.git
synced 2026-10-19 05:51:27 +08:00
343 lines
9.8 KiB
C
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);
|
|
} |