- global callbacks replaced by callbacks per transaction
authorBogdan-Andrei Iancu <bogdan@voice-system.ro>
Fri, 5 Dec 2003 14:29:12 +0000 (14:29 +0000)
committerBogdan-Andrei Iancu <bogdan@voice-system.ro>
Fri, 5 Dec 2003 14:29:12 +0000 (14:29 +0000)
- per type callback list merged into a single one
- TMCB_ON_FAILURE callback type addded
- completion callback used by t_uac merged into transaction callbacks as
  TMCB_LOCAL_COMPLETED

14 files changed:
modules/tm/h_table.c
modules/tm/h_table.h
modules/tm/t_funcs.c
modules/tm/t_fwd.c
modules/tm/t_hooks.c
modules/tm/t_hooks.h
modules/tm/t_lookup.c
modules/tm/t_reply.c
modules/tm/t_reply.h
modules/tm/tm.c
modules/tm/tm_load.c
modules/tm/tm_load.h
modules/tm/uac.c
modules/tm/uac_fifo.c

index 944a092..73afd2b 100644 (file)
@@ -34,6 +34,8 @@
  * 2003-04-04  bug_fix: REQ_IN callback not called for local 
  *             UAC transactions (jiri)
  * 2003-09-12  timer_link->tg will be set only if EXTRA_DEBUG (andrei)
+ * 2003-12-04  global callbacks replaceed with callbacks per transaction;
+ *             completion callback merged into them as LOCAL_COMPETED (bogdan)
  */
 
 #include "defs.h"
@@ -106,6 +108,7 @@ void free_cell( struct cell* dead_cell )
        int i;
        struct sip_msg *rpl;
        struct totag_elem *tt, *foo;
+       struct tm_callback *cbs, *cbs_tmp;
 
        release_cell_lock( dead_cell );
        shm_lock();
@@ -116,8 +119,12 @@ void free_cell( struct cell* dead_cell )
        if ( dead_cell->uas.response.buffer )
                shm_free_unsafe( dead_cell->uas.response.buffer );
 
-       /* completion callback */
-       if (dead_cell->cbp) shm_free_unsafe(dead_cell->cbp);
+       /* callbacks */
+       for( cbs=dead_cell->tmcb_hl.first ; cbs ; ) {
+               cbs_tmp = cbs;
+               cbs = cbs->next;
+               shm_free_unsafe( cbs_tmp );
+       }
 
        /* UA Clients */
        for ( i =0 ; i<dead_cell->nr_of_outgoings;  i++ )
@@ -183,15 +190,10 @@ struct cell*  build_cell( struct sip_msg* p_msg )
        new_cell->uas.response.retr_timer.payload = &(new_cell->uas.response);
        new_cell->uas.response.my_T=new_cell;
 
