dlg_profile.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008 Voice System SRL
00003  *
00004  * This file is part of Kamailio, a free SIP server.
00005  *
00006  * Kamailio is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version
00010  *
00011  * Kamailio is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License 
00017  * along with this program; if not, write to the Free Software 
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  * History:
00021  * --------
00022  * 2008-04-20  initial version (bogdan)
00023  *
00024  */
00025 
00026 
00035 #include "../../mem/shm_mem.h"
00036 #include "../../hashes.h"
00037 #include "../../trim.h"
00038 #include "../../dprint.h"
00039 #include "../../ut.h"
00040 #include "../../route.h"
00041 #include "../../modules/tm/tm_load.h"
00042 #include "dlg_hash.h"
00043 #include "dlg_var.h"
00044 #include "dlg_handlers.h"
00045 #include "dlg_profile.h"
00046 
00047 
00049 #define PROFILE_HASH_SIZE 16
00050 
00052 extern struct tm_binds d_tmb;
00053 
00055 static unsigned int       current_dlg_msg_id  = 0 ;
00056 static unsigned int       current_dlg_msg_pid = 0 ;
00057 
00059 static dlg_profile_link_t *current_pending_linkers = NULL;
00060 
00062 static dlg_profile_table_t *profiles = NULL;
00063 
00064 
00065 static dlg_profile_table_t* new_dlg_profile( str *name,
00066                 unsigned int size, unsigned int has_value);
00067 
00068 
00069 
00077 int add_profile_definitions( char* profiles, unsigned int has_value)
00078 {
00079         char *p;
00080         char *d;
00081         str name;
00082         unsigned int i;
00083 
00084         if (profiles==NULL || strlen(profiles)==0 )
00085                 return 0;
00086 
00087         p = profiles;
00088         do {
00089                 /* locate name of profile */
00090                 name.s = p;
00091                 d = strchr( p, ';');
00092                 if (d) {
00093                         name.len = d-p;
00094                         d++;
00095                 } else {
00096                         name.len = strlen(p);
00097                 }
00098 
00099                 /* we have the name -> trim it for spaces */
00100                 trim_spaces_lr( name );
00101 
00102                 /* check len name */
00103                 if (name.len==0)
00104                         /* ignore */
00105                         continue;
00106 
00107                 /* check the name format */
00108                 for(i=0;i<name.len;i++) {
00109                         if ( !isalnum(name.s[i]) ) {
00110                                 LM_ERR("bad profile name <%.*s>, char %c - use only "
00111                                         "alphanumerical characters\n", name.len,name.s,name.s[i]);
00112                                 return -1;
00113                         }
00114                 }
00115 
00116                 /* name ok -> create the profile */
00117                 LM_DBG("creating profile <%.*s>\n",name.len,name.s);
00118 
00119                 if (new_dlg_profile( &name, PROFILE_HASH_SIZE, has_value)==NULL) {
00120                         LM_ERR("failed to create new profile <%.*s>\n",name.len,name.s);
00121                         return -1;
00122                 }
00123 
00124         }while( (p=d)!=NULL );
00125 
00126         return 0;
00127 }
00128 
00129 
00136 struct dlg_profile_table* search_dlg_profile(str *name)
00137 {
00138         struct dlg_profile_table *profile;
00139 
00140         for( profile=profiles ; profile ; profile=profile->next ) {
00141                 if (name->len==profile->name.len &&
00142                 memcmp(name->s,profile->name.s,name->len)==0 )
00143                         return profile;
00144         }
00145         return NULL;
00146 }
00147 
00148 
00157 static struct dlg_profile_table* new_dlg_profile( str *name, unsigned int size,
00158                 unsigned int has_value)
00159 {
00160         struct dlg_profile_table *profile;
00161         struct dlg_profile_table *ptmp;
00162         unsigned int len;
00163         unsigned int i;
00164 
00165         if ( name->s==NULL || name->len==0 || size==0 ) {
00166                 LM_ERR("invalid parameters\n");
00167                 return NULL;
00168         }
00169 
00170         for( len=0,i=0 ; i<8*sizeof(size) ; i++ ) {
00171                 if ( size & (1<<i) ) len++;
00172         }
00173         if (len!=1) {
00174                 LM_ERR(" size %u is not power of 2!\n", size);
00175                 return NULL;
00176         }
00177 
00178         profile = search_dlg_profile(name);
00179         if (profile!=NULL) {
00180                 LM_ERR("duplicate dialog profile registered <%.*s>\n",
00181                         name->len, name->s);
00182                 return NULL;
00183         }
00184 
00185         len = sizeof(struct dlg_profile_table) +
00186                 size*sizeof(struct dlg_profile_entry) +
00187                 name->len + 1;
00188         profile = (struct dlg_profile_table *)shm_malloc(len);
00189         if (profile==NULL) {
00190                 LM_ERR("no more shm mem\n");
00191                 return NULL;
00192         }
00193 
00194         memset( profile , 0 , len);
00195         profile->size = size;
00196         profile->has_value = (has_value==0)?0:1;
00197 
00198         /* init lock */
00199         if (lock_init( &profile->lock )==NULL) {
00200                 LM_ERR("failed to init lock\n");
00201                 shm_free(profile);
00202                 return NULL;
00203         }
00204 
00205         /* set inner pointers */
00206         profile->entries = (struct dlg_profile_entry*)(profile + 1);
00207         profile->name.s = ((char*)profile->entries) + 
00208                 size*sizeof(struct dlg_profile_entry);
00209 
00210         /* copy the name of the profile */
00211         memcpy( profile->name.s, name->s, name->len );
00212         profile->name.len = name->len;
00213         profile->name.s[profile->name.len] = 0;
00214 
00215         /* link profile */
00216         for( ptmp=profiles ; ptmp && ptmp->next; ptmp=ptmp->next );
00217         if (ptmp==NULL)
00218                 profiles = profile;
00219         else
00220                 ptmp->next = profile;
00221 
00222         return profile;
00223 }
00224 
00225 
00230 static void destroy_dlg_profile(struct dlg_profile_table *profile)
00231 {
00232         if (profile==NULL)
00233                 return;
00234 
00235         lock_destroy( &profile->lock );
00236         shm_free( profile );
00237         return;
00238 }
00239 
00240 
00244 void destroy_dlg_profiles(void)
00245 {
00246         struct dlg_profile_table *profile;
00247 
00248         while(profiles) {
00249                 profile = profiles;
00250                 profiles = profiles->next;
00251                 destroy_dlg_profile( profile );
00252         }
00253         return;
00254 }
00255 
00256 
00261 void destroy_linkers(struct dlg_profile_link *linker)
00262 {
00263         struct dlg_profile_entry *p_entry;
00264         struct dlg_profile_link *l;
00265         struct dlg_profile_hash *lh;
00266 
00267         while(linker) {
00268                 l = linker;
00269                 linker = linker->next;
00270                 /* unlink from profile table */
00271                 if (l->hash_linker.next) {
00272                         p_entry = &l->profile->entries[l->hash_linker.hash];
00273                         lock_get( &l->profile->lock );
00274                         lh = &l->hash_linker;
00275                         /* last element on the list? */
00276                         if (lh==lh->next) {
00277                                 p_entry->first = NULL;
00278                         } else {
00279                                 if (p_entry->first==lh)
00280                                         p_entry->first = lh->next;
00281                                 lh->next->prev = lh->prev;
00282                                 lh->prev->next = lh->next;
00283                         }
00284                         lh->next = lh->prev = NULL;
00285                         p_entry->content --;
00286                         lock_release( &l->profile->lock );
00287                 }
00288                 /* free memory */
00289                 shm_free(l);
00290         }
00291 }
00292 
00293 
00301 int profile_cleanup( struct sip_msg *msg, unsigned int flags, void *param )
00302 {
00303         dlg_cell_t *dlg;
00304 
00305         current_dlg_msg_id = 0;
00306         current_dlg_msg_pid = 0;
00307         dlg = dlg_get_ctx_dialog();
00308         if (dlg!=NULL) {
00309                 if(dlg->dflags & DLG_FLAG_TM) {
00310                         dlg_unref(dlg, 1);
00311                 } else {
00312                         /* dialog didn't make it to tm */
00313                         dlg_unref(dlg, 2);
00314                 }
00315         }
00316         if (current_pending_linkers) {
00317                 destroy_linkers(current_pending_linkers);
00318                 current_pending_linkers = NULL;
00319         }
00320 
00321         /* need to return non-zero - 0 will break the exec of the request */
00322         return 1;
00323 }
00324 
00325 
00326 
00335 inline static unsigned int calc_hash_profile(str *value, dlg_cell_t *dlg,
00336                 dlg_profile_table_t *profile)
00337 {
00338         if (profile->has_value) {
00339                 /* do hash over the value */
00340                 return core_hash( value, NULL, profile->size);
00341         } else {
00342                 /* do hash over dialog pointer */
00343                 return ((unsigned long)dlg) % profile->size ;
00344         }
00345 }
00346 
00347 
00353 static void link_dlg_profile(struct dlg_profile_link *linker, struct dlg_cell *dlg)
00354 {
00355         unsigned int hash;
00356         struct dlg_profile_entry *p_entry;
00357         struct dlg_entry *d_entry;
00358 
00359         /* add the linker to the dialog */
00360         /* FIXME zero h_id is not 100% for testing if the dialog is inserted
00361          * into the hash table -> we need circular lists  -bogdan */
00362         if (dlg->h_id) {
00363                 d_entry = &d_table->entries[dlg->h_entry];
00364                 dlg_lock( d_table, d_entry);
00365                 linker->next = dlg->profile_links;
00366                 dlg->profile_links =linker;
00367                 linker->hash_linker.dlg = dlg;
00368                 dlg_unlock( d_table, d_entry);
00369         } else {
00370                 linker->next = dlg->profile_links;
00371                 dlg->profile_links =linker;
00372                 linker->hash_linker.dlg = dlg;
00373         }
00374 
00375         /* calculate the hash position */
00376         hash = calc_hash_profile(&linker->hash_linker.value, dlg, linker->profile);
00377         linker->hash_linker.hash = hash;
00378 
00379         /* insert into profile hash table */
00380         p_entry = &linker->profile->entries[hash];
00381         lock_get( &linker->profile->lock );
00382         if (p_entry->first) {
00383                 linker->hash_linker.prev = p_entry->first->prev;
00384                 linker->hash_linker.next = p_entry->first;
00385                 p_entry->first->prev->next = &linker->hash_linker;
00386                 p_entry->first->prev = &linker->hash_linker;
00387         } else {
00388                 p_entry->first = linker->hash_linker.next 
00389                         = linker->hash_linker.prev = &linker->hash_linker;
00390         }
00391         p_entry->content ++;
00392         lock_release( &linker->profile->lock );
00393 }
00394 
00395 
00401 void set_current_dialog(sip_msg_t *msg, dlg_cell_t *dlg)
00402 {
00403         struct dlg_profile_link *linker;
00404         struct dlg_profile_link *tlinker;
00405 
00406         LM_DBG("setting current dialog [%u:%u]\n", dlg->h_entry, dlg->h_id);
00407         /* if linkers are not from current request, just discard them */
00408         if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
00409                 current_dlg_msg_id = msg->id;
00410                 current_dlg_msg_pid = msg->pid;
00411                 destroy_linkers(current_pending_linkers);
00412         } else {
00413                 /* add the linker, one by one, to the dialog */
00414                 linker = current_pending_linkers;
00415                 while (linker) {
00416                         tlinker = linker;
00417                         linker = linker->next;
00418                         /* process tlinker */
00419                         tlinker->next = NULL;
00420                         link_dlg_profile( tlinker, dlg);
00421                 }
00422         }
00423         current_pending_linkers = NULL;
00424 }
00425 
00426 
00434 int set_dlg_profile(struct sip_msg *msg, str *value, struct dlg_profile_table *profile)
00435 {
00436         dlg_cell_t *dlg = NULL;
00437         dlg_profile_link_t *linker;
00438 
00439         /* get current dialog */
00440         dlg = dlg_get_msg_dialog(msg);
00441 
00442         if (dlg==NULL && !is_route_type(REQUEST_ROUTE)) {
00443                 LM_CRIT("BUG - dialog not found in a non REQUEST route (%d)\n",
00444                         REQUEST_ROUTE);
00445                 return -1;
00446         }
00447 
00448         /* build new linker */
00449         linker = (struct dlg_profile_link*)shm_malloc(
00450                 sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) );
00451         if (linker==NULL) {
00452                 LM_ERR("no more shm memory\n");
00453                 goto error;
00454         }
00455         memset(linker, 0, sizeof(struct dlg_profile_link));
00456 
00457         /* set backpointer to profile */
00458         linker->profile = profile;
00459 
00460         /* set the value */
00461         if (profile->has_value) {
00462                 linker->hash_linker.value.s = (char*)(linker+1);
00463                 memcpy( linker->hash_linker.value.s, value->s, value->len);
00464                 linker->hash_linker.value.len = value->len;
00465         }
00466 
00467         if (dlg!=NULL) {
00468                 /* add linker directly to the dialog and profile */
00469                 link_dlg_profile( linker, dlg);
00470         } else {
00471                 /* no dialog yet -> set linker as pending */
00472                 if (msg->id!=current_dlg_msg_id || msg->pid!=current_dlg_msg_pid) {
00473                         current_dlg_msg_id = msg->id;
00474                         current_dlg_msg_pid = msg->pid;
00475                         destroy_linkers(current_pending_linkers);
00476                 }
00477 
00478                 linker->next = current_pending_linkers;
00479                 current_pending_linkers = linker;
00480         }
00481 
00482         dlg_release(dlg);
00483         return 0;
00484 error:
00485         dlg_release(dlg);
00486         return -1;
00487 }
00488 
00496 int dlg_add_profile(dlg_cell_t *dlg, str *value, struct dlg_profile_table *profile)
00497 {
00498         dlg_profile_link_t *linker;
00499 
00500         if (dlg==NULL)
00501                 return -1;
00502 
00503         /* build new linker */
00504         linker = (struct dlg_profile_link*)shm_malloc(
00505                 sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) );
00506         if (linker==NULL) {
00507                 LM_ERR("no more shm memory\n");
00508                 goto error;
00509         }
00510         memset(linker, 0, sizeof(struct dlg_profile_link));
00511 
00512         /* set backpointer to profile */
00513         linker->profile = profile;
00514 
00515         /* set the value */
00516         if (profile->has_value) {
00517                 linker->hash_linker.value.s = (char*)(linker+1);
00518                 memcpy( linker->hash_linker.value.s, value->s, value->len);
00519                 linker->hash_linker.value.len = value->len;
00520         }
00521 
00522         /* add linker directly to the dialog and profile */
00523         link_dlg_profile( linker, dlg);
00524         return 0;
00525 error:
00526         return -1;
00527 }
00528 
00536 int unset_dlg_profile(sip_msg_t *msg, str *value,
00537                 dlg_profile_table_t *profile)
00538 {
00539         dlg_cell_t *dlg;
00540         dlg_profile_link_t *linker;
00541         dlg_profile_link_t *linker_prev;
00542         dlg_entry_t *d_entry;
00543 
00544         if (is_route_type(REQUEST_ROUTE)) {
00545                 LM_ERR("dialog delete profile cannot be used in request route\n");
00546                 return -1;
00547         }
00548 
00549         /* get current dialog */
00550         dlg = dlg_get_msg_dialog(msg);
00551 
00552         if (dlg==NULL) {
00553                 LM_WARN("dialog is NULL for delete profile\n");
00554                 return -1;
00555         }
00556 
00557         /* check the dialog linkers */
00558         d_entry = &d_table->entries[dlg->h_entry];
00559         dlg_lock( d_table, d_entry);
00560         linker = dlg->profile_links;
00561         linker_prev = NULL;
00562         for( ; linker ; linker_prev=linker,linker=linker->next) {
00563                 if (linker->profile==profile) {
00564                         if (profile->has_value==0) {
00565                                 goto found;
00566                         } else if (value && value->len==linker->hash_linker.value.len &&
00567                         memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
00568                                 goto found;
00569                         }
00570                         /* allow further search - maybe the dialog is inserted twice in
00571                          * the same profile, but with different values -bogdan
00572                          */
00573                 }
00574         }
00575         dlg_unlock( d_table, d_entry);
00576         dlg_release(dlg);
00577         return -1;
00578 
00579 found:
00580         /* table still locked */
00581         /* remove the linker element from dialog */
00582         if (linker_prev==NULL) {
00583                 dlg->profile_links = linker->next;
00584         } else {
00585                 linker_prev->next = linker->next;
00586         }
00587         linker->next = NULL;
00588         dlg_unlock( d_table, d_entry);
00589         /* remove linker from profile table and free it */
00590         destroy_linkers(linker);
00591         dlg_release(dlg);
00592         return 1;
00593 }
00594 
00595 
00603 int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile,
00604                 str *value)
00605 {
00606         struct dlg_cell *dlg;
00607         struct dlg_profile_link *linker;
00608         struct dlg_entry *d_entry;
00609 
00610         /* get current dialog */
00611         dlg = dlg_get_msg_dialog(msg);
00612 
00613         if (dlg==NULL)
00614                 return -1;
00615 
00616         /* check the dialog linkers */
00617         d_entry = &d_table->entries[dlg->h_entry];
00618         dlg_lock( d_table, d_entry);
00619         for( linker=dlg->profile_links ; linker ; linker=linker->next) {
00620                 if (linker->profile==profile) {
00621                         if (profile->has_value==0) {
00622                                 dlg_unlock( d_table, d_entry);
00623                                 goto done;
00624                         } else if (value && value->len==linker->hash_linker.value.len &&
00625                         memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
00626                                 dlg_unlock( d_table, d_entry);
00627                                 goto done;
00628                         }
00629                         /* allow further search - maybe the dialog is inserted twice in
00630                          * the same profile, but with different values -bogdan
00631                          */
00632                 }
00633         }
00634         dlg_unlock( d_table, d_entry);
00635 
00636 done:
00637         dlg_release(dlg);
00638         return -1;
00639 }
00640 
00641 
00648 unsigned int get_profile_size(struct dlg_profile_table *profile, str *value)
00649 {
00650         unsigned int n,i;
00651         struct dlg_profile_hash *ph;
00652 
00653         if (profile->has_value==0 || value==NULL) {
00654                 /* iterate through the hash and count all records */
00655                 lock_get( &profile->lock );
00656                 for( i=0,n=0 ; i<profile->size ; i++ )
00657                         n += profile->entries[i].content;
00658                 lock_release( &profile->lock );
00659                 return n;
00660         } else {
00661                 /* iterate through the hash entry and count only matching */
00662                 /* calculate the hash position */
00663                 i = calc_hash_profile( value, NULL, profile);
00664                 n = 0;
00665                 lock_get( &profile->lock );
00666                 ph = profile->entries[i].first;
00667                 if(ph) {
00668                         do {
00669                                 /* compare */
00670                                 if ( value->len==ph->value.len &&
00671                                 memcmp(value->s,ph->value.s,value->len)==0 ) {
00672                                         /* found */
00673                                         n++;
00674                                 }
00675                                 /* next */
00676                                 ph=ph->next;
00677                         }while( ph!=profile->entries[i].first );
00678                 }
00679                 lock_release( &profile->lock );
00680                 return n;
00681         }
00682 }
00683 
00684 /*
00685  * Determine if message is in a dialog currently being tracked
00686  */
00687 int     is_known_dlg(struct sip_msg *msg) {
00688         dlg_cell_t *dlg;
00689 
00690         dlg = dlg_get_msg_dialog(msg);
00691         
00692         if(dlg == NULL)
00693                 return -1;
00694 
00695         dlg_release(dlg);
00696 
00697         return 1;
00698 }
00699 
00700 /****************************** MI commands *********************************/
00701 
00708 struct mi_root * mi_get_profile(struct mi_root *cmd_tree, void *param)
00709 {
00710         struct mi_node* node;
00711         struct mi_root* rpl_tree= NULL;
00712         struct mi_node* rpl = NULL;
00713         struct mi_attr* attr;
00714         struct dlg_profile_table *profile;
00715         str *value;
00716         str *profile_name;
00717         unsigned int size;
00718         int len;
00719         char *p;
00720 
00721         node = cmd_tree->node.kids;
00722         if (node==NULL || !node->value.s || !node->value.len)
00723                 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00724         profile_name = &node->value;
00725 
00726         if (node->next) {
00727                 node = node->next;
00728                 if (!node->value.s || !node->value.len)
00729                         return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
00730                 if (node->next)
00731                         return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00732                 value = &node->value;
00733         } else {
00734                 value = NULL;
00735         }
00736 
00737         /* search for the profile */
00738         profile = search_dlg_profile( profile_name );
00739         if (profile==NULL)
00740                 return init_mi_tree( 404, MI_SSTR("Profile not found"));
00741 
00742         size = get_profile_size( profile , value );
00743 
00744         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00745         if (rpl_tree==0)
00746                 return 0;
00747         rpl = &rpl_tree->node;
00748 
00749         node = add_mi_node_child(rpl, MI_DUP_VALUE, "profile", 7, NULL, 0);
00750         if (node==0) {
00751                 free_mi_tree(rpl_tree);
00752                 return NULL;
00753         }
00754 
00755         attr = add_mi_attr(node, MI_DUP_VALUE, "name", 4, 
00756                 profile->name.s, profile->name.len);
00757         if(attr == NULL) {
00758                 goto error;
00759         }
00760 
00761         if (value) {
00762                 attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, value->s, value->len);
00763         } else {
00764                 attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, NULL, 0);
00765         }
00766         if(attr == NULL) {
00767                 goto error;
00768         }
00769 
00770         p= int2str((unsigned long)size, &len);
00771         attr = add_mi_attr(node, MI_DUP_VALUE, "count", 5, p, len);
00772         if(attr == NULL) {
00773                 goto error;
00774         }
00775 
00776         return rpl_tree;
00777 error:
00778         free_mi_tree(rpl_tree);
00779         return NULL;
00780 }
00781 
00782 
00789 struct mi_root * mi_profile_list(struct mi_root *cmd_tree, void *param )
00790 {
00791         struct mi_node* node;
00792         struct mi_root* rpl_tree= NULL;
00793         struct mi_node* rpl = NULL;
00794         struct dlg_profile_table *profile;
00795         struct dlg_profile_hash *ph;
00796         str *profile_name;
00797         str *value;
00798         unsigned int i;
00799 
00800         node = cmd_tree->node.kids;
00801         if (node==NULL || !node->value.s || !node->value.len)
00802                 return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00803         profile_name = &node->value;
00804 
00805         if (node->next) {
00806                 node = node->next;
00807                 if (!node->value.s || !node->value.len)
00808                         return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
00809                 if (node->next)
00810                         return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00811                 value = &node->value;
00812         } else {
00813                 value = NULL;
00814         }
00815 
00816         /* search for the profile */
00817         profile = search_dlg_profile( profile_name );
00818         if (profile==NULL)
00819                 return init_mi_tree( 404, MI_SSTR("Profile not found"));
00820 
00821         rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00822         if (rpl_tree==0)
00823                 return 0;
00824         rpl = &rpl_tree->node;
00825 
00826         /* go through the hash and print the dialogs */
00827         if (profile->has_value==0 || value==NULL) {
00828                 /* no value */
00829                 lock_get( &profile->lock );
00830                 for ( i=0 ; i< profile->size ; i++ ) {
00831                         ph = profile->entries[i].first;
00832                         if(ph) {
00833                                 do {
00834                                         /* print dialog */
00835                                         if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 )
00836                                                 goto error;
00837                                         /* next */
00838                                         ph=ph->next;
00839                                 }while( ph!=profile->entries[i].first );
00840                         }
00841                         lock_release( &profile->lock );
00842                 }
00843         } else {
00844                 /* check for value also */
00845                 lock_get( &profile->lock );
00846                 for ( i=0 ; i< profile->size ; i++ ) {
00847                         ph = profile->entries[i].first;
00848                         if(ph) {
00849                                 do {
00850                                         if ( value->len==ph->value.len &&
00851                                         memcmp(value->s,ph->value.s,value->len)==0 ) {
00852                                                 /* print dialog */
00853                                                 if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 )
00854                                                         goto error;
00855                                         }
00856                                         /* next */
00857                                         ph=ph->next;
00858                                 }while( ph!=profile->entries[i].first );
00859                         }
00860                         lock_release( &profile->lock );
00861                 }
00862         }
00863 
00864         return rpl_tree;
00865 error:
00866         free_mi_tree(rpl_tree);
00867         return NULL;
00868 }
00869 
00870 
00874 int dlg_profiles_to_json(dlg_cell_t *dlg, srjson_doc_t *jdoc)
00875 {
00876         dlg_profile_link_t *l;
00877         srjson_t *sj = NULL;
00878         srjson_t *dj = NULL;
00879 
00880         LM_DBG("serializing profiles for dlg[%u:%u]\n",
00881                                 dlg->h_entry, dlg->h_id);
00882         if(dlg==NULL || dlg->profile_links==NULL)
00883                 return -1;
00884         LM_DBG("start of serializing profiles for dlg[%u:%u]\n",
00885                                 dlg->h_entry, dlg->h_id);
00886 
00887         for (l = dlg->profile_links ; l ; l=l->next) {
00888                 if(l->profile->has_value)
00889                 {
00890                         if(dj==NULL)
00891                         {
00892                                 dj = srjson_CreateObject(jdoc);
00893                                 if(dj==NULL)
00894                                 {
00895                                         LM_ERR("cannot create json dynamic profiles obj\n");
00896                                         goto error;
00897                                 }
00898                         }
00899                         srjson_AddStrStrToObject(jdoc, dj,
00900                                         l->profile->name.s, l->profile->name.len,
00901                                         l->hash_linker.value.s, l->hash_linker.value.len);
00902                 } else {
00903                         if(sj==NULL)
00904                         {
00905                                 sj = srjson_CreateArray(jdoc);
00906                                 if(sj==NULL)
00907                                 {
00908                                         LM_ERR("cannot create json static profiles obj\n");
00909                                         goto error;
00910                                 }
00911                         }
00912                         srjson_AddItemToArray(jdoc, sj,
00913                                         srjson_CreateStr(jdoc, l->profile->name.s, l->profile->name.len));
00914                 }
00915         }
00916 
00917         if(jdoc->root==NULL)
00918         {
00919                 jdoc->root = srjson_CreateObject(jdoc);
00920                 if(jdoc->root==NULL)
00921                 {
00922                         LM_ERR("cannot create json root\n");
00923                         goto error;
00924                 }
00925         }
00926         if(dj!=NULL)
00927                 srjson_AddItemToObject(jdoc, jdoc->root, "dprofiles", dj);
00928         if(sj!=NULL)
00929                 srjson_AddItemToObject(jdoc, jdoc->root, "sprofiles", sj);
00930         if(jdoc->buf.s != NULL)
00931         {
00932                 jdoc->free_fn(jdoc->buf.s);
00933                 jdoc->buf.s = NULL;
00934                 jdoc->buf.len = 0;
00935         }
00936         jdoc->buf.s = srjson_PrintUnformatted(jdoc, jdoc->root);
00937         if(jdoc->buf.s!=NULL)
00938         {
00939                 jdoc->buf.len = strlen(jdoc->buf.s);
00940                 LM_DBG("serialized profiles for dlg[%u:%u] = [[%.*s]]\n",
00941                                 dlg->h_entry, dlg->h_id, jdoc->buf.len, jdoc->buf.s);
00942                 return 0;
00943         }
00944         return -1;
00945 
00946 error:
00947         srjson_Delete(jdoc, dj);
00948         srjson_Delete(jdoc, sj);
00949         return -1;
00950 }
00951 
00952 
00956 int dlg_json_to_profiles(dlg_cell_t *dlg, srjson_doc_t *jdoc)
00957 {
00958         srjson_t *sj = NULL;
00959         srjson_t *dj = NULL;
00960         srjson_t *it = NULL;
00961         dlg_profile_table_t *profile;
00962         str name;
00963         str val;
00964 
00965         if(dlg==NULL || jdoc==NULL || jdoc->buf.s==NULL)
00966                 return -1;
00967 
00968         if(jdoc->root == NULL)
00969         {
00970                 jdoc->root = srjson_Parse(jdoc, jdoc->buf.s);
00971                 if(jdoc->root == NULL)
00972                 {
00973                         LM_ERR("invalid json doc [[%s]]\n", jdoc->buf.s);
00974                         return -1;
00975                 }
00976         }
00977         dj = srjson_GetObjectItem(jdoc, jdoc->root, "dprofiles");
00978         sj = srjson_GetObjectItem(jdoc, jdoc->root, "sprofiles");
00979         if(dj!=NULL)
00980         {
00981                 for(it=dj->child; it; it = it->next)
00982                 {
00983                         name.s = it->string;
00984                         name.len = strlen(name.s);
00985                         val.s = it->valuestring;
00986                         val.len = strlen(val.s);
00987                         profile = search_dlg_profile(&name);
00988                         if(profile==NULL)
00989                         {
00990                                 LM_ERR("profile [%.*s] not found\n", name.len, name.s);
00991                                 continue;
00992                         }
00993                         if(profile->has_value)
00994                         {
00995                                 if(dlg_add_profile(dlg, &val, profile) < 0)
00996                                         LM_ERR("dynamic profile cannot be added, ignore!\n");
00997                                 else
00998                                         LM_DBG("dynamic profile added [%s : %s]\n", name.s, val.s);
00999                         }
01000                 }
01001         }
01002         if(sj!=NULL)
01003         {
01004                 for(it=sj->child; it; it = it->next)
01005                 {
01006                         name.s = it->valuestring;
01007                         name.len = strlen(name.s);
01008                         profile = search_dlg_profile(&name);
01009                         if(profile==NULL)
01010                         {
01011                                 LM_ERR("profile [%.*s] not found\n", name.len, name.s);
01012                                 continue;
01013                         }
01014                         if(!profile->has_value)
01015                         {
01016                                 if(dlg_add_profile(dlg, NULL, profile) < 0)
01017                                         LM_ERR("static profile cannot be added, ignore!\n");
01018                                 else
01019                                         LM_DBG("static profile added [%s]\n", name.s);
01020                         }
01021                 }
01022         }
01023         return 0;
01024 }