Esempio n. 1
0
void cancel_invite(struct sip_msg *cancel_msg,
								struct cell *t_cancel, struct cell *t_invite )
{
#define CANCEL_REASON_SIP_487  \
	"Reason: SIP;cause=487;text=\"ORIGINATOR_CANCEL\"" CRLF

	branch_bm_t cancel_bitmap;
	branch_bm_t dummy_bm;
	str reason;
	unsigned int i;
	struct hdr_field *hdr;

	cancel_bitmap=0;

	/* send back 200 OK as per RFC3261 */
	reason.s = CANCELING;
	reason.len = sizeof(CANCELING)-1;
	t_reply( t_cancel, cancel_msg, 200, &reason );

	reason.s = NULL;
	reason.len = 0;
	/* propagate the REASON flag ? */
	if ( t_cancel->flags&T_CANCEL_REASON_FLAG ) {
		/* look for the Reason header */
		if (parse_headers(cancel_msg, HDR_EOH_F, 0)<0) {
			LM_ERR("failed to parse all hdrs - ignoring Reason hdr\n");
		} else {
			hdr = get_header_by_static_name(cancel_msg, "Reason");
			if (hdr!=NULL) {
				reason.s = hdr->name.s;
				reason.len = hdr->len;
			}
		}
	}

	/* if no reason, use NORMAL CLEARING */
	if (reason.s == NULL) {
		reason.s = CANCEL_REASON_SIP_487;
		reason.len = sizeof(CANCEL_REASON_SIP_487) - 1;
	}

	/* generate local cancels for all branches */
	which_cancel(t_invite, &cancel_bitmap );

	set_cancel_extra_hdrs( reason.s, reason.len);
	cancel_uacs(t_invite, cancel_bitmap );
	set_cancel_extra_hdrs( NULL, 0);

	/* internally cancel branches with no received reply */
	for (i=t_invite->first_branch; i<t_invite->nr_of_outgoings; i++) {
		if (t_invite->uac[i].last_received==0){
			/* reset the "request" timers */
			reset_timer(&t_invite->uac[i].request.retr_timer);
			reset_timer(&t_invite->uac[i].request.fr_timer);
			LOCK_REPLIES( t_invite );
			relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm);
		}
	}
}
Esempio n. 2
0
void cancel_invite(struct sip_msg *cancel_msg,
					struct cell *t_cancel, struct cell *t_invite, int locked)
{

	branch_bm_t cancel_bitmap;
	str reason;

	cancel_bitmap=0;

	/* send back 200 OK as per RFC3261 */
	reason.s = CANCELING;
	reason.len = sizeof(CANCELING)-1;
	if (locked)
		t_reply_unsafe( t_cancel, cancel_msg, 200, &reason );
	else
		t_reply( t_cancel, cancel_msg, 200, &reason );

	get_cancel_reason(cancel_msg, t_cancel->flags, &reason);

	/* generate local cancels for all branches */
	which_cancel(t_invite, &cancel_bitmap );

	set_cancel_extra_hdrs( reason.s, reason.len);
	cancel_uacs(t_invite, cancel_bitmap );
	set_cancel_extra_hdrs( NULL, 0);

	/* Do not do anything about branches with no received reply;
	 * continue the retransmission hoping to get something back;
	 * if still not, we will generate the 408 Timeout based on FR
	 * timer; this helps with better coping with missed/lated provisional
	 * replies in the context of cancelling the transaction
	 */
#if 0
	/* internally cancel branches with no received reply */
	for (i=t_invite->first_branch; i<t_invite->nr_of_outgoings; i++) {
		if (t_invite->uac[i].last_received==0){
			/* reset the "request" timers */
			reset_timer(&t_invite->uac[i].request.retr_timer);
			reset_timer(&t_invite->uac[i].request.fr_timer);
			LOCK_REPLIES( t_invite );
			relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm);
		}
	}
