12 Commits

Author SHA1 Message Date
niubinghui
b9b511575f 【修改】调整部分结构之间依赖关系,重新梳理接口 2024-10-16 15:16:09 +08:00
niubinghui
9c39d69b21 【修改】删除就版本中部分失效文件 2024-10-15 19:15:38 +08:00
niubinghui
7c8146f00f 【修改】重新组织部分数据结构,所有逻辑均改为面向数据结构的编程思路 2024-10-15 19:15:05 +08:00
niubinghui
be165549d1 【新增】完成新接口代码修改,通过编译未测试 2024-10-14 19:04:56 +08:00
niubinghui
965403fbad 【修改】更新依赖的stellar头文件 2024-10-14 19:04:00 +08:00
niubinghui
024db869aa 【修改】
修改一处可能出现段错误的情况
2024-10-09 12:04:45 +08:00
niubinghui
ad865134dc 【新增】
修改部分测试代码
2024-10-08 15:13:06 +08:00
niubinghui
6417137294 【修改】
1. 新增获取session current payload接口;
2. 修改一处变量名称;
2024-10-08 15:12:23 +08:00
niubinghui
f32a799e7d 【修改】修改名称 2024-09-06 18:59:12 +08:00
niubinghui
1d9e187624 【修改】基础功能验证 2024-09-06 18:57:29 +08:00
niubinghui
425cd807d3 【修改】BugFix:基础功能验证过程中发现的一些bug 2024-09-06 18:55:31 +08:00
niubinghui
f8dcaabfbd 【修改】重新梳理数据结构并重构部分逻辑 2024-09-06 16:29:07 +08:00
58 changed files with 3140 additions and 4563 deletions

View File

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

View File

@@ -1,10 +0,0 @@
# config.toml
[[plugin]]
path = "example_plugin-1.lua"
init = "plugin_load"
exit = "plugin_unload"
[[plugin]]
path = "example_plugin-2.lua"
init = "plugin_load"
exit = "plugin_unload"

View File

@@ -0,0 +1,31 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#define MESSAGE_MAGIC 0x12345678
#define MAX_APP_ID_NUM 8
#define APP_ID_MESSAGE_TOPIC "TOPIC_APP_ID"
enum APP_IDENTIFY_ORIGIN
{
ORIGIN_PROTO_IDENTIFY=0,
ORIGIN_APP_SKETCH_USER_DEFINE,
ORIGIN_PROTO_ENGINE,
ORIGIN_APP_SKETCH_BUILT_IN,
ORIGIN_PROTO_DECODED,
ORIGIN_EXCEED_PACKET_LIMIT,
ORIGIN_TUNNEL,
ORIGIN_MAX
};
struct app_id_message
{
int magic;
enum APP_IDENTIFY_ORIGIN origin;
uint32_t app_id_num;
int32_t app_id[MAX_APP_ID_NUM];
uint32_t surrogate_id[MAX_APP_ID_NUM];
uint32_t packet_sequence[MAX_APP_ID_NUM];
};

View File

@@ -0,0 +1,31 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
typedef void exdata_free(int idx, void *ex_ptr, void *arg);
struct exdata_schema;
struct exdata_schema *exdata_schema_new();
void exdata_schema_free(struct exdata_schema *schemas);
int exdata_schema_new_index(struct exdata_schema *schema, const char *name, exdata_free *free_func,void *free_arg);
int exdata_schema_get_idx_by_name(struct exdata_schema *schema, const char *name);
struct exdata_runtime;
struct exdata_runtime *exdata_runtime_new(struct exdata_schema *schemas);
void exdata_runtime_free(struct exdata_runtime *rt);
void exdata_runtime_reset(struct exdata_runtime *rt);//call free_func, and set ex_ptr to NULL
int exdata_set(struct exdata_runtime *rt, int idx, void *ex_ptr);
void *exdata_get(struct exdata_runtime *rt, int idx);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,113 @@
#pragma once
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define HTTP_TOPIC "HTTP_MESSAGE"
struct http_message;
enum http_message_type
{
HTTP_TRANSACTION_START,
HTTP_MESSAGE_REQ_LINE,
HTTP_MESSAGE_REQ_HEADER,
HTTP_MESSAGE_REQ_HEADER_END, // todo, delete END, push all fileds at once
HTTP_MESSAGE_REQ_BODY_START,
HTTP_MESSAGE_REQ_BODY,
HTTP_MESSAGE_REQ_BODY_END,
HTTP_MESSAGE_RES_LINE,
HTTP_MESSAGE_RES_HEADER,
HTTP_MESSAGE_RES_HEADER_END, // todo, delete END, push all fileds at once
HTTP_MESSAGE_RES_BODY_START,
HTTP_MESSAGE_RES_BODY,
HTTP_MESSAGE_RES_BODY_END,
HTTP_TRANSACTION_END,
HTTP_MESSAGE_MAX
};
struct http_header_field
{
char *name;
size_t name_len;
char *value;
size_t value_len;
};
struct http_request_line
{
char *method;
size_t method_len;
char *uri;
size_t uri_len;
char *version;
size_t version_len;
int major_version;
int minor_version;
};
struct http_response_line
{
char *version;
size_t version_len;
char *status;
size_t status_len;
int major_version;
int minor_version;
int status_code;
};
enum http_message_type http_message_get_type(const struct http_message *msg);
void http_message_get0_request_line(const struct http_message *msg, struct http_request_line *line);
void http_message_get0_response_line(const struct http_message *msg, struct http_response_line *line);
/*
* Pay attention: key->iov_base is case-insensitive.
*/
void http_message_get0_header(const struct http_message *msg, const char *name, size_t name_len, struct http_header_field *field_result);
/**
* @brief loop reading all headers.
*
* @retval succeed( >= 0) failed(-1)
*/
int http_message_get0_next_header(const struct http_message *msg, struct http_header_field *header);
/**
* @retval succeed( >= 0) failed(-1)
*/
int http_message_reset_header_iter(struct http_message *msg); // to do , obsoleted
void http_message_get0_uncompressed_body(const struct http_message *msg, const char **body, size_t *body_len);
/**
* @brief If the body hasn't been compressed, same as http_message_get0_uncompressed_body().
*
*/
void http_message_get0_decompressed_body(const struct http_message *msg, const char **body, size_t *body_len);
void http_message_get0_raw_url(const struct http_message *msg, const char **url, size_t *url_len);
/*
return value:
0: failed
>1: success, length of decoded_url_buffer, not C string( no EOF with '\0' )
*/
size_t http_url_decode(const char *raw_url, size_t raw_url_len, char *decoded_url_buffer, size_t decoded_url_buffer_len);
/**
* @retval succeed( >= 0) failed(-1)
*/
int http_message_get_transaction_seq(const struct http_message *msg);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,60 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
enum log_level
{
LOG_TRACE,
LOG_DEBUG,
LOG_INFO,
LOG_WARN,
LOG_ERROR,
LOG_FATAL,
};
#define STELLAR_LOG_TRACE(logger, module, format, ...) \
if (log_check_level((logger), LOG_TRACE)) \
{ \
log_print((logger), LOG_TRACE, (module), (format), ##__VA_ARGS__); \
}
#define STELLAR_LOG_DEBUG(logger, module, format, ...) \
if (log_check_level((logger), LOG_DEBUG)) \
{ \
log_print((logger), LOG_DEBUG, (module), (format), ##__VA_ARGS__); \
}
#define STELLAR_LOG_INFO(logger, module, format, ...) \
if (log_check_level((logger), LOG_INFO)) \
{ \
log_print((logger), LOG_INFO, (module), (format), ##__VA_ARGS__); \
}
#define STELLAR_LOG_WARN(logger, module, format, ...) \
if (log_check_level((logger), LOG_WARN)) \
{ \
log_print((logger), LOG_WARN, (module), (format), ##__VA_ARGS__); \
}
#define STELLAR_LOG_ERROR(logger, module, format, ...) \
if (log_check_level((logger), LOG_ERROR)) \
{ \
log_print((logger), LOG_ERROR, (module), (format), ##__VA_ARGS__); \
}
#define STELLAR_LOG_FATAL(logger, module, format, ...) \
if (log_check_level((logger), LOG_FATAL)) \
{ \
log_print((logger), LOG_FATAL, (module), (format), ##__VA_ARGS__); \
}
struct logger;
int log_check_level(struct logger *logger, enum log_level level);
void log_print(struct logger *logger, enum log_level level, const char *module, const char *fmt, ...);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,49 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/mq.h"
#include "stellar/log.h"
#define PACKET_MANAGER_MODULE_NAME "packet_manager_module"
#define SESSION_MANAGER_MODULE_NAME "session_manager_module"
struct stellar_module;
struct stellar_module *stellar_module_new(const char *name, void *ctx);
void stellar_module_free(struct stellar_module *mod);
void * stellar_module_get_ctx(struct stellar_module *mod);
void stellar_module_set_ctx(struct stellar_module *mod, void *ctx);
const char *stellar_module_get_name(struct stellar_module* mod);
void stellar_module_set_name(struct stellar_module* mod, const char *name);
struct stellar_module_manager;
typedef struct stellar_module *module_on_init_func(struct stellar_module_manager *mod_mgr);
typedef void module_on_exit_func(struct stellar_module_manager *mod_mgr, struct stellar_module *mod);
struct stellar_module_manager *stellar_module_manager_new(const char *module_spec_toml_path, int max_thread_num, struct mq_schema *mq_schema, struct logger *logger);
void stellar_module_manager_free(struct stellar_module_manager *mod_mgr);
void stellar_module_manager_register_thread(struct stellar_module_manager* mod_mgr, int thread_id, struct mq_runtime *mq_rt);
// return -1 on error
int stellar_module_manager_get_thread_id(struct stellar_module_manager* mod_mgr);
struct mq_runtime *stellar_module_manager_get_mq_runtime(struct stellar_module_manager *mod_mgr);
struct stellar_module *stellar_module_manager_get_module(struct stellar_module_manager *mod_mgr, const char *module_name);
int stellar_module_manager_get_max_thread_num(struct stellar_module_manager* mod_mgr);
const char *stellar_module_manager_get_toml_path(struct stellar_module_manager *mod_mgr);
struct mq_schema *stellar_module_manager_get_mq_schema(struct stellar_module_manager *mod_mgr);
struct logger *stellar_module_manager_get_logger(struct stellar_module_manager *mod_mgr);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,54 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
struct mq_schema;
struct mq_schema *mq_schema_new();
void mq_schema_free(struct mq_schema *s);
typedef void mq_msg_free_cb_func(void *msg, void *msg_free_arg);
typedef void on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg);
typedef void 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);
//return topic_id
int mq_schema_create_topic(struct mq_schema *s,
const char *topic_name,
on_msg_dispatch_cb_func *on_dispatch_cb,
void *on_dispatch_arg,
mq_msg_free_cb_func *msg_free_cb,
void *msg_free_arg);
int mq_schema_get_topic_id(struct mq_schema *s, const char *topic_name);
int mq_schema_update_topic(struct mq_schema *s,
int topic_id,
on_msg_dispatch_cb_func *on_dispatch_cb,
void *on_dispatch_arg,
mq_msg_free_cb_func *msg_free_cb,
void *msg_free_arg);
int mq_schema_destroy_topic(struct mq_schema *s, int topic_id);
//return 0 if success, otherwise return -1.
int mq_schema_subscribe(struct mq_schema *s, int topic_id, on_msg_cb_func *on_msg_cb, void * on_msg_cb_arg);
struct mq_runtime;
struct mq_runtime *mq_runtime_new(struct mq_schema *s);
void mq_runtime_free(struct mq_runtime *s);
// return 0 if success, otherwise return -1
int mq_runtime_publish_message(struct mq_runtime *rt, int topic_id, void *msg);// append message to pending queue
void mq_runtime_dispatch(struct mq_runtime *rt);// dispatch all message in pending queue, dispatched message will be append to dlq
void mq_runtime_clean(struct mq_runtime *rt); // free all message in dlq and pending queue, during this period, publish will be disabled
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,193 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#define __FAVOR_BSD 1
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <netinet/ip_icmp.h>
#include <linux/if_ether.h>
#include <linux/mpls.h>
struct packet;
/******************************************************************************
* layer
******************************************************************************/
enum layer_proto
{
LAYER_PROTO_NONE = 0,
// L2 -- data link layer
LAYER_PROTO_ETHER = 1,
LAYER_PROTO_PWETH = 2,
LAYER_PROTO_PPP = 3,
LAYER_PROTO_L2TP = 4,
// L2 -- tunnel
LAYER_PROTO_VLAN = 21,
LAYER_PROTO_PPPOE = 22,
LAYER_PROTO_MPLS = 23,
// L3 -- network layer
LAYER_PROTO_IPV4 = 31,
LAYER_PROTO_IPV6 = 32,
LAYER_PROTO_IPAH = 33,
// L3 -- tunnel
LAYER_PROTO_GRE = 41,
// L4 -- transport layer
LAYER_PROTO_UDP = 51,
LAYER_PROTO_TCP = 52,
LAYER_PROTO_ICMP = 53,
LAYER_PROTO_ICMP6 = 54,
// L4 -- tunnel
LAYER_PROTO_VXLAN = 61,
LAYER_PROTO_GTP_U = 62,
LAYER_PROTO_GTP_C = 63,
};
struct layer
{
enum layer_proto proto;
uint16_t hdr_len;
union
{
// all hdr ptr refer to raw packet, read-only
const struct ethhdr *eth;
const struct ip *ip4;
const struct ip6_hdr *ip6;
const struct tcphdr *tcp;
const struct udphdr *udp;
const struct icmphdr *icmp4;
const struct icmp6_hdr *icmp6;
const struct mpls_label *mpls;
const char *raw; // e.g. pppoe, l2tp, gre, gtp, etc.
} hdr;
};
int packet_get_layer_count(const struct packet *pkt);
const struct layer *packet_get_layer_by_idx(const struct packet *pkt, int idx);
// // example: foreach layer in packet (inorder)
// int count = packet_get_layer_count(pkt);
// for (int i = 0; i < count; i++)
// {
// const struct layer *layer = packet_get_layer_by_idx(pkt, i);
// // do something with layer
// }
//
//
// // example: foreach layer in packet (reverse)
// int count = packet_get_layer_count(pkt);
// for (int i = count - 1; i >= 0; i--)
// {
// const struct layer *layer = packet_get_layer_by_idx(pkt, i);
// // do something with layer
// }
/******************************************************************************
* tunnel
******************************************************************************/
enum tunnel_type
{
TUNNEL_IPV4 = 1, // contain layers: IPv4, (next inner layer must be IPv4 / IPv6)
TUNNEL_IPV6 = 2, // contain layers: IPv6, (next inner layer must be IPv4 / IPv6)
TUNNEL_GRE = 3, // contain layers: IPv4 + GRE
// contain layers: IPv6 + GRE
TUNNEL_GTP = 4, // contain layers: IPv4 + UDP + GTP
// contain layers: IPv6 + UDP + GTP
TUNNEL_VXLAN = 5, // contain layers: IPv4 + UDP + VXLAN
// contain layers: IPv6 + UDP + VXLAN
TUNNEL_L2TP = 6, // contain layers: IPv4 + UDP + L2TP
// contain layers: IPv6 + UDP + L2TP
TUNNEL_TEREDO = 7, // contain layers: IPv4 + UDP, (next inner layer must be IPv6)
};
#define MAX_LAYERS_PER_TUNNEL 3
struct tunnel
{
enum tunnel_type type;
int layer_count;
const struct layer *layers[MAX_LAYERS_PER_TUNNEL];
};
int packet_get_tunnel_count(const struct packet *pkt);
// return 0: success 
// return -1: failed
int packet_get_tunnel_by_idx(const struct packet *pkt, int idx, struct tunnel *out);
/******************************************************************************
* build
******************************************************************************/
/*
* tcp_seq: the sequence number of the new TCP packet (in host byte order)
* tcp_ack: the acknowledgment number of the new TCP packet (in host byte order)
* tcp_options_len: the length of the options (must be a multiple of 4)
*/
struct packet *packet_build_tcp(const struct packet *origin_pkt, uint32_t tcp_seq, uint32_t tcp_ack, uint8_t tcp_flags,
const char *tcp_options, uint16_t tcp_options_len,
const char *tcp_payload, uint16_t tcp_payload_len);
struct packet *packet_build_udp(const struct packet *origin_pkt, const char *udp_payload, uint16_t udp_payload_len);
struct packet *packet_build_l3(const struct packet *origin_pkt, uint8_t ip_proto, const char *l3_payload, uint16_t l3_payload_len);
/******************************************************************************
* utils
******************************************************************************/
#define MAX_SIDS 8
struct sids
{
uint16_t sid[MAX_SIDS];
int used;
};
void packet_prepend_sids(struct packet *pkt, const struct sids *sids);
enum packet_direction
{
PACKET_DIRECTION_OUTGOING = 0, // Internal -> External: 0
PACKET_DIRECTION_INCOMING = 1, // External -> Internal: 1
};
enum packet_direction packet_get_direction(const struct packet *pkt);
enum packet_action
{
PACKET_ACTION_FORWARD = 0,
PACKET_ACTION_DROP = 1,
};
void packet_set_action(struct packet *pkt, enum packet_action action);
enum packet_action packet_get_action(const struct packet *pkt);
void packet_set_timeval(struct packet *pkt, const struct timeval *tv);
const struct timeval *packet_get_timeval(const struct packet *pkt);
const char *packet_get_raw_data(const struct packet *pkt);
uint16_t packet_get_raw_len(const struct packet *pkt);
const char *packet_get_payload(const struct packet *pkt);
uint16_t packet_get_payload_len(const struct packet *pkt);
void packet_set_exdata(struct packet *pkt, int idx, void *ex_ptr);
void *packet_get_exdata(struct packet *pkt, int idx);
#ifdef __cplusplus
}
#endif

View File

@@ -1,8 +0,0 @@
#pragma once
#include "stellar.h"
typedef void packet_exdata_free(struct packet *pkt, int idx, void *ex_ptr, void *arg);
int stellar_packet_exdata_new_index(struct stellar *st, const char *name, packet_exdata_free *free_func,void *arg);
int packet_exdata_set(struct packet *pkt, int idx, void *ex_ptr);
void *packet_exdata_get(struct packet *pkt, int idx);

View File

@@ -0,0 +1,37 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/exdata.h"
#include "stellar/packet.h"
enum packet_stage
{
PACKET_STAGE_PREROUTING,
PACKET_STAGE_INPUT,
PACKET_STAGE_FORWARD,
PACKET_STAGE_OUTPUT,
PACKET_STAGE_POSTROUTING,
PACKET_STAGE_MAX,
};
struct packet_manager;
int packet_manager_new_packet_exdata_index(struct packet_manager *pkt_mgr, const char *name, exdata_free *func, void *arg);
typedef void on_packet_stage_callback(enum packet_stage stage, struct packet *pkt, void *args);
int packet_manager_subscribe(struct packet_manager *pkt_mgr, enum packet_stage stage, on_packet_stage_callback *cb, void *args);
// if two modules claim the same packet at the same stage, the second 'claim' fails.
// return 0 on success
// return -1 on failure
typedef void on_packet_claimed_callback(struct packet *pkt, void *args);
int packet_manager_claim_packet(struct packet_manager *pkt_mgr, uint16_t thread_id, struct packet *pkt, on_packet_claimed_callback cb, void *args);
void packet_manager_schedule_packet(struct packet_manager *pkt_mgr, uint16_t thread_id, struct packet *pkt, enum packet_stage stage);
#ifdef __cplusplus
}
#endif

View File

@@ -1,22 +0,0 @@
#pragma once
#include "stellar.h"
//session mq
typedef void packet_msg_free_cb_func(struct packet *pkt, void *msg, void *msg_free_arg);
typedef void on_packet_msg_cb_func(struct packet *pkt, int topic_id, const void *msg, void *plugin_env);
//return topic_id
int stellar_packet_mq_create_topic(struct stellar *st, const char *topic_name, packet_msg_free_cb_func *msg_free_cb, void *msg_free_arg);
int stellar_packet_mq_get_topic_id(struct stellar *st, const char *topic_name);
int stellar_packet_mq_update_topic(struct stellar *st, int topic_id, packet_msg_free_cb_func *msg_free_cb, void *msg_free_arg);
int stellar_packet_mq_destroy_topic(struct stellar *st, int topic_id);
//return 0 if success, otherwise return -1.
int stellar_packet_mq_subscribe(struct stellar *st, int topic_id, on_packet_msg_cb_func *plugin_on_msg_cb, int plugin_id); //packet plugin only
int packet_mq_publish_message(struct packet *pkt, int topic_id, void *msg);

View File

@@ -0,0 +1,21 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/module_manager.h"
struct stellar_polling_manager;
struct stellar_polling_manager *stellar_module_get_polling_manager(struct stellar_module_manager *mod_mgr);
typedef void module_on_polling_func(struct stellar_polling_manager* mod_mgr, void *polling_arg);
//return 0 if success, otherwise return -1.
int stellar_polling_subscribe(struct stellar_polling_manager* mod_mgr, module_on_polling_func on_polling, void *polling_arg);
void stellar_polling_active(struct stellar_polling_manager *mod_mgr);
#ifdef __cplusplus
}
#endif

View File

@@ -1,134 +1,151 @@
#pragma once
#include "stellar.h"
#include <stdint.h>
#include <stddef.h>
enum session_type
#ifdef __cplusplus
extern "C"
{
SESSION_TYPE_TCP,
SESSION_TYPE_UDP,
__SESSION_TYPE_MAX,
};
#endif
#include "stellar/packet.h"
enum session_state
{
SESSION_STATE_INVALID = 0,
SESSION_STATE_OPENING = 1 ,
SESSION_STATE_ACTIVE = 2,
SESSION_STATE_CLOSING = 3,
SESSION_STATE_CONTROL = 6,
__SESSION_STATE_MAX,
SESSION_STATE_INIT = 0,
SESSION_STATE_OPENING = 1,
SESSION_STATE_ACTIVE = 2,
SESSION_STATE_CLOSING = 3,
SESSION_STATE_DISCARD = 4,
SESSION_STATE_CLOSED = 5,
MAX_STATE = 6,
};
enum session_type session_get_type(struct session *sess);
enum session_type
{
SESSION_TYPE_TCP = 0x1,
SESSION_TYPE_UDP = 0x2,
};
enum session_direction
{
SESSION_DIRECTION_INBOUND = 0,
SESSION_DIRECTION_OUTBOUND = 1,
};
enum flow_type
{
FLOW_TYPE_NONE = -1,
FLOW_TYPE_C2S = 0,
FLOW_TYPE_S2C = 1,
MAX_FLOW_TYPE = 2,
};
enum closing_reason
{
CLOSING_BY_TIMEOUT = 0x1,
CLOSING_BY_LRU_EVICTED = 0x2,
CLOSING_BY_PORT_REUSE_EVICTED = 0x3,
CLOSING_BY_CLIENT_FIN = 0x4,
CLOSING_BY_CLIENT_RST = 0x5,
CLOSING_BY_SERVER_FIN = 0x6,
CLOSING_BY_SERVER_RST = 0x7,
};
enum session_stat
{
// raw packet
STAT_RAW_PACKETS_RECEIVED,
STAT_RAW_BYTES_RECEIVED,
STAT_RAW_PACKETS_TRANSMITTED,
STAT_RAW_BYTES_TRANSMITTED,
STAT_RAW_PACKETS_DROPPED,
STAT_RAW_BYTES_DROPPED,
// duplicate packets
STAT_DUPLICATE_PACKETS_BYPASS,
STAT_DUPLICATE_BYTES_BYPASS,
// injected packet
STAT_INJECTED_PACKETS_FAILED,
STAT_INJECTED_PACKETS_SUCCESS,
STAT_INJECTED_BYTES_SUCCESS,
// control packet
STAT_CONTROL_PACKETS_RECEIVED, // TODO
STAT_CONTROL_BYTES_RECEIVED, // TODO
STAT_CONTROL_PACKETS_TRANSMITTED,
STAT_CONTROL_BYTES_TRANSMITTED,
STAT_CONTROL_PACKETS_DROPPED,
STAT_CONTROL_BYTES_DROPPED,
// TCP segment
STAT_TCP_SEGMENTS_RECEIVED,
STAT_TCP_PAYLOADS_RECEIVED,
STAT_TCP_SEGMENTS_EXPIRED,
STAT_TCP_PAYLOADS_EXPIRED,
STAT_TCP_SEGMENTS_RETRANSMIT,
STAT_TCP_PAYLOADS_RETRANSMIT,
STAT_TCP_SEGMENTS_OVERLAP,
STAT_TCP_PAYLOADS_OVERLAP,
STAT_TCP_SEGMENTS_NOSPACE,
STAT_TCP_PAYLOADS_NOSPACE,
STAT_TCP_SEGMENTS_INORDER,
STAT_TCP_PAYLOADS_INORDER,
STAT_TCP_SEGMENTS_REORDERED,
STAT_TCP_PAYLOADS_REORDERED,
STAT_TCP_SEGMENTS_BUFFERED,
STAT_TCP_PAYLOADS_BUFFERED,
STAT_TCP_SEGMENTS_RELEASED,
STAT_TCP_PAYLOADS_RELEASED,
MAX_STAT,
};
// realtime in milliseconds
enum session_timestamp
{
SESSION_TIMESTAMP_START,
SESSION_TIMESTAMP_LAST,
MAX_TIMESTAMP,
};
struct session;
#define SESSION_SEEN_C2S_FLOW (1 << 0)
#define SESSION_SEEN_S2C_FLOW (1 << 1)
int session_is_symmetric(struct session *sess, unsigned char *flag);
int session_is_symmetric(const struct session *sess, unsigned char *flag);
long long session_get_client_isn(struct session *sess);
long long session_get_server_isn(struct session *sess);
int session_has_duplicate_traffic(const struct session *sess);
enum session_type session_get_type(const struct session *sess);
#define SESSION_IS_TUNNLE_NON (0) /* default is 0, not tunnel; */
#define SESSION_IS_TUNNLE_6OVER4 (1 << 0)
#define SESSION_IS_TUNNLE_4OVER6 (1 << 1)
#define SESSION_IS_TUNNLE_GRE (1 << 2)
#define SESSION_IS_TUNNLE_IP_IN_IP (1 << 3)
#define SESSION_IS_TUNNLE_PPTP (1 << 4)
#define SESSION_IS_TUNNLE_L2TP (1 << 5)
#define SESSION_IS_TUNNLE_TEREDO (1 << 6)
#define SESSION_IS_TUNNLE_GTP (1 << 7)
#define SESSION_IS_TUNNLE_SOCKS (1 << 8)
#define SESSION_IS_TUNNLE_HTTP_PROXY (1 << 9)
enum session_state session_get_current_state(const struct session *sess);
const struct packet *session_get0_current_packet(const struct session *sess);
int session_is_outmost(struct session *sess, uint64_t *flag);
int session_is_innermost(struct session *sess, uint64_t *flag);
enum closing_reason session_get_closing_reason(const struct session *sess);
enum session_direction session_get_direction(const struct session *sess);
enum flow_type session_get_flow_type(const struct session *sess);
const struct packet *session_get_first_packet(const struct session *sess, enum flow_type type);
uint64_t session_get_id(const struct session *sess);
uint64_t session_get_timestamp(const struct session *sess, enum session_timestamp type);
uint64_t session_get_stat(const struct session *sess, enum flow_type type, enum session_stat stat);
#define SESSION_DIRECTION_IN 0
#define SESSION_DIRECTION_OUT 1
int session_get_direction(struct session *sess);
const char *session_get0_readable_addr(const struct session *sess);
enum session_addr_type
{
SESSION_ADDR_TYPE_IPV4_TCP,
SESSION_ADDR_TYPE_IPV4_UDP,
SESSION_ADDR_TYPE_IPV6_TCP,
SESSION_ADDR_TYPE_IPV6_UDP,
SESSION_ADDR_TYPE_UNKNOWN,
__SESSION_ADDR_TYPE_MAX,
};
struct session_addr_ipv4{
uint32_t saddr; /* network order */
uint32_t daddr; /* network order */
uint16_t sport; /* network order */
uint16_t dport; /* network order */
};
void session_set_discard(struct session *sess);
#include <netinet/in.h>
#ifndef IPV6_ADDR_LEN
#define IPV6_ADDR_LEN (sizeof(struct in6_addr))
void session_set_exdata(struct session *sess, int idx, void *ex_ptr);
void *session_get_exdata(const struct session *sess, int idx);
#ifdef __cplusplus
}
#endif
struct session_addr_ipv6
{
uint8_t saddr[IPV6_ADDR_LEN] ;
uint8_t daddr[IPV6_ADDR_LEN] ;
uint16_t sport; /* network order */
uint16_t dport; /* network order */
};
struct session_addr
{
union
{
struct session_addr_ipv4 ipv4;
struct session_addr_ipv6 ipv6;
};
};
struct session_addr *session_get0_addr(struct session *sess, enum session_addr_type *addr_type);
const char *session_get0_readable_addr(struct session *sess);
const char *session_get0_current_payload(struct session *sess, size_t *payload_len);
enum session_state session_get_current_state(struct session *sess);
int session_get_current_thread_id(struct session *sess);
int session_get_current_plugin_id(struct session *sess);
/* ------------session------------------*/
/* |l2|l3|l4|session payload| */
const char *session_get0_current_l3_header(struct session *sess);
const char *session_get0_current_l4_header(struct session *sess);
const char *session_get0_l2_l3_hdr(struct session *sess, int session_direction, size_t *l2_l3_hdr_len);
uint16_t *session_get0_segment_id_list(struct session *sess, int session_direction, size_t *sid_num);
const char *session_get0_route_ctx(struct session *sess, int session_direction, size_t *route_ctx_len);
int session_set_session_id(struct session *sess, uint64_t session_id);
int session_set_preappend_segment_id_list(struct session *sess, uint16_t *sid, size_t sid_num);
const struct packet *session_get0_current_packet(struct session *sess);
//flow direction
#define PACKET_DIRECTION_C2S 0
#define PACKET_DIRECTION_S2C 1
#define PACKET_DIRECTION_UNKNOWN 2
int packet_get_direction(const struct packet *pkt);
//route direction
#define PACKET_DIRECTION_INCOMING 0
#define PACKET_DIRECTION_OUTGOING 1
int packet_get_route_direction(const struct packet *pkt);
const char *packet_get0_data(const struct packet *pkt, size_t *data_len);
int packet_arrive_time(const struct packet *pkt, struct timeval *ts);
unsigned char packet_get_ip_protocol(struct packet *pkt);
void packet_drop(const struct packet *pkt);
const char *packet_get0_readable_addr(struct packet *pkt);
int packet_get_current_thread_id(struct packet *pkt);
struct session *packet_get_session(const struct packet *pkt);

