diff --git a/modules/tm/doc/api.xml b/modules/tm/doc/api.xml
index 2a627ab..7aeea5d 100644
--- a/modules/tm/doc/api.xml
+++ b/modules/tm/doc/api.xml
@@ -262,5 +262,127 @@ end of body
 	    </itemizedlist>
 	    <para>Return value: 0 - success, &lt;0 - error.</para>
 	</section>
+        
+        <section id="t_suspend_reply">
+	    <title>
+	    	<function>int t_suspend_reply(struct sip_msg *msg,
+			unsigned int *hash_index, unsigned int *label)</function>
+	    </title>
+	    <para>
+	    	For programmatic use only.
+                This function is the equivalent of t_continue, but used to 
+                suspend on SIP responses.
+		This function together with t_continue_reply() can be used to
+		implement asynchronous actions on responses: t_suspend() saves 
+                the transaction, returns its identifiers, and t_continue() continues the
+		SIP response processing. (The response processing does not continue
+		from the same point in the script, a separate route block defined
+		by the parameter of t_continue_reply() is executed instead. The reply lock
+		is held during the route block execution.)
+		FR timer is ticking while the transaction is suspended, and the
+		transaction's failure route is executed if t_continue() is not
+		called in time.
+	    </para>
+	    <para>Meaning of the parameters is as follows:</para>
+	    <itemizedlist>
+		<listitem>
+		    <para><emphasis>msg</emphasis> - SIP message pointer.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para><emphasis>hash_index</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para><emphasis>label</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    <para>Return value: 0 - success, &lt;0 - error.</para>
+	    <para>
+		Usage: Allocate a memory block for storing the transaction identifiers
+		(hash_index and label), and for storing also any variable related to
+		the async query. Before calling t_suspend(), register for the following
+		callbacks, and pass the pointer to the allocated shared memory as
+		a parameter: TMCB_ON_FAILURE, TMCB_DESTROY, and TMCB_E2ECANCEL_IN
+		(in case of INVITE transaction). The async operation can be
+		cancelled, if it is still pending, when TMCB_ON_FAILURE or
+		TMCB_E2ECANCEL_IN is called. TMCB_DESTROY is suitable to free
+		the shared memory allocated for the async and SIP transaction identifiers.
+		Once the async query result is available call t_continue(), see below.
+		The SIP transaction must exist before calling t_suspend(), and the module
+		function calling t_suspend() should return 0 to make sure that the script
+		processing does not continue.
+	    </para>
+	</section>
+
+	<section id="t_continue_reply">
+	    <title>
+		<function>int t_continue_reply(unsigned int hash_index, unsigned int label,
+		                struct action *route, int branch)</function>
+	    </title>
+	    <para>
+		For programmatic use only.
+                This function is the equivalent of t_continue but used to 
+                suspend on SIP responses.
+		This function is the pair of t_suspend_reply(), and is supposed
+		to be called when the asynchronous query result is available.
+		The function executes a route block with the saved SIP message.
+                The calling application passes in the branch of the suspended 
+                reply when wanting to continue.
+	    </para>
+	    <para>Meaning of the parameters is as follows:</para>
+	    <itemizedlist>
+		<listitem>
+		    <para><emphasis>hash_index</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para><emphasis>label</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para><emphasis>route</emphasis> - route block to execute.
+		    </para>
+		</listitem>
+                <listitem>
+		    <para><emphasis>branch</emphasis> - reply branch to resume.
+		    </para>
+		</listitem>
+	    </itemizedlist>
+	    <para>Return value: 0 - success, &lt;0 - error.</para>
+	</section>
+    
+	<section id="t_cancel_suspend_reply">
+	    <title>
+	    	<function>int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, branch)</function>
+	    </title>
+	    <para>
+	    	For programmatic use only.
+                This function is the equivalent of t_cancel_suspend but for SIP
+                responses.
+		This function is for revoking t_suspend_reply() from the
+		same process as it was executed before. t_cancel_suspend_reply() can be
+		used when something fails after t_suspend_reply() has already been executed
+		and it turns out that the transcation should not have been
+		suspended. The function cancels the FR timer of the transacation.
+	    </para>
+	    <para>Meaning of the parameters is as follows:</para>
+	    <itemizedlist>
+		<listitem>
+		    <para><emphasis>hash_index</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+		<listitem>
+		    <para><emphasis>label</emphasis> - transaction identifier.
+		    </para>
+		</listitem>
+                <listitem>
+		    <para><emphasis>branch</emphasis> - reply branch that was suspended.
+		    </para>
+                </listitem>
+	    </itemizedlist>
+	    <para>Return value: 0 - success, &lt;0 - error.</para>
+	</section>
     </section>
 </section>
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
index 97b813f..4acb704 100644
--- a/modules/tm/t_reply.c
+++ b/modules/tm/t_reply.c
@@ -806,6 +806,199 @@ static int _reply( struct cell *trans, struct sip_msg* p_msg,
 	}
 }
 
