Sfoglia il codice sorgente

t_check_status() checks also the blind UACs if t_pick_branch()
fails to determine the picked branch in failure_route.
Closes SER-434.

Miklos Tirpak 16 anni fa
parent
commit
611a9ba950
3 ha cambiato i file con 43 aggiunte e 2 eliminazioni
  1. 30 0
      modules/tm/t_reply.c
  2. 2 0
      modules/tm/t_reply.h
  3. 11 2
      modules/tm/tm.c

+ 30 - 0
modules/tm/t_reply.c

@@ -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 */

+ 2 - 0
modules/tm/t_reply.h

@@ -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

+ 11 - 2
modules/tm/tm.c

@@ -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;