dlg_profile.c

Go to the documentation of this file.
00001 /*
00002  * $Id: dlg_profile.c 5787 2009-04-02 19:55:23Z henningw $
00003  *
00004  * Copyright (C) 2008 Voice System SRL
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  * 2008-04-20  initial version (bogdan)
00025  *
00026  */
00027 
00028 
00029 /*!
00030  * \file
00031  * \brief Profile related functions for the dialog module
00032  * \ingroup dialog
00033  * Module: \ref dialog
00034  */
00035 
00036 
00037 #include "../../mem/shm_mem.h"
00038 #include "../../hash_func.h"
00039 #include "../../dprint.h"
00040 #include "../../ut.h"
00041 #include "../../route.h"
00042 #include "../tm/tm_load.h"
00043 #include "dlg_hash.h"
00044 #include "dlg_profile.h"
00045 
00046 
00047 /*! size of dialog profile hash */
00048 #define PROFILE_HASH_SIZE 16
00049 
00050 /*! tm bindings */
00051 extern struct tm_binds d_tmb;
00052 
00053 /*! global dialog message id */
00054 static unsigned int            current_dlg_msg_id = 0 ;
00055 
00056 /*! global dialog */
00057 struct dlg_cell                *current_dlg_pointer = NULL ;
00058 
00059 /*! pending dialog links */
00060 static struct dlg_profile_link *current_pending_linkers = NULL;
00061 
00062 /*! global dialog profile list */
00063 static struct dlg_profile_table *profiles = NULL;
00064 
00065 
00066 static struct dlg_profile_table* new_dlg_profile( str *name,
00067       unsigned int size, unsigned int has_value);
00068 
00069 
00070 /*!
00071  * \brief Add profile definitions to the global list
00072  * \see new_dlg_profile
00073  * \param profiles profile name
00074  * \param has_value set to 0 for a profile without value, otherwise it has a value
00075  * \return 0 on success, -1 on failure
00076  */
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 
00130 /*!
00131  * \brief Search a dialog profile in the global list
00132  * \note Linear search, this won't have the best performance for huge profile lists
00133  * \param name searched dialog profile
00134  * \return pointer to the profile on success, NULL otherwise
00135  */
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 
00149 /*!
00150  * \brief Creates a new dialog profile
00151  * \see add_profile_definitions
00152  * \param name profile name
00153  * \param size profile size
00154  * \param has_value set to 0 for a profile without value, otherwise it has a value
00155  * \return pointer to the created dialog on success, NULL otherwise
00156  */
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 
00226 /*!
00227  * \brief Destroy a dialog profile list
00228  * \param profile dialog profile
00229  */
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 
00241 /*!
00242  * \brief Destroy the global dialog profile list
00243  */
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 
00257 /*!
00258  * \brief Destroy dialog linkers
00259  * \param linker dialog linker
00260  */ 
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          get_lock( &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          release_lock( &l->profile->lock );
00287       }
00288       /* free memory */
00289       shm_free(l);
00290    }
00291 }
00292 
00293 
00294 /*!
00295  * \brief Cleanup a profile
00296  * \param msg SIP message
00297  * \param unused
00298  * \return 1
00299  */
00300 int profile_cleanup( struct sip_msg *msg, void *param )
00301 {
00302    current_dlg_msg_id = 0;
00303    if (current_dlg_pointer) {
00304       unref_dlg( current_dlg_pointer, 1);
00305       current_dlg_pointer = NULL;
00306    }
00307    if (current_pending_linkers) {
00308       destroy_linkers(current_pending_linkers);
00309       current_pending_linkers = NULL;
00310    }
00311 
00312    /* need to return non-zero - 0 will break the exec of the request */
00313    return 1;
00314 }
00315 
00316 
00317 /*!
00318  * \brief Get the current dialog for a message, if exists
00319  * \param msg SIP message
00320  * \return NULL if called in REQUEST_ROUTE, pointer to dialog ctx otherwise
00321  */ 
00322 static struct dlg_cell *get_current_dialog(struct sip_msg *msg)
00323 {
00324    struct cell *trans;
00325 
00326    if (route_type==REQUEST_ROUTE) {
00327       /* use the per-process static holder */
00328       if (msg->id==current_dlg_msg_id)
00329          return current_dlg_pointer;
00330       current_dlg_pointer = NULL;
00331       current_dlg_msg_id = msg->id;
00332       destroy_linkers(current_pending_linkers);
00333       current_pending_linkers = NULL;
00334       return NULL;
00335    } else {
00336       /* use current transaction to get dialog */
00337       trans = d_tmb.t_gett();
00338       if (trans==NULL || trans==T_UNDEFINED)
00339          return NULL;
00340       return (struct dlg_cell*)trans->dialog_ctx;
00341    }
00342 }
00343 
00344 
00345 /*!
00346  * \brief Calculate the hash profile from a dialog
00347  * \see core_hash
00348  * \param value hash source
00349  * \param dlg dialog cell
00350  * \param profile dialog profile table (for hash size)
00351  * \return value hash if the value has a value, hash over dialog otherwise
00352  */
00353 inline static unsigned int calc_hash_profile(str *value, struct dlg_cell *dlg,
00354       struct dlg_profile_table *profile)
00355 {
00356    if (profile->has_value) {
00357       /* do hash over the value */
00358       return core_hash( value, NULL, profile->size);
00359    } else {
00360       /* do hash over dialog pointer */
00361       return ((unsigned long)dlg) % profile->size ;
00362    }
00363 }
00364 
00365 
00366 /*!
00367  * \brief Link a dialog profile
00368  * \param linker dialog linker
00369  * \param dlg dialog cell
00370  */
00371 static void link_dlg_profile(struct dlg_profile_link *linker, struct dlg_cell *dlg)
00372 {
00373    unsigned int hash;
00374    struct dlg_profile_entry *p_entry;
00375    struct dlg_entry *d_entry;
00376 
00377    /* add the linker to the dialog */
00378    /* FIXME zero h_id is not 100% for testing if the dialog is inserted
00379     * into the hash table -> we need circular lists  -bogdan */
00380    if (dlg->h_id) {
00381       d_entry = &d_table->entries[dlg->h_entry];
00382       dlg_lock( d_table, d_entry);
00383       linker->next = dlg->profile_links;
00384       dlg->profile_links =linker;
00385       linker->hash_linker.dlg = dlg;
00386       dlg_unlock( d_table, d_entry);
00387    } else {
00388       linker->next = dlg->profile_links;
00389       dlg->profile_links =linker;
00390       linker->hash_linker.dlg = dlg;
00391    }
00392 
00393    /* calculate the hash position */
00394    hash = calc_hash_profile(&linker->hash_linker.value, dlg, linker->profile);
00395    linker->hash_linker.hash = hash;
00396 
00397    /* insert into profile hash table */
00398    p_entry = &linker->profile->entries[hash];
00399    get_lock( &linker->profile->lock );
00400    if (p_entry->first) {
00401       linker->hash_linker.prev = p_entry->first->prev;
00402       linker->hash_linker.next = p_entry->first;
00403       p_entry->first->prev->next = &linker->hash_linker;
00404       p_entry->first->prev = &linker->hash_linker;
00405    } else {
00406       p_entry->first = linker->hash_linker.next 
00407          = linker->hash_linker.prev = &linker->hash_linker;
00408    }
00409    p_entry->content ++;
00410    release_lock( &linker->profile->lock );
00411 }
00412 
00413 
00414 /*!
00415  * \brief Set the global variables to the current dialog
00416  * \param msg SIP message
00417  * \param dlg dialog cell
00418  */
00419 void set_current_dialog(struct sip_msg *msg, struct dlg_cell *dlg)
00420 {
00421    struct dlg_profile_link *linker;
00422    struct dlg_profile_link *tlinker;
00423 
00424    /* if linkers are not from current request, just discard them */
00425    if (msg->id!=current_dlg_msg_id) {
00426       current_dlg_msg_id = msg->id;
00427       destroy_linkers(current_pending_linkers);
00428    } else {
00429       /* add the linker, one be one, to the dialog */
00430       linker = current_pending_linkers;
00431       while (linker) {
00432          tlinker = linker;
00433          linker = linker->next;
00434          /* process tlinker */
00435          tlinker->next = NULL;
00436          link_dlg_profile( tlinker, dlg);
00437       }
00438    }
00439    current_pending_linkers = NULL;
00440    current_dlg_pointer = dlg;
00441 }
00442 
00443 
00444 /*!
00445  * \brief Set a dialog profile
00446  * \param msg SIP message
00447  * \param value value
00448  * \param profile dialog profile table
00449  * \return 0 on success, -1 on failure
00450  */
00451 int set_dlg_profile(struct sip_msg *msg, str *value, struct dlg_profile_table *profile)
00452 {
00453    struct dlg_cell *dlg;
00454    struct dlg_profile_link *linker;
00455 
00456    /* get current dialog */
00457    dlg = get_current_dialog(msg);
00458 
00459    if (dlg==NULL && route_type!=REQUEST_ROUTE) {
00460       LM_CRIT("BUG - dialog not found in a non REQUEST route (%d)\n",
00461          REQUEST_ROUTE);
00462       return -1;
00463    }
00464 
00465    /* build new linker */
00466    linker = (struct dlg_profile_link*)shm_malloc(
00467       sizeof(struct dlg_profile_link) + (profile->has_value?value->len:0) );
00468    if (linker==NULL) {
00469       LM_ERR("no more shm memory\n");
00470       return -1;
00471    }
00472    memset(linker, 0, sizeof(struct dlg_profile_link));
00473 
00474    /* set backpointer to profile */
00475    linker->profile = profile;
00476 
00477    /* set the value */
00478    if (profile->has_value) {
00479       linker->hash_linker.value.s = (char*)(linker+1);
00480       memcpy( linker->hash_linker.value.s, value->s, value->len);
00481       linker->hash_linker.value.len = value->len;
00482    }
00483 
00484    if (dlg!=NULL) {
00485       /* add linker directly to the dialog and profile */
00486       link_dlg_profile( linker, dlg);
00487    } else {
00488       /* no dialog yet -> set linker as pending */
00489       linker->next = current_pending_linkers;
00490       current_pending_linkers = linker;
00491    }
00492 
00493    return 0;
00494 }
00495 
00496 
00497 /*!
00498  * \brief Unset a dialog profile
00499  * \param msg SIP message
00500  * \param value value
00501  * \param profile dialog profile table
00502  * \return 1 on success, -1 on failure
00503  */
00504 int unset_dlg_profile(struct sip_msg *msg, str *value,
00505       struct dlg_profile_table *profile)
00506 {
00507    struct dlg_cell *dlg;
00508    struct dlg_profile_link *linker;
00509    struct dlg_profile_link *linker_prev;
00510    struct dlg_entry *d_entry;
00511 
00512    /* get current dialog */
00513    dlg = get_current_dialog(msg);
00514 
00515    if (dlg==NULL || route_type==REQUEST_ROUTE) {
00516       LM_CRIT("BUG - dialog NULL or del_profile used in request route\n");
00517       return -1;
00518    }
00519 
00520    /* check the dialog linkers */
00521    d_entry = &d_table->entries[dlg->h_entry];
00522    dlg_lock( d_table, d_entry);
00523    linker = dlg->profile_links;
00524    linker_prev = NULL;
00525    for( ; linker ; linker_prev=linker,linker=linker->next) {
00526       if (linker->profile==profile) {
00527          if (profile->has_value==0) {
00528             goto found;
00529          } else if (value && value->len==linker->hash_linker.value.len &&
00530          memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
00531             goto found;
00532          }
00533          /* allow further search - maybe the dialog is inserted twice in
00534           * the same profile, but with different values -bogdan
00535           */
00536       }
00537    }
00538    dlg_unlock( d_table, d_entry);
00539    return -1;
00540 
00541 found:
00542    /* table still locked */
00543    /* remove the linker element from dialog */
00544    if (linker_prev==NULL) {
00545       dlg->profile_links = linker->next;
00546    } else {
00547       linker_prev->next = linker->next;
00548    }
00549    linker->next = NULL;
00550    dlg_unlock( d_table, d_entry);
00551    /* remove linker from profile table and free it */
00552    destroy_linkers(linker);
00553    return 1;
00554 }
00555 
00556 
00557 /*!
00558  * \brief Check if a dialog belongs to a profile
00559  * \param msg SIP message
00560  * \param profile dialog profile table
00561  * \param value value
00562  * \return 1 on success, -1 on failure
00563  */
00564 int is_dlg_in_profile(struct sip_msg *msg, struct dlg_profile_table *profile,
00565       str *value)
00566 {
00567    struct dlg_cell *dlg;
00568    struct dlg_profile_link *linker;
00569    struct dlg_entry *d_entry;
00570 
00571    /* get current dialog */
00572    dlg = get_current_dialog(msg);
00573 
00574    if (dlg==NULL)
00575       return -1;
00576 
00577    /* check the dialog linkers */
00578    d_entry = &d_table->entries[dlg->h_entry];
00579    dlg_lock( d_table, d_entry);
00580    for( linker=dlg->profile_links ; linker ; linker=linker->next) {
00581       if (linker->profile==profile) {
00582          if (profile->has_value==0) {
00583             dlg_unlock( d_table, d_entry);
00584             return 1;
00585          } else if (value && value->len==linker->hash_linker.value.len &&
00586          memcmp(value->s,linker->hash_linker.value.s,value->len)==0){
00587             dlg_unlock( d_table, d_entry);
00588             return 1;
00589          }
00590          /* allow further search - maybe the dialog is inserted twice in
00591           * the same profile, but with different values -bogdan
00592           */
00593       }
00594    }
00595    dlg_unlock( d_table, d_entry);
00596    return -1;
00597 }
00598 
00599 
00600 /*!
00601  * \brief Get the size of a profile
00602  * \param profile evaluated profile
00603  * \param value value
00604  * \return the profile size
00605  */
00606 unsigned int get_profile_size(struct dlg_profile_table *profile, str *value)
00607 {
00608    unsigned int n,i;
00609    struct dlg_profile_hash *ph;
00610 
00611    if (profile->has_value==0 || value==NULL) {
00612       /* iterate through the hash and count all records */
00613       get_lock( &profile->lock );
00614       for( i=0,n=0 ; i<profile->size ; i++ )
00615          n += profile->entries[i].content;
00616       release_lock( &profile->lock );
00617       return n;
00618    } else {
00619       /* iterate through the hash entry and count only matching */
00620       /* calculate the hash position */
00621       i = calc_hash_profile( value, NULL, profile);
00622       n = 0;
00623       get_lock( &profile->lock );
00624       ph = profile->entries[i].first;
00625       if(ph) {
00626          do {
00627             /* compare */
00628             if ( value->len==ph->value.len &&
00629             memcmp(value->s,ph->value.s,value->len)==0 ) {
00630                /* found */
00631                n++;
00632             }
00633             /* next */
00634             ph=ph->next;
00635          }while( ph!=profile->entries[i].first );
00636       }
00637       release_lock( &profile->lock );
00638       return n;
00639    }
00640 }
00641 
00642 /****************************** MI commands *********************************/
00643 
00644 /*!
00645  * \brief Output a profile via MI interface
00646  * \param cmd_tree MI command tree
00647  * \param param unused
00648  * \return MI root output on success, NULL on failure
00649  */
00650 struct mi_root * mi_get_profile(struct mi_root *cmd_tree, void *param)
00651 {
00652    struct mi_node* node;
00653    struct mi_root* rpl_tree= NULL;
00654    struct mi_node* rpl = NULL;
00655    struct mi_attr* attr;
00656    struct dlg_profile_table *profile;
00657    str *value;
00658    str *profile_name;
00659    unsigned int size;
00660    int len;
00661    char *p;
00662 
00663    node = cmd_tree->node.kids;
00664    if (node==NULL || !node->value.s || !node->value.len)
00665       return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00666    profile_name = &node->value;
00667 
00668    if (node->next) {
00669       node = node->next;
00670       if (!node->value.s || !node->value.len)
00671          return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
00672       if (node->next)
00673          return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00674       value = &node->value;
00675    } else {
00676       value = NULL;
00677    }
00678 
00679    /* search for the profile */
00680    profile = search_dlg_profile( profile_name );
00681    if (profile==NULL)
00682       return init_mi_tree( 404, MI_SSTR("Profile not found"));
00683 
00684    size = get_profile_size( profile , value );
00685 
00686    rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00687    if (rpl_tree==0)
00688       return 0;
00689    rpl = &rpl_tree->node;
00690 
00691    node = add_mi_node_child(rpl, MI_DUP_VALUE, "profile", 7, NULL, 0);
00692    if (node==0) {
00693       free_mi_tree(rpl_tree);
00694       return NULL;
00695    }
00696 
00697    attr = add_mi_attr(node, MI_DUP_VALUE, "name", 4, 
00698       profile->name.s, profile->name.len);
00699    if(attr == NULL) {
00700       goto error;
00701    }
00702 
00703    if (value) {
00704       attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, value->s, value->len);
00705    } else {
00706       attr = add_mi_attr(node, MI_DUP_VALUE, "value", 5, NULL, 0);
00707    }
00708    if(attr == NULL) {
00709       goto error;
00710    }
00711 
00712    p= int2str((unsigned long)size, &len);
00713    attr = add_mi_attr(node, MI_DUP_VALUE, "count", 5, p, len);
00714    if(attr == NULL) {
00715       goto error;
00716    }
00717 
00718    return rpl_tree;
00719 error:
00720    free_mi_tree(rpl_tree);
00721    return NULL;
00722 }
00723 
00724 
00725 /*!
00726  * \brief List the profiles via MI interface
00727  * \param cmd_tree MI command tree
00728  * \param param unused
00729  * \return MI root output on success, NULL on failure
00730  */
00731 struct mi_root * mi_profile_list(struct mi_root *cmd_tree, void *param )
00732 {
00733    struct mi_node* node;
00734    struct mi_root* rpl_tree= NULL;
00735    struct mi_node* rpl = NULL;
00736    struct dlg_profile_table *profile;
00737    struct dlg_profile_hash *ph;
00738    str *profile_name;
00739    str *value;
00740    unsigned int i;
00741 
00742    node = cmd_tree->node.kids;
00743    if (node==NULL || !node->value.s || !node->value.len)
00744       return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00745    profile_name = &node->value;
00746 
00747    if (node->next) {
00748       node = node->next;
00749       if (!node->value.s || !node->value.len)
00750          return init_mi_tree( 400, MI_SSTR(MI_BAD_PARM));
00751       if (node->next)
00752          return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));
00753       value = &node->value;
00754    } else {
00755       value = NULL;
00756    }
00757 
00758    /* search for the profile */
00759    profile = search_dlg_profile( profile_name );
00760    if (profile==NULL)
00761       return init_mi_tree( 404, MI_SSTR("Profile not found"));
00762 
00763    rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
00764    if (rpl_tree==0)
00765       return 0;
00766    rpl = &rpl_tree->node;
00767 
00768    /* go through the hash and print the dialogs */
00769    if (profile->has_value==0 || value==NULL) {
00770       /* no value */
00771       get_lock( &profile->lock );
00772       for ( i=0 ; i< profile->size ; i++ ) {
00773          ph = profile->entries[i].first;
00774          if(ph) {
00775             do {
00776                /* print dialog */
00777                if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 )
00778                   goto error;
00779                /* next */
00780                ph=ph->next;
00781             }while( ph!=profile->entries[i].first );
00782          }
00783          release_lock( &profile->lock );
00784       }
00785    } else {
00786       /* check for value also */
00787       get_lock( &profile->lock );
00788       for ( i=0 ; i< profile->size ; i++ ) {
00789          ph = profile->entries[i].first;
00790          if(ph) {
00791             do {
00792                if ( value->len==ph->value.len &&
00793                memcmp(value->s,ph->value.s,value->len)==0 ) {
00794                   /* print dialog */
00795                   if ( mi_print_dlg( rpl, ph->dlg, 0)!=0 )
00796                      goto error;
00797                }
00798                /* next */
00799                ph=ph->next;
00800             }while( ph!=profile->entries[i].first );
00801          }
00802          release_lock( &profile->lock );
00803       }
00804    }
00805 
00806    return rpl_tree;
00807 error:
00808    free_mi_tree(rpl_tree);
00809    return NULL;
00810 }

Generated on Tue May 22 16:00:27 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6