-       /* bogdan - debug */
-       /*fprintf(stderr,"before clone VIA |%.*s|\n",via_len(p_msg->via1),
-               via_s(p_msg->via1,p_msg));*/
-
        /* enter callback, which may potentially want to parse some stuff,
-          before the request is shmem-ized
-       */ 
-    if (p_msg) callback_event(TMCB_REQUEST_IN, new_cell, p_msg,
-            p_msg->REQ_METHOD );
+        * before the request is shmem-ized */
+       if ( p_msg && has_reqin_tmcbs() )
+               run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
 
        if (p_msg) {
                new_cell->uas.request = sip_msg_cloner(p_msg);
index f865cb6..5792074 100644 (file)
@@ -29,6 +29,8 @@
  * 2003-03-16  removed _TOTAG (jiri)
  * 2003-03-06  we keep a list of 200/INV to-tags now (jiri)
  * 2003-03-01  kr set through a function now (jiri)
+ * 2003-12-04  callbacks per transaction added; completion callback
+ *             merge into them as LOCAL_COMPETED (bogdan)
  */
 
 #include "defs.h"
@@ -174,21 +176,15 @@ typedef struct cell
           with proxied transactions to inbound request */
        str from, callid, cseq_n, to;
        /* a short-cut for remember whether this transaction needs
-          INVITE-special handling (e.g., CANCEL, ACK, FR...)
-       */
+          INVITE-special handling (e.g., CANCEL, ACK, FR...)  */
        short is_invite;
        /* method shortcut -- for local transactions, pointer to
           outbound buffer, for proxies transactions pointer to
-          original message; needed for reply matching
-       */
+          original message; needed for reply matching */
        str method;
 
-       /* callback and parameter on completion of local transactions */
-       transaction_cb *completion_cb;
-       /* the parameter stores a pointer to shmem -- it will be released
-          during freeing transaction too
-       */
-       void *cbp;
+       /* head of callback list */
+       struct tmcb_head_list tmcb_hl;
 
        /* how many processes are currently processing this transaction ;
           note that only processes working on a request/reply belonging
index ed66cf7..9959051 100644 (file)
@@ -110,6 +110,8 @@ void tm_shutdown()
        free_timer_table();
        DBG("DEBUG: tm_shutdown : removing semaphores\n");
        lock_cleanup();
+       DBG("DEBUG: tm_shutdown : destroing tmcb lists\n");
+       destroy_tmcb_lists();
        free_tm_stats();
        DBG("DEBUG: tm_shutdown : done\n");
 }
index 6cea391..e6c942b 100644 (file)
@@ -39,6 +39,8 @@
  *  2003-03-30  we now watch downstream delivery and if it fails, send an
  *              error message upstream (jiri)
  *  2003-04-14  use protocol from uri (jiri)
+ *  2003-12-04  global TM callbacks switched to per transaction callbacks
+ *              (bogdan)
  */
 
 #include "defs.h"
@@ -83,8 +85,8 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req,
        /* ... update uri ... */
        i_req->new_uri=*uri;
 
-       /* ... give apps a chance to change things ... */
-       callback_event( TMCB_REQUEST_FWDED, t, i_req, -i_req->REQ_METHOD);
+       /* run the specific callbacks for this transaction */
+       run_trans_callbacks( TMCB_REQUEST_FWDED , t, i_req, 0, -i_req->REQ_METHOD);
 
        /* ... and build it now */
        buf=build_req_buf_from_sip_req( i_req, len, send_sock, proto );
index 2d1cb31..d006f52 100644 (file)
@@ -28,6 +28,9 @@
  * History:
  * --------
  *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
+ *  2003-12-04  global callbacks moved into transaction callbacks;
+ *              multiple events per callback added; single list per
+ *              transaction for all its callbacks (bogdan)
  */
 
 #include "defs.h"
 #include "../../error.h"
 #include "../../mem/mem.h"
 #include "t_hooks.h"
+#include "t_lookup.h"
+#include "t_funcs.h"
 
-/* strange things happen if callback_array is static on openbsd */
-struct tm_callback_s* callback_array[ TMCB_END ] = { 0, 0 } ;
-static int callback_id=0;
 
-/* register a callback function 'f' of type 'cbt'; will be called
-   back whenever the event 'cbt' occurs in transaction module
-*/
-int register_tmcb( tmcb_type cbt, transaction_cb f, void *param )
+struct tmcb_head_list* req_in_tmcb_hl = 0;
+
+
+
+int init_tmcb_lists()
+{
+       req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
+               ( sizeof(struct tmcb_head_list) );
+       if (req_in_tmcb_hl==0) {
+               LOG(L_CRIT,"ERROR:tm:init_tmcb_lists: nomore shared mem\n");
+               return -1;
+       }
+       req_in_tmcb_hl->first = 0;
+       req_in_tmcb_hl->reg_types = 0;
+       return 1;
+}
+
+
+void destroy_tmcb_lists()
 {
-       struct tm_callback_s *cbs;
+       struct tm_callback *cbp, *cbp_tmp;
 
-       if (cbt<0 || cbt>=TMCB_END ) {
-               LOG(L_ERR, "ERROR: register_tmcb: invalid callback type: %d\n",
-                       cbt );
-               return E_BUG;
+       if (!req_in_tmcb_hl)
+               return;
+
+       for( cbp=req_in_tmcb_hl->first; cbp ; ) {
+               cbp_tmp = cbp;
+               cbp = cbp->next;
+               if (cbp->param) shm_free( cbp->param );
+               shm_free( cbp_tmp );
        }
 
-       if (!(cbs=pkg_malloc( sizeof( struct tm_callback_s)))) {
-               LOG(L_ERR, "ERROR: register_tmcb: out of mem\n");
+       shm_free(req_in_tmcb_hl);
+}
+
+
+inline int insert_tmcb(struct tmcb_head_list *cb_list, int types,
+                                                                       transaction_cb f, void *param )
+{
+       struct tm_callback *cbp;
+
+       /* build a new callback structure */
+       if (!(cbp=shm_malloc( sizeof( struct tm_callback)))) {
+               LOG(L_ERR, "ERROR:tm:register_tmcb: out of shm. mem\n");
                return E_OUT_OF_MEM;
        }
 
-       callback_id++;
-       cbs->id=callback_id;
-       cbs->callback=f;
-       cbs->next=callback_array[ cbt ];
-       cbs->param=param;
-       callback_array[ cbt ]=cbs;
+       /* link it into the proper place... */
+       cbp->next = cb_list->first;
+       cb_list->first = cbp;
+       cb_list->reg_types |= types;
+       /* ... and fill it up */
+       cbp->callback = f;
+       cbp->param = param;
+       cbp->types = types;
+       if (cbp->next)
+               cbp->id = cbp->next->id+1;
+       else
+               cbp->id = 0;
+
+       return 1;
+}
+
+
+
+/* register a callback function 'f' for 'types' mask of events;
+ * will be called back whenever one of the events occurs in transaction module
+ * (global or per transacation, depinding of event type)
+*/
+int register_tmcb( struct sip_msg* p_msg, int types, transaction_cb f,
+                                                                                                                               void *param )
+{
+       struct cell* t;
+       struct tmcb_head_list *cb_list;
+
+       /* are the callback types valid?... */
+       if ( types<0 || types>=TMCB_MAX ) {
+               LOG(L_CRIT, "BUG:tm:register_tmcb: invalid callback types: mask=%d\n",
+                       types);
+               return E_BUG;
+       }
+       if (types&TMCB_REQUEST_IN) {
+               if (types!=TMCB_REQUEST_IN) {
+                       LOG(L_CRIT, "BUG:tm:register_tmcb: callback type TMCB_REQUEST_IN "
+                               "can't be register along with types\n");
+                       return E_BUG;
+               }
+               cb_list = req_in_tmcb_hl;
+       } else {
+               /* look for the transaction */
+               if ( t_check(p_msg,0)!=1 ){
+                       LOG(L_CRIT,"BUG:tm:register_tmcb: no transaction found\n");
+                       return E_BUG;
+               }
+               if ( (t=get_t())==0 ) {
+                       LOG(L_CRIT,"BUG:tm:register_tmcb: transaction found is NULL\n");
+                       return E_BUG;
+               }
+               cb_list = &(t->tmcb_hl);
+       }
+
+       return insert_tmcb( cb_list, types, f, param );
+}
 
-       return callback_id;
+
+void run_trans_callbacks( int type , struct cell *trans,
+                                               struct sip_msg *req, struct sip_msg *rpl, int code )
+{
+       static struct tmcb_params params = {0,0,0,0};
+       struct tm_callback    *cbp;
+
+       params.req = req;
+       params.rpl = rpl;
+       params.code = code;
+
+       for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
+               if ( (cbp->types)&type ) {
+                       DBG("DBG: trans=%p, callback type %d, id %d entered\n",
+                               trans, type, cbp->id );
+                       params.param = cbp->param;
+                       cbp->callback( trans, type, &params );
+               }
+       }
 }
 
-void callback_event( tmcb_type cbt , struct cell *trans,
-       struct sip_msg *msg, int code )
+
+
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
 {
-       struct tm_callback_s *cbs;
+       static struct tmcb_params params = {0,0,0,0};
+       struct tm_callback    *cbp;
 
-       for (cbs=callback_array[ cbt ]; cbs; cbs=cbs->next)  {
-               DBG("DBG: callback type %d, id %d entered\n", cbt, cbs->id );
-               cbs->callback( trans, msg, code, cbs->param );
+       params.req = req;
+       params.code = code;
+
+       for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
+               DBG("DBG: trans=%p, callback type %d, id %d entered\n",
+                       trans, cbp->types, cbp->id );
+               params.param = cbp->param;
+               cbp->callback( trans, cbp->types, &params );
        }
 }
+
index 4149211..fd5037b 100644 (file)
  *
  * History:
  * --------
- * 2003-03-16 backwards-compatibility callback names introduced (jiri)
- * 2003-03-06 old callbacks renamed, new one introduced (jiri)
+ * 2003-03-16 : backwards-compatibility callback names introduced (jiri)
+ * 2003-03-06 : old callbacks renamed, new one introduced (jiri)
+ * 2003-12-04 : global callbacks moved into transaction callbacks;
+ *              multiple events per callback added; single list per
+ *              transaction for all its callbacks (bogdan)
  */
 
 
 
 #include "defs.h"
 
-
 struct sip_msg;
 struct cell;
 
-/* backwards compatibility hooks */
-#define TMCB_REPLY TMCB_RESPONSE_OUT
-#define TMCB_E2EACK TMCB_E2EACK_IN
-#define TMCB_REPLY_IN TMCB_RESPONSE_IN
-#define TMCB_REQUEST_OUT TMCB_REQUEST_FWDED
-#define TMCB_ON_NEGATIVE TMCB_ON_FAILURE
-
-typedef enum { 
-               /* input events */
-               TMCB_RESPONSE_IN=1, TMCB_REQUEST_IN, TMCB_E2EACK_IN, 
-               /* routing decisions in progress */
-               TMCB_REQUEST_FWDED, TMCB_RESPONSE_FWDED, TMCB_ON_FAILURE,
-               /* completion events */
-               TMCB_RESPONSE_OUT, TMCB_LOCAL_COMPLETED, 
-               TMCB_END } tmcb_type;
+
+#define TMCB_REQUEST_IN       (1<<0)
+#define TMCB_RESPONSE_IN      (1<<1)
+#define TMCB_E2EACK_IN        (1<<2)
+#define TMCB_REQUEST_FWDED    (1<<3)
+#define TMCB_RESPONSE_FWDED   (1<<4)
+#define TMCB_ON_FAILURE_RO    (1<<5)
+#define TMCB_ON_FAILURE       (1<<6)
+#define TMCB_RESPONSE_OUT     (1<<7)
+#define TMCB_LOCAL_COMPLETED  (1<<8)
+#define TMCB_MAX              ((1<<9)-1)
 
 /* 
  *  Caution: most of the callbacks work with shmem-ized messages
@@ -65,6 +63,13 @@ typedef enum {
  *  is a non-dereferencable pointer indicating that no message
  *  was received and a timer hit instead.
  *
+ *  All callbacks excepting the TMCB_REQUEST_IN are associates to a
+ *  transaction. It means they will be run only when the event will hint
+ *  the transaction the callbacks were register for.
+ *  TMCB_REQUEST_IN is a global callback - it means it will be run for
+ *  all transactions.
+ *
+ *
  *  Callback description:
  *  ---------------------
  *
@@ -98,6 +103,11 @@ typedef enum {
  *    drops state silently, doesn't use callbacks and expects the
  *    transaction to complete statelessly.
  *
+ *  TMCB_ON_FAILURE_RO -- called on receipt of a reply or timer;
+ *  it means all branches completed with a failure; the callback 
+ *  function MUST not change anything in the transaction (READONLY)
+ *  that's a chance for doing ACC or stuff like this
+ *
  *  TMCB_ON_FAILURE -- called on receipt of a reply or timer;
  *  it means all branches completed with a failure; that's 
  *  a chance for example to add new transaction branches
@@ -139,36 +149,73 @@ typedef enum {
  *  TMCB_LOCAL COMPLETED -- final reply for localy initiated
  *  transaction arrived. Message may be FAKED_REPLY.
  *
- *  TMCB_END   - just a bumper
-
-       see the 'acc' module for an example of callback usage
 
        note that callbacks MUST be installed before forking
-    (callback lists do not live in shmem and have no access
+       (callback lists do not live in shmem and have no access
        protection), i.e., at best from mod_init functions.
 
-       also, note: the callback param is currently not used;
-       if whoever wishes to use a callback parameter, use
-       trans->cbp
+       the callback's param MUST be in shared memory and will
+       NOT be freed by TM; you must do it yourself from the
+       callback function id necessary.
 */
 
-typedef void (transaction_cb) ( struct cell* t, struct sip_msg* msg, 
-       int code, void *param );
 
-struct tm_callback_s {
-       int id;
-       transaction_cb* callback;
-       struct tm_callback_s* next;
+/* pack structure with all params passed toa callback function */
+struct tmcb_params {
+       struct sip_msg* req;
+       struct sip_msg* rpl;
+       int code;
        void *param;
 };
 
+/* callback function prototype */
+typedef void (transaction_cb) (struct cell* t, int type, struct tmcb_params*);
+/* register callback function prototype */
+typedef int (*register_tmcb_f)(struct sip_msg* p_msg, int cb_types,
+               transaction_cb f, void *param);
+
+
+struct tm_callback {
+       int id;                      /* id of this callback - useless */
+       int types;                   /* types of events that trigger the callback*/
+       transaction_cb* callback;    /* callback function */
+       void *param;                 /* param to be passed to callback function */
+       struct tm_callback* next;
+};
+
+struct tmcb_head_list {
+       struct tm_callback *first;
+       int reg_types;
+};
+
+
+extern struct tmcb_head_list*  req_in_tmcb_hl;
+
+
+#define has_tran_tmcbs(_T_, _types_) \
+       ( ((_T_)->tmcb_hl.reg_types)|(_types_) )
+#define has_reqin_tmcbs() \
+       ( req_in_tmcb_hl->first!=0 )
+
+
+int init_tmcb_lists();
+
+void destroy_tmcb_lists();
+
+
+/* register a callback for several types of events */
+int register_tmcb( struct sip_msg* p_msg, int types, transaction_cb f,
+                                                                                                                               void *param );
 
-extern struct tm_callback_s* callback_array[ TMCB_END ];
+/* inserts a callback into the a callback list */
+int insert_tmcb(struct tmcb_head_list *cb_list, int types,
+                                                                       transaction_cb f, void *param );
 
-typedef int (*register_tmcb_f)(tmcb_type cbt, transaction_cb f, void *param);
+/* run all transaction callbacks for an event type */
+void run_trans_callbacks( int type , struct cell *trans,
+                                               struct sip_msg *req, struct sip_msg *rpl, int code );
 
-int register_tmcb( tmcb_type cbt, transaction_cb f, void *param );
-void callback_event( tmcb_type cbt, struct cell *trans,
-       struct sip_msg *msg, int code );
+/* run all REQUEST_IN callbacks */
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code );
 
 #endif
index c0d4ae5..187a3f6 100644 (file)
@@ -72,6 +72,8 @@
  * 2003-04-30  t_newtran clean up (jiri)
  * 2003-08-21  request lookups fixed to skip UAC transactions, 
  *             thanks Ed (jiri)
+ * 2003-12-04  global TM callbacks switched to per transaction callbacks
+ *             (bogdan)
  */
 
 
@@ -784,17 +786,19 @@ int t_reply_matching( struct sip_msg *p_msg , int *p_branch )
                 * retransmissions of multiple 200/INV or ACK/200s
                 */
                if (p_cell->is_invite && p_msg->REPLY_STATUS>=200 
-                               && p_msg->REPLY_STATUS<300 
-                               && ( (!p_cell->local && 
-                                       (callback_array[TMCB_RESPONSE_OUT]||
-                                               callback_array[TMCB_E2EACK_IN]))
-                                       || (p_cell->local && callback_array[TMCB_LOCAL_COMPLETED]) )) {
+               && p_msg->REPLY_STATUS<300 
+               && ( (!p_cell->local && 
+                               has_tran_tmcbs(p_cell,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) )
+                       || (p_cell->local && has_tran_tmcbs(p_cell,TMCB_LOCAL_COMPLETED))
+               )) {
                        if (parse_headers(p_msg, HDR_TO, 0)==-1) {
                                LOG(L_ERR, "ERROR: t_reply_matching: to parsing failed\n");
                        }
                }
-               if (!p_cell->local) 
-                       callback_event(TMCB_RESPONSE_IN, T, p_msg, p_msg->REPLY_STATUS);
+               if (!p_cell->local) {
+                       run_trans_callbacks( TMCB_RESPONSE_IN, T, T->uas.request, p_msg,
+                               p_msg->REPLY_STATUS);
+               }
                return 1;
        } /* for cycle */
 
@@ -1051,21 +1055,20 @@ int t_newtran( struct sip_msg* p_msg )
 
        if (lret==-2) { /* was it an e2e ACK ? if so, trigger a callback */
                /* no callbacks? complete quickly */
-               if (!callback_array[TMCB_E2EACK_IN]) {
+               if ( !has_tran_tmcbs(t_ack,TMCB_E2EACK_IN) ) {
                        UNLOCK_HASH(p_msg->hash_index);
                        return 1;
                } 
                REF_UNSAFE(t_ack);
                UNLOCK_HASH(p_msg->hash_index);
                /* we don't call from within REPLY_LOCK -- that introduces
-                  a race condition; however, it is so unlikely and the
-                  impact is so small (callback called multiple times of
-           multiple ACK/200s received in parallel), that we do not
-                   better waste time in locks
-                */
+                * a race condition; however, it is so unlikely and the
+                * impact is so small (callback called multiple times of
+                * multiple ACK/200s received in parallel), that we do not
+                * better waste time in locks  */
                if (unmatched_totag(t_ack, p_msg)) {
-                       callback_event( TMCB_E2EACK_IN, t_ack, p_msg, 
-                               p_msg->REQ_METHOD );
+                       run_trans_callbacks( TMCB_E2EACK_IN , t_ack, p_msg, 0,
+                               -p_msg->REQ_METHOD );
                }
                UNREF(t_ack);
                return 1;
index fd52c46..5b92e5a 100644 (file)
@@ -52,6 +52,8 @@
  *  2003-11-05  flag context updated from failure/reply handlers back
  *              to transaction context (jiri)
  *  2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags (bogdan)
+ *  2003-12-04  global TM callbacks switched to per transaction callbacks
+ *              (bogdan)
  */
 
 
@@ -102,6 +104,7 @@ static int goto_on_negative=0;
 static int goto_on_reply=0;
 
 
+
 /* we store the reply_route # in private memory which is
    then processed during t_relay; we cannot set this value
    before t_relay creates transaction context or after
@@ -309,11 +312,13 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
        if (code>=200) {
                if (trans->local) {
                        DBG("DEBUG: local transaction completed from _reply\n");
-                       callback_event( TMCB_LOCAL_COMPLETED, trans, FAKED_REPLY, code );
-                       if (trans->completion_cb) 
-                               trans->completion_cb( trans, FAKED_REPLY, code, trans->cbp);
+                       if ( has_tran_tmcbs(trans, TMCB_LOCAL_COMPLETED) )
+                               run_trans_callbacks( TMCB_LOCAL_COMPLETED, trans,
+                                       0, FAKED_REPLY, code);
                } else {
-                       callback_event( TMCB_RESPONSE_OUT, trans, FAKED_REPLY, code );
+                       if ( has_tran_tmcbs(trans, TMCB_RESPONSE_OUT) )
+                               run_trans_callbacks( TMCB_RESPONSE_OUT, trans,
+                                       trans->uas.request, FAKED_REPLY, code);
                }
 
                cleanup_uac_timers( trans );
@@ -380,45 +385,15 @@ static int _reply( struct cell *trans, struct sip_msg* p_msg,
 }
 
 
-/* create a temporary faked message environment in which a conserved
- * t->uas.request in shmem is partially duplicated to pkgmem
- * to allow pkg-based actions to use it; 
- *
- * if restore parameter is set, the environment is restored to the
- * original setting and return value is unsignificant (always 0); 
- * otherwise  a faked environment if created; if that fails,
- * false is returned
- */
-static int faked_env(struct sip_msg *fake, 
-                               struct cell *_t,
-                               struct sip_msg *shmem_msg,
-                               int _restore )
+/*if msg is set -> it will fake the env. vars conforming with the msg; if NULL
+ * the env. will be restore to original */
+static inline void faked_env( struct cell *t,struct sip_msg *msg)
 {
        static enum route_mode backup_mode;
        static struct cell *backup_t;
        static unsigned int backup_msgid;
 
-       if (_restore) goto restore;
-
-       /* 
-     on_negative_reply faked msg now copied from shmem msg (as opposed
-     to zero-ing) -- more "read-only" actions (exec in particular) will 
-     work from reply_route as they will see msg->from, etc.; caution, 
-     rw actions may append some pkg stuff to msg, which will possibly be 
-     never released (shmem is released in a single block)
-    */
-       memcpy( fake, shmem_msg, sizeof(struct sip_msg));
-
-       /* if we set msg_id to something different from current's message
-       id, the first t_fork will properly clean new branch URIs
-       */
-       fake->id=shmem_msg->id-1;
-       /* set items, which will be duped to pkg_mem, to zero, so that
-        * "restore" called on error does not free the original items */
-       fake->add_rm=0;
-       fake->body_lumps=0;
-       fake->new_uri.s=0; fake->new_uri.len=0; 
-
+       if (msg) {
        /* remember we are back in request processing, but process
         * a shmem-ed replica of the request; advertise it in rmode;
         * for example t_reply needs to know that
@@ -435,90 +410,109 @@ static int faked_env(struct sip_msg *fake,
        backup_t=get_t();
        backup_msgid=global_msg_id;
        /* fake transaction and message id */
-       global_msg_id=fake->id;
-       set_t(_t);
+               global_msg_id=msg->id;
+               set_t(t);
+       } else {
+               /* restore original environment */
+               set_t(backup_t);
+               global_msg_id=backup_msgid;
+               rmode=backup_mode;
+       }
+}
+
+
+
+/* return 1 if a failure_route processes */
+static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
+                                                                                                                                       int code)
+{
+       static struct sip_msg fake_req;
+       struct sip_msg *shmem_msg = t->uas.request;
+
+       /* failure_route for a local UAC? */
+       if (!shmem_msg) {
+               LOG(L_WARN, "Warning: run_failure_handlers: no UAC support\n");
+               return 0;
+       }
+
+       /* don't start faking anything if we don't have to */
+       if ( !has_tran_tmcbs( t, TMCB_ON_FAILURE) && !t->on_negative ) {
+               return 1;
+       }
 
-       /* environment is set up now, try to fake the message */
+       /* on_negative_reply faked msg now copied from shmem msg (as opposed
+        * to zero-ing) -- more "read-only" actions (exec in particular) will
+        * work from reply_route as they will see msg->from, etc.; caution,
+        * rw actions may append some pkg stuff to msg, which will possibly be
+        * never released (shmem is released in a single block) */
+       memcpy( &fake_req, shmem_msg, sizeof(struct sip_msg));
+
+       /* if we set msg_id to something different from current's message
+        * id, the first t_fork will properly clean new branch URIs */
+       fake_req.id=shmem_msg->id-1;
 
        /* new_uri can change -- make a private copy */
        if (shmem_msg->new_uri.s!=0 && shmem_msg->new_uri.len!=0) {
-               fake->new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1);
-               if (!fake->new_uri.s) {
-                       LOG(L_ERR, "ERROR: faked_env: no uri/pkg mem\n");
-                       goto restore;
+               fake_req.new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1);
+               if (!fake_req.new_uri.s) {
+                       LOG(L_ERR, "ERROR: run_failure_handlers: no uri/pkg mem\n");
+                       return 0;
                }
-               fake->new_uri.len=shmem_msg->new_uri.len;
-               memcpy( fake->new_uri.s, shmem_msg->new_uri.s, 
-                       fake->new_uri.len);
-               fake->new_uri.s[fake->new_uri.len]=0;
-       } 
+               fake_req.new_uri.len=shmem_msg->new_uri.len;
+               memcpy( fake_req.new_uri.s, shmem_msg->new_uri.s, 
+                       fake_req.new_uri.len);
+               fake_req.new_uri.s[fake_req.new_uri.len]=0;
+       }
 
        /* create a duplicated lump list to which actions can add
-        * new pkg items 
-        */
+        * new pkg items  */
        if (shmem_msg->add_rm) {
-               fake->add_rm=dup_lump_list(shmem_msg->add_rm);
-               if (!fake->add_rm) { /* non_emty->empty ... failure */
-                       LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n");
-                       goto restore;
+               fake_req.add_rm=dup_lump_list(shmem_msg->add_rm);
+               if (!fake_req.add_rm) { /* non_emty->empty ... failure */
+                       LOG(L_ERR, "ERROR: run_failure_handlers: lump dup failed\n");
+                       if (fake_req.new_uri.s) pkg_free(fake_req.new_uri.s);
+                       return 0;
                }
        }
 
+       /* same for the body lumps */
        if (shmem_msg->body_lumps) {
-               fake->body_lumps=dup_lump_list(shmem_msg->body_lumps);
-               if (!fake->body_lumps) { /* non_empty->empty ... failure */
-                       LOG(L_ERR, "ERROR: on_negative_reply: lump dup failed\n");
-                       goto restore;
+               fake_req.body_lumps=dup_lump_list(shmem_msg->body_lumps);
+               if (!fake_req.body_lumps) { /* non_empty->empty ... failure */
+                       LOG(L_ERR, "ERROR: on_negative_handlers: lump dup failed\n");
+                       free_duped_lump_list(fake_req.add_rm);
+                       if (fake_req.new_uri.s) pkg_free(fake_req.new_uri.s);
+                       return 0;
                }
        }
-       
-       /* success */
-       return 1;
-
-restore:
-       /* restore original environment and destroy faked message */
-       free_duped_lump_list(fake->add_rm);
-       free_duped_lump_list(fake->body_lumps);
-       if (fake->new_uri.s) pkg_free(fake->new_uri.s);
-       set_t(backup_t);
-       global_msg_id=backup_msgid;
-       rmode=backup_mode;
-       /* if failure handler changed flag, update transaction context */
-       shmem_msg->flags=fake->flags;
-       return 0;
-}
 
-/* return 1 if a failure_route processes */
-int failure_route(struct cell *t)
-{
-       struct sip_msg faked_msg;
-       struct sip_msg *orig_request;
-
-       /* don't do anything if we don't have to */
-       if (!t->on_negative) return 0;
-       orig_request=t->uas.request;
-       /* failure_route for a local UAC? */
-       if (!orig_request) {
-               LOG(L_WARN, "Warning: failure_route: no UAC support\n");
-               return 0;
-       }
+       /* fake also the env. conforming to the fake msg */
+       faked_env( t, &fake_req);
+       /* DONE with faking ;-) -> run the failure handlers */
 
-       /* if fake message creation failes, return error too */
-       if (!faked_env(&faked_msg, t, orig_request, 0 /* create fake */ )) {
-               LOG(L_ERR, "ERROR: on_negative_reply: faked_env failed\n");
-               return 0;
+       if ( has_tran_tmcbs( t, TMCB_ON_FAILURE) ) {
+               run_trans_callbacks( TMCB_ON_FAILURE, t, &fake_req, rpl, code);
        }
-
+       if (t->on_negative) {
        /* avoid recursion -- if failure_route forwards, and does not 
         * set next failure route, failure_route will not be rentered
         * on failure */
        t_on_negative(0);
        /* run a reply_route action if some was marked */
-       if (run_actions(failure_rlist[t->on_negative], &faked_msg)<0)
-               LOG(L_ERR, "ERROR: on_negative_reply: "
-                       "Error in do_action\n");
-       /* restore original environment */
-       faked_env(&faked_msg, 0, orig_request, 1 );
+               if (run_actions(failure_rlist[t->on_negative], &fake_req)<0)
+                       LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n");
+       }
+
+       /* restore original environment and free the fake msg */
+       faked_env( t, 0);
+       free_duped_lump_list(fake_req.add_rm);
+       free_duped_lump_list(fake_req.body_lumps);
+       fake_req.add_rm = fake_req.body_lumps = 0;
+       if (fake_req.new_uri.s) {
+               pkg_free(fake_req.new_uri.s);
+               fake_req.new_uri.s = 0;
+       }
+
        return 1;
 }
 
@@ -572,7 +566,6 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
        int branch , int *should_store, int *should_relay,
        branch_bm_t *cancel_bitmap, struct sip_msg *reply )
 {
-       
        int branch_cnt;
        int picked_branch;
        int picked_code;
@@ -630,15 +623,16 @@ static enum rps t_should_relay_response( struct cell *Trans , int new_code,
 
                /* no more pending branches -- try if that changes after
                   a callback; save banch count to be able to determine
-                  later if new branches were initiated
-               */
+                  later if new branches were initiated */
                branch_cnt=Trans->nr_of_outgoings;
-               callback_event( TMCB_ON_FAILURE, Trans, 
-                       picked_branch==branch?reply:Trans->uac[picked_branch].reply, 
-                       picked_code);
-               /* here, we create a faked environment, from which we
-                * return to request processing, if marked to do so */
-               failure_route(Trans);
+
+               /* run ON_FAILURE handlers ( route and callbacks) */
+               if ( has_tran_tmcbs( Trans, TMCB_ON_FAILURE_RO|TMCB_ON_FAILURE)
+               || Trans->on_negative ) {
+                       run_failure_handlers( Trans,
+                               picked_branch==branch?reply:Trans->uac[picked_branch].reply, 
+                               picked_code);
+               }
 
                /* look if the callback perhaps replied transaction; it also
                   covers the case in which a transaction is replied localy
@@ -849,7 +843,7 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 
 
        /* remember, what was sent upstream to know whether we are
-          forwarding a first final reply or not */
+        * forwarding a first final reply or not */
 
        /* *** store and relay message as needed *** */
        reply_status = t_should_relay_response(t, msg_status, branch, 
@@ -866,19 +860,19 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 
        uas_rb = & t->uas.response;
        if (relay >= 0 ) {
-
                /* initialize sockets for outbound reply */
                uas_rb->activ_type=msg_status;
                /* only messages known to be relayed immediately will be
-                  be called on; we do not evoke this callback on messages
-                  stored in shmem -- they are fixed and one cannot change them
-                  anyway 
-        */
-               if (msg_status<300 && branch==relay) {
-                       callback_event( TMCB_RESPONSE_FWDED, t, p_msg, msg_status );
+                * be called on; we do not evoke this callback on messages
+                * stored in shmem -- they are fixed and one cannot change them
+                * anyway */
+               if (msg_status<300 && branch==relay
+               && has_tran_tmcbs(t,TMCB_RESPONSE_FWDED) ) {
+                       run_trans_callbacks( TMCB_RESPONSE_FWDED, t, t->uas.request,
+                               p_msg, msg_status );
                }
                /* try bulding the outbound reply from either the current
-              or a stored message */
+                * or a stored message */
                relayed_msg = branch==relay ? p_msg :  t->uac[relay].reply;
                if (relayed_msg==FAKED_REPLY) {
                        tm_stats->replied_localy++;
@@ -942,9 +936,8 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
                t->relaied_reply_branch = relay;
 
                if (t->is_invite && relayed_msg!=FAKED_REPLY
-                               && relayed_code>=200 && relayed_code < 300
-                               && (callback_array[TMCB_RESPONSE_OUT] ||
-                                               callback_array[TMCB_E2EACK_IN]))  {
+               && relayed_code>=200 && relayed_code < 300
+               && has_tran_tmcbs( t, TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) ) {
                        totag_retr=update_totag_set(t, relayed_msg);
                }
        }; /* if relay ... */
@@ -956,8 +949,10 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
                SEND_PR_BUFFER( uas_rb, buf, res_len );
                DBG("DEBUG: reply relayed. buf=%p: %.9s..., shmem=%p: %.9s\n", 
                        buf, buf, uas_rb->buffer, uas_rb->buffer );
-               if (!totag_retr) 
-                               callback_event( TMCB_RESPONSE_OUT, t, relayed_msg, relayed_code );
+               if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) {
+                       run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request,
+                               relayed_msg, relayed_code);
+               }
                pkg_free( buf );
        }
 
@@ -1026,22 +1021,19 @@ enum rps local_reply( struct cell *t, struct sip_msg *p_msg, int branch,
                }
                t->uas.status = winning_code;
                update_reply_stats( winning_code );
-               if (t->is_invite && winning_msg!=FAKED_REPLY 
-                               && winning_code>=200 && winning_code <300
-                               && (callback_array[TMCB_RESPONSE_OUT] ||
-                                               callback_array[TMCB_E2EACK_IN]))  {
+               if (t->is_invite && winning_msg!=FAKED_REPLY
+               && winning_code>=200 && winning_code <300
+               && has_tran_tmcbs(t,TMCB_RESPONSE_OUT|TMCB_E2EACK_IN) )  {
                        totag_retr=update_totag_set(t, winning_msg);
                }
-               
        }
        UNLOCK_REPLIES(t);
        if (local_winner>=0 && winning_code>=200 ) {
                DBG("DEBUG: local transaction completed\n");
                if (!totag_retr) {
-                       callback_event( TMCB_LOCAL_COMPLETED, t, winning_msg, 
-                               winning_code );
-                       if (t->completion_cb) t->completion_cb( t, winning_msg, 
-                                               winning_code, t->cbp);
+                       if ( has_tran_tmcbs(t,TMCB_LOCAL_COMPLETED) )
+                               run_trans_callbacks( TMCB_LOCAL_COMPLETED, t, 0,
+                                       winning_msg, winning_code );
                }
        }
        return reply_status;
index 3d069a9..ecb548a 100644 (file)
@@ -141,6 +141,5 @@ void tm_init_tags();
 /* selects the branch for fwd-ing the reply */
 int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code);
 
-
 #endif
 
index ee7a7c9..d336c42 100644 (file)
@@ -452,12 +452,12 @@ static int mod_init(void)
                return -1;
        }
 
+       /* building the hash table*/
        if (!init_hash_table()) {
                LOG(L_ERR, "ERROR: mod_init: initializing hash_table failed\n");
                return -1;
        }
 
-
        /* init static hidden values */
        init_t();
 
@@ -480,20 +480,24 @@ static int mod_init(void)
                return -1;
        }
 
-       /* building the hash table*/
-
        if (uac_init()==-1) {
                LOG(L_ERR, "ERROR: mod_init: uac_init failed\n");
                return -1;
        }
+
+       if (init_tmcb_lists()!=1) {
+               LOG(L_CRIT, "ERROR:tm:mod_init: failed to init tmcb lists\n");
+               return -1;
+       }
+
+       tm_init_tags();
+
        /* register post-script clean-up function */
        register_script_cb( w_t_unref, POST_SCRIPT_CB, 
                        0 /* empty param */ );
        register_script_cb( script_init, PRE_SCRIPT_CB , 
                        0 /* empty param */ );
 
-       tm_init_tags();
-
        return 0;
 }
 
