【修改】重新梳理数据结构并重构部分逻辑

This commit is contained in:
niubinghui
2024-09-06 16:29:07 +08:00
parent b6780f7f4a
commit f8dcaabfbd
14 changed files with 1778 additions and 2819 deletions

View File

@@ -5,4 +5,3 @@ cd -
cp -rf config/* output/conf/
cp -rf include/* output/include/
cp -rf dependence/include/stellar.h output/include/

View File

@@ -1,43 +1,17 @@
/*************************************************************************
> File Name: lua_plugin_manage.h
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* version
* [ v0.1 ]
* 08-01
* 1. 修改外部暴露接口
* lua_plugin_manage_init
* lua_plugin_manage_exit
* 2. 声明数据结构
* struct lua_plugin_manage_schema
*
* 08-09
* 1. 修改参数函数原型, 传入参数修改为已经加载的配置信息
************************************************************************/
#pragma once
#include "stellar/stellar.h"
struct lua_config_specific
struct lua_config_spec
{
/* 插件需要使用的文件名 */
char *config_specific_file;
/* 载插件需要调用的函数名称 */
char *config_specific_load_func;
/* 卸载插件需要调用的函数名称 */
char *config_specific_unload_func;
char *spec_file_path; /* 插件需要使用的文件名 */
char *spec_load_func_name; /* 加载插件需要调用的函数名称 */
char *spec_unload_func_name; /* 载插件需要调用的函数名称 */
};
struct lua_plugin_manage_schema;
struct lua_plugin_manage;
struct lua_plugin_manage_schema *lua_plugin_manage_init(struct stellar *st, int specific_count, struct lua_config_specific *specifics);
int lua_plugin_manage_load_one_specific(struct lua_plugin_manage_schema *schema, struct lua_config_specific *specific);
void lua_plugin_manage_exit(struct lua_plugin_manage_schema *lua_plug_mgr);
struct lua_plugin_manage *lua_plugin_manage_init(struct stellar *st, struct lua_config_spec specifics[], size_t specific_num);
void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr);
void lua_plugin_get_statistics(int plugin_id, int thread_id, int *new_success, int *new_fail, int *free_success, int *free_fail);
void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema);
// void debug_lua_plugin_manage_schema(struct lua_plugin_manage *schema);

View File

@@ -5,18 +5,12 @@ TARGET=libluaplugin.so
# TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST
SRC := lua_plugin_data.c \
lua_plugin_chunk.c \
lua_plugin_cfunc.c \
lua_binding_functions.c \
lua_plugin_binding.c \
SRC := lua_plugin_cfunc.c \
lua_binding_function.c \
lua_plugin_manage.c
OBJECTS := lua_plugin_data.o \
lua_plugin_chunk.o \
lua_plugin_cfunc.o \
lua_binding_functions.o \
lua_plugin_binding.o \
OBJECTS := lua_plugin_cfunc.o \
lua_binding_function.o \
lua_plugin_manage.o
INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include

View File

@@ -1,22 +0,0 @@
#ifndef LUA_PLUGIN_MANAGE_LPM_LOG_H
#define LUA_PLUGIN_MANAGE_LPM_LOG_H
#include <stdio.h>
/* 简单定义一个日志输出, 可根据实际的日志输出调整定义 */
/* define some basic log macros */
#define LOG(level, format, ...) printf("[%s][%s]%d: " format "\n", #level, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define LOGDEBUG(...) LOG(DEBUG, __VA_ARGS__)
// #define LOGDEBUG(...)
#define LOGINFO(...) LOG(INFO, __VA_ARGS__)
// #define LOGINFO(...)
#define LOGNOTICE(...) LOG(INFO, __VA_ARGS__)
// #define LOGNOTICE(...)
#define LOGWARN(...) LOG(WARNING, __VA_ARGS__)
// #define LOGWARN(...)
#define LOGERROR(...) LOG(ERROR, __VA_ARGS__)
// #define LOGERROR(...)
#define LOGFATAL(...) LOG(FALT, __VA_ARGS__)
// #define LOGFATAL(...)
#endif

576
src/lua_binding_function.c Normal file
View File

@@ -0,0 +1,576 @@
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <utlist.h>
#include "lua_binding_function.h"
/* ***** ***** ***** ***** ***** ***** */
int lua_get_worker_thread_num(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 1)
{
lua_settop(L, 0);
return 0;
}
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
int thread_num = stellar_get_worker_thread_num(st);
lua_pushinteger(L, thread_num);
return 1;
}
int lua_get_current_thread_id(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 1)
{
lua_settop(L, 0);
return 0;
}
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
int thread_id = stellar_get_current_thread_id(st);
lua_pushinteger(L, thread_id);
return 1;
}
int lua_get_stellar_pointer(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
lua_settop(L, 0);
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
struct stellar *st = plugin_manage->st;
lua_pushlightuserdata(L, (void *)st);
return 1;
}
/*
int lua_get_plugin_manage_pointer(struct lua_state *state)
{
lua_settop((lua_State *)state, 0);
struct lua_plugin_manage * plugin_manage = lua_state_get_plugin_manage(state);
lua_pushlightuserdata((lua_State *)state, (void *)plugin_manage);
return 1;
}
*/
/* ***** ***** ***** ***** ***** ***** */
int lua_session_plugin_regist(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
/* stack -1 */
int plugin_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (plugin_env_ref_id == LUA_REFNIL)
plugin_env_ref_id = 0;
/* stack -2 */
int ctx_free_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
ctx_free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
/* stack -3 */
int ctx_new_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
ctx_new_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
/* stack -4 */
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_session_plugin_env *new_plugin_env = (struct lua_session_plugin_env *)calloc(1, sizeof(struct lua_session_plugin_env));
memset(new_plugin_env, 0, sizeof(struct lua_session_plugin_env));
new_plugin_env->lua_ctx_new_fn_ref_id = ctx_new_fn_ref_id;
new_plugin_env->lua_ctx_free_fn_ref_id = ctx_free_fn_ref_id;
new_plugin_env->lua_plug_env_ref_id = plugin_env_ref_id;
int plugin_id = stellar_session_plugin_register(st, lpm_ctx_new_func, lpm_ctx_free_func, (void *)new_plugin_env);
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
LL_APPEND(plugin_manage->session_plugin_env_list, new_plugin_env);
new_plugin_env->plugin_manage = plugin_manage;
lua_settop(L, 0);
lua_pushinteger(L, plugin_id);
return 1;
}
int lua_packet_plugin_regist(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
/* stack -1 */
int plugin_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (plugin_env_ref_id == LUA_REFNIL)
plugin_env_ref_id = 0;
/* stack -2 */
int on_packet_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
on_packet_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
/* stack -3 */
int ip_protocol = lua_tointeger(L, -1);
lua_pop(L, 1);
/* stack -4 */
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_packet_plugin_env *new_plugin_env = (struct lua_packet_plugin_env *)calloc(1, sizeof(struct lua_packet_plugin_env));
memset(new_plugin_env, 0, sizeof(struct lua_packet_plugin_env));
new_plugin_env->lua_plug_env_ref_id = plugin_env_ref_id;
new_plugin_env->lua_on_packet_fn_ref_id = on_packet_fn_ref_id;
int plugin_id = stellar_packet_plugin_register(st, (unsigned char)ip_protocol, lpm_on_packet_func, (void *)new_plugin_env);
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
LL_APPEND(plugin_manage->packet_plugin_env_list, new_plugin_env);
new_plugin_env->plugin_manage = plugin_manage;
lua_settop(L, 0);
lua_pushinteger(L, plugin_id);
return 1;
}
/* ***** ***** ***** ***** ***** ***** */
int lua_session_get_type(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 1 || lua_type(L, -1) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
struct session *sess = (struct session *)lua_topointer(L, -1);
lua_settop(L, 0);
if (!sess)
return 0;
lua_pushinteger(L, (int)session_get_type(sess));
return 1;
}
/* ***** ***** ***** ***** ***** ***** */
#define MQ_TYPE_PACKET 1
#define MQ_TYPE_SESSION 2
static int lua_plugin_manage_msg_mq_create_topic(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -3) != LUA_TSTRING || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
/* stack -1 */
int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (free_arg_ref_id == LUA_REFNIL)
free_arg_ref_id = 0;
/* stack -2 */
int free_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
/* stack -3 */
char *topic_name = strdup((char *)lua_tostring(L, -1));
lua_pop(L, 1);
/* stack -4 */
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_message_free_arg *new_message_free_arg = (struct lua_message_free_arg *)calloc(1, sizeof(struct lua_message_free_arg));
memset(new_message_free_arg, 0, sizeof(struct lua_message_free_arg));
new_message_free_arg->lua_msg_free_fn_ref_id = free_fn_ref_id;
new_message_free_arg->lua_msg_free_arg_ref_id = free_arg_ref_id;
int topic_id = -1;
if (type == MQ_TYPE_PACKET)
stellar_packet_mq_create_topic(st, (const char *)topic_name, lpm_packet_message_free_func, new_message_free_arg);
else if (type == MQ_TYPE_SESSION)
stellar_session_mq_create_topic(st, (const char *)topic_name, lpm_session_message_free_func, new_message_free_arg);
if (topic_id >= 0)
{
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
LL_APPEND(plugin_manage->message_free_arg_list, new_message_free_arg);
new_message_free_arg->topic_id = topic_id;
new_message_free_arg->plugin_manage = plugin_manage;
lua_pop(L, 1);
}
else
{
if (new_message_free_arg)
free(new_message_free_arg);
return 0;
}
lua_pushinteger(L, topic_id);
return 1;
}
static int lua_plugin_manage_msg_mq_get_topic_id(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 2 || lua_type(L, -1) != LUA_TSTRING || lua_type(L, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
char *topic_name = strdup(lua_tostring(L, -1));
lua_pop(L, 1);
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
int topic_id = -1;
if (type == MQ_TYPE_PACKET)
stellar_packet_mq_get_topic_id(st, (const char *)topic_name);
else if (type == MQ_TYPE_SESSION)
stellar_session_mq_get_topic_id(st, (const char *)topic_name);
if (topic_name)
free(topic_name);
lua_pushinteger(L, topic_id);
return 1;
}
static int lua_plugin_manage_msg_mq_update_topic(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -3) != LUA_TNUMBER || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
goto err;
/* stack -1 */
int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (free_arg_ref_id == LUA_REFNIL)
free_arg_ref_id = 0;
/* stack -2 */
int free_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
free_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
/* stack -3 */
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
/* stack -4 */
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_message_free_arg *new_message_free_arg = (struct lua_message_free_arg *)calloc(1, sizeof(struct lua_message_free_arg));
memset(new_message_free_arg, 0, sizeof(struct lua_message_free_arg));
new_message_free_arg->topic_id = topic_id;
new_message_free_arg->lua_msg_free_fn_ref_id = free_fn_ref_id;
new_message_free_arg->lua_msg_free_arg_ref_id = free_arg_ref_id;
int update_result = -1;
if (type == MQ_TYPE_PACKET)
update_result = stellar_packet_mq_update_topic(st, topic_id, lpm_packet_message_free_func, new_message_free_arg);
else if (type == MQ_TYPE_SESSION)
update_result = stellar_session_mq_update_topic(st, topic_id, lpm_session_message_free_func, new_message_free_arg);
if (update_result)
{
if (new_message_free_arg)
free(new_message_free_arg);
goto err;
}
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
new_message_free_arg->plugin_manage = plugin_manage;
LL_APPEND(plugin_manage->message_free_arg_list, new_message_free_arg);
lua_settop(L, 0);
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
static int lua_plugin_manage_msg_mq_destory_topic(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 2)
goto err;
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
int destory_result = -1;
if (type == MQ_TYPE_PACKET)
destory_result = stellar_packet_mq_destroy_topic(st, topic_id);
else if (type == MQ_TYPE_SESSION)
destory_result = stellar_session_mq_destroy_topic(st, topic_id);
if (destory_result < 0)
goto err;
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
static int lua_plugin_manage_msg_mq_subscribe_topic(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
goto err;
int plugin_id = lua_tointeger(L, -1);
lua_pop(L, 1);
int on_message_fn_ref_id = 0;
if (lua_type(L, -1) == LUA_TFUNCTION)
on_message_fn_ref_id = luaL_ref(L, -1);
else
lua_pop(L, 1);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct stellar *st = (struct stellar *)lua_topointer(L, -1);
lua_settop(L, 0);
int subscribe_result = -1;
if (type == MQ_TYPE_PACKET)
subscribe_result = stellar_packet_mq_subscribe(st, topic_id, lpm_on_packet_msg_func, plugin_id);
else if (type == MQ_TYPE_SESSION)
subscribe_result = stellar_session_mq_subscribe(st, topic_id, lpm_on_session_msg_func, plugin_id);
if (subscribe_result)
goto err;
struct lua_on_message_fn *on_message = NULL;
struct lua_plugin_manage *plugin_manage = lua_state_get_plugin_manage(state);
if (type == MQ_TYPE_PACKET)
on_message = hash_find_on_msg_fn(plugin_manage->on_packet_message_hashlist, topic_id, plugin_id);
else if (type == MQ_TYPE_SESSION)
on_message = hash_find_on_msg_fn(plugin_manage->on_session_message_hashlist, topic_id, plugin_id);
if (on_message)
{
on_message->lua_on_msg_fn_ref_id = on_message_fn_ref_id;
}
else
{
if (type == MQ_TYPE_PACKET)
on_message = hash_on_msg_fn_insert(plugin_manage->on_packet_message_hashlist, topic_id, plugin_id);
else if (type == MQ_TYPE_SESSION)
on_message = hash_on_msg_fn_insert(plugin_manage->on_session_message_hashlist, topic_id, plugin_id);
if (!on_message)
goto err;
else
on_message->lua_on_msg_fn_ref_id = on_message_fn_ref_id;
}
lua_settop(L, 0);
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
static int lua_plugin_manage_msg_mq_publish_message(struct lua_state *state, int type)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 3)
goto err;
int msg_ref_id = luaL_ref(L, -1);
if (msg_ref_id == LUA_REFNIL)
msg_ref_id = 0;
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
void *p = (void *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context));
new_context->lua_context_ref_id = msg_ref_id;
int publish_result = -1;
if (type == MQ_TYPE_PACKET)
publish_result = packet_mq_publish_message((struct packet *)p, topic_id, new_context);
else if (type == MQ_TYPE_SESSION)
publish_result = session_mq_publish_message((struct session *)p, topic_id, new_context);
if (publish_result)
{
luaL_unref(L, LUA_REGISTRYINDEX, new_context->lua_context_ref_id);
free(new_context);
goto err;
}
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
/* ***** ***** ***** ***** ***** ***** */
int lua_packet_mq_create_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_create_topic(state, MQ_TYPE_PACKET);
}
int lua_packet_mq_get_topic_id(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_get_topic_id(state, MQ_TYPE_PACKET);
}
int lua_packet_mq_update_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_update_topic(state, MQ_TYPE_PACKET);
}
int lua_packet_mq_destory_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_destory_topic(state, MQ_TYPE_PACKET);
}
int lua_packet_mq_subscribe_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_subscribe_topic(state, MQ_TYPE_PACKET);
}
int lua_packet_mq_publish_message(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_publish_message(state, MQ_TYPE_PACKET);
}
/* ***** ***** ***** ***** ***** ***** */
int lua_session_mq_create_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_create_topic(state, MQ_TYPE_SESSION);
}
int lua_session_mq_get_topic_id(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_get_topic_id(state, MQ_TYPE_SESSION);
}
int lua_session_mq_update_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_update_topic(state, MQ_TYPE_SESSION);
}
int lua_session_mq_destory_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_destory_topic(state, MQ_TYPE_SESSION);
}
int lua_session_mq_subscribe_topic(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_subscribe_topic(state, MQ_TYPE_SESSION);
}
int lua_session_mq_publish_message(struct lua_state *state)
{
return lua_plugin_manage_msg_mq_publish_message(state, MQ_TYPE_SESSION);
}
int lua_session_mq_ignore_message(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 3)
goto err;
int plugin_id = lua_tointeger(L, -1);
lua_pop(L, 1);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct session *sess = (struct session *)lua_topointer(L, -1);
lua_settop(L, 0);
if (session_mq_ignore_message(sess, topic_id, plugin_id))
goto err;
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
int lua_session_mq_unignore_message(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4)
goto err;
int plugin_id = lua_tointeger(L, -1);
lua_pop(L, 1);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct session *sess = (struct session *)lua_topointer(L, -1);
lua_settop(L, 0);
if (session_mq_unignore_message(sess, topic_id, plugin_id))
goto err;
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}
int lua_session_mq_topic_is_active(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 2)
goto err;
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct session *sess = (struct session *)lua_topointer(L, -1);
lua_settop(L, 0);
/* 1 means active */
if (session_mq_topic_is_active(sess, topic_id) != 1)
goto err;
lua_pushboolean(L, 1);
return 1;
err:
lua_settop(L, 0);
lua_pushboolean(L, 0);
return 1;
}

