- epxerimental TMCB_LOCAL_REQUEST_IN callback: must be registered from mod_init ...
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Mar 2007 18:21:50 +0000 (18:21 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Fri, 23 Mar 2007 18:21:50 +0000 (18:21 +0000)
 (e.g. t_uac called from fifo/rpc).

modules/tm/h_table.c
modules/tm/t_hooks.c
modules/tm/t_hooks.h
modules/tm/uac.c

index e94bda1..04b9d52 100644 (file)
@@ -266,32 +266,37 @@ struct cell*  build_cell( struct sip_msg* p_msg )
        /* timers */
        init_cell_timers(new_cell);
 
-       old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI,  &new_cell->uri_avps_from );
+       old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, 
+                       &new_cell->uri_avps_from );
        new_cell->uri_avps_from = *old;
        *old = 0;
 
-       old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI,  &new_cell->uri_avps_to );
+       old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, 
+                       &new_cell->uri_avps_to );
        new_cell->uri_avps_to = *old;
        *old = 0;
 
-       old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER,  &new_cell->user_avps_from );
+       old = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, 
+                       &new_cell->user_avps_from );
        new_cell->user_avps_from = *old;
        *old = 0;
 
-       old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER,  &new_cell->user_avps_to );
+       old = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, 
+                       &new_cell->user_avps_to );
        new_cell->user_avps_to = *old;
        *old = 0;
 
             /* We can just store pointer to domain avps in the transaction context,
              * because they are read-only
              */
-       new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN);
+       new_cell->domain_avps_from = get_avp_list(AVP_TRACK_FROM | 
+                                                               AVP_CLASS_DOMAIN);
        new_cell->domain_avps_to = get_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN);
 
        /* enter callback, which may potentially want to parse some stuff,
         * 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 && has_reqin_tmcbs())
+                       run_reqin_callbacks( new_cell, p_msg, p_msg->REQ_METHOD);
 
        if (p_msg) {
                /* clean possible previous added vias/clen header or else they would 
index 0534144..73f82eb 100644 (file)
@@ -35,6 +35,7 @@
  *              available in callbacks (bogdan)
  * 2007-03-08  membar_write() used in insert_tmcb(...) (andrei)
  * 2007-03-14  added *_SENT callbacks (andrei)
+ * 2007-03-23  added local_req_in callbacks support (andrei)
  */
 
 #include "defs.h"
@@ -52,6 +53,7 @@
 
 
 struct tmcb_head_list* req_in_tmcb_hl = 0;
+struct tmcb_head_list* local_req_in_tmcb_hl = 0;
 
 
 
@@ -59,13 +61,27 @@ 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) {
+       local_req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
+               ( sizeof(struct tmcb_head_list) );
+       if ((req_in_tmcb_hl==0) || (local_req_in_tmcb_hl==0)) {
                LOG(L_CRIT,"ERROR:tm:init_tmcb_lists: no more shared mem\n");
-               return -1;
+               goto error;
        }
        req_in_tmcb_hl->first = 0;
        req_in_tmcb_hl->reg_types = 0;
+       local_req_in_tmcb_hl->first = 0;
+       local_req_in_tmcb_hl->reg_types = 0;
        return 1;
+error:
+       if (req_in_tmcb_hl){
+               shm_free(req_in_tmcb_hl);
+               req_in_tmcb_hl=0;
+       }
+       if(local_req_in_tmcb_hl){
+               shm_free(local_req_in_tmcb_hl);
+               local_req_in_tmcb_hl=0;
+       }
+       return -1;
 }
 
 
@@ -73,17 +89,26 @@ void destroy_tmcb_lists()
 {
        struct tm_callback *cbp, *cbp_tmp;
 
-       if (!req_in_tmcb_hl)
-               return;
-
-       for( cbp=req_in_tmcb_hl->first; cbp ; ) {
-               cbp_tmp = cbp;
-               cbp = cbp->next;
-               if (cbp_tmp->param) shm_free( cbp_tmp->param );
-               shm_free( cbp_tmp );
+       if (req_in_tmcb_hl){
+               for( cbp=req_in_tmcb_hl->first; cbp ; ) {
+                       cbp_tmp = cbp;
+                       cbp = cbp->next;
+                       if (cbp_tmp->param) shm_free( cbp_tmp->param );
+                       shm_free( cbp_tmp );
+               }
+               shm_free(req_in_tmcb_hl);
+               req_in_tmcb_hl=0;
+       }
+       if(local_req_in_tmcb_hl){
+               for( cbp=local_req_in_tmcb_hl->first; cbp ; ) {
+                       cbp_tmp = cbp;
+                       cbp = cbp->next;
+                       if (cbp_tmp->param) shm_free( cbp_tmp->param );
+                       shm_free( cbp_tmp );
+               }
+               shm_free(local_req_in_tmcb_hl);
+               local_req_in_tmcb_hl=0;
        }
-
-       shm_free(req_in_tmcb_hl);
 }
 
 
@@ -130,8 +155,8 @@ int insert_tmcb(struct tmcb_head_list *cb_list, int types,
  * (global or per transaction, depending of event type)
  * It _must_ be always called either with the REPLY_LOCK held, or before the
  *  branches are created.
- *  Special case: TMCB_REQUEST_IN - it must be called from mod_init
- *  (before forking!).
+ *  Special cases: TMCB_REQUEST_IN & TMCB_LOCAL_REQUEST_IN - must be called 
+ *                 from mod_init (before forking!).
 */
 int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
                                                                                        transaction_cb f, void *param )
@@ -158,6 +183,14 @@ int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
                        return E_BUG;
                }
                cb_list = req_in_tmcb_hl;