index 17cd45f..e2090a3 100644 (file)
@@ -45,7 +45,6 @@ int load_tm( struct tm_binds *tmb)
                LOG(L_ERR, LOAD_ERROR "'register_tmcb' not found\n");
                return -1;
        }
-
        if (!( tmb->t_relay_to_tcp=find_export(T_RELAY_TO_TCP, 2, 0)) ) {
                LOG(L_ERR, LOAD_ERROR "'t_relay_to_tcp' not found\n");
                return -1;
index 798f35f..b4f5185 100644 (file)
@@ -56,6 +56,7 @@
 #define T_RELAY              "t_relay"
 #define T_REPLY              "t_reply"
 #define T_REPLY_WB           "t_reply_with_body"
+#define T_REPLY_UNSAFE       "t_reply_unsafe"
 #define T_ADDBLIND           "t_add_blind"
 #define T_REPLY_UNSAFE       "t_reply_unsafe"
 #define T_FORWARD_NONACK     "t_forward_nonack"
 #define T_IS_LOCAL           "t_is_local"
 #define T_REQUEST_WITHIN     "request_within"
 #define T_REQUEST_OUTSIDE    "request_outside"
-#define T_GETT                          "t_gett"
+#define T_GETT               "t_gett"
 
 
 
 struct tm_binds {
-       register_tmcb_f register_tmcb;
-       cmd_function    t_relay_to_udp;
-       cmd_function    t_relay_to_tcp;
-       cmd_function    t_relay;
-       treply_f        t_reply;
-       treply_wb_f     t_reply_with_body;
-       tislocal_f      t_is_local;
-       tget_ti_f       t_get_trans_ident;
-       tlookup_ident_f t_lookup_ident;
-       taddblind_f     t_addblind;
-       treply_f        t_reply_unsafe;
-       tfwd_f          t_forward_nonack;
-       reqwith_t       t_request_within;
-       reqout_t        t_request_outside;
-       req_t           t_request;
-       
+       register_tmcb_f  register_tmcb;
+       cmd_function     t_relay_to_udp;
+       cmd_function     t_relay_to_tcp;
+       cmd_function     t_relay;
+       treply_f         t_reply;
+       treply_wb_f      t_reply_with_body;
+       tislocal_f       t_is_local;
+       tget_ti_f        t_get_trans_ident;
+       tlookup_ident_f  t_lookup_ident;
+       taddblind_f      t_addblind;
+       treply_f         t_reply_unsafe;
+       tfwd_f           t_forward_nonack;
+       reqwith_t        t_request_within;
+       reqout_t         t_request_outside;
+       req_t            t_request;
        new_dlg_uac_f      new_dlg_uac;
        dlg_response_uac_f dlg_response_uac;
        new_dlg_uas_f      new_dlg_uas;
        dlg_request_uas_f  dlg_request_uas;
        free_dlg_f         free_dlg;
        print_dlg_f        print_dlg;
-
-       tgett_f                 t_gett;
+       tgett_f            t_gett;
 };
 
 
index 7afbd06..783a0c9 100644 (file)
@@ -45,6 +45,8 @@
  *  2003-07-08  appropriate log messages in check_params(...), 
  *               call calculate_hooks if next_hop==NULL in t_uac (dcm) 
  *  2003-10-24  updated to the new socket_info lists (andrei)
+ *  2003-12-03  completion filed removed from transaction and uac callbacks
+ *              merged in transaction callbacks as LOCAL_COMPLETED (bogdan)
  */
 
 #include <string.h>
@@ -148,7 +150,8 @@ static inline int check_params(str* method, str* to, str* from, dlg_t** dialog)
 /*
  * Send a request using data from the dialog structure
  */
-int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp)
+int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
+                                                                                               transaction_cb cb, void* cbp)
 {
        struct socket_info* send_sock;
        union sockaddr_union to_su;
@@ -180,13 +183,15 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb
                goto error2;
        }
 
