浏览代码

tm: t_append_branches extra checks for cancelled transaction

fcabiddu 11 年之前
父节点
当前提交
ed1a5476e8
共有 1 个文件被更改,包括 31 次插入0 次删除
  1. 31 0
      modules/tm/t_append_branches.c

+ 31 - 0
modules/tm/t_append_branches.c

@@ -63,6 +63,7 @@ int t_append_branches(void) {
 	flag_t bflags = 0;
 	int new_branch, branch_ret, lowest_ret;
 	branch_bm_t	added_branches;
+	int replies_locked = 0;
 
 	t = get_t();
 	if(t == NULL)
@@ -73,6 +74,9 @@ int t_append_branches(void) {
 
 	LM_DBG("transaction %u:%u in status %d\n", t->hash_index, t->label, t->uas.status);
 
+	/* test if transaction has already been canceled */
+	if (t->flags & T_CANCELED) goto canceled;
+
 	if ((t->uas.status >= 200 && t->uas.status<=399)
 			|| ((t->uas.status >= 600 && t->uas.status)
 				&& !(t->flags & (T_6xx | T_DISABLE_6xx))) ) {
@@ -82,6 +86,7 @@ int t_append_branches(void) {
 
 	/* set the lock on the transaction here */
 	LOCK_REPLIES(t);
+	replies_locked = 1;
 	outgoings = t->nr_of_outgoings;
 	orig_msg = t->uas.request;
 
@@ -125,6 +130,10 @@ int t_append_branches(void) {
 					&path, 0, si, orig_msg->fwd_send_flags,
 					orig_msg->rcv.proto, (dst_uri.len)?-1:UAC_SKIP_BR_DST_F, &instance,
 					&ruid, &location_ua);
+
+		/* test if cancel was received meanwhile */
+		if (t->flags & T_CANCELED) goto canceled;
+
 		if (new_branch>=0)
 			added_branches |= 1<<new_branch;
 		else
@@ -143,6 +152,7 @@ int t_append_branches(void) {
 		if(lowest_ret!=E_CFG)
 			LOG(L_ERR, "ERROR: t_append_branch: failure to add branches\n");
 		ser_error=lowest_ret;
+		replies_locked = 0;
 		UNLOCK_REPLIES(t);
 		return lowest_ret;
 	}
@@ -175,12 +185,33 @@ int t_append_branches(void) {
 		ser_error=E_SEND;
 		/* else return the last error (?) */
 		/* the caller should take care and delete the transaction */
+		replies_locked = 0;
 		UNLOCK_REPLIES(t);
 		return -1;
 	}
 
 	ser_error=0; /* clear branch send errors, we have overall success */
 	set_kr(REQ_FWDED);
+	replies_locked = 0;
 	UNLOCK_REPLIES(t);
 	return 1;
+
+canceled:
+	DBG("t_append_branches: cannot append branches to a canceled transaction\n");
+	/* reset processed branches */
+	clear_branches();
+	/* restore backup flags from initial env */
+	setbflagsval(0, backup_bflags);
+	/* update message flags, if changed in branch route */
+	t->uas.request->flags = orig_msg->flags;
+	/* if needed unlock transaction's replies */
+	if (likely(replies_locked)) {
+		/* restore the number of outgoing branches
+		 * since new branches have not been completed */
+		t->nr_of_outgoings = outgoings;
+		replies_locked = 0;
+		UNLOCK_REPLIES(t);
+	}
+	ser_error=E_CANCELED;
+	return -1;
 }