Luci流程分析(openwrt下)


轉自:http://blog.chinaunix.net/uid-23780428-id-4367414.html

 

1. 頁面請求:

1.1. 代碼結構

在openwrt文件系統中,lua語言的代碼不要編譯,類似一種腳本語言被執行,還有一些uhttpd服務器的主目錄,它們是:

/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. 界面顯示

網頁請求格式基本都如下所示:http://10.10.82.238/cgi-bin/luci,說明處理都在服務器的默認網站下的/cgi-bin/luci文件進行處理。

1.2.1.  /www/cgi-bin/luci

luci.dispatcher.indexcache = "/tmp/luci-indexcache"--緩存文件位置“/tmp/luci-indexcache”

luci.sgi.cgi.run()--cgi程序接下來執行程序,Luci的默認路徑是/usr/lib/lua/luci,所以luci.sgi.cgi.run()是運行/usr/lib/lua/luci/sgi/cgi.lua文件中的run函數。

1.2.2. /usr/lib/lua/luci/sgi/cgi.lua

local r = luci.http.Request(…)--把web請求放於r中(包括環境變量,web請求,出錯處理接口)

local x = coroutine.create(luci.dispatcher.httpdispatch)--創建一個協同程序

local res, id, data1, data2 = coroutine.resume(x, r)--運行上面創建的協同程序,即運行httpdispatch,參數為上面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.lua

httpdispatch:解析請求,獲得請求節點,並調用dispatch處理請求節點,如:

Request :http://10.10.82.238/cgi-bin/luci/;stok=e10fa5c70fbb55d478eb8b8a2eaabc6f/admin/network/firewall/      get: admin network firewall

 

dispatch:四個部分處理請求

A.節點樹node-tree創立

              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. 請求頁面network

http://10.10.82.238/cgi-bin/luci/;stok=4b77c83a89c7b9cd8f4dcc0fcbc28024/admin/network/

 

1.2.3中D顯示部分與entry()函數(形如entry(path,target,title,order))有關,其中定義的target方法或者target部分。在以上http請求中會根據請求路徑去訪問到/usr/lib/lua/luci/controller/admin/network.lua,調用順序如下:

ok, err = util.copcall(target, unpack(args))-- dispatcher.luaà

page.target = firstchild() -- network.luaà

function firstchild()-- dispatcher.luaà

_firstchild()-- dispatcher.luaàdispatch(path)-- 自動鏈接到它的第一個子節點,

在network.lua中定義order,Interfaces是10,為第一個子節點:

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. 頁面響應

2.1. Web請求

當點擊頁面“Save & Apply”按鈕時,瀏覽器會把每一個有name的web元素的對應值下傳,下傳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. 處理

服務器處理過程和頁面生成基本類似,也調用到/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函數的集合)

function cbi(model, config) à

local function _cbi(self, ...) à

local cstate = res:parse()à

function Map.parse(self, readinput, ...) à

Node.parse(self, ...)

Node.parse會調用Map中的每一個子元素自身的處理

 

EX:

如調用Flag的處理:function Flag.parse(self, section),他會通過遍歷處理from傳下來的每一個Flag,並通過本身的write/remove來啟用和禁用這個選項。

當form保存下來cbid.firewall.cfg02e63d.syn_flood這個Network/Firewall/General Setting下的Flag標簽的值時,處理函數就會調用Flag.parse處理:調用self:formvalue來匹配標簽值,然后調用model/cbi/firewall/zones.lua的write或者remove來禁用或者啟用這個選項所控制的開關。

由於Flag = class(AbstractValue),繼承於AbstractValue類,所以其write/remove是調用的AbstractValue類的write/remove方法。

AbstractValue.write調用self.map:set即function Map.set(self, section, option, value),Map.set 再調用self.uci:set(self.config, section, option, value)來設置對應config文件,然后Map.parse 會調用self.uci:commit(config)對已修改的config逐一提交。

生效的兩種方式

1、按照固定格式設置對應選項,系統自動調用來使各個參數生效,self.uci:apply(self.parsechain) (應用剛設置的config設置服務)àfunction Cursor.apply(self, configlist, command) àreturn { "/sbin/luci-reload", unpack(configlist) };

2、self:_run_hooks("on_apply", "on_after_apply"),自己在對應的.lua文件中寫m.on_apply來啟動或者處理方式。

 

 

ps:openwrt個人理解加上前輩的blog來寫的,基本是一路打log來了解流程,若有文中問題還請指正

參考:http://www.verydemo.com/demo_c101_i48675.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM