t_hooks.c

Go to the documentation of this file.
00001 /*
00002  * $Id: t_hooks.c 5376 2008-12-17 19:07:14Z osas $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
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  *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00025  *  2003-12-04  global callbacks moved into transaction callbacks;
00026  *              multiple events per callback added; single list per
00027  *              transaction for all its callbacks (bogdan)
00028  *  2004-08-23  user avp(attribute value pair) added -> making avp list
00029  *              available in callbacks (bogdan)
00030  */
00031 
00032 /*! \file
00033  * \brief TM :: ???
00034  *
00035  * \ingroup tm
00036  * - Module: \ref tm
00037  */
00038 
00039 #include "stdlib.h"
00040 #include "../../dprint.h"
00041 #include "../../error.h"
00042 #include "../../mem/mem.h"
00043 #include "../../usr_avp.h"
00044 #include "t_hooks.h"
00045 #include "t_lookup.h"
00046 #include "t_funcs.h"
00047 
00048 
00049 struct tmcb_head_list* req_in_tmcb_hl = 0;
00050 
00051 struct tmcb_head_list tmcb_pending_hl = {0,0};
00052 unsigned int tmcb_pending_id = -1;
00053 
00054 
00055 void empty_tmcb_list(struct tmcb_head_list *head)
00056 {
00057    struct tm_callback *cbp, *cbp_tmp;
00058 
00059    for( cbp=head->first; cbp ; ) {
00060       cbp_tmp = cbp;
00061       cbp = cbp->next;
00062       if (cbp_tmp->release)
00063          cbp_tmp->release(cbp_tmp->param);
00064       shm_free( cbp_tmp );
00065    }
00066    head->first = 0 ;
00067    head->reg_types = 0;
00068 }
00069 
00070 
00071 int init_tmcb_lists(void)
00072 {
00073    req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
00074       ( sizeof(struct tmcb_head_list) );
00075    if (req_in_tmcb_hl==0) {
00076       LM_CRIT("no more shared memory\n");
00077       return -1;
00078    }
00079    req_in_tmcb_hl->first = 0;
00080    req_in_tmcb_hl->reg_types = 0;
00081    return 1;
00082 }
00083 
00084 
00085 void destroy_tmcb_lists(void)
00086 {
00087    if (!req_in_tmcb_hl)
00088       return;
00089 
00090    empty_tmcb_list(req_in_tmcb_hl);
00091 
00092    shm_free(req_in_tmcb_hl);
00093 }
00094 
00095 /*!
00096  * \brief Inserts a callback into the a callback list
00097  * \param cb_list callback list
00098  * \param types callback type
00099  * \param f transaction callback
00100  * \param param callback parameter
00101  */
00102 int insert_tmcb(struct tmcb_head_list *cb_list, int types,
00103             transaction_cb f, void *param, release_tmcb_param release_func )
00104 {
00105    struct tm_callback *cbp;
00106 
00107    /* build a new callback structure */
00108    if (!(cbp=shm_malloc( sizeof( struct tm_callback)))) {
00109       LM_ERR("no more shared memory\n");
00110       return E_OUT_OF_MEM;
00111    }
00112 
00113    /* link it into the proper place... */
00114    cbp->next = cb_list->first;
00115    cb_list->first = cbp;
00116    cb_list->reg_types |= types;
00117    /* ... and fill it up */
00118    cbp->callback = f;
00119    cbp->param = param;
00120    cbp->release = release_func;
00121    cbp->types = types;
00122    if (cbp->next)
00123       cbp->id = cbp->next->id+1;
00124    else
00125       cbp->id = 0;
00126 
00127    return 1;
00128 }
00129 
00130 
00131 
00132 /*!
00133  * \brief Register a callback function for several types of events
00134  *
00135  * Register a callback function 'f' for 'types' mask of events. This
00136  * will be called back whenever one of the events occurs in transaction module
00137  * (global or per transaction, depending of event type).
00138  * \param p_msg SIP message
00139  * \param t transaction
00140  * \param types
00141  * \param f callback
00142  * \param param callback parameter
00143  * \param release_func release function for the callback parameter
00144  * \return negative result on error, the return code from insert_tmcb on success
00145  */
00146 int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types, transaction_cb f, void *param, release_tmcb_param release_func )
00147 {
00148    struct tmcb_head_list *cb_list;
00149 
00150    /* are the callback types valid?... */
00151    if ( types<0 || types>TMCB_MAX ) {
00152       LM_CRIT("invalid callback types: mask=%d\n",
00153          types);
00154       return E_BUG;
00155    }
00156    /* we don't register null functions */
00157    if (f==0) {
00158       LM_CRIT("null callback function\n");
00159       return E_BUG;
00160    }
00161 
00162    if (types&TMCB_REQUEST_IN) {
00163       if (types!=TMCB_REQUEST_IN) {
00164          LM_CRIT("callback type TMCB_REQUEST_IN "
00165             "can't be register along with types\n");
00166          return E_BUG;
00167       }
00168       if (req_in_tmcb_hl==0) {
00169          LM_ERR("callback type TMCB_REQUEST_IN "
00170             "registration attempt before TM module initialization\n");
00171          return E_CFG;
00172       }
00173       cb_list = req_in_tmcb_hl;
00174    } else {
00175       if (!t) {
00176          if (!p_msg) {
00177             LM_CRIT("no sip_msg, nor transaction given\n");
00178             return E_BUG;
00179          }
00180          /* look for the transaction */
00181          t = get_t();
00182          if ( t!=NULL && t!=T_UNDEFINED ){
00183             cb_list = &(t->tmcb_hl);
00184          } else {
00185             /* no transaction found -> link it to waitting list */
00186             if (p_msg->id!=tmcb_pending_id) {
00187                empty_tmcb_list(&tmcb_pending_hl);
00188                tmcb_pending_id = p_msg->id;
00189             }
00190             cb_list = &(tmcb_pending_hl);
00191          }
00192       } else {
00193          cb_list = &(t->tmcb_hl);
00194       }
00195    }
00196 
00197    return insert_tmcb( cb_list, types, f, param, release_func );
00198 }
00199 
00200 
00201 static struct tmcb_params params = {0,0,0,0,0,0};
00202 
00203 /*!
00204  * \brief Set extra parameter for tm callback
00205  */
00206 void set_extra_tmcb_params(void *extra1, void *extra2)
00207 {
00208    params.extra1 = extra1;
00209    params.extra2 = extra2;
00210 }
00211 
00212 /*!
00213  * \brief Run all transaction callbacks for an event type
00214  * \param type callback type
00215  * \param trans transaction
00216  * \param req SIP request
00217  * \param rpl SIP reply
00218  * \param code callback code
00219  */
00220 void run_trans_callbacks( int type , struct cell *trans,
00221                   struct sip_msg *req, struct sip_msg *rpl, int code )
00222 {
00223    struct tm_callback *cbp;
00224    struct usr_avp **backup;
00225    struct cell *trans_backup = get_t();
00226 
00227    params.req = req;
00228    params.rpl = rpl;
00229    params.code = code;
00230 
00231    if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==0 )
00232       return;
00233 
00234    backup = set_avp_list( &trans->user_avps );
00235    for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
00236       if ( (cbp->types)&type ) {
00237          LM_DBG("trans=%p, callback type %d, id %d entered\n",
00238             trans, type, cbp->id );
00239          params.param = &(cbp->param);
00240          cbp->callback( trans, type, &params );
00241       }
00242    }
00243    /* SHM message cleanup */
00244    if (trans->uas.request && trans->uas.request->msg_flags&FL_SHM_CLONE)
00245       clean_msg_clone( trans->uas.request, trans->uas.request, trans->uas.end_request);
00246    /* env cleanup */
00247    set_avp_list( backup );
00248    params.extra1 = params.extra2 = 0;
00249    set_t(trans_backup);
00250 }
00251 
00252 
00253 /*! \brief run all REQUEST_IN callbacks */
00254 void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
00255 {
00256    struct tm_callback    *cbp;
00257    struct usr_avp **backup;
00258    struct cell *trans_backup = get_t();
00259 
00260    params.req = req;
00261    params.rpl = 0;
00262    params.code = code;
00263 
00264    if (req_in_tmcb_hl->first==0)
00265       return;
00266 
00267    backup = set_avp_list( &trans->user_avps );
00268    for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
00269       LM_DBG("trans=%p, callback type %d, id %d entered\n",
00270          trans, cbp->types, cbp->id );
00271       params.param = &(cbp->param);
00272       cbp->callback( trans, cbp->types, &params );
00273    }
00274    set_avp_list( backup );
00275    params.extra1 = params.extra2 = 0;
00276    set_t(trans_backup);
00277 }
00278 

Generated on Thu May 24 20:00:32 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6