1.总述
上一篇总结了uhttpd的工作方式,openwrt中利用它作为web服务器,实现客户端web页面配置功能。对于request处理方式,采用的是cgi,而所用的cgi程序就是luci,工作框架如下图所示:
Client端和serv端采用cgi方式交互,uhttpd服务器的cgi方式中,fork出一个子进程,子进程利用execl替换为luci进程空间,并通过setenv环境变量的方式,传递一些固定格式的数据(如PATH_INFO)给luci。另外一些非固定格式的数据(post-data)则由父进程通过一个w_pipe写给luci的stdin,而luci的返回数据则写在stdout上,由父进程通过一个r_pipe读取。
下面的图描述了web配置时的数据交互:
-
首次运行时,是以普通的file方式获得docroot/index.html,该文件中以meta的方式自动跳转到cgi的url,这是web服务器的一般做法。
-
然后第一次执行luci,path_info='/',会alise到'/admin'('/'会索引到 tree.rootnode,并执行其target方法,即alise('/admin'),即重新去索引adminnode,这在后面会详细描述),该节点需要认证,所以返回一个登录界面。
-
第3次交互,过程同上一次的,只是这时已post来了登录信息,所以serv端会生成一个session值,然后执行'/admin'的target(它的target为firstchild,即索引第一个子节点),最终返回/admin/status.html,同时会把session值以cookie的形式发给client。这就是从原始状态到得到显示页面的过程,之后主要就是点击页面上的连接,产生新的request。
-
每个链接的url中都会带有一个stok值(它是serv生成的,并放在html中的url里),并且每个新request都要带有session值,它和stok值一起供serv端联合认证。
2.luci程序流程
前面已经说明了,luci作为web服务器的cgi程序,是通过execl函数替换到进程空间的,并且详细说明了它与其它进程的交互方法。另外上一节给出了初始阶段http报文,可以看到从第2次交互开始,所有request都是cgi方式(除一些css、js等resource文件外),且执行的cgi程序都是luci,只是带的参数不同,且即使所带参数相同(如都是'/'),由于需要认证,执行的过程也是不同的。
正是由于多种情况的存在,使得luci中需要多个判断分支,代码多少看起来有点乱,但openwrt还是把这些分支都糅合在了一个流程线中。下面首先给出整体流程,首先介绍一下lua语言中一个执行方式coroutine,它可以创造出另一个执行体,但却没有并行性,如下图所示,每一时刻只有一个执行体在执行,通过resume、yield来传递数据,且数据可以是任意类型,任意多个的。
Luci正是利用了这种方式,它首先执行的是running()函数,其中create出另一个执行体httpdispatch,每次httpdispatch执行yield返回一些数据时,running()函数就读取这些数据,做相应处理,然后再次执行resume(httpdispath),……如此直到httpdispatch执行完毕,如下图所示:
如上图所示,其实luci真正的主体部分正是dispatch,该函数中有多个判断分支,全部糅合在一起,代码比较烦,总体上有4个部分,下面对它们进行一些描述。
首先说明一下代码组成,在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
2.1节点树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如下:
这里要注意的是,每次dispatch()会根据path_info逐层索引,且每一层都把找到的节点信息放在一个变量track中,这样做使得上层node的信息会影响下层node,而下层node的信息又会覆盖上层node。比如{/admin/system},最后的auto=false,target=aa,而由于admin有sysauth值,它会遗传给它的子节点,也即所有admin下的节点都需要认证。
2.2target简介
对每个节点,最重要的属性当然是target,这也是dispatch()流程最后要执行的方法。target主要有:alise、firstchild、call、cbi、form、template。这几个总体上可以分成两类,前两种主要用于链接其它node,后一个则是主要的操作、以及页面生成。下面分别描述。
链接方法:在介绍初始登录流程时,已经讲到了这种方法。比如初始登录时,url中的path_info仅为'/',这应该会索引到rootnode节点。而该节点本身是没有内容显示的,所以它用alias('admin')方法,自动链接到admin节点。再比如,admin节点本身也没有内容显示,它用firstchild()方法,自动链接到它的第一个子节点/admin/status。
操作方法:这种方法一般用于一个路径的叶节点leaf,它们会去执行相应的操作,如修改interface参数等,并且动态生成页面html文件,传递给client。这里实际上是利用了所谓的MVC架构,这在后面再描述,这里主要描述luci怎么把生成的html发送给client端。
Call、cbi、form、template这几种方法,执行的原理各不相同,但最终都会生成完整的http-response报文(包括html文件),并调用luci.template.render(),luci.http.redirect()等函数,它们会调用几个特殊的函数,把报文内容返回给luci.running()流程。
如上图所示,再联系luci.running()流程,就很容易看出,生成的完整的http-response报文会通过io.write()写在stdout上,而uhttpd架构已决定了,这些数据将传递给父进程,并通过tcp连接返回给client端。
3.sysauth用户认证
2.1节已描述了,由于节点是由上而下逐层索引的,所以只要一个节点有sysauth值,那么它所有的子节点都需要认证。不难想象,/admin节点有sysauth值,它以下的所有子节点都是需要认证才能查看、操作的;/mini节点没有sysauth值,那么它以下的所有子节点都不需要认证。
luci中关于登陆密码,用到的几个函数为:
可以看出它的密码是用的linux的密码,而openwrt的精简内核没有实现多用户机制,只有一个root用户,且开机时自动以root用户登录。要实现多用户,必须在web层面上,实现另外一套(user、passwd)系统。
另外,认证后,serv端会发给client一个session值,且它要一直以cookie的形式存在于request报文中,供serv端来识别用户。这是web服务器的一般做法,这里就不多讲了。
4.MVC界面生成
这其实是luci的精华所在,第二节开始介绍/usr/lib/lua/luci/下有三个目录model、view、controller,它们对应M、V、C。第2.2节介绍了生成的界面怎么传递给client,下面简单介绍生成界面的方法。
Call()方法会调用controller里的函数,主要通过openwrt系统的uci、network、inconfig等工具对系统进行设置,如果需要还会生成新界面。动态生成界面的方法有两种,一是通过cbi()/form()方法,它们利用model中定义的模板map,生成html文件;另一种是通过template()方法,利用view中定义的htm(一种类似html的文件),直接生成界面。
上面的标题是由node-tree生成的,下面的内容由每个node通过上面的方法来动态生成。这套系统是很复杂的,但只要定义好了,使用起来就非常方法,增加页面,修改页面某个内容等操作都非常简单。
相关推荐
2. **前端框架**:Luci使用了Bootstrap作为基础样式库,提供响应式布局,确保在不同设备上都能良好显示。此外,还可能包含jQuery等JavaScript库用于交互效果。 3. **主题结构**:一个Luci主题通常包括以下部分: -...
《LuCI 框架:探索 0.11 版本的魅力》 LuCI,全称为 Lua Configuration Interface,是一个轻量级且高效的基于 Lua 的Web 管理界面框架,专为OpenWrt等嵌入式Linux系统设计。LuCI 提供了一个直观的界面,使得用户...
OpenWRT提供了基础操作系统的框架,LuCI提供了图形化管理界面,而“打印机服务器”则表明703N在刷入OpenWRT后扮演的角色。此外,“luci-app-usb”暗示了这个应用专门针对USB设备,尤其是打印机。 总结起来,这个...
开发OpenWrt路由器上的LuCI模块,首先需要了解LuCI的开发框架。LuCI框架分为三个主要部分:Model、View和Controller。Model层负责数据处理,Controller层处理用户请求并调用Model层的代码,而View层则是最终展示给...
LUCI提供了用户友好的图形界面,便于管理网络设备,而WIFIDOG则用于实现 captive portal(门户认证)功能。 AR9341是Atheros公司生产的一款高性能的无线网络SoC(系统级芯片),广泛应用于无线路由器、AP(接入点)...
Luci是一个开源的Web界面框架,用于配置和控制网络设备,而"luci-app-onliner"则是其功能扩展,使得网络管理员能够更便捷地了解网络的实时状态。 该应用的核心功能是基于ARP协议实现的在线人员查看。ARP(Address ...
在本教程中,我们将深入探讨Lua的基础语法、函数以及其在luci web框架中的应用。 首先,让我们从基础开始。Lua的语法结构非常清晰,易于学习。变量在Lua中是无类型的,意味着它们可以存储任何类型的数据,如数字、...
3. **Web界面重构**:结合Angular JS,LuCI-ng可能是对原始LuCI界面的重构,旨在提供更好的用户交互和响应性,通过使用Angular的模板和控制器实现动态更新。 4. **组件化开发**:Angular JS的组件化特性允许LuCI-ng...
一个简单的 luci web api接口框架,可以通过http 对接手机APP等其他第三方程序,实现对基于OpenWrt系统的路由器的实时管理。 基于原有luci框架,可加密访问,通过预先固定的命令接口(可方便的进行扩展)进行shell...
3. **JavaScript框架**:LuCI前端可能采用了特定的JavaScript库或框架(如jQuery、React或Vue.js)来提升用户体验和开发效率。 4. **HTTPS分叉**:通常指从原始HTTPS源获取代码并创建一个单独的分支,这可能是为了...
虽然LUCI UI Switcher主要面向的是Chrome浏览器用户,随着浏览器扩展框架的发展,开发者可能考虑将其扩展到Firefox、Edge等其他主流浏览器。随着Buildbot和LUCI系统的不断升级和改进,此插件也可能需要定期更新以...
总结来说,"app的短信与e-mail注册及常规app功能框架"是一个综合性的开发资源,它包括了用户验证、登录管理和页面布局等核心功能的实现,对于快速搭建移动应用是非常有价值的。开发者可以通过学习和使用这些模板代码...
标题 "luci2-solardata" 和描述 "luci2-tracertools" 提到的项目似乎与网络管理和监控工具有关,尤其是针对太阳能数据采集和分析的系统。在这个项目中,"luci2" 可能是 LuCI(Luci Interactive Configuration ...
OpenWRT提供了一个基于 BusyBox 的基础系统,包含了必要的命令行工具,以及LuCI(轻量级用户界面)来实现图形化配置。 二、OpenWRT的编译框架 OpenWRT的编译框架是其核心竞争力之一,它采用了称为"Buildroot"的...
总的来说,`luci-app-shellfirebox` 是 OpenWRT 用户通过 LuCI Web-UI 管理和控制 Shellfire Box 的关键工具,利用 CSS 实现美观的界面设计。这个应用程序的初稿提供了一个基础框架,允许用户安全地远程访问和管理...
Oui 是一个用来开发 OpenWrt Web 接口的框架。 Oui 使用 Lua-eco 开发其静态文件服务器。...Oui 实现了和 Luci 一样的模块化,每个页面独立打包,互不影响。其处理方式为将每个页面以库的形式进行打包。
10.OpenWRT UI框架发展历史讲解,石像鬼、X-WRT、Luci。 11.基于uhttpd,lua编写简单的UI界面,基于Luci编写简单的UI界面。 12.OpenWrt常用命令使用方法讲解,bash/lua讲解。 13.OpenWrt UCI框架分析,/etc/config/...
6. **luci wiki资料**:LuCI(Luci Interface)是一个基于Web的用户界面框架,用于配置基于OpenWrt的路由器。它使用Lua编写,提供了一系列的模板和库,使得开发者可以轻松创建交互式的配置界面。了解LuCI可以帮助你...
10. **第三方库和框架**:开发者可能会引入各种第三方库以实现特定功能,如网络请求库(OkHttp、AFNetworking)、图片加载库(Glide、Fresco、SDWebImage)等。理解这些库的用法能提升开发效率。 11. **测试**:...
Next oui –在vue.js中实现的OpenWrt现代Web界面oui(中文)在vue.js和Vue的Ant Design中实现的OpenWrt Web用户界面。 Oui使用json-rpc与OpenWrt子系统通信并支持ACL。 Oui特别适合企业定制开发。 如何构建添加提要...