From f564c0d33974eeaa1833abeb7972f5d207c5663f Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Fri, 12 Nov 2021 17:16:37 +0200 Subject: [PATCH] tm: API improvement, new function introduced: t_append_branch_by_contact() New module functions introduced: - t_append_branch_by_contact() This commit introduces a possibility of TM's API to append a branch based on specific location (Contact's URI). Indeed the 't_append_branch_by_contact()' is a corrected copy of the 't_append_branches()', which instead takes Contact as a parameter of str type. The separate function has been introduced, in order to save full back-compatibility, and not affect existing implementation. --- src/modules/tm/t_append_branches.c | 206 +++++++++++++++++++++++++++++ src/modules/tm/t_append_branches.h | 4 + src/modules/tm/tm_load.c | 1 + src/modules/tm/tm_load.h | 1 + 4 files changed, 212 insertions(+) diff --git a/src/modules/tm/t_append_branches.c b/src/modules/tm/t_append_branches.c index c754a908234..2daca1a593d 100644 --- a/src/modules/tm/t_append_branches.c +++ b/src/modules/tm/t_append_branches.c @@ -237,3 +237,209 @@ int t_append_branches(void) { } return ret; } + +/* append a new transaction based on desired Contact hf value + * contact parameter must be of syntax (no hf parameters): + * sip:@: */ +int t_append_branch_by_contact(str * contact) { + struct cell *t = NULL; + struct sip_msg *orig_msg = NULL; + struct sip_msg *faked_req; + int faked_req_len = 0; + + short outgoings; + + int success_branch; + + str current_uri; + str dst_uri, path, instance, ruid, location_ua; + struct socket_info* si; + int q, i, found, append; + flag_t backup_bflags = 0; + flag_t bflags = 0; + int new_branch, branch_ret, lowest_ret; + branch_bm_t added_branches; + int replies_locked = 0; + int ret = 0; + + t = get_t(); + if(t == NULL) + { + LM_ERR("cannot get transaction\n"); + return -1; + } + + LM_DBG("transaction %u:%u in status %d\n", t->hash_index, t->label, t->uas.status); + + /* test if transaction has already been canceled */ + if (t->flags & T_CANCELED) { + ser_error=E_CANCELED; + return -1; + } + + if ((t->uas.status >= 200 && t->uas.status<=399) + || ((t->uas.status >= 600 && t->uas.status) + && !(t->flags & (T_6xx | T_DISABLE_6xx))) ) { + LM_DBG("transaction %u:%u in status %d: cannot append new branch\n", + t->hash_index, t->label, t->uas.status); + return -1; + } + + /* set the lock on the transaction here */ + LOCK_REPLIES(t); + replies_locked = 1; + outgoings = t->nr_of_outgoings; + orig_msg = t->uas.request; + + LM_DBG("Call %.*s: %d (%d) outgoing branches\n",orig_msg->callid->body.len, + orig_msg->callid->body.s,outgoings, nr_branches); + + lowest_ret=E_UNSPEC; + added_branches=0; + + /* it's a "late" branch so the on_branch variable has already been + reset by previous execution of t_forward_nonack: we use the saved + value */ + if (t->on_branch_delayed) { + /* tell add_uac that it should run branch route actions */ + set_branch_route(t->on_branch_delayed); + } + faked_req = fake_req(orig_msg, 0, NULL, &faked_req_len); + if (faked_req==NULL) { + LM_ERR("fake_req failed\n"); + return -1; + } + + /* fake also the env. conforming to the fake msg */ + faked_env( t, faked_req, 0); + + /* DONE with faking ;-) -> run the failure handlers */ + init_branch_iterator(); + + while((current_uri.s=next_branch( ¤t_uri.len, &q, &dst_uri, &path, + &bflags, &si, &ruid, &instance, &location_ua))) { + LM_DBG("Current uri %.*s\n",current_uri.len, current_uri.s); + + append = 1; + if (strstr(current_uri.s, contact->s) == NULL) { + append = 0; + } + + /* do not append the branch if a contact does not match */ + if (!append) + continue; + + LM_DBG("Branch will be appended for contact <%.*s>\n", contact->len, contact->s); + + found = 0; + for (i=0; iuac[i].ruid.len == ruid.len + && !memcmp(t->uac[i].ruid.s, ruid.s, ruid.len) + && t->uac[i].uri.len == current_uri.len + && !memcmp(t->uac[i].uri.s, current_uri.s, current_uri.len)) { + LM_DBG("branch already added [%.*s]\n", ruid.len, ruid.s); + found = 1; + break; + } + } + if (found) + continue; + + setbflagsval(0, bflags); + new_branch=add_uac( t, faked_req, ¤t_uri, + (dst_uri.len) ? (&dst_uri) : ¤t_uri, + &path, 0, si, faked_req->fwd_send_flags, + PROTO_NONE, (dst_uri.len)?0:UAC_SKIP_BR_DST_F, &instance, + &ruid, &location_ua); + + LM_DBG("added branch [%.*s] with ruid [%.*s]\n", + current_uri.len, current_uri.s, ruid.len, ruid.s); + + /* test if cancel was received meanwhile */ + if (t->flags & T_CANCELED) goto canceled; + + if (new_branch>=0) + added_branches |= 1<callid->body.len, orig_msg->callid->body.s,outgoings, nr_branches); + setbflagsval(0, backup_bflags); + + /* update message flags, if changed in branch route */ + t->uas.request->flags = faked_req->flags; + + if (added_branches==0) { + if(lowest_ret!=E_CFG) + LM_ERR("failure to add branches (%d)\n", lowest_ret); + ser_error=lowest_ret; + ret = lowest_ret; + goto done; + } + + ser_error=0; /* clear branch adding errors */ + /* send them out now */ + success_branch=0; + /* since t_append_branch can only be called from REQUEST_ROUTE, always lock replies */ + + for (i=outgoings; inr_of_outgoings; i++) { + if (added_branches & (1<=0){ /* some kind of success */ + if (branch_ret==i) { /* success */ + success_branch++; + if (unlikely(has_tran_tmcbs(t, TMCB_REQUEST_OUT))) + run_trans_callbacks_with_buf( TMCB_REQUEST_OUT, + &t->uac[nr_branches].request, + faked_req, 0, TMCB_NONE_F); + } + else /* new branch added */ + added_branches |= 1<uas.request->flags = faked_req->flags; + /* if needed unlock transaction's replies */ + /* restore the number of outgoing branches + * since new branches have not been completed */ + t->nr_of_outgoings = outgoings; + ser_error=E_CANCELED; + ret = -1; +done: + /* restore original environment and free the fake msg */ + faked_env( t, 0, 0); + free_faked_req(faked_req, faked_req_len); + + if (likely(replies_locked)) { + replies_locked = 0; + UNLOCK_REPLIES(t); + } + return ret; +} \ No newline at end of file diff --git a/src/modules/tm/t_append_branches.h b/src/modules/tm/t_append_branches.h index 2e1cbfb38a0..a502909fbf7 100644 --- a/src/modules/tm/t_append_branches.h +++ b/src/modules/tm/t_append_branches.h @@ -34,4 +34,8 @@ int t_append_branches(void); typedef int (*t_append_branches_f)(void); +/* append a new transaction based on desired Contact hf value */ +int t_append_branch_by_contact(str * contact); +typedef int (*t_append_branch_by_contact_f)(str * contact); + #endif diff --git a/src/modules/tm/tm_load.c b/src/modules/tm/tm_load.c index 911be5d9175..c6fd3056550 100644 --- a/src/modules/tm/tm_load.c +++ b/src/modules/tm/tm_load.c @@ -134,6 +134,7 @@ int load_tm( struct tm_binds *tmb) tmb->tm_ctx_get = tm_ctx_get; #endif tmb->t_append_branches = t_append_branches; + tmb->t_append_branch_by_contact = t_append_branch_by_contact; tmb->t_load_contacts = t_load_contacts; tmb->t_next_contacts = t_next_contacts; tmb->set_fr = t_set_fr; diff --git a/src/modules/tm/tm_load.h b/src/modules/tm/tm_load.h index a0f3afde001..7ecfd1b5f3c 100644 --- a/src/modules/tm/tm_load.h +++ b/src/modules/tm/tm_load.h @@ -117,6 +117,7 @@ struct tm_binds { void* reserved5; #endif t_append_branches_f t_append_branches; + t_append_branch_by_contact_f t_append_branch_by_contact; cmd_function t_load_contacts; cmd_function t_next_contacts; tset_fr_f set_fr;