New TM export - cancel_all_uacs() - to allow canceling all branches of a
authorBogdan Pintea <bogdan@iptego.com>
Mon, 31 Mar 2008 18:19:49 +0000 (18:19 +0000)
committerBogdan Pintea <bogdan@iptego.com>
Mon, 31 Mar 2008 18:19:49 +0000 (18:19 +0000)
transaction. (Closes issue #SER-253).

Some error messages are corrected to reflect new function name.

(Bits of code for the AS support also added; issue #SER-346 in the works.)

modules/tm/t_cancel.c
modules/tm/t_cancel.h
modules/tm/t_fwd.c
modules/tm/t_fwd.h
modules/tm/t_lookup.h
modules/tm/tm.c
modules/tm/tm_load.c
modules/tm/tm_load.h
modules/tm/ut.h

index 8cdf410..ea48054 100644 (file)
@@ -45,6 +45,9 @@
  */
 
 #include <stdio.h> /* for FILE* in fifo_uac_cancel */
+#ifdef EXTRA_DEBUG
+#include <assert.h>
+#endif /* EXTRA_DEBUG */
 
 #include "defs.h"
 #include "config.h"
@@ -106,6 +109,40 @@ int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags)
        return ret;
 }
 
+int cancel_all_uacs(struct cell *trans, int how)
+{
+       branch_bm_t cancel_bm;
+       int i,j;
+
+#ifdef EXTRA_DEBUG
+       assert(trans);
+#endif
+       DBG("Canceling T@%p [%u:%u]\n", trans, trans->hash_index, trans->label);
+       
+       cancel_bm=0;
+       which_cancel(trans, &cancel_bm);
+        /* tell tm to cancel the call */
+       i=cancel_uacs(trans, cancel_bm, how);
+       
+       if (how & F_CANCEL_UNREF)
+#ifndef TM_DEL_UNREF
+       /* in case of 'too many' _buggy_ invocations, the ref count (a uint) might 
+        * actually wrap around, possibly leaving the T leaking. */
+#warning "use of F_CANCEL_UNREF flag is unsafe without defining TM_DEL_UNREF"
+#endif
+               UNREF(trans);
+
+       /* count the still active branches */
+       if (! how) {
+               j=0;
+               while(i){
+                       j++;
+                       i&=i-1;
+               }
+               return j;
+       }
+       return 0;
+}
 
 
 /* should be called directly only if one of the condition bellow is true:
index 1327786..7e55980 100644 (file)
                                                                        if no provisional response was received;
                                                                        F_CANCEL_B_FORCE_C, F_CANCEL_B_FAKE_REPLY
                                                                        and F_CANCE_B_KILL take precedence */
+#define F_CANCEL_UNREF 16 /* unref the trans after canceling */
 
 
 void which_cancel( struct cell *t, branch_bm_t *cancel_bm );
 int cancel_uacs( struct cell *t, branch_bm_t cancel_bm, int flags );
+int cancel_all_uacs(struct cell *trans, int how);
 int cancel_branch( struct cell *t, int branch, int flags );
 
 typedef int(*cancel_uacs_f)( struct cell *t, branch_bm_t cancel_bm,
                                                                int flags );
+typedef int (*cancel_all_uacs_f)(struct cell *trans, int how);
 
 
 
index 39b5ccc..a822154 100644 (file)
 #include "../../atomic_ops.h" /* membar_depends() */
 #endif
 
-/* cancel hop by hop */
-#define E2E_CANCEL_HOP_BY_HOP
-
 static int goto_on_branch = 0, branch_route = 0;
 
 void t_on_branch( unsigned int go_to )
index d842304..f7d0146 100644 (file)
@@ -41,6 +41,9 @@
 #include "../../proxy.h"
 #include "h_table.h"
 
+/* cancel hop by hop */
+#define E2E_CANCEL_HOP_BY_HOP
+
 enum unmatched_cancel_t { UM_CANCEL_STATEFULL=0, UM_CANCEL_STATELESS,
                                                        UM_CANCEL_DROP };
 
index 98ed979..3ac599d 100644 (file)
@@ -108,4 +108,14 @@ int t_set_max_lifetime(struct sip_msg* msg, unsigned int eol_inv,
                                                                                        unsigned int eol_noninv);
 int t_reset_max_lifetime();
 
+#ifdef WITH_AS_SUPPORT
+/**
+ * Returns the hash coordinates of the transaction current CANCEL is targeting.
+ */
+int t_get_canceled_ident(struct sip_msg *msg, unsigned int *hash_index, 
+               unsigned int *label);
+typedef int (*t_get_canceled_ident_f)(struct sip_msg *msg, 
+               unsigned int *hash_index, unsigned int *label);
+#endif /* WITH_AS_SUPPORT */
+
 #endif