View File

@@ -1,8 +0,0 @@
#pragma once
#include "stellar.h"
typedef void session_exdata_free(struct session *sess, int idx, void *ex_ptr, void *arg);
int stellar_session_exdata_new_index(struct stellar *st, const char *name, session_exdata_free *free_func,void *arg);
int session_exdata_set(struct session *sess, int idx, void *ex_ptr);
void *session_exdata_get(struct session *sess, int idx);

View File

@@ -0,0 +1,55 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#define MESSAGE_MAGIC 0x12345678
#define SESSION_FLAGS_MESSAGE_TOPIC "TOPIC_SESSION_FLAGS"
enum
{
session_flags_bulky_mask = 1,
session_flags_cbr_mask,
session_flags_local_client_mask,
session_flags_local_server_mask,
session_flags_download_mask,
session_flags_interactive_mask,
session_flags_inbound_mask,
session_flags_outbound_mask,
session_flags_pseudo_unidirectional_mask,
session_flags_streaming_mask,
session_flags_unidirectional_mask,
session_flags_random_looking_mask,
session_flags_c2s_mask,
session_flags_s2c_mask,
session_flags_bidirectional_mask,
session_flags_tunneling_mask,
session_flags_all_mask
};
#define SESSION_FLAGS_START (0x0000000000000001)
#define SESSION_FLAGS_BULKY (SESSION_FLAGS_START << session_flags_bulky_mask)
#define SESSION_FLAGS_CBR (SESSION_FLAGS_START << session_flags_cbr_mask)
#define SESSION_FLAGS_LOCAL_CLIENT (SESSION_FLAGS_START << session_flags_local_client_mask)
#define SESSION_FLAGS_LOCAL_SERVER (SESSION_FLAGS_START << session_flags_local_server_mask)
#define SESSION_FLAGS_DOWNLOAD (SESSION_FLAGS_START << session_flags_download_mask)
#define SESSION_FLAGS_INTERACTIVE (SESSION_FLAGS_START << session_flags_interactive_mask)
#define SESSION_FLAGS_INBOUND (SESSION_FLAGS_START << session_flags_inbound_mask)
#define SESSION_FLAGS_OUTBOUND (SESSION_FLAGS_START << session_flags_outbound_mask)
#define SESSION_FLAGS_PSEUDO_UNIDIRECTIONAL (SESSION_FLAGS_START << session_flags_pseudo_unidirectional_mask)
#define SESSION_FLAGS_STREAMING (SESSION_FLAGS_START << session_flags_streaming_mask)
#define SESSION_FLAGS_UNIDIRECTIONAL (SESSION_FLAGS_START << session_flags_unidirectional_mask)
#define SESSION_FLAGS_RANDOM_LOOKING (SESSION_FLAGS_START << session_flags_random_looking_mask)
#define SESSION_FLAGS_C2S (SESSION_FLAGS_START << session_flags_c2s_mask)
#define SESSION_FLAGS_S2C (SESSION_FLAGS_START << session_flags_s2c_mask)
#define SESSION_FLAGS_BIDIRECTIONAL (SESSION_FLAGS_START << session_flags_bidirectional_mask)
#define SESSION_FLAGS_TUNNELING (SESSION_FLAGS_START << session_flags_tunneling_mask)
struct session_flags_message
{
int magic;
uint64_t flags;
uint32_t array_num;
uint32_t *packet_sequence_array;
};

View File

