t_check_status() checks also the blind UACs if t_pick_branch()
authorMiklos Tirpak <miklos@iptel.org>
Wed, 28 Jan 2009 14:49:55 +0000 (14:49 +0000)
committerMiklos Tirpak <miklos@iptel.org>
Wed, 28 Jan 2009 14:49:55 +0000 (14:49 +0000)
fails to determine the picked branch in failure_route.
Closes SER-434.

modules/tm/t_reply.c
modules/tm/t_reply.h
modules/tm/tm.c

index 84e75ad..cdcd029 100644 (file)
@@ -937,6 +937,36 @@ int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
        return best_b;
 }
 
+/* The same as t_pick_branch(), but allows also
+ * blind branches to be picked up.
+ * This function should be used only in failure_route
+ * to check which response has been 
+ * picked up by t_pick_branch().
+ * returns:
+ * 0..X ... branch number
+ * -1   ... error
+ * -2   ... can't decide yet -- incomplete branches present
+ */
+int t_pick_branch_blind(struct cell *t, int *res_code)
+{
+       int best_b, best_s, b;
+
+       best_b=-1; best_s=0;
+       for ( b=0; b<t->nr_of_outgoings ; b++ ) {
+               /* there is still an unfinished UAC transaction; wait now! */
+               if ( t->uac[b].last_received<200 )
+                       return -2;
+               /* if reply is null => t_send_branch "faked" reply, skip over it */
+               if ( t->uac[b].reply && 
+                               get_prio(t->uac[b].last_received)<get_prio(best_s) ) {
+                       best_b = b;
+                       best_s = t->uac[b].last_received;
+               }
+       } /* find lowest branch */
+       
+       *res_code=best_s;
+       return best_b;
+}
 
 /* flag indicating whether it is requested
  * to drop the already saved replies or not */
index 4b3ebab..7732c54 100644 (file)
@@ -147,6 +147,8 @@ 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);
+/* checks the selected branch from failure_route */
+int t_pick_branch_blind(struct cell *t, int *res_code);
 
 /* drops all the replies to make sure
  * that none of them is picked up again
index e053f6e..ef8c9af 100644 (file)
@@ -791,7 +791,7 @@ static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
        struct cell *t;
        char *status, *s = NULL;
        char backup;
-       int lowest_status, n;
+       int lowest_status, n, ret;
        fparam_t* fp;
        regex_t* re = NULL;
        str tmp;
@@ -850,7 +850,16 @@ static int t_check_status(struct sip_msg* msg, char *p1, char *foo)
 
        case MODE_ONFAILURE:
                /* use the status of the winning reply */
-               if (t_pick_branch( -1, 0, t, &lowest_status)<0 ) {
+               ret = t_pick_branch( -1, 0, t, &lowest_status);
+               if (ret == -1) {
+                       /* t_pick_branch() retuns error also when there are only
+                        * blind UACs. Let us give it another chance including the
+                        * blind branches. */
+                       LOG(L_DBG, "DEBUG: t_check_status: t_pick_branch returned error, "
+                               "trying t_pick_branch_blind\n");
+                       ret = t_pick_branch_blind(t, &lowest_status);
+               }
+               if (ret < 0) {
                        LOG(L_CRIT,"BUG:t_check_status: t_pick_branch failed to get "
                                " a final response in MODE_ONFAILURE\n");
                        goto error;