#endif
}
Esempio n. 3
0
File: tm.c Progetto: Deni90/opensips
int t_cancel_trans(struct cell *t, str *extra_hdrs)
{
	branch_bm_t cancel_bitmap = 0;

	if (t==NULL || t==T_UNDEFINED) {
		/* no transaction */
		LM_ERR("cannot cancel with no transaction");
		return -1;
	}

	LOCK_REPLIES(t);
	which_cancel( t, &cancel_bitmap );
	UNLOCK_REPLIES(t);

	/* send cancels out */
	if (extra_hdrs)
		set_cancel_extra_hdrs( extra_hdrs->s, extra_hdrs->len);
	cancel_uacs(t, cancel_bitmap);
	set_cancel_extra_hdrs( NULL, 0);

	return 0;
}
Esempio n. 4
0
int t_inject_branch( struct cell *t, struct sip_msg *msg, int flags)
{
	static struct sip_msg faked_req;
	branch_bm_t cancel_bm;
	str reason = str_init(CANCEL_REASON_200);
	int rc;

	/* does the transaction state still accept new branches ? */
	if (t->uas.status >= 200) {
		LM_DBG("cannot add branches to a transaction with %d UAS\n",
			t->uas.status);
		return -2;
	}

	if (!fake_req( &faked_req, t->uas.request, &t->uas, NULL, 0)) {
		LM_ERR("fake_req failed\n");
		return -1;
	}

	/* do we have the branches to be injected ? */
	if (flags&TM_INJECT_SRC_EVENT) {
		/* get the branch from Event AVPs, as populated by EVI/EBR */
		if (ul_contact_event_to_msg( &faked_req )<0) {
			LM_ERR("failed to grab new branch from Event\n");
			goto error;
		}
	} else {
		/* use the RURI+dset array as destinations to be injected */
		if (msg->first_line.type==SIP_REQUEST) {
			/* take the RURI branch from the script msg and move it
			 * into the faked msg (that will be used by t_fwd function) */
			if (dst_to_msg( msg, &faked_req )<0) {
				LM_ERR("failed to grab new branch from Event\n");
				goto error;
			}
		} else {
			/* current message is a reply, so take the first branch from dset
			 * and move it into the faked msg (that will be used by t_fwd 
			 * function)*/
			if (move_branch_to_ruri( 0, &faked_req)<0) {
				LM_ERR("no branch found to be moved as new destination\n");
				goto error;
			}
			/* remove it from set */
			remove_branch(0);
		}
	}

	/* do we have to cancel the existing branches before injecting new ones? */
	if (flags&TM_INJECT_FLAG_CANCEL) {
		which_cancel( t, &cancel_bm );
	}

	/* generated the new branches, without branch counter reset */
	rc = t_forward_nonack( t, &faked_req , NULL, 0, 1/*locked*/ );

	/* do we have to cancel the existing branches before injecting new ones? */
	if (flags&TM_INJECT_FLAG_CANCEL) {
		set_cancel_extra_hdrs( reason.s, reason.len);
		cancel_uacs( t, cancel_bm );
		set_cancel_extra_hdrs( NULL, 0);
	}

	/* cleanup the faked request */
	free_faked_req( &faked_req, t);

	return (rc==1)?1:-3;

error:
	/* cleanup the faked request */
	free_faked_req( &faked_req, t);
	return -1;
}
Esempio n. 5
0
inline static void final_response_handler( struct timer_link *fr_tl )
{
#define CANCEL_REASON_SIP_480  \
	"Reason: SIP;cause=480;text=\"NO_ANSWER\"" CRLF

	static context_p my_ctx = NULL;
	context_p old_ctx;
	struct retr_buf* r_buf;
	struct cell *t;

	if (fr_tl==0){
		/* or BUG?, ignoring it for now */
		LM_CRIT("final_response_handler(0) called\n");
		return;
	}
	r_buf = get_fr_timer_payload(fr_tl);
	t=r_buf->my_T;

#	ifdef EXTRA_DEBUG
	if (t->damocles)
	{
		LM_ERR("transaction %p scheduled for deletion and"
			" called from FR timer\n",r_buf->my_T);
		abort();
	}
#	endif

	reset_timer(  &(r_buf->retr_timer) );

	/* the transaction is already removed from FR_LIST by the timer */

	/* FR for local cancels.... */
	if (r_buf->activ_type==TYPE_LOCAL_CANCEL)
	{
		LM_DBG("stop retr for Local Cancel\n");
		return;
	}

	/* FR for replies (negative INVITE replies) */
	if (r_buf->activ_type>0) {
#		ifdef EXTRA_DEBUG
		if (t->uas.request->REQ_METHOD!=METHOD_INVITE
			|| t->uas.status < 200 ) {
			LM_ERR("unknown type reply buffer\n");
			abort();
		}
#		endif
		put_on_wait( t );
		return;
	};

	/* as this processing is outside the scope of other messages (it is
	   trigger from timer), a processing context must be attached to it */
	old_ctx = current_processing_ctx;
	if (my_ctx==NULL) {
		my_ctx = context_alloc(CONTEXT_GLOBAL);
		if (my_ctx==NULL) {
			LM_ERR("failed to alloc new ctx in pkg\n");
		}
	}
	memset( my_ctx, 0, context_size(CONTEXT_GLOBAL) );
	current_processing_ctx = my_ctx;
	/* set the T context too */
	set_t( t );

	/* out-of-lock do the cancel I/O */
	if (is_invite(t) && should_cancel_branch(t, r_buf->branch) ) {
		set_cancel_extra_hdrs( CANCEL_REASON_SIP_480, sizeof(CANCEL_REASON_SIP_480)-1);
		cancel_branch(t, r_buf->branch );
		set_cancel_extra_hdrs( NULL, 0);
	}
	/* lock reply processing to determine how to proceed reliably */
	LOCK_REPLIES( t );
	LM_DBG("Cancel sent out, sending 408 (%p)\n", t);
	fake_reply(t, r_buf->branch, 408 );

	/* flush the context */
	if (current_processing_ctx==NULL)
		my_ctx=NULL;
	else
		context_destroy(CONTEXT_GLOBAL, my_ctx);
	/* switch back to the old context */
	current_processing_ctx = old_ctx;
	/* reset the T context */
	init_t();

	LM_DBG("done\n");
}