博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于Linux内核红黑树的TR069参数解析工具:树形结构+CPE RPC支持
阅读量:2029 次
发布时间:2019-04-28

本文共 61489 字,大约阅读时间需要 204 分钟。

目录


tr069_oid.h

/* Dependencies ------------------------------------------------------------------------------------------------------*/#ifndef __CPE_OID_REG_H#define __CPE_OID_REG_H 1#include "easy_macros.h"#include "rbtree.h"#include "flog.h"/* Constants ---------------------------------------------------------------------------------------------------------*/#define TR069_OID_ITEM_SIZE 64  /* 参数路径单项的最大长度 Device.DeviceInfo.XXXX 中 DeviceInfo的最大长度 */#define TR069_OID_SIZE      256 /* 参数路径的最大长度  ,Device.DeviceInfo.XXXX 的最大长度             *//* 参数节点类型 Device.DeviceInfo.1.A  A为叶子,其余为枝干          */enum TR069_OID_ITEM_TYPE {    TR069_OID_ITEM_TYPE_BRANCH, //枝干    TR069_OID_ITEM_TYPE_LEAF    //叶子};/* 参数节点Object类型 Device.DeviceInfo.1.A                                         ^   Table 矢量,其余为Scalar 标量*/enum TR069_OID_TYPE {    TR069_OID_TYPE_TABLE,   //表    TR069_OID_TYPE_SCALAR,  //标量};    /* Types -------------------------------------------------------------------------------------------------------------*/struct tr069_oid;struct tr069_oid_leaf;/** *  参数设置回调函数 *  说明: *      当接口 "tr069_oid_set_parameter_values" 被调用时,该回调函数将被调用。 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。 *  参数说明: *      node        被设置的节点,禁止直接修改该数据结构,会影响参数树的结构。 *      isObj       参数路径中是否存在可创建/可删除节点,当存在时,其值为真值,否则为假。 *                  如: 设置 Device.IP.Interface.1.IPv4Address.2.IPAddress,该值为真。 *      nObj        参数路径中出现的实例号个数。当 isObj 为真时,该参数可用。 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,nObj==2. *      ObjInsNums  参数路径中出现的实例号数组。当 isObj 为真时,该参数可用。 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,ObjInsNums[0]==1, ObjInsNums[1] = 2. *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argc"。 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argv"。 */typedef void (*tr069_oid_set_fn_t)(struct tr069_oid *node, bool isObj, int nObj, int ObjInsNums[], int argc, void *argv[]);/** *  目标创建回调函数 *  说明: *      当接口 "tr069_oid_add_object" 被调用时,该回调函数将被调用。 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。 *  参数说明: *      node        被添加的节点,禁止直接修改该数据结构,会影响参数树的结构。 *                  当 注册 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress" ,可使用 "tr069_oid_add_object" 接口添加实例 *                  当 tr069_oid_add_object(参数树, Device.IP.Interface.)被调用时,注册的该回调函数将被调用。 *      currObjIdx  当前添加的实例参数路径中的实例号位置,起始值为 1。 *                  若支持添加object的参数路径为 Device.A.{i}.{i}.{i}.{i}.{i}.{i}.{i}.{i}.name *                  添加一个实例 Device.A. 时, currObjIdx==1 *                  添加一个实例 Device.A.1. 时, currObjIdx==2 *                  添加一个实例 Device.A.1.1. 时, currObjIdx==3 *                  ... *                  添加一个实例 Device.A.1.1.1.1.1.1.1. 时, currObjIdx==8 * *      nPrevObj        创建的当前参数路径之前中出现的实例号个数。 *      prevObjInsNums  创建的当前参数路径之前中出现的实例号。 * *      参数 nPrevObj 和 prevObjInsNums 的例子: *                  AddObject: Device.A.        nPrevObj==0,    prevObjInsNums=NULL *                  AddObject: Device.A.1.      nPrevObj==1,    prevObjInsNums={1,} *                  AddObject: Device.A.1.1.    nPrevObj==2,    prevObjInsNums={1,1,} *                      ... *                  AddObject: Device.A.1.1.1.2.3.1.1. nPrevObj==8, prevObjInsNums={1,1,1,2,3,1,1,} * *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "add_argc"。 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "add_argv"。 *      ObjInsNum   生成的实例号。 1,2,3,4,5... *      aliasName   别名:TR069协议规定。 * *  返回值:     *      AddObject成功,生成实例号填入 ObjInsNum , 并返回真值。否则返回假。 */typedef bool (*tr069_oid_addobj_fn_t)(struct tr069_oid *node, int currObjIdx, int nPrevObj, int prevObjInsNums[], int argc, void *argv[], int *ObjInsNum, char aliasName[TR069_OID_ITEM_SIZE]);/** *  目标删除回调函数 *  说明: *      当接口 "tr069_oid_delete_object" 被调用时,该回调函数将被调用。 *      该回调函数在参数注册时被参数树保存。使用 "tr069_oid_register" 注册。 *  参数说明:(见AddObject接口回调   tr069_oid_addobj_fn_t        ) *      node        被删除的节点,禁止直接修改该数据结构,会影响参数树的结构。 *      nObj        参数路径中出现的实例号个数。当 isObj 为真时,该参数可用。 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,nObj==2. *      ObjInsNums  参数路径中出现的实例号数组。当 isObj 为真时,该参数可用。 *                  当参数为 Device.IP.Interface.1.IPv4Address.2.IPAddress 时,ObjInsNums[0]==1, ObjInsNums[1] = 2. *      argc        用户注册参数个数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argc"。 *      argv        用户注册参数,该参数为 "tr069_oid_register" 注册时填写 的 "set_argv"。 */typedef bool (*tr069_oid_delobj_fn_t)(struct tr069_oid *node, int nObj, int ObjInsNums[], int argc, void *argv[]);/* TR069 OID树节点结构 */struct tr069_oid {        char oidNameItem[TR069_OID_ITEM_SIZE];/* 参数路径中的单项名称 */    char oidAliasNameItem[TR069_OID_ITEM_SIZE];/* 参数单项名称的别名 */        unsigned int oidInstanceNum; /* 实例号 */        enum TR069_OID_ITEM_TYPE node_type; /* 节点单项类型:枝干 或 叶子 */    enum TR069_OID_TYPE oid_type; /* 目标节点类型:是否可创建,表或标量 */        int writeable; //是否可写        /* 保存下一级 */    rt_rbtree_t child;  //该节点下的下一级节点                        //A.B1.C.D                        //A.B2.C.D                        //A.B3.C.D                        //A.child => B1, B2, B3                            struct tr069_oid *father;   //所有节点指向该节点的父节点                                // A.B.C.D => D.father = &C;                                    struct tr069_oid_leaf *leaf_value;    //每个a.b.c.d的叶子"d"需要malloc该块内存        struct tr069_oid_obj_opt *obj_operation; //每个A.{i}.B 中的"{i}"需要malloc该块内存                                                //并将注册时的参数列表填入该块内存};/* TR069 OID树叶子节点数据:供用户使用 */struct tr069_oid_leaf {    tr069_oid_set_fn_t set_fn;  /* 参数设置回调函数,在注册参数时提供 */    int set_argc;/* 参数设置用户参数个数 */    void **set_argv;/* 参数设置用户参数 */    char value[TR069_OID_SIZE];/* 参数值 */    int Notification; /* 参数通知级别:参考TR069协议 *///check in ParameterAttributeStruct, "GetParameterAttribute"};/* 目标创建删除用户回调函数 */struct tr069_oid_obj_opt {    /* 目标创建 */    tr069_oid_addobj_fn_t add_fn;    int add_argc;    void **add_argv;    /* 目标删除 */    tr069_oid_delobj_fn_t del_fn;    int del_argc;    void **del_argv;};/* TR069 OID路径名结构 */struct tr069_oid_names {    int count;/* 获取的参数名个数 */    ParameterInfoStruct *NameList;/* 参数名 */};/* TR069 OID 值结构 */struct tr069_oid_values {    int count;/* 获取的参数值的个数 */    ParameterValueStruct *ValueList;/* 参数值 */};/* TR069 OID 属性值结构 */struct tr069_oid_attrs {    int count;/* 参数属性个数 */    ParameterAttributeStruct *AttrList;/* 参数属性 */};/* Macros ------------------------------------------------------------------------------------------------------------*/#define TR069_OID_GetParamNamesShow(tree, str, nextlevel, printfn) \    {\        printfn("\n--------------GetParamNames %s--------------\n", str); \        struct tr069_oid_names *__names = tr069_oid_get_parameter_names(tree, str, nextlevel);\        int __inames;\        for(__inames=0;__inames<__names->count;__inames++) {\            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"writable\": \"%d\" }\n", \                        __inames, __names->count, __names->NameList[__inames].Name, __names->NameList[__inames].Writable);\        }\        printfn("------------------------------------------------------\n");\        tr069_oid_get_parameter_names_free(__names);\    }#define TR069_OID_GetParamValuesShow(tree, str, printfn) \    {\        printfn("\n-----------GetParamValues %s-----------\n", str); \        struct tr069_oid_values *__values = tr069_oid_get_parameter_values(tree, str);\        int __ivalues;\        for(__ivalues=0;__ivalues<__values->count;__ivalues++) {\            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"value\": \"%s\" }\n", \                        __ivalues, __values->count, __values->ValueList[__ivalues].Name, __values->ValueList[__ivalues].Value);\        }\        printfn("------------------------------------------------------\n");\        tr069_oid_get_parameter_values_free(__values);\    }#define TR069_OID_GetParamAttributeShow(tree, str, printfn) \    {\        printfn("\n------------GetParamAttribute %s------------\n", str); \        struct tr069_oid_attrs *__attrs = tr069_oid_get_parameter_attributes(tree, str);\        int __iattrs;\        for(__iattrs=0;__iattrs<__attrs->count;__iattrs++) {\            printfn(">> %d/%d:{ \"parameter\": \"%s\", \"notification\": \"%d\" }\n", \                        __iattrs, __attrs->count, __attrs->AttrList[__iattrs].Name, __attrs->AttrList[__iattrs].Notification);\        }\        printfn("------------------------------------------------------\n");\        tr069_oid_get_parameter_attributes_free(__attrs);\    }/* Globals -----------------------------------------------------------------------------------------------------------*//* Functions ---------------------------------------------------------------------------------------------------------*//** *  参数树的创建/初始化 与 摧毁 */rt_rbtree_t tr069_oid_tree_create();void tr069_oid_tree_destroy(rt_rbtree_t oid_root);/** *  参数注册 *  函数说明: *      当使用 接口 tr069_oid_tree_create 创建参数树后,可以使用该接口注册一个参数。 *  函数参数列表: *      oid_root        参数树 *      ParameterPath   一个完整的参数路径, 如 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress" *      writeable       是否可写(0-不可写,1-可写),值得一提的是,该值只决定了 ParameterPath 路径规定的最后一个参数,而其他参数的可写性, *                      由接口内部决定,如 参数 "Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress" 的可写性为: *                      可写的有:         Interface IPv4Address  *                      不可写的有:  Device IP {i}  *                      由参数 writeable 决定 IPAddress 是否可写 *      default_value   一个默认值,字符串形式 *      Notification    通知级别,参考TR069协议中的 ParameterAttributeStruct 结构,取值 0~6 *      set_fn          参考 tr069_oid_set_fn_t  *      set_argc        set_fn 的入参 *      set_argv        set_fn 的入参 *      add_fn          参考 tr069_oid_addobj_fn_t  *      add_argc        add_fn 的入参 *      add_argv        add_fn 的入参 *      del_fn          参考 tr069_oid_delobj_fn_t  *      del_argc        del_fn 的入参 *      del_argv        del_fn 的入参 */int tr069_oid_register(rt_rbtree_t oid_root, char ParameterPath[TR069_OID_SIZE],                          int writeable, char default_value[TR069_OID_SIZE], int Notification,                         tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[],                         tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[],                         tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[]);/** *  参数轮询 *  函数说明: *      该参数将轮询此树的所有节点, display 将被调用。 遗憾的是, oid 将不被允许修改, 否则会捣乱树结构, oid只读。 *  函数参数列表: *      oid_root    参数树 *      display     轮询树是被调用的回调函数 *                  oid 参数节点 *                  arg 用户数据 *      arg         用户数据, 将被透传至 display 的参数列表中 */void tr069_oid_display(rt_rbtree_t oid_root, void (*display)(struct tr069_oid *oid, void *arg), void *arg);/** *  参数名获取 *  函数说明: *      GetParameterNames  *  函数参数列表: *      oid_root    参数树 *      pathPrefix  参数路径, 如 "Device." *      nextlevel   是否只获取下一级参数节点, 取值0或1,参考标准协议。 *  返回值    *      结构 struct tr069_oid_names 该结构需要使用 tr069_oid_get_parameter_names_free 进行释放 *       */struct tr069_oid_names *tr069_oid_get_parameter_names(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE], int nextlevel);void tr069_oid_get_parameter_names_free(struct tr069_oid_names *oid_names);/** *  参数获取 *  函数说明: *      GetParameterValues *  函数参数列表: *      oid_root    参数树 *      pathPrefix  参数路径, 如 "Device." *  返回值 *      结构    struct tr069_oid_values   , 需要使用 tr069_oid_get_parameter_values_free 释放内存 *       *       */struct tr069_oid_values *tr069_oid_get_parameter_values(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);void tr069_oid_get_parameter_values_free(struct tr069_oid_values *oid_values);/** *  参数设置 *  函数说明: *      SetParameterValues *  函数参数列表: *      oid_root    参数树 *      paramPath   参数的完整路径, 如 "Device.IPsec.Enable" *      paramValue  参数值, 字符串 *  返回值 *      结构 struct tr069_oid, 很遗憾, 这个返回值不许修改,否则会损坏树结构。 */struct tr069_oid *tr069_oid_set_parameter_values(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], char paramValue[TR069_OID_SIZE]);/** *  参数属性获取 *  函数说明: *      GetParamAttributes *  函数参数列表: *      oid_root    参数树 *      pathPrefix  参数路径, 如 "Device." *  返回值 *      结构      struct tr069_oid_attrs, 需要使用 tr069_oid_get_parameter_attributes_free 释放内存 */struct tr069_oid_attrs *tr069_oid_get_parameter_attributes(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);void tr069_oid_get_parameter_attributes_free(struct tr069_oid_attrs *oid_attrs);/** *  参数属性设置 *  函数说明: *      SetParamAttributes *  函数参数列表: *      oid_root    参数树 *      paramPath   参数的完整路径, 如 "Device.IPsec.Enable" *      Notification    通知级别,参考TR069协议中的 ParameterAttributeStruct 结构,取值 0~6 *  返回值 *      结构 struct tr069_oid, 很遗憾, 这个返回值不许修改,否则会损坏树结构。 */struct tr069_oid *tr069_oid_set_parameter_attributes(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], int Notification);/** *  目标实例添加和删除 *  函数说明: *      AddObject DeleteObject *  函数参数列表: *      oid_root        参数树 *      ParameterPath   参数路径, 如 注册了 Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress *                      此时 Device.IP.Interface. 是支持 AddObject 的,当 调用了 tr069_oid_add_object , 参见注册接口: *                      tr069_oid_register 的 add_fn 将被调用, 需要生成   实例号。 *      pathPrefix      参数路径, 如添加了目标实例 1,-> 可使用 "Device.IP.Interface.1." 对其进行删除, 可调用该接口删除该实例。 *  返回值 *      tr069_oid_add_object 成功返回实例号, 失败返回 VOS_ERROR *       */int tr069_oid_add_object(rt_rbtree_t oid_root, char ParameterPath[TR069_OID_SIZE]);int tr069_oid_delete_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]);#endif //__CPE_OID_REG_H