index 9272d48..1d00e70 100644 (file)
@@ -350,6 +350,12 @@ static cmd_export_t cmds[]={
        {"t_unref",            (cmd_function)t_unref,           NO_SCRIPT,   0, 0},
        {"run_failure_handlers", (cmd_function)run_failure_handlers, NO_SCRIPT,   0, 0},
        {"cancel_uacs",        (cmd_function)cancel_uacs,       NO_SCRIPT,   0, 0},
+       {"cancel_all_uacs",    (cmd_function)cancel_all_uacs,        NO_SCRIPT,   0, 0},
+#ifdef WITH_AS_SUPPORT
+       {"ack_local_uac",      (cmd_function)ack_local_uac,     NO_SCRIPT,   0, 0},
+       {"t_get_canceled_ident",   (cmd_function)t_get_canceled_ident,  NO_SCRIPT,
+                       0, 0},
+#endif
        {0,0,0,0,0}
 };
 
index 98fdea1..7e72cb8 100644 (file)
@@ -190,6 +190,11 @@ int load_tm( struct tm_binds *tmb)
                LOG( L_ERR, LOAD_ERROR "'cancel_uacs' not found\n");
                return -1;
        }
+       if (! (tmb->cancel_all_uacs=(cancel_all_uacs_f)find_export(
+                       "cancel_all_uacs", NO_SCRIPT, 0))) {
+               LOG( L_ERR, LOAD_ERROR "'cancel_all_uacs' not found\n");
+               return -1;
+       }
 
        tmb->prepare_request_within = prepare_req_within;
        tmb->send_prepared_request = send_prepared_request;
@@ -199,5 +204,17 @@ int load_tm( struct tm_binds *tmb)
        tmb->register_new_dlg_cb=register_new_dlg_cb;
        tmb->register_dlg_tmcb=register_dlg_tmcb;
 #endif
+#ifdef WITH_AS_SUPPORT
+       if (! (tmb->ack_local_uac=(ack_local_uac_f)find_export("ack_local_uac",
+                       NO_SCRIPT, 0))) {
+               LOG( L_ERR, LOAD_ERROR "'ack_uac' not found\n");
+               return -1;
+       }
+       if (! (tmb->t_get_canceled_ident=(t_get_canceled_ident_f)find_export(
+                       "t_get_canceled_ident", NO_SCRIPT, 0))) {
+               LOG( L_ERR, LOAD_ERROR "'t_get_canceled_ident' not found\n");
+               return -1;
+       }
+#endif
        return 1;
 }
index c488f27..0d0c4c5 100644 (file)
@@ -108,6 +108,7 @@ struct tm_binds {
        tunref_f           t_unref;
        run_failure_handlers_f run_failure_handlers;
        cancel_uacs_f      cancel_uacs;
+       cancel_all_uacs_f  cancel_all_uacs;
        prepare_request_within_f  prepare_request_within;
        send_prepared_request_f   send_prepared_request;
        enum route_mode*   route_mode;
@@ -119,6 +120,13 @@ struct tm_binds {
                            if no dlg callbacks are used/defined*/
        void* reserved2;
 #endif
+#ifdef WITH_AS_SUPPORT
+       ack_local_uac_f           ack_local_uac;
+       t_get_canceled_ident_f    t_get_canceled_ident;
+#else
+       void* reserved3;
+       void* reserved4;
+#endif
 };
 
 extern int tm_init;
index 59b555c..f91f791 100644 (file)
@@ -297,21 +297,19 @@ inline static struct dest_info *uri2dst(struct dest_info* dst,
                                return dst; /* found a good one */
                        }
                }while(dns_srv_handle_next(dns_h, err));
-               LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for \"%.*s\" "
-                                       "af %d\n", host->len, ZSW(host->s), dst->to.s.sa_family);
+               ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
+                               ZSW(host->s), dst->to.s.sa_family);
                /* try to continue */
                return dst;
        }
 #endif
        if (sip_hostport2su(&dst->to, host, parsed_uri.port_no, &dst->proto)!=0){
-               LOG(L_ERR, "ERROR: uri2dst: failed to resolve \"%.*s\"\n",
-                                       host->len, ZSW(host->s));
+               ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
                return 0;
        }
        dst->send_sock = get_send_socket(msg, &dst->to, dst->proto);
        if (dst->send_sock==0) {
-               LOG(L_ERR, "ERROR: uri2sock: no corresponding socket for af %d\n", 
-                                       dst->to.s.sa_family);
+               ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
                /* ser_error = E_NO_SOCKET;*/
                /* try to continue */
        }