- tm on_send callbacks support: if such a callback is registered it will be
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Thu, 15 Mar 2007 16:30:16 +0000 (16:30 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Thu, 15 Mar 2007 16:30:16 +0000 (16:30 +0000)
 called after tm sends a message. The callback can "see" what exactly was sent
  on the wire and to whom. These callbacks are intended to be read-only
 (no changes to the message are allowed). Their man purpose is extra-accounting
  or logging. For more info see the comments in tm/t_hooks.h.

NEWS
modules/tm/h_table.h
modules/tm/t_cancel.c
modules/tm/t_fwd.c
modules/tm/t_hooks.c
modules/tm/t_hooks.h
modules/tm/t_reply.c
modules/tm/timer.c
modules/tm/uac.c

diff --git a/NEWS b/NEWS
index 8186e5a..97dd5e4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,7 +3,15 @@ Release notes for SIP Express Router (ser)
 
 $Id$
 
-0.10.99-dev changes
+
+2.1.0 changes
+
+modules:
+ - tm        - new onsend callbacks support (require defining TMCB_ONSEND prior
+               to compiling tm)
+
+
+2.0.0 changes
 
 
 new archs:
index 57bc3f0..3044afa 100644 (file)
 #ifndef _H_TABLE_H
 #define _H_TABLE_H
 
-#include <stdio.h>
-#include <stdlib.h>
+/*
+ #include <stdio.h>
+ #include <stdlib.h>
+*/
 
 #include "../../parser/msg_parser.h"
 #include "../../types.h"
@@ -80,6 +82,7 @@ void unlock_hash(int i);
 #define NO_CANCEL       ( (char*) 0 )
 #define EXTERNAL_CANCEL ( (char*) -1)
 
+#define TYPE_LOCAL_ACK    -2
 #define TYPE_LOCAL_CANCEL -1
 #define TYPE_REQUEST       0
 
index 2af5ed8..f3676d1 100644 (file)
@@ -32,6 +32,7 @@
  * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri)
  * 2004-02-13  timer_link.payload removed (bogdan)
  * 2006-10-10  cancel_uacs  & cancel_branch take more options now (andrei)
+ * 2007-03-15  TMCB_ONSEND hooks added (andrei)
  */
 
 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
@@ -46,6 +47,7 @@
 #include "t_cancel.h"
 #include "t_msgbuilder.h"
 #include "t_lookup.h" /* for t_lookup_callid in fifo_uac_cancel */
+#include "t_hooks.h"
 
 
 /* determine which branches should be canceled; do it
@@ -114,9 +116,9 @@ int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
  *         -1 - error
  * WARNING:
  *          - F_CANCEL_KILL_B should be used only if the transaction is killed
- *            explicitely afterwards (since it might kill all the timers
+ *            explicitly afterwards (since it might kill all the timers
  *            the transaction won't be able to "kill" itself => if not
- *            explicitely "put_on_wait" it migh leave forever)
+ *            explicitly "put_on_wait" it might live forever)
  *          - F_CANCEL_B_FAKE_REPLY must be used only if the REPLY_LOCK is not
  *            held
  */
@@ -189,7 +191,12 @@ int cancel_branch( struct cell *t, int branch, int flags )
        crb->activ_type = TYPE_LOCAL_CANCEL;
 
        DBG("DEBUG: cancel_branch: sending cancel...\n");
+#ifdef TMCB_ONSEND
+       if (SEND_BUFFER( crb )>=0)
+               run_onsend_callbacks(TMCB_REQUEST_SENT, crb, 0);
+#else
        SEND_BUFFER( crb );