-       new_cell->completion_cb = cb;
-       new_cell->cbp = cbp;
-       
-            /* cbp is installed -- tell error handling bellow not to free it */
-       cbp = 0;
+       /* add the callback the the transaction for LOCAL_COMPLETED event */
+       if (insert_tmcb( &(new_cell->tmcb_hl), TMCB_LOCAL_COMPLETED, cb, cbp)!=1) {
+               ret=E_OUT_OF_MEM;
+               LOG(L_ERR, "t_uac: short of tmcb shmem\n");
+               goto error2;
+       }
 
-       new_cell->is_invite = method->len == INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN) == 0;
+       new_cell->is_invite =
+               method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0;
        new_cell->local= 1;
        set_kr(REQ_FWDED);
        
@@ -196,12 +201,13 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb
        request->dst.proto = send_sock->proto;
        request->dst.proto_reserved1 = 0;
 
-            /* need to put in table to calculate label which is needed for printing */
+       /* need to put in table to calculate label which is needed for printing */
        LOCK_HASH(new_cell->hash_index);
        insert_into_hash_table_unsafe(new_cell);
        UNLOCK_HASH(new_cell->hash_index);
 
-       buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, send_sock);
+       buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
+               &buf_len, send_sock);
        if (!buf) {
                LOG(L_ERR, "t_uac: Error while building message\n");
                ret=E_OUT_OF_MEM;
@@ -217,23 +223,19 @@ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb
        
        if (SEND_BUFFER(request) == -1) {
                LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", 
-                   dialog->hooks.next_hop->len,
-                   dialog->hooks.next_hop->s
-                   );
+                       dialog->hooks.next_hop->len,
+                       dialog->hooks.next_hop->s);
        }
        
        start_retr(request);
        return 1;
 
