天天看点

luci流程简介

LuCI作为“FFLuCI”诞生于2008年3月份,目的是为OpenWrt固件从Whiterussian 到 Kamikaze实现快速配置接口。

LuCI是OpenWrt上的Web管理界面,LuCI采用了MVC三层架构,使用lua脚本开发,所以开发LuCI的配置界面不需要编辑任何的html代码,除非想自己单独去创建网页(View层),否则我们基本上只需要修改Model层就可以了。

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

luci采用的是MVC架构的web框架,M是指module(有的源码包是module,配置模块代码),C指的是controller(定义模块的入口),V指的是view(创建网页)。

luci其实是Lua脚本语言和UCI统一配置接口的合称。就是说原本openwrt就提供里uci的api让你可以很方便的修改openwrt的配置文件,无论是创建、读取、修改、删除。而且uci命令可以植入shell脚本和c语言或者是lua脚本。在/usr/lib/lua/luci下大多数都是lua脚本,就是这些lua脚本生成我们所看见的web页面。

2、luci框架流程

luci流程简介

①首次运行时,是以普通的file方式获得docroot/index.html,该文件中以meta的方式自动跳转到cgi的url,这是web服务器的一般做法。

http://192.168.1.1/  index.html会自动跳到http://192.168.1.1/cgi-bin/luci,登陆默认root。index.html对于OpenWrt源码路径为:

\package\ramips\ui\luci-mtk\src\modules\base\root\www\index.html源码:

<?xmlversion="1.0" encoding="utf-8"?>

<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<htmlxmlns="http://www.w3.org/1999/xhtml">

<head>

<metahttp-equiv="refresh" content="0; URL=/cgi-bin/luci"/>

</head>

<bodystyle="background-color: black">

<astyle="color: white; text-decoration: none" href="/cgi-bin/luci" target="_blank" rel="external nofollow" >LTERouter</a>

</body>

</html>

②第一次执行luci,path_info='/',会alise到'/admin'('/'会索引到tree.rootnode,并执行其target方法,即alise('/admin'),即重新去索引adminnode),该节点需要认证,所以返回一个登录界面sysauth.html。

Luci脚本源码路径:package\ramips\ui\luci-mtk\src\modules\base\htdocs\cgi-bin\luci,luci 的代码如下:

1#!/usr/bin/lua  -- 执行命令的路径

2require"luci.cacheloader" -- 导入 cacheloader 包

3require"luci.sgi.cgi"  -- 导入sgi.cgi 包

4luci.dispatcher.indexcache = "/tmp/luci-indexcache" --cache 缓存路径地址

5luci.sgi.cgi.run()  -- 执行run方法,此方法位于/usr/lib/lua/luci/sgi/cgi.lua中.

登录界面sysauth.html源码路径:package\ramips\ui\luci-mtk\src\modules\base\luasrc\view\sysauth.htm

③第3次交互,过程同上一次的,只是这时已post来了登录信息,所以server端会生成一个session值,然后执行'/admin'的target(它的target为firstchild,即索引第一个子节点),最终返回/admin/status.html,同时会把session值以cookie的形式发给client。这就是从原始状态到得到显示页面的过程,之后主要就是点击页面上的连接,产生新的request。

返回/admin/status.html源码路径:package\ramips\ui\luci-mtk\src\modules\admin-full\luasrc\view\admin_status\index.htm

④每个链接的url中都会带有一个stok值(它是server生成的,并放在html中的url里),并且每个新request都要带有session值,它和stok值一起供server端联合认证。

3、node-tree

在controller目录下,每个.lua文件中,都有一个index()函数,其中主要调用entry()函 数,形如entry(path,target,title,order),path形如{admin,network,wireless},entry()函数根据这些创建一个node,并把它放在全局node-tree的相应位置,后面的参数都是该node的属性,还可以有其他的参数。其中最重要的就是target。

Createtree()函数就是要找到controller目录下所有的.lua文件,并找到其中的index()函数执行,从而生成一个node-tree。这样做的io操作太多,为了效率,第一次执行后,把生成的node-tree放在/tmp/treecache文件中,以后只要没有更新(一般情况下,服务器里的.lua文件是不会变的),直接读该文件即可。生成的node-tree如下:

luci流程简介
luci流程简介

这里要注意的是,每次dispatch()会根据path_info逐层索引,且每一层都把找到的节点信息放在一个变量track中,这样做使得上层node的信息会影响下层node,而下层node的信息又会覆盖上层node。比如{/admin/system},最后的auto=false,target=aa,而由于admin有sysauth值,它会遗传给它的子节点,也即所有admin下的节点都需要认证。