View File

@@ -0,0 +1,50 @@
#include "stellar/stellar.h"
#include "stellar/packet_mq.h"
#include "stellar/session.h"
#include "stellar/session_mq.h"
#include "lua_plugin_manage_internal.h"
/* ***** ***** ***** ***** ***** ***** */
/* 需要注册至lua中供lua调用的所有函数原型 */
/* 通用函数 */
int lua_get_worker_thread_num(struct lua_state * state);
int lua_get_current_thread_id(struct lua_state * state);
int lua_get_stellar_pointer(struct lua_state * state);
// int lua_get_plugin_manage_pointer(struct lua_state *state);
/* 注册函数 */
int lua_session_plugin_regist(struct lua_state *state);
int lua_packet_plugin_regist(struct lua_state *state);
/* struct session结构相关的函数 */
int lua_session_get_type(struct lua_state *state);
/* packet message mq相关的函数 */
int lua_packet_mq_create_topic(struct lua_state * state);
int lua_packet_mq_get_topic_id(struct lua_state * state);
int lua_packet_mq_update_topic(struct lua_state * state);
int lua_packet_mq_destory_topic(struct lua_state * state);
int lua_packet_mq_subscribe_topic(struct lua_state * state);
int lua_packet_mq_publish_message(struct lua_state * state);
/* session message mq相关的函数 */
int lua_session_mq_create_topic(struct lua_state *state);
int lua_session_mq_get_topic_id(struct lua_state *state);
int lua_session_mq_update_topic(struct lua_state *state);
int lua_session_mq_destory_topic(struct lua_state *state);
int lua_session_mq_subscribe_topic(struct lua_state *state);
int lua_session_mq_publish_message(struct lua_state *state);
int lua_session_mq_topic_is_active(struct lua_state *state);
int lua_session_mq_ignore_message(struct lua_state *state);
int lua_session_mq_unignore_message(struct lua_state *state);
/* ***** ***** ***** ***** ***** ***** */
/* 此部分为注册至C中的lua通用函数, 实现在lua_plugin_cfunc.c中 */
void *lpm_ctx_new_func(struct session *sess, void *plugin_env);
void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env);
void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg);
void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env);
void lpm_on_packet_func(struct packet * pkt, unsigned char ip_protocol, void * plugin_env);
void lpm_packet_message_free_func(struct packet *pkt, void * msg, void * msg_free_arg);
void lpm_on_packet_msg_func(struct packet *pkt, int topic_id, const void *msg, void * plugin_env);

View File

