int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int flags) { int ret; int new_tran; int reply_ret; struct cell *t; ret=0; new_tran = t_newtran( p_msg, 1/*full UAS cloning*/ ); /* parsing error, memory alloc, whatever ... */ if (new_tran<0) { ret = new_tran; goto done; } /* if that was a retransmission, break from script */ if (new_tran==0) { goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { LM_DBG("forwarding ACK\n"); /* send it out */ if (proxy==0) { proxy=uri2proxy(GET_NEXT_HOP(p_msg), p_msg->force_send_socket ? p_msg->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; free_proxy( proxy ); pkg_free( proxy ); } else { ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (flags&TM_T_RELAY_repl_FLAG) t->flags|=T_IS_LOCAL_FLAG; if (flags&TM_T_RELAY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG; if (flags&TM_T_RELAY_reason_FLAG) t->flags|=T_CANCEL_REASON_FLAG; if ((flags&TM_T_RELAY_do_cancel_dis_FLAG) && tm_has_request_disponsition_no_cancel(p_msg)==0 ) t->flags|=T_MULTI_200OK_FLAG; /* now go ahead and forward ... */ ret=t_forward_nonack( t, p_msg, proxy, 0/*no reset*/, 0/*unlocked*/); if (ret<=0) { LM_DBG("t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!(flags&(TM_T_RELAY_repl_FLAG|TM_T_RELAY_noerr_FLAG))) { reply_ret = kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ LM_DBG("generation of a stateful reply on error succeeded\n"); ret=0; } else { LM_DBG("generation of a stateful reply on error failed\n"); } } } else { LM_DBG("new transaction fwd'ed\n"); } done: return ret; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ static int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, unsigned int bflags, str* path, struct proxy_l *proxy) { unsigned short branch; struct sip_msg_body *body_clone=NO_BODY_CLONE_MARKER; int do_free_proxy; int ret; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LM_ERR("maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer.s) { LM_CRIT("buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* set proper RURI to request to reflect the branch */ request->new_uri=*uri; request->parsed_uri_ok=0; request->dst_uri=*next_hop; request->path_vec=*path; request->ruri_bflags=bflags; if ( pre_print_uac_request( t, branch, request, &body_clone)!= 0 ) { ret = -1; goto error01; } /* check DNS resolution */ if (proxy){ do_free_proxy = 0; }else { proxy=uri2proxy( request->dst_uri.len ? &request->dst_uri:&request->new_uri, request->force_send_socket ? request->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error01; } do_free_proxy = 1; } msg_callback_process(request, REQ_PRE_FORWARD, (void *)proxy); if ( !(t->flags&T_NO_DNS_FAILOVER_FLAG) ) { t->uac[branch].proxy = shm_clone_proxy( proxy , do_free_proxy ); if (t->uac[branch].proxy==NULL) { ret = E_OUT_OF_MEM; goto error02; } } /* use the first address */ hostent2su( &t->uac[branch].request.dst.to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); t->uac[branch].request.dst.proto = proxy->proto; /* do print of the uac request */ if ( update_uac_dst( request, &t->uac[branch] )!=0) { ret = ser_error; goto error02; } /* things went well, move ahead */ t->uac[branch].uri.s=t->uac[branch].request.buffer.s+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=request->new_uri.len; t->uac[branch].br_flags = request->ruri_bflags; t->uac[branch].added_rr = count_local_rr( request ); t->nr_of_outgoings++; /* done! */ ret=branch; error02: if(do_free_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error01: post_print_uac_request( request, uri, next_hop, body_clone); if (ret < 0) { /* destroy all the bavps added, the path vector and the destination, * since this branch will never be properly added to * the UAC list, otherwise we'll have memory leaks - razvanc */ clean_branch(t->uac[branch]); memset(&t->uac[branch], 0, sizeof(t->uac[branch])); init_branch(&t->uac[branch], branch, t->wait_tl.set, t); } error: return ret; }
/* * Send a request using data from the dialog structure */ int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp,release_tmcb_param release_func) { union sockaddr_union to_su, new_to_su; struct cell *new_cell; struct cell *backup_cell; struct retr_buf *request; static struct sip_msg *req; struct usr_avp **backup; char *buf, *buf1; int buf_len, buf_len1; int ret, flags, sflag_bk; int backup_route_type; int sip_msg_len; unsigned int hi; struct socket_info *new_send_sock; str h_to, h_from, h_cseq, h_callid; struct proxy_l *proxy, *new_proxy; unsigned short dst_changed; ret=-1; /*** added by dcm * - needed by external ua to send a request within a dlg */ if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0) goto error3; if(dialog->obp.s) dialog->hooks.next_hop = &dialog->obp; LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); /* calculate the socket corresponding to next hop */ proxy = uri2proxy( dialog->hooks.next_hop, dialog->send_sock ? dialog->send_sock->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error3; } /* use the first address */ hostent2su( &to_su, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); /* check/discover the send socket */ if (dialog->send_sock) { /* if already set, the protocol of send sock must have the the same type as the proto required by destination URI */ if (proxy->proto != dialog->send_sock->proto) dialog->send_sock = NULL; } if (dialog->send_sock==NULL) { /* get the send socket */ dialog->send_sock = get_send_socket( NULL/*msg*/, &to_su, proxy->proto); if (!dialog->send_sock) { LM_ERR("no corresponding socket for af %d\n", to_su.s.sa_family); ser_error = E_NO_SOCKET; goto error2; } } LM_DBG("sending socket is %.*s \n", dialog->send_sock->name.len,dialog->send_sock->name.s); /* ***** Create TRANSACTION and all related ***** */ new_cell = build_cell( NULL/*msg*/, 1/*full UAS clone*/); if (!new_cell) { ret=E_OUT_OF_MEM; LM_ERR("short of cell shmem\n"); goto error2; } /* pass the transaction flags from dialog to transaction */ new_cell->flags |= dialog->T_flags; /* add the callback the transaction for LOCAL_COMPLETED event */ flags = TMCB_LOCAL_COMPLETED; /* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */ if (pass_provisional_replies || pass_provisional(new_cell)) flags |= TMCB_LOCAL_RESPONSE_OUT; if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){ ret=E_OUT_OF_MEM; LM_ERR("short of tmcb shmem\n"); goto error2; } if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0) new_cell->flags |= T_IS_INVITE_FLAG; new_cell->flags |= T_IS_LOCAL_FLAG; request = &new_cell->uac[0].request; if (dialog->forced_to_su.s.sa_family == AF_UNSPEC) request->dst.to = to_su; else request->dst.to = dialog->forced_to_su; request->dst.send_sock = dialog->send_sock; request->dst.proto = dialog->send_sock->proto; request->dst.proto_reserved1 = 0; hi=dlg2hash(dialog); LOCK_HASH(hi); insert_into_hash_table_unsafe(new_cell, hi); UNLOCK_HASH(hi); /* copy AVPs into transaction */ new_cell->user_avps = dialog->avps; dialog->avps = NULL; /* ***** Create the message buffer ***** */ buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len); if (!buf) { LM_ERR("failed to build message\n"); ret=E_OUT_OF_MEM; goto error1; } if (local_rlist.a) { LM_DBG("building sip_msg from buffer\n"); req = buf_to_sip_msg(buf, buf_len, dialog); if (req==NULL) { LM_ERR("failed to build sip_msg from buffer\n"); } else { /* set this transaction as active one */ backup_cell = get_t(); set_t( new_cell ); /* set transaction AVP list */ backup = set_avp_list( &new_cell->user_avps ); /* backup script flags */ sflag_bk = getsflags(); /* disable parallel forking */ set_dset_state( 0 /*disable*/); /* run the route */ swap_route_type( backup_route_type, LOCAL_ROUTE); run_top_route( local_rlist.a, req); set_route_type( backup_route_type ); /* transfer current message context back to t */ new_cell->uac[0].br_flags = getb0flags(req); /* restore the prevoius active transaction */ set_t( backup_cell ); set_dset_state( 1 /*enable*/); setsflagsval(sflag_bk); set_avp_list( backup ); /* check for changes - if none, do not regenerate the buffer */ dst_changed = 1; if (req->new_uri.s || req->force_send_socket!=dialog->send_sock || req->dst_uri.len != dialog->hooks.next_hop->len || memcmp(req->dst_uri.s,dialog->hooks.next_hop->s,req->dst_uri.len) || (dst_changed=0)==0 || req->add_rm || req->body_lumps){ new_send_sock = NULL; /* do we also need to change the destination? */ if (dst_changed) { /* calculate the socket corresponding to next hop */ new_proxy = uri2proxy( req->dst_uri.s ? &(req->dst_uri) : &req->new_uri, PROTO_NONE ); if (new_proxy==0) goto abort_update; /* use the first address */ hostent2su( &new_to_su, &new_proxy->host, new_proxy->addr_idx, new_proxy->port ? new_proxy->port:SIP_PORT); /* get the send socket */ new_send_sock = get_send_socket( req, &new_to_su, new_proxy->proto); if (!new_send_sock) { free_proxy( new_proxy ); pkg_free( new_proxy ); LM_ERR("no socket found for the new destination\n"); goto abort_update; } } /* if interface change, we need to re-build the via */ if (new_send_sock && new_send_sock != dialog->send_sock) { LM_DBG("Interface change in local route -> " "rebuilding via\n"); if (!del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len,0)) { LM_ERR("Failed to remove initial via \n"); goto abort_update; } memcpy(req->add_to_branch_s,req->via1->branch->value.s, req->via1->branch->value.len); req->add_to_branch_len = req->via1->branch->value.len; /* update also info about new destination and send sock */ dialog->send_sock = new_send_sock; free_proxy( proxy ); pkg_free( proxy ); proxy = new_proxy; request->dst.send_sock = new_send_sock; request->dst.proto = new_send_sock->proto; request->dst.proto_reserved1 = 0; /* build the shm buffer now */ set_init_lump_flags(LUMPFLAG_BRANCH); buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, new_send_sock, new_send_sock->proto, MSG_TRANS_SHM_FLAG); reset_init_lump_flags(); del_flaged_lumps( &req->add_rm, LUMPFLAG_BRANCH); } else { LM_DBG("Change in local route -> rebuilding buffer\n"); /* build the shm buffer now */ buf1 = build_req_buf_from_sip_req(req, (unsigned int*)&buf_len1, dialog->send_sock, dialog->send_sock->proto, MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG); /* now as it used, hide the original VIA header */ del_lump(req,req->h_via1->name.s - req->buf, req->h_via1->len, 0); } if (!buf1) { LM_ERR("no more shm mem\n"); /* keep original buffer */ goto abort_update; } /* update shortcuts */ if(!req->add_rm && !req->new_uri.s) { /* headers are not affected, simply tranlate */ new_cell->from.s = new_cell->from.s - buf + buf1; new_cell->to.s = new_cell->to.s - buf + buf1; new_cell->callid.s = new_cell->callid.s - buf + buf1; new_cell->cseq_n.s = new_cell->cseq_n.s - buf + buf1; } else { /* use heavy artilery :D */ if (extract_ftc_hdrs( buf1, buf_len1, &h_from, &h_to, &h_cseq, &h_callid)!=0 ) { LM_ERR("failed to update shortcut pointers\n"); shm_free(buf1); goto abort_update; } new_cell->from = h_from; new_cell->to = h_to; new_cell->callid = h_callid; new_cell->cseq_n = h_cseq; } /* here we rely on how build_uac_req() builds the first line */ new_cell->uac[0].uri.s = buf1 + req->first_line.u.request.method.len + 1; new_cell->uac[0].uri.len = GET_RURI(req)->len; /* update also info about new destination and send sock */ if (new_send_sock) request->dst.to = new_to_su; shm_free(buf); buf = buf1; buf_len = buf_len1; /* use new buffer */ } else { /* no changes over the message, buffer is already generated, just hide the original VIA for potential further branches */ del_lump(req,req->h_via1->name.s-req->buf,req->h_via1->len,0); } abort_update: /* save the SIP message into transaction */ new_cell->uas.request = sip_msg_cloner( req, &sip_msg_len, 1); if (new_cell->uas.request==NULL) { /* reset any T triggering */ new_cell->on_negative = 0; new_cell->on_reply = 0; } else { new_cell->uas.end_request= ((char*)new_cell->uas.request)+sip_msg_len; } /* no parallel support in UAC transactions */ new_cell->on_branch = 0; free_sip_msg(req); } } /* for DNS based failover, copy the DNS proxy into transaction */ if (!disable_dns_failover) { new_cell->uac[0].proxy = shm_clone_proxy( proxy, 1/*do_free*/); if (new_cell->uac[0].proxy==NULL) LM_ERR("failed to store DNS info -> no DNS based failover\n"); } new_cell->method.s = buf; new_cell->method.len = method->len; request->buffer.s = buf; request->buffer.len = buf_len; new_cell->nr_of_outgoings++; if(last_localT) { *last_localT = new_cell; REF_UNSAFE(new_cell); } if (SEND_BUFFER(request) == -1) { LM_ERR("attempt to send to '%.*s' failed\n", dialog->hooks.next_hop->len, dialog->hooks.next_hop->s); } if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) { t_release_transaction(new_cell); } else { start_retr(request); } free_proxy( proxy ); pkg_free( proxy ); return 1; error1: LOCK_HASH(hi); remove_from_hash_table_unsafe(new_cell); UNLOCK_HASH(hi); free_cell(new_cell); error2: free_proxy( proxy ); pkg_free( proxy ); error3: return ret; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ static int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, str* path, struct proxy_l *proxy) { unsigned short branch; int do_free_proxy; int ret; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LM_ERR("maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer.s) { LM_CRIT("buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* set proper RURI to request to reflect the branch */ request->new_uri=*uri; request->parsed_uri_ok=0; request->dst_uri=*next_hop; request->path_vec=*path; if ( pre_print_uac_request( t, branch, request)!= 0 ) { ret = -1; goto error01; } /* check DNS resolution */ if (proxy){ do_free_proxy = 0; }else { proxy=uri2proxy( request->dst_uri.len ? &request->dst_uri:&request->new_uri, PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error01; } do_free_proxy = 1; } msg_callback_process(request, REQ_PRE_FORWARD, (void *)proxy); if ( !(t->flags&T_NO_DNS_FAILOVER_FLAG) ) { t->uac[branch].proxy = shm_clone_proxy( proxy , do_free_proxy ); if (t->uac[branch].proxy==NULL) { ret = E_OUT_OF_MEM; goto error02; } } /* use the first address */ hostent2su( &t->uac[branch].request.dst.to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); t->uac[branch].request.dst.proto = proxy->proto; if ( update_uac_dst( request, &t->uac[branch] )!=0) { ret = ser_error; goto error02; } /* things went well, move ahead */ t->uac[branch].uri.s=t->uac[branch].request.buffer.s+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=request->new_uri.len; t->uac[branch].br_flags = getb0flags(); t->uac[branch].added_rr = count_local_rr( request ); t->nr_of_outgoings++; /* done! */ ret=branch; error02: if(do_free_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error01: post_print_uac_request( request, uri, next_hop); error: return ret; }
/* introduce a new uac to transaction; returns its branch id (>=0) or error (<0); it doesn't send a message yet -- a reply to it might interfere with the processes of adding multiple branches */ int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, struct proxy_l *proxy, int proto ) { int ret; short temp_proxy; union sockaddr_union to; unsigned short branch; struct socket_info* send_sock; char *shbuf; unsigned int len; branch=t->nr_of_outgoings; if (branch==MAX_BRANCHES) { LOG(L_ERR, "ERROR: add_uac: maximum number of branches exceeded\n"); ret=E_CFG; goto error; } /* check existing buffer -- rewriting should never occur */ if (t->uac[branch].request.buffer) { LOG(L_CRIT, "ERROR: add_uac: buffer rewrite attempt\n"); ret=ser_error=E_BUG; goto error; } /* check DNS resolution */ if (proxy) { temp_proxy=0; proto=get_proto(proto, proxy->proto); } else { proxy=uri2proxy( next_hop ? next_hop : uri, proto ); if (proxy==0) { ret=E_BAD_ADDRESS; goto error; } proto=proxy->proto; /* uri2proxy will fix it for us */ temp_proxy=1; } if (proxy->ok==0) { if (proxy->host.h_addr_list[proxy->addr_idx+1]) proxy->addr_idx++; else proxy->addr_idx=0; proxy->ok=1; } hostent2su( &to, &proxy->host, proxy->addr_idx, proxy->port ? proxy->port:SIP_PORT); send_sock=get_send_socket( request, &to , proto); if (send_sock==0) { LOG(L_ERR, "ERROR: add_uac: can't fwd to af %d, proto %d " " (no corresponding listening socket)\n", to.s.sa_family, proto ); ret=ser_error=E_NO_SOCKET; goto error01; } /* now message printing starts ... */ shbuf=print_uac_request( t, request, branch, uri, &len, send_sock, proto ); if (!shbuf) { ret=ser_error=E_OUT_OF_MEM; goto error01; } /* things went well, move ahead and install new buffer! */ t->uac[branch].request.dst.to=to; t->uac[branch].request.dst.send_sock=send_sock; t->uac[branch].request.dst.proto=proto; t->uac[branch].request.dst.proto_reserved1=0; t->uac[branch].request.buffer=shbuf; t->uac[branch].request.buffer_len=len; t->uac[branch].uri.s=t->uac[branch].request.buffer+ request->first_line.u.request.method.len+1; t->uac[branch].uri.len=uri->len; t->nr_of_outgoings++; /* update stats */ proxy->tx++; proxy->tx_bytes+=len; /* done! */ ret=branch; error01: if (temp_proxy) { free_proxy( proxy ); pkg_free( proxy ); } error: return ret; }
int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int flags) { int ret; int new_tran; int reply_ret; struct cell *t; context_p ctx_backup; ret=0; new_tran = t_newtran( p_msg, 1/*full UAS cloning*/ ); /* parsing error, memory alloc, whatever ... */ if (new_tran<0) { ret = new_tran; goto done; } /* if that was a retransmission, break from script */ if (new_tran==0) { goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { LM_DBG("forwarding ACK\n"); /* send it out */ if (proxy==0) { proxy=uri2proxy(GET_NEXT_HOP(p_msg), p_msg->force_send_socket ? p_msg->force_send_socket->proto : PROTO_NONE ); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; free_proxy( proxy ); pkg_free( proxy ); } else { ret=forward_request( p_msg , proxy); if (ret>=0) ret=1; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (flags&TM_T_REPLY_repl_FLAG) t->flags|=T_IS_LOCAL_FLAG; if (flags&TM_T_REPLY_nodnsfo_FLAG) t->flags|=T_NO_DNS_FAILOVER_FLAG; if (flags&TM_T_REPLY_reason_FLAG) t->flags|=T_CANCEL_REASON_FLAG; /* INVITE processing might take long, particularly because of DNS look-ups -- let upstream know we're working on it */ if ( p_msg->REQ_METHOD==METHOD_INVITE && !(flags&(TM_T_REPLY_no100_FLAG|TM_T_REPLY_repl_FLAG)) ) { ctx_backup = current_processing_ctx; current_processing_ctx = NULL; t_reply( t, p_msg , 100 , &relay_reason_100); current_processing_ctx = ctx_backup; } /* now go ahead and forward ... */ ret=t_forward_nonack( t, p_msg, proxy); if (ret<=0) { LM_DBG("t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!(flags&(TM_T_REPLY_repl_FLAG|TM_T_REPLY_noerr_FLAG))) { reply_ret = kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ LM_DBG("generation of a stateful reply on error succeeded\n"); ret=0; } else { LM_DBG("generation of a stateful reply on error failed\n"); } } } else { LM_DBG("new transaction fwd'ed\n"); } done: return ret; }
int t_relay_to( struct sip_msg *p_msg , struct proxy_l *proxy, int proto, int replicate) { int ret; int new_tran; str *uri; int reply_ret; /* struct hdr_field *hdr; */ struct cell *t; ret=0; new_tran = t_newtran( p_msg ); /* parsing error, memory alloc, whatever ... if via is bad and we are forced to reply there, return with 0 (->break), pass error status otherwise */ if (new_tran<0) { ret = (ser_error==E_BAD_VIA && reply_to_via) ? 0 : new_tran; goto done; } /* if that was a retransmission, return we are happily done */ if (new_tran==0) { ret = 1; goto done; } /* new transaction */ /* ACKs do not establish a transaction and are fwd-ed statelessly */ if ( p_msg->REQ_METHOD==METHOD_ACK) { DBG("DEBUG:tm:t_relay: forwarding ACK statelessly \n"); if (proxy==0) { uri = GET_RURI(p_msg); proxy=uri2proxy(GET_NEXT_HOP(p_msg), proto); if (proxy==0) { ret=E_BAD_ADDRESS; goto done; } proto=proxy->proto; /* uri2proxy set it correctly */ ret=forward_request( p_msg , proxy, proto) ; free_proxy( proxy ); pkg_free( proxy ); } else { proto=get_proto(proto, proxy->proto); ret=forward_request( p_msg , proxy, proto ) ; } goto done; } /* if replication flag is set, mark the transaction as local so that replies will not be relaied */ t=get_t(); if (replicate) t->flags|=T_IS_LOCAL_FLAG; /* INVITE processing might take long, particularly because of DNS look-ups -- let upstream know we're working on it */ if (p_msg->REQ_METHOD==METHOD_INVITE ) { DBG("DEBUG:tm:t_relay: new INVITE\n"); if (!t_reply( t, p_msg , 100 , "trying -- your call is important to us")) DBG("SER: ERROR: t_reply (100)\n"); } /* now go ahead and forward ... */ ret=t_forward_nonack(t, p_msg, proxy, proto); if (ret<=0) { DBG( "ERROR:tm:t_relay_to: t_forward_nonack returned error \n"); /* we don't want to pass upstream any reply regarding replicating * a request; replicated branch must stop at us*/ if (!replicate) { reply_ret=kill_transaction( t ); if (reply_ret>0) { /* we have taken care of all -- do nothing in script */ DBG("ERROR: generation of a stateful reply " "on error succeeded\n"); ret=0; } else { DBG("ERROR: generation of a stateful reply " "on error failed\n"); } } } else { DBG( "SER: new transaction fwd'ed\n"); } done: return ret; }
/* Actions are composed as follows: * (the action length and type as always= 5 bytes) * * TODO performance speedup: instead of using * dynamically allocated memory for headers,body,totag,reason and my_msg * use static buffers. * */ int ac_sl_msg(as_p the_as,char *action,int len) { struct sip_msg *my_msg; str *uri; struct proxy_l *proxy; rr_t *my_route; int k,retval; unsigned int flags; enum sip_protos proto; my_msg=NULL; k=0; net2hostL(flags,action,k); k++; proxy=0; if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){ LM_ERR("out of memory!\n"); goto error; } if(my_msg->first_line.type == SIP_REQUEST) LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\ my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s); else LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\ my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s); if (my_msg->route) { if (parse_rr(my_msg->route) < 0) { LM_ERR( "Error while parsing Route body\n"); goto error; } my_route = (rr_t*)my_msg->route->parsed; uri=&(my_route->nameaddr.uri); }else{ uri = GET_RURI(my_msg); } my_msg->force_send_socket=grep_sock_info(&my_msg->via1->host,my_msg->via1->port,my_msg->via1->proto); /* or also could be: my_msg->force_send_socket=the_as->binds[processor_id].bind_address; not sure which is better... */ proxy=uri2proxy(uri,PROTO_NONE); if (proxy==0) { LM_ERR("unable to create proxy from URI \n"); goto error; } proto=proxy->proto; /* uri2proxy set it correctly */ //TODO my_msg->recvd if(0>forward_sl_request(my_msg,proxy,proto)) goto error; retval=0; goto exit; error: retval = -1; exit: if(proxy){ free_proxy(proxy); pkg_free(proxy); } if(my_msg){ free_sip_msg_lite(my_msg); pkg_free(my_msg); } return retval; }