+       }else if (types & TMCB_LOCAL_REQUEST_IN) {
+               if (types!=TMCB_LOCAL_REQUEST_IN) {
+                       LOG(L_CRIT, "BUG:tm:register_tmcb: callback type"
+                                       " TMCB_LOCAL_REQUEST_IN can't be register along with"
+                                       " other types\n");
+                       return E_BUG;
+               }
+               cb_list = local_req_in_tmcb_hl;
        } else {
                if (!t) {
                        if (!p_msg) {
@@ -189,12 +222,18 @@ static void run_trans_callbacks_internal(int type, struct cell *trans,
        struct tm_callback    *cbp;
        avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
 
-       backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, &trans->uri_avps_from );
-       backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, &trans->uri_avps_to );
-       backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps_from );
-       backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, &trans->user_avps_to );
-       backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, &trans->domain_avps_from);
-       backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, &trans->domain_avps_to);
+       backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
+                       &trans->uri_avps_from );
+       backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
+                       &trans->uri_avps_to );
+       backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
+                       &trans->user_avps_from );
+       backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
+                       &trans->user_avps_to );
+       backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
+                       &trans->domain_avps_from);
+       backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
+                       &trans->domain_avps_to);
        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",
@@ -275,30 +314,31 @@ void run_onsend_callbacks2(int type , struct retr_buf* rbuf, char* buf,
 
 #endif
 
-void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
+static void run_reqin_callbacks_internal(struct tmcb_head_list* hl,
+                                                       struct cell *trans, struct tmcb_params* params)
 {
-       static struct tmcb_params params;
        struct tm_callback    *cbp;
-       avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
-
-       if (req_in_tmcb_hl->first==0)
-               return;
-       memset (&params, 0, sizeof(params));
-       params.req = req;
-       params.code = code;
-
-
-       backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, &trans->uri_avps_from );
-       backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, &trans->uri_avps_to );
-       backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps_from );
-       backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, &trans->user_avps_to );
-       backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, &trans->domain_avps_from);
-       backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, &trans->domain_avps_to);
-       for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
+       avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to,
+                               *backup_uri_from, *backup_uri_to;
+
+       if (hl==0 || hl->first==0) return;
+       backup_uri_from = set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM,
+                       &trans->uri_avps_from );
+       backup_uri_to = set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, 
+                       &trans->uri_avps_to );
+       backup_from = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, 
+                       &trans->user_avps_from );
+       backup_to = set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, 
+                       &trans->user_avps_to );
+       backup_dom_from = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_FROM, 
+                       &trans->domain_avps_from);
+       backup_dom_to = set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, 
+                       &trans->domain_avps_to);
+       for (cbp=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 );
+               params->param = &(cbp->param);
+               cbp->callback( trans, cbp->types, params );
        }
        set_avp_list(AVP_CLASS_URI | AVP_TRACK_TO, backup_uri_to );
        set_avp_list(AVP_CLASS_URI | AVP_TRACK_FROM, backup_uri_from );
@@ -307,3 +347,33 @@ void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
        set_avp_list(AVP_CLASS_USER | AVP_TRACK_TO, backup_to );
        set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup_from );
 }
+
+
+
+void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
+{
+       static struct tmcb_params params;
+
+       if (req_in_tmcb_hl->first==0)
+               return;
+       memset (&params, 0, sizeof(params));
+       params.req = req;
+       params.code = code;
+       
+       run_reqin_callbacks_internal(req_in_tmcb_hl, trans, &params);
+}
+
+
+void run_local_reqin_callbacks( struct cell *trans, struct sip_msg *req,
+                                                               int code )
+{
+       static struct tmcb_params params;
+
+       if (local_req_in_tmcb_hl->first==0)
+               return;
+       memset (&params, 0, sizeof(params));
+       params.req = req;
+       params.code = code;
+       
+       run_reqin_callbacks_internal(local_req_in_tmcb_hl, trans, &params);
+}
index f72615c..d1e6d29 100644 (file)
@@ -34,6 +34,7 @@
  * 2007-03-14   added *_SENT callbacks (andrei)
  * 2007-03-17   added TMCB_NEG_ACK_IN, TMCB_REQ_RETR_IN & 
  *               TMCB_LOCAL_RESPONSE_IN (andrei)
