Luci流程分析(openwrt下)
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
Luci流程分析(openwrt下)的更多相关文章
- openwrt luci web分析
openwrt luci web分析 来源 https://www.jianshu.com/p/596485f95cf2 www/cbi-bin/luci #!/usr/bin/lua --cgi的执 ...
- freeswitch呼叫流程分析
今天翻文档时发现之前整理的关于freeswitch呼叫相关的内容,写成博文分享出来也方便我以后查阅. 整体结构图 FreeswitchCore 模块加载过程 freeswitch主程序初始化时会从mo ...
- u-boot 流程分析
u-boot 介绍: 对于计算机来说 , 从一开始上机通电是无法直接启动操作系统的 , 这中间需要一个引导过程 , 嵌入式Linux系统同样离不开引导程序 , 这个启动程序就叫启动加载程序(Boot ...
- thttpd和cgilua安装与运行流程分析
安装 参考如下博文安装thttpd软件 http://blog.csdn.net/21aspnet/article/details/7045845 http://blog.csdn.net/drago ...
- u-boot中nandflash初始化流程分析(转)
u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...
- Android7.0 Phone应用源码分析(二) phone来电流程分析
接上篇博文:Android7.0 Phone应用源码分析(一) phone拨号流程分析 今天我们再来分析下Android7.0 的phone的来电流程 1.1TelephonyFramework 当有 ...
- 从注册流程 分析如何安全退出多个Activity 多种方式(附DEMO)
退出Activity注册Android遍历 目录(?)[+] 前言 知识结构 具体方案 方案1 方法采用FLAG_ACTIVITY_CLEAR_TOP退出整个程序多activity 方案2 方 ...
- ofbiz进击 。 ofbiz 退货流程(包含获取可退货项流程分析 以及 取消退货项的过程分析)
根据订单获取可退货项流程分析 退货的时候,调用 services_return.xml 中的获取可进行退货的退货项 getReturnableItems ,该服务调用了Java类 org.ofbi ...
- u-boot启动流程分析(2)_板级(board)部分
转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...
随机推荐
- Android高德地图自定义Markers的例子
下文为各位重点介绍关于Android高德地图自定义Markers的例子,希望这篇文章能够让各位理解到Android高德地图自定义Markers的方法. 之前的博客里说了地图的嵌入和定位,今天就说说在地 ...
- spring框架源码编译
程序猿小菜一枚,最近从github上面下载下来一份spring各个项目的源码一份,但是弄了很长时间,因为网速和(fanqiang)的速度,希望大家不要再为这种无谓的时间花费时间,简单来说github上 ...
- 《Algorithms 4th Edition》读书笔记——3.1 符号表(Elementary Symbol Tables)-Ⅰ
3.1符号表 符号表最主要的目的就是将一个键和一个值联系起来.用例能够将一个键值对插入符号表并希望在之后能够从符号表的所有键值对中按照键值姐找到对应的值.要实现符号表,我们首先要定义其背后的数据结构, ...
- linux下面测试网络带宽 (转载)
利用bmon/nload/iftop/vnstat/iptraf实时查看网络带宽状况 一.添加yum源方便安装bmon# rpm -Uhv http://apt.sw.be/redhat/el5/en ...
- vi命令笔记
vim编辑器 文本编辑器,字处理器ASCII nano, sed vi: Visual Interfacevim: VI iMproved 全屏编辑器,模式化编辑器 vim模式:编辑模式(命令模式)输 ...
- Live555 分析(一):类介绍
从程序的结构来看,live项目包括了四个基本库.程序入口类(在mediaServer中)和一些测试代码(在testProgs中). 四个基本静态库是UsageEnvironment.BasicUsag ...
- .NET 面试题(1)
1.简述 private. protected. public. internal 修饰符的访问权限. private:私有成员,在类的内部才能访问 protected:保护成员,在该类内部和继承本类 ...
- UITableView使用总结和性能优化
UITableView使用总结和性能优化 UITableView有两种风格:UITableViewStylePlain和UITableViewStyleGrouped.如 果我们查看UITabl ...
- (转)25个增强iOS应用程序性能的提示和技巧--中级篇
在性能优化时,当你碰到一些复杂的问题,应该注意和使用如下技巧: 9.重用和延迟加载View10.缓存.缓存.缓存11.考虑绘制12.处理内存警告13.重用花销很大的对象14.使用Sprite Shee ...
- PHP操作MySQL数据库的相关函数
首先,要分清SQL语句的类型: SQL语句的分类 (1)DDL:Data Define Language,数据定义语言--定义表的列结构 CREATE.DROP.ALTER.TRUNCATE (2)D ...