cwmp开源代码研究5——cwmp程序设计思想

京月飞鸿 京月飞鸿     2022-08-20     635

关键词:

声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的。 如有任何问题,欢迎和我交流。(企鹅号:408797506)

本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载,没有源码)

淘宝店:https://shop484606081.taobao.com

参考:

1) http://www.docin.com/p-1306443672.html

2) http://www.easycwmp.org/

一. 背景

  程序设计的思想来自于easycwmp官网,看过或者用过easycwmp的工程师应该都知道,该开源代码还有商业版,而且价格不菲(前公司曾经想要购买后放弃),easycwmp官网如是说:DataModel is developped with shell as free solution and with C as commercial solution.。开源代码用来学习还是值得的,若是用于商业产品可能就会显得"力不从心"。幸运的是,我有机会阅读了Works Systems公司和broadcom公司的tr069代码,架构设计与easycwmp的设计"如出一辙",下图是easycwmp官网的程序架构图。但是,个人对于Works Systems公司的代码"情有独钟"并且进行了重新开发和利用,使得程序更加高效易用和移植性。基于此,本文就着重介绍在商业代码中如何高效,便捷的实现DataModel 和CWMP core分离,给读者一个程序设计的思路。 后续若有机会可以介绍一下broadcom公司的程序设计仅供参考。本质上大同小异。