@@ -1,830 +0,0 @@
/*************************************************************************
> File Name: lua_binding_functions.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* 声明并定义所有需要在lua状态机中绑定的函数
* version
* [ v0.1 ]
* 08-14
* 1. 实现函数
* 新增插件注册函数
* int lua_plugin_manage_regist
* 新增会话相关函数
* int lua_session_get_id
* int lua_session_set_id
* int lua_session_get_type
* int lua_session_set_type
* 新增message相关函数
* int lua_mq_create_topic
* int lua_mq_get_topic_id
* int lua_mq_update_topic
* int lua_mq_destory_topic
* int lua_mq_subscribe_topic
* int lua_mq_topic_is_active
* int lua_mq_publish_message
* int lua_mq_ignore_message
* int lua_mq_unignore_message
*
* 08-29
* 修改create_topic逻辑, 允许创建一个空的topic
************************************************************************/
#include "lua_plugin_manage_internal.h"
#include "stellar/session.h"
#include "stellar/session_mq.h"
int global_max_plugin_id = 0;
/* ***** ***** ***** ***** ***** ***** */
int lua_plugin_manage_regist(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION ||
lua_type(state, -3) != LUA_TFUNCTION || lua_type(state, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 取出处理第四个参数 */
lua_getfield(state, -1, LUA_PLUGIN_ENV_DEFAULT_KEY); /* stack 4, table中取出对应结构的指针 */
if (lua_type(state, -1) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
struct lua_model *plugin_env = (struct lua_model *)lua_topointer(state, -1);
lua_pop(state, 2);
// debug_lua_state_stack(state, 0, "here");
// printf("env pointer is %p\n", plugin_env);
/* 取出处理第三个参数 */
int ctx_free_id = luaL_ref(state, LUA_REGISTRYINDEX); /* stack 3 */
if (ctx_free_id == LUA_REFNIL)
{
lua_settop(state, 0);
return 0;
}
/* 取出处理第二个参数 */
int ctx_new_id = luaL_ref(state, LUA_REGISTRYINDEX); /* stack 2 */
if (ctx_new_id == LUA_REFNIL)
{
luaL_unref(state, LUA_REGISTRYINDEX, ctx_free_id);
lua_settop(state, 0);
return 0;
}
/* 取出处理第一个参数 */
struct stellar *st = (struct stellar *)lua_topointer(state, -1); /* stack 1 */
if (!st)
{
luaL_unref(state, LUA_REGISTRYINDEX, ctx_new_id);
luaL_unref(state, LUA_REGISTRYINDEX, ctx_free_id);
lua_settop(state, 0);
return 0;
}
lua_pop(state, 1);
/* 在stellar中注册, 获取注册id */
int plugin_id = stellar_session_plugin_register(st, lpm_ctx_new_func, lpm_ctx_free_func, (void *)plugin_env);
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("now regist new plugin, plugin id is %d, %d, %d\n", plugin_id, ctx_new_id, ctx_free_id);
#endif
/* TODO: 如果运行完全符合预期的话, 理论上仅有thread 0在此处需要插入新的插件, 且不应该有错误
* 对于其他线程这里应该直接检查ref id是否一致即可, 按理说不应该再插入新插件
* 后续可以修改为根据线程号执行不同的处理流程
*/
/* 如果在其他线程中已经完成过注册 */
struct lua_plugin *search_plugin = NULL;
while ((search_plugin = utarray_next(plugin_env->plugin_array, search_plugin)))
{
if (search_plugin->plugin_id == plugin_id)
{
/* 初始化过程中已经进行过加载 */
if (search_plugin->ctx_new_ref != ctx_new_id || search_plugin->ctx_free_ref != ctx_free_id)
{
LOGERROR("regist plugin, same id with different function ref");
LOGERROR("plugin id %d, registed %d, %d, new ref %d, %d", plugin_id,
search_plugin->ctx_new_ref, search_plugin->ctx_free_ref,
ctx_new_id, ctx_free_id);
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
lua_pushinteger(state, plugin_id);
return 1;
}
}
/* 统计记录一下当前最大的plugin_id编号 */
if (plugin_id > global_max_plugin_id)
global_max_plugin_id = plugin_id;
/* 将注册完成的新插件插入到队列中 */
struct lua_plugin new_plugin;
memset(&new_plugin, 0, sizeof(new_plugin));
new_plugin.plugin_id = plugin_id;
new_plugin.ctx_new_ref = ctx_new_id;
new_plugin.ctx_free_ref = ctx_free_id;
utarray_push_back(plugin_env->plugin_array, &new_plugin);
plugin_env->plugin_count += 1;
global_schema->plugin_count += 1;
lua_settop(state, 0);
lua_pushinteger(state, plugin_id);
return 1;
}
/* ***** ***** ***** ***** ***** ***** */
#if 0
int lua_session_get_id(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 1)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
lua_settop(state, 0);
return 0;
}
lua_pop(state, 1);
lua_pushinteger(state, session_get_id(sess));
return 1;
}
int lua_session_set_id(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 2)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
int setid = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
lua_pop(state, 1);
session_set_id(sess, setid);
return 0;
}
int lua_session_set_type(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 2)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
int settype = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
lua_pop(state, 1);
session_set_type(sess, settype);
return 0;
}
#endif
int lua_session_get_type(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 1)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
lua_settop(state, 0);
return 0;
}
lua_pop(state, 1);
lua_pushinteger(state, (int)session_get_type(sess));
return 1;
}
/* ***** ***** ***** ***** ***** ***** */
/*
* TODO: 未完整考虑线程安全问题, 例如
* 多个线程同时注册一个topic, 是否需要做处理等。
*/
static UT_icd lua_plugin_mq_icd = {sizeof(struct lua_plugin_mq), NULL, NULL, NULL};
int lua_mq_create_topic(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (((lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION) &&
(lua_type(state, -1) != LUA_TNIL || lua_type(state, -2) != LUA_TNIL)) ||
lua_type(state, -3) != LUA_TSTRING || lua_type(state, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 创建对该table的引用, 防止该table被回收 */
int private_ref = 0;
if (lua_type(state, -1) != LUA_TNIL)
{
private_ref = luaL_ref(state, LUA_REGISTRYINDEX); /* stack top function */
if (private_ref == LUA_REFNIL)
{
lua_settop(state, 0);
return 0;
}
}
/* 导出free message的调用函数 */
int free_ref = 0;
if (lua_type(state, -1) != LUA_TFUNCTION)
{
free_ref = luaL_ref(state, LUA_REGISTRYINDEX);
if (free_ref == LUA_REFNIL)
{
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
lua_settop(state, 0);
return 0;
}
}
/* 出栈队列名称 */
char *name = strdup((char *)lua_tostring(state, -1));
lua_pop(state, 1);
/* 出栈传入的stellar */
struct stellar *st = (struct stellar *)lua_topointer(state, -1);
if (!st)
{
luaL_unref(state, LUA_REGISTRYINDEX, free_ref);
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
if (name)
free(name);
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
/* 插入新的元素 */
int topic_id = -1;
if (private_ref && free_ref)
{
struct lua_message_mq new_mq;
memset(&new_mq, 0, sizeof(new_mq));
utarray_push_back(global_schema->message_mq_array, &new_mq);
/* 从队列尾部取出最后一个元素 */
struct lua_message_mq *mq = utarray_eltptr(global_schema->message_mq_array, (utarray_len(global_schema->message_mq_array) - 1));
mq->freemessage_ref = free_ref;
mq->mq_private_ref = private_ref;
/* 调用stellar中mq的topic创建函数 */
/* BugFix: 仔细看了代码, 在stellar中没有对name做拷贝处理, 这里name不能释放 */
topic_id = stellar_session_mq_create_topic(st, (const char *)name, lpm_message_free_func, mq);
/* 创建topic失败, 还原创建topic之前的状态 */
if (topic_id < 0)
{
utarray_pop_back(global_schema->message_mq_array);
luaL_unref(state, LUA_REGISTRYINDEX, free_ref);
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
if (name)
free(name);
return 0;
}
global_schema->mq_count += 1;
lua_rawgeti(state, LUA_REGISTRYINDEX, mq->mq_private_ref);
#if 0
/* 不检查了, 直接覆盖 */
/* 在传入的table中检查是否存在与mq_private_env同名的元素 */
lua_getfield(state, -1, LUA_MQ_ENV_DEFAULT_KEY); /* stack top nil */
if (lua_type(state, -1) != LUA_TNIL) {
lua_settop(state, 0);
return 0;
}
lua_pop(state, 1); /* stack top table */
#endif
/* 在该table中加入新元素 */
lua_pushlightuserdata(state, (void *)mq); /* stack top new_mq */
lua_setfield(state, -2, LUA_MQ_ENV_DEFAULT_KEY); /* stack top table */
mq->topic_id = topic_id;
}
else
{
/* 只是创建一个新的空topic */
topic_id = stellar_session_mq_create_topic(st, (const char *)name, NULL, NULL);
if (topic_id < 0)
{
if (name)
free(name);
return 0;
}
}
lua_settop(state, 0);
lua_pushinteger(state, topic_id);
return 1;
}
int lua_mq_get_topic_id(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 2)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TSTRING || lua_type(state, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 出栈队列名称 */
char *name = strdup(lua_tostring(state, -1));
lua_pop(state, 1);
/* 出栈传入的stellar */
struct stellar *st = (struct stellar *)lua_topointer(state, -1);
if (!st)
{
if (name)
free(name);
return 0;
}
lua_pop(state, 1);
int topic_id = stellar_session_mq_get_topic_id(st, (const char *)name);
if (name)
free(name);
lua_settop(state, 0);
lua_pushinteger(state, topic_id);
return 1;
}
int lua_mq_update_topic(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TFUNCTION ||
lua_type(state, -3) != LUA_TNUMBER || lua_type(state, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 创建对该table的引用, 防止该table被回收 */
int private_ref = luaL_ref(state, LUA_REGISTRYINDEX); /* stack top function */
if (private_ref == LUA_REFNIL)
{
lua_settop(state, 0);
return 0;
}
/* 导出free message的调用函数 */
int free_ref = luaL_ref(state, LUA_REGISTRYINDEX);
if (free_ref == LUA_REFNIL)
{
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
lua_settop(state, 0);
return 0;
}
/* topic_id */
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
/* 出栈传入的stellar */
struct stellar *st = (struct stellar *)lua_topointer(state, -1);
if (!st)
{
luaL_unref(state, LUA_REGISTRYINDEX, free_ref);
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
struct lua_message_mq *mq = search_message_mq_by_id(topic_id);
if (!mq || mq->topic_id != topic_id)
{
/* 如果topic不是lua创建的, 需要加入管理 */
struct lua_message_mq new_mq;
memset(&new_mq, 0, sizeof(new_mq));
utarray_push_back(global_schema->message_mq_array, &new_mq);
mq = utarray_eltptr(global_schema->message_mq_array, (utarray_len(global_schema->message_mq_array) - 1));
if (stellar_session_mq_update_topic(st, topic_id, lpm_message_free_func, mq))
{
utarray_pop_back(global_schema->message_mq_array);
luaL_unref(state, LUA_REGISTRYINDEX, free_ref);
luaL_unref(state, LUA_REGISTRYINDEX, private_ref);
return 0;
}
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("update topic, id %d %d %d", topic_id, private_ref, free_ref);
#endif
mq->freemessage_ref = free_ref;
mq->mq_private_ref = private_ref;
mq->topic_id = topic_id;
lua_pushboolean(state, 1);
return 1;
}
else
{
/* 本身是由lua创建的 */
/* 更新private_ref */
lua_rawgeti(state, LUA_REGISTRYINDEX, private_ref);
lua_pushlightuserdata(state, (void *)mq); /* stack top new_mq */
lua_setfield(state, -2, LUA_MQ_ENV_DEFAULT_KEY); /* stack top table */
// luaL_unref(state, LUA_REGISTRYINDEX, mq->mq_private_ref);
mq->mq_private_ref = private_ref;
/* 更新free function ref */
// luaL_unref(state, LUA_REGISTRYINDEX, mq->freemessage_ref);
mq->freemessage_ref = free_ref;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("update topic, id %d %d %d", topic_id, private_ref, free_ref);
#endif
}
lua_settop(state, 0);
lua_pushboolean(state, 1);
return 1;
}
int lua_mq_destory_topic(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 2)
{
lua_settop(state, 0);
return 0;
}
/* topic_id */
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
/* 出栈传入的stellar */
struct stellar *st = (struct stellar *)lua_topointer(state, -1);
if (!st)
{
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
/* 优先调用C函数进行卸载 */
if (stellar_session_mq_destroy_topic(st, topic_id) < 0)
{
return 0;
}
/* 不方便删除, 将id置为-1, 确保匹配不到 */
struct lua_message_mq *mq = search_message_mq_by_id(topic_id);
if (mq)
{
mq->topic_id = -1;
luaL_unref(state, LUA_REGISTRYINDEX, mq->mq_private_ref);
luaL_unref(state, LUA_REGISTRYINDEX, mq->freemessage_ref);
mq->freemessage_ref = 0;
mq->mq_private_ref = 0;
}
lua_pushboolean(state, 1);
return 1;
}
int lua_mq_subscribe_topic(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TFUNCTION ||
lua_type(state, -3) != LUA_TNUMBER || lua_type(state, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 读取参数 */
int plugin_id = lua_tointeger(state, -1);
lua_pop(state, 1);
int on_message_ref = luaL_ref(state, LUA_REGISTRYINDEX);
if (on_message_ref == LUA_REFNIL)
{
lua_settop(state, 0);
return 0;
}
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
struct stellar *st = (struct stellar *)lua_topointer(state, -1);
if (!st)
{
lua_settop(state, 0);
return 0;
}
lua_pop(state, 1);
lua_settop(state, 0);
if (stellar_session_mq_subscribe(st, topic_id, lpm_on_session_msg_func, plugin_id))
{
/* 订阅失败, 返回false */
lua_pushboolean(state, 0);
}
else
{
struct lua_plugin *plugin = search_plugin_by_id(plugin_id);
if (plugin)
{
if (!plugin->sub_topic_array)
{
/* 该插件尚未注册任何topic, 注册第一个topic时将创建接收的topic列表 */
utarray_new(plugin->sub_topic_array, &lua_plugin_mq_icd);
}
else
{
/* 如果该插件中之前已经订阅过该消息, 更新message函数 */
struct lua_plugin_mq *mq = NULL;
while ((mq = utarray_next(plugin->sub_topic_array, mq)))
{
if (mq->topic_id == topic_id)
{
luaL_unref(state, LUA_REGISTRYINDEX, mq->onmessage_ref);
mq->onmessage_ref = on_message_ref;
lua_pushboolean(state, 1);
return 1;
}
}
}
struct lua_plugin_mq new_mq;
memset(&new_mq, 0, sizeof(new_mq));
new_mq.topic_id = topic_id;
new_mq.onmessage_ref = on_message_ref;
utarray_push_back(plugin->sub_topic_array, &new_mq);
}
/* 订阅成功, 返回true */
lua_pushboolean(state, 1);
}
return 1;
}
int lua_mq_publish_message(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 3)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TTABLE || lua_type(state, -2) != LUA_TNUMBER ||
lua_type(state, -3) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 倒序依次获取参数 */
int mess_ref = luaL_ref(state, LUA_REGISTRYINDEX);
if (mess_ref == LUA_REFNIL)
{
lua_settop(state, 0);
return 0;
}
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
luaL_unref(state, LUA_REGISTRYINDEX, mess_ref);
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
/* 创建一段数据引用 */
struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context));
if (__glibc_unlikely(!new_context))
{
luaL_unref(state, LUA_REGISTRYINDEX, mess_ref);
return 0;
}
new_context->context_ref_id = mess_ref;
/* 调用C接口发布消息 */
if (session_mq_publish_message(sess, topic_id, new_context))
{
luaL_unref(state, LUA_REGISTRYINDEX, new_context->context_ref_id);
free(new_context);
lua_pushboolean(state, 0);
}
else
{
lua_pushboolean(state, 1);
}
return 1;
}
int lua_mq_ignore_message(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TNUMBER ||
lua_type(state, -3) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 倒序获取参数 */
int plugin_id = lua_tointeger(state, -1);
lua_pop(state, 1);
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
if (session_mq_ignore_message(sess, topic_id, plugin_id))
lua_pushboolean(state, 0);
else
lua_pushboolean(state, 1);
return 1;
}
int lua_mq_unignore_message(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TNUMBER ||
lua_type(state, -3) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 倒序获取参数 */
int plugin_id = lua_tointeger(state, -1);
lua_pop(state, 1);
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
if (session_mq_unignore_message(sess, topic_id, plugin_id))
lua_pushboolean(state, 0);
else
lua_pushboolean(state, 1);
return 1;
}
int lua_mq_topic_is_active(lua_State *state)
{
/* 参数个数检查 */
if (lua_gettop(state) != 4)
{
lua_settop(state, 0);
return 0;
}
/* 参数类型检查 */
if (lua_type(state, -1) != LUA_TNUMBER || lua_type(state, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(state, 0);
return 0;
}
/* 倒序获取参数 */
int topic_id = lua_tointeger(state, -1);
lua_pop(state, 1);
struct session *sess = (struct session *)lua_topointer(state, -1);
if (!sess)
{
lua_settop(state, 0);
return 0;
}
lua_settop(state, 0);
/* 1 means active */
if (session_mq_topic_is_active(sess, topic_id) == 1)
lua_pushboolean(state, 1);
else
lua_pushboolean(state, 0);
return 1;
}

View File

@@ -1,54 +0,0 @@
/*************************************************************************
> File Name: lua_binding_functions.h
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* 声明并定义所有需要在lua状态机中绑定的函数
* version
* [ v0.1 ]
* 08-14
* 1. 新增函数声明
* 新增插件注册函数
* int lua_plugin_manage_regist
* 新增会话相关函数
* int lua_session_get_id
* int lua_session_set_id
* int lua_session_get_type
* int lua_session_set_type
* 新增message相关函数
* int lua_mq_create_topic
* int lua_mq_get_topic_id
* int lua_mq_update_topic
* int lua_mq_destory_topic
* int lua_mq_subscribe_topic
* int lua_mq_topic_is_active
* int lua_mq_publish_message
* int lua_mq_ignore_message
* int lua_mq_unignore_message
************************************************************************/
#include "lua_plugin_manage_internal.h"
/* 需要注册至lua中供lua调用的所有函数原型 */
int lua_plugin_manage_regist(lua_State *state);
/* 与struct session结构相关的函数 */
#if 0
int lua_session_get_id(lua_State *state);
int lua_session_set_id(lua_State *state);
int lua_session_set_type(lua_State *state);
#endif
int lua_session_get_type(lua_State *state);
/* 与stellar message mq相关的函数 */
int lua_mq_create_topic(lua_State * state);
int lua_mq_get_topic_id(lua_State * state);
int lua_mq_update_topic(lua_State * state);
int lua_mq_destory_topic(lua_State * state);
int lua_mq_subscribe_topic(lua_State * state);
int lua_mq_topic_is_active(lua_State * state);
int lua_mq_publish_message(lua_State * state);
int lua_mq_ignore_message(lua_State * state);
int lua_mq_unignore_message(lua_State * state);

View File

@@ -1,472 +0,0 @@
/*************************************************************************
> File Name: lua_plugin_binding.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* version
* [ v0.1 ]
* 08 -02
* 1. 实现函数
* int lua_cbinding_function;
* int lua_cbinding_function_remove;
* int lua_cbinding_data;
* int lua_cbinding_data_remove;
* int lua_cbinding_functions;
* int lua_cbinding_datas;
* int lua_plugin_manage_regist;
* ** 注册函数lua_plugin_manage_session_regist还需要补充
*
* 08-12
* 1. 修改函数lua_cbinding_function, 参数与lua_cbinding_data保持统一
* 2. 修改部分函数返回值, 使用枚举代替错误码返回值, 方便统一处理
*
* 08-14
* 1. 将所有待注册函数移动至新文件中, 不再此文件中实现
************************************************************************/
#include "lua_plugin_manage_internal.h"
#include "lua_binding_functions.h"
#include <stdlib.h>
#include <string.h>
/* 需要注册至状态机中的函数定义在链表中, 会依次完成注册 */
struct lua_binding_function lua_bind_functions[] = {
{lua_plugin_manage_regist, "register", "plugin_manage"},
// {lua_session_get_id, "getid", "session"},
// {lua_session_set_id, "setid", "session"},
{lua_session_get_type, "gettype", "session"},
// {lua_session_set_type, "settype", "session"},
{lua_mq_create_topic, "createtopic", "message"},
{lua_mq_get_topic_id, "gettopicid", "message"},
{lua_mq_update_topic, "updatetopic", "message"},
{lua_mq_destory_topic, "destorytopic", "message"},
{lua_mq_subscribe_topic, "subscribetopic", "message"},
{lua_mq_topic_is_active, "topicisactive", "message"},
{lua_mq_publish_message, "publishmessage", "message"},
{lua_mq_ignore_message, "ignoremessage", "message"},
{lua_mq_unignore_message, "unignoremessage", "message"},
{NULL, NULL, NULL},
};
/* 需要注册至状态机中的数据定义在链表中, 会依次完成注册 */
/* 为了实现注册过程的统一, 所有数据类型均使用string作为value格式 */
struct lua_binding_data lua_bind_datas[] = {
{DATATYPE_BOOL, "true", "test_data_bool", "plugin_manage"},
{DATATYPE_INT, "1000", "test_data_int", "plugin_manage"},
{DATATYPE_NUM, "100.001", "test_data_double", "plugin_manage"},
{DATATYPE_STRING, "this is a string test", "test_data_string", "plugin_manage"},
{DATATYPE_END, NULL, NULL, NULL},
};
/* 向lua状态机中注册一个函数 */
int lua_cbinding_function(lua_State *state, struct lua_binding_function *function);
/* 从lua状态机中移除一个已经注册的函数 */
int lua_cbinding_function_remove(lua_State *state, const char *function_name, const char *space_name);
/* 将一个全局数据注册至状态机中 */
int lua_cbinding_data(lua_State *state, struct lua_binding_data *data);
/* 从状态机中移除一个已经注册的全局数据 */
int lua_cbinding_data_remove(lua_State *state, const char *data_name, const char *space_name);
/*
* Function: lua_cbinding_function
* Input: | lua_State * | state | 需要注册函数的状态机
* | struct lua_binding_function * | function | 需要绑定的function函数结构
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 将一个C函数注册至lua中
*/
int lua_cbinding_function(
lua_State *state,
struct lua_binding_function *bind_function)
{
if (__glibc_unlikely(!state || !bind_function))
return PARAM_ERR;
if (__glibc_unlikely(!bind_function->function || !bind_function->function_name))
return PARAM_ERR;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("bind function to state, function %p, name %s, spacename %s",
bind_function->function,
bind_function->function_name,
(bind_function->space_name) ? bind_function->space_name : "no");
#endif
if (bind_function->space_name)
{
/* 包含space_name, 调用时为 space_name.function_name */
lua_getglobal(state, bind_function->space_name);
if (lua_gettop(state) == 0 || lua_type(state, -1) == LUA_TNIL)
{
/* 没有该命名空间, 创建一个 */
lua_newtable(state);
lua_setglobal(state, bind_function->space_name);
lua_settop(state, 0);
lua_getglobal(state, bind_function->space_name);
}
else
{
/* 该全局已经存在 */
if (lua_type(state, -1) != LUA_TTABLE)
{
/* spacename已经被占用, 并且不是table, 无法插入数据 */
lua_settop(state, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
lua_getfield(state, -1, bind_function->function_name);
if (lua_type(state, -1) != LUA_TNIL)
{
/* 在待插入的global table中存在与function_name重名的成员 */
lua_settop(state, 0);
return BIND_FUNCTION_TYPE_ERR;
}
lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */
}
lua_pushcfunction(state, bind_function->function);
lua_setfield(state, -2, bind_function->function_name);
}
else
{
lua_getglobal(state, bind_function->function_name);
if (lua_type(state, -1) != LUA_TNIL)
{
/* 存在与function_name重名的全局成员 */
lua_settop(state, 0);
return BIND_FUNCTION_TYPE_ERR;
}
lua_pop(state, 1);
/* 不包含space_name, 调用时直接使用function_name调用 */
lua_pushcfunction(state, bind_function->function);
lua_setglobal(state, bind_function->function_name);
}
lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
return SUCCESS;
}
/*
* Function: lua_cbinding_function_remove
* Input: | lua_State * | state | 需要删除注册函数的状态机
* | const char * | function_name | 需要删除的函数名称
* | const char * | space_name | 需要删除的命名空间名称
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 从状态机中删除一个C注册的函数, 删除过程中将该函数在lua状态的引用置为nil
*/
int lua_cbinding_function_remove(
lua_State *state,
const char *function_name,
const char *space_name)
{
if (__glibc_unlikely(!state || !function_name))
return PARAM_ERR;
if (space_name)
{
/* 检查该命名空间是否存在 */
lua_getglobal(state, space_name);
if (lua_type(state, -1) != LUA_TTABLE)
{
/* 命名空间存在且不是table */
lua_settop(state, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
/* 检查该命名空间内是否存在function_name */
lua_getfield(state, -1, function_name);
if (lua_type(state, -1) != LUA_TFUNCTION)
{
/* 命名空间存在内部元素名称为function_name, 但是类型不符 */
lua_settop(state, 0);
return BIND_FUNCTION_TYPE_ERR;
}
/* 删除该函数 */
lua_pop(state, 1);
lua_pushnil(state);
lua_setfield(state, -2, function_name);
}
else
{
/* 获取全局数据, 检查function_name */
lua_getglobal(state, function_name);
if (lua_type(state, -1) != LUA_TFUNCTION)
{
/* 类型不符 */
lua_settop(state, 0);
return BIND_FUNCTION_TYPE_ERR;
}
/* 删除该函数 */
lua_pop(state, 1);
lua_pushnil(state);
lua_setglobal(state, function_name);
}
lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
return SUCCESS;
}
/*
* Function: lua_cbinding_data
* Input: | lua_State * | state | 需要注册数据的状态机
* | struct lua_binding_data * | data | 需要注册至状态机中的数据
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 将一个变量注册至lua状态机中
*/
int lua_cbinding_data(
lua_State *state,
struct lua_binding_data *data)
{
if (__glibc_unlikely(!state || !data))
{
return PARAM_ERR;
}
enum DATATYPE data_type = data->data_type;
char *value = data->data_value;
char *data_name = data->data_name;
char *space_name = data->space_name;
if (__glibc_unlikely(!value || !data_name))
return PARAM_ERR;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("bind data to state, type %d, data %s, name %s, spacename %s",
data_type, value, data_name, (space_name) ? space_name : "no");
#endif
if (space_name)
{
/* 包含space_name */
lua_getglobal(state, space_name);
if (lua_gettop(state) == 0 || lua_type(state, -1) == LUA_TNIL)
{
/* 没有该命名空间, 创建一个 */
lua_newtable(state);
lua_setglobal(state, space_name);
lua_settop(state, 0);
lua_getglobal(state, space_name);
}
else
{
/* 该全局已经存在 */
if (lua_type(state, -1) != LUA_TTABLE)
{
/* spacename已经被占用, 并且不是table, 无法插入数据 */
lua_settop(state, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
lua_getfield(state, -1, data_name);
if (lua_type(state, -1) != LUA_TNIL)
{
/* 在待插入的global table中存在与function_name重名的成员 */
lua_settop(state, 0);
return BIND_DATA_TYPE_ERR;
}
lua_pop(state, 1); /* 正确的情况下此时栈顶为nil, 弹出一个nil值 */
}
/* 不同类型需要使用不同的入栈函数 */
switch (data_type)
{
case DATATYPE_BOOL:
if (strstr(value, "true") || strstr(value, "TRUE"))
lua_pushboolean(state, 1);
else if (strstr(value, "false") || strstr(value, "FALSE"))
lua_pushboolean(state, 0);
break;
case DATATYPE_INT:
lua_pushinteger(state, atoi(value));
break;
case DATATYPE_NUM:
lua_pushnumber(state, (lua_Number)atof(value));
break;
case DATATYPE_STRING:
lua_pushstring(state, (const char *)value);
break;
default:
/* 未识别的类型 */
lua_settop(state, 0);
return BIND_DATA_TYPE_UNKNOWN;
}
lua_setfield(state, -2, data_name);
}
else
{
lua_getglobal(state, data_name);
if (lua_type(state, -1) != LUA_TNIL)
{
lua_settop(state, 0);
/* 存在与data_name重名的全局成员 */
return BIND_DATA_TYPE_ERR;
}
lua_pop(state, 1);
/* 不同类型需要使用不同的入栈函数 */
switch (data_type)
{
case DATATYPE_BOOL:
if (strstr(value, "true") || strstr(value, "TRUE"))
lua_pushboolean(state, 1);
else if (strstr(value, "false") || strstr(value, "FALSE"))
lua_pushboolean(state, 0);
break;
case DATATYPE_INT:
lua_pushinteger(state, atoi(value));
break;
case DATATYPE_NUM:
lua_pushnumber(state, (lua_Number)atof(value));
break;
case DATATYPE_STRING:
lua_pushstring(state, (const char *)value);
break;
default:
/* 未识别的类型 */
lua_settop(state, 0);
return BIND_DATA_TYPE_UNKNOWN;
}
lua_setglobal(state, data_name);
}
lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
return SUCCESS;
}
/*
* Function: lua_cbinding_data_remove
* Input: | lua_State * | state | 需要删除注册数据的状态机
* | const char * | data_name | 需要删除的数据名称
* | const char * | space_name | 需要删除的命名空间名称
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 从状态机中删除一个C注册的数据, 删除过程中将该名称在lua状态的引用置为nil
*/
int lua_cbinding_data_remove(
lua_State *state,
const char *data_name,
const char *space_name)
{
if (__glibc_unlikely(!state || !data_name))
return PARAM_ERR;
if (space_name)
{
/* 检查该命名空间是否存在 */
lua_getglobal(state, space_name);
if (lua_type(state, -1) != LUA_TTABLE)
{
/* 命名空间存在且不是table */
lua_settop(state, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
/* 检查该命名空间内是否存在data_name */
lua_getfield(state, -1, data_name);
int data_type = lua_type(state, -1);
if (data_type != LUA_TSTRING && data_type != LUA_TNUMBER && data_type != LUA_TBOOLEAN)
{
/* 命名空间存在内部元素名称为data_name, 但是类型不符 */
lua_settop(state, 0);
return BIND_DATA_TYPE_ERR;
}
else if (data_type == LUA_TNIL)
{
/* 没有该名称的元素 */
lua_settop(state, 0);
return SUCCESS;
}
/* 删除该函数 */
lua_pop(state, 1);
lua_pushnil(state);
lua_setfield(state, -2, data_name);
}
else
{
/* 获取全局数据, 检查function_name */
lua_getglobal(state, data_name);
int data_type = lua_type(state, -1);
if (data_type != LUA_TSTRING && data_type != LUA_TNUMBER && data_type != LUA_TBOOLEAN)
{
/* 类型不符 */
lua_settop(state, 0);
return BIND_DATA_TYPE_ERR;
}
else if (data_type == LUA_TNIL)
{
/* 没有该名称的元素 */
lua_settop(state, 0);
return SUCCESS;
}
/* 删除该函数 */
lua_pop(state, 1);
lua_pushnil(state);
lua_setglobal(state, data_name);
}
lua_settop(state, 0); /* 操作完成, 弹出所有元素 */
return SUCCESS;
}
/*
* Function: lua_cbinding_functions
* Input: | lua_State * | state | 需要绑定函数的状态机实例
* Output:
* Return: | -1 | 参数错误
* | 0 | 成功
* | >0 | 绑定出错的数据数量
* Description: 绑定所有需要在lua中调用的C函数
*/
int lua_cbinding_functions(lua_State *state)
{
if (__glibc_unlikely(!state))
return PARAM_ERR;
int bind_function_count = sizeof(lua_bind_functions) / sizeof(struct lua_binding_function);
int bind_ret = 0;
int failed_count = 0;
for (int i = 0; i < bind_function_count; ++i)
{
if (lua_bind_functions[i].function && lua_bind_functions[i].function_name)
{
bind_ret = lua_cbinding_function(state, &lua_bind_functions[i]);
if (bind_ret)
{
LOGERROR("binding function failed, ret is %d, function name is %s\n", bind_ret, lua_bind_functions[i].function_name);
failed_count += 1;
}
}
}
return failed_count;
}
/*
* Function: lua_cbinding_datas
* Input: | lua_State * | state | 需要绑定数据的状态机实例
* Output:
* Return: | -1 | 参数错误
* | 0 | 成功
* | >0 | 绑定出错的数据数量
* Description: 绑定所有data数据
*/
int lua_cbinding_datas(lua_State *state)
{
if (__glibc_unlikely(!state))
return -1;
int bind_data_count = sizeof(lua_bind_datas) / sizeof(struct lua_binding_data);
int bind_ret = 0;
int failed_count = 0;
for (int i = 0; i < bind_data_count; ++i)
{
if (lua_bind_datas[i].data_value && lua_bind_datas[i].data_name)
{
bind_ret = lua_cbinding_data(state, &lua_bind_datas[i]);
if (bind_ret)
{
LOGERROR("binding data failed, ret is %d, data is [%s]%s", bind_ret, lua_bind_datas[i].data_name, lua_bind_datas[i].data_value);
failed_count += 1;
}
}
}
return failed_count;
}

View File

@@ -1,266 +1,183 @@
/*************************************************************************
> File Name: lua_plugin_cfunc.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
#include "lua_binding_function.h"
/*************************************************************************
* version
* [ v0.1 ]
* 08-06
* 1. 实现函数
* void *lpm_ctx_new_func;
* void lpm_ctx_free_func;
*
* 08-13
* 1. 由于context结构体修改, 部分函数调用及处理逻辑需要同步修改
*
* 08-15
* 1. 实现函数
* void lpm_message_free_func
* void lpm_on_session_msg_func
************************************************************************/
#include "lua_plugin_manage_internal.h"
#include "stellar/session.h"
/* 内存分配过程中可能存在内存浪费的情况, 其他即使不是Lua的插件也分配了内存 */
/* 但是从调用的角度来说能够提高访问速度, 不需要做ID映射, 浪费内存也是以B为单位 */
struct lua_plugin_statistics *global_plugin_statistics = NULL;
/*
* Function: lpm_ctx_new_func
* Input: | struct session * | sess | 会话信息
* | void * | plugin_env | 插件运行环境
* Output:
* Return: | NULL | 运行函数错误
* | pointer | 运行插件上的ctx_new函数成功, 返回context
* Description: 与C插件管理器保持一致的ctx_new_func
*/
void *lpm_ctx_new_func(
struct session *sess,
void *plugin_env)
void *lpm_ctx_new_func(struct session *sess, void *plugin_env)
{
if (__glibc_unlikely(!sess || !plugin_env))
if (!plugin_env)
return NULL;
struct lua_model *env = (struct lua_model *)plugin_env;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
/* 获取插件ID并找到该插件 */
int plugin_id = session_get_current_plugin_id(sess);
// int plugin_id = 1;
struct lua_plugin *plugin = NULL;
while ((plugin = utarray_next(env->plugin_array, plugin)))
{
if (plugin->plugin_id == plugin_id)
break;
}
// LOGDEBUG("%d call plugin id %d, ref %d\n", plugin_id, plugin->plugin_id, plugin->ctx_new_ref);
if (!plugin || plugin->plugin_id != plugin_id)
/* 未找到该插件 */
return NULL;
/* 获取当前的线程id并找到该线程对应的state */
int thread_id = session_get_current_thread_id(sess);
if (thread_id > global_schema->state_count)
return NULL;
lua_State *state = global_schema->thread_state[thread_id];
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = (struct lua_state *)plugin_manage->state[thread_id];
struct lua_context *new_context = lua_context_new(state);
if (__glibc_unlikely(!new_context))
/* 创建新的context失败 */
return NULL;
int statisitc_id = thread_id * global_max_plugin_id + plugin_id;
struct lua_cdata param[3] = {0};
param[0].cdata_type = DATATYPE_POINTER;
param[0].cdata_pointer = sess;
param[1].cdata_type = DATATYPE_TABLE;
param[1].cdata_table = env->private_env_ref;
param[2].cdata_type = DATATYPE_CONTEXT;
param[2].cdata_context = new_context;
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_TABLE;
param[1].table = env->lua_plug_env_ref_id;
param[2].type = DATATYPE_CONTEXT;
param[2].context = new_context;
if (lua_chunk_execute(state, plugin->ctx_new_ref, 3, param, 0, NULL))
if (lua_chunk_execute(state, env->lua_ctx_new_fn_ref_id, param, 3, NULL, 0, NULL, 0))
{
/* 脚本执行失败 */
++global_plugin_statistics[statisitc_id].new_failed_count;
lua_context_free(state, new_context);
lua_context_free(new_context);
return NULL;
}
++global_plugin_statistics[statisitc_id].new_success_count;
return (void *)new_context;
}
/*
* Function: lpm_ctx_free_func
* Input: | struct session * | sess | 会话信息
* | void * | sess_ctx | 会话中的私有数据
* | void * | plugin_env | 插件运行环境
* Output:
* Return:
* Description: 与C插件管理器保持一致的ctx_free_func
*/
void lpm_ctx_free_func(
struct session *sess,
void *sess_ctx,
void *plugin_env)
void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env)
{
if (__glibc_unlikely(!sess || !sess_ctx || !plugin_env))
if (!plugin_env)
return;
struct lua_model *env = (struct lua_model *)plugin_env;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
/* 获取插件ID并找到该插件 */
int plugin_id = session_get_current_plugin_id(sess);
// int plugin_id = 1;
struct lua_plugin *plugin = NULL;
while ((plugin = utarray_next(env->plugin_array, plugin)))
{
if (plugin->plugin_id == plugin_id)
break;
}
if (!plugin || plugin->plugin_id != plugin_id)
/* 未找到该插件 */
return;
int thread_id = session_get_current_thread_id(sess);
if (thread_id > global_schema->state_count)
return;
lua_State *state = global_schema->thread_state[thread_id];
int statistic_id = thread_id * global_max_plugin_id + plugin_id;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
struct lua_cdata param[3] = {0};
param[0].cdata_type = DATATYPE_POINTER;
param[0].cdata_pointer = sess;
param[1].cdata_type = DATATYPE_CONTEXT;
param[1].cdata_context = (struct lua_context *)sess_ctx;
param[2].cdata_type = DATATYPE_TABLE;
param[2].cdata_table = env->private_env_ref;
if (lua_chunk_execute(state, plugin->ctx_free_ref, 3, param, 0, NULL))
++global_plugin_statistics[statistic_id].free_failed_count;
else
++global_plugin_statistics[statistic_id].free_success_count;
lua_context_free(state, (struct lua_context *)sess_ctx);
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)sess_ctx;
param[2].type = DATATYPE_TABLE;
param[2].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, env->lua_ctx_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)sess_ctx);
return;
}
/*
* Function: lpm_message_free_func
* Input: | struct session * | sess | 释放message对应的session
* | void * | msg | 需要释放的message消息
* | void * | msg_free_arg | 释放函数需要存储的私有数据
* Output:
* Return:
* Description: 与C插件保持一致的session_msg_free_cb_func, 作为lua插件实现对应功能的通用函数
*/
void lpm_message_free_func(
struct session *sess,
void *msg,
void *msg_free_arg)
void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg)
{
if (__glibc_unlikely(!sess || !msg || !msg_free_arg))
if (!msg_free_arg)
return;
struct lua_message_mq *plugin_mq = (struct lua_message_mq *)msg_free_arg;
struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg;
struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = session_get_current_thread_id(sess);
if (thread_id > global_schema->state_count)
return;
lua_State *state = global_schema->thread_state[thread_id];
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
struct lua_cdata param[3] = {0};
param[0].cdata_type = DATATYPE_POINTER;
param[0].cdata_pointer = sess;
param[1].cdata_type = DATATYPE_CONTEXT;
param[1].cdata_context = (struct lua_context *)msg;
param[2].cdata_type = DATATYPE_TABLE;
param[2].cdata_table = plugin_mq->mq_private_ref;
lua_chunk_execute(state, plugin_mq->freemessage_ref, 3, param, 0, NULL);
lua_context_free(state, (struct lua_context *)msg);
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)msg;
param[2].type = DATATYPE_TABLE;
param[2].table = free_arg->lua_msg_free_arg_ref_id;
lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)msg);
return;
}
/*
* Function: lpm_on_session_msg_func
* Input: | struct session * | sess | 会话信息
* | int | topic_id | 处理的message topic id
* | const void * | msg | 需要处理的消息信息
* | void * | sess_ctx | 会话中的私有数据
* | void * | plugin_env | 插件运行环境
* Output:
* Return:
* Description: 与C插件管理器保持一致的ctx_free_func
*/
void lpm_on_session_msg_func(
struct session *sess,
int topic_id,
const void *msg,
void *sess_ctx,
void *plugin_env)
void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env)
{
if (__glibc_unlikely(!sess || !sess || !plugin_env))
if (!plugin_env)
return;
struct lua_context *sess_context = (struct lua_context *)sess_ctx;
struct lua_model *env = (struct lua_model *)plugin_env;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_session_message_hashlist, topic_id, env->session_plugin_id);
struct stellar *st = plugin_manage->st;
/* 获取插件ID并找到该插件 */
int plugin_id = session_get_current_plugin_id(sess);
// int plugin_id = 1;
struct lua_plugin *plugin = NULL;
while ((plugin = utarray_next(env->plugin_array, plugin)))
{
if (plugin->plugin_id == plugin_id)
break;
}
if (!plugin || plugin->plugin_id != plugin_id || !plugin->sub_topic_array)
/* 未找到该插件, 或者在该插件中未发现注册的topic_id */
return;
struct lua_plugin_mq *mq = NULL;
while ((mq = utarray_next(plugin->sub_topic_array, mq)))
{
if (mq->topic_id == topic_id)
break;
}
if (!mq || mq->topic_id != topic_id)
/* 未找到对应的消息处理函数 */
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
struct lua_cdata param[5] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_INT;
param[1].integer = topic_id;
/* 后续统一为相同结构 */
param[2].type = DATATYPE_CONTEXT;
param[2].context = (struct lua_context *)msg;
param[3].type = DATATYPE_CONTEXT;
param[3].context = (struct lua_context *)sess_ctx;
param[4].type = DATATYPE_TABLE;
param[4].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0);
return;
}
void lpm_on_packet_func(struct packet *pkt, unsigned char ip_protocol, void *plugin_env)
{
if (!plugin_env)
return;
/* 判断该消息是由C端插件产生的还是由Lua插件产生的 */
struct lua_message_mq *message_mq = search_message_mq_by_id(topic_id);
struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = session_get_current_thread_id(sess);
if (thread_id > global_schema->state_count)
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_INT;
param[1].integer = (int)ip_protocol;
param[2].type = DATATYPE_TABLE;
param[2].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, env->lua_on_packet_fn_ref_id, param, 3, NULL, 0, NULL, 0);
return;
}
void lpm_packet_message_free_func(struct packet *pkt, void *msg, void *msg_free_arg)
{
if (!msg_free_arg)
return;
lua_State *state = global_schema->thread_state[thread_id];
struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg;
struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage;
struct stellar *st = plugin_manage->st;
struct lua_cdata params[5] = {0};
params[0].cdata_type = DATATYPE_POINTER;
params[0].cdata_pointer = sess;
params[1].cdata_type = DATATYPE_INT;
params[1].cdata_int = topic_id;
if (!message_mq)
{
/* C端产生的直接使用指针 */
params[2].cdata_type = DATATYPE_POINTER;
params[2].cdata_pointer = (void *)msg;
}
else
{
/* lua端产生的为一个context结构 */
params[2].cdata_type = DATATYPE_CONTEXT;
params[2].cdata_context = (struct lua_context *)msg;
}
params[3].cdata_type = DATATYPE_CONTEXT;
params[3].cdata_context = sess_context;
params[4].cdata_type = DATATYPE_TABLE;
params[4].cdata_table = env->private_env_ref;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
lua_chunk_execute(state, mq->onmessage_ref, 5, params, 0, NULL);
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)msg;
param[2].type = DATATYPE_TABLE;
param[2].table = free_arg->lua_msg_free_arg_ref_id;
lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)msg);
return;
}
void lpm_on_packet_msg_func(struct packet *pkt, int topic_id, const void *msg, void *plugin_env)
{
if (!plugin_env)
return;
struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_packet_message_hashlist, topic_id, env->packet_plugin_id);
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state[thread_id];
struct lua_cdata param[4] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_INT;
param[1].integer = topic_id;
/* 后续统一为相同结构 */
param[2].type = DATATYPE_CONTEXT;
param[2].context = (struct lua_context *)msg;
param[3].type = DATATYPE_TABLE;
param[3].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0);
return;
}