@@ -0,0 +1,27 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/exdata.h"
#include "stellar/session.h"
struct session_manager;
int session_manager_new_session_exdata_index(struct session_manager *sess_mgr, const char *name, exdata_free *func, void *arg);
typedef void on_session_callback(struct session *sess, struct packet *pkt, void *args);
typedef void on_tcp_stream_callback(struct session *sess, const char *tcp_payload, uint32_t tcp_payload_len, void *args);
int session_manager_subscribe_tcp(struct session_manager *sess_mgr, on_session_callback *cb, void *args);
int session_manager_subscribe_udp(struct session_manager *sess_mgr, on_session_callback *cb, void *args);
int session_manager_subscribe_control_packet(struct session_manager *sess_mgr, on_session_callback *cb, void *args);
int session_manager_subscribe_tcp_stream(struct session_manager *sess_mgr, on_tcp_stream_callback *cb, void *args);
#ifdef __cplusplus
}
#endif

View File

@@ -1,36 +0,0 @@
#pragma once
#include "stellar.h"
//session mq
typedef void session_msg_free_cb_func(struct session *sess, void *msg, void *msg_free_arg);
typedef void on_session_msg_cb_func(struct session *sess, int topic_id, const void *msg, void *per_session_ctx, void *plugin_env);
//return topic_id
int stellar_session_mq_create_topic(struct stellar *st, const char *topic_name, session_msg_free_cb_func *msg_free_cb, void *msg_free_arg);
int stellar_session_mq_get_topic_id(struct stellar *st, const char *topic_name);
int stellar_session_mq_update_topic(struct stellar *st, int topic_id, session_msg_free_cb_func *msg_free_cb, void *msg_free_arg);
int stellar_session_mq_destroy_topic(struct stellar *st, int topic_id);
//return 0 if success, otherwise return -1.
int stellar_session_mq_subscribe(struct stellar *st, int topic_id, on_session_msg_cb_func *plugin_on_msg_cb, int plugin_id);
int session_mq_publish_message(struct session *sess, int topic_id, void *msg);
int session_mq_ignore_message(struct session *sess, int topic_id, int plugin_id);
int session_mq_unignore_message(struct session *sess, int topic_id, int plugin_id);
int session_mq_topic_is_active(struct session *sess, int topic_id);
enum session_mq_priority
{
SESSION_MQ_PRIORITY_LOW,
SESSION_MQ_PRIORITY_NORMAL,
SESSION_MQ_PRIORITY_HIGH,
SESSION_MQ_PRIORITY_MAX,
};
int session_mq_publish_message_with_priority(struct session *sess, int topic_id, void *msg, enum session_mq_priority priority);

View File

@@ -0,0 +1,44 @@
#include <sys/uio.h>
#include <netinet/in.h>
#ifndef IPV6_ADDR_LEN
#define IPV6_ADDR_LEN (sizeof(struct in6_addr))
#endif
#define SOCKS_MESSAGE_TOPIC "TOPIC_SOCKS"
enum socks_addr_type
{
SOCKS_ADDR_IPV4,
SOCKS_ADDR_IPV6,
SOCKS_ADDR_FQDN
};
struct socks_addr
{
enum socks_addr_type type;
union
{
uint32_t ipv4; /* network order */
uint8_t ipv6[IPV6_ADDR_LEN] ;
struct iovec fqdn;
};
uint16_t port; /* network order */
};
enum socks_version
{
SOCKS_VERSION_4,
SOCKS_VERSION_5
};
struct socks_info
{
enum socks_version version;
struct socks_addr dst_addr;
struct iovec user_name;
struct iovec password;
};//message data

View File

@@ -1,48 +1,35 @@
#pragma once
struct session;
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include "stellar/log.h"
#include "stellar/packet.h"
struct stellar;
int stellar_get_worker_thread_num(struct stellar *st);
int stellar_get_current_thread_id(struct stellar *st);
//return plugin_env
typedef void *plugin_on_load_func(struct stellar *st);
typedef void plugin_on_unload_func(void *plugin_env);
//return per_session_ctx
typedef void *session_ctx_new_func(struct session *sess, void *plugin_env);
typedef void session_ctx_free_func(struct session *sess, void *session_ctx, void *plugin_env);
//intrinsic topic, publish packet as message
#define TOPIC_TCP "TCP"
#define TOPIC_TCP_STREAM "TCP_STREAM"
#define TOPIC_UDP "UDP"
#define TOPIC_EGRESS "EGRESS"
#define TOPIC_CONTROL_PACKET "CONTROL_PACKET"
//return session plugin_id
int stellar_session_plugin_register(struct stellar *st,
session_ctx_new_func session_ctx_new,
session_ctx_free_func session_ctx_free,
void *plugin_env);
void stellar_session_plugin_dettach_current_session(struct session *sess);
typedef void plugin_on_packet_func(struct packet *pkt, void *on_packet_cb_arg);
//return 0 if success, otherwise return -1.
int stellar_raw_packet_subscribe(struct stellar *st, plugin_on_packet_func *on_packet_cb, void *on_packet_cb_arg);
struct packet;
typedef void plugin_on_packet_func(struct packet *pkt, unsigned char ip_protocol, void *plugin_env);
void stellar_emit_datapath_telemetry(struct packet *pkt, const char * module, const char *str);
//return packet plugin_id
int stellar_packet_plugin_register(struct stellar *st, unsigned char ip_protocol, plugin_on_packet_func on_packet, void *plugin_env);
// only send user build packet, can't send packet which come from network
// void stellar_send_build_packet(struct stellar *st, struct packet *pkt);
struct stellar *stellar_new(const char *toml_file);
void stellar_run(struct stellar *st);
void stellar_free(struct stellar *st);
void stellar_loopbreak(struct stellar *st);
void stellar_reload_log_level(struct stellar *st);
struct logger *stellar_get_logger(struct stellar *st);
//return polling work result, 0: no work, 1: work
typedef int plugin_on_polling_func(void *plugin_env);
//return polling plugin_id
int stellar_polling_plugin_register(struct stellar *st, plugin_on_polling_func on_polling, void *plugin_env);
void stellar_emit_datapath_telemetry(struct packet *pkt, const char * module, const char *str);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,18 @@
#include <sys/uio.h>
#define STRATUM_MESSAGE_TOPIC "TOPIC_STRATUM"
enum cryptocurrency_type
{
ETH=1,
OTHER=2
};
struct stratum_field
{
enum cryptocurrency_type type;
struct iovec mining_pools;
struct iovec mining_program;
struct iovec mining_subscribe;
};//message data

View File

@@ -1,43 +1,52 @@
#pragma once
#include <stdlib.h> //calloc
#include <stddef.h> //NULL
#include <stdlib.h> //calloc
#include <stddef.h> //NULL
#define ALLOC(type, number) ((type *)calloc(sizeof(type), number))
#define CALLOC(type, number) ((type *)calloc(sizeof(type), number))
#define REALLOC(type, ptr, number) ((type *)realloc(ptr, (number) * sizeof(type)))
#define FREE(p) {free(p); p = NULL;}
#define FREE(p) \
{ \
free(p); \
p = NULL; \
}
#define TRUE 1
#define FALSE 0
#define TRUE 1
#define FALSE 0
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
#endif
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
(type *)( (char *)__mptr - offsetof(type,member) ); })
#endif
#ifndef count_of
#define count_of(x) (sizeof(x) / sizeof(0 [x]))
#endif
#ifndef likely
#define likely(x) __builtin_expect((x), 1)
#endif /* likely */
#ifndef unlikely
#define unlikely(x) __builtin_expect((x), 0)
#endif /* unlikely */
#ifndef __unused
#define __unused __attribute__((__unused__))
#endif
#ifndef likely
#define likely(x) __builtin_expect((x),1)
#endif /* likely */
#ifndef unlikely
#define unlikely(x) __builtin_expect((x),0)
#endif /* unlikely */

View File

@@ -1,36 +0,0 @@
TOPDIR = ./..
CC=gcc
MAKE=make
TARGET=example
SIMPLE=simple_stellar_plugin.so
EXAMPLE_FLAG = -DLUAPLUGIN_EXAMPLE
SRC := example_plugin_manage.c
OBJECTS := example_plugin_manage.o
SIMPLE_SRC := simple_example_plugin.c
SIMPLE_OBJECTS := simple_example_plugin.o
INCLUDE = -I$(TOPDIR)/output/include -I$(TOPDIR)/dependence/include -I$(TOPDIR)/example/include
CFLAGS = -g -Wextra -Wall -O0 -fPIC
# CFLAGS += -pedantic -fsanitize=address
# LDLIBS = -L$(TOPDIR)/output/lib -llua -ldl -lm
LDLIBS += -L$(TOPDIR)/output/libs -lluaplugin -L$(TOPDIR)/dependence/lib -ltoml -lbitmap -lplugin_manager
TARGET:$(OBJECTS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) $(LDLIBS)
$(OBJECTS):$(SRC)
$(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SRC) -c $^
SIMPLE:$(SIMPLE_OBJECTS)
$(CC) $(CFLAGS) --shared -o $(SIMPLE) $(SIMPLE_OBJECTS) $(LDLIBS)
cp $(SIMPLE) plugin
$(SIMPLE_OBJECTS):$(SIMPLE_SRC)
$(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SIMPLE_SRC) -c $^
clean:
rm -rf $(OBJECTS) $(TARGET) $(SIMPLE_OBJECTS) $(SIMPLE)
rm -rf $(TOPDIR)/output/libs/$(TARGET)

View File

@@ -1,15 +0,0 @@
# config.toml
[[plugin]]
path = "./plugin/example_plugin_regist.lua"
init = "plugin_load"
exit = "plugin_unload"
[[plugin]]
path = "./plugin/example_plugin_topic.lua"
init = "plugin_load"
exit = "plugin_unload"
[[plugin]]
path = "./plugin/example_plugin_message.lua"
init = "plugin_load"
exit = "plugin_unload"

View File

@@ -1,4 +0,0 @@
[[plugin]]
path = "./plugin/simple_stellar_plugin.so"
init = "simple_plugin_sub_session_stat_init"
exit = "simple_plugin_sub_session_stat_exit"

View File

