5 Commits
dev ... dev-2.0

54 changed files with 2909 additions and 3604 deletions

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 */

Binary file not shown.

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,18 +0,0 @@
#pragma once
#include "stellar/stellar.h"
#include <stddef.h>
struct lua_config_spec
{
char *spec_file_path; /* 插件需要使用的文件名 */
char *spec_load_func_name; /* 加载插件需要调用的函数名称 */
char *spec_unload_func_name; /* 卸载插件需要调用的函数名称 */
};
struct lua_plugin_manage;
struct lua_plugin_manage *lua_plugin_manage_init(struct stellar *st, struct lua_config_spec specifics[], size_t specific_num);
void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr);
// void debug_lua_plugin_manage_schema(struct lua_plugin_manage *schema);

View File

@@ -5,13 +5,15 @@ TARGET=libluaplugin.so
# TEST_FLAG = -DLUAPLUGIN_BASIC_UNITTEST
SRC := lua_plugin_cfunc.c \
SRC := lua_module_manage_internal.c \
lua_binding_cfunc.c \
lua_binding_function.c \
lua_plugin_manage.c
lua_module_manage.c
OBJECTS := lua_plugin_cfunc.o \
OBJECTS := lua_module_manage_internal.o \
lua_binding_cfunc.o \
lua_binding_function.o \
lua_plugin_manage.o
lua_module_manage.o
INCLUDE = -I$(TOPDIR)/dependence/include -I$(TOPDIR)/include
CFLAGS = -g -Wextra -Wall -O0 -fPIC
@@ -20,8 +22,8 @@ LDLIBS = -L$(TOPDIR)/dependence/lib -llua -ltoml -lplugin_manager -ldl -lm
all:$(OBJECTS)
$(CC) $(CFLAGS) -shared -o $(TARGET) $(OBJECTS) $(LDLIBS)
mkdir -p $(TOPDIR)/output/libs
cp -f $(TARGET) $(TOPDIR)/output/libs
# mkdir -p $(TOPDIR)/output/libs
# cp -f $(TARGET) $(TOPDIR)/output/libs
$(OBJECTS):$(SRC)
$(CC) $(TEST_FLAG) $(INCLUDE) $(CFLAGS) $(SRC) -c $^

Binary file not shown.

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

File diff suppressed because it is too large Load Diff

View File

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

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,201 +0,0 @@
#include "lua_binding_function.h"
void *lpm_ctx_new_func(struct session *sess, void *plugin_env)
{
if (!plugin_env)
return NULL;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = (struct lua_state *)plugin_manage->state_array[thread_id];
struct lua_context *new_context = lua_context_new(state);
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_TABLE;
param[1].table = env->lua_plug_env_ref_id;
param[2].type = DATATYPE_CONTEXT;
param[2].context = new_context;
if (lua_chunk_execute(state, env->lua_ctx_new_fn_ref_id, param, 3, NULL, 0, NULL, 0))
{
lua_context_free(new_context);
return NULL;
}
return (void *)new_context;
}
void lpm_ctx_free_func(struct session *sess, void *sess_ctx, void *plugin_env)
{
if (!plugin_env)
return;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)sess_ctx;
param[2].type = DATATYPE_TABLE;
param[2].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, env->lua_ctx_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)sess_ctx);
return;
}
void lpm_session_message_free_func(struct session *sess, void *msg, void *msg_free_arg)
{
if (!msg_free_arg)
return;
struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg;
struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)msg;
param[2].type = DATATYPE_TABLE;
param[2].table = free_arg->lua_msg_free_arg_ref_id;
lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)msg);
return;
}
void lpm_on_session_msg_func(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_env)
{
if (!plugin_env)
return;
struct lua_session_plugin_env *env = (struct lua_session_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_session_message_hashlist, topic_id, env->session_plugin_id);
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[5] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = sess;
param[1].type = DATATYPE_INT;
param[1].integer = topic_id;
/* 这里是不是有更好的办法 */
struct lua_context *context = (struct lua_context *)msg;
if (context && context->magic_code == context_magic_code)
{
param[2].type = DATATYPE_CONTEXT;
param[2].context = context;
}
else
{
param[2].type = DATATYPE_POINTER;
param[2].pointer = (void *)msg;
}
param[3].type = DATATYPE_CONTEXT;
param[3].context = (struct lua_context *)sess_ctx;
param[4].type = DATATYPE_TABLE;
param[4].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0);
return;
}
void lpm_on_packet_func(struct packet *pkt, unsigned char ip_protocol, void *plugin_env)
{
if (!plugin_env)
return;
struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_INT;
param[1].integer = (int)ip_protocol;
param[2].type = DATATYPE_TABLE;
param[2].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, env->lua_on_packet_fn_ref_id, param, 3, NULL, 0, NULL, 0);
return;
}
void lpm_packet_message_free_func(struct packet *pkt, void *msg, void *msg_free_arg)
{
if (!msg_free_arg)
return;
struct lua_message_free_arg *free_arg = (struct lua_message_free_arg *)msg_free_arg;
struct lua_plugin_manage *plugin_manage = free_arg->plugin_manage;
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[3] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_CONTEXT;
param[1].context = (struct lua_context *)msg;
param[2].type = DATATYPE_TABLE;
param[2].table = free_arg->lua_msg_free_arg_ref_id;
lua_chunk_execute(state, free_arg->lua_msg_free_fn_ref_id, param, 3, NULL, 0, NULL, 0);
lua_context_free((struct lua_context *)msg);
return;
}
void lpm_on_packet_msg_func(struct packet *pkt, int topic_id, const void *msg, void *plugin_env)
{
if (!plugin_env)
return;
struct lua_packet_plugin_env *env = (struct lua_packet_plugin_env *)plugin_env;
struct lua_plugin_manage *plugin_manage = env->plugin_manage;
struct lua_on_message_fn *on_message = hash_find_on_msg_fn(plugin_manage->on_packet_message_hashlist, topic_id, env->packet_plugin_id);
struct stellar *st = plugin_manage->st;
int thread_id = stellar_get_current_thread_id(st);
struct lua_state *state = plugin_manage->state_array[thread_id];
struct lua_cdata param[4] = {0};
param[0].type = DATATYPE_POINTER;
param[0].pointer = pkt;
param[1].type = DATATYPE_INT;
param[1].integer = topic_id;
/* 这里是不是有更好的办法 */
struct lua_context *context = (struct lua_context *)msg;
if (context && context->magic_code == context_magic_code)
{
param[2].type = DATATYPE_CONTEXT;
param[2].context = (struct lua_context *)msg;
}
else
{
param[2].type = DATATYPE_POINTER;
param[2].pointer = (void *)msg;
}
param[3].type = DATATYPE_TABLE;
param[3].table = env->lua_plug_env_ref_id;
lua_chunk_execute(state, on_message->lua_on_msg_fn_ref_id, param, 5, NULL, 0, NULL, 0);
return;
}

