libdmclient 代码阅读
2016 年 11 月 22 日
libdmclient 是oma-dm的客户端库,基于syncml rtk库封装,后者源出自syncml.org,但现在打不开。libdmclient里面充斥着大量的指针强制转换,且缺少文档。虽然代码量不大,但阅读起来比较繁琐。
libdmclient里面包含了一个test的例子,从这个例子里可以看到libdmclient的使用方法,以下对其中的主要函数进行简单分析:
关于omadmclient_session_init,初始化
- 一切开始是从omadmclient_session_init开始,初始化一个session句柄,全局变量是g_session,该句柄对外是dmclt_session类型,也是一个无类型指针;在dmcore内部是internals_t类型的指针,定义在dmcore/src/internals.h。
- 在上面这个internals_t结构体中,InstanceID_t类型的smlH就是在SyncMLRTK(externals/SyncMLRTK/src/sml/inc/smldef.h)中的一个无类型(或short类型)指针,可以理解为syncml Handle。从最上层跟SyncML RTK基本就是靠这个句柄来维持instance的。
- 再说一下internals_t,这是libdmclient自己的session指针,其中有一个链表,放置所有element
- SyncML RTK初始化instance是在smlInitInstance函数,该函数设置了callback和options,输出是上面说到的InstanceID_t。其中callback在
dmcore/src/callbacks.c
中hard-coded,options仅包含了encoding(xml/wbxml)和workspaceSize(40000)两个值。smlInitInstance位于externals/SyncMLRTK/src/sml/mgr/all/mgrinstancemgr.c
,有注释。
关于omadmclient_session_start,启动会话
- 中间UI_Callback和add_mo过程略过,接下来是omadmclient_session_start。这里需要给出serverID。这个过程没做太多事情,主要就是检查serverID,和将状态置为STATE_CLIENT_INIT,应该是用于状态机的初始化状态。
- 从已经看到的代码来看,状态机处理非常简单,只有STATE_IN_SESSION/STATE_SERVER_INIT/STATE_CLIENT_INIT这3个,意思比较明显
关于omadmclient_get_next_packet,获得下一个要发的包
- 这里是根据句柄获得buffer的地方,buffer的类型是dmclt_buffer_t,定义在
dmcore/include/omadmclient.h
,其中调用到的主要函数有:- prvCreatePacket1,非STATE_IN_SESSION状况,也就是CI/SI的情况下,需要在internals_t结构中,增加alert和devinfo element
- prvComposeMessage,真正组合消息的代码,将internals_t中的链表,依次丢到syncml rtk,以允许底层生成xml buffer
- smlLockReadBuffer,锁定buffer,得到xml代码
关于omadmclient_process_reply,处理http/https响应,没有例子,暂时不看了,不解释。
关于omadmclient_session_close,关闭会话,不解释。
总体来说,omadmclient的本质就是在一个持续的for循环中,不断地完成这样的循环:
graph LR
A[发消息给server] --> B[收消息解析]
B --> C[更新本地数据结构/UI callback等]
C --> D[生成下一个包]
D --> A
而libdmclient的本质就是分层处理,在libdmclient这一层面,通过internals_t结构的全局变量,保存所有元素,并在需要时将所有元素丢到syncml RTK(其函数通常都以sml开头),并从syncml RTK得到最后输出的buffer。处理http/https结果的解析部分没看,但应该类似。
第二部分,omadmclient_session_add_mo,添加plugin
add_mo函数的参数是session句柄和mo接口指针,session句柄和mo的关系是:(internals_t)->dmtreeH(dmtree_t)->MOs(mo_mgr_t),括号里面是数据结构名。
核心的实现在momgr.c
中的momgr_add_plugin函数中,添加mo的主要动作包括:
- 执行initFunc,此时得到data的回调
- 将mo plugin的interface/data/container塞到MOs中
每一个mo包含base_uri和以下回调函数:
- initFunc
- closeFunc
- isNodeFunc
- findURNFunc
- getFunc
- setFunc
- getACLFunc
- setACLFunc
- renameFunc
- deleteFunc
- execFunc
不需要全部实现,但initFunc必须要有,否则无法加到session中。
这些函数的定义在dmcore/include/omadmtree_mo.h
中