tr069_oid.c

/* Dependencies ------------------------------------------------------------------------------------------------------*/#include 
#include
#include
#include "tr069_oid.h"/* Types -------------------------------------------------------------------------------------------------------------*//* Constants ---------------------------------------------------------------------------------------------------------*/#define TABLE_NODE "TABLE"/* Macros ------------------------------------------------------------------------------------------------------------*//* Globals -----------------------------------------------------------------------------------------------------------*/ /* Functions ---------------------------------------------------------------------------------------------------------*//* 正则化检验参数字符串是否合法 * 例如:Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity */static int _unused oid_string_pattern_check(char *oidString){#define OID_REGEX_PATTERN "^Device\\.[a-zA-Z]\\w+\\.(([a-zA-Z0-9]\\w+|\\{[0-9a-z]\\})\\.)*[a-zA-Z0-9]\\w+"// ^Device\\.[a-zA-Z]\\w+\\.(([a-zA-Z]\\w+|\\{[0-9a-z]\\})\\.)*[a-zA-Z0-9]\\w+ int ret = VOS_ERROR; int status = 0; int flag = REG_EXTENDED; regmatch_t pmatch[1]; const size_t nmatch = 1; regex_t reg; const char *pattern = OID_REGEX_PATTERN; regcomp(®, pattern, flag); status = regexec(®, oidString, nmatch, pmatch, 0); if(status == REG_NOMATCH){ ret = VOS_ERROR; }else if(status == 0){ ret = VOS_OK; } regfree(®); return ret;}/* OID 节点项的对比函数 */static int _unused __tr069_oid_node_cmp(void *d1, void *d2){ struct tr069_oid *oid1 = d1, *oid2 = d2; char *oidName1 = oid1->oidNameItem; char *oidName2 = oid2->oidNameItem; if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) > 0) return GT; else if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) == 0) return EQ; else if(strncmp(oidName1, oidName2, TR069_OID_ITEM_SIZE) < 0) return LT; return EQ;}/* OID 树的创建 */static void _unused __tr069_oid_tree_create(rt_rbtree_t *tree){ *tree = rt_rbtree_init_nonmalloc("OIDTree", __tr069_oid_node_cmp);}/* 初始化OID的树的根 */rt_rbtree_t tr069_oid_tree_create(){ rt_rbtree_t oid_root; __tr069_oid_tree_create(&oid_root); return oid_root;}/* 获取参数名中Item的项数 * 例如:Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity 返回 5 */static int _unused __get_N_item(char path[TR069_OID_SIZE]){ int iItem = 0; int iChar = 0; int len = strlen(path); while(path[iChar] != '\0' && iChar <= len) { while(path[iChar] != '.' && path[iChar] != '\0') { iChar++; } iItem++; iChar++; } return iItem;}/* 获取参数名中某一项的 名称 * 例如: * ParameterPath = Device.FaultMgmt.ExpeditedEvent.{2}.PerceivedSeverity * iItem = 2 * 那么, oidNameItem = FaultMgmt */static int _unused __get_I_item_name(char path[TR069_OID_SIZE], int iItem, char oidNameItem[TR069_OID_ITEM_SIZE]){ int __iItem = 0; int iChar = 0; int len = strlen(path); while(path[iChar] != '\0' && iChar <= len) { memset(oidNameItem, 0, TR069_OID_ITEM_SIZE); int i = 0; while(path[iChar] != '.' && path[iChar] != '\0') { oidNameItem[i++] = path[iChar++]; } oidNameItem[i] = '\0'; __iItem++; iChar++; if(__iItem == iItem) { return iItem; } } return -1;}/* 向树种递归添加节点,若不存在该节点则创建 */static struct tr069_oid * _unused __oid_tree_add_node(struct tr069_oid *father, rt_rbtree_t tree, char currPath[TR069_OID_SIZE], int writeable, char *defaultValue, int Notification, tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[], tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[], tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[]){ /* OID名称 */ char oidNameItem[TR069_OID_ITEM_SIZE] = {0}; char oidNameItemTmp[TR069_OID_ITEM_SIZE] = {0}; memset(oidNameItem, 0, TR069_OID_ITEM_SIZE); memset(oidNameItemTmp, 0, TR069_OID_ITEM_SIZE); /* 获取项数 */ int nItem = __get_N_item(currPath); __get_I_item_name(currPath, 1, oidNameItem);/* 解析出第一项名称 */ /* 是否为“{3}”类型 */ int oidTableNode = 0; if(oidNameItem[0] == '{') { oidTableNode = 1; if(!add_fn || !del_fn) { vos_err_print("Error: Must fill 'add_fn' and 'del_fn' when register a addable object OID.\n"); return NULL; } } /* 申请内存 */ struct tr069_oid *new_node = malloc(sizeof(struct tr069_oid)); VOS_MemZero(new_node->oidNameItem, TR069_OID_ITEM_SIZE); VOS_MemZero(new_node->oidAliasNameItem, TR069_OID_ITEM_SIZE); new_node->obj_operation = NULL; new_node->leaf_value = NULL; new_node->father = father; if(oidTableNode) { VOS_Snprintf(oidNameItemTmp, TR069_OID_ITEM_SIZE, TABLE_NODE); new_node->father->writeable = 1; new_node->oid_type = TR069_OID_TYPE_TABLE; new_node->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt )); new_node->obj_operation->add_fn = add_fn; new_node->obj_operation->add_argc = add_argc; new_node->obj_operation->add_argv = add_argv; new_node->obj_operation->del_fn = del_fn; new_node->obj_operation->del_argc = del_argc; new_node->obj_operation->del_argv = del_argv; } else { VOS_StrCpy(oidNameItemTmp, oidNameItem); if(nItem == 1) { new_node->writeable = writeable; //叶子 new_node->node_type = TR069_OID_ITEM_TYPE_LEAF; } else { new_node->writeable = 0; //枝干不可写 new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH; } new_node->oid_type = TR069_OID_TYPE_SCALAR; } VOS_StrCpy(new_node->oidNameItem, oidNameItemTmp); new_node->oidInstanceNum = 0; int exist_flag = 0; rt_rbtree_node_t *node = rt_rbtree_search(tree, new_node); if( node ) { //已存在的节点 if(oidTableNode) { free(new_node->obj_operation); } free(new_node); new_node = node->data; new_node->father = father; if(nItem != 1) { new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH; } else if(nItem == 1) { new_node->writeable = writeable; //叶子 new_node->node_type = TR069_OID_ITEM_TYPE_LEAF; } exist_flag = 1; } else { //不存在该节点 exist_flag = 0; __tr069_oid_tree_create(&new_node->child); rt_rbtree_insert(tree, new_node, sizeof(struct tr069_oid)); } /* 若为最后一项:叶子节点 */ if(nItem == 1) { if(exist_flag) return NULL; new_node->node_type = TR069_OID_ITEM_TYPE_LEAF; new_node->writeable = writeable; //只设置最后一个叶子节点 new_node->leaf_value = malloc(sizeof(struct tr069_oid_leaf)); VOS_StrnCpy(new_node->leaf_value->value, defaultValue, TR069_OID_SIZE); new_node->leaf_value->Notification = Notification; new_node->leaf_value->set_fn = set_fn; new_node->leaf_value->set_argc = set_argc; new_node->leaf_value->set_argv = set_argv; return new_node; /* 非叶子节点,递归添加 */ } else { new_node->node_type = TR069_OID_ITEM_TYPE_BRANCH; new_node->leaf_value = NULL;// new_node->writeable = 0; //枝干不可写 int iChar = 0; while(currPath[iChar++] != '.'); __oid_tree_add_node(new_node, new_node->child, &currPath[iChar], writeable, defaultValue, Notification, set_fn, set_argc, set_argv, add_fn, add_argc, add_argv, del_fn, del_argc, del_argv); } return NULL;}/* 获取路径下的项 */static struct tr069_oid _unused* __oid_tree_find_oid_path(rt_rbtree_t tree, char currPath[TR069_OID_SIZE]){ char oidNameItem[TR069_OID_ITEM_SIZE] = {0}; memset(oidNameItem, 0, TR069_OID_ITEM_SIZE); int nItem = __get_N_item(currPath); __get_I_item_name(currPath, 1, oidNameItem); struct tr069_oid *find_node = malloc(sizeof(struct tr069_oid)); memset(find_node->oidNameItem, 0, TR069_OID_ITEM_SIZE); memset(find_node->oidAliasNameItem, 0, TR069_OID_ITEM_SIZE); // VOS_MemZero(find_node->ParameterPath, TR069_OID_SIZE); VOS_StrCpy(find_node->oidNameItem, oidNameItem); rt_rbtree_node_t *node = rt_rbtree_search(tree, find_node); if( node ) { //存在该节点 free(find_node); find_node = node->data; if(nItem == 1) { return find_node; } else { int iChar = 0; while(currPath[iChar++] != '.'); return __oid_tree_find_oid_path(find_node->child, &currPath[iChar]); } } return NULL;}/* 递归获取树下面所有的节点数 */static int _unused __oid_tree_subcount(rt_rbtree_t tree, int nextlevel){ int count = 0; struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(tree); node; node=rt_rbtree_getnext(node)) { this_oid = node->data; if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue; count++; if(!nextlevel) { count += __oid_tree_subcount(this_oid->child, nextlevel); } } return count;}/* 递归获取树下面所有的叶子节点数 */static int _unused __oid_tree_subleafcount(rt_rbtree_t tree){ int count = 0; struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(tree); node; node=rt_rbtree_getnext(node)) { this_oid = node->data; if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue; if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) { count++; continue; } count += __oid_tree_subleafcount(this_oid->child); } return count;}/* 递归获取树下面所有的节点数 */static void __tr069_oid_oids_get(struct tr069_oid *oid, ParameterInfoStruct *NameList, int *ioid, int nextlevel){ struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) { this_oid = node->data; if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue; VOS_MemZero(NameList[*ioid].Name, sizeof(char)*TR069_OID_SIZE); NameList[*ioid].Writable = this_oid->writeable; char tmp[TR069_OID_SIZE] = {0}; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) { VOS_MemZero(tmp, TR069_OID_SIZE); VOS_StrCat(tmp, NameList[*ioid].Name); VOS_Sprintf(NameList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", tmp); } (*ioid)++; if(!nextlevel && this_oid) { //如果不止获取下一级节点 __tr069_oid_oids_get(this_oid, NameList, ioid, nextlevel); } }}/* 递归获取树下面所有的叶子节点数 */static void __tr069_oid_oids_getleaf_value(struct tr069_oid *oid, ParameterValueStruct *ValuesList, int *ioid){ struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) { this_oid = node->data; if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue; if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) { char tmp[TR069_OID_SIZE] = {0}; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) { VOS_MemZero(tmp, TR069_OID_SIZE); VOS_StrCat(tmp, ValuesList[*ioid].Name); VOS_Sprintf(ValuesList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", tmp); }// printf("%s: %s\n", tmp_oid->oidNameItem, oid_values->ValueList[i].Name); VOS_StrnCpy(ValuesList[*ioid].Value, this_oid->leaf_value->value, TR069_OID_SIZE); (*ioid)++; continue; } else { __tr069_oid_oids_getleaf_value(this_oid, ValuesList, ioid); } }}/* 递归获取树下面所有的叶子节点数 */static void __tr069_oid_oids_getleaf_attr(struct tr069_oid *oid, ParameterAttributeStruct *AttrsList, int *ioid){ struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(oid->child); node; node=rt_rbtree_getnext(node), this_oid = NULL) { this_oid = node->data; if(VOS_StrnCmp(TABLE_NODE, this_oid->oidNameItem, TR069_OID_ITEM_SIZE) == 0) continue; if(this_oid->node_type == TR069_OID_ITEM_TYPE_LEAF) { char tmp[TR069_OID_SIZE] = {0}; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = this_oid; tmp_oid; tmp_oid = tmp_oid->father) { VOS_MemZero(tmp, TR069_OID_SIZE); VOS_StrCat(tmp, AttrsList[*ioid].Name); VOS_Sprintf(AttrsList[*ioid].Name, "%s%s%s", tmp_oid->oidNameItem, tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", tmp); }// printf("%s: %s\n", tmp_oid->oidNameItem, oid_values->ValueList[i].Name); AttrsList[*ioid].Notification = this_oid->leaf_value->Notification; (*ioid)++; continue; } else { __tr069_oid_oids_getleaf_attr(this_oid, AttrsList, ioid); } }}/* 注册一个参数 */int tr069_oid_register(rt_rbtree_t oid_root, char absolutePath[TR069_OID_SIZE], int writeable, char default_value[TR069_OID_SIZE], int Notification, tr069_oid_set_fn_t set_fn, int set_argc, void *set_argv[], tr069_oid_addobj_fn_t add_fn, int add_argc, void *add_argv[], tr069_oid_delobj_fn_t del_fn, int del_argc, void *del_argv[]){ if(VOS_OK != oid_string_pattern_check(absolutePath)) { vos_err_print("TR069 Notmatch: %s\n", absolutePath); return VOS_ERROR; } if(!default_value ) {//必须有默认值 vos_err_print("TR069 must need default value.\n"); return VOS_ERROR; } struct tr069_oid *oid = __oid_tree_add_node(NULL, oid_root, absolutePath, writeable, default_value, Notification, set_fn, set_argc, set_argv, add_fn, add_argc, add_argv, del_fn, del_argc, del_argv); if(oid) { return VOS_OK; } else {// vos_warning_print("Exist Node: %s\n", absolutePath); return VOS_ERROR; } return VOS_OK;}/* 递归操作一个OID */static void __tr069_oid_display(rt_rbtree_t this_tree, void (*display)(struct tr069_oid *oid, void *arg), void *arg){ if(!this_tree) return; struct tr069_oid *this_oid = NULL; rt_rbtree_node_t *node = NULL; for(node = rt_rbtree_getfirst(this_tree); node; node=rt_rbtree_getnext(node)) { this_oid = node->data; display(this_oid, arg); __tr069_oid_display(this_oid->child, display, arg); }}/* 操作一个OID */_api void tr069_oid_display(rt_rbtree_t oid_root, void (*display)(struct tr069_oid *oid, void *arg), void *arg) { __tr069_oid_display(oid_root, display, arg);}/* GetParameterNames */_api struct tr069_oid_names *tr069_oid_get_parameter_names(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE], int nextlevel){ int count = 0; struct tr069_oid_names *oid_names = malloc(sizeof(struct tr069_oid_names)); oid_names->count = 0; oid_names->NameList = NULL; struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", pathPrefix); return oid_names; } if(!nextlevel) (count)++; count += __oid_tree_subcount(oid_item->child, nextlevel); oid_names->count = count; oid_names->NameList = malloc(sizeof(ParameterInfoStruct)*(count)); int i = 0; if(!nextlevel) { strcpy(oid_names->NameList[i].Name, pathPrefix); oid_names->NameList[i].Writable = oid_item->writeable; (i)++; } __tr069_oid_oids_get(oid_item, oid_names->NameList, &i, nextlevel); return oid_names;}/* GetParameterNames Free */_api void tr069_oid_get_parameter_names_free(struct tr069_oid_names *oid_names){ if(!oid_names) return; free(oid_names->NameList); free(oid_names);}/* 查询一个参数 *//* GetParameterValues */_api struct tr069_oid_values *tr069_oid_get_parameter_values(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]){ int count = 0; struct tr069_oid_values *oid_values = malloc(sizeof(struct tr069_oid_values)); oid_values->count = 0; oid_values->ValueList = NULL; struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", pathPrefix); return oid_values; } if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { count ++; } count += __oid_tree_subleafcount(oid_item->child);// vos_err_print("count = %d\n", count); oid_values->count = count; oid_values->ValueList = malloc(sizeof(ParameterValueStruct)*(count)); VOS_MemZero(oid_values->ValueList, sizeof(ParameterValueStruct)*(count)); int i = 0;// printf(">>>%s\n", oid_values->ValueList[i].Name); /* 如果是叶子 */ if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { char tmp[TR069_OID_SIZE] = {0}; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = oid_item; tmp_oid; tmp_oid = tmp_oid->father) { VOS_MemZero(tmp, TR069_OID_SIZE); VOS_StrCat(tmp, oid_values->ValueList[i].Name); VOS_Sprintf(oid_values->ValueList[i].Name, "%s%s%s", tmp_oid->oidNameItem, tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", tmp); } (i)++; } else { __tr069_oid_oids_getleaf_value(oid_item, oid_values->ValueList, &i); } return oid_values;}/* GetParameterValues Free */_api void tr069_oid_get_parameter_values_free(struct tr069_oid_values *oid_values){ if(!oid_values) return; free(oid_values->ValueList); free(oid_values);}/* 查询一个参数 *//* GetParameterAttribute */_api struct tr069_oid_attrs *tr069_oid_get_parameter_attributes(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]){ int count = 0; struct tr069_oid_attrs *oid_attrs = malloc(sizeof(struct tr069_oid_attrs)); oid_attrs->count = 0; oid_attrs->AttrList = NULL; struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", pathPrefix); return oid_attrs; } if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { count ++; } count += __oid_tree_subleafcount(oid_item->child);// vos_err_print("count = %d\n", count); oid_attrs->count = count; oid_attrs->AttrList = malloc(sizeof(ParameterAttributeStruct)*(count)); VOS_MemZero(oid_attrs->AttrList, sizeof(ParameterAttributeStruct)*(count)); int i = 0; /* 如果是叶子 */ if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { char tmp[TR069_OID_SIZE] = {0}; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = oid_item; tmp_oid; tmp_oid = tmp_oid->father) { VOS_MemZero(tmp, TR069_OID_SIZE); VOS_StrCat(tmp, oid_attrs->AttrList[i].Name); VOS_Sprintf(oid_attrs->AttrList[i].Name, "%s%s%s", tmp_oid->oidNameItem, tmp_oid->node_type==TR069_OID_ITEM_TYPE_LEAF?"":".", tmp); } (i)++; } else { __tr069_oid_oids_getleaf_attr(oid_item, oid_attrs->AttrList, &i); } return oid_attrs;}/* GetParameterValues Free */_api void tr069_oid_get_parameter_attributes_free(struct tr069_oid_attrs *oid_attrs){ if(!oid_attrs) return; free(oid_attrs->AttrList); free(oid_attrs);}static void _unused __tr069_tree_obj_count(struct tr069_oid * oid_tail, int **instanceNums, int *instanceCount){ *instanceCount = 0; struct tr069_oid *tmp_oid = NULL; for(tmp_oid = oid_tail; tmp_oid; tmp_oid = tmp_oid->father) { if(tmp_oid->oidInstanceNum) { (*instanceCount)++; if(*instanceCount == 1) { *instanceNums = malloc(sizeof(int)*(*instanceCount)); } else { *instanceNums = realloc(*instanceNums, sizeof(int)*(*instanceCount)); } (*instanceNums)[(*instanceCount)-1] = tmp_oid->oidInstanceNum; } } int i; for(i=0; i<*instanceCount/2;i++) { (*instanceNums)[i] += (*instanceNums)[*instanceCount-1-i]; (*instanceNums)[*instanceCount-1-i] = (*instanceNums)[i] - (*instanceNums)[*instanceCount-1-i]; (*instanceNums)[i] -= (*instanceNums)[*instanceCount-1-i]; }}struct tr069_oid *tr069_oid_set_parameter_values(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], char paramValue[TR069_OID_SIZE]){ struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, paramPath); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", paramPath); return NULL; } if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { VOS_StrnCpy(oid_item->leaf_value->value, paramValue, TR069_OID_SIZE); int *instanceNums, instanceCount = 0; __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount); oid_item->leaf_value->set_fn(oid_item, instanceCount?true:false, instanceCount, instanceNums, oid_item->leaf_value->set_argc, oid_item->leaf_value->set_argv); if(instanceCount) free(instanceNums); return oid_item; } return NULL;}struct tr069_oid *tr069_oid_set_parameter_attributes(rt_rbtree_t oid_root, char paramPath[TR069_OID_SIZE], int Notification){ struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, paramPath); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", paramPath); return NULL; } if(oid_item->node_type == TR069_OID_ITEM_TYPE_LEAF) { oid_item->leaf_value->Notification = Notification; int *instanceNums, instanceCount = 0; __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount); oid_item->leaf_value->set_fn(oid_item, true, instanceCount, instanceNums, oid_item->leaf_value->set_argc, oid_item->leaf_value->set_argv); if(instanceCount) free(instanceNums); return oid_item; } return NULL;}static struct tr069_oid *__tr069_oid_itemdup(struct tr069_oid *from,struct tr069_oid *father){ struct tr069_oid *to = malloc(sizeof(struct tr069_oid)); VOS_MemZero(to, sizeof(struct tr069_oid)); VOS_Sprintf(to->oidNameItem, "%s", from->oidNameItem); to->oidInstanceNum = 0; VOS_Sprintf(to->oidAliasNameItem, "%s", from->oidAliasNameItem); to->father = father; to->oid_type = from->oid_type; to->node_type = from->node_type; to->writeable = from->writeable; /* 如果是叶子,需要分配内存 */ if(from->node_type == TR069_OID_ITEM_TYPE_LEAF) { to->leaf_value = malloc(sizeof(struct tr069_oid_leaf)); VOS_StrnCpy(to->leaf_value->value, from->leaf_value->value, TR069_OID_SIZE); to->leaf_value->Notification = from->leaf_value->Notification; to->leaf_value->set_fn = from->leaf_value->set_fn; to->leaf_value->set_argc = from->leaf_value->set_argc; to->leaf_value->set_argv = from->leaf_value->set_argv; } if(from->oid_type == TR069_OID_TYPE_TABLE) { to->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt)); to->obj_operation->add_fn = from->obj_operation->add_fn; to->obj_operation->add_argc = from->obj_operation->add_argc; to->obj_operation->add_argv = from->obj_operation->add_argv; to->obj_operation->del_fn = from->obj_operation->del_fn; to->obj_operation->del_argc = from->obj_operation->del_argc; to->obj_operation->del_argv = from->obj_operation->del_argv; } __tr069_oid_tree_create(&to->child); return to;}static void _unused __tr069_oid_tree_clone(struct tr069_oid * from_oid, struct tr069_oid * to_oid){ to_oid->writeable = from_oid->writeable; struct tr069_oid *from_oid_item = NULL; rt_rbtree_node_t *from_node = NULL; for(from_node = rt_rbtree_getfirst(from_oid->child); from_node; from_node=rt_rbtree_getnext(from_node)) { from_oid_item = from_node->data; struct tr069_oid *to_oid_item = __tr069_oid_itemdup(from_oid_item, to_oid); rt_rbtree_insert(to_oid->child, to_oid_item, sizeof(struct tr069_oid)); __tr069_oid_tree_clone(from_oid_item, to_oid_item); }}_api int tr069_oid_add_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]){ struct tr069_oid * oid_item = __oid_tree_find_oid_path(oid_root, pathPrefix); if(!oid_item) { vos_err_print("Not exist ParamPath: %s\n", pathPrefix); return VOS_ERROR; } if(!oid_item->writeable) { vos_err_print("ParamPath: %s is not writeable.\n", pathPrefix); return VOS_ERROR; } struct tr069_oid * template_item = __oid_tree_find_oid_path(oid_item->child, TABLE_NODE); if(!template_item) { vos_err_print("ParamPath: %s is not addable Object.\n", pathPrefix); return VOS_ERROR; } int oidInstanceNum; char aliasName[TR069_OID_ITEM_SIZE]; //获取参数 int *instanceNums, instanceCount = 0; __tr069_tree_obj_count(oid_item, &instanceNums, &instanceCount);// vos_info_print("add object. %s, %s\n", oid_item->oidNameItem, template_item->oidNameItem); bool add_rlst = false; if(template_item->obj_operation) add_rlst = template_item->obj_operation->add_fn(oid_item, instanceCount+1, instanceCount, instanceNums, template_item->obj_operation->add_argc, template_item->obj_operation->add_argv, &oidInstanceNum, aliasName);// vos_info_print("add object.\n"); if(instanceCount) free(instanceNums); if(!add_rlst) { vos_err_print("ParamPath: %s add Object failed.\n", pathPrefix); return VOS_ERROR; } /* 实例 */ struct tr069_oid * instance_item = malloc(sizeof(struct tr069_oid)); VOS_MemZero(instance_item, sizeof(struct tr069_oid)); VOS_Sprintf(instance_item->oidNameItem, "%d", oidInstanceNum); instance_item->oidInstanceNum = oidInstanceNum; VOS_Sprintf(instance_item->oidAliasNameItem, "%s", aliasName); instance_item->father = oid_item;#if 1 //为第一个分配add/delete内存 instance_item->oid_type = template_item->oid_type; instance_item->node_type = template_item->node_type; instance_item->writeable = template_item->writeable; instance_item->obj_operation = malloc(sizeof(struct tr069_oid_obj_opt)); instance_item->obj_operation->add_fn = template_item->obj_operation->add_fn; instance_item->obj_operation->add_argc = template_item->obj_operation->add_argc; instance_item->obj_operation->add_argv = template_item->obj_operation->add_argv; instance_item->obj_operation->del_fn = template_item->obj_operation->del_fn; instance_item->obj_operation->del_argc = template_item->obj_operation->del_argc; instance_item->obj_operation->del_argv = template_item->obj_operation->del_argv;#endif __tr069_oid_tree_create(&instance_item->child); int ret = rt_rbtree_insert(oid_item->child, instance_item, sizeof(struct tr069_oid)); if(ret != 0) { vos_err_print("ParamPath: %s instance Object %d exist.\n", pathPrefix, oidInstanceNum); free(instance_item); return VOS_ERROR; } __tr069_oid_tree_clone(template_item, instance_item); return oidInstanceNum;}static void __tr069_oid_tree_destroy_loop(rt_rbtree_t tree);_api int tr069_oid_delete_object(rt_rbtree_t oid_root, char pathPrefix[TR069_OID_SIZE]){ struct tr069_oid * instance_item = __oid_tree_find_oid_path(oid_root, pathPrefix); if(!instance_item) { vos_err_print("Not exist ParamPath: %s\n", pathPrefix); return VOS_ERROR; } if(instance_item->oid_type != TR069_OID_TYPE_TABLE) { vos_err_print("ParamPath: %s is not object instance.\n", pathPrefix); return VOS_ERROR; } //获取参数 int *instanceNums, instanceCount = 0; __tr069_tree_obj_count(instance_item, &instanceNums, &instanceCount); bool del_rlst = false; if(instance_item->obj_operation) del_rlst = instance_item->obj_operation->del_fn(instance_item, instanceCount, instanceNums, instance_item->obj_operation->del_argc, instance_item->obj_operation->del_argv); if(!del_rlst) { vos_err_print("ParamPath: %s delete Object failed.\n", pathPrefix); return VOS_ERROR; } //递归删除子树 __tr069_oid_tree_destroy_loop(instance_item->child); //删除自己在父树种的叶子 int ret_del = rt_rbtree_delete(instance_item->father->child, instance_item); if(ret_del != 0) { vos_warning_print("ParamPath: %s delete Object failed.\n", pathPrefix); return VOS_ERROR; } //释放自己的内存 free(instance_item); return VOS_OK;}/* 递归销毁树 */static void __tr069_oid_tree_destroy_loop(rt_rbtree_t tree){ rt_rbtree_t this_tree = tree; struct tr069_oid *this_node = NULL; rt_rbtree_node_t *find_node = NULL; for( find_node = rt_rbtree_getfirst(this_tree); find_node; find_node=rt_rbtree_getnext(find_node)) { this_node = find_node->data; __tr069_oid_tree_destroy_loop(this_node->child); rt_rbtree_destroy(this_node->child); if(this_node->leaf_value) free(this_node->leaf_value); if(this_node->obj_operation) free(this_node->obj_operation); free(this_node); }}/* 销毁OID树 */_api void tr069_oid_tree_destroy(rt_rbtree_t oid_root){ __tr069_oid_tree_destroy_loop(oid_root); oid_root = NULL;}

