blob: 34391d14f0af546d96f5b0942f62adf6734840c4 [file] [log] [blame]
#include "rpc.h"
//static unsigned short int instance_id = 0;
struct tr069_instance * malloc_instance(struct tr069_obj * obj, struct tr069_instance * parent, int id)
{
struct tr069_instance * instance = (struct tr069_instance *)tr069_malloc(sizeof(struct tr069_instance));
if (instance == NULL) {
TR069_ERR("Malloc instance failed!");
return NULL;
}
//TR069_DEBUG("%s: %s old %p", __func__, obj->name, obj->instance_list);
memset(instance, 0, sizeof(struct tr069_instance));
instance->id = (id > 0) ? id : ++obj->instance_cnt;
instance->parent = parent;
instance->next = obj->instance_list;
//TR069_DEBUG("%s: %s new %p", __func__, obj->name, obj->instance_list);
obj->instance_list = instance;
return instance;
}
int free_instance(struct tr069_obj * obj, struct tr069_instance * is)
{
struct tr069_instance * backup = obj->instance_list;
TR069_DEBUG("%s: %s(%p)", __func__, obj->name, is);
if (obj->instance_list == is) {
obj->instance_list = is->next;
if (obj->del_obj) obj->del_obj(obj, is);
tr069_free(is);
return 0;
}
while (backup) {
if (backup->next == is) {
backup->next = is->next;
if (obj->del_obj) obj->del_obj(obj, is);
tr069_free(is);
return 0;
}
backup = backup->next;
}
TR069_DEBUG("%s: failed", __func__);
return -1;
}
#define MAX_TRACE_DEEP 20
static struct tr069_instance * instance_stack[MAX_TRACE_DEEP] = {NULL};
static int instance_index = 0;
static void push_instance(struct tr069_instance * instance)
{
instance_stack[instance_index == 0 ? instance_index : ++instance_index] = instance;
}
/*
static struct tr069_instance * pop_instance(void)
{
return instance_stack[instance_index--];
}
*/
struct tr069_instance * top_instance(void)
{
return instance_stack[instance_index];
}
static void reset_stack(void)
{
memset(instance_stack, 0, sizeof(instance_stack));
instance_index = 0;
}
#if 1
// This API used by user
extern struct tr069_obj root_obj[];
int rpc_add_obj_api(const char * path, int id, struct tr069_instance ** ppis)
{
struct tr069_obj * obj = find_obj(root_obj, path);
struct tr069_instance * pis = NULL;
int ret = 0;
if (!obj) {
TR069_ERR("RPC add object failed, cannot find object...");
return -1;
}
pis = malloc_instance(obj, top_instance(), id);
if (pis) {
*ppis = pis;
if (obj->add_obj)
ret = obj->add_obj(obj, pis);
//TR069_DEBUG("%s: %s new %p next %p", __func__, path, pis, pis->next);
if (ret) {
TR069_ERR("%s: Add object failed:%s", __func__, path);
free_instance(obj, pis);
*ppis = NULL;
return -1;
}
return pis->id;
}
return -1;
}
#endif
static struct tr069_instance * __find_instance(struct tr069_obj * obj, const char * id)
{
struct tr069_instance * is = obj->instance_list;
while (is) {
if (is->parent == top_instance()) {
if (*id == '[') {
struct tr069_param * p = obj->param_list;
while (p && p->name) {
if (!strcmp(p->name, "Alias")) {
if (p->get_value) {
char * value = NULL;
p->get_value(is, &value);
if (value) {
if (!strncmp(id + 1, value, strlen(value))) {
TR069_DEBUG("find_instance: Handle alias instance %s", id);
tr069_free(value);
return is;
}
tr069_free(value);
value = NULL;
}
}
}
p++;
}
} else if (is->id == atoi(id)) {
TR069_DEBUG("find_instance: return instance for %s(%s)", obj->name, id);
return is;
}
}
is = is->next;
}
TR069_DEBUG("find_instance: return NULL instance with %s", obj->name);
return NULL;
}
static struct tr069_obj * __find_obj(struct tr069_obj * root, char ** trace)
{
struct tr069_obj * p = root;
while (p && p->name) {
if (!strcmp(*trace, p->name)) {
if (*(trace + 1) == NULL) {
return p;
} else {
char ** next = trace + 1;
// If next object is instance, find instance and push to stack
if (isdigit(**next) || (**next == '[')) {
// Push to stack
push_instance(__find_instance(p, *next));
if (*(next + 1) == NULL)
return p;
next++;
}
return __find_obj(p->obj_list, next);
}
}
p++;
}
return NULL;
}
struct tr069_obj * find_obj(struct tr069_obj * root, const char * path)
{
char * trace[MAX_TRACE_DEEP] = {0};
struct tr069_obj * obj;
char * pos, * temp_path;
char ** trace_index = &trace[0];
int len = strlen(path);
if (path[len - 1] != '.' || *path == '.') {
TR069_ERR("Bat agr @%s:%d", __func__, __LINE__);
return NULL;
}
reset_stack();
pos = temp_path = tr069_strdup(path);
while (pos != (temp_path + len)) {
char * c;
// Add trace deep check
*trace_index = tr069_strdup(pos);
c = strchr(*trace_index, '.');
if (c == NULL) {
// assert, add free code
tr069_free(*trace_index);
tr069_free(temp_path);
TR069_ERR("Assert failed @%s:%d", __func__, __LINE__);
return NULL;
}
*c = '\0';
trace_index++;
pos = strchr(pos, '.');
if(pos){
pos++;
}else{
break;
}
}
tr069_free(temp_path);
instance_index = 0;
obj = __find_obj(root, &trace[0]);
if (!obj) TR069_ERR("%s: failed, %s", __func__, path);
// Free trace data
trace_index = &trace[0];
while (*trace_index) {
tr069_free(*trace_index);
*trace_index = NULL;
trace_index++;
}
return obj;
}
static struct tr069_param * __find_param(struct tr069_obj * object, char * path)
{
struct tr069_param * p = object->param_list;
while (p && p->name) {
if (!strcmp(path, p->name)) {
return p;
}
p++;
}
return NULL;
}
struct tr069_param * find_param(struct tr069_obj * root, const char * path)
{
char * trace[MAX_TRACE_DEEP + 1] = {0};
struct tr069_obj * obj;
struct tr069_param * param = NULL;
char * pos, * temp_path;
char ** trace_index = &trace[0];
int len = strlen(path);
int deep = 0;
if (*path == '.') {
TR069_ERR("Bat agr @%s:%d", __func__, __LINE__);
return NULL;
}
reset_stack();
pos = temp_path = tr069_strdup(path);
while (pos != (temp_path + len)) {
char * c;
*trace_index = tr069_strdup(pos);
c = strchr(*trace_index, '.');
if (c == NULL) {
// Means path end, so we can find object first
tr069_free(*trace_index);
*trace_index = NULL;
obj = __find_obj(root, &trace[0]);
if (obj == NULL) {
// Failed
TR069_ERR("Failed when try find object for find parameter");
break;
}
param = __find_param(obj, pos);
break;
}
*c = '\0';
pos = strchr(pos, '.');
if(pos){
pos++;
trace_index++;
deep++;
if (deep >= MAX_TRACE_DEEP) TR069_ERR("Failed! %s:%d", __func__, __LINE__);
}else{
break;
}
}
tr069_free(temp_path);
// Free all trace data
trace_index = &trace[0];
while (*trace_index) {
tr069_free(*trace_index);
*trace_index = NULL;
trace_index++;
}
if (!param) TR069_ERR("%s: failed, %s", __func__, path);
return param;
}
static int __walk_obj_and_paramet(struct tr069_obj * root,
struct tr069_instance * instance, walk_obj_paramet_cb callback, struct walk_context * data, int flag)
{
struct tr069_param * paramet;
struct tr069_instance * is;
struct tr069_obj * obj = root;
char temp[16];
// Walk all object
while (obj && obj->name) {
// Push current object name to stack
TR069_DEBUG("%s: object %s(%s)", __func__, obj->name,
obj->type == TR069OBJ_TYPE_NORMAL ? "normal" : "instance");
if (data->stack[data->index] == NULL) {
data->stack[data->index] = obj->name;
} else {
data->stack[++data->index] = obj->name;
}
// Callback notify to user
if (callback) callback(obj, NULL, NULL, data, TR069_TYPE_OBJECT);
// Walk all paramet
if (obj->type == TR069OBJ_TYPE_NORMAL) {
paramet = obj->param_list;
while (paramet && paramet->name) {
TR069_DEBUG(" parameter %s", paramet->name);
// Push current parameter name to stack
data->stack[++data->index] = paramet->name;
// Callback notify to user
if (callback) callback(NULL, paramet, instance, data, TR069_TYPE_PARAMETER);
// Pop name
data->stack[data->index--] = NULL;
paramet++;
}
// Walk next object && parameter
if (obj->obj_list)
__walk_obj_and_paramet(obj->obj_list, instance, callback, data, 0);
} else {
int i = 0;
is = obj->instance_list;
if (is) i = ++data->index;
while (is) {
// Push instance ID to stack
TR069_DEBUG(" now %p, next %p", is, is->next);
snprintf(temp, 16, "%d", is->id);
data->stack[i] = temp;
if (is->parent == NULL ||
data->instance_stack[data->instance_index] == is->parent->id) {
data->instance_stack[++data->instance_index] = is->id;
// Walk all parameter
paramet = obj->param_list;
while (paramet && paramet->name) {
TR069_DEBUG(" parameter %s", paramet->name);
// Push current parameter name to stack
data->stack[++data->index] = paramet->name;
// Callback notify to user
if (callback) callback(NULL, paramet, is, data, TR069_TYPE_PARAMETER);
// Pop name
data->stack[data->index--] = NULL;
paramet++;
}
if (obj->obj_list) {
__walk_obj_and_paramet(obj->obj_list, is, callback, data, 0);
}
data->instance_stack[data->instance_index--] = -1;
}
is = is->next;
}
if (obj->instance_list) data->stack[data->index--] = NULL;
}
// Pop object name
data->stack[data->index--] = NULL;
if (flag) {
break; // If the flag set, do not continue process next object under the same parent
} else {
obj++;
}
}
return 0;
}
int walk_obj_and_paramet(struct tr069_obj * root,
struct tr069_instance * instance, walk_obj_paramet_cb callback, void * data, int flag)
{
UNUSED(flag);
struct walk_context * context = tr069_malloc(sizeof(struct walk_context));
if (context == NULL) {
TR069_ERR("Can not malloc memory for walk context...");
return -1;
}
memset(context, 0, sizeof(struct walk_context));
context->userdata = data;
__walk_obj_and_paramet(root, instance, callback, context, 1);
TR069_DEBUG("%s: after quit index %d", __func__, context->index);
tr069_free(context);
return 0;
}
const char * rpc_type2string(int type)
{
switch (type) {
case TR069_STRING:
return "xsdstring";
case TR069_INT:
return "xsdint";
case TR069_UINT:
return "xsdunsignedInt";
case TR069_BOOL:
return "xsdboolean";
case TR069_DATATIME:
return "xsddateTime";
case TR069_ULONG:
return "xsdunsignedLong";
case TR069_HEX:
return "xsdhexBinary";
default:
TR069_DEBUG("type2string with unknow type...\n");
return "";
}
}