@@ -1,103 +0,0 @@
#include "lua_plugin_manage.h"
#include <toml.h>
#include <utarray.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define CONFIG_PATH "../output/conf/lua_plugin_manage.toml"
struct lua_config_specific * config_load(const char *config_file_name, int * specific_num);
int main()
{
struct stellar *st = stellar_new();
int num = 0;
struct lua_config_specific * specific = config_load(CONFIG_PATH, &num);
struct lua_plugin_manage_schema *schema = lua_plugin_manage_init(st, num, specific);
for (int i = 0; i < 1; ++i)
{
struct session *sess1 = session_new(10000, 20000);
struct registered_session_plugin_schema *plugin = NULL;
while ((plugin = utarray_next(st->plugin_array, plugin)))
{
printf("call plugin id %d\n", plugin->plugin_id);
sess1->plugin_id = plugin->plugin_id;
void *temp_pointer = plugin->on_ctx_new(sess1, plugin->plugin_env);
struct session_data_pair pair = {plugin->plugin_id, temp_pointer};
utarray_push_back(sess1->session_plugin, &pair);
printf("debug session: %d, %d\n", sess1->session_id, sess1->session_type);
}
plugin = NULL;
while ((plugin = utarray_next(st->plugin_array, plugin)))
{
printf("call plugin id %d\n", plugin->plugin_id);
sess1->plugin_id = plugin->plugin_id;
void *temp_context = session_get_private(sess1, plugin->plugin_id);
plugin->on_ctx_free(sess1, temp_context, plugin->plugin_env);
}
utarray_free(sess1->session_plugin);
free(sess1);
}
lua_plugin_manage_exit(schema);
return 0;
}
struct lua_config_specific * config_load(const char *config_file_name, int * specific_count)
{
if (__glibc_unlikely(!config_file_name))
return NULL;
int specific_num = 0;
char errbuff[256] = {0};
if (access(config_file_name, F_OK))
return NULL;
FILE *fp = fopen(config_file_name, "r");
if (!fp)
return NULL;
toml_table_t *conf = toml_parse_file(fp, errbuff, sizeof(errbuff));
if (fp)
fclose(fp);
if (!conf)
{
printf("parse config file failed, filename %s, err %s\n", config_file_name, errbuff);
return NULL;
}
toml_array_t *plugin_array = toml_array_in(conf, "plugin");
if (!plugin_array)
return NULL;
specific_num = toml_array_nelem(plugin_array);
struct lua_config_specific * new_spec = (struct lua_config_specific *)calloc(specific_num, sizeof(struct lua_config_specific));
if (!new_spec)
return NULL;
struct lua_config_specific * specific = NULL;
for (int i = 0; i < specific_num; ++i)
{
toml_table_t *plugin = toml_table_at(plugin_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");
specific = &new_spec[i];
if (toml_rtos(raw_filepath, &specific->config_specific_file) ||
toml_rtos(raw_load_func_name, &specific->config_specific_load_func) ||
toml_rtos(raw_unload_func_name, &specific->config_specific_unload_func))
{
toml_free(conf);
free(specific);
return NULL;
}
}
*specific_count = specific_num;
return new_spec;
}

View File

@@ -1,298 +0,0 @@
#include "plugin_manager_gtest_mock.h"
#include "lua_plugin_manage.h"
#include <toml.h>
#include <utarray.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <getopt.h>
#include <time.h>
#define PLUGIN_CONFIG_PATH "./conf/plugin_manage.toml"
#define LUA_CONFIG_PATH "./conf/lua_plugin_manage.toml"
// #define DEBUG_PLUGIN_SCHEMA
#define PACKET_COUNT 3
#define SESSION_COUNT 10
struct arg_config
{
int session_count;
int packet_count;
int wait_time;
int thread_num;
unsigned char lua_mod;
unsigned char session_mod;
unsigned char print_mod;
unsigned char time_mod;
char *config_path;
};
struct arg_config global_arg_config = {SESSION_COUNT, PACKET_COUNT, 10, 1, 1, 1, 1, 1, LUA_CONFIG_PATH};
static struct lua_config_specific *config_load(const char *config_file_name, int *specific_num);
static void parse_args(int argc, char *argv[]);
// #ifdef DEBUG_PLUGIN_SCHEMA
static void debug_plugin_manage_specifics(struct lua_config_specific *specifics, int num);
static void debug_plugin_manage_schema(struct plugin_manager_schema *schema);
// #endif
int main(int argc, char *argv[])
{
parse_args(argc, argv);
if (global_arg_config.print_mod)
{
printf("***** ***** ***** ***** ***** *****\n");
printf("load example config:\n");
printf("session count is %d\n", global_arg_config.session_count);
printf("packet count is %d\n", global_arg_config.packet_count);
printf("thread num is %d\n", global_arg_config.thread_num);
printf("load config from path %s\n", global_arg_config.config_path);
printf("***** ***** ***** ***** ***** *****\n\n");
}
clock_t start_clock, end_clock;
struct stellar st;
memset(&st, 0, sizeof(st));
st.thread_num = global_arg_config.thread_num;
/* ***** ***** 进行初始化 ***** ***** */
struct plugin_manager_schema *plug_mgr = plugin_manager_init(&st, PLUGIN_CONFIG_PATH);
assert(plug_mgr);
/* 初始化lua插件 */
printf("now wait time to compute memory ... ...\n");
sleep(global_arg_config.wait_time);
struct lua_plugin_manage_schema *lua_schema = NULL;
if (global_arg_config.lua_mod)
{
int num = 0;
struct lua_config_specific *specific = config_load(LUA_CONFIG_PATH, &num);
assert(specific);
if (global_arg_config.print_mod)
debug_plugin_manage_specifics(specific, num);
lua_schema = lua_plugin_manage_init(&st, num, specific);
st.lua_plug_mgr = lua_schema;
assert(lua_schema);
if (specific)
free(specific);
/* 测试单个插件加载函数 */
struct lua_config_specific add_specific = {NULL, NULL, NULL};
add_specific.config_specific_file = "./plugin/example_plugin_load.lua";
add_specific.config_specific_load_func = "plugin_load";
add_specific.config_specific_unload_func = "plugin_unload";
lua_plugin_manage_load_one_specific(st.lua_plug_mgr, &add_specific);
if (global_arg_config.print_mod)
debug_lua_plugin_manage_schema(lua_schema);
printf("now wait time to compute memory ... ...\n");
sleep(global_arg_config.wait_time);
}
// #ifdef DEBUG_PLUGIN_SCHEMA
if (global_arg_config.print_mod)
debug_plugin_manage_schema(plug_mgr);
// #endif
/* ***** ***** 初始化完成 ***** ***** */
/* ***** ***** 会话相关测试 ***** ***** */
if (global_arg_config.session_mod)
{
unsigned char ip_proto = 6;
struct packet pkt = {&st, TCP, ip_proto};
struct session *sess = (struct session *)calloc(global_arg_config.session_count, sizeof(struct session));
memset(sess, 0, global_arg_config.session_count * sizeof(struct session));
/* 创建session */
for (int i = 0; i < global_arg_config.session_count; i++)
{
sess[i].plug_mgr_rt = plugin_manager_session_runtime_new(plug_mgr, &sess[i]);
sess[i].type = SESSION_TYPE_TCP;
}
clock_t total_clock = 0;
for (int j = 0; j < global_arg_config.packet_count; j++)
{
plugin_manager_on_packet_ingress(plug_mgr, &pkt);
for (int i = 0; i < global_arg_config.session_count; i++)
{
sess[i].sess_pkt_cnt += 1;
if (global_arg_config.time_mod)
start_clock = clock();
plugin_manager_on_session_ingress(&sess[i], &pkt);
plugin_manager_on_session_egress(&sess[i], &pkt);
if (global_arg_config.time_mod)
{
end_clock = clock();
total_clock += (end_clock - start_clock);
}
}
if (global_arg_config.time_mod)
{
printf("for session count %d, total time is %ld\n", global_arg_config.session_count, total_clock);
printf("trans to second, time is %f\n", ((double)total_clock / CLOCKS_PER_SEC));
}
plugin_manager_on_packet_egress(plug_mgr, &pkt);
}
/* 释放session */
for (int i = 0; i < global_arg_config.session_count; i++)
{
plugin_manager_on_session_closing(&sess[i]);
plugin_manager_session_runtime_free(sess[i].plug_mgr_rt);
}
}
/* ***** ***** 会话相关完成 ***** ***** */
/* ***** ***** 释放 ***** ***** */
lua_plugin_manage_exit(lua_schema);
plugin_manager_exit(plug_mgr);
/* ***** ***** 释放 ***** ***** */
return 0;
}
static struct lua_config_specific *config_load(const char *config_file_name, int *specific_count)
{
if (__glibc_unlikely(!config_file_name))
return NULL;
int specific_num = 0;
char errbuff[256] = {0};
if (access(config_file_name, F_OK))
return NULL;
FILE *fp = fopen(config_file_name, "r");
if (!fp)
return NULL;
toml_table_t *conf = toml_parse_file(fp, errbuff, sizeof(errbuff));
if (fp)
fclose(fp);
if (!conf)
{
printf("parse config file failed, filename %s, err %s\n", config_file_name, errbuff);
return NULL;
}
toml_array_t *plugin_array = toml_array_in(conf, "plugin");
if (!plugin_array)
return NULL;
specific_num = toml_array_nelem(plugin_array);
struct lua_config_specific *new_spec = (struct lua_config_specific *)calloc(specific_num, sizeof(struct lua_config_specific));
if (!new_spec)
return NULL;
struct lua_config_specific *specific = NULL;
for (int i = 0; i < specific_num; ++i)
{
toml_table_t *plugin = toml_table_at(plugin_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");
specific = &new_spec[i];
if (toml_rtos(raw_filepath, &specific->config_specific_file) ||
toml_rtos(raw_load_func_name, &specific->config_specific_load_func) ||
toml_rtos(raw_unload_func_name, &specific->config_specific_unload_func))
{
toml_free(conf);
free(specific);
return NULL;
}
}
*specific_count = specific_num;
return new_spec;
}
static void parse_args(int argc, char *argv[])
{
int opt;
static const char *shortopts = "s:p:w:c:t:lnde";
static struct option longopts[] = {
{"session_count", required_argument, NULL, 's'},
{"packet_count", required_argument, NULL, 'p'},
{"wait_time", required_argument, NULL, 'w'},
{"config_path", required_argument, NULL, 'c'},
{"thread_num", required_argument, NULL, 't'},
{"disable_lua", no_argument, NULL, 'l'},
{"disable_session", no_argument, NULL, 'n'},
{"print_debug", no_argument, NULL, 'd'},
{"disable_time", no_argument, NULL, 'e'},
{0, 0, 0, 0},
};
while ((opt = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1)
{
switch (opt)
{
case 's':
global_arg_config.session_count = atoi(optarg);
break;
case 'p':
global_arg_config.packet_count = atoi(optarg);
break;
case 'w':
global_arg_config.wait_time = atoi(optarg);
break;
case 'c':
global_arg_config.config_path = strdup(optarg);
break;
case 't':
global_arg_config.thread_num = atoi(optarg);
break;
case 'l':
global_arg_config.lua_mod = 0;
break;
case 'n':
global_arg_config.session_mod = 0;
break;
case 'd':
global_arg_config.print_mod = 1;
break;
case 'e':
global_arg_config.time_mod = 0;
break;
default:
break;
}
}
}
// #ifdef DEBUG_PLUGIN_SCHEMA
static void debug_plugin_manage_specifics(struct lua_config_specific *specifics, int num)
{
printf("***** ***** ***** ***** ***** *****\n");
printf("load config specifics count is %d\n", num);
for (int i = 0; i < num; ++i)
{
printf("[%d]file path: %s\n", i, specifics[i].config_specific_file);
printf("[%d]load func: %s\n", i, specifics[i].config_specific_load_func);
printf("[%d]unload func: %s\n", i, specifics[i].config_specific_unload_func);
}
printf("***** ***** ***** ***** ***** *****\n\n");
}
static void debug_plugin_manage_schema(struct plugin_manager_schema *schema)
{
struct registered_session_plugin_schema *plugin = NULL;
for (int i = 0; i < (int)utarray_len(schema->registered_session_plugin_array); ++i)
{
plugin = (struct registered_session_plugin_schema *)utarray_eltptr(schema->registered_session_plugin_array, (unsigned int)i);
printf("plugin[%d]: new func %p, free func %p, env %p\n", i, plugin->on_ctx_new, plugin->on_ctx_free, plugin->plugin_env);
}
printf("\n");
return;
}
// #endif

View File

@@ -1,22 +0,0 @@
#pragma once
#include "stellar/stellar.h"
struct plugin_manager_schema;
struct plugin_manager_runtime;
struct plugin_manager_schema *plugin_manager_init(struct stellar *st, const char *plugin_spec_file_path);
void plugin_manager_exit(struct plugin_manager_schema *plug_mgr);
void plugin_manager_on_packet_ingress(struct plugin_manager_schema *plug_mgr, struct packet *pkt);
void plugin_manager_on_packet_egress(struct plugin_manager_schema *plug_mgr, struct packet *pkt);
//return polling work state, 0: idle, 1: working
int plugin_manager_on_polling(struct plugin_manager_schema *plug_mgr);
//publish and dispatch session msg(msg, pkt) on session_mq
void plugin_manager_on_session_ingress(struct session *sess,struct packet *pkt);
void plugin_manager_on_session_egress(struct session *sess,struct packet *pkt);
void plugin_manager_on_session_closing(struct session *sess);
struct plugin_manager_runtime *plugin_manager_session_runtime_new(struct plugin_manager_schema *plug_mgr, struct session *sess);
void plugin_manager_session_runtime_free(struct plugin_manager_runtime *plug_mgr_rt);

View File

@@ -1,102 +0,0 @@
#ifdef __cplusplus
extern "C"
{
#endif
#include "plugin_manager_interna.h"
#include "stellar_internal.h"
#include "stellar/session.h"
#include "lua_plugin_manage.h"
//mock stellar
struct stellar
{
struct plugin_manager_schema *plug_mgr;
struct lua_plugin_manage_schema * lua_plug_mgr;
int thread_num;
};
struct packet
{
struct stellar *st;
enum packet_type type;
unsigned char ip_proto;
};
struct session
{
struct plugin_manager_runtime *plug_mgr_rt;
enum session_type type;
enum session_state state;
int sess_pkt_cnt;
};
enum session_state session_get_current_state(struct session *sess)
{
return sess->state;
}
enum session_type session_get_type(struct session *sess)
{
return sess->type;
}
int session_get_current_plugin_id(struct session *sess)
{
return sess->plug_mgr_rt->current_session_plugin_id;
}
struct plugin_manager_schema * stellar_plugin_manager_schema_get(struct stellar *st)
{
return st->plug_mgr;
}
int stellar_plugin_manager_schema_set(struct stellar *st, struct plugin_manager_schema *pm)
{
st->plug_mgr=pm;
return 0;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int session_get_current_thread_id(struct session *sess)
{
return 0;
}
int stellar_get_worker_thread_num(struct stellar *st)
{
return st->thread_num;
}
int stellar_get_current_thread_id(struct stellar *st)
{
return 0;
}
#pragma GCC diagnostic pop
struct stellar * packet_stellar_get(struct packet *pkt)
{
return pkt->st;
}
struct plugin_manager_runtime * session_plugin_manager_runtime_get(struct session *sess)
{
return sess->plug_mgr_rt;
}
unsigned char packet_get_ip_protocol(struct packet *pkt)
{
return pkt->ip_proto;
}
enum packet_type packet_get_type(const struct packet *pkt)
{
return pkt->type;
}
#ifdef __cplusplus
}
#endif

View File

@@ -1,199 +0,0 @@
#include "plugin_manager.h"
#include "stellar/stellar.h"
#include "stellar/session_exdata.h"
#include "stellar/session_mq.h"
#include "stellar/packet_exdata.h"
#include "stellar/packet_mq.h"
#include "bitmap.h"
#include "utarray.h"
struct per_thread_exdata_array
{
struct stellar_exdata *exdata_array;
};
struct stellar_message;
struct plugin_manger_per_thread_data
{
struct per_thread_exdata_array per_thread_pkt_exdata_array;
struct stellar_message *priority_mq[SESSION_MQ_PRIORITY_MAX];// message list
struct stellar_message *dealth_letter_queue;// dlq list
long long pub_packet_msg_cnt;
};
struct plugin_manager_schema
{
struct stellar *st;
UT_array *plugin_load_specs_array;
UT_array *packet_exdata_schema_array;
UT_array *session_exdata_schema_array;
UT_array *stellar_mq_schema_array;
UT_array *registered_session_plugin_array;
UT_array *registered_packet_plugin_array;
UT_array *registered_polling_plugin_array;
int packet_mq_topic_num;
int session_mq_topic_num;
int packet_topic_subscriber_num;
int session_topic_subscriber_num;
int tcp_topic_id;
int tcp_stream_topic_id;
int udp_topic_id;
int egress_topic_id;
int control_packet_topic_id;
int max_message_dispatch;
struct plugin_manger_per_thread_data *per_thread_data;
}__attribute__((aligned(sizeof(void*))));
enum plugin_exdata_state
{ INIT, ACTIVE, EXIT };
struct stellar_exdata
{
void *exdata;
enum plugin_exdata_state state;
};
struct stellar_exdata_schema
{
char *name;
union
{
void *free_func;
session_exdata_free *sess_free_func;
packet_exdata_free *pkt_free_func;
};
void *free_arg;
int idx;
}__attribute__((aligned(sizeof(void*))));
enum stellar_topic_type
{
ON_SESSION_TOPIC,
ON_PACKET_TOPIC,
};
struct stellar_message
{
struct
{
int topic_id;
enum stellar_topic_type type;
enum session_mq_priority priority;
} header;
void *body;
struct stellar_message *next, *prev;
} __attribute__((aligned(sizeof(void *))));
typedef struct stellar_mq_subscriber
{
int topic_subscriber_idx;
int plugin_idx;
union
{
on_session_msg_cb_func *sess_msg_cb;
on_packet_msg_cb_func *pkt_msg_cb;
void *msg_cb;
};
struct stellar_mq_subscriber *next, *prev;
}stellar_mq_subscriber __attribute__((aligned(sizeof(void*))));
struct stellar_mq_topic_schema
{
char *topic_name;
void *free_cb_arg;
int topic_id;
int subscriber_cnt;
int is_destroyed;
union
{
void *free_cb;
session_msg_free_cb_func *sess_msg_free_cb;
packet_msg_free_cb_func *pkt_msg_free_cb;
};
struct stellar_mq_subscriber *subscribers;
}__attribute__((aligned(sizeof(void*))));
struct session_plugin_ctx_runtime
{
enum plugin_exdata_state state;
int session_plugin_id;
void *plugin_ctx;
}__attribute__((aligned(sizeof(void*))));
struct plugin_manager_runtime
{
struct plugin_manager_schema *plug_mgr;
struct session *sess;
struct bitmap *session_mq_status; //N * M bits, N topic, M subscriber
struct bitmap *session_topic_status; //N bits, N topic
struct stellar_exdata *sess_exdata_array;
struct session_plugin_ctx_runtime *plugin_ctx_array;//N plugins TODO: call alloc and free
int current_session_plugin_id;
int pub_session_msg_cnt;
}__attribute__((aligned(sizeof(void*))));
struct registered_packet_plugin_schema
{
char ip_protocol;
plugin_on_packet_func *on_packet;
void *plugin_env;
UT_array *registed_packet_mq_subscriber_info;
}__attribute__((aligned(sizeof(void*))));
struct registered_polling_plugin_schema
{
plugin_on_polling_func *on_polling;
void *plugin_env;
}__attribute__((aligned(sizeof(void*))));
struct stellar_mq_subscriber_info
{
int topic_id;
int subscriber_idx;
}__attribute__((aligned(sizeof(void*))));
struct registered_session_plugin_schema
{
session_ctx_new_func *on_ctx_new;
session_ctx_free_func *on_ctx_free;
void *plugin_env;
UT_array *registed_session_mq_subscriber_info;
}__attribute__((aligned(sizeof(void*))));
#define SESSION_PULGIN_ID_BASE 0x00000
#define PACKET_PULGIN_ID_BASE 0x10000
#define POLLING_PULGIN_ID_BASE 0x20000
/*******************************
* PLUGIN MANAGER INIT & EXIT *
*******************************/
#define MAX_MSG_PER_DISPATCH 128
#include <dlfcn.h>
struct plugin_specific
{
char plugin_name[256];
plugin_on_load_func *load_cb;
plugin_on_unload_func *unload_cb;
void *plugin_ctx;
}__attribute__((aligned(sizeof(void*))));

View File

@@ -1,27 +0,0 @@
#pragma once
#include "stellar/stellar.h"
struct plugin_manager_schema;
struct plugin_manager_runtime;
int stellar_plugin_manager_schema_set(struct stellar *st, struct plugin_manager_schema *pm);
struct plugin_manager_schema * stellar_plugin_manager_schema_get(struct stellar *st);
struct plugin_manager_runtime * session_plugin_manager_runtime_get(struct session *sess);
enum packet_type
{
UNKNOWN,
IPv4,
IPv6,
UDP,
TCP,
TCP_STREAM,
CONTROL,
};
enum packet_type packet_get_type(const struct packet *pkt);
struct stellar * packet_stellar_get(struct packet *pkt);

View File

@@ -1,11 +0,0 @@
function plugin_load(stellar, plug_env)
print("now load lua plugin example load")
print("this example aims to test load function")
plug_env.data = "load plugin env"
print("plugin env data is", plug_env.data)
end
function plugin_unload(plug_env)
print("now unload lua plugin example load")
print("plugin env data is", plug_env.data)
end

View File

@@ -1,30 +0,0 @@
function plugin_ctx_new(sess, plug_env, sess_context)
-- print("now create new ctx example message, plugin id", plug_env.id)
end
function plugin_ctx_free(sess, sess_context, plug_env)
-- print("now begin to free ctx context example message")
end
function on_message(sess, topic_id, msg, sess_context, env)
-- print("message call on message function, id", topic_id)
-- print("message is", msg.data)
end
function plugin_load(stellar, plug_env)
print("now begin to load plugin example messaga")
print("this example aims to test topic functions")
plug_env.st = stellar
plug_env.id = plugin_manage.register(stellar, plugin_ctx_new, plugin_ctx_free, plug_env)
plug_env.data = "this is message example plug env data"
--[[ 订阅TOPIC_SESSION_STAT, 并完成函数注册 ]]
test_topic_id = message.gettopicid(stellar, "TOPIC_SESSION_STAT")
message.subscribetopic(stellar, test_topic_id, on_message, plug_env.id)
end
function plugin_unload(plug_env)
print("now unload lua plugin example message")
print("plugin env data is", plug_env.data)
end

View File

@@ -1,25 +0,0 @@
function plugin_ctx_new(sess, plug_env, sess_context)
print("now begin to create new ctx context example regist")
sess_context.data = "this is example regist sess context data"
print("session data is", sess_context.data)
end
function plugin_ctx_free(sess, sess_context, plug_env)
print("now begin to free ctx context example regist")
print("session data is", sess_context.data)
end
function plugin_load(stellar, plug_env)
print("now load lua plugin example regist")
print("this example aims to test regist function")
plug_env.data = "my example regist plugin env"
--[[ 由于未订阅消息, 注册函数应该永远不会触发 ]]
plug_env.id = plugin_manage.register(stellar, plugin_ctx_new, plugin_ctx_free, plug_env)
print("plugin env data is", plug_env.data)
print("after regist, plugin id is", plug_env.id)
end
function plugin_unload(plug_env)
print("now unload lua plugin example regist")
print("plugin env data is", plug_env.data)
end

View File

@@ -1,57 +0,0 @@
function plugin_ctx_new(sess, plug_env, sess_context)
-- print("now create new ctx example topic, plugin id", plug_env.id)
msg = {}
msg.data = "this is message"
message.publishmessage(sess, plug_env.topic_id, msg)
end
function plugin_ctx_free(sess, sess_context, plug_env)
-- print("now begin to free ctx context example topic")
end
function on_message(sess, topic_id, msg, sess_context, env)
-- print("topic call on message function, id", topic_id)
end
function free_message(sess, msg, private_env)
-- print("message need to free is", msg.data)
-- print("env id is ", private_env.id)
end
function plugin_load(stellar, plug_env)
print("now begin to load plugin example topic")
print("this example aims to test topic functions")
plug_env.st = stellar
plug_env.id = plugin_manage.register(stellar, plugin_ctx_new, plugin_ctx_free, plug_env)
plug_env.data = "this is topic example plug env data"
--[[ 获取TCP topic, 并完成订阅 ]]
tcp_topic_id = message.gettopicid(stellar, "TCP")
print("get TCP topic id is", tcp_topic_id)
message.subscribetopic(stellar, tcp_topic_id, on_message, plug_env.id)
--[[ 创建TOPIC_SESSION_STAT, 并完成函数注册 ]]
msg_private_table = {}
msg_private_table.data = "this is example topic msg private data"
test_topic_id = message.gettopicid(stellar, "TOPIC_SESSION_STAT")
if (test_topic_id < 0)
then
--[[ 该消息未创建, 创建该topic ]]
test_topic_id = message.createtopic(stellar, "TOPIC_SESSION_STAT", free_message, msg_private_table)
print("create topic is", test_topic_id)
else
--[[ 如果该消息已经注册, 更新其注册函数 ]]
message.updatetopic(stellar, test_topic_id, free_message, msg_private_table)
print("topic already created, id is", test_topic_id)
end
plug_env.tcp_topic_id = tcp_topic_id
plug_env.topic_id = test_topic_id
end
function plugin_unload(plug_env)
print("now unload lua plugin example topic")
print("plugin env data is", plug_env.data)
print("now destory topic id is", plug_env.topic_id)
message.destorytopic(plug_env.st, plug_env.topic_id)
end

View File

@@ -1,362 +0,0 @@
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include "stellar/stellar.h"
#include "stellar/session.h"
#include "stellar/utils.h"
#include "stellar/session_exdata.h"
#include "stellar/session_mq.h"
#include "stellar/packet_exdata.h"
#include "stellar/packet_mq.h"
#include <stdio.h>
#include <string.h>
#include <assert.h>
struct simple_stellar_plugin_env
{
struct stellar *st;
int session_plugin_id;
int session_exdata_idx;
int packet_exdata_idx;
int packet_topic_id;
int stat_topic_id;
int egress_topic_id;
int tcp_topic_id;
int udp_topic_id;
int tcp_stream_topic_id;
long long tcp_packet_count;
long long udp_packet_count;
long long icmp_packet_count;
long long icmp6_packet_count;
long long polling_times;
};
struct mq_message_stat
{
uint32_t c2s_pkts;
uint32_t c2s_bytes;
uint32_t s2c_pkts;
uint32_t s2c_bytes;
uint32_t c2s_stream_pkts;
uint32_t c2s_stream_bytes;
uint32_t s2c_stream_pkts;
uint32_t s2c_stream_bytes;
};
static void print_session_stat(struct session *sess, struct mq_message_stat *stat, int plugin_id, const char *banner)
{
if (stat)
{
printf("%s(plug:%d)-----------%20s: ", banner, plugin_id, session_get0_readable_addr(sess));
printf("server-pkt=%u, server-count=%u, client-pkt=%u, client-count=%u, ", stat->c2s_pkts, stat->c2s_bytes,
stat->s2c_pkts, stat->s2c_bytes);
printf("total-pkt=%u, ", stat->c2s_pkts + stat->s2c_pkts);
printf("total-count=%u\n", stat->c2s_bytes + stat->s2c_bytes);
if(stat->c2s_stream_pkts+stat->s2c_stream_pkts > 0)
{
printf("----------------server-stream_pkt=%u, server-stream_count=%u, client-stream_pkt=%u, client-stream_count=%u\n", stat->c2s_stream_pkts, stat->c2s_stream_bytes,
stat->s2c_stream_pkts, stat->s2c_stream_bytes);
}
}
return;
}
/*******************************
* simple session & packet plugin *
*******************************/
static void *simple_plugin_session_ctx_new(struct session *sess, void *plugin_env)
{
struct mq_message_stat * stat= CALLOC(struct mq_message_stat, 1);
struct simple_stellar_plugin_env *env=(struct simple_stellar_plugin_env *)plugin_env;
session_exdata_set(sess, env->session_exdata_idx, stat);
return stat;
}
static void simple_plugin_session_ctx_free(struct session *sess, void *session_ctx, void *plugin_env)
{
struct simple_stellar_plugin_env *env=(struct simple_stellar_plugin_env *)plugin_env;
struct mq_message_stat *stat = (struct mq_message_stat *)session_ctx;
print_session_stat(sess, stat, env->session_plugin_id, __FUNCTION__);
session_exdata_set(sess, env->session_exdata_idx, NULL);
if(session_ctx)FREE(session_ctx);
return;
}
static void simple_plugin_on_session_msg(struct session *sess, int topic_id, const void *data, void *plugin_ctx, void *plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
struct mq_message_stat *stat = (struct mq_message_stat *)plugin_ctx;
struct packet * pkt=(struct packet *)data;
if (pkt)
{
// TEST: try stellar_session_plugin_dettach_current_session when pkt > 3
if(stat->c2s_pkts+stat->s2c_pkts >= 3 && session_get_type(sess)== SESSION_TYPE_UDP)
{
stellar_session_plugin_dettach_current_session(sess);
return;
}
size_t payload_len = 0;
session_get0_current_payload(sess, &payload_len);
int dir = packet_get_direction(pkt);
if (dir==PACKET_DIRECTION_C2S)
{
if(topic_id==env->tcp_stream_topic_id)
{
stat->c2s_stream_bytes += payload_len;
stat->c2s_stream_pkts += 1;
}
else
{
stat->c2s_bytes += payload_len;
stat->c2s_pkts += 1;
}
}
if (dir==PACKET_DIRECTION_S2C)
{
if(topic_id==env->tcp_stream_topic_id)
{
stat->s2c_stream_bytes += payload_len;
stat->s2c_stream_pkts += 1;
}
else
{
stat->s2c_bytes += payload_len;
stat->s2c_pkts += 1;
}
}
session_mq_publish_message(sess, ((struct simple_stellar_plugin_env *)plugin_env)->stat_topic_id, stat);
}
return;
}
void simple_plugin_on_packet(struct packet *pkt, unsigned char ip_protocol, void *plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
packet_exdata_set(pkt, env->packet_exdata_idx, env);
packet_mq_publish_message(pkt, env->packet_topic_id, env);
switch (ip_protocol)
{
case IPPROTO_TCP:
env->tcp_packet_count++;
break;
case IPPROTO_UDP:
env->udp_packet_count++;
break;
case IPPROTO_ICMP:
env->icmp_packet_count++;
break;
case IPPROTO_ICMPV6:
env->icmp6_packet_count++;
break;
default:
perror("invalid ip_protocol\n");
exit(-1);
break;
}
return;
}
void simple_plugin_packet_get_exdata(struct packet *pkt, unsigned char ip_protocol , void *plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
struct simple_stellar_plugin_env *exdata = (struct simple_stellar_plugin_env *)packet_exdata_get(pkt, env->packet_exdata_idx);
if(memcmp(env, exdata, sizeof(struct simple_stellar_plugin_env)) != 0)
{
abort();
}
return;
}
int simple_plugin_on_polling(void *plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
env->polling_times++;
return 0;
}
static void simple_plugin_packet_exdata_free(struct packet *pkt , int idx , void *ex_ptr, void *arg)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)arg;
assert(env);
struct simple_stellar_plugin_env *exdata = (struct simple_stellar_plugin_env *)ex_ptr;
if(memcmp(env, exdata, sizeof(struct simple_stellar_plugin_env)) != 0)
{
abort();
}
}
static void simple_plugin_packet_msg_free(struct packet *pkt , void *msg, void *msg_free_arg)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)msg_free_arg;
assert(env);
struct simple_stellar_plugin_env *exdata = (struct simple_stellar_plugin_env *)msg;
if(memcmp(env, exdata, sizeof(struct simple_stellar_plugin_env)) != 0)
{
abort();
}
}
static void simple_plugin_on_packet_msg_cb(struct packet *pkt , int topic_id , const void *msg, void *plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
assert(env);
struct simple_stellar_plugin_env *exdata = (struct simple_stellar_plugin_env *)msg;
if(memcmp(env, exdata, sizeof(struct simple_stellar_plugin_env)) != 0)
{
abort();
}
}
void *simple_session_packet_plugin_init(struct stellar *st)
{
struct simple_stellar_plugin_env *env = CALLOC(struct simple_stellar_plugin_env, 1);
env->st = st;
env->session_exdata_idx = stellar_session_exdata_new_index(st, "EXDATA_SESSION_STAT", NULL, NULL);
env->session_plugin_id = stellar_session_plugin_register(st,
simple_plugin_session_ctx_new,
simple_plugin_session_ctx_free,
env);
int tcp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_TCP, simple_plugin_on_packet, env);
int udp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_UDP, simple_plugin_on_packet, env);
int icmp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_ICMP, simple_plugin_on_packet, env);
int icmp6_plugin_id=stellar_packet_plugin_register(st, IPPROTO_ICMPV6, simple_plugin_on_packet, env);
if(tcp_plugin_id < 0 || udp_plugin_id < 0 || icmp_plugin_id < 0 || icmp6_plugin_id < 0)
{
perror("register packet plugin return invalid plugin id\n");
exit(-1);
}
env->packet_topic_id=stellar_packet_mq_get_topic_id(st, "TOPIC_PACKET_ENV");
if(env->packet_topic_id < 0)
{
env->packet_topic_id=stellar_packet_mq_create_topic(st, "TOPIC_PACKET_ENV", simple_plugin_packet_msg_free, env);
}
tcp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_TCP, simple_plugin_packet_get_exdata, env);
udp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_UDP, simple_plugin_packet_get_exdata, env);
icmp_plugin_id=stellar_packet_plugin_register(st, IPPROTO_ICMP, simple_plugin_packet_get_exdata, env);
icmp6_plugin_id=stellar_packet_plugin_register(st, IPPROTO_ICMPV6, simple_plugin_packet_get_exdata, env);
if(tcp_plugin_id < 0 || udp_plugin_id < 0 || icmp_plugin_id < 0 || icmp6_plugin_id < 0)
{
perror("register packet plugin get exdata return invalid plugin id\n");
exit(-1);
}
stellar_packet_mq_subscribe(st, env->packet_topic_id, simple_plugin_on_packet_msg_cb, tcp_plugin_id);
stellar_packet_mq_subscribe(st, env->packet_topic_id, simple_plugin_on_packet_msg_cb, udp_plugin_id);
stellar_packet_mq_subscribe(st, env->packet_topic_id, simple_plugin_on_packet_msg_cb, icmp_plugin_id);
stellar_packet_mq_subscribe(st, env->packet_topic_id, simple_plugin_on_packet_msg_cb, icmp6_plugin_id);
env->packet_exdata_idx=stellar_packet_exdata_new_index(st, "EXDATA_PACKET_ENV", simple_plugin_packet_exdata_free, env);
int polling_plugin_id=stellar_polling_plugin_register(st, simple_plugin_on_polling, env);
if(polling_plugin_id < 0)
{
perror("register polling plugin return invalid plugin id \n");
exit(-1);
}
env->tcp_stream_topic_id=stellar_session_mq_get_topic_id(st, TOPIC_TCP_STREAM);
env->tcp_topic_id=stellar_session_mq_get_topic_id(st, TOPIC_TCP);
env->udp_topic_id=stellar_session_mq_get_topic_id(st, TOPIC_UDP);
if(env->tcp_topic_id < 0 || env->udp_topic_id < 0 || env->tcp_stream_topic_id < 0)
{
perror("get tcp or udp topic id failed\n");
exit(-1);
}
stellar_session_mq_subscribe(st, env->tcp_stream_topic_id, simple_plugin_on_session_msg, env->session_plugin_id);
stellar_session_mq_subscribe(st, env->tcp_topic_id, simple_plugin_on_session_msg, env->session_plugin_id);
stellar_session_mq_subscribe(st, env->udp_topic_id, simple_plugin_on_session_msg, env->session_plugin_id);
int stat_topic_id=stellar_session_mq_get_topic_id(st, "TOPIC_SESSION_STAT");
if(stat_topic_id < 0)
{
stat_topic_id=stellar_session_mq_create_topic(st, "TOPIC_SESSION_STAT", NULL, NULL);
}
env->stat_topic_id = stat_topic_id;
return env;
}
void simple_session_packet_plugin_exit(void *plugin_env)
{
if(plugin_env)
{
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
printf("(%s):tcp_packet_num:%lld, udp_packet_num:%lld, icmp_packet_num:%lld, icmp6_packet_num:%lld, polling_times:%lld\n", __FUNCTION__, env->tcp_packet_count, env->udp_packet_count, env->icmp_packet_count, env->icmp6_packet_count, env->polling_times);
FREE(plugin_env);
}
return;
}
/*******************************
* simple plugin sub session stat *
*******************************/
static void simple_plugin_sub_session_stat_on_msg(struct session *sess, int topic_id, const void *data, void *plugin_ctx , void *plugin_env)
{
// printf("get message, %d\n", topic_id);
struct simple_stellar_plugin_env *env = (struct simple_stellar_plugin_env *)plugin_env;
if(topic_id == env->egress_topic_id)
{
session_mq_ignore_message(sess, topic_id, env->session_plugin_id);
}
#if 0
if (topic_id == env->stat_topic_id)
{
struct mq_message_stat *stat = (struct mq_message_stat *)data;
struct mq_message_stat *exdata_stat = (struct mq_message_stat *)session_exdata_get(sess, env->session_exdata_idx);
if (memcmp(exdata_stat, stat, sizeof(struct mq_message_stat)) != 0)
{
perror("exdata and mq data not equal\n");
exit(-1);
}
// print_session_stat(sess, stat, env->plugin_id, __FUNCTION__);
session_mq_unignore_message(sess, env->egress_topic_id, env->session_plugin_id);
}
#endif
return;
}
void *simple_plugin_sub_session_stat_init(struct stellar *st)
{
printf("init new plugin, regist\n");
struct simple_stellar_plugin_env *env = CALLOC(struct simple_stellar_plugin_env, 1);
env->st = st;
env->session_exdata_idx = stellar_session_exdata_new_index(st, "EXDATA_SESSION_STAT", NULL, NULL);
int topic_id=stellar_session_mq_get_topic_id(st, "TOPIC_SESSION_STAT");
if(topic_id < 0)
{
topic_id=stellar_session_mq_create_topic(st, "TOPIC_SESSION_STAT", NULL, NULL);
}
env->stat_topic_id = topic_id;
env->session_plugin_id = stellar_session_plugin_register(st,
NULL,
NULL,
env);
stellar_session_mq_subscribe(st, topic_id, simple_plugin_sub_session_stat_on_msg, env->session_plugin_id);
// TEST: subscirbe egress message then ignore
env->egress_topic_id=stellar_session_mq_get_topic_id(st, TOPIC_EGRESS);
if(env->egress_topic_id < 0)
{
perror("get egress topic id failed\n");
exit(-1);
}
stellar_session_mq_subscribe(st, env->egress_topic_id, simple_plugin_sub_session_stat_on_msg, env->session_plugin_id);
return env;
}
void simple_plugin_sub_session_stat_exit(void *plugin_env)
{
if(plugin_env)FREE(plugin_env);
return;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#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 */
/* 注册新数据及自定义函数的接口,能够传参或获取返回值 */
#ifdef __cplusplus
}
#endif