二. 程序设计概要

  对于单一的产品线程序采用"单进程多线程"的思想。这样比较容易简洁,而且方便维护。若是多功能的产品,即一个设备上需要运行多个"CWMP进程", 那么我们使用了创建"多个子进程"的方法,每个子进程根据配置文件的不同从而实现设备的不同需求(该功能待完善)。比如现在家庭或者企业网关产品越来越需要"智慧""智能"的需求,如何让设备与手机互连互通,保证安全方便高效的前提下,既可以被运营商(卖方)管理,同时又可以被自己(买方)控制管理,这是一个值得思考的问题,也是工程师需要考虑的技术。

  下图是单一产品的tr069程序处理流程。大致分为:配置文件解析模块,日志模块,设备xml解析模块,任务模块以及事件处理模块(有关联),多线程模块(可插入模块)等。

   原则上,CWMP core的程序代码不需要修改,主要是根据客户的需求修正或者进行"插入式的"新增事件类型和模块化处理。而设备相关的程序,我们封装成了一个动态库(libcwmp.so),便于独立编译和维护开发。

                                                                                     (附: 高清PDF版下载路径http://download.csdn.net/detail/eryunyong/9731487

3.1 配置文件解析(libconf)

  根据配置文件的全路径和内容初始化数据结构,使用例子如下:

1 char      conf_file[PATH_MAX] = {0};
2 conf_t   *tmp = NULL;
3 
4 tmp = conf_load(conf_file);
5 count = conf_get_int(tmp, "global:count", 0);
View Code

 3.2 日志模块

  为了便于和Linux的syslog统一和管理,这里定义的日志等级与syslog一致。 

   CWMP_LOG_EMERG        ---------------------->        EMERG = 0
   CWMP_LOG_ALERT        ---------------------->         ALERT = 1
   CWMP_LOG_CRIT        ---------------------->           CRIT  = 2
   CWMP_LOG_ERROR        ---------------------->        ERROR = 3
   CWMP_LOG_WARN        --------------------->          WARN  = 4
   CWMP_LOG_NOTICE        --------------------->        NOTICE= 5
   CWMP_LOG_INFO        --------------------->            INFO  = 6
   CWMP_LOG_DEBUG        --------------------->        DEBUG = 7

3.3 XML解析模块

  使用libexpat库函数解析设备XML格式文件,以及CWMP和ACS之间交换的SOAP消息。device.xml文件内容如下:

 1 <TR069 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 2   <trf>
 3     <obj name="InternetGatewayDevice">
 4       <param name="DeviceSummary" getval_func="CpeGetDeviceSummary"></param>
 5       <param name="LANDeviceNumberOfEntries" type="2" getval_func="CpeGetLANDeviceNumberOfEntries"></param>
 6       <param name="WANDeviceNumberOfEntries" type="2" getval_func="CpeGetWANDeviceNumberOfEntries"></param>
 7       <obj name="DeviceInfo" noti_rw="1">
 8         <param name="SpecVersion" getval_func="CpeGetDeviceInfoSpecVersion"/>
 9         <param name="HardwareVersion" getval_func="CpeGetDeviceInfoHardwareVersion"></param>
10         <param name="SoftwareVersion" getval_func="CpeGetDeviceInfoSoftwareVersion"></param>
11         <param name="Manufacturer"      getval_func="CpeGetDeviceInfoManufacturer"></param>
12         <param name="SerialNumber"      getval_func="CpeGetDeviceInfoSerialNumber"></param>
13         <param name="ManufacturerOUI" getval_func="CpeGetDeviceInfoManufacturerOUI"></param>
14         <param name="ProvisioningCode" rw="1" getval_func="CpeGetDeviceInfoProvisioningCode" setval_func="CpeSetDeviceInfoProvisioningCode"></param>
15         <param name="ProductClass" getval_func="CpeGetDeviceInfoProductClass"></param>
16         <param name="DeviceType" getval_func="CpeGetDeviceInfoDeviceType"></param>
17      <param name="ModelName" getval_func="CpeGetDeviceInfoModelName"></param>
18         <param name="CpeWANAddress" noti_rw="1" rw="1" getval_func="CpeGetCpeWANAddress" setval_func="CpeSetCpeWANAddress"/>
19       </obj>
20       <obj name="ManagementServer">
21         <param name="ConnectionRequestURL"                                   getval_func="CpeGetManagementServerConnectionRequestURL"></param>
22         <param name="ConnectionRequestUsername"     rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerConnectionRequestUsername" setval_func="CpeSetManagementServerConnectionRequestUsername"></param>
23         <param name="ConnectionRequestPassword"     rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerConnectionRequestPassword" setval_func="CpeSetManagementServerConnectionRequestPassword"></param>
24         <param name="Username"                      rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerUsername"          setval_func="CpeSetManagementServerUsername"></param>
25         <param name="Password"                      rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerPassword"          setval_func="CpeSetManagementServerPassword"></param>
26         <param name="ParameterKey"                   getval_func="CpeGetManagementServerParameterKey"      setval_func="CpeSetManagementServerParameterKey"/>
27         <param name="URL"                           rw="1"    noti_rw="1"    getval_func="CpeGetManagementServerUrl"               setval_func="CpeSetManagementServerUrl"></param>
28         <param name="PeriodicInformEnable"          rw="1"  noti_rw="1"  type="3" getval_func="CpeGetManagementServerPeriodicInformEnable"      setval_func="CpeSetManagementServerPeriodicInformEnable"></param>
29         <param name="PeriodicInformInterval"        rw="1"  noti_rw="1"  type="2" getval_func="CpeGetManagementServerPeriodicInformInterval"    setval_func="CpeSetManagementServerPeriodicInformInterval"></param>
30         <param name="PeriodicInformTime"            rw="1"          type="4" getval_func="CpeGetManagementServerPeriodicInformTime"        setval_func="CpeSetManagementServerPeriodicInformTime"></param>
31       </obj>
32 
33       <obj name="Time">
34         <param name="Enable"          rw="1"  type="3"     getval_func="CpeGetTimeEnable"          setval_func="CpeSetTimeEnable"></param>
35         <param name="NTPServer1"              rw="1"     getval_func="CpeGetTimeNTPServer1"      setval_func="CpeSetTimeNTPServer1"></param>
36         <param name="CurrentLocalTime"       type="4"             getval_func="CpeGetTimeCurrentLocalTime"></param>
37       </obj>
38       <obj name="X_CT-COM_MonitorCollector">
39          <param name="Enable"      noti_rw="1"     rw="1" type="3"   getval_func="CpeGet_MonitorEnable"                 setval_func="CpeSet_MonitorEnable"></param>
40          <obj name="MonitorConfig"  rw="1" addobj_func="TRF_Add_MonitorConfig" delobj_func="TRF_Del_MonitorConfig"  refresh_func="TRF_Refresh_MonitorConfig">
41            <obj name="0">
42              <param name="ParaList"  noti_rw="1"     rw="1"   getval_func="CpeGet_MonitorConfig_ParaList"                 setval_func="CpeSet_MonitorConfig_ParaList"></param>
43              <param name="TimeList"   rw="1"  type="2"          getval_func="CpeGet_MonitorConfig_TimeList"      setval_func="CpeSet_MonitorConfig_TimeList"></param>
44            </obj>
45         </obj>
46       </obj>    
47       <obj name="LANDevice">
48         <obj name="1">
49           <param name="LANEthernetInterfaceNumberOfEntries" type="2" getval_func="CpeGetLANEthernetInterfaceNumberOfEntries"/>
50         </obj>
51       </obj>
52     <obj name="ObjTest"   rw="1"  addobj_func="TRF_Add_ObjTest" delobj_func="TRF_Del_ObjTest" refresh_func="TRF_Refresh_ObjTest">
53         <obj name="0">
54             <param name="TestEnabled" rw="1" type="3" getval_func="CpeGetObjTest_TestEnabled" setval_func="CpeSetObjTest_TestEnabled"/>
55         </obj>
56     </obj>
57     </obj>
58   </trf>
59 
60   <devlib name="/usr/lib/libcwmp.so"></devlib>
61   
62   <auth name="dev_get_auth"></auth>
63   
64   <listenport name="dev_get_listenport"></listenport>
65   <wanparamname name="dev_get_wanparam_name"></wanparamname>
66   
67   <bootstrap name="dev_bootstrap"></bootstrap>  
68   <init name="dev_init"></init>  
69   <reboot name="dev_reboot"></reboot>
70 
71   <factoryreset name="dev_factoryreset"></factoryreset>
72   <download name="dev_download"></download>
73   <acsstatus name="dev_set_acs_status"></acsstatus>
74   <urldnsresolve name="dev_url_dns_resolve"></urldnsresolve>
75   
76   <upload name="dev_upload"></upload>
77   <cwmpenable name="dev_cwmp_enable"/>
78  
79   <informlist>
80     <inform name="InternetGatewayDevice.DeviceInfo.ModelName"/>
81     <inform name="InternetGatewayDevice.DeviceInfo.DeviceType"/>
82   </informlist>
83 
84   <eventlist>
85     <event name="X CT-COM BIND"></event>
86   </eventlist>
87 
88 
89 </TR069>
View Code

 InternetGatewayDevice是整个参数树的根。obj表示这是一个对象,obj可以读,可以写,当objname0时,表示该obj可以是个模板,为创建后面的实例提供一个模板,当ACS查询时,不会把obj name0的Obj发送给ACS。Objrw=1,表示该obj可以添加子obj,通过addobj_func来添加,通过delobj_func来删除,refresh_func表示刷新该obj下的信息。 Objnoti_rw =1认为可以设置该obj的属性,譬如notify属性,如果设置了obj的属性,则认为该obj下的所以子树都有该属性。Param表示一个参数项,参数可以读,可以写,通过getval_func来读,通过setval_func来写。noti_rw=1认为可以设置该Param的属性,譬如notify属性。Type的含义如下:

string             ------------------------->         0
int                -------------------------->         1
unsigned int       ----------------------->         2
bool               ------------------------->         3
datetime           ----------------------->         4
base64             ----------------------->         5
long               ------------------------->         6
unsigned long      ---------------------->         7
hex binary         ----------------------->         8
object             ------------------------->         9

3.4 TASK任务模块

  根据任务队列中的消息类型进行处理,把需要发送给ACS的事件event消息加入事件队列。

 1 //诊断
 2 #define TASK_DIAG           1
 3 //重启
 4 #define TASK_REBOOT         2
 5 //恢复出厂设置
 6 #define TASK_FACTORY        3
 7 //download
 8 #define TASK_DOWNLOAD       4
 9 //upload
10 #define TASK_UPLOAD         5
11 //change ACS URL
12 #define TASK_CHANGE_ACS_URL 6
13 #define TASK_SUBDEVICE      7
14 #define TASK_ADD_EVENT      8
15 #define TASK_ADD_INFORM     9
16 #define TASK_CLEAR_EVENT    10
17 
18 #define TASK_VPN_RESTART    20
19 #define TASK_SYSLOG_RESTART 21
20 #define TASK_FIREWARE_RESTART 22
21 
22 #define TASK_OTHER          99
View Code

3.5 事件处理模块

   使用event_handle函数来处理事件,通过信号量来等待是否需要处理的事件,以及从事件队列中获取处理的事件。同理,在其他线程函数中,通过置信号量,将事件加入队列中来通知该模块处理。

    STATUS_IDLE = 0,        /* 空闲状态 */
    STATUS_INIT,            /* 初始化,获取ACS的URL,以及发送Inform消息*/
    STATUS_CONN,            /* CPE和ACS处于连接状态,并处理ACS下发的任务 */
    STATUS_ERROR,         /* 发生错误 */
    STATUS_FINS,         
/* 结束事件处理 */

3.6 其他多线程模块

   为了实现"低耦合高内聚"的模块化思想,程序设计采用了多线程来实现。比如:周期上报Inform事件, 根据tr069规范监测参数变化的上报事件,检测WAN口地址变化的事件,STUN线程,DHCP发现ACS地址事件。

四. 数据结构

 1) cwmp_context结构体是CWMP进程处理的上下文,主要包括初始化设备参数树,Value change,监视参数变化,记录事件等。

 1 struct cwmp_context{
 2     file_context_t      file_ctx;           //配置文件
 3     trf_param_t         param_root;         //参数树根节点
 4     dev_info_t          dev_info;           //设备信息
 5 
 6     void                *handle_lib;        //设备library的handle
 7     
 8     int                 acs_port;           //监听ACS的端口
 9     int                 acs_retrycount;     //连接ACS重试次数
10     int                 notify_interval;    //监视参数变化的间隔时间
11     
12     pthread_mutex_t     mutex_attr;
13     hash_t              *ht_attr;           //记录参数属性,需要上报的。
14 
15     pthread_mutex_t     mutex_val_change;  
16     hash

cwmp开源代码研究——cwmp移植(代码片段)

...误,请留言!email:[email protected]声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的。如有任何问题,欢迎和我交流。(企鹅号:408797506)本篇用到的文件包下载路径:http://download.csdn.net/detail/eryunyong/9735149一.环... 查看详情

开源免费tr069协议cpe代理程序对比

...门的学习,是再合适不过的了,其中EasyCWMPCore是开源的,十分方便我们进行二次开发和拓展。但是EasyCwmpDataModel并不是完全开源的,开源版本只支持部分协议模型。官网地址:http://easycwmp.org 查看详情

configuregenieacs(代码片段)

GenieACSGeneralConfigconfig.json actsasthemainconfigurationfileandisstoredin /path_to_genieacs/config/.Inthisfolderthere‘salsoabackupfileofthemain(/default)config(config-sample.json).Thefollowingexampleshowssomeaddedoptions."DATABASE_NAME":"genieacs","MONGODB_SOCKET":"/tmp/mongodb-27017.... 查看详情

tr-069_amendment-4:附录g.穿越nat网关的连接请求方式

...典STUN,RFC5389引入后,这个机制已经过时。这个机制不是设计用于RFC5389中定义的STUN。IPv6部署要么不使用NAT,要么以不同的方式使用它。G.1介绍CWMP可以用来对通过网关连接的局域网下的CPE设备进行远程管理。当设备部在NAT网关之... 查看详情

tr069事件类型(eventcode对应的含义)(代码片段)

...WMP端第一次与ACS连接。注意,0BOOTSTARP可能和其他事件代码一起组成事件代码组,例如,在出厂后CPE初始启动时,CPE发送0BOOTSTARP和1BOOT事件代码。1BOOT当给电或是复位时引起的会话建立,这包括初始系统启动或... 查看详情

1-5算法设计常用思想之穷举法(代码片段)

穷举法又称穷举搜索法,是一种在问题域的解空间中对所有可能的解穷举搜索,并根据条件选择最优解的方法的总称。数学上也把穷举法称为枚举法,就是在一个由有限个元素构成的集合中,把所有元素一一枚举研究的方法。使... 查看详情

eventbus编程思想-实现简易版eventbus(代码片段)

...;不纠结实现细节。先理解设计思想,这也是研究学习开源框架的第一步。代码:点击GitHub一个开源框架的出现肯定是有原因的,便捷,性能基本离不开这两点。而EventBus设计的初衷应该是为了便捷。回想自己为什... 查看详情

学习设计模式的思想

...的基石:利用C++中的多态技术;3、开闭原则:通过添加代码,而不是修改代码,完成功能的修改与扩展;4、依赖倒置原则:产品和框架都向抽象层靠拢;5、简单工产模式:不属于23种设计模式,将产品的创建都放到一个类(具体... 查看详情

java编程思想:通配符(后面有两个小节,研究的不够深入)(代码片段)

importjava.util.*;publicclassTestpublicstaticvoidmain(String[]args)/*15.9边界要点:1.T继承的顺序,类放必须放在第一位,后面跟接口2.类与接口用&进行链接3.可以继承于一个类,可以实现多个接口4.可以使用边界类的方法5.可以使用边界类的... 查看详情

设计思想-第二篇(代码片段)

设计思想-第二篇文章目录设计思想-第二篇1)、设计思想之获取泛型T的真实类型2)、设计思想之通过String,StringBuffer实现字符串反转3)、设计思想之MVC表现层框架的核心思想4)、设计思想之使用fastjson获取... 查看详情

设计思想-第二篇(代码片段)

设计思想-第二篇文章目录设计思想-第二篇1)、设计思想之获取泛型T的真实类型2)、设计思想之通过String,StringBuffer实现字符串反转3)、设计思想之MVC表现层框架的核心思想4)、设计思想之使用fastjson获取... 查看详情

近5年来头脑风暴优化算法的研究热点

...各位支持!我们在​​头脑风暴优化(BSO)算法(附MATLAB代码)​​这篇推文中讲解了头脑风暴优化算法的基本思想,并在​​头脑风暴优化(BSO)算法求解旅行商问题(TSP)(附MATLAB代码)​​和​​免费代码|头脑风暴优化... 查看详情

游戏设计模式——面向数据编程思想(代码片段)

前言:随着软件需求的日益复杂发展,远古时期面的向过程编程思想才渐渐萌生了面向对象编程思想。当人们发现面向对象在应对高层软件的种种好处时,越来越沉醉于面向对象,热衷于研究如何更加优雅地抽象出对象。然而现... 查看详情

面向对象思想

...0年代,位于美国加州的Xerox研究中心推出smalltalk语言及其程序设计环境,使得面向对象程序设计方法得到比较完善的实现,掀起了面向对象研究的高潮。到80年代中后期,面向对象的软件设计和程序设计方法 查看详情

基于大数据的音乐推荐系统的设计与实现(代码片段)

...:用户可以自行下载个人喜欢分歌曲。本系统部署在开源大数据平台hadoop3.5之上,搭配的spark2.2也为开源免费。后端使用的关系型数据库为mysql。开发软件使用的是eclipse社区版、pycharm社区版和其他一些免费开源软件。前... 查看详情

设计思想-第一篇-初出茅庐(代码片段)

MoCha设计思想-第一篇文章内容是初学Java时,记录的内容,现在回头看感觉很有意思。文章目录MoCha设计思想-第一篇1)、设计思想之限制接口调用的参数范围2)、设计思想之利用Properties类读取配置文件3)、设... 查看详情

设计思想-第一篇-初出茅庐(代码片段)

MoCha设计思想-第一篇文章内容是初学Java时,记录的内容,现在回头看感觉很有意思。文章目录MoCha设计思想-第一篇1)、设计思想之限制接口调用的参数范围2)、设计思想之利用Properties类读取配置文件3)、设... 查看详情

设计思想-第二篇(代码片段)

设计思想-第二篇文章目录设计思想-第二篇1)、设计思想之获取泛型T的真实类型2)、设计思想之通过String,StringBuffer实现字符串反转3)、设计思想之MVC表现层框架的核心思想4)、设计思想之使用fastjson获取... 查看详情