【新增】完成新接口代码修改,通过编译未测试
This commit is contained in:
16
include/lua_module_manage.h
Normal file
16
include/lua_module_manage.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "stellar/module_manager.h"
|
||||
|
||||
#define LUA_MODULE_MANAGE_MODULE_NAME "lua_moduel_manager_module"
|
||||
#define LUA_MODULE_MANAGE_CONF_PATH "lua_module_manage.toml"
|
||||
|
||||
typedef void lua_mq_on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg, void *after_dispatch_arg);
|
||||
|
||||
struct stellar_module *lua_module_manager_on_init(struct stellar_module_manager *mod_mgr);
|
||||
void lua_module_manager_on_exit(struct stellar_module_manager *mod_mgr, struct stellar_module *mod);
|
||||
|
||||
|
||||
/* 提供的通用函数 */
|
||||
/* 通用的Lua mq订阅函数, on_msg */
|
||||
/* 注册新数据及自定义函数的接口,能够传参或获取返回值 */
|
||||
14
src/Makefile
14
src/Makefile
@@ -5,13 +5,15 @@ TARGET=libluaplugin.so
|
||||
|
||||
# TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST
|
||||
|
||||
SRC := lua_plugin_cfunc.c \
|
||||
SRC := lua_module_manage_internal.c \
|
||||
lua_binding_cfunc.c \
|
||||
lua_binding_function.c \
|
||||
lua_plugin_manage.c
|
||||
lua_module_manage.c
|
||||
|
||||
OBJECTS := lua_plugin_cfunc.o \
|
||||
OBJECTS := lua_module_manage_internal.o \
|
||||
lua_binding_cfunc.o \
|
||||
lua_binding_function.o \
|
||||
lua_plugin_manage.o
|
||||
lua_module_manage.o
|
||||
|
||||
INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include
|
||||
CFLAGS = -g -Wextra -Wall -O0 -fPIC
|
||||
@@ -20,8 +22,8 @@ LDLIBS = -L$(TOPDIR)/dependence/lib -llua -ltoml -lplugin_manager -ldl -lm
|
||||
|
||||
all:$(OBJECTS)
|
||||
$(CC) $(CFLAGS) -shared -o $(TARGET) $(OBJECTS) $(LDLIBS)
|
||||
mkdir -p $(TOPDIR)/output/libs
|
||||
cp -f $(TARGET) $(TOPDIR)/output/libs
|
||||
# mkdir -p $(TOPDIR)/output/libs
|
||||
# cp -f $(TARGET) $(TOPDIR)/output/libs
|
||||
|
||||
$(OBJECTS):$(SRC)
|
||||
$(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SRC) -c $^
|
||||
|
||||
116
src/lua_binding_cfunc.c
Normal file
116
src/lua_binding_cfunc.c
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "lua_binding_cfunc.h"
|
||||
#include "lua_module_manage_internal.h"
|
||||
|
||||
static inline struct lua_state *lua_fn_arg_pair_get_thread_state(struct lua_fn_arg_pair *pair)
|
||||
{
|
||||
struct lua_module_manager *lua_mod_mgr = pair->lua_mod_mgr;
|
||||
int thread_id = stellar_module_manager_get_thread_id(lua_mod_mgr->mod_mgr);
|
||||
return lua_mod_mgr->state_array[thread_id];
|
||||
}
|
||||
|
||||
void lua_manager_mq_msg_free_cb_func(void *msg, void *msg_free_arg)
|
||||
{
|
||||
if (!msg_free_arg)
|
||||
return;
|
||||
struct lua_fn_arg_pair *free_arg = (struct lua_fn_arg_pair *)msg_free_arg;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(free_arg);
|
||||
|
||||
struct lua_cdata param[2];
|
||||
if (lua_context_check_if_context(msg))
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_CONTEXT, msg, 0);
|
||||
else
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_POINTER, msg, 0);
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_TABLE, NULL, free_arg->lua_arg_ref_id);
|
||||
|
||||
lua_chunk_execute(state, free_arg->lua_fn_ref_id, param, 2, NULL, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_manager_mq_on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg)
|
||||
{
|
||||
if (!on_msg_arg)
|
||||
return;
|
||||
struct lua_fn_arg_pair *msg_arg = (struct lua_fn_arg_pair *)on_msg_arg;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(msg_arg);
|
||||
|
||||
struct lua_cdata param[3];
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_INT, NULL, topic_id);
|
||||
if (lua_context_check_if_context(msg))
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_CONTEXT, msg, 0);
|
||||
else
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_POINTER, msg, 0);
|
||||
lua_cdata_data_set(¶m[2], DATATYPE_TABLE, NULL, msg_arg->lua_arg_ref_id);
|
||||
|
||||
lua_chunk_execute(state, msg_arg->lua_fn_ref_id, param, 3, NULL, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_manager_mq_on_msg_dispatch_cb_func(int topic_id, void *msg, on_msg_cb_func *on_msg_cb, void *on_msg_cb_arg, void *dispatch_arg)
|
||||
{
|
||||
if (!dispatch_arg)
|
||||
return;
|
||||
struct lua_fn_arg_pair *dis_arg = (struct lua_fn_arg_pair *)dispatch_arg;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(dis_arg);
|
||||
|
||||
struct lua_cdata param[4];
|
||||
struct lua_context *new_context = lua_context_new(state);
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_INT, NULL, topic_id);
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_CONTEXT, msg, 0);
|
||||
lua_cdata_data_set(¶m[2], DATATYPE_TABLE, 0, dis_arg->lua_arg_ref_id);
|
||||
lua_cdata_data_set(¶m[3], DATATYPE_CONTEXT, (void *)new_context, 0);
|
||||
|
||||
lua_chunk_execute(state, dis_arg->lua_fn_ref_id, param, 4, NULL, 0, NULL, 0);
|
||||
((lua_mq_on_msg_cb_func *)(void *)on_msg_cb)(topic_id, msg, on_msg_cb_arg, (void *)new_context);
|
||||
|
||||
lua_context_free(new_context);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_manager_packet_on_stage_callback(enum packet_stage stage, struct packet *pkt, void *args)
|
||||
{
|
||||
if (!args)
|
||||
return;
|
||||
struct lua_fn_arg_pair *on_stage_callback = (struct lua_fn_arg_pair *)args;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(on_stage_callback);
|
||||
|
||||
struct lua_cdata param[3];
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_INT, NULL, stage);
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_POINTER, pkt, 0);
|
||||
lua_cdata_data_set(¶m[2], DATATYPE_TABLE, NULL, on_stage_callback->lua_arg_ref_id);
|
||||
|
||||
lua_chunk_execute(state, on_stage_callback->lua_fn_ref_id, param, 3, NULL, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_manager_session_callback(struct session *sess, struct packet *pkt, void *args)
|
||||
{
|
||||
if (!args)
|
||||
return;
|
||||
struct lua_fn_arg_pair *sess_callback = (struct lua_fn_arg_pair *)args;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(sess_callback);
|
||||
|
||||
struct lua_cdata param[3];
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_POINTER, sess, 0);
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_POINTER, pkt, 0);
|
||||
lua_cdata_data_set(¶m[2], DATATYPE_TABLE, NULL, sess_callback->lua_arg_ref_id);
|
||||
|
||||
lua_chunk_execute(state, sess_callback->lua_fn_ref_id, param, 3, NULL, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_manager_tcp_stream_callback(struct session *sess, const char *tcp_payload, uint32_t tcp_payload_len, void *args)
|
||||
{
|
||||
if (!args)
|
||||
return;
|
||||
struct lua_fn_arg_pair *tcp_stream_callback = (struct lua_fn_arg_pair *)args;
|
||||
struct lua_state *state = lua_fn_arg_pair_get_thread_state(tcp_stream_callback);
|
||||
|
||||
struct lua_cdata param[4];
|
||||
lua_cdata_data_set(¶m[0], DATATYPE_POINTER, sess, 0);
|
||||
lua_cdata_data_set(¶m[1], DATATYPE_BUFF, (void *)tcp_payload, (int)tcp_payload_len);
|
||||
lua_cdata_data_set(¶m[2], DATATYPE_INT, NULL, (int)tcp_payload_len);
|
||||
lua_cdata_data_set(¶m[3], DATATYPE_TABLE, NULL, tcp_stream_callback->lua_arg_ref_id);
|
||||
|
||||
lua_chunk_execute(state, tcp_stream_callback->lua_fn_ref_id, param, 3, NULL, 0, NULL, 0);
|
||||
return;
|
||||
}
|
||||
17
src/lua_binding_cfunc.h
Normal file
17
src/lua_binding_cfunc.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef LUA_MODULE_MANAGE_BINDING_CFUNC_H
|
||||
#define LUA_MODULE_MANAGE_BINDING_CFUNC_H
|
||||
|
||||
#include "stellar/module_manager.h"
|
||||
#include "stellar/packet_manager.h"
|
||||
#include "stellar/session_manager.h"
|
||||
|
||||
void lua_manager_mq_msg_free_cb_func(void *msg, void *msg_free_arg);
|
||||
void lua_manager_mq_on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg);
|
||||
void lua_manager_mq_on_msg_dispatch_cb_func(int topic_id, void *msg, on_msg_cb_func *on_msg_cb, void *on_msg_cb_arg, void *dispatch_arg);
|
||||
|
||||
void lua_manager_packet_on_stage_callback(enum packet_stage stage, struct packet *pkt, void *args);
|
||||
|
||||
void lua_manager_session_callback(struct session *sess, struct packet *pkt, void *args);
|
||||
void lua_manager_tcp_stream_callback(struct session *sess, const char *tcp_payload, uint32_t tcp_payload_len, void *args);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,53 +1,32 @@
|
||||
#include "stellar/stellar.h"
|
||||
#include "stellar/packet_mq.h"
|
||||
#include "stellar/session.h"
|
||||
#include "stellar/session_mq.h"
|
||||
#ifndef LUA_MODULE_MANAGE_BINDING_FUNCTION_H
|
||||
#define LUA_MODULE_MANAGE_BINDING_FUNCTION_H
|
||||
|
||||
#include "lua_plugin_manage_internal.h"
|
||||
#include "lua_module_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_mq_schema_get_topic_id(struct lua_state *state);
|
||||
int lua_mq_schema_create_topic(struct lua_state *state);
|
||||
int lua_mq_schema_update_topic(struct lua_state *state);
|
||||
int lua_mq_shcema_destory_topic(struct lua_state *state);
|
||||
int lua_mq_schema_subscribe(struct lua_state *state);
|
||||
int lua_mq_runtime_publish_message(struct lua_state *state);
|
||||
|
||||
/* 注册函数 */
|
||||
int lua_session_plugin_regist(struct lua_state *state);
|
||||
int lua_packet_plugin_regist(struct lua_state *state);
|
||||
int lua_module_manager_get_thread_id(struct lua_state *state);
|
||||
int lua_module_manager_get_max_thread_num(struct lua_state *state);
|
||||
int lua_module_manager_get_mq_runtime(struct lua_state *state);
|
||||
int lua_module_manager_get_mq_schema(struct lua_state *state);
|
||||
int lua_module_manager_get_logger(struct lua_state *state);
|
||||
|
||||
/* struct session结构相关的函数 */
|
||||
int lua_session_get_type(struct lua_state *state);
|
||||
int lua_packet_get_direction(struct lua_state *state);
|
||||
int lua_packet_get_payload(struct lua_state *state);
|
||||
int lua_packet_get_payload_len(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);
|
||||
int lua_packet_manager_subscribe(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);
|
||||
int lua_session_get0_current_packet(struct lua_state *state);
|
||||
|
||||
/* session相关其他函数 */
|
||||
int lua_session_get0_current_payload(struct lua_state *state);
|
||||
int lua_session_manager_subscribe_tcp(struct lua_state *state);
|
||||
int lua_session_manager_subscribe_udp(struct lua_state *state);
|
||||
int lua_session_manager_subscribe_control_packet(struct lua_state *state);
|
||||
int lua_session_manager_subscribe_tcp_stream(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);
|
||||
#endif
|
||||
137
src/lua_module_manage.c
Normal file
137
src/lua_module_manage.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include "lua_module_manage_internal.h"
|
||||
#include "lua_binding_function.h"
|
||||
|
||||
#include "stellar/utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MQ_SCHEMA_SPACE_NAME "mq_schema"
|
||||
#define MQ_RUNTIME_SPACE_NAME "mq_runtime"
|
||||
#define MODULE_MANAGER_SPACE_NAME "module_manager"
|
||||
#define PACKET_SPACE_NAME "packet"
|
||||
#define PACKET_MANAGER_SPACE_NAME "packet_manager"
|
||||
#define SESSION_SPACE_NAME "session"
|
||||
#define SESSION_MANAGER_SPACE_NAME "session_manager"
|
||||
|
||||
struct lua_bind_func_spec lua_bind_function[] = {
|
||||
{lua_mq_schema_get_topic_id, MQ_SCHEMA_SPACE_NAME, "get_topic_id"},
|
||||
{lua_mq_schema_create_topic, MQ_SCHEMA_SPACE_NAME, "create_topic"},
|
||||
{lua_mq_schema_update_topic, MQ_SCHEMA_SPACE_NAME, "update_topic"},
|
||||
{lua_mq_shcema_destory_topic, MQ_SCHEMA_SPACE_NAME, "destory_topic"},
|
||||
{lua_mq_schema_subscribe, MQ_SCHEMA_SPACE_NAME, "subcribe"},
|
||||
{lua_mq_runtime_publish_message, MQ_RUNTIME_SPACE_NAME, "publish_message"},
|
||||
|
||||
{lua_module_manager_get_thread_id, MODULE_MANAGER_SPACE_NAME, "get_thread_id"},
|
||||
{lua_module_manager_get_max_thread_num, MODULE_MANAGER_SPACE_NAME, "get_max_thread_num"},
|
||||
{lua_module_manager_get_mq_runtime, MODULE_MANAGER_SPACE_NAME, "get_mq_runtime"},
|
||||
{lua_module_manager_get_mq_schema, MODULE_MANAGER_SPACE_NAME, "get_mq_schema"},
|
||||
{lua_module_manager_get_logger, MODULE_MANAGER_SPACE_NAME, "get_logger"},
|
||||
|
||||
{lua_packet_get_direction, PACKET_SPACE_NAME, "get_direction"},
|
||||
{lua_packet_get_payload, PACKET_SPACE_NAME, "get_payload"},
|
||||
{lua_packet_get_payload_len, PACKET_SPACE_NAME, "get_payload_len"},
|
||||
|
||||
{lua_packet_manager_subscribe, PACKET_MANAGER_SPACE_NAME, "subscribe"},
|
||||
|
||||
{lua_session_get0_current_packet, SESSION_SPACE_NAME, "get0_current_payload"},
|
||||
|
||||
{lua_session_manager_subscribe_tcp, SESSION_MANAGER_SPACE_NAME, "subscribe_tcp"},
|
||||
{lua_session_manager_subscribe_udp, SESSION_MANAGER_SPACE_NAME, "subscribe_udp"},
|
||||
{lua_session_manager_subscribe_control_packet, SESSION_MANAGER_SPACE_NAME, "subscribe_control_packet"},
|
||||
{lua_session_manager_subscribe_tcp_stream, SESSION_MANAGER_SPACE_NAME, "subscribe_tcp_stream"},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
#define ENUM_PACKET_STAGE_SPACE_NAME "packet_stage"
|
||||
|
||||
struct lua_bind_data_spec lua_bind_data[] = {
|
||||
{DATATYPE_INT, "0", ENUM_PACKET_STAGE_SPACE_NAME, "prerouting"},
|
||||
{DATATYPE_INT, "1", ENUM_PACKET_STAGE_SPACE_NAME, "input"},
|
||||
{DATATYPE_INT, "2", ENUM_PACKET_STAGE_SPACE_NAME, "forward"},
|
||||
{DATATYPE_INT, "3", ENUM_PACKET_STAGE_SPACE_NAME, "output"},
|
||||
{DATATYPE_INT, "4", ENUM_PACKET_STAGE_SPACE_NAME, "postrouting"},
|
||||
{DATATYPE_END, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
static void lua_module_manager_free(struct lua_module_manager *lua_mod_mgr)
|
||||
{
|
||||
if (!lua_mod_mgr)
|
||||
return;
|
||||
for (size_t script_index = 0; script_index < lua_mod_mgr->load_script_num; ++script_index)
|
||||
{
|
||||
lua_chunk_execute(lua_mod_mgr->state_array[0], lua_mod_mgr->load_script_array[script_index].lua_unload_fn_ref_id, NULL, 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
for (size_t state_index = 0; state_index < lua_mod_mgr->state_num; ++state_index)
|
||||
{
|
||||
lua_state_free(lua_mod_mgr->state_array[state_index]);
|
||||
}
|
||||
FREE(lua_mod_mgr);
|
||||
return;
|
||||
}
|
||||
|
||||
struct stellar_module *lua_module_manager_on_init(struct stellar_module_manager *mod_mgr)
|
||||
{
|
||||
struct stellar_module *new_mod = NULL;
|
||||
struct lua_module_manager *new_lua_manage = CALLOC(struct lua_module_manager, 1);
|
||||
memset(new_lua_manage, 0, sizeof(struct lua_module_manager));
|
||||
new_lua_manage->mod_mgr = mod_mgr;
|
||||
|
||||
int thread_count = stellar_module_manager_get_max_thread_num(mod_mgr);
|
||||
if (thread_count <= 0)
|
||||
goto init_lua_module_finish;
|
||||
new_lua_manage->state_num = (size_t)thread_count;
|
||||
new_lua_manage->state_array = CALLOC(struct lua_state *, thread_count);
|
||||
memset(new_lua_manage->state_array, 0, thread_count * sizeof(struct lua_state *));
|
||||
for (size_t thread_index = 0; thread_index < new_lua_manage->state_num; ++thread_index)
|
||||
{
|
||||
new_lua_manage->state_array[thread_index] = lua_state_new(new_lua_manage);
|
||||
lua_cbinding_function(new_lua_manage->state_array[thread_index], lua_bind_function, (sizeof(lua_bind_function) / sizeof(struct lua_bind_func_spec)));
|
||||
lua_cbinding_data(new_lua_manage->state_array[thread_index], lua_bind_data, (sizeof(lua_bind_data) / sizeof(struct lua_bind_data_spec)));
|
||||
}
|
||||
|
||||
struct lua_module_spec *module_spec = lua_module_config_file_load(LUA_MODULE_MANAGE_CONF_PATH, &new_lua_manage->load_script_num);
|
||||
if (new_lua_manage->load_script_num && module_spec)
|
||||
{
|
||||
new_lua_manage->load_script_array = CALLOC(struct lua_load_script, new_lua_manage->load_script_num);
|
||||
for (size_t script_index = 0; script_index < new_lua_manage->load_script_num; ++script_index)
|
||||
{
|
||||
if (lua_load_script_load_single_specific(&new_lua_manage->load_script_array[script_index], new_lua_manage->state_array[0], &module_spec[script_index]))
|
||||
{
|
||||
lua_module_spec_free(module_spec, new_lua_manage->load_script_num);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto init_lua_module_finish;
|
||||
}
|
||||
lua_module_spec_free(module_spec, new_lua_manage->load_script_num);
|
||||
for (size_t script_index = 0; script_index < new_lua_manage->load_script_num; ++script_index)
|
||||
{
|
||||
lua_chunk_execute(new_lua_manage->state_array[0], new_lua_manage->load_script_array[script_index].lua_load_fn_ref_id, NULL, 0, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
for (size_t thread_index = 1; thread_index < new_lua_manage->state_num; ++thread_index)
|
||||
{
|
||||
lua_state_copy_ref_value(new_lua_manage->state_array[thread_index], new_lua_manage->state_array[0]);
|
||||
}
|
||||
|
||||
init_lua_module_finish:
|
||||
new_mod = stellar_module_new(LUA_MODULE_MANAGE_MODULE_NAME, (void *)new_lua_manage);
|
||||
return new_mod;
|
||||
err:
|
||||
if (new_lua_manage)
|
||||
lua_module_manager_free(new_lua_manage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lua_module_manager_on_exit(struct stellar_module_manager *mod_mgr __unused, struct stellar_module *mod)
|
||||
{
|
||||
struct lua_module_manager *lua_mod_mgr = (struct lua_module_manager *)stellar_module_get_ctx(mod);
|
||||
lua_module_manager_free(lua_mod_mgr);
|
||||
stellar_module_free(mod);
|
||||
return;
|
||||
}
|
||||
862
src/lua_module_manage_internal.c
Normal file
862
src/lua_module_manage_internal.c
Normal file
@@ -0,0 +1,862 @@
|
||||
#include "lua_module_manage_internal.h"
|
||||
|
||||
#include "stellar/utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <toml.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* lua state */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_state
|
||||
{
|
||||
lua_State *state;
|
||||
};
|
||||
|
||||
#define LUA_GLOBAL_INFO_REF_ID (LUA_RIDX_LAST + 2)
|
||||
#define LUA_GLOBAL_INFO_MANAGE_POINTER "__global_lua_module_manage"
|
||||
// #define LUA_GLOBAL_FUNCTION_REF_ID (LUA_RIDX_LAST + 3)
|
||||
// #define LUA_GLOBAL_CONTEXT_REF_ID (LUA_RIDX_LAST + 4)
|
||||
|
||||
struct lua_state *lua_state_new(struct lua_module_manager *lua_mod_mgr)
|
||||
{
|
||||
lua_State *new_L = luaL_newstate();
|
||||
if (!new_L)
|
||||
return NULL;
|
||||
luaL_openlibs(new_L);
|
||||
|
||||
lua_newtable(new_L);
|
||||
lua_pushlightuserdata(new_L, (void *)lua_mod_mgr);
|
||||
lua_setfield(new_L, -2, LUA_GLOBAL_INFO_MANAGE_POINTER);
|
||||
int global_ref = luaL_ref(new_L, LUA_REGISTRYINDEX);
|
||||
lua_settop(new_L, 0);
|
||||
assert(global_ref == LUA_GLOBAL_INFO_REF_ID);
|
||||
|
||||
return (struct lua_state *)new_L;
|
||||
}
|
||||
|
||||
void lua_state_free(struct lua_state *state)
|
||||
{
|
||||
lua_State *L = (lua_State *)state;
|
||||
lua_close(L);
|
||||
return;
|
||||
}
|
||||
|
||||
struct lua_module_manager *lua_state_get_lua_module_manager(struct lua_state *state)
|
||||
{
|
||||
lua_State *L = (lua_State *)state;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_INFO_REF_ID);
|
||||
lua_getfield(L, -1, LUA_GLOBAL_INFO_MANAGE_POINTER);
|
||||
struct lua_module_manager *lua_mod_mgr = (struct lua_module_manager *)lua_topointer(L, -1);
|
||||
lua_settop(L, 0);
|
||||
return lua_mod_mgr;
|
||||
}
|
||||
|
||||
int lua_state_copy_ref_value(struct lua_state *to, struct lua_state *from)
|
||||
{
|
||||
if (!to || !from)
|
||||
return PARAM_ERR;
|
||||
lua_State *from_L = (lua_State *)from;
|
||||
lua_State *to_L = (lua_State *)to;
|
||||
|
||||
lua_newtable(from_L);
|
||||
int lua_ref_max_id = luaL_ref(from_L, LUA_REGISTRYINDEX);
|
||||
int data_ret = 0;
|
||||
for (int ref_index = (LUA_GLOBAL_INFO_REF_ID + 1); ref_index < lua_ref_max_id; ++ref_index)
|
||||
{
|
||||
struct lua_cdata *trans_data = lua_cdata_new();
|
||||
lua_settop(from_L, 0);
|
||||
lua_rawgeti(from_L, LUA_REGISTRYINDEX, ref_index);
|
||||
data_ret = lua_cdata_pop_stack(from, trans_data);
|
||||
if (data_ret)
|
||||
{
|
||||
lua_cdata_free(trans_data);
|
||||
return data_ret;
|
||||
}
|
||||
data_ret = lua_cdata_push_stack(to, trans_data);
|
||||
if (data_ret)
|
||||
{
|
||||
lua_cdata_free(trans_data);
|
||||
return data_ret;
|
||||
}
|
||||
int ref_id = luaL_ref(to_L, LUA_REGISTRYINDEX);
|
||||
lua_cdata_free(trans_data);
|
||||
if (ref_id != ref_index)
|
||||
{
|
||||
return STATE_COPY_REF_VALUE_ERR;
|
||||
}
|
||||
}
|
||||
luaL_unref(from_L, LUA_REGISTRYINDEX, lua_ref_max_id);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* read lua module config */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_module_spec *lua_module_config_file_load(const char *config_file_name, size_t *spec_num)
|
||||
{
|
||||
*spec_num = 0;
|
||||
if (access(config_file_name, F_OK))
|
||||
return NULL;
|
||||
FILE *fp = fopen(config_file_name, "r");
|
||||
if (!fp)
|
||||
return NULL;
|
||||
char errbuff[256] = {0};
|
||||
toml_table_t *toml_table = toml_parse_file(fp, errbuff, sizeof(errbuff));
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
if (!toml_table)
|
||||
return NULL;
|
||||
toml_array_t *module_array = toml_array_in(toml_table, "module");
|
||||
if (!module_array)
|
||||
{
|
||||
toml_free(toml_table);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int specific_nelem = toml_array_nelem(module_array);
|
||||
struct lua_module_spec *new_spec = CALLOC(struct lua_module_spec, specific_nelem);
|
||||
memset(new_spec, 0, (sizeof(struct lua_module_spec) * specific_nelem));
|
||||
|
||||
for (int i = 0; i < specific_nelem; ++i)
|
||||
{
|
||||
toml_table_t *plugin = toml_table_at(module_array, i);
|
||||
const char *raw_filepath = toml_raw_in(plugin, "path");
|
||||
const char *raw_load_func_name = toml_raw_in(plugin, "init");
|
||||
const char *raw_unload_func_name = toml_raw_in(plugin, "exit");
|
||||
|
||||
/* TODO:是不是需要进行一下配置检查 */
|
||||
new_spec[i].spec_file_path = strdup(raw_filepath);
|
||||
new_spec[i].spec_load_func_name = strdup(raw_load_func_name);
|
||||
new_spec[i].spec_unload_func_name = strdup(raw_unload_func_name);
|
||||
}
|
||||
toml_free(toml_table);
|
||||
*spec_num = specific_nelem;
|
||||
return new_spec;
|
||||
}
|
||||
|
||||
void lua_module_spec_free(struct lua_module_spec spec[], size_t spec_num)
|
||||
{
|
||||
if (!spec)
|
||||
return;
|
||||
for (size_t spec_index = 0; spec_index < spec_num; ++spec_index)
|
||||
{
|
||||
if (spec[spec_index].spec_file_path)
|
||||
FREE(spec[spec_index].spec_file_path);
|
||||
if (spec[spec_index].spec_load_func_name)
|
||||
FREE(spec[spec_index].spec_load_func_name);
|
||||
if (spec[spec_index].spec_unload_func_name)
|
||||
FREE(spec[spec_index].spec_unload_func_name);
|
||||
}
|
||||
FREE(spec);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* binding function or data to state */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
static int lua_cbinding_single_function(struct lua_state *state, struct lua_bind_func_spec *func_spec)
|
||||
{
|
||||
lua_State *L = (lua_State *)state;
|
||||
if (func_spec->space_name)
|
||||
{
|
||||
lua_getglobal(L, func_spec->space_name);
|
||||
if (lua_type(L, -1) == LUA_TNIL)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CFUNC_BIND_NAMESPACE_CONFLICT;
|
||||
}
|
||||
lua_getfield(L, -1, func_spec->func_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CFUNC_BIND_NAME_CONFLICT;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pushcfunction(L, (lua_CFunction)func_spec->func);
|
||||
lua_setfield(L, -2, func_spec->func_name);
|
||||
lua_setglobal(L, func_spec->space_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_getglobal(L, func_spec->func_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CFUNC_BIND_NAME_CONFLICT;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
lua_pushcfunction(L, (lua_CFunction)func_spec->func);
|
||||
lua_setglobal(L, func_spec->func_name);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec)
|
||||
{
|
||||
lua_State *L = (lua_State *)state;
|
||||
if (data_spec->space_name)
|
||||
{
|
||||
lua_getglobal(L, data_spec->space_name);
|
||||
if (lua_type(L, -1) == LUA_TNIL)
|
||||
{
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CDATA_BIND_NAMESPACE_CONFLICT;
|
||||
}
|
||||
lua_getfield(L, -1, data_spec->data_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CDATA_BIND_NAME_CONFLICT;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
switch (data_spec->data_type)
|
||||
{
|
||||
case DATATYPE_BOOL:
|
||||
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
|
||||
lua_pushboolean(L, 1);
|
||||
else
|
||||
lua_pushboolean(L, 0);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, atoi(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushlstring(L, (const char *)data_spec->data_value, strlen(data_spec->data_value));
|
||||
break;
|
||||
default:
|
||||
lua_settop(L, 0);
|
||||
return CDATA_BIND_TYPE_ERR;
|
||||
}
|
||||
lua_setfield(L, -2, data_spec->data_name);
|
||||
lua_setglobal(L, data_spec->space_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_getglobal(L, data_spec->data_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CDATA_BIND_NAME_CONFLICT;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
switch (data_spec->data_type)
|
||||
{
|
||||
case DATATYPE_BOOL:
|
||||
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
|
||||
lua_pushboolean(L, 1);
|
||||
else
|
||||
lua_pushboolean(L, 0);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, atoi(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushlstring(L, (const char *)data_spec->data_value, strlen(data_spec->data_value));
|
||||
break;
|
||||
default:
|
||||
lua_settop(L, 0);
|
||||
return CDATA_BIND_TYPE_ERR;
|
||||
}
|
||||
lua_setglobal(L, data_spec->data_name);
|
||||
}
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cbinding_function(struct lua_state *state, struct lua_bind_func_spec bind_function[], size_t bind_func_num)
|
||||
{
|
||||
if (!state || !bind_function)
|
||||
return PARAM_ERR;
|
||||
for (size_t index = 0; index < bind_func_num; ++index)
|
||||
{
|
||||
if (bind_function[index].func && bind_function[index].func_name)
|
||||
{
|
||||
int bind_ret = lua_cbinding_single_function(state, &bind_function[index]);
|
||||
if (bind_ret)
|
||||
return bind_ret;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num)
|
||||
{
|
||||
if (!state || !bind_data)
|
||||
return PARAM_ERR;
|
||||
for (size_t index = 0; index < bind_data_num; ++index)
|
||||
{
|
||||
if (bind_data[index].data_value && bind_data[index].data_name)
|
||||
{
|
||||
int bind_ret = lua_cbinding_single_data(state, &bind_data[index]);
|
||||
if (bind_ret)
|
||||
return bind_ret;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* context */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
const char *context_magic_code = "ctx_code";
|
||||
struct lua_context
|
||||
{
|
||||
const char *magic_code;
|
||||
struct lua_state *state;
|
||||
int lua_context_ref_id;
|
||||
};
|
||||
|
||||
struct lua_context *lua_context_new(struct lua_state *state)
|
||||
{
|
||||
if (!state)
|
||||
return NULL;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
lua_newtable(L);
|
||||
int ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
struct lua_context *new_context = lua_context_new_with_ref_id(state, ref_id);
|
||||
if (!new_context)
|
||||
luaL_unref(L, LUA_REGISTRYINDEX, ref_id);
|
||||
return new_context;
|
||||
}
|
||||
|
||||
struct lua_context *lua_context_new_with_ref_id(struct lua_state *state, int ref_id)
|
||||
{
|
||||
if (!state)
|
||||
return NULL;
|
||||
struct lua_context *new_context = CALLOC(struct lua_context, 1);
|
||||
new_context->magic_code = context_magic_code;
|
||||
new_context->state = state;
|
||||
new_context->lua_context_ref_id = ref_id;
|
||||
return new_context;
|
||||
}
|
||||
|
||||
void lua_context_free(struct lua_context *context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
luaL_unref((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
|
||||
FREE(context);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_context_push_stack(struct lua_context *context)
|
||||
{
|
||||
if (context && context->lua_context_ref_id)
|
||||
lua_rawgeti((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
|
||||
return;
|
||||
}
|
||||
|
||||
int lua_context_check_if_context(void *context)
|
||||
{
|
||||
struct lua_context *check = (struct lua_context *)context;
|
||||
if (check && check->magic_code == context_magic_code)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* trans data between C and Lua */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_cnode
|
||||
{
|
||||
char *node_string_key;
|
||||
int node_integer_key;
|
||||
struct lua_cdata *node_data;
|
||||
};
|
||||
|
||||
struct lua_ctable
|
||||
{
|
||||
size_t array_size;
|
||||
size_t node_size;
|
||||
struct lua_cdata **array_data;
|
||||
struct lua_cnode **node_data;
|
||||
};
|
||||
|
||||
static struct lua_ctable *lua_ctable_new(void);
|
||||
static void lua_ctable_free(struct lua_ctable *ctable);
|
||||
static int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable);
|
||||
static int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable);
|
||||
static struct lua_cnode *lua_cnode_new(void);
|
||||
static void lua_cnode_free(struct lua_cnode *cnode);
|
||||
static int lua_cdata_function_reader(lua_State *state __unused, const void *p, size_t sz, void *ud);
|
||||
static const char *lua_cdata_function_writer(lua_State *state __unused, void *ud, size_t *sz);
|
||||
|
||||
struct lua_cdata *lua_cdata_new(void)
|
||||
{
|
||||
struct lua_cdata *new_data = CALLOC(struct lua_cdata, 1);
|
||||
memset(new_data, 0, sizeof(struct lua_cdata));
|
||||
return new_data;
|
||||
}
|
||||
|
||||
static void lua_cdata_inner_data_free(struct lua_cdata *cdata)
|
||||
{
|
||||
cdata->type = 0;
|
||||
cdata->data_len = 0;
|
||||
switch (cdata->type)
|
||||
{
|
||||
case DATATYPE_STRING:
|
||||
FREE(cdata->string);
|
||||
break;
|
||||
case DATATYPE_LUA_TABLE:
|
||||
lua_ctable_free(cdata->ctable);
|
||||
break;
|
||||
case DATATYPE_BUFF:
|
||||
FREE(cdata->buff);
|
||||
break;
|
||||
case DATATYPE_FUNCTION:
|
||||
FREE(cdata->function);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_cdata_free(struct lua_cdata *cdata)
|
||||
{
|
||||
if (!cdata)
|
||||
return;
|
||||
lua_cdata_inner_data_free(cdata);
|
||||
FREE(cdata);
|
||||
return;
|
||||
}
|
||||
|
||||
int lua_cdata_data_set(struct lua_cdata *cdata, enum LUA_DATATYPE type, void *value_p, int value_i)
|
||||
{
|
||||
if (!cdata)
|
||||
return PARAM_ERR;
|
||||
lua_cdata_inner_data_free(cdata);
|
||||
switch (type)
|
||||
{
|
||||
case DATATYPE_NIL:
|
||||
break;
|
||||
case DATATYPE_BOOL:
|
||||
cdata->bool = value_i;
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
cdata->integer = value_i;
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
cdata->number = *(double *)value_p;
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
cdata->string = CALLOC(char, value_i);
|
||||
memcpy(cdata->string, value_p, (size_t)value_i);
|
||||
break;
|
||||
case DATATYPE_BUFF:
|
||||
cdata->buff = CALLOC(char, value_i);
|
||||
memcpy(cdata->buff, value_p, (size_t)value_i);
|
||||
cdata->data_len = (size_t)value_i;
|
||||
break;
|
||||
case DATATYPE_TABLE:
|
||||
cdata->table = value_i;
|
||||
break;
|
||||
case DATATYPE_POINTER:
|
||||
cdata->pointer = value_p;
|
||||
break;
|
||||
case DATATYPE_CONTEXT:
|
||||
cdata->context = (struct lua_context *)value_p;
|
||||
break;
|
||||
default:
|
||||
return CDATA_SET_VALUE_TYPE_UNSUPPORT;
|
||||
}
|
||||
cdata->type = type;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata)
|
||||
{
|
||||
if (!state || !cdata)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
switch (cdata->type)
|
||||
{
|
||||
case DATATYPE_NIL:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
case DATATYPE_BOOL:
|
||||
lua_pushboolean(L, cdata->bool);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, cdata->integer);
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, cdata->number);
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushstring(L, cdata->string);
|
||||
break;
|
||||
case DATATYPE_BUFF:
|
||||
lua_pushlstring(L, cdata->buff, cdata->data_len);
|
||||
break;
|
||||
case DATATYPE_TABLE:
|
||||
if (cdata->table)
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, cdata->table);
|
||||
break;
|
||||
case DATATYPE_LUA_TABLE:
|
||||
lua_ctable_push_stack(state, cdata->ctable);
|
||||
break;
|
||||
case DATATYPE_POINTER:
|
||||
lua_pushlightuserdata(L, (void *)cdata->pointer);
|
||||
break;
|
||||
case DATATYPE_CONTEXT:
|
||||
lua_context_push_stack(cdata->context);
|
||||
break;
|
||||
case DATATYPE_FUNCTION:
|
||||
lua_load(L, lua_cdata_function_writer, (void *)cdata, NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
return CDATA_PUSH_STACK_TYPE_UNKNOWN;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata)
|
||||
{
|
||||
if (!state || !cdata)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
lua_cdata_inner_data_free(cdata);
|
||||
switch (lua_type(L, -1))
|
||||
{
|
||||
case LUA_TNIL:
|
||||
cdata->type = DATATYPE_NIL;
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
cdata->type = DATATYPE_BOOL;
|
||||
cdata->bool = lua_toboolean(L, -1);
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
cdata->type = DATATYPE_POINTER;
|
||||
cdata->pointer = (void *)lua_topointer(L, -1);
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
cdata->type = DATATYPE_NUM;
|
||||
cdata->number = lua_tonumber(L, -1);
|
||||
int try_int = (int)cdata->number;
|
||||
if ((double)try_int == cdata->number)
|
||||
{
|
||||
cdata->type = DATATYPE_INT;
|
||||
cdata->integer = lua_tointeger(L, -1);
|
||||
}
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
cdata->type = DATATYPE_STRING;
|
||||
cdata->string = (char *)strdup(lua_tostring(L, -1));
|
||||
break;
|
||||
case LUA_TTABLE:
|
||||
cdata->type = DATATYPE_LUA_TABLE;
|
||||
cdata->ctable = lua_ctable_new();
|
||||
lua_ctable_pop_stack(state, cdata->ctable);
|
||||
break;
|
||||
case LUA_TFUNCTION:
|
||||
cdata->type = DATATYPE_FUNCTION;
|
||||
lua_dump(L, lua_cdata_function_reader, cdata, 0);
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
cdata->type = DATATYPE_POINTER;
|
||||
cdata->pointer = (void *)lua_topointer(L, -1);
|
||||
break;
|
||||
default:
|
||||
return CDATA_POP_STACK_TYPE_UNSUPPORT;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static struct lua_ctable *lua_ctable_new(void)
|
||||
{
|
||||
struct lua_ctable *new_table = CALLOC(struct lua_ctable, 1);
|
||||
memset(new_table, 0, sizeof(struct lua_ctable));
|
||||
return new_table;
|
||||
}
|
||||
|
||||
static void lua_ctable_free(struct lua_ctable *ctable)
|
||||
{
|
||||
if (!ctable)
|
||||
return;
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
lua_cdata_free(ctable->array_data[array_index]);
|
||||
}
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
lua_cnode_free(ctable->node_data[node_index]);
|
||||
}
|
||||
if (ctable->array_data)
|
||||
FREE(ctable->array_data);
|
||||
if (ctable->node_data)
|
||||
FREE(ctable->node_data);
|
||||
FREE(ctable);
|
||||
return;
|
||||
}
|
||||
|
||||
static int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable)
|
||||
{
|
||||
if (!state || !ctable)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
lua_newtable(L);
|
||||
int push_ret = 0;
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
lua_pushinteger(L, (array_index + 1));
|
||||
push_ret = lua_cdata_push_stack(state, ctable->array_data[array_index]);
|
||||
if (push_ret)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return push_ret;
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
if (ctable->node_data[node_index]->node_string_key)
|
||||
lua_pushstring(L, ctable->node_data[node_index]->node_string_key);
|
||||
else
|
||||
lua_pushinteger(L, ctable->node_data[node_index]->node_integer_key);
|
||||
push_ret = lua_cdata_push_stack(state, ctable->node_data[node_index]->node_data);
|
||||
if (push_ret)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return push_ret;
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable)
|
||||
{
|
||||
if (!state || !ctable)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
/* 获取table长度 */
|
||||
ctable->array_size = (size_t)lua_rawlen(L, -1);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2))
|
||||
{
|
||||
ctable->node_size++;
|
||||
if (lua_type(L, -2) == LUA_TNUMBER)
|
||||
{
|
||||
int numkey = lua_tointeger(L, -2);
|
||||
if (numkey > 0 && numkey <= (int)ctable->array_size)
|
||||
ctable->node_size--;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
ctable->array_data = CALLOC(struct lua_cdata *, ctable->array_size);
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
ctable->array_data[array_index] = lua_cdata_new();
|
||||
}
|
||||
ctable->node_data = CALLOC(struct lua_cnode *, ctable->node_size);
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
ctable->node_data[node_index] = lua_cnode_new();
|
||||
}
|
||||
|
||||
/* 依次获取数据 */
|
||||
int key_index = 0;
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2))
|
||||
{
|
||||
if (lua_type(L, -2) == LUA_TNUMBER)
|
||||
{
|
||||
int numkey = lua_tointeger(L, -2);
|
||||
if (numkey > 0 && numkey <= (int)ctable->array_size)
|
||||
lua_cdata_pop_stack(state, ctable->array_data[numkey - 1]);
|
||||
else
|
||||
{
|
||||
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
|
||||
ctable->node_data[key_index]->node_integer_key = lua_tointeger(L, -1);
|
||||
++key_index;
|
||||
}
|
||||
}
|
||||
else if (lua_type(L, -2) == LUA_TSTRING)
|
||||
{
|
||||
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
|
||||
ctable->node_data[key_index]->node_string_key = strdup((char *)lua_tostring(L, -1));
|
||||
++key_index;
|
||||
}
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static struct lua_cnode *lua_cnode_new(void)
|
||||
{
|
||||
struct lua_cnode *new_node = CALLOC(struct lua_cnode, 1);
|
||||
memset(new_node, 0, sizeof(struct lua_cnode));
|
||||
new_node->node_data = lua_cdata_new();
|
||||
return new_node;
|
||||
}
|
||||
|
||||
static void lua_cnode_free(struct lua_cnode *cnode)
|
||||
{
|
||||
if (cnode->node_string_key)
|
||||
FREE(cnode->node_string_key);
|
||||
if (cnode->node_data)
|
||||
lua_cdata_free(cnode->node_data);
|
||||
FREE(cnode);
|
||||
return;
|
||||
}
|
||||
|
||||
static int lua_cdata_function_reader(lua_State *state __unused, const void *p, size_t sz, void *ud)
|
||||
{
|
||||
/* TODO: 这个函数在lua中会被大量调用, 频繁的realloc可能会导致内存碎片化, 后续调整一下内存分配机制 */
|
||||
struct lua_cdata *data = (struct lua_cdata *)ud;
|
||||
data->type = DATATYPE_FUNCTION;
|
||||
if (!data->function)
|
||||
data->function = (void *)calloc(1, sizeof(sz));
|
||||
else
|
||||
data->function = (void *)realloc(data->function, (data->data_len + sz));
|
||||
memcpy((data->function + data->data_len), p, sz);
|
||||
data->data_len += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *lua_cdata_function_writer(lua_State *state __unused, void *ud, size_t *sz)
|
||||
{
|
||||
struct lua_cdata *data = (struct lua_cdata *)ud;
|
||||
*sz = data->data_len;
|
||||
return (const char *)data->function;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* execute one chunk */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
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)
|
||||
{
|
||||
if (!state || fn_ref_id <= 0 || (param_num && !param) || (r_num && !returnvalue))
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, fn_ref_id);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CHUNK_EXECUTE_TYPE_NOT_FUNCTION;
|
||||
}
|
||||
|
||||
int pushret = 0;
|
||||
for (unsigned param_index = 0; param_index < param_num; ++param_index)
|
||||
{
|
||||
if ((pushret = lua_cdata_push_stack(state, ¶m[param_index])))
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return pushret;
|
||||
}
|
||||
}
|
||||
|
||||
if (lua_pcall(L, param_num, LUA_MULTRET, 0))
|
||||
{
|
||||
if (errlog)
|
||||
snprintf(errlog, (err_len - 1), "run script[%d] err %s\n", fn_ref_id, lua_tostring(L, -1));
|
||||
lua_settop(L, 0);
|
||||
return CHUNK_EXECUTE_RUN_CODE_ERR;
|
||||
}
|
||||
|
||||
if (r_num > 0)
|
||||
{
|
||||
int count = lua_gettop(L);
|
||||
/* 如果接收返回值数量不够, 只保留前r_num个返回值 */
|
||||
if (count > (int)r_num)
|
||||
{
|
||||
lua_pop(L, (count - (int)r_num));
|
||||
count = (int)r_num;
|
||||
}
|
||||
int pop_ret = 0;
|
||||
for (int i = (count - 1); i >= 0; --i)
|
||||
{
|
||||
if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i]))))
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return pop_ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_load_script_load_single_specific(struct lua_load_script *script, struct lua_state *state, struct lua_module_spec *module_spec)
|
||||
{
|
||||
if (!state || !module_spec || !script)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
if (luaL_loadfile(L, module_spec->spec_file_path) || lua_pcall(L, 0, 0, 0))
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return SCRIPT_LOAD_FILE_ERR;
|
||||
}
|
||||
|
||||
lua_getglobal(L, module_spec->spec_load_func_name);
|
||||
lua_getglobal(L, module_spec->spec_unload_func_name);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION || lua_type(L, -2) != LUA_TFUNCTION)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return SCRIPT_LOAD_FUNCTION_TYPE_ERR;
|
||||
}
|
||||
script->lua_unload_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_newtable(L);
|
||||
script->lua_script_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
231
src/lua_module_manage_internal.h
Normal file
231
src/lua_module_manage_internal.h
Normal file
@@ -0,0 +1,231 @@
|
||||
#ifndef LUA_MODULE_MANAGE_INTERNAL_H
|
||||
#define LUA_MODULE_MANAGE_INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "lua_module_manage.h"
|
||||
|
||||
struct lua_state;
|
||||
struct lua_module_manager;
|
||||
|
||||
enum LUA_MODULE_ERR_CODE
|
||||
{
|
||||
/* 加载配置到状态机中错误码 */
|
||||
SCRIPT_ERR = -400,
|
||||
SCRIPT_LOAD_FILE_ERR, /* 配置拷贝至状态机过程中无法处理Lua文件 */
|
||||
SCRIPT_LOAD_FUNCTION_TYPE_ERR, /* 获取得到的函数名称不是全局函数, 无法加载 */
|
||||
/* 代码块执行过程中错误码 */
|
||||
CHUNK_ERR = -300,
|
||||
CHUNK_EXECUTE_TYPE_NOT_FUNCTION, /* 执行代码块过程中根据ref_id获取得到的变量不是函数 */
|
||||
CHUNK_EXECUTE_RUN_CODE_ERR, /* 执行代码块运行错误 */
|
||||
/* 函数与全局变量操作错误码 */
|
||||
CDATA_ERR = -200,
|
||||
CFUNC_BIND_NAMESPACE_CONFLICT, /* 命名空间数据类型不符 */
|
||||
CFUNC_BIND_NAME_CONFLICT, /* 绑定函数的函数名称与已有数据冲突 */
|
||||
CDATA_BIND_NAMESPACE_CONFLICT, /* 命名空间数据类型不符 */
|
||||
CDATA_BIND_NAME_CONFLICT, /* 全局变量名称与已有数据冲突 */
|
||||
CDATA_BIND_TYPE_ERR, /* 数据类型无法识别或存在异常 */
|
||||
CDATA_SET_VALUE_TYPE_UNSUPPORT, /* 使用了未识别的数据类型 */
|
||||
CDATA_PUSH_STACK_TYPE_UNKNOWN, /* 入栈数据无法识别数据类型 */
|
||||
CDATA_POP_STACK_TYPE_UNSUPPORT, /* 出栈数据类型不支持出栈 */
|
||||
/* 状态机基础操作中错误码 */
|
||||
STATE_ERR = -100,
|
||||
STATE_COPY_REF_VALUE_ERR, /* 在状态机之间拷贝数据过程中出现异常 */
|
||||
/* 通用返回值 */
|
||||
PARAM_ERR = -1, /* 传入参数错误, 可能是指针为空或类型不符合 */
|
||||
SUCCESS = 0, /* 运行成功 */
|
||||
};
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_state *lua_state_new(struct lua_module_manager *lua_mod_mgr);
|
||||
void lua_state_free(struct lua_state *state);
|
||||
struct lua_module_manager *lua_state_get_lua_module_manager(struct lua_state *state);
|
||||
int lua_state_copy_ref_value(struct lua_state *to, struct lua_state *from);
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_module_spec
|
||||
{
|
||||
char *spec_file_path; /* 插件需要使用的文件名 */
|
||||
char *spec_load_func_name; /* 加载插件需要调用的函数名称 */
|
||||
char *spec_unload_func_name; /* 卸载插件需要调用的函数名称 */
|
||||
};
|
||||
struct lua_module_spec *lua_module_config_file_load(const char *config_file_name, size_t *spec_num);
|
||||
void lua_module_spec_free(struct lua_module_spec spec[], size_t spec_num);
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* 需要注册至lua中的函数 */
|
||||
typedef int (*lua_cbind_func)(struct lua_state *state);
|
||||
struct lua_bind_func_spec
|
||||
{
|
||||
lua_cbind_func func; /* 注册函数原型 */
|
||||
char *func_name; /* 注册至lua中的函数名称 */
|
||||
char *space_name; /* 注册至lua中的命名空间名称 */
|
||||
};
|
||||
int lua_cbinding_function(struct lua_state *state, struct lua_bind_func_spec bind_function[], size_t bind_func_num);
|
||||
|
||||
enum LUA_DATATYPE
|
||||
{
|
||||
DATATYPE_BEGIN = 0,
|
||||
DATATYPE_NIL, /* nil类型 */
|
||||
DATATYPE_BOOL, /* bool类型 */
|
||||
DATATYPE_INT, /* int类型 */
|
||||
DATATYPE_NUM, /* double类型 */
|
||||
DATATYPE_STRING, /* 字符串类型 */
|
||||
/* 以下类型不能用于全局变量注册 */
|
||||
DATATYPE_BUFF, /* 传递报文payload时使用 */
|
||||
DATATYPE_TABLE, /* table类型 */
|
||||
DATATYPE_POINTER, /* 指针类型 */
|
||||
DATATYPE_CONTEXT, /* context上下文类型 */
|
||||
DATATYPE_LUA_TABLE, /* 此类型用于在lua之间翻译传递数据 */
|
||||
DATATYPE_FUNCTION, /* 函数类型 */
|
||||
DATATYPE_END
|
||||
};
|
||||
|
||||
/* 需要注册至lua状态机中的数据 */
|
||||
struct lua_bind_data_spec
|
||||
{
|
||||
enum LUA_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);
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_context;
|
||||
struct lua_context *lua_context_new(struct lua_state *state);
|
||||
struct lua_context *lua_context_new_with_ref_id(struct lua_state *state, int ref_id);
|
||||
void lua_context_free(struct lua_context *context);
|
||||
void lua_context_push_stack(struct lua_context *context);
|
||||
int lua_context_check_if_context(void *context);
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
struct lua_ctable;
|
||||
struct lua_cdata
|
||||
{
|
||||
enum LUA_DATATYPE type;
|
||||
size_t data_len; /* 只有在类型为buff或function时使用此标识 */
|
||||
union
|
||||
{
|
||||
int bool;
|
||||
int integer;
|
||||
double number;
|
||||
char *string;
|
||||
|
||||
char *buff;
|
||||
int table;
|
||||
void *pointer;
|
||||
struct lua_context *context;
|
||||
void *function;
|
||||
struct lua_ctable *ctable;
|
||||
};
|
||||
};
|
||||
struct lua_cdata *lua_cdata_new(void);
|
||||
void lua_cdata_free(struct lua_cdata *cdata);
|
||||
int lua_cdata_data_set(struct lua_cdata *cdata, enum LUA_DATATYPE type, void *value_p, int value_i);
|
||||
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);
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
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
|
||||
{
|
||||
int lua_load_fn_ref_id;
|
||||
int lua_unload_fn_ref_id;
|
||||
int lua_script_env_ref_id;
|
||||
};
|
||||
int lua_load_script_load_single_specific(struct lua_load_script *load_script, struct lua_state *state, struct lua_module_spec *module_spec);
|
||||
|
||||
struct lua_fn_arg_pair
|
||||
{
|
||||
struct lua_fn_arg_pair *next;
|
||||
struct lua_module_manager *lua_mod_mgr;
|
||||
int lua_fn_ref_id;
|
||||
int lua_arg_ref_id;
|
||||
};
|
||||
|
||||
/*
|
||||
struct lua_mq_dispatch_arg
|
||||
{
|
||||
struct lua_mq_dispatch_arg *next;
|
||||
struct lua_module_manage *module_manage;
|
||||
int topic_id;
|
||||
int lua_mq_dispatch_fn_ref_id;
|
||||
int lua_mq_dispatch_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_mq_msg_free_arg
|
||||
{
|
||||
struct lua_mq_msg_free_arg *next;
|
||||
struct lua_module_manage *module_manage;
|
||||
int topic_id;
|
||||
int lua_mq_msg_free_fn_ref_id;
|
||||
int lua_mq_msg_free_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_mq_on_msg_arg
|
||||
{
|
||||
struct lua_mq_on_msg_arg *next;
|
||||
struct lua_module_manage *module_manage;
|
||||
int topic_id;
|
||||
int lua_mq_on_msg_fn_ref_id;
|
||||
int lua_mq_on_msg_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_on_packet_stage_callback_arg{
|
||||
struct lua_on_packet_stage_callback_arg * next;
|
||||
struct lua_module_manage * module_manage;
|
||||
int lua_on_packet_stage_fn_ref_id;
|
||||
int lua_on_packet_stage_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_on_session_callback_arg
|
||||
{
|
||||
struct lua_on_session_callback_arg * next;
|
||||
struct lua_module_manage * module_manage;
|
||||
int lua_on_session_fn_ref_id;
|
||||
int lua_on_session_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_on_tcp_stream_callback_arg
|
||||
{
|
||||
struct lua_on_tcp_stream_callback_arg * next;
|
||||
struct lua_module_manage * module_manage;
|
||||
int lua_on_tcp_stream_fn_ref_id;
|
||||
int lua_on_tcp_stream_arg_ref_id;
|
||||
};
|
||||
*/
|
||||
|
||||
struct lua_module_manager
|
||||
{
|
||||
struct stellar_module_manager *mod_mgr;
|
||||
|
||||
size_t state_num;
|
||||
struct lua_state **state_array;
|
||||
size_t load_script_num;
|
||||
// struct lua_module_spec *module_spec_array;
|
||||
struct lua_load_script *load_script_array;
|
||||
|
||||
struct lua_fn_arg_pair *mq_dispatch_list;
|
||||
struct lua_fn_arg_pair *mq_msg_free_list;
|
||||
struct lua_fn_arg_pair *mq_on_msg_list;
|
||||
|
||||
struct lua_fn_arg_pair *on_packet_stage_list;
|
||||
struct lua_fn_arg_pair *on_session_tcp_list;
|
||||
struct lua_fn_arg_pair *on_session_udp_list;
|
||||
struct lua_fn_arg_pair *on_session_control_packet_list;
|
||||
struct lua_fn_arg_pair *on_tcp_stream_list;
|
||||
/*
|
||||
struct lua_mq_dispatch_arg *mq_dispatch_list;
|
||||
struct lua_mq_msg_free_arg *mq_msg_free_list;
|
||||
struct lua_mq_on_msg_arg *mq_on_msg_list;
|
||||
|
||||
struct lua_on_packet_stage_callback_arg *on_packet_stage_list;
|
||||
struct lua_on_session_callback_arg *on_session_tcp_list;
|
||||
struct lua_on_session_callback_arg *on_session_udp_list;
|
||||
struct lua_on_session_callback_arg *on_session_control_packet_list;
|
||||
struct lua_on_tcp_stream_callback_arg * on_tcp_stream_list;
|
||||
*/
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,201 +0,0 @@
|
||||
#include "lua_binding_function.h"
|
||||
|
||||
void *lpm_ctx_new_func(struct session *sess, void *plugin_env)
|
||||
{
|
||||
if (!plugin_env)
|
||||
return NULL;
|
||||
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;
|
||||
|
||||
int thread_id = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = (struct lua_state *)plugin_manage->state_array[thread_id];
|
||||
struct lua_context *new_context = lua_context_new(state);
|
||||
|
||||
struct lua_cdata param[3] = {0};
|
||||
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, env->lua_ctx_new_fn_ref_id, param, 3, NULL, 0, NULL, 0))
|
||||
{
|
||||
lua_context_free(new_context);
|
||||
return NULL;
|
||||
}
|
||||
return (void *)new_context;
|
||||
}
|
||||
|
||||
void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env)
|
||||
{
|
||||
if (!plugin_env)
|
||||
return;
|
||||
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;
|
||||
|
||||
int thread_id = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = plugin_manage->state_array[thread_id];
|
||||
|
||||
struct lua_cdata param[3] = {0};
|
||||
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;
|
||||
}
|
||||
|
||||
void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg)
|
||||
{
|
||||
if (!msg_free_arg)
|
||||
return;
|
||||
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 = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = plugin_manage->state_array[thread_id];
|
||||
|
||||
struct lua_cdata param[3] = {0};
|
||||
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;
|
||||
}
|
||||
|
||||
void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env)
|
||||
{
|
||||
if (!plugin_env)
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
int thread_id = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = plugin_manage->state_array[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;
|
||||
/* 这里是不是有更好的办法 */
|
||||
struct lua_context *context = (struct lua_context *)msg;
|
||||
if (context && context->magic_code == context_magic_code)
|
||||
{
|
||||
param[2].type = DATATYPE_CONTEXT;
|
||||
param[2].context = context;
|
||||
}
|
||||
else
|
||||
{
|
||||
param[2].type = DATATYPE_POINTER;
|
||||
param[2].pointer = (void *)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;
|
||||
|
||||
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 = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = plugin_manage->state_array[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;
|
||||
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 = stellar_get_current_thread_id(st);
|
||||
struct lua_state *state = plugin_manage->state_array[thread_id];
|
||||
|
||||
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_array[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;
|
||||
/* 这里是不是有更好的办法 */
|
||||
struct lua_context *context = (struct lua_context *)msg;
|
||||
if (context && context->magic_code == context_magic_code)
|
||||
{
|
||||
param[2].type = DATATYPE_CONTEXT;
|
||||
param[2].context = (struct lua_context *)msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
param[2].type = DATATYPE_POINTER;
|
||||
param[2].pointer = (void *)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;
|
||||
}
|
||||
@@ -1,931 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utlist.h>
|
||||
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
#include "lua_binding_function.h"
|
||||
|
||||
struct lua_bind_function_spec lua_bind_function[] = {
|
||||
{lua_get_worker_thread_num, "get_worker_thread_num", "stellar"},
|
||||
{lua_get_current_thread_id, "get_current_thread_id", "stellar"},
|
||||
{lua_get_stellar_pointer, "get_stellar", "stellar"},
|
||||
|
||||
{lua_session_plugin_regist, "register", "session_plugin"},
|
||||
{lua_packet_plugin_regist, "register", "packet_plugin"},
|
||||
|
||||
{lua_session_get_type, "get_type", "session"},
|
||||
|
||||
{lua_packet_mq_create_topic, "create_topic", "packet_mq"},
|
||||
{lua_packet_mq_get_topic_id, "get_topic_id", "packet_mq"},
|
||||
{lua_packet_mq_update_topic, "update_topic", "packet_mq"},
|
||||
{lua_packet_mq_destory_topic, "destory_topic", "packet_mq"},
|
||||
{lua_packet_mq_subscribe_topic, "subscribe_topic", "packet_mq"},
|
||||
{lua_packet_mq_publish_message, "publish_message", "packet_mq"},
|
||||
|
||||
{lua_session_mq_create_topic, "create_topic", "session_mq"},
|
||||
{lua_session_mq_get_topic_id, "get_topic_id", "session_mq"},
|
||||
{lua_session_mq_update_topic, "update_topic", "session_mq"},
|
||||
{lua_session_mq_destory_topic, "destory_topic", "session_mq"},
|
||||
{lua_session_mq_subscribe_topic, "subscribe_topic", "session_mq"},
|
||||
{lua_session_mq_topic_is_active, "topic_is_active", "session_mq"},
|
||||
{lua_session_mq_publish_message, "publish_message", "session_mq"},
|
||||
{lua_session_mq_ignore_message, "ignore_message", "session_mq"},
|
||||
{lua_session_mq_unignore_message, "unignore_message", "session_mq"},
|
||||
|
||||
{lua_session_get0_current_payload, "get_payload", "session"},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
struct lua_bind_data_spec lua_bind_data[] = {
|
||||
{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},
|
||||
};
|
||||
|
||||
struct lua_state
|
||||
{
|
||||
lua_State *state;
|
||||
};
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* cbinding */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
static int lua_cbinding_single_function(struct lua_state *state, struct lua_bind_function_spec *function_spec)
|
||||
{
|
||||
if (!state || !function_spec || !function_spec->function || !function_spec->func_name)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
if (function_spec->space_name)
|
||||
{
|
||||
lua_getglobal(L, function_spec->space_name);
|
||||
if (lua_type(L, -1) == LUA_TNIL)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, function_spec->space_name);
|
||||
lua_settop(L, 0);
|
||||
lua_getglobal(L, function_spec->space_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_NAMESPACE_TYPE_ERR;
|
||||
}
|
||||
|
||||
lua_getfield(L, -1, function_spec->func_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_FUNCTION_TYPE_ERR;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pushcfunction(L, (lua_CFunction)function_spec->function);
|
||||
lua_setfield(L, -2, function_spec->func_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_getglobal(L, function_spec->func_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_FUNCTION_TYPE_ERR;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushcfunction(L, (lua_CFunction)function_spec->function);
|
||||
lua_setglobal(L, function_spec->func_name);
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec)
|
||||
{
|
||||
if (!state || !data_spec || !data_spec->data_value || !data_spec->data_name)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
if (data_spec->space_name)
|
||||
{
|
||||
lua_getglobal(L, data_spec->space_name);
|
||||
if (lua_gettop(L) == 0 || lua_type(L, -1) == LUA_TNIL)
|
||||
{
|
||||
lua_newtable(L);
|
||||
lua_setglobal(L, data_spec->space_name);
|
||||
lua_settop(L, 0);
|
||||
lua_getglobal(L, data_spec->space_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lua_type(L, -1) != LUA_TTABLE)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_NAMESPACE_TYPE_ERR;
|
||||
}
|
||||
|
||||
lua_getfield(L, -1, data_spec->data_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_DATA_TYPE_ERR;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
switch (data_spec->data_type)
|
||||
{
|
||||
case DATATYPE_BOOL:
|
||||
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
|
||||
lua_pushboolean(L, 1);
|
||||
else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE"))
|
||||
lua_pushboolean(L, 0);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, atoi(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushstring(L, (const char *)data_spec->data_value);
|
||||
break;
|
||||
default:
|
||||
/* 其他类型不支持 */
|
||||
lua_settop(L, 0);
|
||||
return BIND_DATA_TYPE_UNKNOWN;
|
||||
}
|
||||
lua_setfield(L, -2, data_spec->data_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_getglobal(L, data_spec->data_name);
|
||||
if (lua_type(L, -1) != LUA_TNIL)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return BIND_DATA_TYPE_ERR;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
switch (data_spec->data_type)
|
||||
{
|
||||
case DATATYPE_BOOL:
|
||||
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
|
||||
lua_pushboolean(L, 1);
|
||||
else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE"))
|
||||
lua_pushboolean(L, 0);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, atoi(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushstring(L, (const char *)data_spec->data_value);
|
||||
break;
|
||||
default:
|
||||
/* 其他类型不支持 */
|
||||
lua_settop(L, 0);
|
||||
return BIND_DATA_TYPE_UNKNOWN;
|
||||
}
|
||||
lua_setglobal(L, data_spec->data_name);
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num)
|
||||
{
|
||||
int failed_count = 0;
|
||||
for (unsigned index = 0; index < bind_func_num; index++)
|
||||
{
|
||||
if (lua_cbinding_single_function(state, &bind_function[index]))
|
||||
failed_count++;
|
||||
}
|
||||
return failed_count;
|
||||
}
|
||||
|
||||
int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num)
|
||||
{
|
||||
int failed_count = 0;
|
||||
for (unsigned index = 0; index < bind_data_num; index++)
|
||||
{
|
||||
if (lua_cbinding_single_data(state, &bind_data[index]))
|
||||
failed_count++;
|
||||
}
|
||||
return failed_count;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* context */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
const char *context_magic_code = "ctx_code";
|
||||
struct lua_context *lua_context_new(struct lua_state *state)
|
||||
{
|
||||
if (!state)
|
||||
return NULL;
|
||||
lua_State *L = (lua_State *)state;
|
||||
struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context));
|
||||
new_context->magic_code = context_magic_code;
|
||||
new_context->state = state;
|
||||
|
||||
lua_newtable(L);
|
||||
int ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (ref_id == LUA_REFNIL)
|
||||
return NULL;
|
||||
new_context->lua_context_ref_id = ref_id;
|
||||
return new_context;
|
||||
}
|
||||
|
||||
void lua_context_free(struct lua_context *context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
luaL_unref((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
|
||||
free(context);
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_context_push_stack(struct lua_context *context)
|
||||
{
|
||||
if (!context)
|
||||
return;
|
||||
if (context->lua_context_ref_id)
|
||||
lua_rawgeti((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* trans data between lua table and C */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
static int lua_function_writer(lua_State *state, const void *p, size_t sz, void *ud)
|
||||
{
|
||||
/* TODO: 这个函数在lua中会被大量调用, 频繁的realloc可能会导致内存碎片化, 后续调整一下内存分配机制 */
|
||||
struct lua_cdata *data = (struct lua_cdata *)ud;
|
||||
data->type = DATATYPE_FUNCTION;
|
||||
if (!data->function)
|
||||
data->function = (void *)calloc(1, sizeof(sz));
|
||||
else
|
||||
data->function = (void *)realloc(data->function, (data->data_len + sz));
|
||||
memcpy((data->function + data->data_len), p, sz);
|
||||
data->data_len += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *lua_function_reader(lua_State *state, void *ud, size_t *sz)
|
||||
{
|
||||
struct lua_cdata *data = (struct lua_cdata *)ud;
|
||||
*sz = data->data_len;
|
||||
return (const char *)data->function;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
struct lua_cdata *lua_cdata_new(void)
|
||||
{
|
||||
struct lua_cdata *new_data = (struct lua_cdata *)calloc(1, sizeof(struct lua_cdata));
|
||||
memset(new_data, 0, sizeof(struct lua_cdata));
|
||||
return new_data;
|
||||
}
|
||||
|
||||
static void lua_cdata_inner_data_free(struct lua_cdata *cdata)
|
||||
{
|
||||
if (!cdata)
|
||||
return;
|
||||
cdata->type = 0;
|
||||
cdata->data_len = 0;
|
||||
switch (cdata->type)
|
||||
{
|
||||
case DATATYPE_STRING:
|
||||
free(cdata->string);
|
||||
break;
|
||||
case DATATYPE_LUA_TABLE:
|
||||
lua_ctable_free(cdata->ctable);
|
||||
break;
|
||||
case DATATYPE_FUNCTION:
|
||||
free(cdata->function);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void lua_cdata_free(struct lua_cdata *cdata)
|
||||
{
|
||||
lua_cdata_inner_data_free(cdata);
|
||||
if (cdata)
|
||||
free(cdata);
|
||||
return;
|
||||
}
|
||||
|
||||
int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata)
|
||||
{
|
||||
if (!state || !cdata)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
switch (cdata->type)
|
||||
{
|
||||
case DATATYPE_NIL:
|
||||
lua_pushnil(L);
|
||||
break;
|
||||
case DATATYPE_BOOL:
|
||||
lua_pushboolean(L, cdata->bool);
|
||||
break;
|
||||
case DATATYPE_INT:
|
||||
lua_pushinteger(L, cdata->integer);
|
||||
break;
|
||||
case DATATYPE_NUM:
|
||||
lua_pushnumber(L, cdata->number);
|
||||
break;
|
||||
case DATATYPE_STRING:
|
||||
lua_pushstring(L, cdata->string);
|
||||
break;
|
||||
case DATATYPE_TABLE:
|
||||
if (cdata->table)
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, cdata->table);
|
||||
break;
|
||||
case DATATYPE_LUA_TABLE:
|
||||
lua_ctable_push_stack(state, cdata->ctable);
|
||||
break;
|
||||
case DATATYPE_POINTER:
|
||||
lua_pushlightuserdata(L, (void *)cdata->pointer);
|
||||
break;
|
||||
case DATATYPE_CONTEXT:
|
||||
lua_context_push_stack(cdata->context);
|
||||
break;
|
||||
case DATATYPE_FUNCTION:
|
||||
lua_load(L, lua_function_reader, (void *)cdata, NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
return DATA_TYPE_UNKNOWN;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata)
|
||||
{
|
||||
if (!state || !cdata)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
lua_cdata_inner_data_free(cdata);
|
||||
switch (lua_type(L, -1))
|
||||
{
|
||||
case LUA_TNIL:
|
||||
cdata->type = DATATYPE_NIL;
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
cdata->type = DATATYPE_BOOL;
|
||||
cdata->bool = lua_toboolean(L, -1);
|
||||
break;
|
||||
case LUA_TLIGHTUSERDATA:
|
||||
cdata->type = DATATYPE_POINTER;
|
||||
cdata->pointer = (void *)lua_topointer(L, -1);
|
||||
break;
|
||||
case LUA_TNUMBER:
|
||||
cdata->type = DATATYPE_NUM;
|
||||
cdata->number = lua_tonumber(L, -1);
|
||||
int try_int = (int)cdata->number;
|
||||
if ((double)try_int == cdata->number)
|
||||
{
|
||||
cdata->type = DATATYPE_INT;
|
||||
cdata->integer = lua_tointeger(L, -1);
|
||||
}
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
cdata->type = DATATYPE_STRING;
|
||||
cdata->string = (char *)strdup(lua_tostring(L, -1));
|
||||
break;
|
||||
case LUA_TTABLE:
|
||||
cdata->type = DATATYPE_LUA_TABLE;
|
||||
cdata->ctable = lua_ctable_new();
|
||||
lua_ctable_pop_stack(state, cdata->ctable);
|
||||
break;
|
||||
case LUA_TFUNCTION:
|
||||
cdata->type = DATATYPE_FUNCTION;
|
||||
lua_dump(L, lua_function_writer, cdata, 0);
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
cdata->type = DATATYPE_POINTER;
|
||||
cdata->pointer = (void *)lua_topointer(L, -1);
|
||||
break;
|
||||
default:
|
||||
return DATA_TYPE_UNKNOWN;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
struct lua_ctable *lua_ctable_new(void)
|
||||
{
|
||||
struct lua_ctable *new_table = (struct lua_ctable *)calloc(1, sizeof(struct lua_ctable));
|
||||
memset(new_table, 0, sizeof(struct lua_ctable));
|
||||
return new_table;
|
||||
}
|
||||
|
||||
void lua_ctable_free(struct lua_ctable *ctable)
|
||||
{
|
||||
if (!ctable)
|
||||
return;
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
lua_cdata_free(ctable->array_data[array_index]);
|
||||
}
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
lua_cnode_free(ctable->node_data[node_index]);
|
||||
}
|
||||
if (ctable->array_data)
|
||||
free(ctable->array_data);
|
||||
if (ctable->node_data)
|
||||
free(ctable->node_data);
|
||||
free(ctable);
|
||||
return;
|
||||
}
|
||||
|
||||
int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable)
|
||||
{
|
||||
if (!state || !ctable)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
lua_newtable(L);
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
lua_pushinteger(L, (array_index + 1));
|
||||
lua_cdata_push_stack(state, ctable->array_data[array_index]);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
if (ctable->node_data[node_index]->node_string_key)
|
||||
lua_pushstring(L, ctable->node_data[node_index]->node_string_key);
|
||||
else
|
||||
lua_pushinteger(L, ctable->node_data[node_index]->node_integer_key);
|
||||
lua_cdata_push_stack(state, ctable->node_data[node_index]->node_data);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable)
|
||||
{
|
||||
if (!state || !ctable)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
/* 获取table长度 */
|
||||
ctable->array_size = (size_t)lua_rawlen(L, -1);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2))
|
||||
{
|
||||
ctable->node_size++;
|
||||
if (lua_type(L, -2) == LUA_TNUMBER)
|
||||
{
|
||||
int numkey = lua_tointeger(L, -2);
|
||||
if (numkey > 0 && numkey <= (int)ctable->array_size)
|
||||
ctable->node_size--;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
ctable->array_data = (struct lua_cdata **)calloc(ctable->array_size, sizeof(struct lua_cdata *));
|
||||
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
|
||||
{
|
||||
ctable->array_data[array_index] = lua_cdata_new();
|
||||
}
|
||||
ctable->node_data = (struct lua_cnode **)calloc(ctable->node_size, sizeof(struct lua_cnode *));
|
||||
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
|
||||
{
|
||||
ctable->node_data[node_index] = lua_cnode_new();
|
||||
}
|
||||
|
||||
/* 依次获取数据 */
|
||||
int key_index = 0;
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2))
|
||||
{
|
||||
if (lua_type(L, -2) == LUA_TNUMBER)
|
||||
{
|
||||
int numkey = lua_tointeger(L, -2);
|
||||
if (numkey > 0 && numkey <= (int)ctable->array_size)
|
||||
lua_cdata_pop_stack(state, ctable->array_data[numkey - 1]);
|
||||
else
|
||||
{
|
||||
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
|
||||
ctable->node_data[key_index]->node_integer_key = lua_tointeger(L, -1);
|
||||
++key_index;
|
||||
}
|
||||
}
|
||||
else if (lua_type(L, -2) == LUA_TSTRING)
|
||||
{
|
||||
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
|
||||
ctable->node_data[key_index]->node_string_key = strdup((char *)lua_tostring(L, -1));
|
||||
++key_index;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
struct lua_cnode *lua_cnode_new(void)
|
||||
{
|
||||
struct lua_cnode *new_node = (struct lua_cnode *)calloc(1, sizeof(struct lua_cnode));
|
||||
memset(new_node, 0, sizeof(struct lua_cnode));
|
||||
new_node->node_data = lua_cdata_new();
|
||||
return new_node;
|
||||
}
|
||||
|
||||
void lua_cnode_free(struct lua_cnode *cnode)
|
||||
{
|
||||
if (cnode->node_string_key)
|
||||
free(cnode->node_string_key);
|
||||
if (cnode->node_data)
|
||||
lua_cdata_free(cnode->node_data);
|
||||
free(cnode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* execute one chunk */
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
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)
|
||||
{
|
||||
if (!state || fn_ref_id <= 0 || (param_num && !param) || (r_num && !returnvalue))
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, fn_ref_id);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION)
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return CHUNK_TYPE_NOT_FUNCTION;
|
||||
}
|
||||
|
||||
int pushret = 0;
|
||||
for (unsigned param_index = 0; param_index < param_num; ++param_index)
|
||||
{
|
||||
if ((pushret = lua_cdata_push_stack(state, ¶m[param_index])))
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return pushret;
|
||||
}
|
||||
}
|
||||
|
||||
if (lua_pcall(L, param_num, LUA_MULTRET, 0))
|
||||
{
|
||||
if (errlog)
|
||||
snprintf(errlog, (err_len - 1), "run script[%d] err %s\n", fn_ref_id, lua_tostring(L, -1));
|
||||
lua_settop(L, 0);
|
||||
return CHUNK_RUN_CODE_FAIL;
|
||||
}
|
||||
|
||||
if (r_num > 0)
|
||||
{
|
||||
int count = lua_gettop(L);
|
||||
/* 如果接收返回值数量不够, 只保留前r_num个返回值 */
|
||||
if (count > (int)r_num)
|
||||
{
|
||||
lua_pop(L, (count - (int)r_num));
|
||||
count = (int)r_num;
|
||||
}
|
||||
int pop_ret = 0;
|
||||
for (int i = (count - 1); i >= 0; --i)
|
||||
{
|
||||
if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i]))))
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
return pop_ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lua_settop(L, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* TODO: 这个hash函数是不是合适 */
|
||||
int calc_on_message_func_hash_key(int topic_id, int plugin_id)
|
||||
{
|
||||
return (((uint32_t)plugin_id << 3) + (uint32_t)topic_id) % HASH_MAX_NUM;
|
||||
}
|
||||
|
||||
struct lua_on_message_fn *hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id)
|
||||
{
|
||||
int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id);
|
||||
struct lua_on_message_fn *insert_positon = &msg_fn_hashlist[hash_key];
|
||||
while ((insert_positon->hash_on_use - HASH_MAX_NUM) > 0)
|
||||
{
|
||||
if (insert_positon->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1))
|
||||
insert_positon = &msg_fn_hashlist[0];
|
||||
else
|
||||
insert_positon++;
|
||||
/* 没有空位置了 */
|
||||
if (insert_positon->hash_on_use % HASH_MAX_NUM == hash_key)
|
||||
return NULL;
|
||||
}
|
||||
insert_positon->hash_on_use += (HASH_MAX_NUM + 1);
|
||||
insert_positon->topic_id = topic_id;
|
||||
insert_positon->plugin_id = plugin_id;
|
||||
return insert_positon;
|
||||
}
|
||||
|
||||
struct lua_on_message_fn *hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id)
|
||||
{
|
||||
int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id);
|
||||
struct lua_on_message_fn *find_position = &msg_fn_hashlist[hash_key];
|
||||
if ((find_position->hash_on_use - HASH_MAX_NUM) < 0)
|
||||
return NULL;
|
||||
while (find_position)
|
||||
{
|
||||
if (find_position->topic_id == topic_id && find_position->plugin_id == plugin_id)
|
||||
{
|
||||
return find_position;
|
||||
}
|
||||
if (find_position->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1))
|
||||
find_position = &msg_fn_hashlist[0];
|
||||
else
|
||||
find_position++;
|
||||
if ((find_position->hash_on_use % HASH_MAX_NUM == hash_key) || (find_position->hash_on_use - HASH_MAX_NUM) < 0)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define LUA_GLOBAL_VALUE_REF_ID (LUA_RIDX_LAST + 2)
|
||||
|
||||
static inline struct lua_state *thread_state_init(int thread_id, struct stellar *st, struct lua_plugin_manage *plugin_manage)
|
||||
{
|
||||
lua_State *new_L = luaL_newstate();
|
||||
luaL_openlibs(new_L);
|
||||
|
||||
lua_newtable(new_L);
|
||||
lua_pushinteger(new_L, thread_id);
|
||||
lua_setfield(new_L, -2, LUA_GLOBAL_THREAD_ID_KEY);
|
||||
lua_pushlightuserdata(new_L, st);
|
||||
lua_setfield(new_L, -2, LUA_GLOBAL_STELLAR_POINTER);
|
||||
lua_pushlightuserdata(new_L, plugin_manage);
|
||||
lua_setfield(new_L, -2, LUA_GLOBAL_PLUGIN_MANGE_POINTER);
|
||||
int global_ref_id = luaL_ref(new_L, LUA_REGISTRYINDEX);
|
||||
printf("set global ref id is %d\n", global_ref_id);
|
||||
lua_settop(new_L, 0);
|
||||
|
||||
struct lua_state *new_state = (struct lua_state *)new_L;
|
||||
lua_cbinding_function(new_state, lua_bind_function, (sizeof(lua_bind_function) / sizeof(struct lua_bind_function_spec)));
|
||||
lua_cbinding_data(new_state, lua_bind_data, (sizeof(lua_bind_data) / sizeof(struct lua_bind_data_spec)));
|
||||
return new_state;
|
||||
}
|
||||
|
||||
/*
|
||||
int lua_state_get_thread_id(struct lua_state * state)
|
||||
{
|
||||
lua_State * L = (lua_State *)state;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
|
||||
int thread_id = -1;
|
||||
if ( lua_getfield(L, -1, LUA_GLOBAL_THREAD_ID_KEY) == LUA_TNUMBER )
|
||||
thread_id = lua_tointeger(L, -1);
|
||||
lua_pop(L, 2);
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
struct stellar * lua_state_get_stellar(struct lua_state * state)
|
||||
{
|
||||
lua_State * L = (lua_State *)state;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
|
||||
struct stellar * st = NULL;
|
||||
if ( lua_getfield(L, -1, LUA_GLOBAL_STELLAR_POINTER) == LUA_TLIGHTUSERDATA )
|
||||
st = (struct stellar *)lua_topointer(L, -1);
|
||||
lua_pop(L, 2);
|
||||
return st;
|
||||
}
|
||||
*/
|
||||
|
||||
struct lua_plugin_manage *lua_state_get_plugin_manage(struct lua_state *state)
|
||||
{
|
||||
lua_State *L = (lua_State *)state;
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
|
||||
struct lua_plugin_manage *plugin_manage = NULL;
|
||||
if (lua_getfield(L, -1, LUA_GLOBAL_PLUGIN_MANGE_POINTER) == LUA_TLIGHTUSERDATA)
|
||||
plugin_manage = (struct lua_plugin_manage *)lua_topointer(L, -1);
|
||||
lua_pop(L, 2);
|
||||
return plugin_manage;
|
||||
}
|
||||
|
||||
static int lua_state_load_one_specific(
|
||||
struct lua_state *state,
|
||||
struct lua_config_spec *spec,
|
||||
struct lua_load_script *script,
|
||||
struct stellar *st,
|
||||
char *errlog,
|
||||
size_t errlog_len)
|
||||
{
|
||||
if (!state || !spec || !script)
|
||||
return PARAM_ERR;
|
||||
lua_State *L = (lua_State *)state;
|
||||
if (access(spec->spec_file_path, F_OK) || luaL_loadfile(L, spec->spec_file_path))
|
||||
return STATE_LOAD_FILE_ERR;
|
||||
if (lua_pcall(L, 0, 0, 0))
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "load spec[%s] fail err is %s\n", spec->spec_file_path, lua_tostring(L, -1));
|
||||
lua_settop(L, 0);
|
||||
return STATE_LOAD_FILE_ERR;
|
||||
}
|
||||
|
||||
/* 创建on_load函数及on_unload函数的引用 */
|
||||
lua_getglobal(L, spec->spec_load_func_name);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_load_func_name);
|
||||
return STATE_REF_TYPE_ERR;
|
||||
}
|
||||
script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (script->lua_load_fn_ref_id <= 0)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_load_func_name, script->lua_load_fn_ref_id);
|
||||
return STATE_CREATE_REF_FAIL;
|
||||
}
|
||||
lua_getglobal(L, spec->spec_unload_func_name);
|
||||
if (lua_type(L, -1) != LUA_TFUNCTION)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_unload_func_name);
|
||||
return STATE_REF_TYPE_ERR;
|
||||
}
|
||||
script->lua_unload_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (script->lua_unload_fn_ref_id <= 0)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_unload_func_name, script->lua_unload_fn_ref_id);
|
||||
return STATE_CREATE_REF_FAIL;
|
||||
}
|
||||
|
||||
/* 创建依赖于该script的script_env, 并调用on_load函数 */
|
||||
lua_newtable(L);
|
||||
script->lua_script_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
if (script->lua_script_env_ref_id <= 0)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s] create script env failed, ref is %d\n", spec->spec_file_path, script->lua_script_env_ref_id);
|
||||
return STATE_CREATE_REF_FAIL;
|
||||
}
|
||||
|
||||
struct lua_cdata param[2];
|
||||
param[0].type = DATATYPE_POINTER;
|
||||
param[0].pointer = (void *)st;
|
||||
param[1].type = DATATYPE_TABLE;
|
||||
param[1].table = script->lua_script_env_ref_id;
|
||||
char exec_err[1024] = {0};
|
||||
int exec_ret = lua_chunk_execute(state, script->lua_load_fn_ref_id, param, 2, NULL, 0, exec_err, sizeof(exec_err));
|
||||
if (exec_ret)
|
||||
{
|
||||
snprintf(errlog, (errlog_len - 1), "spec[%s]%s call fail, err num %d, err %s\n", spec->spec_file_path, spec->spec_load_func_name, exec_ret, exec_err);
|
||||
return STATE_CALL_LOAD_FAILED;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
};
|
||||
|
||||
// static UT_icd lua_session_plugin_icd = {sizeof(struct lua_session_plugin_env), NULL, NULL, NULL};
|
||||
// static UT_icd lua_packet_plugin_icd = {sizeof(struct lua_packet_plugin_env), NULL, NULL, NULL};
|
||||
// static UT_icd lua_message_free_icd = {sizeof(struct lua_message_free_arg), NULL, NULL, NULL};
|
||||
|
||||
struct lua_plugin_manage *lua_plugin_manage_init(
|
||||
struct stellar *st,
|
||||
struct lua_config_spec specific[],
|
||||
size_t specific_num)
|
||||
{
|
||||
if (!st)
|
||||
return NULL;
|
||||
char errlog[1024] = {0};
|
||||
|
||||
struct lua_plugin_manage *new_plugin_manage = (struct lua_plugin_manage *)calloc(1, sizeof(struct lua_plugin_manage));
|
||||
memset(new_plugin_manage, 0, sizeof(struct lua_plugin_manage));
|
||||
|
||||
new_plugin_manage->st = st;
|
||||
|
||||
int thread_count = stellar_get_worker_thread_num(st);
|
||||
if (thread_count <= 0)
|
||||
return new_plugin_manage;
|
||||
new_plugin_manage->state_num = thread_count;
|
||||
new_plugin_manage->state_array = (struct lua_state **)calloc(thread_count, sizeof(struct lua_state *));
|
||||
memset(new_plugin_manage->state_array, 0, thread_count * sizeof(struct lua_state *));
|
||||
for (int thread_index = 0; thread_index < thread_count; thread_index++)
|
||||
{
|
||||
new_plugin_manage->state_array[thread_index] = thread_state_init(thread_index, st, new_plugin_manage);
|
||||
}
|
||||
|
||||
for (unsigned on_message_index = 0; on_message_index < HASH_MAX_NUM; on_message_index++)
|
||||
{
|
||||
new_plugin_manage->on_session_message_hashlist[on_message_index].hash_on_use = on_message_index;
|
||||
new_plugin_manage->on_packet_message_hashlist[on_message_index].hash_on_use = on_message_index;
|
||||
}
|
||||
|
||||
if (specific_num == 0)
|
||||
return new_plugin_manage;
|
||||
new_plugin_manage->load_script_array = (struct lua_load_script *)calloc(specific_num, sizeof(struct lua_load_script));
|
||||
new_plugin_manage->load_script_num = specific_num;
|
||||
for (unsigned spec_index = 0; spec_index < specific_num; spec_index++)
|
||||
{
|
||||
if (lua_state_load_one_specific(new_plugin_manage->state_array[0],
|
||||
&specific[spec_index],
|
||||
&new_plugin_manage->load_script_array[spec_index],
|
||||
st,
|
||||
errlog,
|
||||
sizeof(errlog)))
|
||||
{
|
||||
printf("%s\n", errlog);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
lua_newtable((lua_State *)new_plugin_manage->state_array[0]);
|
||||
int lua_ref_max_id = luaL_ref((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX);
|
||||
struct lua_cdata *trans_data = lua_cdata_new();
|
||||
for (int ref_index = (LUA_GLOBAL_VALUE_REF_ID + 1); ref_index < lua_ref_max_id; ref_index++)
|
||||
{
|
||||
lua_settop((lua_State *)new_plugin_manage->state_array[0], 0);
|
||||
lua_rawgeti((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, ref_index);
|
||||
lua_cdata_pop_stack(new_plugin_manage->state_array[0], trans_data);
|
||||
for (int thread_index = 1; thread_index < thread_count; thread_index++)
|
||||
{
|
||||
lua_cdata_push_stack(new_plugin_manage->state_array[thread_index], trans_data);
|
||||
int ref_id = luaL_ref((lua_State *)new_plugin_manage->state_array[thread_index], LUA_REGISTRYINDEX);
|
||||
printf("ref to new thread, ref id is %d, %d\n", ref_index, ref_id);
|
||||
}
|
||||
lua_cdata_inner_data_free(trans_data);
|
||||
}
|
||||
luaL_unref((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, lua_ref_max_id);
|
||||
|
||||
return new_plugin_manage;
|
||||
|
||||
err:
|
||||
lua_plugin_manage_exit(new_plugin_manage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr)
|
||||
{
|
||||
if (!lua_plug_mgr)
|
||||
return;
|
||||
|
||||
for (unsigned script_index = 0; script_index < lua_plug_mgr->load_script_num; script_index++)
|
||||
{
|
||||
struct lua_cdata param;
|
||||
param.type = DATATYPE_TABLE;
|
||||
param.table = lua_plug_mgr->load_script_array[script_index].lua_script_env_ref_id;
|
||||
lua_chunk_execute(lua_plug_mgr->state_array[0], lua_plug_mgr->load_script_array[script_index].lua_unload_fn_ref_id, ¶m, 1, NULL, 0, NULL, 0);
|
||||
}
|
||||
free(lua_plug_mgr->load_script_array);
|
||||
|
||||
for (unsigned state_index = 0; state_index < lua_plug_mgr->state_num; ++state_index)
|
||||
{
|
||||
lua_close((lua_State *)lua_plug_mgr->state_array[state_index]);
|
||||
}
|
||||
free(lua_plug_mgr->state_array);
|
||||
|
||||
struct lua_session_plugin_env *session_env = lua_plug_mgr->session_plugin_env_list;
|
||||
while (session_env)
|
||||
{
|
||||
struct lua_session_plugin_env *next = session_env->next;
|
||||
free(session_env);
|
||||
session_env = next;
|
||||
}
|
||||
|
||||
struct lua_packet_plugin_env *packet_env = lua_plug_mgr->packet_plugin_env_list;
|
||||
while (packet_env)
|
||||
{
|
||||
struct lua_packet_plugin_env *next = packet_env->next;
|
||||
free(packet_env);
|
||||
packet_env = next;
|
||||
}
|
||||
|
||||
struct lua_message_free_arg *message_free_arg = lua_plug_mgr->message_free_arg_list;
|
||||
while (message_free_arg)
|
||||
{
|
||||
struct lua_message_free_arg *next = message_free_arg->next;
|
||||
free(message_free_arg);
|
||||
message_free_arg = next;
|
||||
}
|
||||
|
||||
free(lua_plug_mgr);
|
||||
return;
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
#ifndef LUA_PLUGIN_MANAGE_INTERNAL_H
|
||||
#define LUA_PLUGIN_MANAGE_INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "lua_plugin_manage.h"
|
||||
|
||||
struct lua_state;
|
||||
|
||||
enum LUA_PLUGIN_MANGE_ERR_NUM
|
||||
{
|
||||
/* 状态机相关的错误码 */
|
||||
STATE_LOAD_FILE_ERR = -400, /* 状态机加载lua文件时出错, 可能原因是文件不存在或文件无法加载 */
|
||||
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, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */
|
||||
/* lua与C之间数据转换或操作错误码 */
|
||||
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, /* 绑定或删除函数过程中数据类型错误 */
|
||||
BIND_DATA_TYPE_ERR, /* 绑定或删除全局变量过程中数据类型错误 */
|
||||
BIND_DATA_TYPE_UNKNOWN, /* struct lua_binding_data格式中数据类型无法识别, 或在该功能中操作了不支持的数据类型 */
|
||||
/* 通用返回值 */
|
||||
PARAM_ERR = -1, /* 传入参数错误, 可能是指针为空或类型不符合 */
|
||||
SUCCESS = 0, /* 运行成功 */
|
||||
};
|
||||
|
||||
/* ***** ***** ***** ***** ***** ***** */
|
||||
/* 需要注册至lua中的函数 */
|
||||
typedef int (*lua_cbind_func)(struct lua_state *state);
|
||||
struct lua_bind_function_spec
|
||||
{
|
||||
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);
|
||||
|
||||
extern const char *context_magic_code;
|
||||
struct lua_context
|
||||
{
|
||||
const char *magic_code;
|
||||
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);
|
||||
|
||||
enum DATATYPE
|
||||
{
|
||||
DATATYPE_BEGIN = 0,
|
||||
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_bind_data_spec
|
||||
{
|
||||
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);
|
||||
|
||||
struct lua_cdata;
|
||||
struct lua_cnode;
|
||||
struct lua_ctable;
|
||||
|
||||
struct lua_cdata
|
||||
{
|
||||
enum DATATYPE type;
|
||||
size_t data_len; /* 只有在类型为function时使用此标识 */
|
||||
union
|
||||
{
|
||||
int bool;
|
||||
int integer;
|
||||
double number;
|
||||
char *string;
|
||||
|
||||
int table;
|
||||
void *pointer;
|
||||
struct lua_context *context;
|
||||
void *function;
|
||||
struct lua_ctable *ctable;
|
||||
};
|
||||
};
|
||||
|
||||
struct lua_cnode
|
||||
{
|
||||
char *node_string_key;
|
||||
int node_integer_key;
|
||||
struct lua_cdata *node_data;
|
||||
};
|
||||
|
||||
struct lua_ctable
|
||||
{
|
||||
size_t array_size;
|
||||
size_t node_size;
|
||||
struct lua_cdata **array_data;
|
||||
struct lua_cnode **node_data;
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
int lua_msg_free_fn_ref_id;
|
||||
int lua_msg_free_arg_ref_id;
|
||||
};
|
||||
|
||||
struct lua_on_message_fn
|
||||
{
|
||||
int hash_on_use;
|
||||
int topic_id;
|
||||
int plugin_id;
|
||||
int lua_on_msg_fn_ref_id;
|
||||
};
|
||||
|
||||
#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_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"
|
||||
|
||||
// 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);
|
||||
|
||||
struct lua_plugin_manage
|
||||
{
|
||||
struct stellar *st;
|
||||
|
||||
size_t state_num;
|
||||
size_t load_script_num;
|
||||
struct lua_state **state_array;
|
||||
struct lua_load_script *load_script_array;
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user