+ * 2007-03-23   added TMCB_LOCAL_REQUEST_IN (andrei)
  */
 
 
@@ -67,12 +68,13 @@ struct cell;
 #define TMCB_ACK_NEG_IN_N       10
 #define TMCB_REQ_RETR_IN_N      11
 #define TMCB_LOCAL_RESPONSE_IN_N 12
+#define TMCB_LOCAL_REQUEST_IN_N  13
 #ifdef TMCB_ONSEND
-#define TMCB_REQUEST_SENT_N     13
-#define TMCB_RESPONSE_SENT_N    14
-#define TMCB_MAX_N              14
+#define TMCB_REQUEST_SENT_N     14
+#define TMCB_RESPONSE_SENT_N    15
+#define TMCB_MAX_N              15
 #else
-#define TMCB_MAX_N              12
+#define TMCB_MAX_N              13
 #endif
 
 #define TMCB_REQUEST_IN       (1<<TMCB_REQUEST_IN_N)
@@ -88,6 +90,7 @@ struct cell;
 #define TMCB_ACK_NEG_IN       (1<<TMCB_ACK_NEG_IN_N)
 #define TMCB_REQ_RETR_IN      (1<<TMCB_REQ_RETR_IN_N)
 #define TMCB_LOCAL_RESPONSE_IN (1<<TMCB_LOCAL_RESPONSE_IN_N)
+#define TMCB_LOCAL_REQUEST_IN (1<<TMCB_LOCAL_REQUEST_IN_N)
 #ifdef TMCB_ONSEND
 #define TMCB_REQUEST_SENT      (1<<TMCB_REQUEST_SENT_N)
 #define TMCB_RESPONSE_SENT     (1<<TMCB_RESPONSE_SENT_N)
@@ -239,6 +242,20 @@ struct cell;
  * transactions). It may or may not be a retransmission.
  * No lock is held here (yet). It's unsafe to register other TMCB callbacks.
  *
+ * TMCB_LOCAL_REQUEST_IN -- like TMCB_REQUEST_IN but for locally generated 
+ * request (e.g. via fifo/rpc):  a brand-new local request was 
+ * received/generated and a transaction for it is about to be created.
+ * It's called from HASH_LOCK, so be careful. It is guaranteed not to be
+ * a retransmission. The transactional context is mostly
+ * incomplete -- this callback is called in very early stage
+ * before the message is shmem-ized (so that you can work
+ * with it).
+ * It's safe to install other TMCB callbacks from here.
+ * Note: this callback MUST be installed before forking
+ * (the local_req_in_tmcb_hl callback list does not live in shmem and has no 
+ * access protection), i.e., at best from mod_init functions.
+ *
+ *
  *  All of the following callbacks are called immediately after or before 
  *  sending a message. All of them are read-only (no change can be made to
  * the message). These callbacks use the t_rbuf, send_buf, dst, is_retr
@@ -327,12 +344,15 @@ struct tmcb_head_list {
 
 
 extern struct tmcb_head_list*  req_in_tmcb_hl;
+extern struct tmcb_head_list*  local_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 )
+#define has_local_reqin_tmcbs() \
+       ( local_req_in_tmcb_hl->first!=0 )
 
 
 int init_tmcb_lists();
@@ -354,6 +374,8 @@ void run_trans_callbacks( int type , struct cell *trans,
 
 /* run all REQUEST_IN callbacks */
 void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code );
+void run_local_reqin_callbacks( struct cell *trans, struct sip_msg *req, 
+               int code );
 
 #ifdef TMCB_ONSEND
 void run_onsend_callbacks(int type, struct retr_buf* rbuf, int retr);
index 7a6e02a..1289805 100644 (file)
@@ -54,6 +54,7 @@
  *               fixes 0 fr_timer bug (andrei)
  *  2006-08-11  t_uac uses dns failover until it finds a send socket (andrei)
  *  2007-03-15  TMCB_ONSEND callbacks support added (andrei)
+ *  2007-03-23  TMCB_LOCAL_REQUEST_IN callbacks support (andrei)
  */
 
 #include <string.h>
@@ -294,6 +295,8 @@ static inline int t_uac_prepare(str* method, str* headers, str* body,
        request->buffer_len = buf_len;
        new_cell->nr_of_outgoings++;
        
+       if (has_local_reqin_tmcbs())
+                       run_local_reqin_callbacks(new_cell, 0, 0);
        if (dst_req) *dst_req = request;
        if (dst_cell) *dst_cell = new_cell;