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); } } }
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 }
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; }
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; }
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"); }