View File

@@ -1,107 +0,0 @@
/*************************************************************************
> File Name: lua_plugin_chunk.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* 实现代码块相关操作
* version
* [ v0.1 ]
* 08-12
* 1. 实现函数
* int lua_chunk_execute;
************************************************************************/
#include "lua_plugin_manage_internal.h"
/*
* Function: lua_chunk_execute
* Input: | lua_State * | state | 执行该代码块使用的状态机
* | int | ref_id | 代码块在状态机中的引用ID
* | int | pcount | 执行过程中传入的参数个数
* | struct lua_cdata * | params | 执行过程中传入的参数
* | int | rcount | 执行结束后返回值的个数
* | struct lua_cdata * | returns | 执行结束后返回值
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 在lua状态机中执行一段代码块, 执行的代码块需要提前在状态机中完成注册
* 并已经生成相关的引用ID, 根据该ID进行调用
*/
int lua_chunk_execute(
lua_State *state,
int ref_id,
int pcount,
struct lua_cdata *params,
int rcount,
struct lua_cdata *returns)
{
if (__glibc_unlikely(!state || ref_id == LUA_REFNIL))
return PARAM_ERR;
if ((pcount && !params) || (pcount < 0))
return PARAM_ERR;
if ((rcount && !returns) || (rcount < 0))
return PARAM_ERR;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("now execute chunk, %p, %d", state, ref_id);
#endif
/* 需要调用的函数入栈, 由于后续在读取参数个数的时候对栈操作较多, 需要先将函数入栈 */
lua_rawgeti(state, LUA_REGISTRYINDEX, ref_id);
if (lua_gettop(state) == 0 || lua_type(state, -1) != LUA_TFUNCTION)
{
lua_settop(state, 0);
return CHUNK_TYPE_NOT_FUNCTION;
}
/* 参数入栈 */
int pushret = 0;
for (int i = 0; i < pcount; ++i)
{
if ((pushret = lua_cdata_push_stack(state, &params[i])))
{
lua_settop(state, 0);
return pushret;
}
}
/* 执行该脚本并记录执行时间 */
// clock_t start_time, end_time;
// start_time = clock();
/* 调用该脚本 or 代码片段 */
if (lua_pcall(state, pcount, LUA_MULTRET, 0))
{
// end_time = clock();
LOGERROR("run script failed, mess is %s\n", lua_tostring(state, -1));
/* 仅函数运行过程中出错记入出错记录, 由于参数错误等原因导致的错误不记录 */
lua_settop(state, 0);
return CHUNK_RUN_CODE_FAIL;
}
// end_time = clock();
/* 返回值出栈 */
if (rcount > 0)
{
/* 如果rmaxcount为0, 说明在期望中不准备接收返回值, 也不必处理 */
int count = lua_gettop(state);
if (count > rcount)
{
lua_settop(state, 0);
return CHUNK_RCOUNT_ERR;
}
int pop_ret = 0;
for (int i = (count - 1); i >= 0; --i)
{
if ((pop_ret = lua_cdata_pop_stack(state, &(returns[i]))))
{
lua_settop(state, 0);
return pop_ret;
}
}
}
lua_settop(state, 0);
/* TODO: 记录耗时等数据 */
return SUCCESS;
}

