void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite ) { branch_bm_t cancel_bm; branch_bm_t dummy_bm; int i; int lowest_error; str backup_uri; int rurib_flags; int ret; cancel_bm=0; lowest_error=0; /* e2e_cancel_branch() makes no RURI parsing, so no need to * save the ->parse_uri_ok */ backup_uri = cancel_msg->new_uri; /* branch flags specific to RURI */ rurib_flags = cancel_msg->flags&(~gflags_mask); /* determine which branches to cancel ... */ which_cancel( t_invite, &cancel_bm ); t_cancel->nr_of_outgoings=t_invite->nr_of_outgoings; t_cancel->first_branch=t_invite->first_branch; /* fix label -- it must be same for reply matching */ t_cancel->label=t_invite->label; /* ... and install CANCEL UACs */ for (i=t_invite->first_branch; i<t_invite->nr_of_outgoings; i++) { if (cancel_bm & (1<<i)) { ret=e2e_cancel_branch(cancel_msg, t_cancel, t_invite, i); if (ret<0) cancel_bm &= ~(1<<i); if (ret<lowest_error) lowest_error=ret; } } /* restore new_uri */ cancel_msg->new_uri = backup_uri; cancel_msg->parsed_uri_ok = 0; /* set flags */ cancel_msg->flags = (cancel_msg->flags&gflags_mask)|rurib_flags; t_cancel->uas.request->flags = cancel_msg->flags&gflags_mask; /* send them out */ for (i=t_cancel->first_branch; i<t_cancel->nr_of_outgoings; i++) { if (cancel_bm & (1<<i)) { if (SEND_BUFFER( &t_cancel->uac[i].request)==-1) { LOG(L_ERR, "ERROR: e2e_cancel: send failed\n"); } start_retr( &t_cancel->uac[i].request ); } } /* 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){ /* mark as cancelled */ t_invite->uac[i].flags |= T_UAC_TO_CANCEL_FLAG; /* 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 ); if (RPS_ERROR==relay_reply(t_invite,FAKED_REPLY,i,487,&dummy_bm)) lowest_error = -1; /* force sending 500 error */ } } /* do not attmpt to send reply for CANCEL if we already did it once; * to work arround the race between receiveing reply and generating * local reply, we better check if we are in failure route (which means that * the reply to UAC is /to be/ sent) or if was actually sent out */ /* calling here t_relay from within failure route will lead to dead lock * on the transaction's reply lock -bogdan */ if (route_type==FAILURE_ROUTE || t_cancel->uas.status>=200) return; /* if error occurred, let it know upstream (final reply will also move the transaction on wait state */ if (lowest_error<0) { LOG(L_ERR, "ERROR: cancel error\n"); t_reply( t_cancel, cancel_msg, 500, "cancel error"); /* if there are pending branches, let upstream know we are working on it */ } else if (cancel_bm) { DBG("DEBUG: e2e_cancel: e2e cancel proceeding\n"); t_reply( t_cancel, cancel_msg, 200, CANCELING ); /* if the transaction exists, but there is no more pending branch, tell upstream we're done */ } else { DBG("DEBUG: e2e_cancel: e2e cancel -- no more pending branches\n"); t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE ); } #ifdef LOCAL_487 /* local 487s have been deprecated -- it better handles * race conditions (UAS sending 200); hopefully there are * no longer UACs who go crazy waiting for the 487 whose * forwarding is being blocked by other unresponsive branch */ /* we could await downstream UAS's 487 replies; however, if some of the branches does not do that, we could wait long time and annoy upstream UAC which wants to see a result of CANCEL quickly */ DBG("DEBUG: e2e_cancel: sending 487\n"); /* in case that something in the meantime has been sent upstream (like if FR hit at the same time), don't try to send */ if (t_invite->uas.status>=200) return; /* there is still a race-condition -- the FR can hit now; that's not too bad -- we take care in t_reply's REPLY_LOCK; in the worst case, both this t_reply and other replier will try, and the later one will result in error message "can't reply twice" */ t_reply(t_invite, t_invite->uas.request, 487, CANCELED ); #endif }
void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite ) { branch_bm_t cancel_bm, tmp_bm; int i; int lowest_error; str backup_uri; int ret; cancel_bm=0; lowest_error=0; backup_uri=cancel_msg->new_uri; /* determine which branches to cancel ... */ which_cancel( t_invite, &cancel_bm ); t_cancel->nr_of_outgoings=t_invite->nr_of_outgoings; /* fix label -- it must be same for reply matching */ t_cancel->label=t_invite->label; /* ... and install CANCEL UACs */ for (i=0; i<t_invite->nr_of_outgoings; i++) if (cancel_bm & (1<<i)) { ret=e2e_cancel_branch(cancel_msg, t_cancel, t_invite, i); if (ret<0) cancel_bm &= ~(1<<i); if (ret<lowest_error) lowest_error=ret; } cancel_msg->new_uri=backup_uri; /* send them out */ for (i=0; i<t_cancel->nr_of_outgoings; i++) { if (cancel_bm & (1<<i)) { /* Provisional reply received on this branch, send CANCEL */ /* No need to stop timers as they have already been stopped by the reply */ if (SEND_BUFFER( &t_cancel->uac[i].request)==-1) { LOG(L_ERR, "ERROR: e2e_cancel: send failed\n"); } start_retr( &t_cancel->uac[i].request ); } else { if (t_invite->uac[i].last_received < 100) { /* No provisional response received, stop * retransmission timers */ reset_timer(&t_invite->uac[i].request.retr_timer); reset_timer(&t_invite->uac[i].request.fr_timer); /* Generate faked reply */ LOCK_REPLIES(t_invite); if (relay_reply(t_invite, FAKED_REPLY, i, 487, &tmp_bm) == RPS_ERROR) { lowest_error = -1; } } } } /* if error occurred, let it know upstream (final reply will also move the transaction on wait state */ if (lowest_error<0) { LOG(L_ERR, "ERROR: cancel error\n"); t_reply( t_cancel, cancel_msg, 500, "cancel error"); /* if there are pending branches, let upstream know we are working on it */ } else if (cancel_bm) { DBG("DEBUG: e2e_cancel: e2e cancel proceeding\n"); t_reply( t_cancel, cancel_msg, 200, CANCELING ); /* if the transaction exists, but there is no more pending branch, tell upstream we're done */ } else { DBG("DEBUG: e2e_cancel: e2e cancel -- no more pending branches\n"); t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE ); } #ifdef LOCAL_487 /* local 487s have been deprecated -- it better handles * race conditions (UAS sending 200); hopefully there are * no longer UACs who go crazy waiting for the 487 whose * forwarding is being blocked by other unresponsive branch */ /* we could await downstream UAS's 487 replies; however, if some of the branches does not do that, we could wait long time and annoy upstream UAC which wants to see a result of CANCEL quickly */ DBG("DEBUG: e2e_cancel: sending 487\n"); /* in case that something in the meantime has been sent upstream (like if FR hit at the same time), don't try to send */ if (t_invite->uas.status>=200) return; /* there is still a race-condition -- the FR can hit now; that's not too bad -- we take care in t_reply's REPLY_LOCK; in the worst case, both this t_reply and other replier will try, and the later one will result in error message "can't reply twice" */ t_reply(t_invite, t_invite->uas.request, 487, CANCELED ); #endif }
void e2e_cancel( struct sip_msg *cancel_msg, struct cell *t_cancel, struct cell *t_invite ) { branch_bm_t cancel_bm; int i; int lowest_error; str backup_uri; int ret; cancel_bm=0; lowest_error=0; backup_uri=cancel_msg->new_uri; /* determine which branches to cancel ... */ which_cancel( t_invite, &cancel_bm ); t_cancel->nr_of_outgoings=t_invite->nr_of_outgoings; /* fix label -- it must be same for reply matching */ t_cancel->label=t_invite->label; /* ... and install CANCEL UACs */ for (i=0; i<t_invite->nr_of_outgoings; i++) if (cancel_bm & (1<<i)) { ret=e2e_cancel_branch(cancel_msg, t_cancel, t_invite, i); if (ret<0) cancel_bm &= ~(1<<i); if (ret<lowest_error) lowest_error=ret; } cancel_msg->new_uri=backup_uri; /* send them out */ for (i=0; i<t_cancel->nr_of_outgoings; i++) { if (cancel_bm & (1<<i)) { if (SEND_BUFFER( &t_cancel->uac[i].request)==-1) { LOG(L_ERR, "ERROR: e2e_cancel: send failed\n"); } start_retr( &t_cancel->uac[i].request ); } } /* if error occured, let it know upstream (final reply will also move the transaction on wait state */ if (lowest_error<0) { LOG(L_ERR, "ERROR: cancel error\n"); t_reply( t_cancel, cancel_msg, 500, "cancel error"); /* if there are pending branches, let upstream know we are working on it */ } else if (cancel_bm) { DBG("DEBUG: e2e_cancel: e2e cancel proceeding\n"); t_reply( t_cancel, cancel_msg, 200, CANCELLING ); /* if the transaction exists, but there is no more pending branch, tell usptream we're done */ } else { DBG("DEBUG: e2e_cancel: e2e cancel -- no more pending branches\n"); t_reply( t_cancel, cancel_msg, 200, CANCEL_DONE ); } /* we could await downstream UAS's 487 replies; however, if some of the branches does not do that, we could wait long time and annoy upstream UAC which wants to see a result of CANCEL quickly */ DBG("DEBUG: e2e_cancel: sending 487\n"); /* in case that something in the meantime has been sent upstream (like if FR hit at the same time), don't try to send */ if (t_invite->uas.status>=200) return; /* there is still a race-condition -- the FR can hit now; that's not too bad -- we take care in t_reply's REPLY_LOCK; in the worst case, both this t_reply and other replier will try, and the later one will result in error message "can't reply twice" */ t_reply(t_invite, t_invite->uas.request, 487, CANCELLED ); }