EasyCWMP学习
OpenACS:web服务器可以用来远程管理设备。
1 代码设计思路:
1.1 EasyCWMP主体分为了两个部分:
-
EasyCwmp Core:包含了负责与ACS服务器交互的功能
-
EasyCwmp DataModel:包含了TR098、TR181、TR104等与TR069相关的数据模型规范
对于单一的产品线,程序采用"单进程多线程"的思想。这样比较容易简洁,而且方便维护。若是多功能的产品,即一个设备上需要运行多个"CWMP进程", 那么我们使用了创建"多个子进程"的方法,每个子进程根据配置文件的不同从而实现设备的不同需求(该功能待完善)。
tr069程序处理流程大致分为:配置文件解析模块,日志模块,设备xml解析模块,任务模块以及事件处理模块(有关联),多线程模块(可插入模块)等。
原则上,CWMP core的程序代码不需要修改,主要是根据客户的需求修正或者进行"插入式的"新增事件类型和模块化处理。而设备相关的程序,我们封装成了一个动态库(libcwmp.so),便于独立编译和维护开发
1.2 tr069协议完整的通信过程.
2 代码总结
2.1 main 函数(easycwmp.c)
1. 读取命令参数
2. 创建进程id保存文件(/var/run/easycwmp.pid)
3. 创建全局变量struct cwmp_internal
struct cwmp_internal {
struct list_head events; //事件链表
struct list_head notifications; //通知链表
struct list_head downloads; //下载链表
struct list_head uploads; //上传链表
struct list_head scheduled_informs; // 计划通知链表
struct deviceid deviceid; //设备信息
int retry_count;
int download_count;
int upload_count;
int end_session;
int method_id;
bool get_rpc_methods;
bool hold_requests;
int netlink_sock[2];
};
4. uloop_init
初始化loop,创建epooll进行事件处理
5. backup_init();
从配置文件xml中读取下载、上传、事件信息,创建定时器。
6. external_init();
创建管道,启动脚本 "/usr/sbin/easycwmp", 进入while循环处理
7. config_load();
读取配置文件, 创建定时器periodic,周期执行client检测, 发送命令执行“update_value_change”。
8. cwmp_init_deviceid
发送命令“inform"+"device_id", 读取设备信息.
9. external_exit();
发送命令 "command", "exit", 退出子进程,即退出脚本循环.
10. 根据启动参数, 添加事件备份、增加定时器。
cwmp_add_event(EVENT_BOOT, NULL, 0, EVENT_BACKUP);
cwmp_add_inform_timer();
11. netlink_init
netlink初始化,增加fd处理netlink_new_msg, 监听设备接口状态
12. ubus_init()
初始化ubus, 与ubus建立连接, 调用函数ubus_handle_data()进行消息处理。
13. http_server_init()
http服务器初始化。
14. 根据命令参数 是否创建守护进程。
15. uloop_run(); 进行uloop循环处理。
2.2 netlink初始化
1. 建立netlink 通信, 调用easycwmp_netlink_interface 函数进行处理
2. 创建事件。
2.3 ubus初始化
1. 创建ubus_connect
2. 添加object
static struct ubus_object main_object = {
.name = "tr069",
.type = &main_object_type,
.methods =easycwmp_methods,
.n_methods = ARRAY_SIZE(easycwmp_methods),
};
3. 添加处理接口
easycwmp_methods,
static const struct ubus_method easycwmp_methods[] = {
UBUS_METHOD_NOARG("notify", easycwmpd_handle_notify),
UBUS_METHOD("inform", easycwmpd_handle_inform, inform_policy),
UBUS_METHOD("command", easycwmpd_handle_command, command_policy),
};
4. 模式中主要关注"notify", easycwmpd_handle_notify
启动定时器notify_timer 执行easycwmp_do_notify
int json_handle_check_parameter_value_change(char *line)
{
json_object *js_obj;
char *param_name, *param_value, *param_notif, *param_type;
js_obj=json_tokener_parse(line);
if (js_obj == NULL || json_object_get_type(js_obj) != json_type_object)
return -1;
param_name = json_common_get_string(js_obj, "parameter");
param_value = json_common_get_string(js_obj, "value");
param_notif = json_common_get_string(js_obj, "notification");
param_type = json_common_get_string(js_obj, "type");
if (param_type == NULL || param_type[0] == '\0')
param_type = "xsd:string";
cwmp_add_notification(param_name, param_value, param_type, param_notif);
json_object_put(js_obj);
return 0;
}
2.4 HTTP Server初始化
1. http_digest_init_nonce_priv_key
随机生成私钥。
2. 创建tcp server
3. uloop中添加fd处理,处理函数http_new_client
uloop_fd_add(&http_s.http_event, ULOOP_READ | ULOOP_EDGE_TRIGGER);
2.4.1 http_new_client
1. 接收client连接(只允许一个连接,接收最后一次连接)
2. 进行认证,两种方式Basic 和 Digest
3. 认证成功后,返回200 OK,产生事件
cwmp_connection_request(EVENT_CONNECTION_REQUEST);
EVENT_CONNECTION_REQUEST
添加定时器 cwmp_add_inform_timer ->cwmp_do_inform->cwmp_inform
2.4.1.1. cwmp_inform
1. http_client_init
初始化libcul 创建句柄
2. external_init
创建管道,启动脚本 "/usr/sbin/easycwmp", 进入while循环处理
3. rpc_inform
创建xml,通过发送脚本命令"inform"+"parameter",获取参数,以及存在的一些通知信息,填入到xml中,发送至服务器 。
4. cwmp_handle_messages->xml_handle_message->method->handler();
调用函数处理ACS发送的消息.
5. xml.c 中定义了method->handler的处理方法
const struct rpc_method rpc_methods[] = {
{ "GetRPCMethods", xml_handle_get_rpc_methods },
{ "SetParameterValues", xml_handle_set_parameter_values },
{ "GetParameterValues", xml_handle_get_parameter_values },
{ "GetParameterNames", xml_handle_get_parameter_names },
{ "GetParameterAttributes", xml_handle_get_parameter_attributes },
{ "SetParameterAttributes", xml_handle_set_parameter_attributes },
{ "AddObject", xml_handle_AddObject },
{ "DeleteObject", xml_handle_DeleteObject },
{ "Download", xml_handle_download },
{ "Upload", xml_handle_upload },
{ "Reboot", xml_handle_reboot },
{ "FactoryReset", xml_handle_factory_reset },
{ "ScheduleInform", xml_handle_schedule_inform },
};
3 脚本总结
3.1 easycwmp脚本
1. 程序运行时:执行easycwmp --json-input
2. 脚本进入while循环读取cmd命令
3. 运行命令返回输出参数