原创作品,转载请注明出处,严禁非法转载。如有错误,请留言!

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动态库开发的更多相关文章

  1. CWMP开源代码研究——git代码工程

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  2. CWMP开源代码研究5——CWMP程序设计思想

    声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...

  3. CWMP开源代码研究——cwmp移植

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  4. CWMP开源代码研究7——cwmp移植

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  5. CWMP开源代码研究1——开篇之作

    原创作品,转载请注明出处,严禁非法转载.如有错误,请留言! email:40879506@qq.com 声明:本系列涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅 ...

  6. CWMP开源代码研究2——easycwmp安装和学习

    声明:本文是对开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文所有笔记和代码可以到csdn下载:http://download.csdn.n ...

  7. CWMP开源代码研究3——ACS介绍

    声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...

  8. CWMP开源代码研究4——认证流程

    TR069 Http Digest 认证流程   一 流程及流程图 1.1盒端主动发起Http Digest认证流程  盒端CPE                                    ...

  9. CWMP开源代码研究番外篇——博通方案

    声明:本篇文章来自于某公司Cable Modem产品的文档资料,源码来自于博通公司,只提供参考(为保护产权,本人没有源码). 前文曾提到会写一篇关于博通的tr069,那么福利来了.福利,福利,福利,重 ...

随机推荐

  1. SharePoint Framework 向web部件中添加外部库

    博客地址:http://blog.csdn.net/FoxDave 在进行开发的时候,你很可能会想要引用一些公开的JavaScript库到你的项目中,本文将会介绍如何打包和共享这些库. 打包脚本 默认 ...

  2. DAY:3 列表

    列表元素提取 mes = ["北京","哈尔滨","长春","沈阳","天津"] print(mes ...

  3. L362 When to Bring up Salary During the Job Interview Process

    Money is an awkward topic of conversation for many professionals—even more so when you’re busy tryin ...

  4. maven下载源码

    能下载到源代码的原则是仓库中打了resource的jar包 1.使用命令 mvn dependency:sources 下载依赖包的源代码. mvn dependency:sources -Ddown ...

  5. java版数据结构与算法第二章数组

    数组由一组具有相同类型的数据元素组成,并存储在一组连续存储单元中.一维数组是常量. 二维数组:若一维数组中的数据元素又是一堆数据结构,我们称之为二维数组.二维数组可以看成是n个列向量组成的线性表. 数 ...

  6. [转] Springboot的数据库操作

    转载自:https://www.cnblogs.com/juncaoit/p/7789034.html springBoot的数据库操作 一:操作数据库起步 1.Spring-Data-Jpa JPA ...

  7. 作为程序员你不知道中国互联网300强你就OUT了!

    很多程序员们工作一段时间之后,都想跳槽到综合实力更强的公司以获取高薪资或者接触到前沿的技术,但是哪些行业值得我们投入大量的时间,哪些公司属于我们行业中的佼佼者呢, 那么小编给您分析下2018年中国互联 ...

  8. 调试利器GDB(上)

    什么是GDB: GDB应用: 静态分析工具与动态分析工具: GDB启动方式: GDB启动之后会有一个交互式的命令行,可以输入GDB特定的命令让GDB去工作. gdb test.out意思是这一次gdb ...

  9. git教程:添加远程仓库

    转自: 添加远程仓库 现在的情景是,你已经在本地创建了一个Git仓库后,又想在GitHub创建一个Git仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过 ...

  10. 2018上C语言程序设计(高级)作业- 第4次作业成绩及总结

    作业地址 https://edu.cnblogs.com/campus/hljkj/CS2017-01/homework/1842 评分准则 第4次作业各项成绩包括三项: 完成WC项目:60分:基本功 ...