第一版初步跑通

This commit is contained in:
崔一鸣
2019-04-22 14:29:45 +08:00
parent 4333c8d31b
commit 34e58f972f
8 changed files with 661 additions and 141 deletions

View File

@@ -1,38 +1,36 @@
#include "adapter.h" #include "adapter.h"
#define LOG_MODULE_NAME "SAPP_LUA"
#define LUA_SAPP_SYMBOL_MAX 64
#define LUA_SAPP_PATH_MAX 256
#define LUA_SAPP_STRING_MAX 2048
#define LUA_ENTRY_TYPE_NUM 8
enum lua_entry_type{
LUA_ENTRY_TYPE_IP = 0,
LUA_ENTRY_TYPE_TCP,
LUA_ENTRY_TYPE_UDP,
LUA_ENTRY_TYPE_HTTP,
LUA_ENTRY_TYPE_TLS,
LUA_ENTRY_TYPE_DNS,
LUA_ENTRY_TYPE_MAIL,
LUA_ENTRY_TYPE_FTP,
};
//TODO: //TODO:
// other_regions 有多个, 怎么处理 //每个函数都要判断返回值 done
// 增加根据region返回header功能 // lua错误处理比如函数没有注册resume的返回值判断然后打印错误, 不再resume该协程 done
//压栈之前要check_stack done
class lua_plug{ //流结束clear_ctx之外还要释放该协程自动垃圾回收做实验验证一下 done
public: //destroy释放lua_state done
std::string file_path; //多线程 m * n个虚拟机
enum lua_entry_type entry_type; //dumpfile改成在线试一下
int dir; //错误处理,日志, 工程化,日志完备
std::unordered_set<std::string> regions;
lua_State *lua_state;
};
static void* g_logger = NULL; static void* g_logger = NULL;
static std::vector<std::vector<lua_plug>> g_lua_plugs(LUA_ENTRY_TYPE_NUM, std::vector<lua_plug>()); static std::vector<std::vector<lua_plug>> g_lua_plugs(LUA_ENTRY_TYPE_NUM, std::vector<lua_plug>());
static void lua_traceback(const char *func_name, lua_State *lua_state, int ret){
int n = lua_gettop(lua_state);
printf("%s error: ret is %d, traceback is:\n", func_name, ret);
for(int i = -1; i >= 0 - n; i--){
std::string type = std::string(lua_typename(lua_state, lua_type(lua_state, i)));
if(type == "string"){
printf("%s\n", lua_tostring(lua_state, i));
}
}
lua_pop(lua_state, n);
}
std::string _inet_ntoa(uint32_t ip)
{
const char *_ip = inet_ntoa(*(struct in_addr *)&ip);
return std::string(_ip);
}
//copy from suricata //copy from suricata
static int lua_push_string_buffer(lua_State *lua_state, const char *input, size_t input_len) static int lua_push_string_buffer(lua_State *lua_state, const char *input, size_t input_len)
{ {
@@ -53,48 +51,179 @@ static int lua_push_string_buffer(lua_State *lua_state, const char *input, size_
return 1; return 1;
} }
static int get_stream_tuple5(lua_State *lua_state){
static int _get_http_headers(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
lua_getglobal(lua_state, "cur_http_sess_ctx"); lua_getglobal(lua_state, "cur_http_sess_ctx");
http_sess_ctx *sess_ctx = (http_sess_ctx *)lua_touserdata(lua_state, -1); http_sess_ctx *sess_ctx = (http_sess_ctx *)lua_touserdata(lua_state, -1);
lua_getglobal(lua_state, "cur_http_sess_dir"); lua_pop(lua_state, 1);
int curdir = (int)lua_tonumber(lua_state, -1);
lua_pop(lua_state, 2);
if(sess_ctx == NULL){ if(sess_ctx == NULL){
//do log //do log
std::cout<<"sess_ctx is null"<<std::endl; std::cout<<"sess_ctx is null"<<std::endl;
return -1;
}
stream_tuple5& tuple5 = sess_ctx->tuple5;
if(tuple5.parse_done == true){
lua_newtable(lua_state);
lua_push_string_buffer(lua_state, "ip_version", std::string("ip_version").length());
lua_push_string_buffer(lua_state, tuple5.ip_version.c_str(), tuple5.ip_version.length());
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "stream_type", std::string("stream_type").length());
lua_push_string_buffer(lua_state, tuple5.stream_type.c_str(), tuple5.stream_type.length());
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "sip", std::string("sip").length());
lua_push_string_buffer(lua_state, tuple5.sip.c_str(), tuple5.sip.length());
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "dip", std::string("dip").length());
lua_push_string_buffer(lua_state, tuple5.dip.c_str(), tuple5.dip.length());
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "sport", std::string("sport").length());
lua_pushinteger(lua_state, tuple5.sport);
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "dport", std::string("dport").length());
lua_pushinteger(lua_state, tuple5.dport);
lua_settable(lua_state, -3);
return 0; return 0;
} }
lua_newtable(lua_state); return -1;
for(auto header : curdir == DIR_C2S ? sess_ctx->request_headers : sess_ctx->response_headers){ }
lua_push_string_buffer(lua_state, header.first.c_str(), header.first.length() + 1);
lua_push_string_buffer(lua_state, header.second.c_str(), header.second.length() + 1); static int _get_stream_info(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
lua_settable(lua_state, -3); int ret = get_stream_tuple5(lua_state);
if(ret < 0){
lua_yieldk(lua_state, 0, 0, _get_stream_info);
} }
//return 1 means one return value
return 1; return 1;
} }
static int get_http_headers(lua_State *lua_state){ static int get_stream_info(lua_State* lua_state){
lua_yieldk(lua_state, 0, 0, _get_http_headers); //printf("call get_strem_info\n");
return 1; return _get_stream_info(lua_state, 0, 0);
} }
int regions_parse(char *str, std::unordered_set<std::string>& regions){ static int get_http_header(lua_State *lua_state, int type){
char *token; lua_getglobal(lua_state, "cur_http_sess_ctx");
char *rest = str; http_sess_ctx *sess_ctx = (http_sess_ctx *)lua_touserdata(lua_state, -1);
while((token = strtok_r(rest, ",", &rest))){ lua_pop(lua_state, 1);
std::string _token = std::string(token); if(sess_ctx == NULL){
if(_token == "all"){ //do log
regions.clear(); std::cout<<"sess_ctx is null"<<std::endl;
regions.insert(_token); return -1;
return 0; }
std::unordered_set<std::string> required_regions;
lua_pushnil(lua_state);
while(lua_next(lua_state, -2) != 0){
required_regions.insert(std::string(lua_tostring(lua_state, -1)));
lua_pop(lua_state, 1);
}
http_header& header = (type == HTTP_TYPE_REQUEST ? sess_ctx->req_header : sess_ctx->resp_header);
if(header.parse_done == true){
//printf("header parse done\n");
lua_newtable(lua_state);
for(auto region : header.std_regions){
if(required_regions.find("ALL") != required_regions.end() || required_regions.find(region.first) != required_regions.end()){
lua_push_string_buffer(lua_state, region.first.c_str(), region.first.length());
lua_push_string_buffer(lua_state, region.second.c_str(), region.second.length());
lua_settable(lua_state, -3);
}
} }
regions.insert(_token); if(!header.other_regions.empty()){
if(required_regions.find("ALL") != required_regions.end() || required_regions.find("HTTP_OTHER_REGIONS") != required_regions.end()){
lua_push_string_buffer(lua_state, "HTTP_OTHER_REGIONS", std::string("HTTP_OTHER_REGIONS").length());
lua_newtable(lua_state);
int i = 1;
for(auto region : header.other_regions){
lua_push_string_buffer(lua_state, region.c_str(), region.length());
lua_rawseti(lua_state, -2, i++);
}
lua_settable(lua_state, -3);
}
}
return 0;
} }
return 0; return -1;
} }
static int _get_http_request_header(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
//printf("call get_http_request_header\n");
int ret = get_http_header(lua_state, HTTP_TYPE_REQUEST);
if(ret < 0){
lua_yieldk(lua_state, 0, 0, _get_http_request_header);
}
return 1;
}
static int get_http_request_header(lua_State* lua_state){
return _get_http_request_header(lua_state, 0, 0);
}
static int _get_http_response_header(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
int ret = get_http_header(lua_state, HTTP_TYPE_RESPONSE);
if(ret < 0){
lua_yieldk(lua_state, 0, 0, _get_http_response_header);
}
return 1;
}
static int get_http_response_header(lua_State* lua_state){
return _get_http_response_header(lua_state, 0, 0);
}
static int get_http_body(lua_State *lua_state, int type){
//printf("call _get_http_response_body\n");
lua_getglobal(lua_state, "cur_http_sess_ctx");
http_sess_ctx *sess_ctx = (http_sess_ctx *)lua_touserdata(lua_state, -1);
lua_pop(lua_state, 1);
if(sess_ctx == NULL){
//do log
std::cout<<"sess_ctx is null"<<std::endl;
return -1;
}
http_body& body = (type == HTTP_TYPE_REQUEST? sess_ctx->req_body : sess_ctx->resp_body);
if(body.data_end == true || body.buf != nullptr){
lua_newtable(lua_state);
lua_push_string_buffer(lua_state, "block_id", std::string("block_id").length());
lua_pushinteger(lua_state, body.block_id);
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "data_end", std::string("data_end").length());
lua_pushboolean(lua_state, body.data_end);
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "buf", std::string("buf").length());
lua_pushlightuserdata(lua_state, body.buf);
lua_settable(lua_state, -3);
lua_push_string_buffer(lua_state, "buflen", std::string("buflen").length());
lua_pushinteger(lua_state, body.buflen);
lua_settable(lua_state, -3);
body.buf = nullptr;
body.buflen = 0;
return 0;
}
return -1;
}
static int _get_http_request_body(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
int ret = get_http_body(lua_state, HTTP_TYPE_REQUEST);
if(ret < 0){
lua_yieldk(lua_state, 0, 0, _get_http_request_body);
}
return 1;
}
static int get_http_request_body(lua_State* lua_state){
return _get_http_request_body(lua_state, 0, 0);
}
static int _get_http_response_body(lua_State *lua_state, int status, lua_KContext yieldk_ctx){
int ret = get_http_body(lua_state, HTTP_TYPE_RESPONSE);
if(ret < 0){
lua_yieldk(lua_state, 0, 0, _get_http_response_body);
}
return 1;
}
static int get_http_response_body(lua_State* lua_state){
return _get_http_response_body(lua_state, 0, 0);
}
static int load_lua_plug(const char *profile){ static int load_lua_plug(const char *profile){
std::unordered_map<std::string, int> type_map = { std::unordered_map<std::string, int> type_map = {
{"ip", LUA_ENTRY_TYPE_IP}, {"ip", LUA_ENTRY_TYPE_IP},
@@ -105,40 +234,40 @@ static int load_lua_plug(const char *profile){
{"dns", LUA_ENTRY_TYPE_DNS}, {"dns", LUA_ENTRY_TYPE_DNS},
{"mail", LUA_ENTRY_TYPE_MAIL}, {"mail", LUA_ENTRY_TYPE_MAIL},
{"ftp", LUA_ENTRY_TYPE_FTP} {"ftp", LUA_ENTRY_TYPE_FTP}
}; };
std::unordered_map<std::string, int> dir_map{
{"c2s", DIR_C2S},
{"s2c", DIR_S2C},
{"all", DIR_DOUBLE}
};
const char *section = "main"; const char *section = "main";
char file_path[LUA_SAPP_PATH_MAX] = ""; char file_path[LUA_SAPP_PATH_MAX] = "";
char entry_type[LUA_SAPP_SYMBOL_MAX] = ""; char entry_type[LUA_SAPP_SYMBOL_MAX] = "";
char dir[LUA_SAPP_SYMBOL_MAX] = "";
char regions[LUA_SAPP_STRING_MAX] = "";
MESA_load_profile_string_def(profile, section, "file_path", file_path, sizeof(file_path), ""); MESA_load_profile_string_def(profile, section, "file_path", file_path, sizeof(file_path), "");
MESA_load_profile_string_def(profile, section, "entry_type", entry_type, sizeof(entry_type), "http"); MESA_load_profile_string_def(profile, section, "entry_type", entry_type, sizeof(entry_type), "http");
MESA_load_profile_string_def(profile, section, "dir", dir, sizeof(dir), "all");
MESA_load_profile_string_def(profile, section, "regions", regions, sizeof(regions), "all");
lua_State *lua_state = luaL_newstate(); lua_State *lua_state = luaL_newstate();
if(lua_state == NULL){
printf("failed to LuaL_newstate\n");
return -1;
}
luaL_openlibs(lua_state); luaL_openlibs(lua_state);
luaL_dofile(lua_state, file_path); int ret = luaL_dofile(lua_state, file_path);
lua_register(lua_state, "get_http_headers", get_http_headers); if(ret){
lua_getglobal(lua_state, "main"); //log error
printf("error: ret is %d, file_path is %s\n", ret, file_path);
return -1;
}
//TODO: what if not register, rusume handle error
lua_register(lua_state, "get_stream_info", get_stream_info);
lua_register(lua_state, "get_http_request_header", get_http_request_header);
lua_register(lua_state, "get_http_response_header", get_http_response_header);
lua_register(lua_state, "get_http_request_body", get_http_request_body);
lua_register(lua_state, "get_http_response_body", get_http_response_body);
lua_plug plug; lua_plug plug;
plug.file_path = std::string(file_path); plug.file_path = std::string(file_path);
plug.entry_type = (enum lua_entry_type)type_map[std::string(entry_type)]; plug.entry_type = (enum lua_entry_type)type_map[std::string(entry_type)];
plug.dir = dir_map[std::string(dir)];
regions_parse(regions, plug.regions);
plug.lua_state = lua_state; plug.lua_state = lua_state;
g_lua_plugs[plug.entry_type].push_back(plug); g_lua_plugs[plug.entry_type].push_back(plug);
lua_resume(lua_state, NULL, 0);
return 0; return 0;
} }
int process_lua_plug_conflist(const char* filename) static int process_lua_plug_conflist(const char* filename)
{ {
char lua_plug_conf_path[LUA_SAPP_PATH_MAX] = {0}; char lua_plug_conf_path[LUA_SAPP_PATH_MAX] = {0};
FILE* fp = fopen(filename, "r"); FILE* fp = fopen(filename, "r");
@@ -157,7 +286,10 @@ int process_lua_plug_conflist(const char* filename)
} }
int len = strnlen(lua_plug_conf_path, LUA_SAPP_PATH_MAX); int len = strnlen(lua_plug_conf_path, LUA_SAPP_PATH_MAX);
lua_plug_conf_path[len - 1] = '\0'; lua_plug_conf_path[len - 1] = '\0';
load_lua_plug(lua_plug_conf_path); int ret = load_lua_plug(lua_plug_conf_path);
if(ret < 0){
printf("failed to load_lua_plug: conf_path is %s\n", lua_plug_conf_path);
}
} }
fclose(fp); fclose(fp);
fp=NULL; fp=NULL;
@@ -166,6 +298,17 @@ int process_lua_plug_conflist(const char* filename)
static http_sess_ctx* init_http_sess_ctx(){ static http_sess_ctx* init_http_sess_ctx(){
http_sess_ctx *ctx = new http_sess_ctx(); http_sess_ctx *ctx = new http_sess_ctx();
for(lua_plug plug : g_lua_plugs[LUA_ENTRY_TYPE_HTTP]){
lua_State* lua_state = plug.lua_state;
lua_State* coroutine = lua_newthread(lua_state);
int ret = lua_checkstack(lua_state, 1);
if(ret != 1){
//do log
printf("do not have enough space, ret is %d\n", ret);
break;
}
ctx->coroutines.push_back(coroutine);
}
return ctx; return ctx;
} }
@@ -174,38 +317,41 @@ static void clear_http_sess_ctx(http_sess_ctx *ctx){
ctx = NULL; ctx = NULL;
} }
static std::string trans_to_binary(unsigned int n){
std::string res;
while(n){
res = std::to_string(n % 2) + res;
n /= 2;
}
return res;
}
static void output_stack_size(lua_State *lua_state){ std::string utils_inet_ntoa(uint32_t ip)
int n = lua_gettop(lua_state); {
std::cout<<"stack size is "<<n<<std::endl; const char *_ip = inet_ntoa(*(struct in_addr *)&ip);
return std::string(_ip);
} }
uchar NEW_HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thread_seq, struct streaminfo *a_tcp, void *a_packet){ uchar NEW_HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thread_seq, struct streaminfo *a_tcp, void *a_packet){
uchar rec = PROT_STATE_GIVEME; uchar ret = PROT_STATE_GIVEME;
http_sess_ctx *ctx = (http_sess_ctx*)*param; http_sess_ctx *ctx = (http_sess_ctx*)*param;
http_infor *a_http = (http_infor *)(session_info->app_info); http_infor *a_http = (http_infor *)(session_info->app_info);
//static int header_len = 0; bool stream_begin = false;
//static int content_len = 0; if(session_info == nullptr){
if(NULL==session_info){
return PROT_STATE_DROPME; return PROT_STATE_DROPME;
} }
if(ctx == NULL){ if(ctx == nullptr){
ctx = init_http_sess_ctx(); ctx = init_http_sess_ctx();
*param = ctx; *param = ctx;
stream_begin = true;
} }
std::string prot_flag_str = trans_to_binary(session_info->prot_flag); if(ctx->tuple5.parse_done == false){
//MESA_handle_runtime_log(g_logger, RLOG_LV_INFO, HTTP_SERVICE_PLUGNAME, struct stream_tuple4_v4 *tuple4_v4 = a_tcp->addr.tuple4_v4;
// "call http_service entry, http_state is %02x\n, prot_flag mask is %s : %d", http_state, prot_flag_str.c_str(), prot_flag_str.length() - 1); ctx->tuple5.ip_version = "IPV4";
std::string temp = (a_http->http_state == HTTP_DATA_BEGIN) ? "data begin" : "not data begin"; if(a_tcp->type == STREAM_TYPE_TCP){
//curdir: request or response ctx->tuple5.stream_type = "TCP";
}
if(a_tcp->type == STREAM_TYPE_UDP){
ctx->tuple5.stream_type = "UDP";
}
ctx->tuple5.sip = utils_inet_ntoa(tuple4_v4->saddr);
ctx->tuple5.dip = utils_inet_ntoa(tuple4_v4->daddr);
ctx->tuple5.sport = ntohs(tuple4_v4->source);
ctx->tuple5.dport = ntohs(tuple4_v4->dest);
ctx->tuple5.parse_done = true;
}
uchar curdir = a_http->curdir; uchar curdir = a_http->curdir;
switch(session_info->prot_flag) switch(session_info->prot_flag)
{ {
@@ -213,38 +359,92 @@ uchar NEW_HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thre
case HTTP_CONTENT: case HTTP_CONTENT:
break; break;
case HTTP_UNGZIP_CONTENT: case HTTP_UNGZIP_CONTENT:
//fwrite(session_info->buf, session_info->buflen, 1, service_pme->fp); if(curdir == DIR_C2S){
//fflush(service_pme->fp); ctx->req_body.block_id++;
ctx->req_body.buf = session_info->buf;
ctx->req_body.buflen = session_info->buflen;
}
if(curdir == DIR_S2C){
ctx->resp_body.block_id++;
ctx->resp_body.buf = session_info->buf;
ctx->resp_body.buflen = session_info->buflen;
}
break; break;
default: default:
std::string key(http_proto_flag2region(session_info->prot_flag)); std::string key(http_proto_flag2region(session_info->prot_flag));
std::string value((const char*)(session_info->buf), session_info->buflen); std::string value((const char*)(session_info->buf), session_info->buflen);
if(curdir == DIR_C2S){ if(curdir == DIR_C2S){
ctx->request_headers.insert({key, value}); if(key == "HTTP_OTHER_REGIONS"){
ctx->req_header.other_regions.insert(value);
}
else{
ctx->req_header.std_regions.insert({key, value});
}
} }
else{ else{
ctx->response_headers.insert({key, value}); if(key == "HTTP_OTHER_REGIONS"){
ctx->resp_header.other_regions.insert(value);
}
else{
ctx->resp_header.std_regions.insert({key, value});
}
} }
break; break;
} }
uchar http_state = a_http->http_state; uchar http_state = a_http->http_state;
//header over, resume lua //printf("curdir is %d, http_state is %d\n", curdir, http_state);
//header over
if(http_state == HTTP_DATA_BEGIN){ if(http_state == HTTP_DATA_BEGIN){
for(auto plug : g_lua_plugs[LUA_ENTRY_TYPE_HTTP]){ if(curdir == DIR_C2S){
if(plug.dir == DIR_DOUBLE || plug.dir == curdir){ ctx->req_header.parse_done = true;
lua_pushlightuserdata(plug.lua_state, (void *)ctx); }
lua_setglobal(plug.lua_state, "cur_http_sess_ctx"); if(curdir == DIR_S2C){
lua_pushinteger(plug.lua_state, curdir); ctx->resp_header.parse_done = true;
lua_setglobal(plug.lua_state, "cur_http_sess_dir");
lua_resume(plug.lua_state, NULL, 0);
}
} }
} }
//data over
if(http_state == HTTP_DATA_END){
if(curdir == DIR_C2S){
ctx->req_body.data_end = true;
}
if(curdir == DIR_S2C){
ctx->resp_body.data_end = true;
}
}
//resume coroutine
for(lua_State*& coroutine : ctx->coroutines){
if(coroutine == nullptr){
continue;
}
/*
int ret = lua_checkstack(coroutine, 1);
if(ret != 1){
//do log
printf("do not have enough space, ret is %d\n", ret);
continue;
}
*/
lua_pushlightuserdata(coroutine, (void *)ctx);
lua_setglobal(coroutine, "cur_http_sess_ctx");
if(stream_begin){
lua_getglobal(coroutine, "process");
}
ret = lua_resume(coroutine, NULL, 0);
if(ret == LUA_OK){
coroutine = nullptr;
continue;
}
if(ret != LUA_YIELD){
lua_traceback("lua_resume", coroutine, ret);
coroutine = nullptr;
}
}
if(session_info->session_state & SESSION_STATE_CLOSE){ if(session_info->session_state & SESSION_STATE_CLOSE){
//printf("close tcp stream\n");
clear_http_sess_ctx(ctx); clear_http_sess_ctx(ctx);
*param = NULL; *param = NULL;
} }
return rec; return ret;
} }
int NEW_HTTP_SERVICE_INIT(void) int NEW_HTTP_SERVICE_INIT(void)
@@ -254,7 +454,7 @@ int NEW_HTTP_SERVICE_INIT(void)
printf("%s init : get log handle error!\n", HTTP_SERVICE_PLUGNAME); printf("%s init : get log handle error!\n", HTTP_SERVICE_PLUGNAME);
return -1; return -1;
} }
// get thread num
// get all business lua script which register http // get all business lua script which register http
const char *conflist_path = "./plug/lua/conflist_lua.inf"; const char *conflist_path = "./plug/lua/conflist_lua.inf";
if(g_lua_plugs[LUA_ENTRY_TYPE_HTTP].size() == 0){ if(g_lua_plugs[LUA_ENTRY_TYPE_HTTP].size() == 0){
@@ -265,6 +465,9 @@ int NEW_HTTP_SERVICE_INIT(void)
void NEW_HTTP_SERVICE_DESTROY(void) void NEW_HTTP_SERVICE_DESTROY(void)
{ {
for(auto plug : g_lua_plugs[LUA_ENTRY_TYPE_HTTP]){
lua_close(plug.lua_state);
}
return ; return ;
} }

View File

@@ -38,13 +38,71 @@ extern "C" {
#define HTTP_SERVICE_PLUGNAME "new_http_service.so" #define HTTP_SERVICE_PLUGNAME "new_http_service.so"
#define LOG_PATH "./log/new_http_service/" #define LOG_PATH "./log/new_http_service/"
#define LOG_MODULE_NAME "SAPP_LUA"
#define LUA_SAPP_SYMBOL_MAX 64
#define LUA_SAPP_PATH_MAX 256
#define LUA_SAPP_STRING_MAX 2048
#define LUA_ENTRY_TYPE_NUM 8
enum lua_entry_type{
LUA_ENTRY_TYPE_IP = 0,
LUA_ENTRY_TYPE_TCP,
LUA_ENTRY_TYPE_UDP,
LUA_ENTRY_TYPE_HTTP,
LUA_ENTRY_TYPE_TLS,
LUA_ENTRY_TYPE_DNS,
LUA_ENTRY_TYPE_MAIL,
LUA_ENTRY_TYPE_FTP
};
enum http_type{
HTTP_TYPE_REQUEST = 0,
HTTP_TYPE_RESPONSE
};
class http_header{
public:
bool parse_done;
std::unordered_map<std::string, std::string> std_regions;
std::unordered_set<std::string> other_regions;
http_header() : parse_done(false){}
};
class http_body{
public:
bool data_end;
int block_id;
void *buf;
int buflen;
http_body() : data_end(false), block_id(-1), buf(nullptr), buflen(0){}
};
class stream_tuple5{
public:
bool parse_done;
std::string ip_version; //IPV4 or IPV6
std::string stream_type; //TCP or UDP
std::string sip;
std::string dip;
uint16_t sport;
uint16_t dport;
stream_tuple5() : parse_done(false){}
};
class http_sess_ctx{ class http_sess_ctx{
public: public:
std::unordered_map<std::string, std::string> request_headers; stream_tuple5 tuple5;
std::unordered_map<std::string, std::string> response_headers; http_header req_header;
http_header resp_header;
http_body req_body;
http_body resp_body;
std::vector<lua_State*> coroutines;
}; };
class lua_plug{
public:
std::string file_path;
enum lua_entry_type entry_type;
lua_State *lua_state;
};
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@@ -0,0 +1,87 @@
function printf(s,...)
io.write(s:format(...))
io.flush()
end
function format_write_file(file, s, ...)
file:write(s:format(...))
file:flush()
end
function init()
---init something
end
function print_header(header)
for k, v in pairs(header) do
if k == "HTTP_OTHER_REGIONS" then
format_write_file(file, "%s: ", k)
for k, v in pairs(header["HTTP_OTHER_REGIONS"]) do
format_write_file(file, "{%s} ", v)
end
format_write_file(file, "\n")
else
format_write_file(file, "%s: %s\n", k, v)
end
end
end
function process()
printf("\nprint stream: \n")
stream_info = get_stream_info()
for k, v in pairs(stream_info) do
printf("%s: %s\n", k, v)
end
printf("\nprint header:\n")
local regions = {"ALL"}
header = get_http_request_header(regions)
for k, v in pairs(header) do
printf("%s: %s\n", k, v)
end
printf("\nprint body: \n")
while true do
body = get_http_request_body()
for k, v in pairs(body) do
printf("%s: %s\n", k, v)
end
if body['data_end'] == true then
break
end
end
--[[
file = io.open("./log/lua/http_request.log", "a+")
format_write_file(file, "lua: call process\n")
format_write_file(file, "\nprint stream info: \n")
stream_info = get_stream_info()
for k, v in pairs(stream_info) do
format_write_file(file, "%s: %s\n", k, v)
end
format_write_file(file, "\nprint request headers: \n")
local req_regions = {"HTTP_HOST", "HTTP_REQ_LINE", "HTTP_OTHER_REGIONS"}
req_header = get_http_request_header(req_regions)
print_header(req_header)
format_write_file(file, "\nprint request body: \n")
while true do
body = get_http_request_body()
for k, v in pairs(body) do
format_write_file(file, "%s: %s\n", k, v)
end
if body['data_end'] == true then
format_write_file(file, "request body end\n")
break
end
format_write_file(file, "\n");
end
format_write_file(file, "\nlua: process end\n")
io.close(file)
]]
end

View File

@@ -0,0 +1,57 @@
function printf(s,...)
io.write(s:format(...))
io.flush()
end
function format_write_file(file, s, ...)
file:write(s:format(...))
file:flush()
end
function init()
---init something
end
function print_header(header)
for k, v in pairs(header) do
if k == "HTTP_OTHER_REGIONS" then
format_write_file(file, "%s: ", k)
for k, v in pairs(header["HTTP_OTHER_REGIONS"]) do
format_write_file(file, "{%s} ", v)
end
format_write_file(file, "\n")
else
format_write_file(file, "%s: %s\n", k, v)
end
end
end
function process()
file = io.open("./log/lua/http_response.log", "a+")
format_write_file(file, "lua: call process\n")
format_write_file(file, "\nprint stream info: \n")
stream_info = get_stream_info()
for k, v in pairs(stream_info) do
format_write_file(file, "%s: %s\n", k, v)
end
local resp_regions = {"HTTP_SERVER", "HTTP_RES_LINE", "HTTP_OTHER_REGIONS"}
format_write_file(file, "\nprint response headers: \n")
resp_header = get_http_response_header(resp_regions)
print_header(resp_header)
format_write_file(file, "\nprint response body: \n")
while true do
body = get_http_response_body()
for k, v in pairs(body) do
format_write_file(file, "%s: %s\n", k, v)
end
if body['data_end'] == true then
format_write_file(file, "response body end\n")
break
end
end
format_write_file(file, "\nlua: process end\n")
end

View File

@@ -1,14 +0,0 @@
function main()
while true do
headers = get_http_request_headers(ctx)
for k, v in pairs(headers) do
print(k, v)
end
end
end
function main()
headers = get_http_request_headers()
content = get_http_content()
---handle

View File

@@ -1,6 +1,9 @@
#include <iostream> #include <iostream>
#include <cstring>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <vector> #include <vector>
#include <unordered_set>
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
extern "C" { extern "C" {
@@ -9,9 +12,50 @@ extern "C" {
#include "lauxlib.h" #include "lauxlib.h"
} }
static void output_stack_size(lua_State *L){ static void output_stack_size(lua_State *L, int line){
int n = lua_gettop(L); int n = lua_gettop(L);
cout<<"stack size is "<<n<<endl; printf("line %d: stack size is %d\n", line, n);
for(int i = -1; i >= 0 - n; i--){
string type = string(lua_typename(L, lua_type(L, i)));
string value = "unknown";
if(type == "string"){
value = lua_tostring(L, i);
}
printf("index is %d, type is %s, value is %s\n", i, type.c_str(), value.c_str());
}
}
static void lua_traceback(const char *func_name, lua_State *L){
int n = lua_gettop(L);
printf("%s error: stack size is %d, traceback is:\n", func_name, n);
for(int i = -1; i >= 0 - n; i--){
string type = string(lua_typename(L, lua_type(L, i)));
if(type == "string"){
printf("%s\n", lua_tostring(L, i));
}
}
lua_pop(L, n);
}
//copy from suricata
static int lua_push_string_buffer(lua_State *lua_state, const char *input, size_t input_len)
{
if (input_len % 4 != 0) {
/* we're using a buffer sized at a multiple of 4 as lua_pushlstring generates
* invalid read errors in valgrind otherwise. Adding in a nul to be sure.
* Buffer size = len + 1 (for nul) + whatever makes it a multiple of 4 */
size_t buflen = input_len + 1 + ((input_len + 1) % 4);
char buf[buflen];
memset(buf, 0x00, buflen);
memcpy(buf, input, input_len);
buf[input_len] = '\0';
/* return value through lua_state, as a luastring */
lua_pushlstring(lua_state, buf, input_len);
} else {
lua_pushlstring(lua_state, input, input_len);
}
return 1;
} }
static void test_coroutine(int argc, char *argv[]){ static void test_coroutine(int argc, char *argv[]){
@@ -58,7 +102,7 @@ static void test_coroutine(int argc, char *argv[]){
static int foo (lua_State *L) { static int foo (lua_State *L) {
cout<<"call foo"<<endl; cout<<"call foo"<<endl;
output_stack_size(L); output_stack_size(L, 84);
lua_Number sum = 0.0; lua_Number sum = 0.0;
int n = lua_gettop(L); int n = lua_gettop(L);
for (int i = 1; i <= n; i++) { for (int i = 1; i <= n; i++) {
@@ -71,10 +115,10 @@ static int foo (lua_State *L) {
} }
printf("sum is %f\n", sum); printf("sum is %f\n", sum);
lua_pop(L, n); lua_pop(L, n);
output_stack_size(L); output_stack_size(L, 97);
lua_pushnumber(L, sum/n); //first result lua_pushnumber(L, sum/n); //first result
lua_pushnumber(L, sum); //second result lua_pushnumber(L, sum); //second result
output_stack_size(L); output_stack_size(L, 100);
return 2; //number of results return 2; //number of results
} }
@@ -83,8 +127,41 @@ static int foo2(lua_State *L, int n, long int m){
return 0; return 0;
} }
static int foo1(lua_State *L){ int flag = 0;
static int _foo1(lua_State *L, int status, lua_KContext yieldk_ctx){
printf("call foo1\n");
output_stack_size(L, 121);
/*
unordered_set<string> regions;
output_stack_size(L); output_stack_size(L);
lua_pushnil(L);
while(lua_next(L, -2) != 0){
printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1)));
regions.insert(string(lua_tostring(L, -1)));
lua_pop(L, 1);
}
for(auto region : regions)
cout<<region<<endl;
output_stack_size(L);
*/
//lua_pop(L, 1);
if(flag == 1){
lua_newtable(L);
lua_push_string_buffer(L, "name", 4);
lua_newtable(L);
lua_push_string_buffer(L, "leo", 3);
lua_rawseti(L, -2, 1);
lua_push_string_buffer(L, "cui", 3);
lua_rawseti(L, -2, 2);
lua_settable(L, -3);
return 1;
}
lua_yieldk(L, 0, 0, _foo1);
}
static int foo1(lua_State *L){
return _foo1(L, 0, 0);
/* /*
lua_getglobal(L, "g_http_sess_ctx"); lua_getglobal(L, "g_http_sess_ctx");
output_stack_size(L); output_stack_size(L);
@@ -102,7 +179,8 @@ static void test_lua_CFunction(){
const char *filename = "../../test/test_coroutine/test.lua"; const char *filename = "../../test/test_coroutine/test.lua";
lua_State *L = luaL_newstate(); lua_State *L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
luaL_dofile(L, filename); int ret = luaL_dofile(L, filename);
printf("luaL_dofile, ret is %d\n", ret);
lua_register(L, "myfoo", foo1); lua_register(L, "myfoo", foo1);
lua_getglobal(L, "lua_call_c"); lua_getglobal(L, "lua_call_c");
/* /*
@@ -119,8 +197,24 @@ static void test_lua_CFunction(){
//lua_pushinteger(L, 2); //lua_pushinteger(L, 2);
//lua_pushinteger(L, 3); //lua_pushinteger(L, 3);
*/ */
lua_resume(L, NULL, 0); //output_stack_size(L);
cout<<"cpp: atfer lua_call"<<endl;
ret = lua_resume(L, NULL, 0);
if(ret != LUA_OK && ret != LUA_YIELD){
lua_traceback("lua_resume", L);
return;
}
printf("lua resume: ret is %d\n", ret);
//output_stack_size(L, 190);
//flag = 1;
ret = lua_resume(L, NULL, 0);
printf("lua resume: ret is %d\n", ret);
output_stack_size(L, 194);
//printf("lua_resume: ret is %d\n", ret);
//cout<<"cpp: atfer lua_call"<<endl;
//lua_resume(L, NULL, 0); //lua_resume(L, NULL, 0);
} }

View File

@@ -1,8 +1,11 @@
function printf(s,...)
io.write(s:format(...))
end
printf = function(s,...) format_write = function(file, s, ...)
return io.write(s:format(...)) return file:write(s:format(...))
end end
function test(id) function test(id)
i = 0 i = 0
@@ -47,8 +50,14 @@ function main()
end end
function lua_call_c() function lua_call_c()
---printf("lua: call lua_call_c\n")
printf("lua: call lua_call_c\n") t = {"aa", "bb", "cc"}
myfoo() file = io.open("./output.txt", "a+")
printf("lua: after my_foo\n") format_write(file, "%s: %d", "age", 12)
end ret = myfoo(t)
for k, v in pairs(ret["name"]) do
print(k, v)
end
---printf("lua: after my_foo\n")
end

View File

@@ -48,8 +48,25 @@ std::string trans_to_binary(unsigned int n){
return res; return res;
} }
std::string _inet_ntoa(uint32_t ip)
{
const char *_ip = inet_ntoa(*(struct in_addr *)&ip);
return std::string(_ip);
}
static int get_stream_tuple4(struct streaminfo *a_tcp){
struct stream_tuple4_v4 *tuple4_v4 = a_tcp->addr.tuple4_v4;
printf("saddr: %s\n", _inet_ntoa(tuple4_v4->saddr).c_str());
printf("daddr: %s\n", _inet_ntoa(tuple4_v4->daddr).c_str());
printf("source: %d\n", ntohs(tuple4_v4->source));
printf("dest: %d\n", ntohs(tuple4_v4->dest));
return 0;
}
uchar HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thread_seq, struct streaminfo *a_tcp, void *a_packet) uchar HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thread_seq, struct streaminfo *a_tcp, void *a_packet)
{ {
//get_stream_tuple4(a_tcp);
uchar rec = PROT_STATE_GIVEME; uchar rec = PROT_STATE_GIVEME;
service_pmeinfo *service_pme = (service_pmeinfo*)*param; service_pmeinfo *service_pme = (service_pmeinfo*)*param;
http_infor *a_http = (http_infor *)(session_info->app_info); http_infor *a_http = (http_infor *)(session_info->app_info);
@@ -74,8 +91,17 @@ uchar HTTP_SERVICE_ENTRY(stSessionInfo* session_info, void **param, int thread_s
*param = service_pme; *param = service_pme;
} }
std::string prot_flag_str = trans_to_binary(session_info->prot_flag); std::string prot_flag_str = trans_to_binary(session_info->prot_flag);
uchar curdir = a_http->curdir;
printf("curdir is %d, http_state is %d\n", curdir, http_state);
/*
MESA_handle_runtime_log(g_log_handle, RLOG_LV_INFO, HTTP_SERVICE_PLUGNAME, MESA_handle_runtime_log(g_log_handle, RLOG_LV_INFO, HTTP_SERVICE_PLUGNAME,
"call http_service entry, http_state is %02x\n, prot_flag mask is %s : %d", http_state, prot_flag_str.c_str(), prot_flag_str.length() - 1); "call http_service entry, http_state is %02x\n, prot_flag mask is %s : %d", http_state, prot_flag_str.c_str(), prot_flag_str.length() - 1);
if(curdir == DIR_C2S){
int i = 0;
printf("data begin: curdir is %d, http_state is %d, prot_flag mask is %d\n", curdir, http_state, prot_flag_str.length() - 1);
}
*/
switch(session_info->prot_flag) switch(session_info->prot_flag)
{ {
case HTTP_STATE: case HTTP_STATE: