CWMP开源代码研究6——libcwmp动态库开发
原创作品,转载请注明出处,严禁非法转载。如有错误,请留言!
email:40879506@qq.com
为了使程序具有通用性,便于扩展和维护。采用了"模块"插入的思想。将设备业务相关的实现以动态库的形式加载进来。
在上篇文章已经介绍了CWMP的程序处理流程。本篇主要分析一下在CWMP core的程序里如何加载lib库。。比如如何实现调用so库函数, 实现ACS URL解析, CPE get/set函数怎么被调用,怎样添加/删除/更新 obj对象等。
一. 加载lib库
1) 打开动态连接库
还记得上节我们定义的cwmp进程上下文结构体cwmp_context,使用dlopen以指定的模式打开动态库文件,并返回设备library的handle。
//打开设备handle
cwmp_ctx->handle_lib = dlopen(cwmp_ctx->dev_info.dev_lib, RTLD_LAZY);
2) 调用设备相关函数
上节已经介绍了相关设备函数,并定义在device.xml。根据xml定义的tag头取得函数名称,并赋给CWMP进程上下文。比如
cwmp_ctx->dev_info.func_bootstrap = dlsym(cwmp_ctx->handle_lib, attr_value);
cwmp_ctx->dev_info.func_init = dlsym(cwmp_ctx->handle_lib, attr_value);
cwmp_ctx->dev_info.func_get_listenport = dlsym(cwmp_ctx->handle_lib, attr_value);
cwmp_ctx->dev_info.func_get_auth = dlsym(cwmp_ctx->handle_lib, attr_value);
cwmp_ctx->dev_info.func_url_dns_resolve= dlsym(cwmp_ctx->handle_lib, attr_value);
......
二. 设备相关初始化
//用于需要平台一开始初始化
void dev_init(trf_param_t* param, callback_reg_func_t func, pthread_mutex_t *pmutex_param, LogFunc log_func)
{
pthread_t thd;
monitor_info_t *info = NULL; //init local pointer
cwmplog_func = log_func;
g_reg_func = func;
g_root_param = param;
g_pmutex_param = pmutex_param; info = (monitor_info_t *)malloc_check(sizeof(monitor_info_t));
info->func = func;
info->param = param;
// info->log_func = log_func; closeinout(); //初始化CPE 与ACS 连接状态
CpeSetValue(NULL, "", "cpeagent.tr069.acs_status"); /*
1. define user-defined event code in the device.xml.
*/
inform_bind(func); // monitor_socket_event 线程函数用于与其他程序或进程指定的socket进行通信
// 比如源码目录下的sendSocket/client.c 程序,可用于测试或其他
// CWMP_SOCK "/opt/cwmp.sock"
// pthread_create(&thd, NULL, monitor_socket_event, (void*)info);
return;
}
主要完成初始化操作:将内存中的根节点参数位置赋给动态库中的全局变量g_root_param指针,以及初始化信号量,日志记录函数,以及FUNC回调函数。 inform_bind(func)函数实现用户自定义的<EventCode>事件,比如电信运营商自定义了X CT-COM BIND事件类型,只用上报正确才能进行工单下发业务。
dev_bootstrap主要用来判断是否是首次连接ACS,如果是把0 BOOTSTRAP和1 BOOT加入Inform事件中,否则把1 BOOT加入Inform事件中。
Inform中带有如下结构信息:
<cwmp:Inform>
<DeviceId xsi:type="cwmp:DeviceIdStruct">
<Manufacturer>TEST</Manufacturer>
<OUI>A1B2C4</OUI>
<ProductClass>TEST_PC</ProductClass>
<SerialNumber></SerialNumber>
</DeviceId>
<Event SOAP-ENC:arrayType="cwmp:EventStruct[2]">
<EventStruct>
<EventCode> BOOT</EventCode>
<CommandKey></CommandKey>
</EventStruct>
<EventStruct>
<EventCode>X CT-COM BIND</EventCode>
<CommandKey></CommandKey>
</EventStruct>
</Event>
<MaxEnvelopes></MaxEnvelopes>
<CurrentTime>--09T11::</CurrentTime>
<RetryCount></RetryCount>
<ParameterList SOAP-ENC:arrayType="cwmp:ParameterValueStruct[10]">
<ParameterValueStruct>
<Name>InternetGatewayDevice.DeviceSummary</Name>
.......
三. 解析ACS URL
同时支持域名和ip地址解析。(放在后续高级部分专门讲解)
四. 每个节点RPC Method
节点结构体如下:
struct trf_param
{
char name[PARAM_NAME_LEN+]; //参数名
int type; //参数类型 trf_datatype_e
int writable; //是否可写。0:不可写,1:可写,如果object
//可以Add,则可写
int max_instance; //属于Object, 最大instance值,-1表示无限制
int notification; //属于Parameter, 0:off,1:passive,2:active
unsigned char noti_rw; //属于Parameter, 是否可以设置上报属性,0 不可以 1 可以
unsigned long acl; /*属于Parameter, access list */
TRFGetParamValueFunc getparamval_func; //属于Parameter, 取得参数值函数
TRFSetParamValueFunc setparamval_func; //属于Parameter, 设置参数值函数
TRFAddObjectFunc addobject_func; //属于Object, AddObject
TRFDelObjectFunc delobject_func; //属于Object, DeleteObject
TRFRefreshFunc refresh_func; //属于Object, 刷新
struct trf_param *parent; //父节点
struct trf_param *child; //子节点
struct trf_param *nextSibling; //兄弟节点
};
每个参数节点拥有自己的属性和方法,并且通过递归方式创建初始化参数树,把初始化后的结果保存在cwmp_context进程上下文中
create_param(&cwmp_ctx->param_root, xmldata->doc->root->firstChild);
五. 其他RPC方法
本文开头已经介绍了调用设备相关函数的方法,其中包括除TR069规范中的升级,恢复出厂,Reboot,Download等方法,我们也可以通过”插件"的形式实现自己的或者私有厂商定义的方法。
<devlib name="/usr/lib/libcwmp.so"></devlib>
<auth name="dev_get_auth"></auth>
<listenport name="dev_get_listenport"></listenport>
<wanparamname name="dev_get_wanparam_name"></wanparamname>
<bootstrap name="dev_bootstrap"></bootstrap>
<init name="dev_init"></init>
<reboot name="dev_reboot"></reboot>
<factoryreset name="dev_factoryreset"></factoryreset>
<download name="dev_download"></download>
<acsstatus name="dev_set_acs_status"></acsstatus>
<urldnsresolve name="dev_url_dns_resolve"></urldnsresolve>
<upload name="dev_upload"></upload>
<cwmpenable name="dev_cwmp_enable"/>
六. 总结
tr069只是个协议栈,按照规范实现这个协议并不困难,在github上我们也可以去找到各种各用的开源程序,有Python写的,java写的,C写的等等。但是,能够从开源程序中找到一个优秀的程序设计架构就如同大海捞针,很困难,更不要说商业用途了。
至此,已经基本写完了关于程序设计部分的内容,本篇涉及的代码比较多,尽量不深入代码,而只是围绕协议规范和程序模块化思想分析了部分代码的实现。
七. 参考
1)http://www.cnblogs.com/Anker/p/3746802.html
附:遗留问题
程序开发中在使用dl库中遇到一个问题,若有心的读者能解答,欢迎留言告诉我:
若dlopen打开的库中不存在线程,或线程不在运行状态,则调用dlclose时,进程不会死;
若存在运行时的线程(比如dev_init函数里的 pthread_create(&thd, NULL, monitor_socket_event, (void*)info);),则dlclose时出现segmentation fault。
若不调用dlclose则会出现内存漏洞
CWMP开源代码研究6——libcwmp动态库开发的更多相关文章
- CWMP开源代码研究——git代码工程
原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...
- CWMP开源代码研究5——CWMP程序设计思想
声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...
- CWMP开源代码研究——cwmp移植
原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...
- CWMP开源代码研究7——cwmp移植
原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...
- CWMP开源代码研究1——开篇之作
原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...
- CWMP开源代码研究2——easycwmp安装和学习
声明:本文是对开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文所有笔记和代码可以到csdn下载:http://download.csdn.n ...
- CWMP开源代码研究3——ACS介绍
声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...
- CWMP开源代码研究4——认证流程
TR069 Http Digest 认证流程 一 流程及流程图 1.1盒端主动发起Http Digest认证流程 盒端CPE ...
- CWMP开源代码研究番外篇——博通方案
声明:本篇文章来自于某公司Cable Modem产品的文档资料,源码来自于博通公司,只提供参考(为保护产权,本人没有源码). 前文曾提到会写一篇关于博通的tr069,那么福利来了.福利,福利,福利,重 ...
随机推荐
- μCOS-Ⅲ——常用注意事项
**1,**main函数在调用其他函数之前必须先调用OSInit()函数对内核进行初始化. 2,所有的错误类型码都以OS_ERR_为前缀, 3,命名时尽量统一个格式,所有的函数.变量.宏定义和#def ...
- C# 连蒙带骗不知所以然的搞定USB下位机读写
公司用了一台发卡机,usb接口,半双工,给了个dll,不支持线程操作,使得UI线程老卡. 懊恼了,想自己直接通过usb读写,各种百度,然后是无数的坑,最终搞定. 现将各种坑和我自己的某些猜想记录一下, ...
- 关于Grid Layout
.wrapper { display: grid;/*产生一个块级的网格*/ grid-template-columns: repeat(3, 1fr);/*利用空格分隔的值定义网格的 ...
- 汉诺塔III
题目描述: 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动 ...
- 关于Java方法重载
今天在做项目的时候发现一个问题,如果有两个方法是重载的,而且他们的参数一个是父类,一个是子类,那么调用的时候会调用哪个函数呢? 做了个测试,发现调用的是子类. 例子: public class Ani ...
- JS 删除Array对象中的元素。
var idTemp=new Array(); var nameTemp = new Array(); nameTemp.splice($.inArray(“1”, nameTemp),1); idT ...
- openstack之neutron配额调整
1. 前言 neutron在安装配置完成之后,openstack为了实现对所有tenant对网络资源的使用,针对neutron设置有专门的配额,以防止租户使用过多的资源,而对其他的tena ...
- 将一个float型转化为内存存储格式的步骤
将一个float型转化为内存存储格式的步骤为: (1)先将这个实数的绝对值化为二进制格式. (2)将这个二进制格式实数的小数点左移或右移n位,直到小数点移动到第一个有效数字的右边. (3)从小数点右边 ...
- javascript 对象数组排序(按照科目级次)
需求 从后台获取的数据是这样的 上帝要这样的 背景 从后台获取到表格数据,然后填充到excel.当然是用js来填充的.js 本身的数组具有sort()功能.但是是针对 ...
- 浅析toString()和toLocaleString()的区别
翻看<javascript高级程序设计>,对toString()和toLocaleString()两者的区别并没有直白的说明,简单查阅了一下 ecmascript官方文档 和 MDN 二者 ...