1 /*
2  * Copyright (C) 2008 iptelorg GmbH
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21 
22 #include "../../core/action.h"
23 #include "../../core/script_cb.h"
24 #include "../../core/dset.h"
25 #include "../../core/cfg/cfg_struct.h"
26 #include "../../core/kemi.h"
27 
28 #include "config.h"
29 #include "sip_msg.h"
30 #include "t_reply.h"
31 #include "h_table.h"
32 #include "t_lookup.h"
33 #include "t_fwd.h"
34 #include "t_funcs.h"
35 #include "timer.h"
36 #include "t_cancel.h"
37 
38 #include "t_suspend.h"
39 
40 #include "../../core/data_lump.h"
41 #include "../../core/data_lump_rpl.h"
42 
43 
44 #define LOCK_ASYNC_CONTINUE(_t) LOCK_REPLIES(_t)
45 #define UNLOCK_ASYNC_CONTINUE(_t) UNLOCK_REPLIES(_t)
46 
47 /* Suspends the transaction for later use.
48  * Save the returned hash_index and label to get
49  * back to the SIP request processing, see the readme.
50  *
51  * Return value:
52  * 	0  - success
53  * 	<0 - failure
54  */
t_suspend(struct sip_msg * msg,unsigned int * hash_index,unsigned int * label)55 int t_suspend(struct sip_msg *msg,
56 		unsigned int *hash_index, unsigned int *label)
57 {
58 	struct cell	*t;
59 	int branch;
60 	int sip_msg_len;
61 
62 	t = get_t();
63 	if (!t || t == T_UNDEFINED) {
64 		LM_ERR("transaction has not been created yet\n");
65 		return -1;
66 	}
67 
68 	if (t->flags & T_CANCELED) {
69 		/* The transaction has already been canceled */
70 		LM_DBG("trying to suspend an already canceled transaction\n");
71 		ser_error = E_CANCELED;
72 		return 1;
73 	}
74 	if (t->uas.status >= 200) {
75 		LM_DBG("trasaction sent out a final response already - %d\n",
76 				t->uas.status);
77 		return -3;
78 	}
79 
80 	if (msg->first_line.type != SIP_REPLY) {
81 		/* send a 100 Trying reply, because the INVITE processing
82 		will probably take a long time */
83 		if (msg->REQ_METHOD==METHOD_INVITE && (t->flags&T_AUTO_INV_100)
84 			&& (t->uas.status < 100)
85 		) {
86 			if (!t_reply( t, msg , 100 ,
87 				cfg_get(tm, tm_cfg, tm_auto_inv_100_r)))
88 				LM_DBG("suspending request processing - sending 100 reply\n");
89 		}
90 
91 		if ((t->nr_of_outgoings==0) && /* if there had already been
92 			an UAC created, then the lumps were
93 			saved as well */
94 			save_msg_lumps(t->uas.request, msg)
95 		) {
96 			LM_ERR("failed to save the message lumps\n");
97 			return -1;
98 		}
99 		/* save the message flags */
100 		t->uas.request->flags = msg->flags;
101 
102 		/* add a blind UAC to let the fr timer running */
103 		if (add_blind_uac() < 0) {
104 			LM_ERR("failed to add the blind UAC\n");
105 			return -1;
106 		}
107 		/* propagate failure route to new branch
108 		 * - failure route to be executed if the branch is not continued
109 		 *   before timeout */
110 		t->uac[t->async_backup.blind_uac].on_failure = t->on_failure;
111 		t->flags |= T_ASYNC_SUSPENDED;
112 	} else {
113 		LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n");
114 		msg->msg_flags |= FL_RPL_SUSPENDED;
115 		/* this is a reply suspend find which branch */
116 
117 		if (t_check( msg  , &branch )==-1){
118 			LM_ERR("failed find UAC branch\n");
119 			return -1;
120 		}
121 		LM_DBG("found a a match with branch id [%d] - "
122 				"cloning reply message to t->uac[branch].reply\n", branch);
123 
124 		sip_msg_len = 0;
125 		t->uac[branch].reply = sip_msg_cloner( msg, &sip_msg_len );
126 
127 		if (! t->uac[branch].reply ) {
128 			LM_ERR("can't alloc' clone memory\n");
129 			return -1;
130 		}
131 		t->uac[branch].end_reply = ((char*)t->uac[branch].reply) + sip_msg_len;
132 
133 		LM_DBG("saving transaction data\n");
134 		t->uac[branch].reply->flags = msg->flags;
135 		t->flags |= T_ASYNC_SUSPENDED;
136 	}
137 
138 	*hash_index = t->hash_index;
139 	*label = t->label;
140 
141 	/* reset the continue flag to be able to suspend in a failure route */
142 	t->flags &= ~T_ASYNC_CONTINUE;
143 
144 	/* backup some extra info that can be used in continuation logic */
145 	t->async_backup.backup_route = get_route_type();
146 	t->async_backup.backup_branch = get_t_branch();
147 	t->async_backup.ruri_new = ruri_get_forking_state();
148 
149 
150 	return 0;
151 }
152 
153 /* Continues the SIP request processing previously saved by
154  * t_suspend(). The script does not continue from the same
155  * point, but a separate route block is executed instead.
156  *
157  * Return value:
158  * 	0  - success
159  * 	<0 - failure
160  */
t_continue_helper(unsigned int hash_index,unsigned int label,struct action * rtact,str * cbname,str * cbparam)161 int t_continue_helper(unsigned int hash_index, unsigned int label,
162 		struct action *rtact, str *cbname, str *cbparam)
163 {
164 	tm_cell_t *t;
165 	tm_cell_t *backup_T = T_UNDEFINED;
166 	int backup_T_branch = T_BR_UNDEFINED;
167 	sip_msg_t *faked_req;
168 	sip_msg_t *brpl = NULL;
169 	void *erpl = NULL;
170 	int faked_req_len = 0;
171 	struct cancel_info cancel_data;
172 	int	branch;
173 	struct ua_client *uac =NULL;
174 	int	ret;
175 	int cb_type;
176 	int msg_status;
177 	int last_uac_status;
178 	int reply_status;
179 	int do_put_on_wait;
180 	struct hdr_field *hdr, *prev = 0, *tmp = 0;
181 	int route_type_bk;
182 	sr_kemi_eng_t *keng = NULL;
183 	str evname = str_init("tm:continue");
184 
185 	cfg_update();
186 
187 	backup_T = get_t();
188 	backup_T_branch = get_t_branch();
189 
190 	if (t_lookup_ident_filter(&t, hash_index, label, 1) < 0) {
191 		set_t(backup_T, backup_T_branch);
192 		LM_WARN("active transaction not found\n");
193 		return -1;
194 	}
195 
196 	if (!(t->flags & T_ASYNC_SUSPENDED)) {
197 		LM_WARN("transaction is not suspended [%u:%u]\n", hash_index, label);
198 		set_t(backup_T, backup_T_branch);
199 		return -2;
200 	}
201 
202 	if (t->flags & T_CANCELED) {
203 		t->flags &= ~T_ASYNC_SUSPENDED;
204 		/* The transaction has already been canceled,
205 		 * needless to continue */
206 		UNREF(t); /* t_unref would kill the transaction */
207 		/* reset T as we have no working T anymore */
208 		set_t(backup_T, backup_T_branch);
209 		return 1;
210 	}
211 
212 	/* The transaction has to be locked to protect it
213 	 * form calling t_continue() multiple times simultaneously */
214 	LOCK_ASYNC_CONTINUE(t);
215 
216 	t->flags |= T_ASYNC_CONTINUE;   /* we can now know anywhere in kamailio
217 					 * that we are executing post a suspend */
218 
219 	/* transaction is no longer suspended, resetting the SUSPEND flag */
220 	t->flags &= ~T_ASYNC_SUSPENDED;
221 
222 	/* which route block type were we in when we were suspended */
223 	cb_type =  FAILURE_CB_TYPE;
224 	switch (t->async_backup.backup_route) {
225 		case REQUEST_ROUTE:
226 			cb_type = FAILURE_CB_TYPE;
227 			break;
228 		case FAILURE_ROUTE:
229 			cb_type = FAILURE_CB_TYPE;
230 			break;
231 		case TM_ONREPLY_ROUTE:
232 			cb_type = ONREPLY_CB_TYPE;
233 			break;
234 		case BRANCH_ROUTE:
235 			cb_type = FAILURE_CB_TYPE;
236 			break;
237 	}
238 
239 	if(t->async_backup.backup_route != TM_ONREPLY_ROUTE) {
240 		/* resume processing of a sip request */
241 		/* get the branch of the blind UAC setup during suspend */
242 		branch = t->async_backup.blind_uac;
243 		if (branch >= 0) {
244 			stop_rb_timers(&t->uac[branch].request);
245 
246 			if (t->uac[branch].last_received != 0) {
247 				/* Either t_continue() has already been
248 				* called or the branch has already timed out.
249 				* Needless to continue. */
250 				t->flags &= ~T_ASYNC_CONTINUE;
251 				UNLOCK_ASYNC_CONTINUE(t);
252 				UNREF(t); /* t_unref would kill the transaction */
253 				set_t(backup_T, backup_T_branch);
254 				return 1;
255 			}
256 
257 			/* Set last_received to something >= 200,
258 			 * the actual value does not matter, the branch
259 			 * will never be picked up for response forwarding.
260 			 * If last_received is lower than 200,
261 			 * then the branch may tried to be cancelled later,
262 			 * for example when t_reply() is called from
263 			 * a failure route => deadlock, because both
264 			 * of them need the reply lock to be held. */
265 			t->uac[branch].last_received=500;
266 			if(t->uac[branch].reply!=NULL) {
267 				LM_WARN("reply (%p) already set for suspended transaction"
268 						" (branch: %d)\n",
269 						t->uac[branch].reply, branch);
270 			} else {
271 				/* set it as a faked reply */
272 				t->uac[branch].reply=FAKED_REPLY;
273 			}
274 			uac = &t->uac[branch];
275 		}
276 		/* else
277 			Not a huge problem, fr timer will fire, but CANCEL
278 			will not be sent. last_received will be set to 408. */
279 
280 		/* We should not reset kr here to 0 as it's quite possible before continuing the dev. has correctly set the
281 		 * kr by, for example, sending a transactional reply in code - resetting here will cause a dirty log message
282 		 * "WARNING: script writer didn't release transaction" to appear in log files. TODO: maybe we need to add
283 		 * a special kr for async?
284 		 * reset_kr();
285 		 */
286 
287 		/* fake the request and the environment, like in failure_route */
288 		faked_req = fake_req(t->uas.request, 0 /* extra flags */, uac,
289 			&faked_req_len);
290 		if (faked_req==NULL) {
291 			LM_ERR("building fake_req failed\n");
292 			ret = -1;
293 			goto kill_trans;
294 		}
295 		faked_env( t, faked_req, 1);
296 
297 		route_type_bk = get_route_type();
298 		set_route_type(FAILURE_ROUTE);
299 		/* execute the pre/post -script callbacks based on original route block */
300 		if (exec_pre_script_cb(faked_req, cb_type)>0) {
301 			if(rtact!=NULL) {
302 				if (run_top_route(rtact, faked_req, 0)<0) {
303 					LM_ERR("failure inside run_top_route\n");
304 				}
305 			} else {
306 				if(cbname!=NULL && cbname->s!=NULL) {
307 					keng = sr_kemi_eng_get();
308 					if(keng!=NULL) {
309 						if(cbparam && cbparam->s) {
310 							evname = *cbparam;
311 						}
312 						if(sr_kemi_route(keng, faked_req, FAILURE_ROUTE, cbname,
313 								&evname)<0) {
314 							LM_ERR("error running event route kemi callback\n");
315 						}
316 					} else {
317 						LM_DBG("event callback (%.*s) set, but no cfg engine\n",
318 								cbname->len, cbname->s);
319 					}
320 				} else {
321 					LM_WARN("no continue callback\n");
322 				}
323 			}
324 			exec_post_script_cb(faked_req, cb_type);
325 		}
326 		set_route_type(route_type_bk);
327 
328 		/* TODO: save_msg_lumps should clone the lumps to shm mem */
329 
330 		/* restore original environment */
331 		faked_env( t, 0, 1);
332 		/* update the flags */
333 		t->uas.request->flags = faked_req->flags;
334 		/* free the fake msg */
335 		free_faked_req(faked_req, faked_req_len);
336 
337 
338 		if (t->uas.status < 200) {
339 			/* No final reply has been sent yet.
340 			* Check whether or not there is any pending branch.
341 			*/
342 			for (	branch = 0;
343 				branch < t->nr_of_outgoings;
344 				branch++
345 			) {
346 				if (t->uac[branch].last_received < 200)
347 					break;
348 			}
349 
350 			if (branch == t->nr_of_outgoings) {
351 			/* There is not any open branch so there is
352 			 * no chance that a final response will be received. */
353 				ret = 0;
354 				goto kill_trans;
355 			}
356 		}
357 
358 	} else {
359 		/* resume processing of a sip response */
360 		branch = t->async_backup.backup_branch;
361 
362 		init_cancel_info(&cancel_data);
363 
364 		LM_DBG("continuing from a suspended reply"
365 				" - resetting the suspend branch flag\n");
366 
367 		if (t->uac[branch].reply) {
368 			t->uac[branch].reply->msg_flags &= ~FL_RPL_SUSPENDED;
369 		} else {
370 			LM_WARN("no reply in t_continue for branch. not much we can do\n");
371 			return 0;
372 		}
373 		if (t->uas.request) t->uas.request->msg_flags&= ~FL_RPL_SUSPENDED;
374 
375 		faked_env( t, t->uac[branch].reply, 1);
376 
377 		if (exec_pre_script_cb(t->uac[branch].reply, cb_type)>0) {
378 			if(rtact!=NULL) {
379 				if (run_top_route(rtact, t->uac[branch].reply, 0)<0){
380 					LM_ERR("Error in run_top_route\n");
381 				}
382 			} else {
383 				if(cbname!=NULL && cbname->s!=NULL) {
384 					keng = sr_kemi_eng_get();
385 					if(keng!=NULL) {
386 						if(cbparam && cbparam->s) {
387 							evname = *cbparam;
388 						}
389 						if(sr_kemi_route(keng, t->uac[branch].reply,
390 									TM_ONREPLY_ROUTE, cbname, &evname)<0) {
391 							LM_ERR("error running event route kemi callback\n");
392 						}
393 					} else {
394 						LM_DBG("event callback (%.*s) set, but no cfg engine\n",
395 								cbname->len, cbname->s);
396 					}
397 				} else {
398 					LM_WARN("no continue callback\n");
399 				}
400 			}
401 			exec_post_script_cb(t->uac[branch].reply, cb_type);
402 		}
403 
404 		LM_DBG("restoring previous environment\n");
405 		faked_env( t, 0, 1);
406 
407 		/*lock transaction replies - will be unlocked when reply is relayed*/
408 		LOCK_REPLIES( t );
409 		if ( is_local(t) ) {
410 			LM_DBG("t is local - sending reply with status code: [%d]\n",
411 					t->uac[branch].reply->first_line.u.reply.statuscode);
412 			reply_status = local_reply( t, t->uac[branch].reply, branch,
413 					t->uac[branch].reply->first_line.u.reply.statuscode,
414 					&cancel_data );
415 			if (reply_status == RPS_COMPLETED) {
416 				/* no more UAC FR/RETR (if I received a 2xx, there may
417 				* be still pending branches ...
418 				*/
419 				cleanup_uac_timers( t );
420 				if (is_invite(t)) cancel_uacs(t, &cancel_data, F_CANCEL_B_KILL);
421 				/* There is no need to call set_final_timer because we know
422 				* that the transaction is local */
423 				put_on_wait(t);
424 			}else if (unlikely(cancel_data.cancel_bitmap)){
425 				/* cancel everything, even non-INVITEs (e.g in case of 6xx), use
426 				* cancel_b_method for canceling unreplied branches */
427 				cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
428 			}
429 
430 		} else {
431 			LM_DBG("t is not local - relaying reply with status code: [%d]\n",
432 					t->uac[branch].reply->first_line.u.reply.statuscode);
433 			do_put_on_wait = 0;
434 			if(t->uac[branch].reply->first_line.u.reply.statuscode>=200){
435 				do_put_on_wait = 1;
436 			}
437 			reply_status=relay_reply( t, t->uac[branch].reply, branch,
438 					t->uac[branch].reply->first_line.u.reply.statuscode,
439 					&cancel_data, do_put_on_wait );
440 			if (reply_status == RPS_COMPLETED) {
441 				/* no more UAC FR/RETR (if I received a 2xx, there may
442 				be still pending branches ...
443 				*/
444 				cleanup_uac_timers( t );
445 				/* 2xx is a special case: we can have a COMPLETED request
446 				* with branches still open => we have to cancel them */
447 				if (is_invite(t) && cancel_data.cancel_bitmap)
448 					cancel_uacs( t, &cancel_data,  F_CANCEL_B_KILL);
449 				/* FR for negative INVITES, WAIT anything else */
450 				/* Call to set_final_timer is embedded in relay_reply to avoid
451 				* race conditions when reply is sent out and an ACK to stop
452 				* retransmissions comes before retransmission timer is set.*/
453 			}else if (unlikely(cancel_data.cancel_bitmap)){
454 				/* cancel everything, even non-INVITEs (e.g in case of 6xx), use
455 				* cancel_b_method for canceling unreplied branches */
456 				cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
457 			}
458 
459 		}
460 		t->uac[branch].request.flags|=F_RB_REPLIED;
461 
462 		if (reply_status==RPS_ERROR){
463 			goto done;
464 		}
465 
466 		/* update FR/RETR timers on provisional replies */
467 
468 		msg_status=t->uac[branch].reply->REPLY_STATUS;
469 		last_uac_status=t->uac[branch].last_received;
470 
471 		if (is_invite(t) && msg_status<200 &&
472 			( cfg_get(tm, tm_cfg, restart_fr_on_each_reply) ||
473 			( (last_uac_status<msg_status) &&
474 			((msg_status>=180) || (last_uac_status==0)) )
475 		) ) { /* provisional now */
476 			restart_rb_fr(& t->uac[branch].request, t->fr_inv_timeout);
477 			t->uac[branch].request.flags|=F_RB_FR_INV; /* mark fr_inv */
478 		}
479 
480 	}
481 
482 done:
483 	t->flags &= ~T_ASYNC_CONTINUE;
484 	if(t->async_backup.backup_route == TM_ONREPLY_ROUTE) {
485 		/* response handling */
486 		/* backup branch reply to free it later and reset it here under lock */
487 		brpl = t->uac[branch].reply;
488 		erpl = (void*)t->uac[branch].end_reply;
489 		t->uac[branch].reply = 0;
490 		t->uac[branch].end_reply = 0;
491 	}
492 	UNLOCK_ASYNC_CONTINUE(t);
493 
494 	if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
495 		/* request handling */
496 		/* unref the transaction */
497 		t_unref(t->uas.request);
498 	} else {
499 		/* response handling */
500 		tm_ctx_set_branch_index(T_BR_UNDEFINED);
501 		if(brpl) {
502 			/* unref the transaction */
503 			t_unref(brpl);
504 			LM_DBG("Freeing earlier cloned reply\n");
505 
506 			/* free lumps that were added during reply processing */
507 			del_nonshm_lump( &(brpl->add_rm) );
508 			del_nonshm_lump( &(brpl->body_lumps) );
509 			del_nonshm_lump_rpl( &(brpl->reply_lump) );
510 
511 			/* free header's parsed structures that were added */
512 			for( hdr=brpl->headers ; hdr ; hdr=hdr->next ) {
513 				if (hdr->parsed && hdr_allocs_parse(hdr) &&
514 						(hdr->parsed<(void*)brpl ||
515 						(erpl && hdr->parsed>=(void*)erpl))) {
516 					clean_hdr_field(hdr);
517 					hdr->parsed = 0;
518 				}
519 			}
520 
521 			/* now go through hdr fields themselves
522 			 * and remove the pkg allocated space */
523 			hdr = brpl->headers;
524 			while (hdr) {
525 				if ( hdr && ((void*)hdr<(void*)brpl ||
526 						(void*)hdr>=(void*)erpl)) {
527 					/* this header needs to be freed and removed form the list */
528 					if (!prev) {
529 						brpl->headers = hdr->next;
530 					} else {
531 						prev->next = hdr->next;
532 					}
533 					tmp = hdr;
534 					hdr = hdr->next;
535 					pkg_free(tmp);
536 				} else {
537 					prev = hdr;
538 					hdr = hdr->next;
539 				}
540 			}
541 			sip_msg_free(brpl);
542 		}
543 	}
544 
545 	set_t(backup_T, backup_T_branch);
546 	return 0;
547 
548 kill_trans:
549 	/* The script has hopefully set the error code. If not,
550 	 * let us reply with a default error. */
551 	if ((kill_transaction_unsafe(t,
552 				tm_error ? tm_error : E_UNSPEC)) <=0) {
553 		LM_ERR("reply generation failed\n");
554 		/* The transaction must be explicitely released,
555 		 * no more timer is running */
556 		t->flags &= ~T_ASYNC_CONTINUE;
557 		UNLOCK_ASYNC_CONTINUE(t);
558 		t_release_transaction(t);
559 	} else {
560 		t->flags &= ~T_ASYNC_CONTINUE;
561 		UNLOCK_ASYNC_CONTINUE(t);
562 	}
563 
564 	/* unref the transaction */
565 	if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
566 		/* request handling */
567 		t_unref(t->uas.request);
568 	} else {
569 		/* response handling */
570 		t_unref(t->uac[branch].reply);
571 	}
572 	set_t(backup_T, backup_T_branch);
573 	return ret;
574 }
575 
t_continue(unsigned int hash_index,unsigned int label,struct action * route)576 int t_continue(unsigned int hash_index, unsigned int label,
577 		struct action *route)
578 {
579 	return t_continue_helper(hash_index, label, route, NULL, NULL);
580 }
581 
t_continue_cb(unsigned int hash_index,unsigned int label,str * cbname,str * cbparam)582 int t_continue_cb(unsigned int hash_index, unsigned int label,
583 		str *cbname, str *cbparam)
584 {
585 	return t_continue_helper(hash_index, label, NULL, cbname, cbparam);
586 }
587 
588 /* Revoke the suspension of the SIP request, i.e.
589  * cancel the fr timer of the blind uac.
590  * This function can be called when something fails
591  * after t_suspend() has already been executed in the same
592  * process, and it turns out that the transaction should
593  * not have been suspended.
594  *
595  * Return value:
596  * 	0  - success
597  * 	<0 - failure
598  */
t_cancel_suspend(unsigned int hash_index,unsigned int label)599 int t_cancel_suspend(unsigned int hash_index, unsigned int label)
600 {
601 	struct cell	*t;
602 	int	branch;
603 
604 	t = get_t();
605 	if (!t || t == T_UNDEFINED) {
606 		LM_ERR("no active transaction\n");
607 		return -1;
608 	}
609 	/* Only to double-check the IDs */
610 	if ((t->hash_index != hash_index)
611 		|| (t->label != label)
612 	) {
613 		LM_ERR("transaction id mismatch\n");
614 		return -1;
615 	}
616 
617 	if(t->async_backup.backup_route != TM_ONREPLY_ROUTE){
618 		/* The transaction does not need to be locked because this
619 		* function is either executed from the original route block
620 		* or from failure route which already locks */
621 
622 		reset_kr(); /* the blind UAC of t_suspend has set kr */
623 
624 		/* Try to find the blind UAC, and cancel its fr timer.
625 		* We assume that the last blind uac called this function. */
626 		for (	branch = t->nr_of_outgoings-1;
627 			branch >= 0 && t->uac[branch].request.buffer;
628 			branch--);
629 
630 		if (branch >= 0) {
631 			stop_rb_timers(&t->uac[branch].request);
632 			/* Set last_received to something >= 200,
633 			* the actual value does not matter, the branch
634 			* will never be picked up for response forwarding.
635 			* If last_received is lower than 200,
636 			* then the branch may tried to be cancelled later,
637 			* for example when t_reply() is called from
638 			* a failure rute => deadlock, because both
639 			* of them need the reply lock to be held. */
640 			t->uac[branch].last_received=500;
641 		} else {
642 			/* Not a huge problem, fr timer will fire, but CANCEL
643 			will not be sent. last_received will be set to 408. */
644 			return -1;
645 		}
646 	}else{
647 		branch = t->async_backup.backup_branch;
648 
649 		LM_DBG("This is a cancel suspend for a response\n");
650 
651 		t->uac[branch].reply->msg_flags &= ~FL_RPL_SUSPENDED;
652 		if (t->uas.request) t->uas.request->msg_flags&= ~FL_RPL_SUSPENDED;
653 	}
654 
655 	return 0;
656 }
657 
658