+int fake_resp(struct sip_msg *faked_resp,
+		struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac)
+{
+        /* on_failure_reply faked msg now copied from shmem msg (as opposed
+	 * to zero-ing) -- more "read-only" actions (exec in particular) will
+	 * work from reply_route as they will see msg->from, etc.; caution,
+	 * rw actions may append some pkg stuff to msg, which will possibly be
+	 * never released (shmem is released in a single block) */
+	memcpy( faked_resp, shmem_msg, sizeof(struct sip_msg));
+        
+	/* if we set msg_id to something different from current's message
+	 * id, the first t_fork will properly clean new branch URIs */
+	faked_resp->id=shmem_msg->id-1;
+	/* msg->parsed_uri_ok must be reset since msg_parsed_uri is
+	 * not cloned (and cannot be cloned) */
+	faked_resp->parsed_uri_ok = 0;
+	
+	faked_resp->msg_flags|=extra_flags; /* set the extra tm flags */
+        
+	/* dst_uri can change ALSO!!! -- make a private copy */
+	if (shmem_msg->dst_uri.s!=0 && shmem_msg->dst_uri.len!=0) {
+		faked_resp->dst_uri.s=pkg_malloc(shmem_msg->dst_uri.len+1);
+		if (!faked_resp->dst_uri.s) {
+			LOG(L_ERR, "ERROR: fake_resp: no uri/pkg mem\n");
+			goto error01;
+		}
+		faked_resp->dst_uri.len=shmem_msg->dst_uri.len;
+		memcpy( faked_resp->dst_uri.s, shmem_msg->dst_uri.s,
+			faked_resp->dst_uri.len);
+		faked_resp->dst_uri.s[faked_resp->dst_uri.len]=0;
+	}else{
+		/* in case len==0, but shmem_msg->dst_uri.s!=0 (extra safety) */
+		faked_resp->dst_uri.s = 0;
+	}
+	/* new_uri can change -- make a private copy */
+	if (shmem_msg->new_uri.s!=0 && shmem_msg->new_uri.len!=0) {
+		faked_resp->new_uri.s=pkg_malloc(shmem_msg->new_uri.len+1);
+		if (!faked_resp->new_uri.s) {
+			LOG(L_ERR, "ERROR: fake_resp: no uri/pkg mem\n");
+			goto error00;
+		}
+		faked_resp->new_uri.len=shmem_msg->new_uri.len;
+		memcpy( faked_resp->new_uri.s, shmem_msg->new_uri.s,
+			faked_resp->new_uri.len);
+		faked_resp->new_uri.s[faked_resp->new_uri.len]=0;
+	}else{
+		/* in case len==0, but shmem_msg->new_uri.s!=0  (extra safety)*/
+		faked_resp->new_uri.s = 0;
+	}
+	if(uac) setbflagsval(0, uac->branch_flags);
+	else setbflagsval(0, 0);
+        
+	return 1;
+error00:
+	if (faked_resp->dst_uri.s) {
+		pkg_free(faked_resp->dst_uri.s);
+		faked_resp->dst_uri.s = 0;
+	}
+error01:
+	return 0;
+}
+
+void free_faked_resp(struct sip_msg *faked_resp, struct cell *t, int branch)
+{
+        struct hdr_field *hdr;
+
+	if (faked_resp->new_uri.s) {
+		pkg_free(faked_resp->new_uri.s);
+		faked_resp->new_uri.s = 0;
+	}
+
+	if (faked_resp->dst_uri.s) {
+		pkg_free(faked_resp->dst_uri.s);
+		faked_resp->dst_uri.s = 0;
+	}
+
+	/* free all types of lump that were added in failure handlers */
+	del_nonshm_lump( &(faked_resp->add_rm) );
+	del_nonshm_lump( &(faked_resp->body_lumps) );
+	del_nonshm_lump_rpl( &(faked_resp->reply_lump) );
+
+	/* free header's parsed structures that were added by failure handlers */
+	for( hdr=faked_resp->headers ; hdr ; hdr=hdr->next ) {
+		if ( hdr->parsed && hdr_allocs_parse(hdr) &&
+		(hdr->parsed<(void*)t->uac[branch].reply)) {
+			/* header parsed filed doesn't point inside uas.request memory
+			 * chunck -> it was added by failure funcs.-> free it as pkg */
+			DBG("DBG:free_faked_resp: removing hdr->parsed %d\n",
+					hdr->type);
+			
+                        clean_hdr_field(hdr);
+			hdr->parsed = 0;
+		}
+	}
+	/* free parsed body added by failure handlers */
+	if (faked_resp->body) {
+		if(faked_resp->body->free)
+			faked_resp->body->free(&faked_resp->body);
+		faked_resp->body = 0;
+	}
+}
+
+/** create or restore a "fake environment" for running a failure_route.
+ *if msg is set -> it will fake the env. vars conforming with the msg; if NULL
+ * the env. will be restore to original.
+ * Side-effect: mark_ruri_consumed().
+ */
+void faked_env_resp( struct cell *t, struct sip_msg *msg)
+{
+        static int backup_route_type;
+	static struct cell *backup_t;
+	static int backup_branch;
+	static unsigned int backup_msgid;
+	static avp_list_t* backup_user_from, *backup_user_to;
+	static avp_list_t* backup_domain_from, *backup_domain_to;
+	static avp_list_t* backup_uri_from, *backup_uri_to;
+#ifdef WITH_XAVP
+	static sr_xavp_t **backup_xavps;
+#endif
+	static struct socket_info* backup_si;
+
+	static struct lump *backup_add_rm;
+	static struct lump *backup_body_lumps;
+	static struct lump_rpl *backup_reply_lump;
+
+
+	if (msg) {
+		/* remember we are back in request processing, but process
+		 * a shmem-ed replica of the request; advertise it in route type;
+		 * for example t_reply needs to know that
+		 */
+		backup_route_type=get_route_type();
+                
+                /*This is reponse so route type is TM_ONREPLY_ROUTE*/
+		set_route_type(TM_ONREPLY_ROUTE);
+		/* don't bother backing up ruri state, since failure route
+		   is called either on reply or on timer and in both cases
+		   the ruri should not be used again for forking */
+		ruri_mark_consumed(); /* in failure route we assume ruri should not be used again for forking */
+		/* also, tm actions look in beginning whether transaction is
+		 * set -- whether we are called from a reply-processing
+		 * or a timer process, we need to set current transaction;
+		 * otherwise the actions would attempt to look the transaction
+		 * up (unnecessary overhead, refcounting)
+		 */
+		/* backup */
+		backup_t=get_t();
+		backup_branch=get_t_branch();
+		backup_msgid=global_msg_id;
+		/* fake transaction and message id */
+		global_msg_id=msg->id;
+		set_t(t, T_BR_UNDEFINED);
+		/* make available the avp list from transaction */
+
+		backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from );
+		backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to );
+		backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from );
+		backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to );
+		backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from );
+		backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to );
+#ifdef WITH_XAVP
+		backup_xavps = xavp_set_list(&t->xavps_list);
+#endif
+		/* set default send address to the saved value */
+		backup_si=bind_address;
+		bind_address=t->uac[0].request.dst.send_sock;
+		/* backup lump lists */
+		backup_add_rm = t->uas.request->add_rm;
+		backup_body_lumps = t->uas.request->body_lumps;
+		backup_reply_lump = t->uas.request->reply_lump;
+	} else {
+		/* restore original environment */
+		set_t(backup_t, backup_branch);
+		global_msg_id=backup_msgid;
+		set_route_type(backup_route_type);
+		/* restore original avp list */
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
+#ifdef WITH_XAVP
+		xavp_set_list(backup_xavps);
+#endif
+		bind_address=backup_si;
+		/* restore lump lists */
+		t->uas.request->add_rm = backup_add_rm;
+		t->uas.request->body_lumps = backup_body_lumps;
+		t->uas.request->reply_lump = backup_reply_lump;
+	}
+}
+
 /** create or restore a "fake environment" for running a failure_route.
  *if msg is set -> it will fake the env. vars conforming with the msg; if NULL
  * the env. will be restore to original.
@@ -2446,6 +2639,11 @@ int reply_received( struct sip_msg  *p_msg )
 			}
 		}
 #endif
+        
+        if (unlikely(p_msg->flags&FL_RPL_SUSPENDED)) {
+				goto skip_send_reply;
+				/* suspend the reply (async), no error */
+	}
 	if (unlikely(!replies_locked)){
 		LOCK_REPLIES( t );
 		replies_locked=1;
@@ -2502,6 +2700,13 @@ int reply_received( struct sip_msg  *p_msg )
 		restart_rb_fr(& uac->request, t->fr_inv_timeout);
 		uac->request.flags|=F_RB_FR_INV; /* mark fr_inv */
 	} /* provisional replies */
