static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg) { struct sip_msg *shm_msg; unsigned int timeout; /* avp timeout gets stored here (in s) */ shm_msg=new_cell->uas.request; new_cell->from.s=shm_msg->from->name.s; new_cell->from.len=HF_LEN(shm_msg->from); new_cell->to.s=shm_msg->to->name.s; new_cell->to.len=HF_LEN(shm_msg->to); new_cell->callid.s=shm_msg->callid->name.s; new_cell->callid.len=HF_LEN(shm_msg->callid); new_cell->cseq_n.s=shm_msg->cseq->name.s; new_cell->cseq_n.len=get_cseq(shm_msg)->number.s +get_cseq(shm_msg)->number.len -shm_msg->cseq->name.s; new_cell->method=new_cell->uas.request->first_line.u.request.method; if (p_msg->REQ_METHOD==METHOD_INVITE) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->on_negative=get_on_negative(); new_cell->on_reply=get_on_reply(); new_cell->fr_timeout=(ticks_t)get_msgid_val(user_fr_timeout, p_msg->id, int); new_cell->fr_inv_timeout=(ticks_t)get_msgid_val(user_fr_inv_timeout, p_msg->id, int); if (new_cell->fr_timeout==0){ if (!fr_avp2timer(&timeout)) { DBG("init_new_t: FR__TIMER = %d s\n", timeout); new_cell->fr_timeout=S_TO_TICKS((ticks_t)timeout); }else{ new_cell->fr_timeout=fr_timeout; } } if (new_cell->fr_inv_timeout==0){ if (!fr_inv_avp2timer(&timeout)) { DBG("init_new_t: FR_INV_TIMER = %d s\n", timeout); new_cell->fr_inv_timeout=S_TO_TICKS((ticks_t)timeout); new_cell->flags |= T_NOISY_CTIMER_FLAG; }else{ new_cell->fr_inv_timeout=fr_inv_timeout; } } new_cell->on_branch=get_on_branch(); }
static inline void init_new_t(struct cell *new_cell, struct sip_msg *p_msg) { struct sip_msg *shm_msg; shm_msg=new_cell->uas.request; new_cell->from.s=shm_msg->from->name.s; new_cell->from.len=HF_LEN(shm_msg->from); new_cell->to.s=shm_msg->to->name.s; new_cell->to.len=HF_LEN(shm_msg->to); new_cell->callid.s=shm_msg->callid->name.s; new_cell->callid.len=HF_LEN(shm_msg->callid); new_cell->cseq_n.s=shm_msg->cseq->name.s; new_cell->cseq_n.len=get_cseq(shm_msg)->number.s +get_cseq(shm_msg)->number.len -shm_msg->cseq->name.s; new_cell->method=new_cell->uas.request->first_line.u.request.method; if (p_msg->REQ_METHOD==METHOD_INVITE) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->on_negative=get_on_negative(); new_cell->on_reply=get_on_reply(); new_cell->on_branch=get_on_branch(); }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy, int reset_bcounter, int locked) { str reply_reason_487 = str_init("Request Terminated"); str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; str dst_uri; struct socket_info *bk_sock; unsigned int br_flags, bk_bflags; int idx; str path; str bk_path; /* make -Wall happy */ current_uri.s=0; /* before doing enything, update the t flags from msg */ t->uas.request->flags = p_msg->flags; if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; cancel_invite( p_msg, t, t_invite, locked ); return 1; } } /* do not forward requests which were already cancelled*/ if (no_new_branches(t)) { LM_INFO("discarding fwd for a 6xx transaction\n"); ser_error = E_NO_DESTINATION; return -1; } if (was_cancelled(t)) { /* is this the first attempt of sending a branch out ? */ if (t->nr_of_outgoings==0) { /* if no other signalling was performed on the transaction * and the transaction was already canceled, better * internally generate the 487 reply here */ if (locked) t_reply_unsafe( t, p_msg , 487 , &reply_reason_487); else t_reply( t, p_msg , 487 , &reply_reason_487); } LM_INFO("discarding fwd for a cancelled transaction\n"); ser_error = E_NO_DESTINATION; return -1; } /* backup current uri, sock and flags... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; bk_path = p_msg->path_vec; bk_bflags = p_msg->ruri_bflags; /* advertised address/port are not changed */ /* check if the UAS retranmission port needs to be updated */ if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT ) su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port ); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ if (reset_bcounter) { t->first_branch=t->nr_of_outgoings; /* check if the previous branch is a PHONY one and if yes * keep it in the set of active branches; that means the * transaction had a t_wait_for_new_branches() call prior to relay() */ if ( t->first_branch>0 && (t->uac[t->first_branch-1].flags & T_UAC_IS_PHONY) ) t->first_branch--; } /* as first branch, use current uri */ current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, getb0flags(p_msg), &p_msg->path_vec, proxy); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; /* ....and now add the remaining additional branches */ for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { branch_ret = add_uac( t, p_msg, ¤t_uri, &dst_uri, br_flags, &path, proxy); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; p_msg->path_vec = bk_path; p_msg->ruri_bflags = bk_bflags; /* update on_branch, _only_ if modified, otherwise it overwrites * whatever it is already in the transaction */ if (get_on_branch()) t->on_branch = get_on_branch(); /* update flags, if changed in branch route */ t->uas.request->flags = p_msg->flags; /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { LM_ERR("failure to add branches\n"); ser_error = lowest_ret; return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { if (t->uac[i].br_flags & tcp_no_new_conn_bflag) tcp_no_new_conn = 1; do { if (check_blacklists( t->uac[i].request.dst.proto, &t->uac[i].request.dst.to, t->uac[i].request.buffer.s, t->uac[i].request.buffer.len)) { LM_DBG("blocked by blacklists\n"); ser_error=E_IP_BLOCKED; } else { run_trans_callbacks(TMCB_PRE_SEND_BUFFER, t, p_msg, 0, i); if (SEND_BUFFER( &t->uac[i].request)==0) { ser_error = 0; break; } LM_ERR("sending request failed\n"); ser_error=E_SEND; } /* get next dns entry */ if ( t->uac[i].proxy==0 || get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to, (ser_error==E_IP_BLOCKED)?0:1)!=0 ) break; t->uac[i].request.dst.proto = t->uac[i].proxy->proto; /* update branch */ if ( update_uac_dst( p_msg, &t->uac[i] )!=0) break; }while(1); tcp_no_new_conn = 0; if (ser_error) { shm_free(t->uac[i].request.buffer.s); t->uac[i].request.buffer.s = NULL; t->uac[i].request.buffer.len = 0; continue; } success_branch++; start_retr( &t->uac[i].request ); set_kr(REQ_FWDED); /* successfully sent out -> run callbacks */ if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT) ) { set_extra_tmcb_params( &t->uac[i].request.buffer, &t->uac[i].request.dst); run_trans_callbacks( TMCB_REQUEST_BUILT|TMCB_MSG_SENT_OUT, t, p_msg, 0, 0); } } } return (success_branch>0)?1:-1; }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy) { str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; str dst_uri; struct socket_info *bk_sock; unsigned int br_flags; unsigned int bk_br_flags; int idx; str path; str bk_path; /* make -Wall happy */ current_uri.s=0; /* before doing enything, update the t falgs from msg */ t->uas.request->flags = p_msg->flags; if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; cancel_invite( p_msg, t, t_invite ); return 1; } } /* do not forward requests which were already cancelled*/ if (was_cancelled(t) || no_new_branches(t)) { LM_ERR("discarding fwd for a cancelled/6xx transaction\n"); ser_error = E_NO_DESTINATION; return -1; } /* backup current uri, sock and flags... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; bk_br_flags = getb0flags(); bk_path = p_msg->path_vec; /* check if the UAS retranmission port needs to be updated */ if ( (p_msg->msg_flags ^ t->uas.request->msg_flags) & FL_FORCE_RPORT ) su_setport( &t->uas.response.dst.to, p_msg->rcv.src_port ); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ t->first_branch=t->nr_of_outgoings; /* as first branch, use current uri */ current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, &p_msg->path_vec, proxy); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; /* ....and now add the remaining additional branches */ for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &path, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { setb0flags(br_flags); branch_ret = add_uac( t, p_msg, ¤t_uri, &dst_uri, &path, proxy); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; p_msg->path_vec = bk_path; setb0flags(bk_br_flags); /* update on_branch, if modified */ t->on_branch = get_on_branch(); /* update flags, if changed in branch route */ t->uas.request->flags = p_msg->flags; /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { LM_ERR("failure to add branches\n"); ser_error = lowest_ret; return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { #ifdef USE_TCP if (t->uac[i].br_flags & tcp_no_new_conn_bflag) tcp_no_new_conn = 1; #endif do { if (check_blacklists( t->uac[i].request.dst.proto, &t->uac[i].request.dst.to, t->uac[i].request.buffer.s, t->uac[i].request.buffer.len)) { LM_DBG("blocked by blacklists\n"); ser_error=E_IP_BLOCKED; } else { if (SEND_BUFFER( &t->uac[i].request)==0) { ser_error = 0; break; } LM_ERR("sending request failed\n"); ser_error=E_SEND; } /* get next dns entry */ if ( t->uac[i].proxy==0 || get_next_su( t->uac[i].proxy, &t->uac[i].request.dst.to, (ser_error==E_IP_BLOCKED)?0:1)!=0 ) break; t->uac[i].request.dst.proto = t->uac[i].proxy->proto; /* update branch */ if ( update_uac_dst( p_msg, &t->uac[i] )!=0) break; }while(1); #ifdef USE_TCP tcp_no_new_conn = 0; #endif if (ser_error) { shm_free(t->uac[i].request.buffer.s); t->uac[i].request.buffer.s = NULL; t->uac[i].request.buffer.len = 0; continue; } success_branch++; start_retr( &t->uac[i].request ); set_kr(REQ_FWDED); /* successfully sent out -> run callbacks */ if ( has_tran_tmcbs( t, TMCB_REQUEST_BUILT) ) { set_extra_tmcb_params( &t->uac[i].request.buffer, &t->uac[i].request.dst); run_trans_callbacks( TMCB_REQUEST_BUILT, t, p_msg,0, -p_msg->REQ_METHOD); } } } return (success_branch>0)?1:-1; }
/* function returns: * 1 - forward successful * -1 - error during forward */ int t_forward_nonack( struct cell *t, struct sip_msg* p_msg , struct proxy_l * proxy, int proto) { str backup_uri; str backup_dst; int branch_ret, lowest_ret; str current_uri; branch_bm_t added_branches; int i, q; struct cell *t_invite; int success_branch; int try_new; str dst_uri; struct socket_info *bk_sock; int rurib_flags; int br_flags; int idx; /* make -Wall happy */ current_uri.s=0; set_kr(REQ_FWDED); if (p_msg->REQ_METHOD==METHOD_CANCEL) { t_invite=t_lookupOriginalT( p_msg ); if (t_invite!=T_NULL_CELL) { t_invite->flags |= T_WAS_CANCELLED_FLAG; e2e_cancel( p_msg, t, t_invite ); UNREF(t_invite); return 1; } } /* do not forward requests which were already cancelled*/ if (was_cancelled(t)) { LOG(L_ERR,"ERROR:tm:t_forward_nonack: discarding fwd for " "a cancelled transaction\n"); return -1; } /* backup current uri, sock and flags ... add_uac changes it */ backup_uri = p_msg->new_uri; backup_dst = p_msg->dst_uri; bk_sock = p_msg->force_send_socket; rurib_flags = p_msg->flags&(~gflags_mask); /* if no more specific error code is known, use this */ lowest_ret=E_BUG; /* branches added */ added_branches=0; /* branch to begin with */ t->first_branch=t->nr_of_outgoings; /* on first-time forwarding, use current uri, later only what is in additional branches (which may be continuously refilled) */ if (t->first_branch==0) { try_new=1; current_uri = *GET_RURI(p_msg); branch_ret = add_uac( t, p_msg, ¤t_uri, &backup_dst, proxy, proto ); if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } else try_new=0; for( idx=0; (current_uri.s=get_branch( idx, ¤t_uri.len, &q, &dst_uri, &br_flags, &p_msg->force_send_socket))!=0 ; idx++ ) { try_new++; p_msg->flags = (p_msg->flags&gflags_mask) | br_flags; branch_ret=add_uac( t, p_msg, ¤t_uri, &dst_uri, proxy, proto); /* pick some of the errors in case things go wrong; note that picking lowest error is just as good as any other algorithm which picks any other negative branch result */ if (branch_ret>=0) added_branches |= 1<<branch_ret; else lowest_ret=branch_ret; } /* consume processed branches */ clear_branches(); /* restore original stuff */ p_msg->new_uri=backup_uri; p_msg->parsed_uri_ok = 0;/* just to be sure; add_uac may parse other uris*/ p_msg->dst_uri = backup_dst; p_msg->force_send_socket = bk_sock; /* update on_branch, if modified */ t->on_branch = get_on_branch(); /* set flags */ p_msg->flags = (p_msg->flags&gflags_mask)|rurib_flags; t->uas.request->flags = p_msg->flags&gflags_mask; /* don't forget to clear all branches processed so far */ /* things went wrong ... no new branch has been fwd-ed at all */ if (added_branches==0) { if (try_new==0) { LOG(L_ERR, "ERROR:tm:t_forward_nonack: no branch for " "forwarding\n"); return -1; } LOG(L_ERR, "ERROR:tm:t_forward_nonack: failure to add branches\n"); return lowest_ret; } /* send them out now */ success_branch=0; for (i=t->first_branch; i<t->nr_of_outgoings; i++) { if (added_branches & (1<<i)) { if (SEND_BUFFER( &t->uac[i].request)==-1) { LOG(L_ERR, "ERROR:tm:t_forward_nonack: sending request " "failed\n"); if (proxy) { proxy->errors++; proxy->ok=0; } } else { success_branch++; } start_retr( &t->uac[i].request ); } } if (success_branch<=0) { ser_error=E_SEND; return -1; } return 1; }