View File

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

View File

@@ -5,19 +5,15 @@ TARGET=libluaplugin.so
# TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST
SRC := lua_plugin_data.c \
lua_plugin_chunk.c \
lua_plugin_cfunc.c \
lua_binding_functions.c \
lua_plugin_binding.c \
lua_plugin_manage.c
SRC := lua_module_manage_internal.c \
lua_binding_cfunc.c \
lua_binding_function.c \
lua_module_manage.c
OBJECTS := lua_plugin_data.o \
lua_plugin_chunk.o \
lua_plugin_cfunc.o \
lua_binding_functions.o \
lua_plugin_binding.o \
lua_plugin_manage.o
OBJECTS := lua_module_manage_internal.o \
lua_binding_cfunc.o \
lua_binding_function.o \
lua_module_manage.o
INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include
CFLAGS = -g -Wextra -Wall -O0 -fPIC
@@ -26,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 $^

View File

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

118
src/lua_binding_cfunc.c Normal file
View File

@@ -0,0 +1,118 @@
#include "lua_module_manage_internal.h"
#include "lua_binding_cfunc.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 = lua_fn_arg_pair_get_lua_mod_mgr(pair);
return lua_module_manager_get_current_thread_state(lua_mod_mgr);
}
void lua_cfunc_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_array = lua_cdata_array_new(2);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_CONTEXT, msg, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_TABLE, NULL, lua_fn_arg_pair_get_arg_ref_id(free_arg));
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(free_arg), param_array, 2, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 2);
lua_context_free((struct lua_context *)msg);
return;
}
void lua_cfunc_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_array = lua_cdata_array_new(3);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_INT, NULL, topic_id);
if (lua_context_check_if_context(msg))
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_CONTEXT, msg, 0);
else
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_POINTER, msg, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 2), DATATYPE_TABLE, NULL, lua_fn_arg_pair_get_arg_ref_id(msg_arg));
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(msg_arg), param_array, 3, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 3);
return;
}
void lua_cfunc_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_array = lua_cdata_array_new(4);
struct lua_context *new_context = lua_context_new(state);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_INT, NULL, topic_id);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_CONTEXT, msg, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 2), DATATYPE_TABLE, 0, lua_fn_arg_pair_get_arg_ref_id(dis_arg));
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 3), DATATYPE_CONTEXT, (void *)new_context, 0);
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(dis_arg), param_array, 4, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 4);
((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_cfunc_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_array = lua_cdata_array_new(3);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_INT, NULL, stage);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_POINTER, pkt, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 2), DATATYPE_TABLE, NULL, lua_fn_arg_pair_get_arg_ref_id(on_stage_callback));
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(on_stage_callback), param_array, 3, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 3);
return;
}
void lua_cfunc_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_array = lua_cdata_array_new(3);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_POINTER, sess, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_POINTER, pkt, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 2), DATATYPE_TABLE, NULL, lua_fn_arg_pair_get_arg_ref_id(sess_callback));
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(sess_callback), param_array, 3, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 3);
return;
}
void lua_cfunc_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_array = lua_cdata_array_new(4);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 0), DATATYPE_POINTER, sess, 0);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 1), DATATYPE_BUFF, (void *)tcp_payload, (int)tcp_payload_len);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 2), DATATYPE_INT, NULL, (int)tcp_payload_len);
lua_cdata_data_set(lua_cdata_array_get_index(param_array, 3), DATATYPE_TABLE, NULL, lua_fn_arg_pair_get_arg_ref_id(tcp_stream_callback));
lua_state_execute_chunk(state, lua_fn_arg_pair_get_fn_ref_id(tcp_stream_callback), param_array, 4, NULL, 0, NULL, 0);
lua_cdata_array_free(param_array, 4);
return;
}

