static void read_dialog_profiles(char *b, int l, struct dlg_cell *dlg,int double_check) { struct dlg_profile_table *profile; struct dlg_profile_link *it; str name, val; char *end; char *p; char bk; end = b + l; p = b; current_dlg_pointer = dlg; do { /* read a new pair from input string */ p = read_pair( p, end, &name, &val); if (p==NULL) break; LM_DBG("new profile found <%.*s>=<%.*s>\n",name.len,name.s,val.len,val.s); if (double_check) { for (it=dlg->profile_links;it;it=it->next) { if (it->profile->name.len == name.len && memcmp(it->profile->name.s,name.s,name.len) == 0) { LM_DBG("Profile is already linked into the dlg\n"); goto next; } } } /* add to the profile */ profile = search_dlg_profile( &name ); if (profile==NULL) { LM_DBG("profile <%.*s> does not exist now, creating it\n",name.len,name.s); /* create a new one */ bk = name.s[name.len]; name.s[name.len] = 0; if (add_profile_definitions(name.s, (val.len && val.s)?1:0 ) != 0) { LM_ERR("failed to add dialog profile <%.*s>\n", name.len, name.s); name.s[name.len] = bk; continue; } name.s[name.len] = bk; /* double check the created profile */ profile = search_dlg_profile(&name); if (profile == NULL) { LM_CRIT("BUG - cannot find just added dialog profile <%.*s>\n", name.len, name.s); continue; } } if (set_dlg_profile( NULL, profile->has_value?&val:NULL, profile) < 0 ) LM_ERR("failed to add to profile, skipping....\n"); next: ; } while(p!=end); current_dlg_pointer = NULL; }
static int fixup_profile(void** param, int param_no) { struct dlg_profile_table *profile; pv_elem_t *model=NULL; str s; s.s = (char*)(*param); s.len = strlen(s.s); if(s.len==0) { LM_ERR("param %d is empty string!\n", param_no); return E_CFG; } if (param_no==1) { profile = search_dlg_profile( &s ); if (profile==NULL) { LM_CRIT("profile <%s> not definited\n",s.s); return E_CFG; } pkg_free(*param); *param = (void*)profile; return 0; } else if (param_no==2) { if(pv_parse_format(&s ,&model) || model==NULL) { LM_ERR("wrong format [%s] for value param!\n", s.s); return E_CFG; } *param = (void*)model; } return 0; }
/*! * \brief Helper function that outputs the size of a given profile via the RPC interface * \see rpc_profile_get_size * \see rpc_profile_w_value_get_size * \param rpc RPC node that should be filled * \param c RPC void pointer * \param profile_name the given profile * \param value the given profile value */ static void internal_rpc_profile_get_size(rpc_t *rpc, void *c, str *profile_name, str *value) { unsigned int size; dlg_profile_table_t *profile; profile = search_dlg_profile( profile_name ); if (!profile) { rpc->printf(c, "Non existing profile:%.*s", profile_name->len, profile_name->s); return; } size = get_profile_size(profile, value); if (value) { rpc->printf(c, "Profile:%.*s => profile:%.*s value:%.*s count:%u", profile_name->len, profile_name->s, profile->name.len, profile->name.s, value->len, value->s, size); return; } else { rpc->printf(c, "Profile:%.*s => profile:%.*s value: count:%u", profile_name->len, profile_name->s, profile->name.len, profile->name.s, size); return; } return; }
/*! * \brief Helper function that outputs the dialogs belonging to a given profile via the RPC interface * \see rpc_profile_print_dlgs * \see rpc_profile_w_value_print_dlgs * \param rpc RPC node that should be filled * \param c RPC void pointer * \param profile_name the given profile * \param value the given profile value * \param with_context if 1 then the dialog context will be also printed */ static void internal_rpc_profile_print_dlgs(rpc_t *rpc, void *c, str *profile_name, str *value) { dlg_profile_table_t *profile; dlg_profile_hash_t *ph; unsigned int i; profile = search_dlg_profile( profile_name ); if (!profile) { rpc->fault(c, 404, "Profile not found: %.*s", profile_name->len, profile_name->s); return; } /* go through the hash and print the dialogs */ if (profile->has_value==0) value=NULL; lock_get( &profile->lock ); for ( i=0 ; i< profile->size ; i++ ) { ph = profile->entries[i].first; if(ph) { do { if ((!value || (STR_EQ(*value, ph->value))) && ph->dlg) { /* print dialog */ internal_rpc_print_dlg(rpc, c, ph->dlg, 0); } /* next */ ph=ph->next; }while(ph!=profile->entries[i].first); } lock_release(&profile->lock); } }
/*! * \brief Helper function that outputs the dialogs belonging to a given profile via the RPC interface * \see rpc_profile_print_dlgs * \see rpc_profile_w_value_print_dlgs * \param rpc RPC node that should be filled * \param c RPC void pointer * \param profile_name the given profile * \param value the given profile value * \param with_context if 1 then the dialog context will be also printed */ static void internal_rpc_profile_print_dlgs(rpc_t *rpc, void *c, str *profile_name, str *value) { dlg_profile_table_t *profile; dlg_profile_hash_t *ph; unsigned int i; profile = search_dlg_profile( profile_name ); if (!profile) { rpc->printf(c, "Non existing profile:%.*s", profile_name->len, profile_name->s); return; } /* go through the hash and print the dialogs */ if (profile->has_value==0 || value==NULL) { /* no value */ lock_get( &profile->lock ); for ( i=0 ; i< profile->size ; i++ ) { ph = profile->entries[i].first; if(ph) { do { /* print dialog */ internal_rpc_print_dlg(rpc, c, ph->dlg, 0); /* next */ ph=ph->next; }while(ph!=profile->entries[i].first); } lock_release(&profile->lock); } } else { /* check for value also */ lock_get( &profile->lock ); for ( i=0 ; i< profile->size ; i++ ) { ph = profile->entries[i].first; if(ph) { do { if ( value->len==ph->value.len && memcmp(value->s,ph->value.s,value->len)==0 ) { /* print dialog */ internal_rpc_print_dlg(rpc, c, ph->dlg, 0); } /* next */ ph=ph->next; }while(ph!=profile->entries[i].first); } lock_release(&profile->lock); } } }
/*! * \brief Helper function that outputs the size of a given profile via the RPC interface * \see rpc_profile_get_size * \see rpc_profile_w_value_get_size * \param rpc RPC node that should be filled * \param c RPC void pointer * \param profile_name the given profile * \param value the given profile value */ static void internal_rpc_profile_get_size(rpc_t *rpc, void *c, str *profile_name, str *value) { unsigned int size; dlg_profile_table_t *profile; profile = search_dlg_profile( profile_name ); if (!profile) { rpc->fault(c, 404, "Profile not found: %.*s", profile_name->len, profile_name->s); return; } size = get_profile_size(profile, value); rpc->add(c, "d", size); return; }
/*! * */ int dlg_cmd_remote_profile(str *cmd, str *pname, str *value, str *puid, time_t expires, int flags) { dlg_profile_table_t *dprofile; int ret; if(cmd==NULL || cmd->s==NULL || cmd->len<=0 || pname==NULL || pname->s==NULL || pname->len<=0 || puid==NULL || puid->s==NULL || puid->len<=0) { LM_ERR("invalid parameters\n"); return -1; } dprofile = search_dlg_profile(pname); if(dprofile==NULL) { LM_ERR("profile [%.*s] not found\n", pname->len, pname->s); return -1; } if(dprofile->has_value) { if(value==NULL || value->s==NULL || value->len<=0) { LM_ERR("profile [%.*s] requires a value\n", pname->len, pname->s); return -1; } } if(cmd->len==3 && strncmp(cmd->s, "add", 3)==0) { if(value && value->s && value->len>0) { ret = dlg_add_profile(NULL, value, dprofile, puid, expires, flags); } else { ret = dlg_add_profile(NULL, NULL, dprofile, puid, expires, flags); } if(ret<0) { LM_ERR("failed to add to profile [%.*s]\n", pname->len, pname->s); return -1; } } else if(cmd->len==2 && strncmp(cmd->s, "rm", 2)==0) { ret = remove_profile(dprofile, value, puid); return ret; } else { LM_ERR("unknown command [%.*s]\n", cmd->len, cmd->s); return -1; } return 0; }
/*! * \brief Creates a new dialog profile * \see add_profile_definitions * \param name profile name * \param size profile size * \param has_value set to 0 for a profile without value, otherwise it has a value * \return pointer to the created dialog on success, NULL otherwise */ static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size, unsigned int has_value) { struct dlg_profile_table *profile; struct dlg_profile_table *ptmp; unsigned int len; unsigned int i; if ( name->s==NULL || name->len==0 || size==0 ) { LM_ERR("invalid parameters\n"); return NULL; } for( len=0,i=0 ; i<8*sizeof(size) ; i++ ) { if ( size & (1<<i) ) len++; } if (len!=1) { LM_ERR(" size %u is not power of 2!\n", size); return NULL; } profile = search_dlg_profile(name); if (profile!=NULL) { LM_ERR("duplicate dialog profile registered <%.*s>\n", name->len, name->s); return NULL; } len = sizeof(struct dlg_profile_table) + size*sizeof(struct dlg_profile_entry) + name->len + 1; profile = (struct dlg_profile_table *)shm_malloc(len); if (profile==NULL) { LM_ERR("no more shm mem\n"); return NULL; } memset( profile , 0 , len); profile->size = size; profile->has_value = (has_value==0)?0:1; /* init lock */ if (lock_init( &profile->lock )==NULL) { LM_ERR("failed to init lock\n"); shm_free(profile); return NULL; } /* set inner pointers */ profile->entries = (struct dlg_profile_entry*)(profile + 1); profile->name.s = ((char*)profile->entries) + size*sizeof(struct dlg_profile_entry); /* copy the name of the profile */ memcpy( profile->name.s, name->s, name->len ); profile->name.len = name->len; profile->name.s[profile->name.len] = 0; /* link profile */ for( ptmp=profiles ; ptmp && ptmp->next; ptmp=ptmp->next ); if (ptmp==NULL) { profiles = profile; sruid_init(&_dlg_profile_sruid, '-', "dlgp", SRUID_INC); } else { ptmp->next = profile; } return profile; }
/** * json de-serialization of dialog profiles */ int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc) { srjson_t *aj = NULL; srjson_t *it = NULL; srjson_t *jt = NULL; dlg_profile_table_t *profile; str name; str val; str puid; time_t expires; int flags; if(dlg==NULL || jdoc==NULL || jdoc->buf.s==NULL) return -1; if(jdoc->root == NULL) { jdoc->root = srjson_Parse(jdoc, jdoc->buf.s); if(jdoc->root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc->buf.s); return -1; } } aj = srjson_GetObjectItem(jdoc, jdoc->root, "profiles"); if(aj!=NULL) { for(it=aj->child; it; it = it->next) { name.s = val.s = puid.s = NULL; expires = 0; flags = 0; for(jt = it->child; jt; jt = jt->next) { if(strcmp(jt->string, "name")==0) { name.s = jt->valuestring; name.len = strlen(name.s); } else if(strcmp(jt->string, "value")==0) { val.s = jt->valuestring; val.len = strlen(val.s); } else if(strcmp(jt->string, "puid")==0) { puid.s = jt->valuestring; puid.len = strlen(puid.s); } else if(strcmp(jt->string, "expires")==0) { expires = (time_t)SRJSON_GET_ULONG(jt); } else if(strcmp(jt->string, "flags")==0) { flags = SRJSON_GET_UINT(jt); } } if(name.s==NULL) continue; profile = search_dlg_profile(&name); if(profile==NULL) { LM_ERR("profile [%.*s] not found\n", name.len, name.s); continue; } if(val.s!=NULL) { if(profile->has_value) { if(dlg_add_profile(dlg, &val, profile, &puid, expires, flags) < 0) LM_ERR("dynamic profile cannot be added, ignore!\n"); else LM_DBG("dynamic profile added [%s : %s]\n", name.s, val.s); } } else { if(!profile->has_value) { if(dlg_add_profile(dlg, NULL, profile, &puid, expires, flags) < 0) LM_ERR("static profile cannot be added, ignore!\n"); else LM_DBG("static profile added [%s]\n", name.s); } } } } return 0; }
/*! * \brief List the profiles via MI interface * \param cmd_tree MI command tree * \param param unused * \return MI root output on success, NULL on failure */ struct mi_root * mi_profile_list(struct mi_root *cmd_tree, void *param ) { struct mi_node* node; struct mi_root* rpl_tree= NULL; struct mi_node* rpl = NULL; struct dlg_profile_table *profile; struct dlg_profile_hash *ph; str *profile_name; str *value; unsigned int i; node = cmd_tree->node.kids; if (node==NULL || !node->value.s || !node->value.len) return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); profile_name = &node->value; if (node->next) { node = node->next; if (!node->value.s || !node->value.len) return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM)); if (node->next) return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); value = &node->value; } else { value = NULL; } /* search for the profile */ profile = search_dlg_profile( profile_name ); if (profile==NULL) return init_mi_tree( 404, MI_SSTR("Profile not found")); rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK)); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; /* go through the hash and print the dialogs */ if (profile->has_value==0 || value==NULL) { /* no value */ lock_get( &profile->lock ); for ( i=0 ; i< profile->size ; i++ ) { ph = profile->entries[i].first; if(ph) { do { /* print dialog */ if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 ) goto error; /* next */ ph=ph->next; }while( ph!=profile->entries[i].first ); } } lock_release( &profile->lock ); } else { /* check for value also */ lock_get( &profile->lock ); for ( i=0 ; i< profile->size ; i++ ) { ph = profile->entries[i].first; if(ph) { do { if ( value->len==ph->value.len && memcmp(value->s,ph->value.s,value->len)==0 ) { /* print dialog */ if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 ) goto error; } /* next */ ph=ph->next; }while( ph!=profile->entries[i].first ); } } lock_release( &profile->lock ); } return rpl_tree; error: free_mi_tree(rpl_tree); return NULL; }
/*! * \brief Output a profile via MI interface * \param cmd_tree MI command tree * \param param unused * \return MI root output on success, NULL on failure */ struct mi_root * mi_get_profile(struct mi_root *cmd_tree, void *param) { struct mi_node* node; struct mi_root* rpl_tree= NULL; struct mi_node* rpl = NULL; struct mi_attr* attr; struct dlg_profile_table *profile; str *value; str *profile_name; unsigned int size; int len; char *p; node = cmd_tree->node.kids; if (node==NULL || !node->value.s || !node->value.len) return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); profile_name = &node->value; if (node->next) { node = node->next; if (!node->value.s || !node->value.len) return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM)); if (node->next) return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM)); value = &node->value; } else { value = NULL; } /* search for the profile */ profile = search_dlg_profile( profile_name ); if (profile==NULL) return init_mi_tree( 404, MI_SSTR("Profile not found")); size = get_profile_size( profile , value ); rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK)); if (rpl_tree==0) return 0; rpl = &rpl_tree->node; node = add_mi_node_child(rpl, MI_DUP_VALUE, "profile", 7, NULL, 0); if (node==0) { free_mi_tree(rpl_tree); return NULL; } attr = add_mi_attr(node, MI_DUP_VALUE, "name", 4, profile->name.s, profile->name.len); if(attr == NULL) { goto error; } if (value) { attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, value->s, value->len); } else { attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, NULL, 0); } if(attr == NULL) { goto error; } p= int2str((unsigned long)size, &len); attr = add_mi_attr(node, MI_DUP_VALUE, "count", 5, p, len); if(attr == NULL) { goto error; } return rpl_tree; error: free_mi_tree(rpl_tree); return NULL; }
/** * json de-serialization of dialog profiles */ int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc) { srjson_t *sj = NULL; srjson_t *dj = NULL; srjson_t *it = NULL; dlg_profile_table_t *profile; str name; str val; if(dlg==NULL || jdoc==NULL || jdoc->buf.s==NULL) return -1; if(jdoc->root == NULL) { jdoc->root = srjson_Parse(jdoc, jdoc->buf.s); if(jdoc->root == NULL) { LM_ERR("invalid json doc [[%s]]\n", jdoc->buf.s); return -1; } } dj = srjson_GetObjectItem(jdoc, jdoc->root, "dprofiles"); sj = srjson_GetObjectItem(jdoc, jdoc->root, "sprofiles"); if(dj!=NULL) { for(it=dj->child; it; it = it->next) { name.s = it->string; name.len = strlen(name.s); val.s = it->valuestring; val.len = strlen(val.s); profile = search_dlg_profile(&name); if(profile==NULL) { LM_ERR("profile [%.*s] not found\n", name.len, name.s); continue; } if(profile->has_value) { if(dlg_add_profile(dlg, &val, profile) < 0) LM_ERR("dynamic profile cannot be added, ignore!\n"); else LM_DBG("dynamic profile added [%s : %s]\n", name.s, val.s); } } } if(sj!=NULL) { for(it=sj->child; it; it = it->next) { name.s = it->valuestring; name.len = strlen(name.s); profile = search_dlg_profile(&name); if(profile==NULL) { LM_ERR("profile [%.*s] not found\n", name.len, name.s); continue; } if(!profile->has_value) { if(dlg_add_profile(dlg, NULL, profile) < 0) LM_ERR("static profile cannot be added, ignore!\n"); else LM_DBG("static profile added [%s]\n", name.s); } } } return 0; }