+        
+skip_send_reply:
+        
+        if (likely(replies_locked)){
+		UNLOCK_REPLIES(t); /* unlock replies  - this would be unlocked by send function*/
+		replies_locked=0;
+	}
 
 done:
 	tm_ctx_set_branch_index(T_BR_UNDEFINED);
diff --git a/modules/tm/t_reply.h b/modules/tm/t_reply.h
index 5df9a7f..17f046b 100644
--- a/modules/tm/t_reply.h
+++ b/modules/tm/t_reply.h
@@ -236,10 +236,15 @@ void t_drop_replies(int v);
 void rpc_reply(rpc_t* rpc, void* c);
 
 void faked_env( struct cell *t,struct sip_msg *msg);
+void faked_env_resp( struct cell *t,struct sip_msg *msg);
+
 int fake_req(struct sip_msg *faked_req,
 		struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac);
+int fake_resp(struct sip_msg *faked_req,
+		struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac);
 
 void free_faked_req(struct sip_msg *faked_req, struct cell *t);
+void free_faked_resp(struct sip_msg *faked_req, struct cell *t, int branch);
 
 typedef int (*tget_picked_f)(void);
 int t_get_picked_branch(void);
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index 35adcb1..9c0c04d 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -42,6 +42,8 @@
 #include "t_fwd.h"
 #include "t_funcs.h"
 #include "timer.h"