demo.c

#include "cpe_oid_register.h"static char *OIDs[] = {"Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.OffsetToPointA","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.MultiFrequencyBandListNRSIB.{i}.FreqBandIndicatorNR","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.OffsetToCarrier","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.subcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoDLSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.CarrierBandwidth","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.AbsoluteFrequencyPointA","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.OffsetToCarrier","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.SubcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PHY.FrequencyInfoULSIB.ScsSpecificCarrierList.{i}.SCSSpecificCarrier.CarrierBandwidth","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.ssbPositionsInBurst.InOneGroup","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsbPeriodicityServingCell","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsPBCHBlockPower","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SSB.SsbSubcarrierOffset","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.SubCarrierSpacingCommon","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.ReferenceSubcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.DlULTransmission","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofDownlinkSlots","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofDownlinkSymbols","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofUplinkSlots","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern1.NrofUplinkSymbols","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.DlULTransmission","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofDownlinkSlots","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofDownlinkSymbols","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofUplinkSlots","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.TddULDLConfigurationCommon.pattern2.NrofUplinkSymbols","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.StartPrbPosition","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.Bandwidth","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.SubcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPDL.CyclicPrefix","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.StartPrbPosition","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.Bandwidth","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.SubcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.CyclicPrefix","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.BWPUL.TimeAlignmentTimerCommon","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PrachConfigurationIndex","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACH-ConfigGeneric.Msg1FDM","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.Msg1FrequencyStart","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.ZeroCorrelationZoneConfig","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.GroupHopping","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.K2","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.MappingType","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.puschTimeDomainAllocationList.{i}.StartSymbolAndLength","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.Msg3DeltaPreamble","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUSCHConfigCommon.P0NominalWithGrant","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.PucchResourceCommon","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.PucchGroupHopping","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.HoppingId","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PUCCHConfigCommon.P0nominal","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RootType","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RootSequenceIndex","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.Msg1Subcarrier","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RestrictedSetConfig","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.DmrsTypeAPosition","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.ControlResourceSetZero","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceZero","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceSIB1","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.SearchSpaceOtherSystemInformation","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.PagingSearchSpace","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.RaSearchSpace","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.ControlResourceSetId","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.FrequencyDomainResources","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.Duration","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.commonControlResourceSet.CceRegMappingType","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.RegBundleSize","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.InterleaverSize","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.CceRegMappingType.ShiftIndex","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.PrecoderGranularity","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonControlResourceSet.PdcchDMRSScramblingID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.SearchSpaceId","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.ControlResourceSetId","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.MonitoringSlotPeriodicity","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.MonitoringSlotOffset","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.Duration","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.MonitoringSymbolsWithinSlot","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel1","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel2","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel4","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel8","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.nrofCandidates.AggregationLevel16","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.SearchSpaceType","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.DciFormat00And10En","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDCCH.CommonSearchSpaceList.{i}.UeSpecificDciFormats","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.K0","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.MappingType","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.PDSCH.PDSCHTimeDomainResourceAllocationList.{i}.StartSymbolAndLength","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.TotalNumberOfRAPreambles","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.SSBPerRACHOccasionChoice","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.CBPreamblesPerSSB","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RaMsg3SizeGroupA","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.MessagePowerOffsetGroupB","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.NumberOfRAPreamblesGroupA","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RaContentionResolutionTimer","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RsrpThresholdSSB","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.PreambleReceivedTargetPower","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PrachConfiguration","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.RACHConfigGeneric.PowerRampingStep","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACH-ConfigCommon.RACH-ConfigGeneric.RaResponseWindow","Device.Services.FAPService.{i}.CellConfig.NR.RAN.PHY.RACHConfigCommon.Msg3TransformPrecoder","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T300","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T301","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T302","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T304","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T310","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T311","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T320","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.N310","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.N311","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T319","Device.Services.FAPService.{i}.CellConfig.NR.RAN.RRCTimers.T380","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.PLMNID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.CID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.NRCarrierARFCN","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.ssbFrequency","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.ssbSubcarrierSpacing","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.PhyCellID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.TAC","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.Qoffset","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.QRxLevMinOffsetCell","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.QQualMinOffsetCell","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.CIO","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.NRCell.{i}.Blacklisted","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.PLMNID.{i}.{i}","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.CID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.EUTRACarrierARFCN","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.PhyCellID","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QOffset","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QRxLevMinOffsetCell","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.QQualMinOffsetCell","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.CIO","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.Blacklisted","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.TAC","Device.Services.FAPService.{i}.CellConfig.NR.RAN.NeighborList.LTECell.{i}.EnbType","Device.Services.FAPService.{i}.Transport.SCTP.Enable","Device.Services.FAPService.{i}.Transport.SCTP.RTOInitial","Device.Services.FAPService.{i}.Transport.SCTP.RTOMin","Device.Services.FAPService.{i}.Transport.SCTP.RTOMax","Device.Services.FAPService.{i}.Transport.SCTP.MaxInitRetransmits","Device.Services.FAPService.{i}.Transport.SCTP.HBInterval","Device.Services.FAPService.{i}.Transport.SCTP.MaxPathRetransmits","Device.Services.FAPService.{i}.Transport.SCTP.MaxAssociationRetransmits","Device.Services.FAPService.{i}.Transport.SCTP.ValCookieLife","Device.DeviceInfo.ManufacturerOUI","Device.DeviceInfo.Manufacturer","Device.DeviceInfo.ModelName","Device.DeviceInfo.SerialNumber","Device.DeviceInfo.HardwareVersion","Device.DeviceInfo.SoftwareVersion","Device.DeviceInfo.HardwarePlatform","Device.DeviceInfo.AdditionalHardwareVersion","Device.DeviceInfo.AdditionalSoftwareVersion","Device.DeviceInfo.ProvisioningCode","Device.DeviceInfo.ProductClass","Device.DeviceInfo.UpTime","Device.DeviceInfo.3GPPSpecVersion","Device.DeviceInfo.FirstUseDate","Device.SoftwareCtrl.AutoActivateEnable","Device.SoftwareCtrl.ActivateTime","Device.SoftwareCtrl.ActivateEnable","Device.SoftwareCtrl.SystemCurrentVersion","Device.SoftwareCtrl.SystemBackupVersion","Device.ManagementServer.URL","Device.ManagementServer.Username","Device.ManagementServer.Password","Device.ManagementServer.PeriodicInformEnable","Device.ManagementServer.PeriodicInformTime","Device.ManagementServer.PeriodicInformInterval","Device.ManagementServer.ParameterKey","Device.ManagementServer.ConnectionRequestURL","Device.ManagementServer.ConnectionRequestUsername","Device.ManagementServer.ConnectionRequestPassword","Device.ManagementServer.UDPConnectionRequestAddress","Device.ManagementServer.STUNEnable","Device.ManagementServer.STUNServerAddress","Device.ManagementServer.STUNServerPort","Device.ManagementServer.STUNUsername","Device.ManagementServer.STUNPassword","Device.ManagementServer.STUNMaximumKeepAlivePeriod","Device.ManagementServer.STUNMinimumKeepAlivePeriod","Device.ManagementServer.NATDetected","Device.FaultMgmt.ExpeditedEvent.{i}.PerceivedSeverity","Device.FaultMgmt.ExpeditedEvent.{i}.AdditionalText","Device.FaultMgmt.ExpeditedEvent.{i}.AdditionalInformation","Device.FaultMgmt.QueuedEvent.{i}.SerialNumber","Device.FaultMgmt.QueuedEvent.{i}.OUI","Device.FaultMgmt.QueuedEvent.{i}.EventTime","Device.FaultMgmt.QueuedEvent.{i}.AlarmIdentifier","Device.FaultMgmt.QueuedEvent.{i}.NotificationType","Device.FaultMgmt.QueuedEvent.{i}.ManagedObjectInstance","Device.FaultMgmt.QueuedEvent.{i}.EventType","Device.FaultMgmt.QueuedEvent.{i}.ProbableCause","Device.FaultMgmt.QueuedEvent.{i}.SpecificProblem","Device.FaultMgmt.QueuedEvent.{i}.PerceivedSeverity","Device.FaultMgmt.QueuedEvent.{i}.AdditionalText","Device.FaultMgmt.QueuedEvent.{i}.AdditionalInformation","Device.LogMgmt.PeriodicUploadEnable","Device.LogMgmt.URL","Device.LogMgmt.Username","Device.LogMgmt.Password","Device.LogMgmt.PeriodicUploadInterval","Device.Ethernet.Interface.{i}.Enable","Device.Ethernet.Interface.{i}.Status","Device.Ethernet.Interface.{i}.MACAddress","Device.Ethernet.Interface.{i}.MaxBitRate","Device.Ethernet.Interface.{i}.SignTransMedia","Device.Ethernet.Interface.{i}.DuplexMode","Device.IP.Interface.{i}.IPv4Address.{i}.IPAddress","Device.IP.Interface.{i}.IPv4Address.{i}.DefaultGateway","Device.IP.Interface.{i}.IPv4Address.{i}.SubnetMask","Device.IP.Interface.{i}.IPv4Address.{i}.AddressingType","Device.IP.Interface.{i}.IPv4Address.{i}.PortType","Device.IPsec.Enable","Device.IPsec.MyKeyMode","Device.IPsec.Status","Device.IPsec.AHSupported","Device.IPsec.IKEv2SupportedEncryptionAlgorithms","Device.IPsec.ESPSupportedEncryptionAlgorithms","Device.IPsec.IKEv2SupportedPseudoRandomFunctions","Device.IPsec.SupportedIntegrityAlgorithms","Device.IPsec.SupportedDiffieHellmanGroupTransforms",NULL,};#define NOIDs ({int n=0;while(OIDs[n++]); n-1;})void oid_display(struct tr069_oid *oid, void *arg){    printf("%s\n", oid->oidNameItem);}void oid_set(struct tr069_oid *node, bool isObj, int nObj, int ObjInsNums[], int argc, void *argv[]){    }bool oid_add(struct tr069_oid *node, int currObjIdx, int nPrevObj, int prevObjInsNums[], int argc, void *argv[],                     int *ObjIns, char aliasName[TR069_OID_ITEM_SIZE]){    int instance_num = 1;    *ObjIns = instance_num++;        sprintf(aliasName, "Alias_%d", instance_num-1);        return true;    }bool oid_del(struct tr069_oid *node, int nObj, int ObjInsNums[], int argc, void *argv[]){        return true;}int set_argc = 3;void *set_argv[] = {    "Rong","Tao","Sylincom"};    int add_argc = 3;void *add_argv[] = {    "Rong","Tao","Sylincom"};     int del_argc = 3;void *del_argv[] = {    "Rong","Tao","Sylincom"};int main(){    /* 创建一个树 */    rt_rbtree_t oid_tree = tr069_oid_tree_create();    /* 注册树节点:注册了所有节点,各模块视情况而定 */    int ioid, Noids = NOIDs;    for(ioid=0;ioid

 

转载地址:http://sdpaf.baihongyu.com/

你可能感兴趣的文章
数据库设计中的14个关键技巧
查看>>
博客作者应该学习的15个国外博客
查看>>
如何将jsp动态网页转换成静态页面
查看>>
Oracle面向服务的架构
查看>>
html中用js调用ASP文件 实现静态页面动态显示
查看>>
谷歌云计算推广互联网新理念
查看>>
软件工程师的6年总结
查看>>
三大搜索引擎 承诺“公正搜索”
查看>>
如何使用命令方式检测mx记录是否生效
查看>>
Tomcat 的集群和负载均衡 - 第二部分
查看>>
云计算将如何改变世界
查看>>
拥抱新技术整合新思路
查看>>
解决spring和struts配合问题
查看>>
Java Interview Questions
查看>>
确定中文字符串的相似度解决方案
查看>>
java JDBC 提高程序可移植性
查看>>
JAVA面试题:1的阶乘到100的阶乘相加的和,末位数是几?
查看>>
微软Java面试题-按照字母排序
查看>>
中企动力面试题--逻辑题,(3顶黑帽子,2顶白帽子),有多少人戴黑帽子?
查看>>
Java面试题:100的阶乘末尾有多少个零?
查看>>