23
src/lua_binding_cfunc.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "stellar/mq.h"
#include "stellar/packet_manager.h"
#include "stellar/session_manager.h"
void lua_cfunc_mq_msg_free_cb_func(void *msg, void *msg_free_arg);
void lua_cfunc_mq_on_msg_cb_func(int topic_id, void *msg, void *on_msg_arg);
void lua_cfunc_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_cfunc_packet_on_stage_callback(enum packet_stage stage, struct packet *pkt, void *args);
void lua_cfunc_session_callback(struct session *sess, struct packet *pkt, void *args);
void lua_cfunc_tcp_stream_callback(struct session *sess, const char *tcp_payload, uint32_t tcp_payload_len, void *args);
#ifdef __cplusplus
}
#endif

471
src/lua_binding_function.c Normal file
View File

@@ -0,0 +1,471 @@
#include "lua_module_manage_internal.h"
#include "lua_binding_function.h"
#include "lua_binding_cfunc.h"
#include "stellar/utils.h"
#include <stdlib.h>
#include <string.h>
#include <utlist.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#define LUA_BINDING_FUNCTION_GET_VALUE_POINTER(func_name, param_type, value_type, value_func) \
int func_name(struct lua_state *state) \
{ \
lua_State *L = (lua_State *)(state); \
if (lua_gettop(L) != 1) \
{ \
lua_settop(L, 0); \
return 0; \
} \
param_type *p = (param_type *)lua_topointer(L, -1); \
lua_settop(L, 0); \
value_type *l = (value_type *)value_func(p); \
lua_pushlightuserdata(L, (void *)l); \
return 1; \
}
#define LUA_BINDING_FUNCTION_GET_VALUE_INT(func_name, param_type, value_func) \
int func_name(struct lua_state *state) \
{ \
lua_State *L = (lua_State *)(state); \
if (lua_gettop(L) != 1) \
{ \
lua_settop(L, 0); \
return 0; \
} \
param_type *p = (param_type *)lua_topointer(L, -1); \
lua_settop(L, 0); \
int v = (int)value_func(p); \
lua_pushinteger(L, v); \
return 1; \
}
int lua_get_lua_module_manager(struct lua_state *state)
{
lua_State *L = (lua_State *)(state);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
lua_pushlightuserdata(L, (void *)lua_mod_mgr);
return 1;
}
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_stellar_module_manager,
struct lua_module_manager,
struct stellar_module_manager,
lua_module_manager_get_stellar_module_manager)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_mq_schema,
struct lua_module_manager,
struct mq_schema,
lua_module_manager_get_mq_schema)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_mq_runtime,
struct lua_module_manager,
struct mq_runtime,
lua_module_manager_get_mq_runtime)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_logger,
struct lua_module_manager,
struct logger,
lua_module_manager_get_logger)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_packet_manager,
struct lua_module_manager,
struct packet_manager,
lua_module_manager_get_packet_manager)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_get_session_manager,
struct lua_module_manager,
struct session_manager,
lua_module_manager_get_session_manager)
LUA_BINDING_FUNCTION_GET_VALUE_INT(lua_get_current_thread_id,
struct lua_module_manager,
lua_module_manager_get_current_thread_id)
LUA_BINDING_FUNCTION_GET_VALUE_INT(lua_get_max_thread_num,
struct lua_module_manager,
lua_module_manager_get_max_thread_num)
int lua_mq_schema_get_topic_id(struct lua_state *state)
{
lua_State *L = (lua_State *)(state);
if (lua_gettop(L) != 2 || lua_type(L, -1) != LUA_TSTRING || lua_type(L, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
char *topic_name = strdup(lua_tostring(L, -1));
lua_pop(L, 1);
struct mq_schema *s = (struct mq_schema *)lua_topointer(L, -1);
lua_settop(L, 0);
int topic_id = mq_schema_get_topic_id(s, (const char *)topic_name);
if (topic_name)
FREE(topic_name);
lua_pushinteger(L, topic_id);
return 1;
}
int lua_mq_schema_create_topic(struct lua_state *state)
{
lua_State *L = (lua_State *)(state);
if (lua_gettop(L) != 6 || lua_type(L, -5) != LUA_TSTRING || lua_type(L, -6) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int free_cb_fn_ref_id = -1;
if (lua_type(L, -1) == LUA_TFUNCTION)
free_cb_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
int on_dispatch_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_dispatch_cb_fn_ref_id = -1;
if (lua_type(L, -1) == LUA_TFUNCTION)
on_dispatch_cb_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
char *topic_name = strdup((char *)lua_tostring(L, -1));
lua_pop(L, 1);
struct mq_schema *s = (struct mq_schema *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_mq_dispatch_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_dispatch_cb_fn_ref_id, on_dispatch_arg_ref_id);
struct lua_fn_arg_pair *new_mq_msg_free_arg = lua_fn_arg_pair_new(lua_mod_mgr, free_cb_fn_ref_id, free_arg_ref_id);
int topic_id = mq_schema_create_topic(s,
(const char *)topic_name,
lua_cfunc_mq_on_msg_dispatch_cb_func,
new_mq_dispatch_arg,
lua_cfunc_mq_msg_free_cb_func,
new_mq_msg_free_arg);
if (topic_id >= 0)
{
lua_fn_arg_pair_insert(new_mq_dispatch_arg);
lua_fn_arg_pair_insert(new_mq_msg_free_arg);
}
else
{
if (free_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, free_arg_ref_id);
if (free_cb_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, free_cb_fn_ref_id);
if (on_dispatch_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_dispatch_arg_ref_id);
if (on_dispatch_cb_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_dispatch_cb_fn_ref_id);
lua_fn_arg_pair_free(new_mq_dispatch_arg);
lua_fn_arg_pair_free(new_mq_msg_free_arg);
}
lua_pushinteger(L, topic_id);
return 1;
}
int lua_mq_schema_update_topic(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 6 || lua_type(L, -5) != LUA_TNUMBER || lua_type(L, -6) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int free_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int free_cb_fn_ref_id = -1;
if (lua_type(L, -1) == LUA_TFUNCTION)
free_cb_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
int on_dispatch_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_dispatch_cb_fn_ref_id = -1;
if (lua_type(L, -1) == LUA_TFUNCTION)
on_dispatch_cb_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
else
lua_pop(L, 1);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct mq_schema *s = (struct mq_schema *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_mq_dispatch_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_dispatch_cb_fn_ref_id, on_dispatch_arg_ref_id);
struct lua_fn_arg_pair *new_mq_msg_free_arg = lua_fn_arg_pair_new(lua_mod_mgr, free_cb_fn_ref_id, free_arg_ref_id);
int update_ret = mq_schema_update_topic(s,
topic_id,
lua_cfunc_mq_on_msg_dispatch_cb_func,
new_mq_dispatch_arg,
lua_cfunc_mq_msg_free_cb_func,
new_mq_msg_free_arg);
if (topic_id)
{
if (free_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, free_arg_ref_id);
if (free_cb_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, free_cb_fn_ref_id);
if (on_dispatch_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_dispatch_arg_ref_id);
if (on_dispatch_cb_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_dispatch_cb_fn_ref_id);
lua_fn_arg_pair_free(new_mq_dispatch_arg);
lua_fn_arg_pair_free(new_mq_msg_free_arg);
}
else
{
lua_fn_arg_pair_insert(new_mq_dispatch_arg);
lua_fn_arg_pair_insert(new_mq_msg_free_arg);
}
lua_pushinteger(L, update_ret);
return 1;
}
int lua_mq_shcema_destory_topic(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 2 || lua_type(L, -1) != LUA_TNUMBER || lua_type(L, -2) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct mq_schema *s = (struct mq_schema *)lua_topointer(L, -1);
lua_settop(L, 0);
int destory_ret = mq_schema_destroy_topic(s, topic_id);
lua_pushinteger(L, destory_ret);
return 1;
}
int lua_mq_schema_subscribe(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -2) != LUA_TFUNCTION || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int on_msg_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_msg_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct mq_schema *s = (struct mq_schema *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_mq_on_msg_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_msg_fn_ref_id, on_msg_arg_ref_id);
int subscribe_ret = mq_schema_subscribe(s, topic_id, lua_cfunc_mq_on_msg_cb_func, new_mq_on_msg_arg);
if (subscribe_ret)
{
if (on_msg_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_msg_arg_ref_id);
if (on_msg_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_msg_fn_ref_id);
lua_fn_arg_pair_free(new_mq_on_msg_arg);
}
else
{
lua_fn_arg_pair_insert(new_mq_on_msg_arg);
}
lua_pushinteger(L, subscribe_ret);
return 1;
}
int lua_mq_runtime_publish_message(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 3 || lua_type(L, -2) != LUA_TNUMBER || lua_type(L, -3) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int msg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int topic_id = lua_tointeger(L, -1);
lua_pop(L, 1);
struct mq_runtime *rt = (struct mq_runtime *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_context *new_context = lua_context_new_with_ref_id(state, msg_ref_id);
int publish_ret = mq_runtime_publish_message(rt, topic_id, new_context);
if (publish_ret)
{
lua_context_free(new_context);
}
lua_pushinteger(L, publish_ret);
return 1;
}
LUA_BINDING_FUNCTION_GET_VALUE_INT(lua_packet_get_direction,
const struct packet,
packet_get_direction)
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_packet_get_payload,
const struct packet,
const char,
packet_get_payload)
LUA_BINDING_FUNCTION_GET_VALUE_INT(lua_packet_get_payload_len,
const struct packet,
packet_get_payload_len)
int lua_packet_manager_subscribe(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
if (lua_gettop(L) != 4 || lua_type(L, -2) != LUA_TFUNCTION || lua_type(L, -3) != LUA_TNUMBER || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int on_packet_stage_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_packet_stage_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int stage = lua_tointeger(L, -1);
lua_pop(L, 1);
struct packet_manager *pkt_mgr = (struct packet_manager *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_on_packet_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_packet_stage_fn_ref_id, on_packet_stage_arg_ref_id);
int subscribe_ret = packet_manager_subscribe(pkt_mgr, (enum packet_stage)stage, lua_cfunc_packet_on_stage_callback, new_on_packet_arg);
if (subscribe_ret)
{
if (on_packet_stage_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_packet_stage_arg_ref_id);
if (on_packet_stage_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_packet_stage_fn_ref_id);
lua_fn_arg_pair_free(new_on_packet_arg);
}
else
{
lua_fn_arg_pair_insert(new_on_packet_arg);
}
lua_pushinteger(L, subscribe_ret);
return 1;
}
LUA_BINDING_FUNCTION_GET_VALUE_POINTER(lua_session_get0_current_packet,
const struct session,
const struct packet,
session_get0_current_packet)
enum sess_mgr_sub_type
{
sub_type_begin = 0,
sub_type_tcp,
sub_type_udp,
sub_type_control_pkt,
sub_type_end
};
static int lua_session_manager_subscribe(struct lua_state *state, enum sess_mgr_sub_type type)
{
lua_State *L = (lua_State *)(state);
if (lua_gettop(L) != 3 || lua_type(L, -2) != LUA_TFUNCTION || lua_type(L, -3) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int on_session_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_session_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
struct session_manager *sess_mgr = (struct session_manager *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_on_sess_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_session_fn_ref_id, on_session_arg_ref_id);
int subscribe_ret = -1;
switch (type)
{
case sub_type_tcp:
subscribe_ret = session_manager_subscribe_tcp(sess_mgr, lua_cfunc_session_callback, new_on_sess_arg);
break;
case sub_type_udp:
subscribe_ret = session_manager_subscribe_udp(sess_mgr, lua_cfunc_session_callback, new_on_sess_arg);
break;
case sub_type_control_pkt:
subscribe_ret = session_manager_subscribe_control_packet(sess_mgr, lua_cfunc_session_callback, new_on_sess_arg);
break;
default:
break;
}
if (subscribe_ret)
{
if (on_session_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_session_arg_ref_id);
if (on_session_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_session_fn_ref_id);
lua_fn_arg_pair_free(new_on_sess_arg);
}
else
{
lua_fn_arg_pair_insert(new_on_sess_arg);
}
lua_pushinteger(L, subscribe_ret);
return 1;
}
int lua_session_manager_subscribe_tcp(struct lua_state *state)
{
return lua_session_manager_subscribe(state, sub_type_tcp);
}
int lua_session_manager_subscribe_udp(struct lua_state *state)
{
return lua_session_manager_subscribe(state, sub_type_udp);
}
int lua_session_manager_subscribe_control_packet(struct lua_state *state)
{
return lua_session_manager_subscribe(state, sub_type_control_pkt);
}
int lua_session_manager_subscribe_tcp_stream(struct lua_state *state)
{
lua_State *L = (lua_State *)(state);
if (lua_gettop(L) != 3 || lua_type(L, -2) != LUA_TFUNCTION || lua_type(L, -4) != LUA_TLIGHTUSERDATA)
{
lua_settop(L, 0);
return 0;
}
int on_tcp_stream_arg_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
int on_tcp_stream_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
struct session_manager *sess_mgr = (struct session_manager *)lua_topointer(L, -1);
lua_settop(L, 0);
struct lua_module_manager *lua_mod_mgr = lua_state_get_lua_module_manager(state);
struct lua_fn_arg_pair *new_on_tcp_stream_arg = lua_fn_arg_pair_new(lua_mod_mgr, on_tcp_stream_fn_ref_id, on_tcp_stream_arg_ref_id);
int subscribe_ret = session_manager_subscribe_tcp_stream(sess_mgr, lua_cfunc_tcp_stream_callback, new_on_tcp_stream_arg);
if (subscribe_ret)
{
if (on_tcp_stream_arg_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_tcp_stream_arg_ref_id);
if (on_tcp_stream_fn_ref_id + 1)
luaL_unref(L, LUA_REGISTRYINDEX, on_tcp_stream_fn_ref_id);
lua_fn_arg_pair_free(new_on_tcp_stream_arg);
}
else
{
lua_fn_arg_pair_insert(new_on_tcp_stream_arg);
}
lua_pushinteger(L, subscribe_ret);
return 1;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include "lua_module_manage_internal.h"
int lua_get_lua_module_manager(struct lua_state *state);
int lua_get_stellar_module_manager(struct lua_state *state);
int lua_get_mq_schema(struct lua_state *state);
int lua_get_mq_runtime(struct lua_state *state);
int lua_get_logger(struct lua_state *state);
int lua_get_packet_manager(struct lua_state *state);
int lua_get_session_manager(struct lua_state *state);
int lua_get_current_thread_id(struct lua_state *state);
int lua_get_max_thread_num(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_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);
int lua_packet_manager_subscribe(struct lua_state *state);
int lua_session_get0_current_packet(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);
#ifdef __cplusplus
}
#endif

View File

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

View File

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

95
src/lua_module_manage.c Normal file
View File

@@ -0,0 +1,95 @@
#include "lua_module_manage_internal.h"
#include "lua_binding_function.h"
#include "stellar/utils.h"
#define GLOBAL_BASIC_SPACE_NAME "lua_module_manager_space"
#define MQ_SCHEMA_SPACE_NAME "mq_schema_space"
#define MQ_RUNTIME_SPACE_NAME "mq_runtime_space"
#define MODULE_MANAGER_SPACE_NAME "stellar_module_manager_space"
#define PACKET_SPACE_NAME "packet_space"
#define PACKET_MANAGER_SPACE_NAME "packet_manager_space"
#define SESSION_SPACE_NAME "session_space"
#define SESSION_MANAGER_SPACE_NAME "session_manager_space"
struct lua_state_cbind_func_spec lua_bind_function[] = {
{lua_get_lua_module_manager, GLOBAL_BASIC_SPACE_NAME, "get_lua_module_manager"},
{lua_get_stellar_module_manager, GLOBAL_BASIC_SPACE_NAME, "get_stellar_module_manager"},
{lua_get_mq_schema, GLOBAL_BASIC_SPACE_NAME, "get_mq_schema"},
{lua_get_mq_runtime, GLOBAL_BASIC_SPACE_NAME, "get_mq_runtime"},
{lua_get_logger, GLOBAL_BASIC_SPACE_NAME, "get_logger"},
{lua_get_packet_manager, GLOBAL_BASIC_SPACE_NAME, "get_pacekt_manager"},
{lua_get_session_manager, GLOBAL_BASIC_SPACE_NAME, "get_session_manager"},
{lua_get_current_thread_id, GLOBAL_BASIC_SPACE_NAME, "get_current_thread_id"},
{lua_get_max_thread_num, GLOBAL_BASIC_SPACE_NAME, "get_max_thread_num"},
{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_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_state_cbind_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},
};
struct stellar_module *lua_module_manager_on_init(struct stellar_module_manager *mod_mgr)
{
struct lua_module_manager *new_lua_mod_mgr = lua_module_manager_new(mod_mgr);
if (lua_module_manager_state_create(
new_lua_mod_mgr,
lua_bind_function,
sizeof(lua_bind_function) / sizeof(struct lua_state_cbind_func_spec),
lua_bind_data,
sizeof(lua_bind_data) / sizeof(struct lua_state_cbind_data_spec)))
goto err;
if (lua_module_manager_load_config(new_lua_mod_mgr, LUA_MODULE_MANAGE_CONF_PATH))
goto err;
if (lua_module_manager_call_init(new_lua_mod_mgr))
goto err;
if (lua_module_manager_duplicate_state(new_lua_mod_mgr))
goto err;
struct stellar_module *module = stellar_module_new(LUA_MODULE_MANAGE_MODULE_NAME, (void *)new_lua_mod_mgr);
return module;
err:
lua_module_manager_free(new_lua_mod_mgr);
return NULL;
}
void lua_module_manager_on_exit(struct stellar_module_manager *mod_mgr __unused, struct stellar_module *mod)
{
if (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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,148 @@
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h>
#include "lua_module_manage.h"
#include "stellar/mq.h"
#include "stellar/module_manager.h"
#include "stellar/packet.h"
#include "stellar/packet_manager.h"
#include "stellar/session.h"
#include "stellar/session_manager.h"
enum LUA_MODULE_ERR_CODE
{
/* 函数与全局变量操作错误码 */
CDATA_ERR = -300,
CDATA_SET_VALUE_TYPE_UNSUPPORT, /* 使用了未识别的数据类型 */
CDATA_SET_VALUE_NULL_POINTER,
CDATA_PUSH_STACK_TYPE_UNKNOWN, /* 入栈数据无法识别数据类型 */
CDATA_POP_STACK_TYPE_UNSUPPORT, /* 出栈数据类型不支持出栈 */
/* 状态机基础操作中错误码 */
STATE_ERR = -200,
STATE_BIND_FUNC_NAMESPACE_CONFLICT, /* 命名空间数据类型不符 */
STATE_BIND_FUNC_NAME_CONFLICT, /* 绑定函数的函数名称与已有数据冲突 */
STATE_BIND_DATA_NAMESPACE_CONFLICT, /* 命名空间数据类型不符 */
STATE_BIND_DATA_NAME_CONFLICT, /* 全局变量名称与已有数据冲突 */
STATE_BIND_DATA_TYPE_ERR, /* 数据类型无法识别或存在异常 */
STATE_COPY_REF_VALUE_ERR, /* 在状态机之间拷贝数据过程中数据拷贝出现异常 */
STATE_COPY_REF_VALUE_CONFLICT, /* 在状态机之间拷贝数据过程中出现引用ID不匹配的情况 */
STATE_CHUNK_REF_ID_NOT_FUNCTION, /* 传入的ref_id获取值之后不是函数类型 */
STATE_CHUNK_DATA_PUSH_ERR, /* 参数入栈过程中异常 */
STATE_CHUNK_DATA_POP_ERR, /* 返回值出栈过程中异常 */
STATE_CHUNK_RUNNING_ERR, /* CHUNK在调用pcall执行过程中运行错误 */
/* lua module manager错误码 */
LUA_MOD_MGR_ERR = -100,
LMM_STATE_THREAD_NUM_ERR, /* 获取最大线程数量时结果为负数 */
LMM_STATE_CREATE_ERR, /* lua_State创建失败 */
LMM_LOAD_CONFIG_FILE_NOT_EXIST, /* 读取配置时配置文件不存在 */
LMM_LOAD_CONFIG_FILE_OPEN_ERR, /* 配置文件无法打开 */
LMM_LOAD_CONFIG_FILE_TOML_PARSE_ERR, /* 配置文件通过toml解析失败 */
LMM_LOAD_SCRIPT_FILE_OPEN_ERR, /* 加载配置过程中lua无法打开文件 */
LMM_LOAD_SCRIPT_FUNC_TYPE_ERR, /* lua获取得到的变量类型不是函数,无法完成初始化 */
/* 通用返回值 */
PARAM_ERR = -1, /* 传入参数错误, 可能是指针为空或类型不符合 */
SUCCESS = 0, /* 运行成功 */
};
struct lua_state;
struct lua_module_manager;
/* ***** ***** ***** ***** ***** ***** */
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);
/* ***** ***** ***** ***** ***** ***** */
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
};
struct lua_cdata;
struct lua_cdata *lua_cdata_new(void);
void lua_cdata_free(struct lua_cdata *cdata);
struct lua_cdata *lua_cdata_array_new(size_t cdata_num);
void lua_cdata_array_free(struct lua_cdata *cdata_array, size_t data_num);
struct lua_cdata *lua_cdata_array_get_index(struct lua_cdata *data_array, size_t index);
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);
/* ***** ***** ***** ***** ***** ***** */
struct lua_fn_arg_pair;
struct lua_fn_arg_pair *lua_fn_arg_pair_new(struct lua_module_manager *lua_mod_mgr, int fn_ref_id, int arg_ref_id);
void lua_fn_arg_pair_free(struct lua_fn_arg_pair *pair);
void lua_fn_arg_pair_insert(struct lua_fn_arg_pair *pair);
int lua_fn_arg_pair_get_fn_ref_id(struct lua_fn_arg_pair *pair);
int lua_fn_arg_pair_get_arg_ref_id(struct lua_fn_arg_pair *pair);
struct lua_module_manager *lua_fn_arg_pair_get_lua_mod_mgr(struct lua_fn_arg_pair *pair);
/* ***** ***** ***** ***** ***** ***** */
typedef int (*lua_cbind_func)(struct lua_state *state);
struct lua_state_cbind_func_spec
{
lua_cbind_func func; /* 注册函数原型 */
char *func_name; /* 注册至lua中的函数名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
struct lua_state_cbind_data_spec
{
enum LUA_DATATYPE data_type; /* 注册的数据类型 */
char *data_value; /* 注册数数据值 */
char *data_name; /* 注册的数据名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
/* ***** ***** ***** ***** ***** ***** */
struct lua_state *lua_state_new(struct lua_module_manager *lua_mod_mgr);
void lua_state_free(struct lua_state *state);
int lua_state_cbinding_function(struct lua_state *state, struct lua_state_cbind_func_spec *bind_func_array, size_t bind_func_num);
int lua_state_cbinding_data(struct lua_state *state, struct lua_state_cbind_data_spec *bind_data_array, size_t bind_data_num);
int lua_state_copy_ref_value(struct lua_state *to, struct lua_state *from);
int lua_state_execute_chunk(struct lua_state *state, int chunk_ref_id, struct lua_cdata *param_array, size_t param_num, struct lua_cdata *return_array, size_t return_num, char *err_log, size_t err_log_len);
struct lua_module_manager *lua_state_get_lua_module_manager(struct lua_state *state);
/* ***** ***** ***** ***** ***** ***** */
struct lua_module_manager *lua_module_manager_new(struct stellar_module_manager *mod_mgr);
void lua_module_manager_free(struct lua_module_manager *lua_mod_mgr);
int lua_module_manager_state_create(struct lua_module_manager *lua_mod_mgr, struct lua_state_cbind_func_spec *bind_func_array, size_t bind_func_num, struct lua_state_cbind_data_spec *bind_data_array, size_t bind_data_num);
int lua_module_manager_load_config(struct lua_module_manager *lua_mod_mgr, const char *conf_file_path);
int lua_module_manager_call_init(struct lua_module_manager *lua_mod_mgr);
int lua_module_manager_duplicate_state(struct lua_module_manager *lua_mod_mgr);
void lua_module_manger_pair_list_insert(struct lua_module_manager *lua_mod_mgr, struct lua_fn_arg_pair *pair);
int lua_module_manager_call_exit(struct lua_module_manager *lua_mod_mgr);
struct stellar_module_manager *lua_module_manager_get_stellar_module_manager(struct lua_module_manager *lua_mod_mgr);
struct mq_schema *lua_module_manager_get_mq_schema(struct lua_module_manager *lua_mod_mgr);
struct mq_runtime *lua_module_manager_get_mq_runtime(struct lua_module_manager *lua_mod_mgr);
struct logger *lua_module_manager_get_logger(struct lua_module_manager *lua_mod_mgr);
struct packet_manager *lua_module_manager_get_packet_manager(struct lua_module_manager *lua_mod_mgr);
struct session_manager *lua_module_manager_get_session_manager(struct lua_module_manager *lua_mod_mgr);
int lua_module_manager_get_current_thread_id(struct lua_module_manager *lua_mod_mgr);
struct lua_state *lua_module_manager_get_current_thread_state(struct lua_module_manager *lua_mod_mgr);
int lua_module_manager_get_max_thread_num(struct lua_module_manager *lua_mod_mgr);
#ifdef __cplusplus
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,630 +0,0 @@
/*************************************************************************
> File Name: lua_plugin_manage.c
> Author:
> Created Time: 2024-08
> Encoding : UTF-8
************************************************************************/
/*************************************************************************
* version
* [ v0.1 ]
* 08-05
* 1. 实现函数
* void specific_instance_copy;
* void specific_instance_destory;
* int script_instance_init_byname;
* int script_instance_init_byrefid;
* void script_instance_clean;
* int script_execute; (暂未实现)
* int session_plugin_instance_init;
* void session_plugin_instance_destory;
* int plugin_env_instance_init;
* void plugin_env_instance_destory;
* int thread_state_instance_init;
* void thread_state_instance_destory;
* int thread_state_instance_load;
* int lua_plugin_manage_config_load;
* int lua_plugin_manage_thread_load;
*
* 08-06
* 1. 实现函数
* int script_execute;
*
* 08-13
* 1. 修改部分创建列表使用的结构
* 2. 实现函数
* struct lua_plugin * search_plugin_by_id
* struct lua_message_mq * search_message_mq_by_id
************************************************************************/
#include "lua_plugin_manage_internal.h"
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
struct lua_plugin_manage_schema *global_schema = NULL;
#if 0
void lua_message_mq_destory(void * elt)
{
if (!elt) return;
struct lua_message_mq * mq = (struct lua_message_mq *)elt;
if ( mq->topic_name )
free(mq->topic_name);
return;
}
#endif
static UT_icd lua_message_mq_icd = {sizeof(struct lua_message_mq), NULL, NULL, NULL};
void lua_plugin_destory(void *elt)
{
if (!elt)
return;
struct lua_plugin *plugin = (struct lua_plugin *)elt;
if (plugin->sub_topic_array)
utarray_free(plugin->sub_topic_array);
return;
}
static UT_icd lua_plugin_icd = {sizeof(struct lua_plugin), NULL, NULL, lua_plugin_destory};
/*
* Function: search_plugin_by_id
* Input: | int | plugin_id | 需要查找plugin数据的id
* Output:
* Return: 查找得到的plugin结构
* Description: 在global schema中根据plugin_id查找一个plugin
*/
struct lua_plugin *search_plugin_by_id(int plugin_id)
{
for (int i = 0; i < global_schema->model_count; ++i)
{
struct lua_model *model = global_schema->model[i];
struct lua_plugin *plugin = NULL;
while ((plugin = utarray_next(model->plugin_array, plugin)))
{
if (plugin->plugin_id == plugin_id)
return plugin;
else if (plugin->plugin_id > plugin_id)
return NULL;
}
}
return NULL;
}
/*
* Function: search_message_mq_by_id
* Input: | int | topic_id | 需要查找的topic_id
* Output:
* Return: 查找得到的message_mq结构
* Description: 在global schema中根据topic_id查找一个message_mq
*/
struct lua_message_mq *search_message_mq_by_id(int topic_id)
{
struct lua_message_mq *mq = NULL;
while ((mq = utarray_next(global_schema->message_mq_array, mq)))
{
if (mq->topic_id == topic_id)
return mq;
}
return NULL;
}
/*
* Function: thread_state_init
* Input: | int | thread_id | 创建状态机的线程号
* Output:
* Return: 创建完成的状态机实例指针
* Description: 创建一个lua的状态机实例, 在每个线程中创建一个
*/
lua_State *thread_state_init(int thread_id)
{
lua_State *new_state = luaL_newstate();
if (__glibc_unlikely(!new_state))
return NULL;
luaL_openlibs(new_state);
/* 绑定所有注册函数 */
lua_cbinding_functions(new_state);
/* 绑定所有全局变量 */
lua_cbinding_datas(new_state);
lua_pushinteger(new_state, thread_id);
lua_setglobal(new_state, LUA_STATE_THREAD_ID_KEY);
lua_settop(new_state, 0);
return new_state;
}
/*
* Function: thread_state_load_specific
* Input: | lua_State * | state | 进行初始化的状态机
* | struct lua_model * | model | 需要加载的模块, 模块数量与具体配置实例的数量一致
* | struct lua_config_specific * | specific | 加载的配置
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 在状态机中加载一个具体配置, 并将加载完成后生成的引用值保存在model中, 加载过程中会使用model进行校验
*/
int thread_state_load_specific(
lua_State *state,
struct lua_model *model,
struct lua_config_specific *specific)
{
if (__glibc_unlikely(!state || !model || !specific))
return PARAM_ERR;
if (__glibc_unlikely(!specific->config_specific_file || !specific->config_specific_load_func || !specific->config_specific_unload_func))
return PARAM_ERR;
/* 加载lua文件 */
if (access(specific->config_specific_file, F_OK))
return STATE_LOAD_FILE_ERR;
if (luaL_loadfile(state, specific->config_specific_file))
return STATE_LOAD_FILE_ERR;
if (lua_pcall(state, 0, 0, 0))
{
LOGERROR("load specific failed, file is %s, err is %s", specific->config_specific_file, lua_tostring(state, -1));
lua_settop(state, 0);
return STATE_LOAD_FILE_ERR;
}
lua_settop(state, 0);
/* 创建plugin_env */
lua_newtable(state);
int env_ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
if (env_ref_id == LUA_REFNIL)
return STATE_CREATE_ENV_FAIL;
if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->private_env_ref != env_ref_id))
{
LOGERROR("load new model, create plugin env id is not same, %d, %d", model->private_env_ref, env_ref_id);
return STATE_CREATE_ENV_FAIL;
}
/* 加载load函数 */
lua_getglobal(state, specific->config_specific_load_func);
if (lua_type(state, -1) != LUA_TFUNCTION)
{
luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
lua_settop(state, 0);
return STATE_GET_LOAD_FAIL;
}
int load_ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
if (load_ref_id == LUA_REFNIL)
{
luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
lua_settop(state, 0);
return STATE_GET_LOAD_FAIL;
}
if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->load_ref != load_ref_id))
{
LOGERROR("load new model, load ref id is not same, %d, %d", model->load_ref, load_ref_id);
return STATE_GET_LOAD_FAIL;
}
/* 加载unload函数 */
lua_getglobal(state, specific->config_specific_unload_func);
if (lua_type(state, -1) != LUA_TFUNCTION)
{
luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
luaL_unref(state, LUA_REGISTRYINDEX, load_ref_id);
lua_settop(state, 0);
return STATE_GET_UNLOAD_FAIL;
}
int unload_ref_id = luaL_ref(state, LUA_REGISTRYINDEX);
if (unload_ref_id == LUA_REFNIL)
{
luaL_unref(state, LUA_REGISTRYINDEX, env_ref_id);
luaL_unref(state, LUA_REGISTRYINDEX, load_ref_id);
lua_settop(state, 0);
return STATE_GET_UNLOAD_FAIL;
}
if ((model->model_mark & MODEL_MARK_INIT_DONE) && (model->unload_ref != unload_ref_id))
{
LOGERROR("load new model, unload ref id is not same, %d, %d", model->unload_ref, unload_ref_id);
return STATE_GET_UNLOAD_FAIL;
}
/* 首次加载时完成model初始化 */
if (!(model->model_mark & MODEL_MARK_INIT_DONE))
{
model->private_env_ref = env_ref_id;
model->load_ref = load_ref_id;
model->unload_ref = unload_ref_id;
model->model_mark |= MODEL_MARK_INIT_DONE;
}
lua_settop(state, 0);
return SUCCESS;
}
/*
* Function: thread_state_call_load
* Input: | lua_State * | state | 进行模块加载的状态机
* | struct lua_model * | model | 需要进行加载的lua模块
* | struct lua_config_specific * | specific | 加载模块的配置信息
* | struct stellar * | st | 与C插件管理保持一致, stellar作为参数传入
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 在状态机中调用一个模块的load函数, 在状态机中完成该模块的加载
*/
int thread_state_call_load(
lua_State *state,
struct lua_model *model,
struct lua_config_specific *specific,
struct stellar *st)
{
if (__glibc_unlikely(!state || !model || !specific || !st))
return PARAM_ERR;
if ((!(model->model_mark & MODEL_MARK_LOAD_DONE)) && (!model->plugin_array))
{
utarray_new(model->plugin_array, &lua_plugin_icd);
model->model_mark |= MODEL_MARK_LOAD_DONE;
}
lua_rawgeti(state, LUA_REGISTRYINDEX, model->private_env_ref);
lua_pushlightuserdata(state, model);
/* 在该状态机对应模块的plugin_env中创建该结构对应的指针 */
lua_setfield(state, -2, LUA_PLUGIN_ENV_DEFAULT_KEY);
lua_settop(state, 0);
luaL_loadfile(state, specific->config_specific_file);
lua_pcall(state, 0, 0, 0);
struct lua_cdata params[2];
params[0].cdata_type = DATATYPE_POINTER;
params[0].cdata_pointer = st;
params[1].cdata_type = DATATYPE_TABLE;
params[1].cdata_table = model->private_env_ref;
return lua_chunk_execute(state, model->load_ref, 2, params, 0, NULL);
}
/*
* Function: thread_state_call_unload
* Input: | lua_State * | 卸载模块的状态机
* | struct lua_model * | 需要卸载的模块
* Output:
* Return: enum LUA_PLUGIN_RETURN
* Description: 在一个状态机中对某模块调用其卸载unload函数
*/
int thread_state_call_unload(
lua_State *state,
struct lua_model *model)
{
if (__glibc_unlikely(!state || !model))
return PARAM_ERR;
struct lua_cdata param;
param.cdata_type = DATATYPE_TABLE;
param.cdata_table = model->private_env_ref;
return lua_chunk_execute(state, model->unload_ref, 1, &param, 0, NULL);
}
/*
* Function:
* Input:
* Output:
* Return:
* Description:
*/
struct lua_plugin_manage_schema *lua_plugin_manage_init(
struct stellar *st,
int specific_count,
struct lua_config_specific *specific)
{
if (__glibc_unlikely(!st))
return NULL;
if (__glibc_unlikely((specific_count && !specific) || (specific_count < 0)))
return NULL;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("get specific count is %d", specific_count);
#endif
struct lua_plugin_manage_schema *new_schema = (struct lua_plugin_manage_schema *)calloc(1, sizeof(struct lua_plugin_manage_schema));
if (__glibc_unlikely(!new_schema))
return NULL;
memset(new_schema, 0, sizeof(struct lua_plugin_manage_schema));
global_schema = new_schema;
new_schema->st = st;
/* 可能运行过程中创建新的topic, 此处进行初始化 */
new_schema->mq_count = 0;
utarray_new(new_schema->message_mq_array, &lua_message_mq_icd);
int thread_count = stellar_get_worker_thread_num(st);
if (thread_count == 0)
/* 无活动线程 */
return new_schema;
#ifdef LUAPLUGIN_BASIC_UNITTEST
LOGDEBUG("get stellar thread num is %d", thread_count);
#endif
new_schema->state_count = thread_count;
/* 为后续待创建的lua_State预分配内存 */
new_schema->thread_state = (lua_State **)calloc(thread_count, sizeof(lua_State *));
if (__glibc_unlikely(!new_schema->thread_state))
{
lua_plugin_manage_exit(new_schema);
return NULL;
}
memset(new_schema->thread_state, 0, thread_count * sizeof(lua_State *));
/* 为将要加载的模块预分配内存 */
new_schema->model_count = specific_count;
/* 如果没有配置, 也应该算是创建成功 */
if (specific_count == 0)
return new_schema;
new_schema->model = (struct lua_model **)calloc(specific_count, sizeof(struct lua_model *));
if (__glibc_unlikely(!new_schema->model))
{
lua_plugin_manage_exit(new_schema);
return NULL;
}
memset(new_schema->model, 0, specific_count * sizeof(struct lua_model *));
/* 依次初始化每个状态机 */
for (int thread_index = 0; thread_index < thread_count; ++thread_index)
{
/* 创建状态机 */
new_schema->thread_state[thread_index] = thread_state_init(thread_index);
if (__glibc_unlikely(!new_schema->thread_state[thread_index]))
{
lua_plugin_manage_exit(new_schema);
return NULL;
}
for (int spec_index = 0; spec_index < specific_count; ++spec_index)
{
/* BugFix: 由于追加model的函数, 拷贝动作可能导致model指针与注册至pluginmanage的指针不一致 */
new_schema->model[spec_index] = (struct lua_model *)calloc(1, sizeof(struct lua_model));
if (__glibc_unlikely(!new_schema->model[spec_index]))
{
lua_plugin_manage_exit(new_schema);
return NULL;
}
/* 在状态机中加载specific中的配置 */
int load_ret = thread_state_load_specific(new_schema->thread_state[thread_index],
new_schema->model[spec_index],
&specific[spec_index]);
if (load_ret)
{
LOGERROR("state load specific failed, ret is %d", load_ret);
lua_plugin_manage_exit(new_schema);
return NULL;
}
/* 调用该模块中的load函数 */
int call_load_ret = thread_state_call_load(new_schema->thread_state[thread_index],
new_schema->model[spec_index],
&specific[spec_index],
st);
if (call_load_ret)
{
LOGERROR("call state load function failed, ret is %d", call_load_ret);
lua_plugin_manage_exit(new_schema);
return NULL;
}
}
}
#ifdef LUAPLUGIN_BASIC_UNITTEST
debug_lua_plugin_manage_schema(new_schema);
#endif
/* 初始化全局状态统计 */
global_plugin_statistics = (struct lua_plugin_statistics *)calloc((thread_count * global_max_plugin_id), sizeof(struct lua_plugin_statistics));
if (!global_plugin_statistics)
{
LOGERROR("create plugin statistics failed");
lua_plugin_manage_exit(new_schema);
return NULL;
}
return new_schema;
}
/*
* Function:
* Input:
* Output:
* Return:
* Description:
*/
int lua_plugin_manage_load_one_specific(
struct lua_plugin_manage_schema *schema,
struct lua_config_specific *specific)
{
if (__glibc_unlikely(!schema || !specific))
return -1;
if (schema->model)
{
schema->model = (struct lua_model **)realloc(schema->model, (schema->model_count + 1) * sizeof(struct lua_model *));
schema->model_count += 1;
}
/* BugFix: 在某些情况下, 该内存未初始化会导致加载失败 */
memset(&schema->model[schema->model_count - 1], 0, sizeof(struct lua_model *));
schema->model[schema->model_count - 1] = (struct lua_model *)calloc(1, sizeof(struct lua_model));
if (__glibc_unlikely(!schema->model[schema->model_count - 1]))
{
LOGERROR("calloc for new model failed\n");
return -1;
}
for (int thread_index = 0; thread_index < schema->state_count; ++thread_index)
{
/* 在状态机中加载specific中的配置 */
int load_ret = thread_state_load_specific(schema->thread_state[thread_index],
schema->model[schema->model_count - 1],
specific);
if (load_ret)
{
LOGERROR("state load specific failed, ret is %d", load_ret);
return -1;
}
/* 调用该模块中的load函数 */
int call_load_ret = thread_state_call_load(schema->thread_state[thread_index],
schema->model[schema->model_count - 1],
specific,
schema->st);
if (call_load_ret)
{
LOGERROR("call state load function failed, ret is %d", call_load_ret);
return -1;
}
}
if (global_plugin_statistics)
free(global_plugin_statistics);
/* 初始化全局状态统计 */
global_plugin_statistics = (struct lua_plugin_statistics *)calloc((schema->state_count * global_max_plugin_id), sizeof(struct lua_plugin_statistics));
if (!global_plugin_statistics)
{
LOGERROR("create plugin statistics failed");
return -1;
}
#ifdef LUAPLUGIN_BASIC_UNITTEST
debug_lua_plugin_manage_schema(schema);
#endif
return 0;
}
/*
* Function:
* Input:
* Output:
* Return:
* Description:
*/
void lua_plugin_manage_exit(struct lua_plugin_manage_schema *lua_plug_mgr)
{
if (__glibc_unlikely(!lua_plug_mgr))
return;
/* 释放所有的状态机 */
for (int state_index = 0; state_index < lua_plug_mgr->state_count; ++state_index)
{
for (int model_index = 0; model_index < lua_plug_mgr->model_count; ++model_index)
{
/* 在状态机中对每一个模块调用对应的卸载函数 */
int call_unload_ret = thread_state_call_unload(lua_plug_mgr->thread_state[state_index],
lua_plug_mgr->model[model_index]);
if (call_unload_ret)
{
LOGERROR("call state unload function failed, ret is %d", call_unload_ret);
}
}
/* 销毁状态机 */
lua_close(lua_plug_mgr->thread_state[state_index]);
}
free(lua_plug_mgr->thread_state);
/* 释放所有加载的模块 */
for (int model_index = 0; model_index < lua_plug_mgr->model_count; ++model_index)
{
utarray_free(lua_plug_mgr->model[model_index]->plugin_array);
free(lua_plug_mgr->model[model_index]);
}
free(lua_plug_mgr->model);
if (lua_plug_mgr->message_mq_array)
utarray_free(lua_plug_mgr->message_mq_array);
free(lua_plug_mgr);
return;
}
/*
* Function:
* Input:
* Output:
* Return:
* Description: 获取某插件的运行成功及失败次数
*/
void lua_plugin_get_statistics(int plugin_id, int thread_id, int *new_success, int *new_fail, int *free_success, int *free_fail)
{
int statistic_id = thread_id * global_max_plugin_id + plugin_id;
if (new_success)
*new_success = global_plugin_statistics[statistic_id].new_success_count;
if (new_fail)
*new_fail = global_plugin_statistics[statistic_id].new_failed_count;
if (free_success)
*free_success = global_plugin_statistics[statistic_id].free_success_count;
if (free_fail)
*free_fail = global_plugin_statistics[statistic_id].free_failed_count;
return;
}
void debug_lua_plugin_manage_schema(struct lua_plugin_manage_schema *schema)
{
printf("\n***** begin to debug one lua schema *****\n");
printf("schema.st is %p\n", schema->st);
printf("schema state count is %d\n", schema->state_count);
for (int i = 0; i < schema->state_count; ++i)
{
printf("schema state[%d]pointer is %p\n", i, schema->thread_state[i]);
}
printf("schema model count is %d\n", schema->model_count);
for (int i = 0; i < schema->model_count; ++i)
{
printf("debug model[%d] %p\n", i, &schema->model[i]);
printf("array %p, load %d, unload %d, env %d, mark %04x, count %d\n",
schema->model[i]->plugin_array, schema->model[i]->load_ref, schema->model[i]->unload_ref,
schema->model[i]->private_env_ref, schema->model[i]->model_mark, schema->model[i]->plugin_count);
struct lua_plugin *plugin = NULL;
while ((plugin = utarray_next(schema->model[i]->plugin_array, plugin)))
{
printf("%d, %d, %d\n", plugin->plugin_id, plugin->ctx_new_ref, plugin->ctx_free_ref);
}
}
printf("schema total plugin count is %d\n", schema->plugin_count);
printf("***** end of debug one lua schema *****\n\n");
}
#ifdef LUAPLUGIN_BASIC_UNITTEST
void debug_lua_state_stack(lua_State *state, int mod, const char *message)
{
int stackcount = lua_gettop(state);
/* nothing in stack */
if (!stackcount)
{
printf("debug stack, but stack is empty");
return;
}
printf("\n***** begin to debug one lua stack *****\n");
if (message)
printf("debug here: %s\n", message);
int i = stackcount;
/* print variables one by one */
for (; i > 0; --i)
{
/* adjust variables according to mod */
if (mod)
i = 0 - i;
int type = lua_type(state, i);
printf("stack[%d]: ", i);
switch (type)
{
case LUA_TBOOLEAN:
printf(lua_toboolean(state, i) ? "true\n" : "false\n");
break;
case LUA_TNUMBER:
printf("%g\n", lua_tonumber(state, i));
break;
case LUA_TSTRING:
printf("%s\n", lua_tostring(state, i));
break;
default:
printf("this is not normal type, type is: %d[%s]\n", type, lua_typename(state, type));
break;
}
/* adjust variables according to mod */
if (mod)
i = 0 - i;
}
printf("***** end of debug one lua stack *****\n\n");
}
#endif