+#include "t_cancel.h"
+
 #include "t_suspend.h"
 
 /* Suspends the transaction for later use.
@@ -107,6 +109,66 @@ int t_suspend(struct sip_msg *msg,
 	return 0;
 }
 
+/* Suspends the transaction for later use.
+ * Save the returned hash_index and label to get
+ * back to the SIP request processing, see the readme.
+ * This method is specifically for suspending replies
+ * 
+ * Return value:
+ * 	0  - success
+ * 	<0 - failure
+ */
+int t_suspend_reply(struct sip_msg *msg,
+		unsigned int *hash_index, unsigned int *label)
+{
+	struct cell	*t;
+        int branch;
+
+	t = get_t();
+	if (!t || t == T_UNDEFINED) {
+		LOG(L_ERR, "ERROR: t_suspend: " \
+			"transaction has not been created yet\n");
+		return -1;
+	}
+
+	if (t->flags & T_CANCELED) {
+               	/* The transaction has already been canceled */
+		LOG(L_DBG, "DEBUG: t_suspend: " \
+			"trying to suspend an already canceled transaction\n");
+		ser_error = E_CANCELED;
+		return 1;
+	}
+        
+	LOG(L_DBG,"DEBUG: This is a suspend on reply - setting msg flag to SUSPEND\n");
+        msg->flags |= FL_RPL_SUSPENDED;
+        /* this is a reply suspend find which branch */
+            
+        if (t_check( msg  , &branch )==-1){
+                LOG(L_ERR, "ERROR: t_suspend: " \
+                        "failed find UAC branch\n");
+                return -1; 
+        }
+        LOG(L_DBG,"DEBUG: Found a a match with branch id [%d]\n", branch);
+        
+        LOG(L_DBG,"DEBUG: Cloning reply message to t->uac[branch].reply\n");
+            
+        t->uac[branch].reply = sip_msg_cloner( msg, 0 );
+
+        if (! t->uac[branch].reply ) {
+                LOG(L_ERR, "ERROR: t_suspend: can't alloc' clone memory\n");
+                return -1;
+        }
+            
+        LOG(L_DBG,"DEBUG: Saving stuff to transaction\n");
+		
+        LOG(L_DBG,"DEBUG: Saving transaction hash and label\n");
+        *hash_index = t->hash_index;
+        *label = t->label;
+        LOG(L_DBG,"DEBUG: Done");
+
+	return 0;
+}
+
 /* Continues the SIP request processing previously saved by
  * t_suspend(). The script does not continue from the same
  * point, but a separate route block is executed instead.
@@ -251,6 +313,152 @@ kill_trans:
 	return ret;
 }
 
+/* Continues the SIP reply processing previously saved by
+ * t_suspend(). The script does not continue from the same
+ * point, but a separate route block is executed instead.
+ *
+ * Parameter:
+ *      The branch of the suspended reply
+ * 
+ * Return value:
+ * 	0  - success
+ * 	<0 - failure
+ */
+int t_continue_reply(unsigned int hash_index, unsigned int label,
+		struct action *route, int branch)
+{
+	struct cell	*t;
+        struct sip_msg	faked_resp;
+        struct cancel_info cancel_data;
+        
+	if (t_lookup_ident(&t, hash_index, label) < 0) {
+		LOG(L_ERR, "ERROR: t_continue: transaction not found\n");
+		return -1;
+	}
+        
+	if (t->flags & T_CANCELED) {
+		/* The transaction has already been canceled,
+		 * needless to continue */
+		UNREF(t); /* t_unref would kill the transaction */
+		/* reset T as we have no working T anymore */
+		set_t(T_UNDEFINED, T_BR_UNDEFINED);
+		return 1;
+	}
+        
+        init_cancel_info(&cancel_data);
+
+	/* The transaction has to be locked to protect it
+	 * form calling t_continue() multiple times simultaneously */
+	LOCK_REPLIES(t);
+
+        LOG(L_DBG,"DEBUG: This a continue from a reply suspend\n");
+        /* this is a continue from a reply suspend */
+            
+        LOG(L_DBG,"Disabling suspend branch");
+        t->uac[branch].reply->flags &= ~FL_RPL_SUSPENDED;
+        if (t->uas.request) t->uas.request->flags&= ~FL_RPL_SUSPENDED;
+        
+        LOG(L_DBG,"Setting up faked environment");
+        if (!fake_resp(&faked_resp, t->uac[branch].reply, 0 /* extra flags */, 0)) {
+		LOG(L_ERR, "ERROR: t_continue: fake_req failed\n");
+		return 0;
+	}
+        
+        faked_env_resp( t, &faked_resp);
+        
+        LOG(L_DBG,"DEBUG: Running pre script\n");
+        if (exec_pre_script_cb(&faked_resp, ONREPLY_CB_TYPE)>0) {
+                if (run_top_route(route, &faked_resp, 0)<0){
+                        LOG(L_ERR, "ERROR: t_continue: Error in run_top_route\n");
+                }
+                LOG(L_DBG,"DEBUG: Running exec post script\n");
+                exec_post_script_cb(&faked_resp, ONREPLY_CB_TYPE);
+        }
+
+        LOG(L_DBG,"Restoring previous environment");
+        faked_env_resp( t, 0);
+	free_faked_resp(&faked_resp, t, branch);
+        
+        int reply_status;
+        if ( is_local(t) ) {
+                LOG(L_DBG,"DEBUG: t is local sending local reply with status code: [%d]\n", t->uac[branch].reply->first_line.u.reply.statuscode);
+                reply_status = local_reply( t, t->uac[branch].reply, branch, t->uac[branch].reply->first_line.u.reply.statuscode, &cancel_data );
+                if (reply_status == RPS_COMPLETED) {
+			     /* no more UAC FR/RETR (if I received a 2xx, there may
+			      * be still pending branches ...
+			      */
+			cleanup_uac_timers( t );
+			if (is_invite(t)) cancel_uacs(t, &cancel_data, F_CANCEL_B_KILL);
+			/* There is no need to call set_final_timer because we know
+			 * that the transaction is local */
+			put_on_wait(t);
+		}else if (unlikely(cancel_data.cancel_bitmap)){
+			/* cancel everything, even non-INVITEs (e.g in case of 6xx), use
+			 * cancel_b_method for canceling unreplied branches */
+			cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
+		}
+                
+        } else {
+                LOG(L_DBG,"DEBUG: t is NOT local sending relaying reply with status code: [%d]\n", t->uac[branch].reply->first_line.u.reply.statuscode);
+                int do_put_on_wait = 0;
+                if(t->uac[branch].reply->first_line.u.reply.statuscode>=200){
+                        do_put_on_wait = 1;
+                }
+                reply_status=relay_reply( t, t->uac[branch].reply, branch, t->uac[branch].reply->first_line.u.reply.statuscode, &cancel_data, do_put_on_wait );
+                if (reply_status == RPS_COMPLETED) {
+			     /* no more UAC FR/RETR (if I received a 2xx, there may
+				be still pending branches ...
+			     */
+			cleanup_uac_timers( t );
+			/* 2xx is a special case: we can have a COMPLETED request
+			 * with branches still open => we have to cancel them */
+			if (is_invite(t) && cancel_data.cancel_bitmap) 
+				cancel_uacs( t, &cancel_data,  F_CANCEL_B_KILL);
+			/* FR for negative INVITES, WAIT anything else */
+			/* Call to set_final_timer is embedded in relay_reply to avoid
+			 * race conditions when reply is sent out and an ACK to stop
+			 * retransmissions comes before retransmission timer is set.*/
+		}else if (unlikely(cancel_data.cancel_bitmap)){
+			/* cancel everything, even non-INVITEs (e.g in case of 6xx), use
+			 * cancel_b_method for canceling unreplied branches */
+			cancel_uacs(t, &cancel_data, cfg_get(tm,tm_cfg, cancel_b_flags));
+		}
+                
+        }
+        t->uac[branch].request.flags|=F_RB_REPLIED;
+
+        if (reply_status==RPS_ERROR){
+            goto done;
+        }
+
+        /* update FR/RETR timers on provisional replies */
+                            
+        int msg_status=t->uac[branch].reply->REPLY_STATUS;
+        int last_uac_status=t->uac[branch].last_received;
+                            
+        if (is_invite(t) && msg_status<200 &&
+        ( cfg_get(tm, tm_cfg, restart_fr_on_each_reply) ||
+        ( (last_uac_status<msg_status) &&
+        ((msg_status>=180) || (last_uac_status==0)) )
+        ) ) { /* provisional now */
+                restart_rb_fr(& t->uac[branch].request, t->fr_inv_timeout);
+                t->uac[branch].request.flags|=F_RB_FR_INV; /* mark fr_inv */
+        } 
+        
+        
+done:
+        
+        tm_ctx_set_branch_index(T_BR_UNDEFINED);        
+        /* unref the transaction */
+        t_unref(t->uac[branch].reply);
+        LOG(L_DBG,"DEBUG: Freeing earlier cloned reply\n");
+        sip_msg_free(t->uac[branch].reply);
+        t->uac[branch].reply = 0;
+        
+        return 0;
+        
+}
+
 /* Revoke the suspension of the SIP request, i.e.
  * cancel the fr timer of the blind uac.
  * This function can be called when something fails
@@ -312,3 +520,44 @@ int t_cancel_suspend(unsigned int hash_index, unsigned int label)
 
 	return 0;
 }
+
+/* Revoke the suspension of the SIP reply, 
+ * This function can be called when something fails
+ * after t_suspend() has already been executed in the same
+ * process, and it turns out that the transaction should
+ * not have been suspended.
+ * 
+ * Parameter:
+ *      The branch of the suspended reply
+ * 
+ * Return value:
+ * 	0  - success
+ * 	<0 - failure
+ */
+int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, int branch)
+{
+	struct cell	*t;
+	
+	t = get_t();
+	if (!t || t == T_UNDEFINED) {
+		LOG(L_ERR, "ERROR: t_revoke_suspend: " \
+			"no active transaction\n");
+		return -1;
+	}
+	/* Only to double-check the IDs */
+	if ((t->hash_index != hash_index)
+		|| (t->label != label)
+	) {
+		LOG(L_ERR, "ERROR: t_revoke_suspend: " \
+			"transaction id mismatch\n");
+		return -1;
+	}
+	
+        LOG(L_DBG,"This is a cancel suspend for a response\n");
+        
+        t->uac[branch].reply->flags &= ~FL_RPL_SUSPENDED;
+        if (t->uas.request) t->uas.request->flags&= ~FL_RPL_SUSPENDED;
+        
+        return 0;
+}
+
diff --git a/modules/tm/t_suspend.h b/modules/tm/t_suspend.h
index 1c19be1..f50fc5d 100644
--- a/modules/tm/t_suspend.h
+++ b/modules/tm/t_suspend.h
@@ -34,13 +34,28 @@ int t_suspend(struct sip_msg *msg,
 typedef int (*t_suspend_f)(struct sip_msg *msg,
 		unsigned int *hash_index, unsigned int *label);
 
+int t_suspend_reply(struct sip_msg *msg,
+		unsigned int *hash_index, unsigned int *label);
+typedef int (*t_suspend_reply_f)(struct sip_msg *msg,
+		unsigned int *hash_index, unsigned int *label);
+
+
 int t_continue(unsigned int hash_index, unsigned int label,
 		struct action *route);
 typedef int (*t_continue_f)(unsigned int hash_index, unsigned int label,
 		struct action *route);
 
+int t_continue_reply(unsigned int hash_index, unsigned int label,
+		struct action *route, int branch);
+typedef int (*t_continue_reply_f)(unsigned int hash_index, unsigned int label,
+		struct action *route, int branch);
+
+
 int t_cancel_suspend(unsigned int hash_index, unsigned int label);
 typedef int (*t_cancel_suspend_f)(unsigned int hash_index, unsigned int label);
 
+int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, int branch);
+typedef int (*t_cancel_suspend_reply_f)(unsigned int hash_index, unsigned int label, int branch);
+
 
 #endif /* _T_SUSPEND_H */
