void which_cancel( struct cell *t, branch_bm_t *cancel_bm ) { int i; for( i=t->first_branch ; i<t->nr_of_outgoings ; i++ ) { if (should_cancel_branch(t, i)) *cancel_bm |= 1<<i ; } }
static void fake_reply(struct cell *t, int branch, int code ) { branch_bm_t cancel_bitmap; short do_cancel_branch; enum rps reply_status; do_cancel_branch = is_invite(t) && should_cancel_branch(t, branch); cancel_bitmap=do_cancel_branch ? 1<<branch : 0; if ( is_local(t) ) { reply_status=local_reply( t, FAKED_REPLY, branch, code, &cancel_bitmap ); if (reply_status==RPS_COMPLETED) { put_on_wait(t); } } else { reply_status=relay_reply( t, FAKED_REPLY, branch, code, &cancel_bitmap ); } }
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"); }