View File

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

24
test_on_stellar/Makefile Normal file
View File

@@ -0,0 +1,24 @@
TOPDIR = ./..
CC=gcc
MAKE=make
TARGET=lua_plugin_manage_example.so
EXAMPLE_FLAG = -DLUAPLUGIN_EXAMPLE
SRC := plugin_manage_on_stellar.c
OBJECTS := plugin_manage_on_stellar.o
INCLUDE = -I$(TOPDIR)/output/include -I$(TOPDIR)/dependence/include
CFLAGS = -g -Wextra -Wall -O0 -fPIC
# CFLAGS += -pedantic -fsanitize=address
# LDLIBS = -L$(TOPDIR)/output/lib -llua -ldl -lm
LDLIBS += -L$(TOPDIR)/output/libs -lluaplugin -L$(TOPDIR)/dependence/lib -ltoml
all:$(OBJECTS)
$(CC) $(CFLAGS) -shared -o $(TARGET) $(OBJECTS) $(LDLIBS)
$(OBJECTS):$(SRC)
$(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SRC) -c $^
clean:
rm -rf $(OBJECTS) $(TARGET)

View File

@@ -0,0 +1,101 @@
#include "stellar/stellar.h"
#include "stellar/utils.h"
#include "lua_plugin_manage.h"
#include <toml.h>
#include <unistd.h>
#include <stdlib.h>
#define LUA_PLUGIN_CONF_PATH "/opt/tsg/sapp/lua_manage/lua_plugin_manage.toml"
static struct lua_config_spec *config_load(const char *config_file_name, int *specific_num);
static void debug_plugin_manage_specific(struct lua_config_spec *specific, int num);
void *lua_plugin_manage_on_load(struct stellar *st __unused)
{
int num = 0;
struct lua_config_spec *specific = config_load(LUA_PLUGIN_CONF_PATH, &num);
debug_plugin_manage_specific(specific, num);
// struct lua_plugin_manage *lua_schema = NULL;
struct lua_plugin_manage *lua_schema = lua_plugin_manage_init(st, specific, num);
if (specific)
free(specific);
return (void *)lua_schema;
}
void lua_plugin_manage_on_unload(void *plugin_env __unused)
{
if (plugin_env)
lua_plugin_manage_exit((struct lua_plugin_manage *)plugin_env);
return;
}
static struct lua_config_spec *config_load(const char *config_file_name, int *specific_count)
{
if (!config_file_name)
return NULL;
int specific_num = 0;
char errbuff[256] = {0};
if (access(config_file_name, F_OK))
{
printf("file access falied, filename is %s\n", config_file_name);
return NULL;
}
FILE *fp = fopen(config_file_name, "r");
if (!fp)
return NULL;
toml_table_t *conf = toml_parse_file(fp, errbuff, sizeof(errbuff));
if (fp)
fclose(fp);
if (!conf)
{
printf("parse config file failed, filename %s, err %s\n", config_file_name, errbuff);
return NULL;
}
toml_array_t *plugin_array = toml_array_in(conf, "plugin");
if (!plugin_array)
return NULL;
specific_num = toml_array_nelem(plugin_array);
struct lua_config_spec *new_spec = (struct lua_config_spec *)calloc(specific_num, sizeof(struct lua_config_spec));
if (!new_spec)
return NULL;
struct lua_config_spec *specific = NULL;
for (int i = 0; i < specific_num; ++i)
{
toml_table_t *plugin = toml_table_at(plugin_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");
specific = &new_spec[i];
if (toml_rtos(raw_filepath, &specific->spec_file_path) ||
toml_rtos(raw_load_func_name, &specific->spec_load_func_name) ||
toml_rtos(raw_unload_func_name, &specific->spec_unload_func_name))
{
toml_free(conf);
free(specific);
return NULL;
}
}
*specific_count = specific_num;
return new_spec;
}
static void debug_plugin_manage_specific(struct lua_config_spec *specific, int num)
{
printf("***** ***** ***** ***** ***** *****\n");
printf("load config specifics count is %d\n", num);
for (int i = 0; i < num; ++i)
{
printf("[%d]file path: %s\n", i, specific[i].spec_file_path);
printf("[%d]load func: %s\n", i, specific[i].spec_load_func_name);
printf("[%d]unload func: %s\n", i, specific[i].spec_unload_func_name);
}
printf("***** ***** ***** ***** ***** *****\n\n");
}