First of all, there is a need to advertise, Qtun's website has been opened, the function is gradually added.
First, the reason for embedding Lua
Because of the increasing number of configurable parameters of the Qtun, it is necessary to write parameters to the configuration file. And because C is not good at string processing, it has added a lightweight Lua scripting language, while embedding Lua is more useful for adding support for third-party plug-ins.
Second, the code changes
- Wrapper initialization function
extern int Init_path (char* cmd), extern int Init_lua (), extern void Show_logo (), extern void Conf_init (library_conf_t* conf );
- The path where the Qtun program is passed into the Init_path and is converted to Realpath after it is recorded in Qtun->this_path
- Init_lua creates a Lua_state object and invokes the Scripts/qtun.lua script to initialize it, and finally calls the Script_global_init function to initialize the LUA environment
- Show_logo call the Scripts/logo.lua script to print out the Qtun logo ^o^
- Set the initial value for the incoming conf variable in Conf_init, such as the default port of 6687, etc.
- The Script_global_init function Script_global_init function is called during Init_lua to initialize the LUA environment
int Script_global_init (lua_state* lua) { load_lib (lua, "_g", luaopen_base); Load_lib (LUA, Lua_tablibname, luaopen_table); Load_lib (LUA, Lua_strlibname, luaopen_string); Load_lib (LUA, Lua_iolibname, luaopen_io); Lua_pushcfunction (LUA, _syslog); Lua_setglobal (LUA, "_syslog"); Init_qtun_state (LUA); Init_qtun_conf (LUA); Init_qtun_log (LUA); return 1;}
- Here, first load the base Lua library
- Then join the Custom function _syslog
- Create Qtun.state, qtun.conf, and Qtun.log objects by LUA.MD documents that all properties in Qtun.state are read-only, Qtun.conf.conf_file properties are read-only, and others are readable and writable. Some log level definitions for syslog are included in the Qtun.log.
- Let's take a look at the implementation of these three functions
static void Init_qtun_state (lua_state* lua) {get_qtun_obj (LUA); Lua_pushstring (LUA, "state"); Lua_newtable (LUA); Lua_newtable (LUA); Lua_pushstring (LUA, "__index"); Lua_pushcfunction (LUA, state_get); Lua_settable (LUA,-3); Lua_setmetatable (LUA,-2); Lua_settable (LUA,-3); Lua_pop (LUA, 1);} static void init_qtun_conf (lua_state* lua) {get_qtun_obj (LUA); Lua_pushstring (LUA, "conf"); Lua_newtable (LUA); Lua_newtable (LUA); Lua_pushstring (LUA, "__index"); Lua_pushcfunction (LUA, conf_get); Lua_settable (LUA,-3); Lua_pushstring (LUA, "__newindex"); Lua_pushcfunction (LUA, conf_set); Lua_settable (LUA,-3); Lua_setmetatable (LUA,-2); Lua_settable (LUA,-3); Lua_pop (LUA, 1);} static void Init_qtun_log (lua_state* lua) {int new_log = 0; Get_qtun_obj (LUA); Lua_pushstring (LUA, "log"); Lua_gettable (LUA,-2); if (Lua_isnil (LUA,-1)) {Lua_pop (LUA, 1); Lua_pushstring (LUA, "log"); Lua_newtAble (LUA); New_log = 1; } push_log_level (Lua, "Log_emerg", 0); Push_log_level (LUA, "Log_alert", 1); Push_log_level (LUA, "Log_crit", 2); Push_log_level (LUA, "Log_err", 3); Push_log_level (LUA, "log_warning", 4); Push_log_level (LUA, "Log_notice", 5); Push_log_level (LUA, "Log_info", 6); Push_log_level (LUA, "Log_debug", 7); if (New_log) lua_settable (LUA,-3); Lua_pop (LUA, 1); }
From the code: Qtun.state and qtun.conf map C objects to Lua through MetaTable, and only the constants of the log level are defined in Qtun.log
- Script_load_config function script_load_config function load configuration file by calling Scripts/load_config.lua script
int Script_load_config (lua_state* lua, library_conf_t* conf, const char* file_path) { char path[max_path]; Lua_pushlightuserdata (LUA, conf); Lua_setglobal (LUA, "__conf__"); strcpy (path, qtun->this_path); strcat (Path, "Scripts/load_config.lua"); if (Lual_dofile (LUA, path)! = 0) { fprintf (stderr, "%s\n", Lua_tostring (Qtun->lua,-1)); Lua_close (Qtun->lua); Exit (1); } return 1;}
- Let's take a look at the whole process of the main function
Third, Lua script
Finally, let's take a look at the three Lua scripts.
- Logo.lua
Print (' ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ') print (' ┃ ... ..... . . . . ┃ ') print (' ┃ ... ┃ ') print (' ┃ ... ┃ ') print (' ┃ ..... ... . . ┃ ') print (' ┃ ┃ ') print (' ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ')
This logo is not very love ^_^
- Qtun.lua
Qtun = { log = { syslog = function (level, FMT, ...) _syslog (Level, String.Format (FMT, ...)) End }}function Trim (s) return s:gsub (' ^%s* (.-)%s*$ ', '%1 ') endfunction is_numeric (s) return Tonumber (s) ~= nilendfunction is_string (s) return not is_numeric (s) end
Some public functions are packaged here
- Load_config.lua
Local function Append_key_value (key, value) if value = = ' true ' then value = true ElseIf value = = ' false ' Then Value = False ElseIf is_numeric (value) then value = Tonumber (value) elseif key = = ' Log_level ' Then If is_string (value) then value = Qtun.log[value] End end Qtun.conf[key] = valueendlocal funct Ion Set_true (key) Qtun.conf[key] = trueendlocal file = Io.open (Qtun.conf.conf_file, ' R ') while True Do::start:: Local line = File:read (' *line ') if line = = nil and break end local len = #line local key = ' local first = ' Local start = 0 Local Have_key = False local Have_value = False local added = False local j = 0 for i=0 , len do j = i local ch = line:sub (i + 1, i + 1) if first = = "and ch ~=" then first = CH End If ch = = ' # ' then If Trim (line:sub (start, i)) = = ' Then goto start end Have_v Alue = True IF Have_key then Append_key_value (key, Trim (line:sub (start, i))) Else Set_true (tri M (line:sub (Start, i))) End added = True break ElseIf ch = = "Then key" = Trim (line:sub (start, i)) if key = = "Then error (' Missing key ') end hav E_key = True start = i + 2 end End If first = = ' # ' then goto start End If not added then If not Have_key then local key = Trim (Line:sub (Start, J)) if key = = "Then goto start end Set_true (key) Else append_key_value (key, Trim (Line:sub (Start, j))) End Endendfile:close ()
The primary logic for parsing the configuration file is here.
Iv. Complete code
Full code can be viewed in STEP14
Jump the Great Firewall "step14 embedded in Lua"