1. 頁面請求:1.1. 代碼結(jié)構(gòu)在openwrt文件系統(tǒng)中,lua語言的代碼不要編譯,類似一種腳本語言被執(zhí)行,還有一些uhttpd服務(wù)器的主目錄,它們是: /www/index.html cgi-bin/luci luci-static/xxx/xx.css、js、gif
/usr/lib/lua/nixio.so、uci.so luci/http.lua、dispatcher.lua、core… controller/xxx.lua model/xxx.lua view/xxx.lua 1.2. 界面顯示網(wǎng)頁請求格式基本都如下所示:http://10.10.82.238/cgi-bin/luci,說明處理都在服務(wù)器的默認網(wǎng)站下的/cgi-bin/luci文件進行處理。 1.2.1. /www/cgi-bin/luciluci.dispatcher.indexcache = "/tmp/luci-indexcache"--緩存文件位置“/tmp/luci-indexcache” luci.sgi.cgi.run()--cgi程序接下來執(zhí)行程序,Luci的默認路徑是/usr/lib/lua/luci,所以luci.sgi.cgi.run()是運行/usr/lib/lua/luci/sgi/cgi.lua文件中的run函數(shù)。 1.2.2. /usr/lib/lua/luci/sgi/cgi.lualocal r = luci.http.Request(…)--把web請求放于r中(包括環(huán)境變量,web請求,出錯處理接口) local x = coroutine.create(luci.dispatcher.httpdispatch)--創(chuàng)建一個協(xié)同程序 local res, id, data1, data2 = coroutine.resume(x, r)--運行上面創(chuàng)建的協(xié)同程序,即運行httpdispatch,參數(shù)為上面local r里的變量。 if active then if id == 1 then io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\r\n") elseif id == 2 then hcache = hcache .. data1 .. ": " .. data2 .. "\r\n"—準備header elseif id == 3 then--寫header、blank io.write(hcache)—默認到stdout io.write("\r\n") elseif id == 4 then io.write(tostring(data1 or ""))--寫body elseif id == 5 then io.flush() io.close()--EOF active = false elseif id == 6 then data1:copyz(nixio.stdout, data2) data1:close() 1.2.3. /usr/lib/lua/luci/dispatcher.luahttpdispatch:解析請求,獲得請求節(jié)點,并調(diào)用dispatch處理請求節(jié)點,如: Request :http://10.10.82.238/cgi-bin/luci/;stok=e10fa5c70fbb55d478eb8b8a2eaabc6f/admin/network/firewall/ get: admin network firewall
dispatch:四個部分處理請求 A.節(jié)點樹node-tree創(chuàng)立 if not c then c = createtree() B.需要顯示的部分 if (c and c.index) or not track.notemplate then C.認證 if track.sysauth then D.顯示/處理 ok, err = util.copcall(target, c.target, unpack(args)) 1.2.4. 請求頁面networkhttp://10.10.82.238/cgi-bin/luci/;stok=4b77c83a89c7b9cd8f4dcc0fcbc28024/admin/network/
1.2.3中D顯示部分與entry()函數(shù)(形如entry(path,target,title,order))有關(guān),其中定義的target方法或者target部分。在以上http請求中會根據(jù)請求路徑去訪問到/usr/lib/lua/luci/controller/admin/network.lua,調(diào)用順序如下: ok, err = util.copcall(target, unpack(args))-- dispatcher.luaà page.target = firstchild() -- network.luaà function firstchild()-- dispatcher.luaà _firstchild()-- dispatcher.luaàdispatch(path)-- 自動鏈接到它的第一個子節(jié)點, 在network.lua中定義order,Interfaces是10,為第一個子節(jié)點: page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), _("Interfaces"), 10)--通過cbi方法處理admin_network/ifaces.lua和admin_network/network.lua,生成html文件 2. 頁面響應(yīng)2.1. Web請求當點擊頁面“Save & Apply”按鈕時,瀏覽器會把每一個有name的web元素的對應(yīng)值下傳,下傳form表格如下:
-----------------------------151563007122428 Content-Disposition: form-data; name="cbi.submit" 1 -----------------------------151563007122428 Content-Disposition: form-data; name="cbi.cbe.firewall.cfg02e63d.syn_flood" 1 -----------------------------151563007122428 Content-Disposition: form-data; name="cbi.cbe.firewall.cfg02e63d.drop_invalid" 1 …… …… -----------------------------151563007122428 Content-Disposition: form-data; name="cbi.apply" Save & Apply -----------------------------151563007122428— 2.2. 處理服務(wù)器處理過程和頁面生成基本類似,也調(diào)用到/usr/lib/lua/luci/dispatcher.lua并走到顯示/處理部分,后繼處理如下: ok, err = util.copcall(target, c.target, unpack(args)) à(target在luci/controller/firewall中被賦值為arcombine(cbi("firewall/zones"), cbi("firewall/zone-details")),即兩個cbi函數(shù)的集合) function cbi(model, config) à local function _cbi(self, ...) à local cstate = res:parse()à function Map.parse(self, readinput, ...) à Node.parse(self, ...) Node.parse會調(diào)用Map中的每一個子元素自身的處理
EX: 如調(diào)用Flag的處理:function Flag.parse(self, section),他會通過遍歷處理from傳下來的每一個Flag,并通過本身的write/remove來啟用和禁用這個選項。 當form保存下來cbid.firewall.cfg02e63d.syn_flood這個Network/Firewall/General Setting下的Flag標簽的值時,處理函數(shù)就會調(diào)用Flag.parse處理:調(diào)用self:formvalue來匹配標簽值,然后調(diào)用model/cbi/firewall/zones.lua的write或者remove來禁用或者啟用這個選項所控制的開關(guān)。 由于Flag = class(AbstractValue),繼承于AbstractValue類,所以其write/remove是調(diào)用的AbstractValue類的write/remove方法。 AbstractValue.write調(diào)用self.map:set即function Map.set(self, section, option, value),Map.set 再調(diào)用self.uci:set(self.config, section, option, value)來設(shè)置對應(yīng)config文件,然后Map.parse 會調(diào)用self.uci:commit(config)對已修改的config逐一提交。 生效的兩種方式 1、按照固定格式設(shè)置對應(yīng)選項,系統(tǒng)自動調(diào)用來使各個參數(shù)生效,self.uci:apply(self.parsechain) (應(yīng)用剛設(shè)置的config設(shè)置服務(wù))àfunction Cursor.apply(self, configlist, command) àreturn { "/sbin/luci-reload", unpack(configlist) }; 2、self:_run_hooks("on_apply", "on_after_apply"),自己在對應(yīng)的.lua文件中寫m.on_apply來啟動或者處理方式。
ps:openwrt個人理解加上前輩的blog來寫的,基本是一路打log來了解流程,若有文中問題還請指正 |
|
|