View File

@@ -1,214 +0,0 @@
/*************************************************************************
> File Name: lua_plugin_data.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* version
* [ v0.1 ]
* 08-06
* 1. 实现函数
* int lua_cdata_push_stack;
* int lua_cdata_pop_stack;
* void lua_cdata_destory;
* struct lua_context * lua_context_new;
* int lua_context_push_stack;
* void lua_context_free;
*
* 08-12
* 1. 修改部分函数返回值, 使用统一的错误码, 方便统一处理
************************************************************************/
#include "lua_plugin_manage_internal.h"
/*
* Function: lua_cdata_push_stack
* Input: | lua_State * | state | 入栈数据使用的状态机
* | struct lua_cdata * | cdata | 需要入栈的数据
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 将一个数据元素入栈
*/
int lua_cdata_push_stack(
lua_State *state,
struct lua_cdata *cdata)
{
if (__glibc_unlikely(!state || !cdata))
return PARAM_ERR;
switch (cdata->cdata_type)
{
/* 不同的数据类型入栈方式不同 */
case DATATYPE_NIL:
lua_pushnil(state);
return SUCCESS;
case DATATYPE_BOOL:
lua_pushboolean(state, cdata->cdata_bool);
return SUCCESS;
case DATATYPE_INT:
lua_pushinteger(state, cdata->cdata_int);
return SUCCESS;
case DATATYPE_NUM:
lua_pushnumber(state, cdata->cdata_num);
return SUCCESS;
case DATATYPE_STRING:
if (lua_pushstring(state, cdata->cdata_string) == NULL)
return DATA_PUSHSTACK_ERR;
return SUCCESS;
case DATATYPE_TABLE:
lua_rawgeti(state, LUA_REGISTRYINDEX, cdata->cdata_table);
return SUCCESS;
case DATATYPE_POINTER:
lua_pushlightuserdata(state, (void *)cdata->cdata_pointer);
return SUCCESS;
case DATATYPE_CONTEXT:
if (lua_context_push_stack(state, cdata->cdata_context))
return DATA_PUSHSTACK_ERR;
return SUCCESS;
default:
LOGERROR("can't recorgnize data type %d", cdata->cdata_type);
}
return DATA_TYPE_UNKNOWN;
}
/*
* Function: lua_cdata_pop_stack
* Input: | lua_State * | state | 出栈数据使用的状态机
* | struct lua_cdata * | cdata | 保存出栈的元素
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 将一个数据元素出栈, 出栈过程中无法出栈context与table类型
* TODO: 扩展类型, 支持更多数据类型
*/
int lua_cdata_pop_stack(
lua_State *state,
struct lua_cdata *cdata)
{
if (__glibc_unlikely(!state || !cdata))
return PARAM_ERR;
if (!lua_gettop(state))
return DATA_POPSTACK_NODATA;
switch (lua_type(state, -1))
{
case LUA_TNIL:
cdata->cdata_type = DATATYPE_NIL;
break;
case LUA_TBOOLEAN:
cdata->cdata_type = DATATYPE_BOOL;
cdata->cdata_bool = lua_toboolean(state, -1);
break;
case LUA_TNUMBER:
cdata->cdata_type = DATATYPE_NUM;
cdata->cdata_num = lua_tonumber(state, -1);
int try_int = (int)cdata->cdata_num;
if ((double)try_int == cdata->cdata_num)
{
cdata->cdata_type = DATATYPE_INT;
cdata->cdata_int = lua_tointeger(state, -1);
}
break;
case LUA_TSTRING:
cdata->cdata_type = DATATYPE_STRING;
cdata->cdata_string = (char *)strdup(lua_tostring(state, -1));
break;
case LUA_TLIGHTUSERDATA:
cdata->cdata_type = DATATYPE_POINTER;
cdata->cdata_pointer = (void *)lua_topointer(state, -1);
break;
default:
/* TODO: 其他数据类型之后处理 */
LOGERROR("other lua type can't pop out, %d", lua_type(state, -1));
return DATA_TYPE_UNKNOWN;
}
lua_pop(state, 1);
return SUCCESS;
}
/*
* Function: lua_cdata_destory
* Input: | struct lua_cdata * | cdata | 待销毁的data结构
* Output:
* Return:
* Description: 销毁是一个data结构, 释放内部占用内存
* 目前该函数仅数据类型为string的时候需要调用一次
*/
void lua_cdata_destory(struct lua_cdata *cdata)
{
if (__glibc_unlikely(!cdata))
return;
if (cdata->cdata_type == DATATYPE_STRING && cdata->cdata_string)
free(cdata->cdata_string);
return;
}
/*
* Function: lua_context_new
* Input: | lua_State * | state | 创建context使用的状态机
* Output:
* Return: | NULL | 创建失败
* | pointer | 创建成功, 返回创建的context指针
* Description: 创建一个context结构, 由于context结构使用需要在状态机中生成引用值, 单独重写一个new函数
*/
struct lua_context *lua_context_new(lua_State *state)
{
if (__glibc_unlikely(!state))
return NULL;
lua_newtable(state);
int ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("create new context, ref id is %d\n", ref_id);
#endif
lua_settop(state, 0);
if (ref_id == LUA_REFNIL)
return NULL;
struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context));
if (__glibc_unlikely(!new_context))
{
luaL_unref(state, LUA_REGISTRYINDEX, ref_id);
return NULL;
}
// new_context->context_state = state;
new_context->context_ref_id = ref_id;
return new_context;
}
/*
* Function: lua_context_push_stack
* Input: | lua_State * | state | 将该context入栈
* | struct lua_context * | context | 待入栈的context结构
* Output:
* Return: | 0 | 入栈成功
* | -1 | 参数错误
* Description: 将一个context入栈, 实际入栈流程与table一致
*/
int lua_context_push_stack(lua_State *state, struct lua_context *context)
{
if (luai_unlikely(!state || !context))
return PARAM_ERR;
lua_rawgeti(state, LUA_REGISTRYINDEX, context->context_ref_id);
return SUCCESS;
}
/*
* Function: lua_context_free
* Input: | lua_State * | state | 在该状态机中删除context
* | struct lua_context * | context | 释放一个context
* Output:
* Return:
* Description: 释放一个context
*/
void lua_context_free(lua_State *state, struct lua_context *context)
{
if (__glibc_unlikely(!state || !context))
return;
luaL_unref(state, LUA_REGISTRYINDEX, context->context_ref_id);
free(context);
return;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +1,34 @@
/*************************************************************************
> File Name: lua_plugin_manage_internal.h
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* version
* [ v0.1 ]
* 08-02
* 完成函数注册及数据注册功能
* 1. 声明及定义结构
* struct lua_binding_function;
* enum BINDING_DATATYPE;
* struct lua_binding_data;
* 2. 声明函数
* int lua_cbinding_function;
* int lua_cbinding_function_remove;
* int lua_cbinding_data;
* int lua_cbinding_data_remove;
* int lua_cbinding_functions;
* int lua_cbinding_datas;
*
* 08-05
* 基本完成lua_plugin_manage中主流程
* 1. 声明及定义结构
* struct lua_config_specific;
* struct lua_script;
* struct lua_session_plugin;
* struct lua_plugin_env;
* struct lua_thread_state;
* struct lua_plugin_manage_schema;
* 2. 声明函数
* void specific_instance_copy;
* void specific_instance_destory;
* int script_instance_init_byname;
* int script_instance_init_byrefid;
* void script_instance_clean;
* int script_execute; (暂未实现)
* int session_plugin_instance_init;
* void session_plugin_instance_destory;
* int plugin_env_instance_init;
* void plugin_env_instance_destory;
* int thread_state_instance_init;
* void thread_state_instance_destory;
* int thread_state_instance_load;
* int lua_plugin_manage_config_load;
* int lua_plugin_manage_thread_load;
*
* 08-06
* 完成数据相关操作, 并补全函数script_execute
* 完成注册至C插件管理器中的session_ctx_new_func及session_ctx_free_func函数
* 1. 声明并定义结构
* struct lua_cdata;
* struct lua_context;
* 2. 声明函数
* int lua_cdata_push_stack;
* int lua_cdata_pop_stack;
* void lua_cdata_destory;
* struct lua_context * lua_context_new;
* int lua_context_push_stack;
* void lua_context_free;
*
* void *lpm_ctx_new_func;
* void lpm_ctx_free_func;
*
* 08-07
* BugFix:
* 修改struct lua_plugin_env, 其中增加文件路径
* 防止在加载过程中由于函数重名导致的加载错误
*
* 08-08
* 整体重构状态机相关结构定义, 拆分高频访问数据与低频访问数据
* 状态机中数据管理由树形结构修改为数组型结构
* 经过多次验证, 相同状态机在执行相同操作后返回结果及中间产物一致, 合并一些冗余数据
* 1. 声明并定义结构
* struct lua_plugin_statistics;
* struct lua_plugin;
* struct lua_model;
* struct lua_plugin_manage_schema;
*
* 08-14
* 新增message相关结构定义
* 1. 声明并定义结构
* struct lua_plugin_mq;
* struct lua_message_mq;
* 2. 声明函数
* void lpm_message_free_func
* void lpm_on_session_msg_func
* struct lua_plugin * search_plugin_by_id
* struct lua_message_mq * search_message_mq_by_id
************************************************************************/
#ifndef LUA_PLUGIN_MANAGE_INTERNAL_H
#define LUA_PLUGIN_MANAGE_INTERNAL_H
#include <stddef.h>
#include "lua_plugin_manage.h"
#include "lpm_log.h"
#include <utarray.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
struct lua_state;
enum LUA_PLUGIN_RETURN
enum LUA_PLUGIN_MANGE_ERR_NUM
{
/* 状态机相关的错误码 */
STATE_LOAD_FILE_ERR = -400, /* 状态机加载lua文件时出错, 可能原因是文件不存在或文件无法加载 */
STATE_CREATE_ENV_FAIL, /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */
STATE_GET_LOAD_FAIL, /* 状态机加载load函数时出现错误, 该函数不存在或引用ID有问题 */
STATE_GET_UNLOAD_FAIL, /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */
STATE_REF_TYPE_ERR, /* 获取函数引用ID过程中数据类型有错, 无法正常执行 */
STATE_CREATE_REF_FAIL, /* 创建引用ID过程中失败, 无法创建refid */
STATE_CALL_LOAD_FAILED, /* 调用on_load函数过程中运行失败 */
STATE_CALL_UNLOAD_FAILED, /* 调用on_unload函数过程中运行失败 */
STATE_CREATE_ENV_FAIL, /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */
STATE_GET_UNLOAD_FAIL, /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */
/* lua代码块运行错误码 */
CHUNK_TYPE_NOT_FUNCTION = -300, /* 获取得到的代码块类型并非可执行的lua语句, 无法执行 */
CHUNK_RUN_CODE_FAIL, /* 调用代码过程中运行失败, 失败的具体报错信息会保存在栈中, 通过日志输出 */
CHUNK_RCOUNT_ERR, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */
CHUNK_RCOUNT_ERR, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */
/* lua与C之间数据转换或操作错误码 */
DATA_PUSHSTACK_ERR = -200, /* 数据入栈过程中遇到未知的问题 */
DATA_POPSTACK_ERR, /* 数据从状态机中出栈过程中遇到未知的问题 */
DATA_POPSTACK_NODATA, /* 出栈过程中栈内无数据, 导致出栈失败 */
DATA_TYPE_UNKNOWN, /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */
DATA_TYPE_UNKNOWN = -200, /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */
DATA_TYPE_ERR, /* 获取到了错误的数据类型 */
DATA_PUSHSTACK_ERR, /* 数据入栈过程中遇到未知的问题 */
DATA_POPSTACK_ERR, /* 数据从状态机中出栈过程中遇到未知的问题 */
DATA_POPSTACK_NODATA, /* 出栈过程中栈内无数据, 导致出栈失败 */
/* lua函数或数据绑定错误码 */
BIND_NAMESPACE_TYPE_ERR = -100, /* 绑定或删除过程中使用命名空间, 但命名空间数据类型不符 */
BIND_FUNCTION_TYPE_ERR, /* 绑定或删除函数过程中数据类型错误 */
@@ -129,236 +40,184 @@ enum LUA_PLUGIN_RETURN
};
/* ***** ***** ***** ***** ***** ***** */
/* 此部分主要功能为C向lua中注册函数及数据, 实现在lua_plugin_binding.c中 */
/* 需要注册至lua中的函数 */
struct lua_binding_function
typedef int (*lua_cbind_func)(struct lua_state *state);
struct lua_bind_function_spec
{
/* 注册函数原型 */
lua_CFunction function;
/* 注册至lua中的函数名称 */
char *function_name;
/* 注册至lua中的命名空间名称 */
char *space_name;
lua_cbind_func function; /* 注册函数原型 */
char *func_name; /* 注册至lua中的函数名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num);
/* 定义在lua_plugin_binding.c文件中 */
/* 所有需要注册至lua状态机中供lua调用的函数 */
extern struct lua_binding_function lua_bind_functions[];
struct lua_context
{
struct lua_state *state;
int lua_context_ref_id;
};
struct lua_context *lua_context_new(struct lua_state *state);
void lua_context_free(struct lua_context *context);
void lua_context_push_stack(struct lua_context *context);
/* 暂时支持前四种数据类型提前注册至lua状态机中 */
/* 其余类型用于运行lua函数等场景 */
enum DATATYPE
{
DATATYPE_BEGIN = 0,
/* nil类型 */
DATATYPE_NIL,
/* bool类型 */
DATATYPE_BOOL,
/* int类型 */
DATATYPE_INT,
/* double类型 */
DATATYPE_NUM,
/* 字符串类型 */
DATATYPE_STRING,
/* 以下类型不能用于全局变量注册, 仅用于函数等场景 */
/* table类型 */
DATATYPE_TABLE,
/* 指针类型 */
DATATYPE_POINTER,
/* context上下文类型 */
DATATYPE_CONTEXT,
DATATYPE_NIL, /* nil类型 */
DATATYPE_BOOL, /* bool类型 */
DATATYPE_INT, /* int类型 */
DATATYPE_NUM, /* double类型 */
DATATYPE_STRING, /* 字符串类型 */
/* 以下类型不能用于全局变量注册 */
DATATYPE_TABLE, /* table类型 */
DATATYPE_LUA_TABLE, /* 此类型用于在lua之间翻译传递数据 */
DATATYPE_POINTER, /* 指针类型 */
DATATYPE_CONTEXT, /* context上下文类型 */
DATATYPE_FUNCTION, /* 函数类型 */
DATATYPE_END
};
/* 需要注册至lua状态机中的数据 */
struct lua_binding_data
struct lua_bind_data_spec
{
/* 注册的数据类型 */
enum DATATYPE data_type;
/* 注册数据 */
char *data_value;
/* 注册的数据名称 */
char *data_name;
/* 注册至lua中的命名空间名称 */
char *space_name;
enum DATATYPE data_type; /* 注册的数据类型 */
char *data_value; /* 注册数数据值 */
char *data_name; /* 注册数据名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num);
/* 定义在lua_plugin_binding.c中 */
/* 所有需要注册至lua状态机中的全局数据 */
extern struct lua_binding_data lua_bind_datas[];
/* 将lua_bind_functions中提前注册的所有函数注册至state状态机中 */
int lua_cbinding_functions(lua_State *state);
/* 将lua_bind_datas中提前注册的所有数据注册至state状态机中 */
int lua_cbinding_datas(lua_State *state);
/* ***** ***** ***** ***** ***** ***** */
/* 此部分主要用于lua与C之间的数据转换与传递, 实现在lua_plugin_data.c中 */
struct lua_cdata;
// struct lua_ctable;
struct lua_context;
struct lua_cnode;
struct lua_ctable;
/* 保存lua数据的结构 */
struct lua_cdata
{
enum DATATYPE cdata_type;
enum DATATYPE type;
size_t data_len; /* 只有在类型为function时使用此标识 */
union
{
int cdata_bool;
int cdata_int;
double cdata_num;
char *cdata_string;
/* table暂时只有plugin_env场景下使用, 暂时使用索引进行操作 */
int cdata_table;
void *cdata_pointer;
struct lua_context *cdata_context;
int bool;
int integer;
double number;
char *string;
int table;
void *pointer;
struct lua_context *context;
void *function;
struct lua_ctable *ctable;
};
};
/* 将一个data结构入栈 */
int lua_cdata_push_stack(lua_State *state, struct lua_cdata *cdata);
/* 从栈中弹出一个元素, 并保存在data结构中 */
int lua_cdata_pop_stack(lua_State *state, struct lua_cdata *cdata);
/* 销毁一个data结构, 只有string类型需要调用此函数, 其他的情况直接释放即可 */
void lua_cdata_destory(struct lua_cdata *cdata);
/* 上下文结构, 保存临时数据 */
struct lua_context
struct lua_cnode
{
// lua_State *context_state;
int context_ref_id;
char *node_string_key;
int node_integer_key;
struct lua_cdata *node_data;
};
/* 在状态机中生成一个context */
struct lua_context *lua_context_new(lua_State *state);
/* 将一个context入栈 */
int lua_context_push_stack(lua_State *state, struct lua_context *context);
/* 释放一个context */
void lua_context_free(lua_State *state, struct lua_context *context);
/* ***** ***** ***** ***** ***** ***** */
/* 此部分为注册至C中的lua通用函数, 实现在lua_plugin_cfunc.c中 */
void *lpm_ctx_new_func(struct session *sess, void *plugin_env);
void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env);
void lpm_message_free_func(struct session *sess, void *msg, void *msg_free_arg);
void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env);
/* ***** ***** ***** ***** ***** ***** */
/* lua代码块相关操作, 实现在lua_plugin_chunk.c中 */
/* 执行一段lua代码块, 执行之前需要先在lua中生成一个引用ID */
int lua_chunk_execute(lua_State *state, int ref_id, int pcount, struct lua_cdata *params, int rcount, struct lua_cdata *returns);
/* ***** ***** ***** ***** ***** ***** */
/* TODO:统计插件的运行情况, 暂时没想好怎么用 */
/* 记录一个插件的运行状态 */
struct lua_plugin_statistics
struct lua_ctable
{
/* ctx_new函数调用成功的次数 */
int new_success_count;
/* ctx_new函数调用失败的次数 */
int new_failed_count;
/* ctx_free函数调用成功的次数 */
int free_success_count;
/* ctx_free函数调用失败的次数 */
int free_failed_count;
size_t array_size;
size_t node_size;
struct lua_cdata **array_data;
struct lua_cnode **node_data;
};
/* 状态机相关的一些数据结构及操作, 实现在lua_plugin_manage.c中 */
extern struct lua_plugin_manage_schema *global_schema;
/* 保存插件的运行情况, 运行次数等信息 */
/* 二维数组修改为一维数组, 方便使用偏移快速查找 */
extern struct lua_plugin_statistics *global_plugin_statistics;
/* 最大插件编号 */
extern int global_max_plugin_id;
#define LUA_MQ_ENV_DEFAULT_KEY "__mqenv_pointer"
#define LUA_MQ_TOPIC_ID_KEY "topic_id"
/* 保存lua插件注册的消息队列信息 */
struct lua_plugin_mq
struct lua_cdata *lua_cdata_new(void);
void lua_cdata_free(struct lua_cdata *cdata);
int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata);
int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata);
struct lua_ctable *lua_ctable_new(void);
void lua_ctable_free(struct lua_ctable *ctable);
int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable);
int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable);
struct lua_cnode *lua_cnode_new(void);
void lua_cnode_free(struct lua_cnode *cnode);
/* ***** ***** ***** ***** ***** ***** */
int lua_chunk_execute(struct lua_state *state, int fn_ref_id, struct lua_cdata param[], size_t param_num, struct lua_cdata returnvalue[], size_t r_num, char *errlog, size_t err_len);
/* ***** ***** ***** ***** ***** ***** */
struct lua_load_script
{
/* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */
int lua_load_fn_ref_id;
int lua_unload_fn_ref_id;
int lua_script_env_ref_id;
};
struct lua_session_plugin_env
{
struct lua_session_plugin_env *next;
struct lua_plugin_manage *plugin_manage;
int session_plugin_id;
int lua_ctx_new_fn_ref_id;
int lua_ctx_free_fn_ref_id;
int lua_plug_env_ref_id;
};
struct lua_packet_plugin_env
{
struct lua_packet_plugin_env *next;
struct lua_plugin_manage * plugin_manage;
int packet_plugin_id;
int lua_on_packet_fn_ref_id;
int lua_plug_env_ref_id;
};
struct lua_message_free_arg
{
struct lua_message_free_arg *next;
struct lua_plugin_manage * plugin_manage;
int topic_id;
/* 如果是订阅的topic必须包含处理函数 */
int onmessage_ref;
int lua_msg_free_fn_ref_id;
int lua_msg_free_arg_ref_id;
};
/* 保存Lua插件信息 */
struct lua_plugin
struct lua_on_message_fn
{
/* 注册完成后得到的插件ID */
int on_use;
int topic_id;
int plugin_id;
/* context_new函数在状态机中的引用值 */
int ctx_new_ref;
/* context_free函数在状态机中的引用值 */
int ctx_free_ref;
/* 该插件中订阅的topic */
UT_array *sub_topic_array;
int lua_on_msg_fn_ref_id;
};
void lua_plugin_destory(void *elt);
/* 根据ID号在整个schema中进行遍历 */
struct lua_plugin *search_plugin_by_id(int plugin_id);
#define MODEL_MARK_INIT_DONE 0x0001
#define MODEL_MARK_LOAD_DONE 0x0002
#define HASH_MAX_NUM 1024
int calc_on_message_func_hash_key(int topic_id, int plugin_id);
struct lua_on_message_fn * hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id);
struct lua_on_message_fn * hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id);
#define LUA_PLUGIN_ENV_DEFAULT_KEY "__penv_pointer"
/* 加载的lua模块, 一个lua模块一般来说对应一个lua文件, 与C插件管理中的so相同 */
struct lua_model
{
/* 该模块注册后的插件列表 */
UT_array *plugin_array;
/* 该模块load函数在状态机中的引用值 */
int load_ref;
/* 该模块unload函数在状态机中的引用值 */
int unload_ref;
/* 该模块创建出的plugin_env数据在状态机中的引用值 */
int private_env_ref;
/* 初始化过程中的标记 */
unsigned short model_mark;
/* 加载的插件数量 */
unsigned short plugin_count;
};
/* 在一个状态机中初始化一个模块 */
int thread_state_load_specific(lua_State *state, struct lua_model *model, struct lua_config_specific *specific);
#define LUA_GLOBAL_THREAD_ID_KEY "__global_thread_id"
#define LUA_GLOBAL_STELLAR_POINTER "__global_stellar_pointer"
#define LUA_GLOBAL_PLUGIN_MANGE_POINTER "__global_plugin_managee_pointer"
/* 由lua创建的topic结构, 该结构保存在schema中 */
struct lua_message_mq
{
/* 消息队列ID, 消息队列可能是订阅得到或者创建得到, 此处保存对应topic信息 */
int topic_id;
/* 如果是新创建的topic, 必须包含释放函数 */
int freemessage_ref;
/* 创建一个消息处理私有数据, 对应session_mq中的msg_free_arg */
int mq_private_ref;
// char * topic_name;
};
/* 根据topic_id在schema中查找一个message对应的函数 */
struct lua_message_mq *search_message_mq_by_id(int topic_id);
// int lua_state_get_thread_id(struct lua_state * state);
// struct stellar * lua_state_get_stellar(struct lua_state * state);
struct lua_plugin_manage * lua_state_get_plugin_manage(struct lua_state * state);
#define LUA_STATE_THREAD_ID_KEY "__thread_id"
struct lua_plugin_manage_schema
struct lua_plugin_manage
{
struct stellar *st;
/* 创建的状态机数量, 状态机数量与线程的个数相同 */
int state_count;
/* 插入模块的数量, 模块的数量与specific的数量相同 */
int model_count;
/* 注册的消息队列的数量 */
int mq_count;
/* 所有模块中注册的插件总数量 */
int plugin_count;
size_t state_num;
size_t load_script_num;
struct lua_state **state;
struct lua_load_script *load_script;
/* 线程状态机 */
lua_State **thread_state;
/* 所有插入的模块 */
struct lua_model **model;
/* TODO: 创建的所有message topic id理论上应该是连续的, 可以考虑用hash数组, 寻址能更快 */
UT_array *message_mq_array;
// UT_array *session_plugin_env;
// UT_array *packet_plugin_env;
// UT_array *message_free_arg;
struct lua_session_plugin_env *session_plugin_env_list;
struct lua_packet_plugin_env *packet_plugin_env_list;
struct lua_message_free_arg *message_free_arg_list;
struct lua_on_message_fn on_session_message_hashlist[HASH_MAX_NUM];
struct lua_on_message_fn on_packet_message_hashlist[HASH_MAX_NUM];
};
#ifdef LUAPLUGIN_BASIC_UNITTEST
void debug_lua_state_stack(lua_State *state, int mod, const char *message);
void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema);
#endif
struct lua_plugin_manage *lua_plugin_manage_init(struct stellar *st, struct lua_config_spec specifics[], size_t specific_count);
void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr);
#endif