diff --git a/modules/tm/tm_load.c b/modules/tm/tm_load.c
index d431a38..8712251 100644
--- a/modules/tm/tm_load.c
+++ b/modules/tm/tm_load.c
@@ -127,8 +127,11 @@ int load_tm( struct tm_binds *tmb)
 	tmb->t_get_canceled_ident = t_get_canceled_ident;
 #endif
 	tmb->t_suspend = t_suspend;
+        tmb->t_suspend_reply = t_suspend_reply;
 	tmb->t_continue = t_continue;
+        tmb->t_continue_reply = t_continue_reply;
 	tmb->t_cancel_suspend = t_cancel_suspend;
+        tmb->t_cancel_suspend_reply = t_cancel_suspend_reply;
 	tmb->t_get_reply_totag = t_get_reply_totag;
 	tmb->t_get_picked_branch = t_get_picked_branch;
 	tmb->t_lookup_callid = t_lookup_callid;
diff --git a/modules/tm/tm_load.h b/modules/tm/tm_load.h
index 6d5959e..bd2ba71 100644
--- a/modules/tm/tm_load.h
+++ b/modules/tm/tm_load.h
@@ -110,8 +110,11 @@ struct tm_binds {
 	void* reserved4;
 #endif
 	t_suspend_f	t_suspend;
+        t_suspend_reply_f	t_suspend_reply;
 	t_continue_f	t_continue;
+        t_continue_reply_f	t_continue_reply;
 	t_cancel_suspend_f	t_cancel_suspend;
+        t_cancel_suspend_reply_f	t_cancel_suspend_reply;
 	tget_reply_totag_f t_get_reply_totag;
 	tget_picked_f t_get_picked_branch;
 	tlookup_callid_f t_lookup_callid;
diff --git a/parser/msg_parser.h b/parser/msg_parser.h
index 9e97e65..d7d92fe 100644
--- a/parser/msg_parser.h
+++ b/parser/msg_parser.h
@@ -120,6 +120,7 @@ typedef enum request_method {
 #define FL_USE_UAC_FROM      (1<<13)  /* take FROM hdr from UAC instead of UAS*/
 #define FL_USE_UAC_TO        (1<<14)  /* take TO hdr from UAC instead of UAS */
 #define FL_TM_RPL_MATCHED    (1<<15)  /* tm matched reply already */
+#define FL_RPL_SUSPENDED     (1<<16)  /* for async reply processing */
 
 /* WARNING: Value (1 << 28) is temporarily reserved for use in kamailio call_control
  * module (flag  FL_USE_CALL_CONTROL )! */