- error1:
+error1:
        LOCK_HASH(new_cell->hash_index);
        remove_from_hash_table_unsafe(new_cell);
        UNLOCK_HASH(new_cell->hash_index);
        free_cell(new_cell);
-
- error2:
-            /* if we did not install cbp, release it now */
-       if (cbp) shm_free(cbp);
+error2:
        return ret;
 }
 
index 960b106..aaaa999 100644 (file)
@@ -1,5 +1,32 @@
 /*
  * $Id$
+ *
+ * Copyright (C) 2001-2003 Fhg Fokus
+ *
+ * This file is part of ser, a free SIP server.
+ *
+ * ser is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version
+ *
+ * For a license to use the ser software under conditions
+ * other than those described here, or to purchase support for this
+ * software, please contact iptel.org by e-mail at the following addresses:
+ *    info@iptel.org
+ *
+ * ser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * History:
+ * --------
+ *  2003-12-03 : fifo_callback() updated for changes in tm callbacks (bogdan)
  */
 
 #include <string.h>
@@ -31,8 +58,8 @@ struct cb_data {
 
 
 struct str_list {
-        str s;
-        struct str_list *next;
+       str s;
+       struct str_list *next;
 };
 
 
@@ -502,8 +529,7 @@ static inline int print_uris(FILE* out, struct sip_msg* reply)
 }
 
 
