00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <string.h>
00064 #include "../../mem/shm_mem.h"
00065 #include "../../dprint.h"
00066 #include "../../globals.h"
00067 #include "../../md5.h"
00068 #include "../../crc.h"
00069 #include "../../ip_addr.h"
00070 #include "../../socket_info.h"
00071 #include "../../compiler_opt.h"
00072 #include "config.h"
00073 #include "ut.h"
00074 #include "h_table.h"
00075 #include "t_hooks.h"
00076 #include "t_funcs.h"
00077 #include "t_msgbuilder.h"
00078 #include "callid.h"
00079 #include "uac.h"
00080 #include "t_stats.h"
00081 #ifdef USE_DNS_FAILOVER
00082 #include "../../dns_cache.h"
00083 #include "../../cfg_core.h"
00084 #endif
00085 #ifdef WITH_EVENT_LOCAL_REQUEST
00086 #include "../../receive.h"
00087 #include "../../route.h"
00088 #include "../../action.h"
00089 #include "../../onsend.h"
00090 #include "t_lookup.h"
00091 #endif
00092
00093 #define FROM_TAG_LEN (MD5_LEN + 1 + CRC16_LEN)
00094
00095 #ifdef WITH_EVENT_LOCAL_REQUEST
00096
00097 int goto_on_local_req=-1;
00098 #endif
00099
00100 static char from_tag[FROM_TAG_LEN + 1];
00101
00102
00103
00104
00105 int uac_init(void)
00106 {
00107 str src[3];
00108 struct socket_info *si;
00109
00110 if (RAND_MAX < TABLE_ENTRIES) {
00111 LOG(L_WARN, "Warning: uac does not spread "
00112 "across the whole hash table\n");
00113 }
00114
00115
00116 si=bind_address?bind_address:get_first_socket();
00117 if (si==0){
00118 LOG(L_CRIT, "BUG: uac_init: null socket list\n");
00119 return -1;
00120 }
00121
00122
00123 src[0].s = "Long live SER server";
00124 src[0].len = strlen(src[0].s);
00125 src[1].s = si->address_str.s;
00126 src[1].len = strlen(src[1].s);
00127 src[2].s = si->port_no_str.s;
00128 src[2].len = strlen(src[2].s);
00129
00130 MD5StringArray(from_tag, src, 3);
00131 from_tag[MD5_LEN] = '-';
00132 return 1;
00133 }
00134
00135
00136
00137
00138
00139 void generate_fromtag(str* tag, str* callid)
00140 {
00141
00142 crcitt_string_array(&from_tag[MD5_LEN + 1], callid, 1);
00143 tag->s = from_tag;
00144 tag->len = FROM_TAG_LEN;
00145 }
00146
00147
00148
00149
00150
00151 static inline int check_params(uac_req_t *uac_r, str* to, str* from)
00152 {
00153 if (!uac_r || !uac_r->method || !to || !from) {
00154 LOG(L_ERR, "check_params(): Invalid parameter value\n");
00155 return -1;
00156 }
00157
00158 if (!uac_r->method->s || !uac_r->method->len) {
00159 LOG(L_ERR, "check_params(): Invalid request method\n");
00160 return -2;
00161 }
00162
00163 if (!to->s || !to->len) {
00164 LOG(L_ERR, "check_params(): Invalid To URI\n");
00165 return -4;
00166 }
00167
00168 if (!from->s || !from->len) {
00169 LOG(L_ERR, "check_params(): Invalid From URI\n");
00170 return -5;
00171 }
00172 return 0;
00173 }
00174
00175 static inline unsigned int dlg2hash( dlg_t* dlg )
00176 {
00177 str cseq_nr;
00178 unsigned int hashid;
00179
00180 cseq_nr.s=int2str(dlg->loc_seq.value, &cseq_nr.len);
00181 hashid=hash(dlg->id.call_id, cseq_nr);
00182 DBG("DEBUG: dlg2hash: %d\n", hashid);
00183 return hashid;
00184 }
00185
00186
00187
00188
00189
00190
00191
00192
00193 static inline int t_uac_prepare(uac_req_t *uac_r,
00194 struct retr_buf **dst_req,
00195 struct cell **dst_cell)
00196 {
00197 struct dest_info dst;
00198 struct cell *new_cell;
00199 struct retr_buf *request;
00200 char* buf;
00201 int buf_len, ret;
00202 unsigned int hi;
00203 int is_ack;
00204 ticks_t lifetime;
00205 #ifdef USE_DNS_FAILOVER
00206 struct dns_srv_handle dns_h;
00207 #endif
00208 long nhtype;
00209 #ifdef WITH_EVENT_LOCAL_REQUEST
00210 struct cell *backup_t;
00211 int backup_branch;
00212 unsigned int backup_msgid;
00213 static struct sip_msg lreq;
00214 char *buf1;
00215 int buf_len1;
00216 int sflag_bk;
00217 int backup_route_type;
00218 #endif
00219 snd_flags_t snd_flags;
00220 tm_xlinks_t backup_xd;
00221 tm_xdata_t local_xd;
00222
00223 ret=-1;
00224 hi=0;
00225
00226 is_ack = (((uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0)) ? 1 : 0);
00227
00228
00229
00230
00231 if ((nhtype = w_calculate_hooks(uac_r->dialog)) < 0)
00232
00233 goto error2;
00234
00235 if (!uac_r->dialog->loc_seq.is_set) {
00236
00237
00238 uac_r->dialog->loc_seq.value = DEFAULT_CSEQ;
00239 uac_r->dialog->loc_seq.is_set = 1;
00240 }
00241
00242 DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",uac_r->dialog->hooks.next_hop->len,
00243 uac_r->dialog->hooks.next_hop->s);
00244
00245
00246 SND_FLAGS_INIT(&snd_flags);
00247 #ifdef USE_DNS_FAILOVER
00248 if (cfg_get(core, core_cfg, use_dns_failover)){
00249 dns_srv_handle_init(&dns_h);
00250 if ((uri2dst2(&dns_h, &dst, uac_r->dialog->send_sock, snd_flags,
00251 uac_r->dialog->hooks.next_hop, PROTO_NONE)==0)
00252 || (dst.send_sock==0)){
00253 dns_srv_handle_put(&dns_h);
00254 ser_error = E_NO_SOCKET;
00255 ret=ser_error;
00256 LOG(L_ERR, "t_uac: no socket found\n");
00257 goto error2;
00258 }
00259 dns_srv_handle_put(&dns_h);
00260 }else{
00261 if ((uri2dst2(0, &dst, uac_r->dialog->send_sock, snd_flags,
00262 uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
00263 (dst.send_sock==0)){
00264 ser_error = E_NO_SOCKET;
00265 ret=ser_error;
00266 LOG(L_ERR, "t_uac: no socket found\n");
00267 goto error2;
00268 }
00269 }
00270 #else
00271 if ((uri2dst2(&dst, uac_r->dialog->send_sock, snd_flags,
00272 uac_r->dialog->hooks.next_hop, PROTO_NONE)==0) ||
00273 (dst.send_sock==0)){
00274 ser_error = E_NO_SOCKET;
00275 ret=ser_error;
00276 LOG(L_ERR, "t_uac: no socket found\n");
00277 goto error2;
00278 }
00279 #endif
00280
00281
00282
00283 memset(&local_xd, 0, sizeof(tm_xdata_t));
00284 tm_xdata_replace(&local_xd, &backup_xd);
00285 new_cell = build_cell(0);
00286 tm_xdata_replace(0, &backup_xd);
00287
00288 if (!new_cell) {
00289 ret=E_OUT_OF_MEM;
00290 LOG(L_ERR, "t_uac: short of cell shmem\n");
00291 goto error2;
00292 }
00293 if (uac_r->method->len==INVITE_LEN && memcmp(uac_r->method->s, INVITE, INVITE_LEN)==0){
00294 new_cell->flags |= T_IS_INVITE_FLAG;
00295 new_cell->flags|=T_AUTO_INV_100 &
00296 (!cfg_get(tm, tm_cfg, tm_auto_inv_100) -1);
00297 #ifdef WITH_AS_SUPPORT
00298 if (uac_r->cb_flags & TMCB_DONT_ACK)
00299 new_cell->flags |= T_NO_AUTO_ACK;
00300 #endif
00301 lifetime=cfg_get(tm, tm_cfg, tm_max_inv_lifetime);
00302 }else
00303 lifetime=cfg_get(tm, tm_cfg, tm_max_noninv_lifetime);
00304 new_cell->flags |= T_IS_LOCAL_FLAG;
00305
00306
00307
00308
00309
00310 new_cell->fr_timeout=cfg_get(tm, tm_cfg, fr_timeout);
00311 new_cell->fr_inv_timeout=cfg_get(tm, tm_cfg, fr_inv_timeout);
00312 new_cell->end_of_life=get_ticks_raw()+lifetime;
00313 #ifdef TM_DIFF_RT_TIMEOUT
00314
00315 new_cell->rt_t1_timeout_ms = cfg_get(tm, tm_cfg, rt_t1_timeout_ms);
00316 new_cell->rt_t2_timeout_ms = cfg_get(tm, tm_cfg, rt_t2_timeout_ms);
00317 #endif
00318
00319 set_kr(REQ_FWDED);
00320
00321 request = &new_cell->uac[0].request;
00322 request->dst = dst;
00323 request->flags |= nhtype;
00324
00325 if (!is_ack) {
00326 #ifdef TM_DEL_UNREF
00327 INIT_REF(new_cell, 1);
00328 #endif
00329 hi=dlg2hash(uac_r->dialog);
00330 LOCK_HASH(hi);
00331 insert_into_hash_table_unsafe(new_cell, hi);
00332 UNLOCK_HASH(hi);
00333 }
00334
00335 buf = build_uac_req(uac_r->method, uac_r->headers, uac_r->body, uac_r->dialog, 0, new_cell,
00336 &buf_len, &dst);
00337 if (!buf) {
00338 LOG(L_ERR, "t_uac: Error while building message\n");
00339 ret=E_OUT_OF_MEM;
00340 goto error1;
00341 }
00342
00343 #ifdef WITH_EVENT_LOCAL_REQUEST
00344 if (unlikely(goto_on_local_req>=0)) {
00345 DBG("executing event_route[tm:local-request]\n");
00346 if(likely(build_sip_msg_from_buf(&lreq, buf, buf_len, inc_msg_no())
00347 == 0)) {
00348
00349 if (unlikely(set_dst_uri(&lreq, uac_r->dialog->hooks.next_hop))) {
00350 LM_ERR("failed to set dst_uri");
00351 free_sip_msg(&lreq);
00352 } else {
00353 struct onsend_info onsnd_info;
00354
00355 lreq.force_send_socket = uac_r->dialog->send_sock;
00356 lreq.rcv.proto = dst.send_sock->proto;
00357 lreq.rcv.src_ip = dst.send_sock->address;
00358 lreq.rcv.src_port = dst.send_sock->port_no;
00359 lreq.rcv.dst_port = su_getport(&dst.to);
00360 su2ip_addr(&lreq.rcv.dst_ip, &dst.to);
00361 lreq.rcv.src_su=dst.send_sock->su;
00362 lreq.rcv.bind_address=dst.send_sock;
00363 #ifdef USE_COMP
00364 lreq.rcv.comp=dst.comp;
00365 #endif
00366 sflag_bk = getsflags();
00367 tm_xdata_swap(new_cell, &backup_xd, 0);
00368
00369 onsnd_info.to=&dst.to;
00370 onsnd_info.send_sock=dst.send_sock;
00371 onsnd_info.buf=buf;
00372 onsnd_info.len=buf_len;
00373 p_onsend=&onsnd_info;
00374
00375
00376 backup_route_type = get_route_type();
00377 set_route_type(LOCAL_ROUTE);
00378
00379 backup_t=get_t();
00380 backup_branch=get_t_branch();
00381 backup_msgid=global_msg_id;
00382
00383 global_msg_id=lreq.id;
00384 set_t(new_cell, T_BR_UNDEFINED);
00385 run_top_route(event_rt.rlist[goto_on_local_req], &lreq, 0);
00386
00387 set_t(backup_t, backup_branch);
00388 global_msg_id=backup_msgid;
00389 set_route_type( backup_route_type );
00390 p_onsend=0;
00391
00392
00393 tm_xdata_swap(new_cell, &backup_xd, 1);
00394 setsflagsval(sflag_bk);
00395
00396 if (unlikely(lreq.new_uri.s))
00397 {
00398 pkg_free(lreq.new_uri.s);
00399 lreq.new_uri.s=0;
00400 lreq.new_uri.len=0;
00401 }
00402 if (unlikely(lreq.dst_uri.s))
00403 {
00404 pkg_free(lreq.dst_uri.s);
00405 lreq.dst_uri.s=0;
00406 lreq.dst_uri.len=0;
00407 }
00408
00409 if (unlikely(lreq.add_rm || lreq.body_lumps)) {
00410 LM_DBG("apply new updates to sip msg\n");
00411 buf1 = build_req_buf_from_sip_req(&lreq,
00412 (unsigned int*)&buf_len1,
00413 &dst, BUILD_NO_LOCAL_VIA|BUILD_NO_VIA1_UPDATE|
00414 BUILD_IN_SHM);
00415 if (likely(buf1)){
00416 shm_free(buf);
00417 buf = buf1;
00418 buf_len = buf_len1;
00419
00420 }
00421 }
00422 lreq.buf=0;
00423 free_sip_msg(&lreq);
00424 }
00425 }
00426 }
00427 #endif
00428
00429 new_cell->method.s = buf;
00430 new_cell->method.len = uac_r->method->len;
00431
00432 request->buffer = buf;
00433 request->buffer_len = buf_len;
00434 new_cell->nr_of_outgoings++;
00435
00436
00437
00438
00439 if(uac_r->cb && insert_tmcb(&(new_cell->tmcb_hl), uac_r->cb_flags,
00440 *(uac_r->cb), uac_r->cbp, NULL)!=1){
00441 ret=E_OUT_OF_MEM;
00442 LOG(L_ERR, "t_uac: short of tmcb shmem\n");
00443 goto error1;
00444 }
00445 if (has_local_reqin_tmcbs())
00446 run_local_reqin_callbacks(new_cell, 0, 0);
00447 #ifdef DIALOG_CALLBACKS
00448 run_trans_dlg_callbacks(uac_r->dialog, new_cell, request);
00449 #endif
00450 if (dst_req) *dst_req = request;
00451 if (dst_cell) *dst_cell = new_cell;
00452 else if(is_ack && dst_req==0){
00453 free_cell(new_cell);
00454 }
00455
00456 return 1;
00457
00458 error1:
00459 if (!is_ack) {
00460 LOCK_HASH(hi);
00461 remove_from_hash_table_unsafe(new_cell);
00462 UNLOCK_HASH(hi);
00463 #ifdef TM_DEL_UNREF
00464 UNREF_FREE(new_cell);
00465 }else
00466 #else
00467 }
00468 #endif
00469 free_cell(new_cell);
00470 error2:
00471 return ret;
00472 }
00473
00474
00475
00476
00477 int prepare_req_within(uac_req_t *uac_r,
00478 struct retr_buf **dst_req)
00479 {
00480 if (!uac_r || !uac_r->method || !uac_r->dialog) {
00481 LOG(L_ERR, "req_within: Invalid parameter value\n");
00482 goto err;
00483 }
00484
00485 if (uac_r->dialog->state != DLG_CONFIRMED) {
00486 LOG(L_ERR, "req_within: Dialog is not confirmed yet\n");
00487 goto err;
00488 }
00489
00490 if ((uac_r->method->len == 3) && (!memcmp("ACK", uac_r->method->s, 3))) goto send;
00491 if ((uac_r->method->len == 6) && (!memcmp("CANCEL", uac_r->method->s, 6))) goto send;
00492 uac_r->dialog->loc_seq.value++;
00493 send:
00494 return t_uac_prepare(uac_r, dst_req, 0);
00495
00496 err:
00497
00498
00499
00500 return -1;
00501 }
00502
00503 static inline void send_prepared_request_impl(struct retr_buf *request, int retransmit)
00504 {
00505 if (SEND_BUFFER(request) == -1) {
00506 LOG(L_ERR, "t_uac: Attempt to send to precreated request failed\n");
00507 }
00508 else if (unlikely(has_tran_tmcbs(request->my_T, TMCB_REQUEST_SENT)))
00509
00510 run_trans_callbacks_with_buf(TMCB_REQUEST_SENT, request, 0, 0,
00511 TMCB_LOCAL_F);
00512
00513 if (retransmit && (start_retr(request)!=0))
00514 LOG(L_CRIT, "BUG: t_uac: failed to start retr. for %p\n", request);
00515 }
00516
00517 void send_prepared_request(struct retr_buf *request)
00518 {
00519 send_prepared_request_impl(request, 1 );
00520 }
00521
00522
00523
00524
00525 int t_uac(uac_req_t *uac_r)
00526 {
00527 return t_uac_with_ids(uac_r, NULL, NULL);
00528 }
00529
00530
00531
00532
00533
00534 int t_uac_with_ids(uac_req_t *uac_r,
00535 unsigned int *ret_index, unsigned int *ret_label)
00536 {
00537 struct retr_buf *request;
00538 struct cell *cell;
00539 int ret;
00540 int is_ack;
00541
00542 ret = t_uac_prepare(uac_r, &request, &cell);
00543 if (ret < 0) return ret;
00544 is_ack = (uac_r->method->len == 3) && (memcmp("ACK", uac_r->method->s, 3)==0) ? 1 : 0;
00545 send_prepared_request_impl(request, !is_ack );
00546 if (is_ack) {
00547 if (cell) free_cell(cell);
00548 if (ret_index && ret_label)
00549 *ret_index = *ret_label = 0;
00550 } else {
00551 if (ret_index && ret_label) {
00552 *ret_index = cell->hash_index;
00553 *ret_label = cell->label;
00554 }
00555 }
00556 return ret;
00557 }
00558
00559 #ifdef WITH_AS_SUPPORT
00560 struct retr_buf *local_ack_rb(sip_msg_t *rpl_2xx, struct cell *trans,
00561 unsigned int branch, str *hdrs, str *body)
00562 {
00563 struct retr_buf *lack;
00564 unsigned int buf_len;
00565 char *buffer;
00566 struct dest_info dst;
00567
00568 buf_len = (unsigned)sizeof(struct retr_buf);
00569 if (! (buffer = build_dlg_ack(rpl_2xx, trans, branch, hdrs, body,
00570 &buf_len, &dst))) {
00571 return 0;
00572 } else {
00573
00574
00575
00576
00577 lack = &((struct retr_buf *)buffer)[-1];
00578 lack->buffer = buffer;
00579 lack->buffer_len = buf_len;
00580 lack->dst = dst;
00581 }
00582
00583
00584 lack->activ_type = TYPE_LOCAL_ACK;
00585 lack->my_T = trans;
00586
00587 return lack;
00588 }
00589
00590 void free_local_ack(struct retr_buf *lack)
00591 {
00592 shm_free(lack);
00593 }
00594
00595 void free_local_ack_unsafe(struct retr_buf *lack)
00596 {
00597 shm_free_unsafe(lack);
00598 }
00599
00606 int ack_local_uac(struct cell *trans, str *hdrs, str *body)
00607 {
00608 struct retr_buf *local_ack, *old_lack;
00609 int ret;
00610 struct tmcb_params onsend_params;
00611
00612
00613
00614 #ifdef EXTRA_DEBUG
00615 if (! trans) {
00616 BUG("no transaction to ACK.\n");
00617 abort();
00618 }
00619 #endif
00620
00621 #define RET_INVALID \
00622 ret = -2; \
00623 goto fin
00624
00625 if (! is_local(trans)) {
00626 ERR("trying to ACK non local transaction (T@%p).\n", trans);
00627 RET_INVALID;
00628 }
00629 if (! is_invite(trans)) {
00630 ERR("trying to ACK non INVITE local transaction (T@%p).\n", trans);
00631 RET_INVALID;
00632 }
00633 if (! trans->uac[0].reply) {
00634 ERR("trying to ACK un-completed INVITE transaction (T@%p).\n", trans);
00635 RET_INVALID;
00636 }
00637
00638 if (! (trans->flags & T_NO_AUTO_ACK)) {
00639 ERR("trying to ACK an auto-ACK transaction (T@%p).\n", trans);
00640 RET_INVALID;
00641 }
00642 if (trans->uac[0].local_ack) {
00643 ERR("trying to rebuild ACK retransmission buffer (T@%p).\n", trans);
00644 RET_INVALID;
00645 }
00646
00647
00648
00649 if (! (local_ack = local_ack_rb(trans->uac[0].reply, trans, 0,
00650 hdrs, body))) {
00651 ERR("failed to build ACK retransmission buffer");
00652 RET_INVALID;
00653 } else {
00654
00655 if ((old_lack = (struct retr_buf *)atomic_cmpxchg_long(
00656 (void *)&trans->uac[0].local_ack, 0, (long)local_ack))) {
00657
00658 ERR("concurrent ACKing for local INVITE detected (T@%p).\n",trans);
00659 free_local_ack(local_ack);
00660 RET_INVALID;
00661 }
00662 }
00663
00664 if (msg_send(&local_ack->dst, local_ack->buffer, local_ack->buffer_len)<0){
00665
00666 ERR("failed to send local ACK (T@%p).\n", trans);
00667 ret = -1;
00668 goto fin;
00669 }
00670 else {
00671 INIT_TMCB_ONSEND_PARAMS(onsend_params, 0, 0, &trans->uac[0].request,
00672 &local_ack->dst,
00673 local_ack->buffer, local_ack->buffer_len,
00674 TMCB_LOCAL_F, 0 , TYPE_LOCAL_ACK);
00675 run_trans_callbacks_off_params(TMCB_REQUEST_SENT, trans, &onsend_params);
00676 }
00677
00678 ret = 0;
00679 fin:
00680
00681
00682
00683
00684
00685
00686 UNREF( trans );
00687 return ret;
00688
00689 #undef RET_INVALID
00690 }
00691 #endif
00692
00693
00694
00695
00696
00697 int req_within(uac_req_t *uac_r)
00698 {
00699 if (!uac_r || !uac_r->method || !uac_r->dialog) {
00700 LOG(L_ERR, "req_within: Invalid parameter value\n");
00701 goto err;
00702 }
00703
00704 if ((uac_r->method->len == 3) && (!memcmp("ACK", uac_r->method->s, 3))) goto send;
00705 if ((uac_r->method->len == 6) && (!memcmp("CANCEL", uac_r->method->s, 6))) goto send;
00706 uac_r->dialog->loc_seq.value++;
00707 send:
00708 return t_uac(uac_r);
00709
00710 err:
00711
00712
00713 return -1;
00714 }
00715
00716
00717
00718
00719
00720
00721 int req_outside(uac_req_t *uac_r, str* ruri, str* to, str* from, str *next_hop)
00722 {
00723 str callid, fromtag;
00724
00725 if (check_params(uac_r, to, from) < 0) goto err;
00726
00727 generate_callid(&callid);
00728 generate_fromtag(&fromtag, &callid);
00729
00730 if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &uac_r->dialog) < 0) {
00731 LOG(L_ERR, "req_outside(): Error while creating new dialog\n");
00732 goto err;
00733 }
00734
00735 if (ruri) {
00736 uac_r->dialog->rem_target.s = ruri->s;
00737 uac_r->dialog->rem_target.len = ruri->len;
00738
00739 }
00740
00741 if (next_hop) uac_r->dialog->dst_uri = *next_hop;
00742 w_calculate_hooks(uac_r->dialog);
00743
00744 return t_uac(uac_r);
00745
00746 err:
00747
00748
00749 return -1;
00750 }
00751
00752
00753
00754
00755
00756
00757 int request(uac_req_t *uac_r, str* ruri, str* to, str* from, str *next_hop)
00758 {
00759 str callid, fromtag;
00760 dlg_t* dialog;
00761 int res;
00762
00763 if (check_params(uac_r, to, from) < 0) goto err;
00764
00765 generate_callid(&callid);
00766 generate_fromtag(&fromtag, &callid);
00767
00768 if (new_dlg_uac(&callid, &fromtag, DEFAULT_CSEQ, from, to, &dialog) < 0) {
00769 LOG(L_ERR, "request(): Error while creating temporary dialog\n");
00770 goto err;
00771 }
00772
00773 if (ruri) {
00774 dialog->rem_target.s = ruri->s;
00775 dialog->rem_target.len = ruri->len;
00776
00777 }
00778
00779 if (next_hop) dialog->dst_uri = *next_hop;
00780 w_calculate_hooks(dialog);
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 uac_r->dialog = dialog;
00794 res = t_uac(uac_r);
00795 dialog->rem_target.s = 0;
00796 dialog->dst_uri.s = 0;
00797 free_dlg(dialog);
00798 uac_r->dialog = 0;
00799 return res;
00800
00801 err:
00802
00803
00804 return -1;
00805 }