+#endif
        /*sets and starts the FINAL RESPONSE timer */
        if (start_retr( crb )!=0)
                LOG(L_CRIT, "BUG: cancel_branch: failed to start retransmission"
index 4e653bd..8900d1d 100644 (file)
@@ -63,6 +63,7 @@
  *              stop retr. timers fix on cancel for non-invites     (andrei)
  *  2006-11-20  new_uri is no longer saved/restore across add_uac calls, since
  *              print_uac_request is now uri safe (andrei)
+ * 2007-03-15  TMCB_ONSEND hooks added (andrei)
  */
 
 #include "defs.h"
@@ -507,6 +508,12 @@ void e2e_cancel( struct sip_msg *cancel_msg,
                                if (SEND_BUFFER(&t_cancel->uac[i].request) == -1) {
                                        LOG(L_ERR, "ERROR: e2e_cancel: send failed\n");
                                }
+#ifdef TMCB_ONSEND
+                               else{
+                                       run_onsend_callbacks(TMCB_REQUEST_SENT, 
+                                                                                       &t_cancel->uac[i].request, 0);
+                               }
+#endif
                                if (start_retr( &t_cancel->uac[i].request )!=0)
                                        LOG(L_CRIT, "BUG: e2e_cancel: failed to start retr."
                                                        " for %p\n", &t_cancel->uac[i].request);
@@ -655,7 +662,7 @@ int t_send_branch( struct cell *t, int branch, struct sip_msg* p_msg ,
        if (SEND_BUFFER( &uac->request)==-1) {
                /* disable the current branch: set a "fake" timeout
                 *  reply code but don't set uac->reply, to avoid overriding 
-                *  a higly unlikely, perfectly timed fake reply (to a message
+                *  a highly unlikely, perfectly timed fake reply (to a message
                 *  we never sent).
                 * (code=final reply && reply==0 => t_pick_branch won't ever pick it)*/
                uac->last_received=408;
@@ -685,6 +692,9 @@ int t_send_branch( struct cell *t, int branch, struct sip_msg* p_msg ,
                if (proxy) { proxy->errors++; proxy->ok=0; }
                return -2;
        } else {
+#ifdef TMCB_ONSEND
+               run_onsend_callbacks(TMCB_REQUEST_SENT, &uac->request, 0);
+#endif
                /* start retr. only if the send succeeded */
                if (start_retr( &uac->request )!=0){
                        LOG(L_CRIT, "BUG: t_send_branch: retr. already started for %p\n",
index 03db93c..0534144 100644 (file)
@@ -34,6 +34,7 @@
  *  2004-08-23  user avp(attribute value pair) added -> making avp list
  *              available in callbacks (bogdan)
  * 2007-03-08  membar_write() used in insert_tmcb(...) (andrei)
+ * 2007-03-14  added *_SENT callbacks (andrei)
  */
 
 #include "defs.h"
@@ -182,20 +183,12 @@ int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
 }
 
 
-void run_trans_callbacks( int type , struct cell *trans,
-                                               struct sip_msg *req, struct sip_msg *rpl, int code )
+static void run_trans_callbacks_internal(int type, struct cell *trans, 
+                                                                                       struct tmcb_params *params)
 {
-       static struct tmcb_params params = {0,0,0,0};
        struct tm_callback    *cbp;
        avp_list_t* backup_from, *backup_to, *backup_dom_from, *backup_dom_to, *backup_uri_from, *backup_uri_to;
 
-       params.req = req;
-       params.rpl = rpl;
-       params.code = code;
-
-       if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==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 );
@@ -206,8 +199,8 @@ void run_trans_callbacks( int type , struct cell *trans,
                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 );
+                       params->param = &(cbp->param);
+                       cbp->callback( trans, type, params );
                }
        }
        set_avp_list(AVP_CLASS_DOMAIN | AVP_TRACK_TO, backup_dom_to );
@@ -220,17 +213,80 @@ void run_trans_callbacks( int type , struct cell *trans,
 
 
 
+void run_trans_callbacks( int type , struct cell *trans,
+                                               struct sip_msg *req, struct sip_msg *rpl, int code )
+{
+       struct tmcb_params params;
+       if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==0 )
+               return;
+       memset (&params, 0, sizeof(params));
+       params.req = req;
+       params.rpl = rpl;
+       params.code = code;
+       run_trans_callbacks_internal(type, trans, &params);
+}
+
+
+
+#ifdef TMCB_ONSEND
+void run_onsend_callbacks(int type, struct retr_buf* rbuf, int retr)
+{
+       struct tmcb_params params;
+       struct cell * trans;
+
+       trans=rbuf->my_T;
+       if ( trans==0 || trans->tmcb_hl.first==0 || 
+                       ((trans->tmcb_hl.reg_types)&type)==0 )
+               return;
+       memset (&params, 0, sizeof(params));
+       params.send_buf.s=rbuf->buffer;
+       params.send_buf.len=rbuf->buffer_len;
+       params.dst=&rbuf->dst;
+       params.is_retr=retr;
+       params.branch=rbuf->branch;
+       params.t_rbuf=rbuf;
+       params.code=rbuf->activ_type;
+       /* req, rpl */
+       run_trans_callbacks_internal(type, trans, &params);
+}
+
+
+void run_onsend_callbacks2(int type , struct retr_buf* rbuf, char* buf,
+                                                       int buf_len, struct dest_info* dst, int code)
+{
+       struct tmcb_params params;
+       struct cell * trans;
+
+       trans=rbuf->my_T;
+       if ( trans==0 || trans->tmcb_hl.first==0 || 
+                       ((trans->tmcb_hl.reg_types)&type)==0 )
+               return;
+       memset (&params, 0, sizeof(params));
+       params.send_buf.s=buf;
+       params.send_buf.len=buf_len;
+       params.dst=dst;
+       params.is_retr=0;
+       params.branch=rbuf->branch;
+       params.t_rbuf=rbuf;
+       params.code=code;
+       /* req, rpl */
+       run_trans_callbacks_internal(type, trans, &params);
+}
+
+#endif
+
 void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
 {
-       static struct tmcb_params params = {0,0,0,0};
+       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;
 
-       if (req_in_tmcb_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 );
index 45c8326..8fca8cd 100644 (file)
@@ -31,6 +31,7 @@
  * 2003-12-04 : global callbacks moved into transaction callbacks;
  *              multiple events per callback added; single list per
  *              transaction for all its callbacks (bogdan)
+ * 2007-03-14   added *_SENT callbacks (andrei)
  */
 
 
 
 #include "defs.h"
 
+/* if defined support for ONSEND callbacks will be added and
+ * the tmcb_params structure will get some additional members */
+/*
+#define TMCB_ONSEND
+*/
+#ifdef TMCB_ONSEND
+#include "../../ip_addr.h" /* dest_info */
+#endif
+
 struct sip_msg;
 struct cell;
 
@@ -52,7 +62,13 @@ struct cell;
 #define TMCB_RESPONSE_OUT_N     7
 #define TMCB_LOCAL_COMPLETED_N  8
 #define TMCB_LOCAL_RESPONSE_OUT_N 9
+#ifdef TMCB_ONSEND
+#define TMCB_REQUEST_SENT_N     10
+#define TMCB_RESPONSE_SENT_N    11
+#define TMCB_MAX_N              11
+#else
 #define TMCB_MAX_N              9
+#endif
 
 #define TMCB_REQUEST_IN       (1<<TMCB_REQUEST_IN_N)
 #define TMCB_RESPONSE_IN      (1<<TMCB_RESPONSE_IN_N)
@@ -64,6 +80,10 @@ struct cell;
 #define TMCB_RESPONSE_OUT     (1<<TMCB_RESPONSE_OUT_N)
 #define TMCB_LOCAL_COMPLETED  (1<<TMCB_LOCAL_COMPLETED_N)
 #define TMCB_LOCAL_RESPONSE_OUT (1<<TMCB_LOCAL_RESPONSE_OUT_N)
+#ifdef TMCB_ONSEND
+#define TMCB_REQUEST_SENT      (1<<TMCB_REQUEST_SENT_N)
+#define TMCB_RESPONSE_SENT     (1<<TMCB_RESPONSE_SENT_N)
+#endif
 #define TMCB_MAX              ((1<<(TMCB_MAX_N+1))-1)
 
 
@@ -199,11 +219,49 @@ struct cell;
  *  called multiple time quasi-simultaneously. No lock is held.
  *  It's unsafe to register other TMCB callbacks.
  *
+ *  TMCB_ONSEND callbacks
+ *
+ *  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
+ *  and the code members of the tmcb_params structure.
+ *  For a request code is <=0. code values can be TYPE_LOCAL_ACK for an ACK 
+ *  generated by ser, TYPE_LOCAL_CANCEL for a CANCEL generated by ser 
+ *  and TYPE_REQUEST for all the other requests or requests generated via 
+ *  t_uac.
+ *   For a reply the code is the response status (which is always >0, e.g. 200,
+ *   408, a.s.o).
+ *  Note: - these callbacks can be used only if TMCB_ONSEND is defined.
+ *        - the callbacks will be called sometimes with the REPLY lock held
+ *          and sometimes without it, so trying to acquire the REPLY lock
+ *          from these callbacks could lead to deadlocks (avoid it unless
+ *           you really know what you're doing).
+ *
+ *  TMCB_REQUEST_SENT (present only if TMCB_ONSEND is defined) -- called 
+ *  each time a request was sent (even for retransmissions), it includes 
+ *  local and forwarded request, ser generated CANCELs and ACKs. The 
+ *  tmcb_params structure will have the t_rbuf, dst, send_buf and is_retr
+ *  members  filled.
+ *  This callback is "read-only", the message was already sent and no changes
+ *  are allowed.
+ *  Note: send_buf can be different from t_rbuf->buffer for ACKs (in this
+ *   case t_rbuf->buf will contain the last request sent on the branch and
+ *   its destination). The same goes for t_rbuf->dst and tmcb->dst for local 
+ *   transactions ACKs to 2xxs.
+ *
+ *  TMCB_RESPONSE_SENT  (present only if TMCB_ONSEND is defined) -- called 
+ *  each time a response was sent (even for retransmissions). The tmcb_params
+ *   structure will have t_rbuf set to the reply retransmission buffer and
+ *   send_buf set to the data sent (in this case it will always be the same 
+ *   with t_rbuf->buf). is_retr will also be set if the reply is retransmitted
+ *   by ser.
+ *  This callback is "read-only", the message was already sent and no changes
+ *  are allowed.
  *
 
        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.
+       callback function if necessary.
 */
 
 
@@ -211,8 +269,22 @@ struct cell;
 struct tmcb_params {
        struct sip_msg* req;
        struct sip_msg* rpl;
-       int code;
        void **param;
+#ifdef TMCB_ONSEND
+       struct retr_buf* t_rbuf; /* transaction retr. buf., all the information
+                                                                regarding destination, data that is/was
+                                                                actually sent on the net, branch a.s.o is
+                                                                inside */
+       struct dest_info* dst; /* destination */
+       str send_buf; /* what was/will be sent on the net, used for ACKs
+                                       (which don't have a retr_buf). */
+       short is_retr; /* set if this is a _ser_ retransmission (but not if
+                                        if it's a "forwarded" retr., like a retr. 200 Ok for 
+                                        example) */
+       unsigned short branch;
+       /* could also be: send_buf, dst, branch */
+#endif
+       int code;
 };
 
 /* callback function prototype */
@@ -267,4 +339,10 @@ 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 );
 
+#ifdef TMCB_ONSEND
+void run_onsend_callbacks(int type, struct retr_buf* rbuf, int retr);
+void run_onsend_callbacks2(int type , struct retr_buf* rbuf, char* buf,
+                                                       int buf_len, struct dest_info* dst, int code);
+#endif
+
 #endif
index 700b23a..c246afc 100644 (file)
@@ -80,7 +80,8 @@
  *               the final response is 401 or 407 (andrei)
  * 2007-03-08  membar_write() used in update_totag_set(...)(andrei)
  * 2007-03-15  build_local_ack: removed next_hop and replaced with dst to 
- *              avoid resolving next_hop twice (andrei)
+ *              avoid resolving next_hop twice
+*              added TMCB_ONSEND callbacks support for replies & ACKs (andrei)
  *
  */
 
@@ -491,7 +492,13 @@ static int _reply_light( struct cell *trans, char* buf, unsigned int len,
        if (!trans->uas.response.dst.send_sock) {
                LOG(L_ERR, "ERROR: _reply_light: no resolved dst to send reply to\n");
        } else {
+#ifdef TMCB_ONSEND
+               if (SEND_PR_BUFFER( rb, buf, len )>=0)
+                       run_onsend_callbacks2(TMCB_RESPONSE_SENT, rb, buf, len, &rb->dst,
+                                                                       code);
+#else
                SEND_PR_BUFFER( rb, buf, len );
+#endif
                DBG("DEBUG: reply sent out. buf=%p: %.9s..., shmem=%p: %.9s\n",
                        buf, buf, rb->buffer, rb->buffer );
        }
@@ -1069,6 +1076,9 @@ int t_retransmit_reply( struct cell *t )
        memcpy( b, t->uas.response.buffer, len );
        UNLOCK_REPLIES( t );
        SEND_PR_BUFFER( & t->uas.response, b, len );
+#ifdef TMCB_ONSEND
+       run_onsend_callbacks(TMCB_RESPONSE_SENT, &t->uas.response, 1);
+#endif
        DBG("DEBUG: reply retransmitted. buf=%p: %.9s..., shmem=%p: %.9s\n",
                b, b, t->uas.response.buffer, t->uas.response.buffer );
        return 1;
@@ -1431,12 +1441,15 @@ enum rps relay_reply( struct cell *t, struct sip_msg *p_msg, int branch,
 
        /* send it now (from the private buffer) */
        if (relay >= 0) {
-               SEND_PR_BUFFER( uas_rb, buf, res_len );
-               DBG("DEBUG: reply relayed. buf=%p: %.15s..., shmem=%p: %.9s totag_retr=%d\n",
-                       buf, buf, uas_rb->buffer, uas_rb->buffer, totag_retr );
-               if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) {
-                       run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request,
-                               relayed_msg, relayed_code);
+               if (SEND_PR_BUFFER( uas_rb, buf, res_len )>=0){
+                       if (!totag_retr && has_tran_tmcbs(t, TMCB_RESPONSE_OUT) ) {
+                               run_trans_callbacks( TMCB_RESPONSE_OUT, t, t->uas.request,
+                                       relayed_msg, relayed_code);
+                       }
+#ifdef TMCB_ONSEND
+                       run_onsend_callbacks2(TMCB_RESPONSE_SENT, uas_rb, buf, res_len,
+                                                                       &uas_rb->dst, relayed_code);
+#endif
                }
                pkg_free( buf );
        }
@@ -1615,15 +1628,28 @@ int reply_received( struct sip_msg  *p_msg )
                        if (msg_status >= 300) {
                                ack = build_ack(p_msg, t, branch, &ack_len);
                                if (ack) {
+#ifdef TMCB_ONSEND
+                                       if (SEND_PR_BUFFER(&uac->request, ack, ack_len)>=0)
+                                               run_onsend_callbacks2(TMCB_REQUEST_SENT,
+                                                                       &uac->request, ack, ack_len, 
+                                                                       &uac->request.dst,
+                                                                       TYPE_LOCAL_ACK);
+#else
                                        SEND_PR_BUFFER(&uac->request, ack, ack_len);
+#endif
                                        shm_free(ack);
                                }
                        } else if (is_local(t) /*&& 200 <= msg_status < 300*/) {
                                ack = build_local_ack(p_msg, t, branch, &ack_len, &lack_dst);
                                if (ack) {
-                                       if (msg_send(&lack_dst, ack, ack_len)<0){
+                                       if (msg_send(&lack_dst, ack, ack_len)<0)
                                                LOG(L_ERR, "Error while sending local ACK\n");
-                                       }
+#ifdef TMCB_ONSEND
+                                       else
+                                               run_onsend_callbacks2(TMCB_REQUEST_SENT,
+                                                                       &uac->request, ack, ack_len, &lack_dst,
+                                                                       TYPE_LOCAL_ACK);
+#endif
                                        shm_free(ack);
                                }
                        }
index ef1d48c..3c361c0 100644 (file)
  *               return a 408
  *              set the corresponding "faked" failure route sip_msg->msg_flags 
  *               on timeout or if the branch received a reply (andrei)
+ *  2007-03-15  TMCB_ONSEND callbacks support (andrei)
  */
 
 #include "defs.h"
 #include "t_funcs.h"
 #include "t_reply.h"
 #include "t_cancel.h"
+#include "t_hooks.h"
 #ifdef USE_DNS_FAILOVER
 #include "t_fwd.h" /* t_send_branch */
 #endif
@@ -305,6 +307,9 @@ inline static ticks_t retransmission_handler( struct retr_buf *r_buf )
                                fake_reply(r_buf->my_T, r_buf->branch, 503 );
                                return (ticks_t)-1;
                        }
+#ifdef TMCB_ONSEND
+                       run_onsend_callbacks(TMCB_REQUEST_SENT, r_buf, 1);
+#endif
        } else {
 #ifdef EXTRA_DEBUG
                        DBG("DEBUG: retransmission_handler : "
index 81363b1..7a6e02a 100644 (file)
@@ -53,6 +53,7 @@
  *  2005-12-16  t_uac will set the new_cell timers to the default values,
  *               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)
  */
 
 #include <string.h>
@@ -344,6 +345,11 @@ static inline void send_prepared_request_impl(struct retr_buf *request, int retr
        if (SEND_BUFFER(request) == -1) {
                LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
        }
+#ifdef TMCB_ONSEND
+       else
+               /* we don't know the method here */
+               run_onsend_callbacks(TMCB_REQUEST_SENT, request, 0);
+#endif
        
        if (retransmit && (start_retr(request)!=0))
                LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);