View File

@@ -1,931 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utlist.h>
#include <lauxlib.h>
#include <lualib.h>
#include "lua_binding_function.h"
struct lua_bind_function_spec lua_bind_function[] = {
{lua_get_worker_thread_num, "get_worker_thread_num", "stellar"},
{lua_get_current_thread_id, "get_current_thread_id", "stellar"},
{lua_get_stellar_pointer, "get_stellar", "stellar"},
{lua_session_plugin_regist, "register", "session_plugin"},
{lua_packet_plugin_regist, "register", "packet_plugin"},
{lua_session_get_type, "get_type", "session"},
{lua_packet_mq_create_topic, "create_topic", "packet_mq"},
{lua_packet_mq_get_topic_id, "get_topic_id", "packet_mq"},
{lua_packet_mq_update_topic, "update_topic", "packet_mq"},
{lua_packet_mq_destory_topic, "destory_topic", "packet_mq"},
{lua_packet_mq_subscribe_topic, "subscribe_topic", "packet_mq"},
{lua_packet_mq_publish_message, "publish_message", "packet_mq"},
{lua_session_mq_create_topic, "create_topic", "session_mq"},
{lua_session_mq_get_topic_id, "get_topic_id", "session_mq"},
{lua_session_mq_update_topic, "update_topic", "session_mq"},
{lua_session_mq_destory_topic, "destory_topic", "session_mq"},
{lua_session_mq_subscribe_topic, "subscribe_topic", "session_mq"},
{lua_session_mq_topic_is_active, "topic_is_active", "session_mq"},
{lua_session_mq_publish_message, "publish_message", "session_mq"},
{lua_session_mq_ignore_message, "ignore_message", "session_mq"},
{lua_session_mq_unignore_message, "unignore_message", "session_mq"},
{lua_session_get0_current_payload, "get_payload", "session"},
{NULL, NULL, NULL},
};
struct lua_bind_data_spec lua_bind_data[] = {
{DATATYPE_BOOL, "true", "test_data_bool", "plugin_manage"},
{DATATYPE_INT, "1000", "test_data_int", "plugin_manage"},
{DATATYPE_NUM, "100.001", "test_data_double", "plugin_manage"},
{DATATYPE_STRING, "this is a string test", "test_data_string", "plugin_manage"},
{DATATYPE_END, NULL, NULL, NULL},
};
struct lua_state
{
lua_State *state;
};
/* ***** ***** ***** ***** ***** ***** */
/* cbinding */
/* ***** ***** ***** ***** ***** ***** */
static int lua_cbinding_single_function(struct lua_state *state, struct lua_bind_function_spec *function_spec)
{
if (!state || !function_spec || !function_spec->function || !function_spec->func_name)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
if (function_spec->space_name)
{
lua_getglobal(L, function_spec->space_name);
if (lua_type(L, -1) == LUA_TNIL)
{
lua_newtable(L);
lua_setglobal(L, function_spec->space_name);
lua_settop(L, 0);
lua_getglobal(L, function_spec->space_name);
}
else
{
if (lua_type(L, -1) != LUA_TTABLE)
{
lua_settop(L, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
lua_getfield(L, -1, function_spec->func_name);
if (lua_type(L, -1) != LUA_TNIL)
{
lua_settop(L, 0);
return BIND_FUNCTION_TYPE_ERR;
}
lua_pop(L, 1);
}
lua_pushcfunction(L, (lua_CFunction)function_spec->function);
lua_setfield(L, -2, function_spec->func_name);
}
else
{
lua_getglobal(L, function_spec->func_name);
if (lua_type(L, -1) != LUA_TNIL)
{
lua_settop(L, 0);
return BIND_FUNCTION_TYPE_ERR;
}
lua_pop(L, 1);
lua_pushcfunction(L, (lua_CFunction)function_spec->function);
lua_setglobal(L, function_spec->func_name);
}
lua_settop(L, 0);
return SUCCESS;
}
static int lua_cbinding_single_data(struct lua_state *state, struct lua_bind_data_spec *data_spec)
{
if (!state || !data_spec || !data_spec->data_value || !data_spec->data_name)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
if (data_spec->space_name)
{
lua_getglobal(L, data_spec->space_name);
if (lua_gettop(L) == 0 || lua_type(L, -1) == LUA_TNIL)
{
lua_newtable(L);
lua_setglobal(L, data_spec->space_name);
lua_settop(L, 0);
lua_getglobal(L, data_spec->space_name);
}
else
{
if (lua_type(L, -1) != LUA_TTABLE)
{
lua_settop(L, 0);
return BIND_NAMESPACE_TYPE_ERR;
}
lua_getfield(L, -1, data_spec->data_name);
if (lua_type(L, -1) != LUA_TNIL)
{
lua_settop(L, 0);
return BIND_DATA_TYPE_ERR;
}
lua_pop(L, 1);
}
switch (data_spec->data_type)
{
case DATATYPE_BOOL:
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
lua_pushboolean(L, 1);
else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE"))
lua_pushboolean(L, 0);
break;
case DATATYPE_INT:
lua_pushinteger(L, atoi(data_spec->data_value));
break;
case DATATYPE_NUM:
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
break;
case DATATYPE_STRING:
lua_pushstring(L, (const char *)data_spec->data_value);
break;
default:
/* 其他类型不支持 */
lua_settop(L, 0);
return BIND_DATA_TYPE_UNKNOWN;
}
lua_setfield(L, -2, data_spec->data_name);
}
else
{
lua_getglobal(L, data_spec->data_name);
if (lua_type(L, -1) != LUA_TNIL)
{
lua_settop(L, 0);
return BIND_DATA_TYPE_ERR;
}
lua_pop(L, 1);
switch (data_spec->data_type)
{
case DATATYPE_BOOL:
if (strstr(data_spec->data_value, "true") || strstr(data_spec->data_value, "TRUE"))
lua_pushboolean(L, 1);
else if (strstr(data_spec->data_value, "false") || strstr(data_spec->data_value, "FALSE"))
lua_pushboolean(L, 0);
break;
case DATATYPE_INT:
lua_pushinteger(L, atoi(data_spec->data_value));
break;
case DATATYPE_NUM:
lua_pushnumber(L, (lua_Number)atof(data_spec->data_value));
break;
case DATATYPE_STRING:
lua_pushstring(L, (const char *)data_spec->data_value);
break;
default:
/* 其他类型不支持 */
lua_settop(L, 0);
return BIND_DATA_TYPE_UNKNOWN;
}
lua_setglobal(L, data_spec->data_name);
}
lua_settop(L, 0);
return SUCCESS;
}
int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num)
{
int failed_count = 0;
for (unsigned index = 0; index < bind_func_num; index++)
{
if (lua_cbinding_single_function(state, &bind_function[index]))
failed_count++;
}
return failed_count;
}
int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num)
{
int failed_count = 0;
for (unsigned index = 0; index < bind_data_num; index++)
{
if (lua_cbinding_single_data(state, &bind_data[index]))
failed_count++;
}
return failed_count;
}
/* ***** ***** ***** ***** ***** ***** */
/* context */
/* ***** ***** ***** ***** ***** ***** */
const char *context_magic_code = "ctx_code";
struct lua_context *lua_context_new(struct lua_state *state)
{
if (!state)
return NULL;
lua_State *L = (lua_State *)state;
struct lua_context *new_context = (struct lua_context *)calloc(1, sizeof(struct lua_context));
new_context->magic_code = context_magic_code;
new_context->state = state;
lua_newtable(L);
int ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (ref_id == LUA_REFNIL)
return NULL;
new_context->lua_context_ref_id = ref_id;
return new_context;
}
void lua_context_free(struct lua_context *context)
{
if (!context)
return;
luaL_unref((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
free(context);
return;
}
void lua_context_push_stack(struct lua_context *context)
{
if (!context)
return;
if (context->lua_context_ref_id)
lua_rawgeti((lua_State *)context->state, LUA_REGISTRYINDEX, context->lua_context_ref_id);
return;
}
/* ***** ***** ***** ***** ***** ***** */
/* trans data between lua table and C */
/* ***** ***** ***** ***** ***** ***** */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
static int lua_function_writer(lua_State *state, const void *p, size_t sz, void *ud)
{
/* TODO: 这个函数在lua中会被大量调用, 频繁的realloc可能会导致内存碎片化, 后续调整一下内存分配机制 */
struct lua_cdata *data = (struct lua_cdata *)ud;
data->type = DATATYPE_FUNCTION;
if (!data->function)
data->function = (void *)calloc(1, sizeof(sz));
else
data->function = (void *)realloc(data->function, (data->data_len + sz));
memcpy((data->function + data->data_len), p, sz);
data->data_len += sz;
return 0;
}
static const char *lua_function_reader(lua_State *state, void *ud, size_t *sz)
{
struct lua_cdata *data = (struct lua_cdata *)ud;
*sz = data->data_len;
return (const char *)data->function;
}
#pragma GCC diagnostic pop
struct lua_cdata *lua_cdata_new(void)
{
struct lua_cdata *new_data = (struct lua_cdata *)calloc(1, sizeof(struct lua_cdata));
memset(new_data, 0, sizeof(struct lua_cdata));
return new_data;
}
static void lua_cdata_inner_data_free(struct lua_cdata *cdata)
{
if (!cdata)
return;
cdata->type = 0;
cdata->data_len = 0;
switch (cdata->type)
{
case DATATYPE_STRING:
free(cdata->string);
break;
case DATATYPE_LUA_TABLE:
lua_ctable_free(cdata->ctable);
break;
case DATATYPE_FUNCTION:
free(cdata->function);
break;
default:
break;
}
return;
}
void lua_cdata_free(struct lua_cdata *cdata)
{
lua_cdata_inner_data_free(cdata);
if (cdata)
free(cdata);
return;
}
int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata)
{
if (!state || !cdata)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
switch (cdata->type)
{
case DATATYPE_NIL:
lua_pushnil(L);
break;
case DATATYPE_BOOL:
lua_pushboolean(L, cdata->bool);
break;
case DATATYPE_INT:
lua_pushinteger(L, cdata->integer);
break;
case DATATYPE_NUM:
lua_pushnumber(L, cdata->number);
break;
case DATATYPE_STRING:
lua_pushstring(L, cdata->string);
break;
case DATATYPE_TABLE:
if (cdata->table)
lua_rawgeti(L, LUA_REGISTRYINDEX, cdata->table);
break;
case DATATYPE_LUA_TABLE:
lua_ctable_push_stack(state, cdata->ctable);
break;
case DATATYPE_POINTER:
lua_pushlightuserdata(L, (void *)cdata->pointer);
break;
case DATATYPE_CONTEXT:
lua_context_push_stack(cdata->context);
break;
case DATATYPE_FUNCTION:
lua_load(L, lua_function_reader, (void *)cdata, NULL, NULL);
break;
default:
return DATA_TYPE_UNKNOWN;
}
return SUCCESS;
}
int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata)
{
if (!state || !cdata)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
lua_cdata_inner_data_free(cdata);
switch (lua_type(L, -1))
{
case LUA_TNIL:
cdata->type = DATATYPE_NIL;
break;
case LUA_TBOOLEAN:
cdata->type = DATATYPE_BOOL;
cdata->bool = lua_toboolean(L, -1);
break;
case LUA_TLIGHTUSERDATA:
cdata->type = DATATYPE_POINTER;
cdata->pointer = (void *)lua_topointer(L, -1);
break;
case LUA_TNUMBER:
cdata->type = DATATYPE_NUM;
cdata->number = lua_tonumber(L, -1);
int try_int = (int)cdata->number;
if ((double)try_int == cdata->number)
{
cdata->type = DATATYPE_INT;
cdata->integer = lua_tointeger(L, -1);
}
break;
case LUA_TSTRING:
cdata->type = DATATYPE_STRING;
cdata->string = (char *)strdup(lua_tostring(L, -1));
break;
case LUA_TTABLE:
cdata->type = DATATYPE_LUA_TABLE;
cdata->ctable = lua_ctable_new();
lua_ctable_pop_stack(state, cdata->ctable);
break;
case LUA_TFUNCTION:
cdata->type = DATATYPE_FUNCTION;
lua_dump(L, lua_function_writer, cdata, 0);
break;
case LUA_TUSERDATA:
cdata->type = DATATYPE_POINTER;
cdata->pointer = (void *)lua_topointer(L, -1);
break;
default:
return DATA_TYPE_UNKNOWN;
}
lua_pop(L, 1);
return SUCCESS;
}
struct lua_ctable *lua_ctable_new(void)
{
struct lua_ctable *new_table = (struct lua_ctable *)calloc(1, sizeof(struct lua_ctable));
memset(new_table, 0, sizeof(struct lua_ctable));
return new_table;
}
void lua_ctable_free(struct lua_ctable *ctable)
{
if (!ctable)
return;
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
{
lua_cdata_free(ctable->array_data[array_index]);
}
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
{
lua_cnode_free(ctable->node_data[node_index]);
}
if (ctable->array_data)
free(ctable->array_data);
if (ctable->node_data)
free(ctable->node_data);
free(ctable);
return;
}
int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable)
{
if (!state || !ctable)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
lua_newtable(L);
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
{
lua_pushinteger(L, (array_index + 1));
lua_cdata_push_stack(state, ctable->array_data[array_index]);
lua_settable(L, -3);
}
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
{
if (ctable->node_data[node_index]->node_string_key)
lua_pushstring(L, ctable->node_data[node_index]->node_string_key);
else
lua_pushinteger(L, ctable->node_data[node_index]->node_integer_key);
lua_cdata_push_stack(state, ctable->node_data[node_index]->node_data);
lua_settable(L, -3);
}
return SUCCESS;
}
int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable)
{
if (!state || !ctable)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
/* 获取table长度 */
ctable->array_size = (size_t)lua_rawlen(L, -1);
lua_pushnil(L);
while (lua_next(L, -2))
{
ctable->node_size++;
if (lua_type(L, -2) == LUA_TNUMBER)
{
int numkey = lua_tointeger(L, -2);
if (numkey > 0 && numkey <= (int)ctable->array_size)
ctable->node_size--;
}
lua_pop(L, 1);
}
ctable->array_data = (struct lua_cdata **)calloc(ctable->array_size, sizeof(struct lua_cdata *));
for (unsigned array_index = 0; array_index < ctable->array_size; array_index++)
{
ctable->array_data[array_index] = lua_cdata_new();
}
ctable->node_data = (struct lua_cnode **)calloc(ctable->node_size, sizeof(struct lua_cnode *));
for (unsigned node_index = 0; node_index < ctable->node_size; node_index++)
{
ctable->node_data[node_index] = lua_cnode_new();
}
/* 依次获取数据 */
int key_index = 0;
lua_pushnil(L);
while (lua_next(L, -2))
{
if (lua_type(L, -2) == LUA_TNUMBER)
{
int numkey = lua_tointeger(L, -2);
if (numkey > 0 && numkey <= (int)ctable->array_size)
lua_cdata_pop_stack(state, ctable->array_data[numkey - 1]);
else
{
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
ctable->node_data[key_index]->node_integer_key = lua_tointeger(L, -1);
++key_index;
}
}
else if (lua_type(L, -2) == LUA_TSTRING)
{
lua_cdata_pop_stack(state, ctable->node_data[key_index]->node_data);
ctable->node_data[key_index]->node_string_key = strdup((char *)lua_tostring(L, -1));
++key_index;
}
}
return SUCCESS;
}
struct lua_cnode *lua_cnode_new(void)
{
struct lua_cnode *new_node = (struct lua_cnode *)calloc(1, sizeof(struct lua_cnode));
memset(new_node, 0, sizeof(struct lua_cnode));
new_node->node_data = lua_cdata_new();
return new_node;
}
void lua_cnode_free(struct lua_cnode *cnode)
{
if (cnode->node_string_key)
free(cnode->node_string_key);
if (cnode->node_data)
lua_cdata_free(cnode->node_data);
free(cnode);
return;
}
/* ***** ***** ***** ***** ***** ***** */
/* execute one chunk */
/* ***** ***** ***** ***** ***** ***** */
int lua_chunk_execute(
struct lua_state *state,
int fn_ref_id,
struct lua_cdata param[],
size_t param_num,
struct lua_cdata returnvalue[],
size_t r_num,
char *errlog,
size_t err_len)
{
if (!state || fn_ref_id <= 0 || (param_num && !param) || (r_num && !returnvalue))
return PARAM_ERR;
lua_State *L = (lua_State *)state;
lua_rawgeti(L, LUA_REGISTRYINDEX, fn_ref_id);
if (lua_type(L, -1) != LUA_TFUNCTION)
{
lua_settop(L, 0);
return CHUNK_TYPE_NOT_FUNCTION;
}
int pushret = 0;
for (unsigned param_index = 0; param_index < param_num; ++param_index)
{
if ((pushret = lua_cdata_push_stack(state, &param[param_index])))
{
lua_settop(L, 0);
return pushret;
}
}
if (lua_pcall(L, param_num, LUA_MULTRET, 0))
{
if (errlog)
snprintf(errlog, (err_len - 1), "run script[%d] err %s\n", fn_ref_id, lua_tostring(L, -1));
lua_settop(L, 0);
return CHUNK_RUN_CODE_FAIL;
}
if (r_num > 0)
{
int count = lua_gettop(L);
/* 如果接收返回值数量不够, 只保留前r_num个返回值 */
if (count > (int)r_num)
{
lua_pop(L, (count - (int)r_num));
count = (int)r_num;
}
int pop_ret = 0;
for (int i = (count - 1); i >= 0; --i)
{
if ((pop_ret = lua_cdata_pop_stack(state, &(returnvalue[i]))))
{
lua_settop(L, 0);
return pop_ret;
}
}
}
lua_settop(L, 0);
return SUCCESS;
}
/* TODO: 这个hash函数是不是合适 */
int calc_on_message_func_hash_key(int topic_id, int plugin_id)
{
return (((uint32_t)plugin_id << 3) + (uint32_t)topic_id) % HASH_MAX_NUM;
}
struct lua_on_message_fn *hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id)
{
int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id);
struct lua_on_message_fn *insert_positon = &msg_fn_hashlist[hash_key];
while ((insert_positon->hash_on_use - HASH_MAX_NUM) > 0)
{
if (insert_positon->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1))
insert_positon = &msg_fn_hashlist[0];
else
insert_positon++;
/* 没有空位置了 */
if (insert_positon->hash_on_use % HASH_MAX_NUM == hash_key)
return NULL;
}
insert_positon->hash_on_use += (HASH_MAX_NUM + 1);
insert_positon->topic_id = topic_id;
insert_positon->plugin_id = plugin_id;
return insert_positon;
}
struct lua_on_message_fn *hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id)
{
int hash_key = calc_on_message_func_hash_key(topic_id, plugin_id);
struct lua_on_message_fn *find_position = &msg_fn_hashlist[hash_key];
if ((find_position->hash_on_use - HASH_MAX_NUM) < 0)
return NULL;
while (find_position)
{
if (find_position->topic_id == topic_id && find_position->plugin_id == plugin_id)
{
return find_position;
}
if (find_position->hash_on_use % HASH_MAX_NUM == (HASH_MAX_NUM - 1))
find_position = &msg_fn_hashlist[0];
else
find_position++;
if ((find_position->hash_on_use % HASH_MAX_NUM == hash_key) || (find_position->hash_on_use - HASH_MAX_NUM) < 0)
break;
}
return NULL;
}
#define LUA_GLOBAL_VALUE_REF_ID (LUA_RIDX_LAST + 2)
static inline struct lua_state *thread_state_init(int thread_id, struct stellar *st, struct lua_plugin_manage *plugin_manage)
{
lua_State *new_L = luaL_newstate();
luaL_openlibs(new_L);
lua_newtable(new_L);
lua_pushinteger(new_L, thread_id);
lua_setfield(new_L, -2, LUA_GLOBAL_THREAD_ID_KEY);
lua_pushlightuserdata(new_L, st);
lua_setfield(new_L, -2, LUA_GLOBAL_STELLAR_POINTER);
lua_pushlightuserdata(new_L, plugin_manage);
lua_setfield(new_L, -2, LUA_GLOBAL_PLUGIN_MANGE_POINTER);
int global_ref_id = luaL_ref(new_L, LUA_REGISTRYINDEX);
printf("set global ref id is %d\n", global_ref_id);
lua_settop(new_L, 0);
struct lua_state *new_state = (struct lua_state *)new_L;
lua_cbinding_function(new_state, lua_bind_function, (sizeof(lua_bind_function) / sizeof(struct lua_bind_function_spec)));
lua_cbinding_data(new_state, lua_bind_data, (sizeof(lua_bind_data) / sizeof(struct lua_bind_data_spec)));
return new_state;
}
/*
int lua_state_get_thread_id(struct lua_state * state)
{
lua_State * L = (lua_State *)state;
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
int thread_id = -1;
if ( lua_getfield(L, -1, LUA_GLOBAL_THREAD_ID_KEY) == LUA_TNUMBER )
thread_id = lua_tointeger(L, -1);
lua_pop(L, 2);
return thread_id;
}
struct stellar * lua_state_get_stellar(struct lua_state * state)
{
lua_State * L = (lua_State *)state;
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
struct stellar * st = NULL;
if ( lua_getfield(L, -1, LUA_GLOBAL_STELLAR_POINTER) == LUA_TLIGHTUSERDATA )
st = (struct stellar *)lua_topointer(L, -1);
lua_pop(L, 2);
return st;
}
*/
struct lua_plugin_manage *lua_state_get_plugin_manage(struct lua_state *state)
{
lua_State *L = (lua_State *)state;
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_GLOBAL_VALUE_REF_ID);
struct lua_plugin_manage *plugin_manage = NULL;
if (lua_getfield(L, -1, LUA_GLOBAL_PLUGIN_MANGE_POINTER) == LUA_TLIGHTUSERDATA)
plugin_manage = (struct lua_plugin_manage *)lua_topointer(L, -1);
lua_pop(L, 2);
return plugin_manage;
}
static int lua_state_load_one_specific(
struct lua_state *state,
struct lua_config_spec *spec,
struct lua_load_script *script,
struct stellar *st,
char *errlog,
size_t errlog_len)
{
if (!state || !spec || !script)
return PARAM_ERR;
lua_State *L = (lua_State *)state;
if (access(spec->spec_file_path, F_OK) || luaL_loadfile(L, spec->spec_file_path))
return STATE_LOAD_FILE_ERR;
if (lua_pcall(L, 0, 0, 0))
{
snprintf(errlog, (errlog_len - 1), "load spec[%s] fail err is %s\n", spec->spec_file_path, lua_tostring(L, -1));
lua_settop(L, 0);
return STATE_LOAD_FILE_ERR;
}
/* 创建on_load函数及on_unload函数的引用 */
lua_getglobal(L, spec->spec_load_func_name);
if (lua_type(L, -1) != LUA_TFUNCTION)
{
snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_load_func_name);
return STATE_REF_TYPE_ERR;
}
script->lua_load_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (script->lua_load_fn_ref_id <= 0)
{
snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_load_func_name, script->lua_load_fn_ref_id);
return STATE_CREATE_REF_FAIL;
}
lua_getglobal(L, spec->spec_unload_func_name);
if (lua_type(L, -1) != LUA_TFUNCTION)
{
snprintf(errlog, (errlog_len - 1), "spec[%s] funcname[%s] is not a function\n", spec->spec_file_path, spec->spec_unload_func_name);
return STATE_REF_TYPE_ERR;
}
script->lua_unload_fn_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (script->lua_unload_fn_ref_id <= 0)
{
snprintf(errlog, (errlog_len - 1), "spec[%s]%s create load func ref id is %d\n", spec->spec_file_path, spec->spec_unload_func_name, script->lua_unload_fn_ref_id);
return STATE_CREATE_REF_FAIL;
}
/* 创建依赖于该script的script_env, 并调用on_load函数 */
lua_newtable(L);
script->lua_script_env_ref_id = luaL_ref(L, LUA_REGISTRYINDEX);
if (script->lua_script_env_ref_id <= 0)
{
snprintf(errlog, (errlog_len - 1), "spec[%s] create script env failed, ref is %d\n", spec->spec_file_path, script->lua_script_env_ref_id);
return STATE_CREATE_REF_FAIL;
}
struct lua_cdata param[2];
param[0].type = DATATYPE_POINTER;
param[0].pointer = (void *)st;
param[1].type = DATATYPE_TABLE;
param[1].table = script->lua_script_env_ref_id;
char exec_err[1024] = {0};
int exec_ret = lua_chunk_execute(state, script->lua_load_fn_ref_id, param, 2, NULL, 0, exec_err, sizeof(exec_err));
if (exec_ret)
{
snprintf(errlog, (errlog_len - 1), "spec[%s]%s call fail, err num %d, err %s\n", spec->spec_file_path, spec->spec_load_func_name, exec_ret, exec_err);
return STATE_CALL_LOAD_FAILED;
}
return SUCCESS;
};
// static UT_icd lua_session_plugin_icd = {sizeof(struct lua_session_plugin_env), NULL, NULL, NULL};
// static UT_icd lua_packet_plugin_icd = {sizeof(struct lua_packet_plugin_env), NULL, NULL, NULL};
// static UT_icd lua_message_free_icd = {sizeof(struct lua_message_free_arg), NULL, NULL, NULL};
struct lua_plugin_manage *lua_plugin_manage_init(
struct stellar *st,
struct lua_config_spec specific[],
size_t specific_num)
{
if (!st)
return NULL;
char errlog[1024] = {0};
struct lua_plugin_manage *new_plugin_manage = (struct lua_plugin_manage *)calloc(1, sizeof(struct lua_plugin_manage));
memset(new_plugin_manage, 0, sizeof(struct lua_plugin_manage));
new_plugin_manage->st = st;
int thread_count = stellar_get_worker_thread_num(st);
if (thread_count <= 0)
return new_plugin_manage;
new_plugin_manage->state_num = thread_count;
new_plugin_manage->state_array = (struct lua_state **)calloc(thread_count, sizeof(struct lua_state *));
memset(new_plugin_manage->state_array, 0, thread_count * sizeof(struct lua_state *));
for (int thread_index = 0; thread_index < thread_count; thread_index++)
{
new_plugin_manage->state_array[thread_index] = thread_state_init(thread_index, st, new_plugin_manage);
}
for (unsigned on_message_index = 0; on_message_index < HASH_MAX_NUM; on_message_index++)
{
new_plugin_manage->on_session_message_hashlist[on_message_index].hash_on_use = on_message_index;
new_plugin_manage->on_packet_message_hashlist[on_message_index].hash_on_use = on_message_index;
}
if (specific_num == 0)
return new_plugin_manage;
new_plugin_manage->load_script_array = (struct lua_load_script *)calloc(specific_num, sizeof(struct lua_load_script));
new_plugin_manage->load_script_num = specific_num;
for (unsigned spec_index = 0; spec_index < specific_num; spec_index++)
{
if (lua_state_load_one_specific(new_plugin_manage->state_array[0],
&specific[spec_index],
&new_plugin_manage->load_script_array[spec_index],
st,
errlog,
sizeof(errlog)))
{
printf("%s\n", errlog);
goto err;
}
}
lua_newtable((lua_State *)new_plugin_manage->state_array[0]);
int lua_ref_max_id = luaL_ref((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX);
struct lua_cdata *trans_data = lua_cdata_new();
for (int ref_index = (LUA_GLOBAL_VALUE_REF_ID + 1); ref_index < lua_ref_max_id; ref_index++)
{
lua_settop((lua_State *)new_plugin_manage->state_array[0], 0);
lua_rawgeti((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, ref_index);
lua_cdata_pop_stack(new_plugin_manage->state_array[0], trans_data);
for (int thread_index = 1; thread_index < thread_count; thread_index++)
{
lua_cdata_push_stack(new_plugin_manage->state_array[thread_index], trans_data);
int ref_id = luaL_ref((lua_State *)new_plugin_manage->state_array[thread_index], LUA_REGISTRYINDEX);
printf("ref to new thread, ref id is %d, %d\n", ref_index, ref_id);
}
lua_cdata_inner_data_free(trans_data);
}
luaL_unref((lua_State *)new_plugin_manage->state_array[0], LUA_REGISTRYINDEX, lua_ref_max_id);
return new_plugin_manage;
err:
lua_plugin_manage_exit(new_plugin_manage);
return NULL;
}
void lua_plugin_manage_exit(struct lua_plugin_manage *lua_plug_mgr)
{
if (!lua_plug_mgr)
return;
for (unsigned script_index = 0; script_index < lua_plug_mgr->load_script_num; script_index++)
{
struct lua_cdata param;
param.type = DATATYPE_TABLE;
param.table = lua_plug_mgr->load_script_array[script_index].lua_script_env_ref_id;
lua_chunk_execute(lua_plug_mgr->state_array[0], lua_plug_mgr->load_script_array[script_index].lua_unload_fn_ref_id, &param, 1, NULL, 0, NULL, 0);
}
free(lua_plug_mgr->load_script_array);
for (unsigned state_index = 0; state_index < lua_plug_mgr->state_num; ++state_index)
{
lua_close((lua_State *)lua_plug_mgr->state_array[state_index]);
}
free(lua_plug_mgr->state_array);
struct lua_session_plugin_env *session_env = lua_plug_mgr->session_plugin_env_list;
while (session_env)
{
struct lua_session_plugin_env *next = session_env->next;
free(session_env);
session_env = next;
}
struct lua_packet_plugin_env *packet_env = lua_plug_mgr->packet_plugin_env_list;
while (packet_env)
{
struct lua_packet_plugin_env *next = packet_env->next;
free(packet_env);
packet_env = next;
}
struct lua_message_free_arg *message_free_arg = lua_plug_mgr->message_free_arg_list;
while (message_free_arg)
{
struct lua_message_free_arg *next = message_free_arg->next;
free(message_free_arg);
message_free_arg = next;
}
free(lua_plug_mgr);
return;
}

View File

@@ -1,217 +0,0 @@
#ifndef LUA_PLUGIN_MANAGE_INTERNAL_H
#define LUA_PLUGIN_MANAGE_INTERNAL_H
#include <stddef.h>
#include "lua_plugin_manage.h"
struct lua_state;
enum LUA_PLUGIN_MANGE_ERR_NUM
{
/* 状态机相关的错误码 */
STATE_LOAD_FILE_ERR = -400, /* 状态机加载lua文件时出错, 可能原因是文件不存在或文件无法加载 */
STATE_REF_TYPE_ERR, /* 获取函数引用ID过程中数据类型有错, 无法正常执行 */
STATE_CREATE_REF_FAIL, /* 创建引用ID过程中失败, 无法创建refid */
STATE_CALL_LOAD_FAILED, /* 调用on_load函数过程中运行失败 */
STATE_CALL_UNLOAD_FAILED, /* 调用on_unload函数过程中运行失败 */
STATE_CREATE_ENV_FAIL, /* 在状态机中创建新的plugin_env时出现错误, 无法创建或该模块之前加载过程中的引用ID与新创建ID不同 */
STATE_GET_UNLOAD_FAIL, /* 状态机加载unload函数时出现错误, 该函数不存在或引用ID有问题 */
/* lua代码块运行错误码 */
CHUNK_TYPE_NOT_FUNCTION = -300, /* 获取得到的代码块类型并非可执行的lua语句, 无法执行 */
CHUNK_RUN_CODE_FAIL, /* 调用代码过程中运行失败, 失败的具体报错信息会保存在栈中, 通过日志输出 */
CHUNK_RCOUNT_ERR, /* 尝试接收返回值, 但传入接收返回值的队列长度小于实际返回值个数 */
/* lua与C之间数据转换或操作错误码 */
DATA_TYPE_UNKNOWN = -200, /* 无法识别的struct lua_cdata数据类型, 或在该函数中操作了不支持的数据类型 */
DATA_TYPE_ERR, /* 获取到了错误的数据类型 */
DATA_PUSHSTACK_ERR, /* 数据入栈过程中遇到未知的问题 */
DATA_POPSTACK_ERR, /* 数据从状态机中出栈过程中遇到未知的问题 */
DATA_POPSTACK_NODATA, /* 出栈过程中栈内无数据, 导致出栈失败 */
/* lua函数或数据绑定错误码 */
BIND_NAMESPACE_TYPE_ERR = -100, /* 绑定或删除过程中使用命名空间, 但命名空间数据类型不符 */
BIND_FUNCTION_TYPE_ERR, /* 绑定或删除函数过程中数据类型错误 */
BIND_DATA_TYPE_ERR, /* 绑定或删除全局变量过程中数据类型错误 */
BIND_DATA_TYPE_UNKNOWN, /* struct lua_binding_data格式中数据类型无法识别, 或在该功能中操作了不支持的数据类型 */
/* 通用返回值 */
PARAM_ERR = -1, /* 传入参数错误, 可能是指针为空或类型不符合 */
SUCCESS = 0, /* 运行成功 */
};
/* ***** ***** ***** ***** ***** ***** */
/* 需要注册至lua中的函数 */
typedef int (*lua_cbind_func)(struct lua_state *state);
struct lua_bind_function_spec
{
lua_cbind_func function; /* 注册函数原型 */
char *func_name; /* 注册至lua中的函数名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
int lua_cbinding_function(struct lua_state *state, struct lua_bind_function_spec bind_function[], size_t bind_func_num);
extern const char *context_magic_code;
struct lua_context
{
const char *magic_code;
struct lua_state *state;
int lua_context_ref_id;
};
struct lua_context *lua_context_new(struct lua_state *state);
void lua_context_free(struct lua_context *context);
void lua_context_push_stack(struct lua_context *context);
enum DATATYPE
{
DATATYPE_BEGIN = 0,
DATATYPE_NIL, /* nil类型 */
DATATYPE_BOOL, /* bool类型 */
DATATYPE_INT, /* int类型 */
DATATYPE_NUM, /* double类型 */
DATATYPE_STRING, /* 字符串类型 */
/* 以下类型不能用于全局变量注册 */
DATATYPE_TABLE, /* table类型 */
DATATYPE_LUA_TABLE, /* 此类型用于在lua之间翻译传递数据 */
DATATYPE_POINTER, /* 指针类型 */
DATATYPE_CONTEXT, /* context上下文类型 */
DATATYPE_FUNCTION, /* 函数类型 */
DATATYPE_END
};
/* 需要注册至lua状态机中的数据 */
struct lua_bind_data_spec
{
enum DATATYPE data_type; /* 注册的数据类型 */
char *data_value; /* 注册数数据值 */
char *data_name; /* 注册的数据名称 */
char *space_name; /* 注册至lua中的命名空间名称 */
};
int lua_cbinding_data(struct lua_state *state, struct lua_bind_data_spec bind_data[], size_t bind_data_num);
struct lua_cdata;
struct lua_cnode;
struct lua_ctable;
struct lua_cdata
{
enum DATATYPE type;
size_t data_len; /* 只有在类型为function时使用此标识 */
union
{
int bool;
int integer;
double number;
char *string;
int table;
void *pointer;
struct lua_context *context;
void *function;
struct lua_ctable *ctable;
};
};
struct lua_cnode
{
char *node_string_key;
int node_integer_key;
struct lua_cdata *node_data;
};
struct lua_ctable
{
size_t array_size;
size_t node_size;
struct lua_cdata **array_data;
struct lua_cnode **node_data;
};
struct lua_cdata *lua_cdata_new(void);
void lua_cdata_free(struct lua_cdata *cdata);
int lua_cdata_push_stack(struct lua_state *state, struct lua_cdata *cdata);
int lua_cdata_pop_stack(struct lua_state *state, struct lua_cdata *cdata);
struct lua_ctable *lua_ctable_new(void);
void lua_ctable_free(struct lua_ctable *ctable);
int lua_ctable_push_stack(struct lua_state *state, struct lua_ctable *ctable);
int lua_ctable_pop_stack(struct lua_state *state, struct lua_ctable *ctable);
struct lua_cnode *lua_cnode_new(void);
void lua_cnode_free(struct lua_cnode *cnode);
/* ***** ***** ***** ***** ***** ***** */
int lua_chunk_execute(struct lua_state *state, int fn_ref_id, struct lua_cdata param[], size_t param_num, struct lua_cdata returnvalue[], size_t r_num, char *errlog, size_t err_len);
/* ***** ***** ***** ***** ***** ***** */
struct lua_load_script
{
int lua_load_fn_ref_id;
int lua_unload_fn_ref_id;
int lua_script_env_ref_id;
};
struct lua_session_plugin_env
{
struct lua_session_plugin_env *next;
struct lua_plugin_manage *plugin_manage;
int session_plugin_id;
int lua_ctx_new_fn_ref_id;
int lua_ctx_free_fn_ref_id;
int lua_plug_env_ref_id;
};
struct lua_packet_plugin_env
{
struct lua_packet_plugin_env *next;
struct lua_plugin_manage *plugin_manage;
int packet_plugin_id;
int lua_on_packet_fn_ref_id;
int lua_plug_env_ref_id;
};
struct lua_message_free_arg
{
struct lua_message_free_arg *next;
struct lua_plugin_manage *plugin_manage;
int topic_id;
int lua_msg_free_fn_ref_id;
int lua_msg_free_arg_ref_id;
};
struct lua_on_message_fn
{
int hash_on_use;
int topic_id;
int plugin_id;
int lua_on_msg_fn_ref_id;
};
#define HASH_MAX_NUM 1024
int calc_on_message_func_hash_key(int topic_id, int plugin_id);
struct lua_on_message_fn *hash_on_msg_fn_insert(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id);
struct lua_on_message_fn *hash_find_on_msg_fn(struct lua_on_message_fn msg_fn_hashlist[], int topic_id, int plugin_id);
#define LUA_GLOBAL_THREAD_ID_KEY "__global_thread_id"
#define LUA_GLOBAL_STELLAR_POINTER "__global_stellar_pointer"
#define LUA_GLOBAL_PLUGIN_MANGE_POINTER "__global_plugin_managee_pointer"
// int lua_state_get_thread_id(struct lua_state * state);
// struct stellar * lua_state_get_stellar(struct lua_state * state);
struct lua_plugin_manage *lua_state_get_plugin_manage(struct lua_state *state);
struct lua_plugin_manage
{
struct stellar *st;
size_t state_num;
size_t load_script_num;
struct lua_state **state_array;
struct lua_load_script *load_script_array;
struct lua_session_plugin_env *session_plugin_env_list;
struct lua_packet_plugin_env *packet_plugin_env_list;
struct lua_message_free_arg *message_free_arg_list;
struct lua_on_message_fn on_session_message_hashlist[HASH_MAX_NUM];
struct lua_on_message_fn on_packet_message_hashlist[HASH_MAX_NUM];
};
#endif

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)/test/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 -lstellar_on_sapp
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,9 +0,0 @@
[[plugin]]
path = "./plugin/simple_stellar_plugin.so"
init = "simple_plugin_sub_session_stat_init"
exit = "simple_plugin_sub_session_stat_exit"
[[plugin]]
path = "./plugin/simple_stellar_plugin.so"
init = "simple_session_packet_plugin_init"
exit = "simple_session_packet_plugin_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,286 +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_spec *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_specific(struct lua_config_spec *specific, 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 *lua_schema = NULL;
if (global_arg_config.lua_mod)
{
int num = 0;
struct lua_config_spec *specific = config_load(LUA_CONFIG_PATH, &num);
assert(specific);
if (global_arg_config.print_mod)
debug_plugin_manage_specific(specific, num);
lua_schema = lua_plugin_manage_init(&st, specific, num);
st.lua_plug_mgr = lua_schema;
assert(lua_schema);
if (specific)
free(specific);
// printf("now wait time to compute memory ... ...\n");
// sleep(global_arg_config.wait_time);
}
if (global_arg_config.print_mod)
debug_plugin_manage_schema(plug_mgr);
/* ***** ***** 初始化完成 ***** ***** */
/* ***** ***** 会话相关测试 ***** ***** */
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_spec *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_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 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_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");
}
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,97 +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 * 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 stellar_get_worker_thread_num(struct stellar *st)
{
return st->thread_num;
}
int stellar_get_current_thread_id(struct stellar *st)
{
return 3;
}
#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,65 +0,0 @@
function plugin_ctx_new(sess, plug_env, sess_context)
print("now lua plugin create sess ctx, plugin id", plug_env.id)
sess_context.count = 0
sess_context.payload_len = 0
msg = {}
msg.data = "this is lua plugin message"
session_mq.publish_message(sess, plug_env.topic_id, msg)
end
function plugin_ctx_free(sess, sess_context, plug_env)
print("now lua plugin begin to free sess ctx")
print("total packet count is", sess_context.count)
print("total paylaod length is", sess_context.payload_len)
end
function on_message_fn(sess, topic_id, msg, sess_context, env)
sess_context.count = sess_context.count + 1
print("lua plugin call on message fn", sess_context.count)
payload, payload_len = session.get_payload(sess)
sess_context.payload_len = sess_context.payload_len + payload_len
print(payload)
end
function free_message(sess, msg, msg_free_arg)
print("message need to free is", msg.data)
print("free arg data is", msg_free_arg.data)
end
function plugin_load(stellar, plug_env)
print("now begin to load lua example plugin")
plug_env.st = stellar
plug_env.id = session_plugin.register(stellar, plugin_ctx_new, plugin_ctx_free, plug_env)
plug_env.data = "this is lua example plug env data"
--[[ 获取TCP topic, 并完成订阅 ]]
tcp_topic_id = session_mq.get_topic_id(stellar, "TCP")
print("lua plugin get TCP topic id is", tcp_topic_id)
session_mq.subscribe_topic(stellar, tcp_topic_id, on_message_fn, plug_env.id)
plug_env.tcp_topic_id = tcp_topic_id
--[[ 创建TOPIC_SESSION_STAT, 并完成函数注册 ]]
msg_free_arg = {}
msg_free_arg.data = "this is lua plugin message free arg data"
test_topic_id = session_mq.get_topic_id(stellar, "LUA_TOPIC_SESSION_STAT")
if (test_topic_id < 0)
then
--[[ 该消息未创建, 创建该topic ]]
test_topic_id = session_mq.create_topic(stellar, "LUA_TOPIC_SESSION_STAT", free_message, msg_free_arg)
print("create topic is", test_topic_id)
else
--[[ 如果该消息已经注册, 更新其注册函数 ]]
session_mq.update_topic(stellar, test_topic_id, free_message, msg_free_arg)
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 example plugin")
print("plugin env data is", plug_env.data)
print("now destory topic id is", plug_env.topic_id)
session_mq.destory_topic(plug_env.st, plug_env.topic_id)
end

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,33 +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("get message is", topic_id, msg.data)
end
function plugin_load(stellar, plug_env)
plug_env.st = stellar
plug_env.id = session_plugin.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 = session_mq.get_topic_id(stellar, "LUA_TOPIC_SESSION_STAT")
if (test_topic_id < 0)
then
--[[ 该消息未创建, 创建该topic ]]
test_topic_id = session_mq.create_topic(stellar, "LUA_TOPIC_SESSION_STAT", nil, nil)
print("create topic is", test_topic_id)
end
session_mq.subscribe_topic(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 = session_plugin.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,65 +0,0 @@
function plugin_ctx_new(sess, plug_env, sess_context)
print("now create new ctx example topic, plugin id", plug_env.id)
sess_context.count = 0
sess_context.payload_len = 0
msg = {}
msg.data = "this is message"
session_mq.publish_message(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")
print("total packet count is", sess_context.count)
print("total paylaod length is", sess_context.payload_len)
end
function on_message_fn(sess, topic_id, msg, sess_context, env)
sess_context.count = sess_context.count + 1
-- print("topic call on message function, id", topic_id)
payload, payload_len = session.get_payload(sess)
sess_context.payload_len = sess_context.payload_len + payload_len
end
function free_message(sess, msg, msg_free_arg)
print("message need to free is", msg.data)
print("env id is ", msg_free_arg.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 = session_plugin.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 = session_mq.get_topic_id(stellar, "TCP")
print("get TCP topic id is", tcp_topic_id)
session_mq.subscribe_topic(stellar, tcp_topic_id, on_message_fn, plug_env.id)
plug_env.tcp_topic_id = tcp_topic_id
--[[ 创建TOPIC_SESSION_STAT, 并完成函数注册 ]]
msg_free_arg = {}
msg_free_arg.data = "this is example topic msg private data"
test_topic_id = session_mq.get_topic_id(stellar, "LUA_TOPIC_SESSION_STAT")
if (test_topic_id < 0)
then
--[[ 该消息未创建, 创建该topic ]]
test_topic_id = session_mq.create_topic(stellar, "LUA_TOPIC_SESSION_STAT", free_message, msg_free_arg)
print("create topic is", test_topic_id)
else
--[[ 如果该消息已经注册, 更新其注册函数 ]]
session_mq.update_topic(stellar, test_topic_id, free_message, msg_free_arg)
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)
session_mq.destory_topic(plug_env.st, plug_env.topic_id)
end

Binary file not shown.

View File

@@ -1,363 +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);
printf("get packet length is %lu\n", 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;
}

Binary file not shown.