-static void fifo_callback(struct cell *t, struct sip_msg *reply,
-                         int code, void *param)
+static void fifo_callback( struct cell *t, int type, struct tmcb_params *ps )
 {
        
        char *filename;
@@ -512,35 +538,39 @@ static void fifo_callback(struct cell *t, struct sip_msg *reply,
 
        DBG("!!!!! ref_counter: %d\n", t->ref_count);
 
-       DBG("DEBUG: fifo UAC completed with status %d\n", code);
-       if (!t->cbp) {
-               LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", code);
+       DBG("DEBUG: fifo UAC completed with status %d\n", ps->code);
+       if (!ps->param) {
+               LOG(L_INFO, "INFO: fifo UAC completed with status %d\n", ps->code);
                return;
        }
 
-       filename=(char *)(t->cbp);
-       if (reply==FAKED_REPLY) {
-               get_reply_status(&text,reply,code);
+       filename=(char *)(ps->param);
+       if (ps->rpl==FAKED_REPLY) {
+               get_reply_status( &text, ps->rpl, ps->code);
                if (text.s==0) {
                        LOG(L_ERR, "ERROR: fifo_callback: get_reply_status failed\n");
-                       fifo_reply(filename, "500 fifo_callback: get_reply_status failed\n");
-                       return;
+                       fifo_reply( filename,
+                               "500 fifo_callback: get_reply_status failed\n");
+                       goto done;
                }
                fifo_reply(filename, "%.*s\n", text.len, text.s );
                pkg_free(text.s);
        } else {
-               text.s=reply->first_line.u.reply.reason.s;
-               text.len=reply->first_line.u.reply.reason.len;
+               text.s = ps->rpl->first_line.u.reply.reason.s;
+               text.len = ps->rpl->first_line.u.reply.reason.len;
 
                f = fopen(filename, "wt");
-               if (!f) return;
-               fprintf(f, "%d %.*s\n", reply->first_line.u.reply.statuscode, text.len, text.s);
-               print_uris(f, reply);
-               fprintf(f, "%s\n", reply->headers->name.s);
+               if (!f) goto done;
+               fprintf(f, "%d %.*s\n", ps->rpl->first_line.u.reply.statuscode,
+                       text.len, text.s);
+               print_uris(f, ps->rpl);
+               fprintf(f, "%s\n", ps->rpl->headers->name.s);
                fclose(f);
        }
        DBG("DEBUG: fifo_callback sucesssfuly completed\n");
-}      
+done:
+       shm_free(ps->param);
+}
 
 
 int fifo_uac(FILE *stream, char *response_file)
@@ -624,7 +654,7 @@ int fifo_uac(FILE *stream, char *response_file)
 
        if (ret <= 0) {
                err_ret = err2reason_phrase(ret, &sip_error, err_buf,
-                                           sizeof(err_buf), "FIFO/UAC") ;
+                       sizeof(err_buf), "FIFO/UAC") ;
                if (err_ret > 0 )
                {
                        fifo_uac_error(response_file, sip_error, err_buf);