From 0e10aab53ea8c28dacb3fe2d76262afde1c592e9 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Fri, 19 Nov 2021 13:50:45 +0200 Subject: [PATCH] TT#144053 TM: 't_append_branches()' improvement / TSILO: add 'ts_append_by_contact()' This commit deprecates: * tm: previously added function t_append_branch_by_contact(). * tsilo: previously added functions ts_append_by_contact() / ts_append_by_contact_to() TM. This commit introduces a possibility of TM's API to append a branch based on a specific location (Contact's URI). The function 't_append_branches()' has been extended, and is now able to obtain a parameter Contact of str type and takes care of appending a branch only for it. The way how the function acts now depends on if the contact parameter of str type is given or not (empty or not). If the contact parameter is given, then only a desired location is meant for appending. If not found in the location table, an append will not happen for this AOR. Otherwise create branches for all existing location records of this particular AOR. Search for locations is done in the location table. TSILO. Add support of a lookup and branch creating by contact Improvement of the TSILO module, which allows to run a lookup using the provided RURI, but only to create a new branch for the Contact, which is set in the currently processed REGISTER. Or optionally a Contact URI value given as a parameter to the function. If the Contact URI for a lookup, is given as a parameter, it is possible to provide it as a pseudo-variable. Hence it is now possible to append new branch(es) for only UAC(s) getting REGISTERED at the moment of calling script function 'ts_append_by_contact()'. Previously it was only possible to create new branches for all previously present location records (for this specific URI), which was in some circumstances undesired. New script functions introduced: ts_append_by_contact(table, ruri [, contact]) New module functions introduced: * w_ts_append_by_contact2() / ki_ts_append_by_contact() * w_ts_append_by_contact3 / ki_ts_append_by_contact_uri() Change-Id: Idd4775000f8e80999455680704c64a1208c67b3f --- debian/patches/series | 4 +- .../tm_t_append_branch_by_contact.patch | 244 ---- .../tsilo_add_ts_append_by_contact.patch | 461 -------- ...ement_t_append_branches_with_contact.patch | 617 ++++++++++ .../upstream/tsilo_append_by_contact.patch | 1051 +++++++++++++++++ 5 files changed, 1670 insertions(+), 707 deletions(-) delete mode 100644 debian/patches/sipwise/tm_t_append_branch_by_contact.patch delete mode 100644 debian/patches/sipwise/tsilo_add_ts_append_by_contact.patch create mode 100644 debian/patches/upstream/tm_api_improvement_t_append_branches_with_contact.patch create mode 100644 debian/patches/upstream/tsilo_append_by_contact.patch diff --git a/debian/patches/series b/debian/patches/series index d5ec8ce6a..768268149 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -43,6 +43,8 @@ upstream/lcr-source-port-check-for-from_any_gw-and-from_gw.patch upstream/lcr-remove-excessive-checks-for-the-src_port-accurac.patch upstream/lcr-improve-binary-search-to-support-match-including-src-port.patch upstream/nathelper-fix_nated_sdp-added-ignoring-RFC3605-param.patch +upstream/tm_api_improvement_t_append_branches_with_contact.patch +upstream/tsilo_append_by_contact.patch ### relevant for upstream sipwise/pua_dialoginfo-refresh_pubruri_avps_flag.patch sipwise/pua_dialoginfo-local_identity_dlg_var.patch @@ -62,8 +64,6 @@ sipwise/kamctl-TMPDIR-config.patch sipwise/lcr-stopper_mode-parameter.patch sipwise/lcr_improve_comparison_based_on_gws_port.patch # -sipwise/tm_t_append_branch_by_contact.patch -sipwise/tsilo_add_ts_append_by_contact.patch sipwise/pv-headers-clone-branch-ignore-skip-header.patch upstream/permissions-don-t-remove-old-data-at-the-end-of-the-.patch upstream/permissions-trusted_cleanup_interval.patch diff --git a/debian/patches/sipwise/tm_t_append_branch_by_contact.patch b/debian/patches/sipwise/tm_t_append_branch_by_contact.patch deleted file mode 100644 index e340d9758..000000000 --- a/debian/patches/sipwise/tm_t_append_branch_by_contact.patch +++ /dev/null @@ -1,244 +0,0 @@ ---- a/src/modules/tm/t_append_branches.c -+++ b/src/modules/tm/t_append_branches.c -@@ -237,3 +237,209 @@ done: - } - 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 ---- 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 ---- 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; ---- a/src/modules/tm/tm_load.h -+++ b/src/modules/tm/tm_load.h -@@ -118,6 +118,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; diff --git a/debian/patches/sipwise/tsilo_add_ts_append_by_contact.patch b/debian/patches/sipwise/tsilo_add_ts_append_by_contact.patch deleted file mode 100644 index 459af9525..000000000 --- a/debian/patches/sipwise/tsilo_add_ts_append_by_contact.patch +++ /dev/null @@ -1,461 +0,0 @@ -From: Sipwise Development Team -Date: Tue, 2 Nov 2021 11:14:23 +0100 -Subject: tsilo_add_ts_append_by_contact - ---- - src/modules/tsilo/ts_append.c | 116 ++++++++++++++++++ - src/modules/tsilo/ts_append.h | 2 + - src/modules/tsilo/tsilo.c | 269 +++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 386 insertions(+), 1 deletion(-) - -diff --git a/src/modules/tsilo/ts_append.c b/src/modules/tsilo/ts_append.c -index 7d95186..1847ac1 100644 ---- a/src/modules/tsilo/ts_append.c -+++ b/src/modules/tsilo/ts_append.c -@@ -139,3 +139,119 @@ done: - - return ret; - } -+ -+int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table) { -+ ts_urecord_t* _r; -+ ts_transaction_t* ptr; -+ -+ struct sip_uri p_uri; -+ struct sip_uri c_uri; -+ str *t_uri; -+ -+ int res; -+ int appended; -+ -+ /* parse R-URI */ -+ if (use_domain) { -+ t_uri = ruri; -+ } else { -+ if (parse_uri(ruri->s, ruri->len, &p_uri) < 0) { -+ LM_ERR("tsilo: failed to parse uri %.*s\n", ruri->len, ruri->s); -+ return -1; -+ } -+ t_uri = &p_uri.user; -+ } -+ -+ /* parse contact */ -+ if (parse_uri(contact->s, contact->len, &c_uri) < 0) { -+ LM_ERR("tsilo: failed to parse contact %.*s\n", ruri->len, ruri->s); -+ return -1; -+ } -+ -+ /* find urecord in TSILO cache */ -+ lock_entry_by_ruri(t_uri); -+ res = get_ts_urecord(t_uri, &_r); -+ -+ if (res != 0) { -+ LM_ERR("tsilo: failed to retrieve record for %.*s\n", t_uri->len, t_uri->s); -+ unlock_entry_by_ruri(t_uri); -+ return -1; -+ } -+ -+ /* cycle through existing transactions */ -+ ptr = _r->transactions; -+ while(ptr) { -+ LM_DBG("tsilo: transaction %u:%u found for %.*s, going to append branches\n", -+ ptr->tindex, ptr->tlabel, t_uri->len, t_uri->s); -+ /* append only if the desired contact has been found in locations */ -+ appended = ts_append_by_contact_to(msg, ptr->tindex, ptr->tlabel, table, ruri, contact); -+ if (appended > 0) -+ update_stat(added_branches, appended); -+ ptr = ptr->next; -+ } -+ -+ unlock_entry_by_ruri(t_uri); -+ -+ return 1; -+} -+ -+int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact) { -+ struct cell *t=0; -+ struct cell *orig_t; /* a pointer to an existing transaction or 0 if lookup fails*/ -+ struct sip_msg *orig_msg; -+ int ret; -+ str stable; -+ -+ LM_DBG("tsilo: trying to append based on contact <%.*s>\n", contact->len, contact->s); -+ -+ /* lookup a transaction based on its identifier (hash_index:label) */ -+ orig_t = _tmb.t_gett(); -+ if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0) -+ { -+ LM_ERR("tsilo: transaction [%u:%u] not found\n", tindex, tlabel); -+ ret = -1; -+ goto done; -+ } -+ -+ /* check if the dialog is still in the early stage */ -+ if (t->flags & T_CANCELED) { -+ LM_DBG("tsilo: trasaction [%u:%u] was cancelled\n", tindex, tlabel); -+ ret = -2; -+ goto done; -+ } -+ if (t->uas.status >= 200) { -+ LM_DBG("tsilo: trasaction [%u:%u] sent out a final response already - %d\n", -+ tindex, tlabel, t->uas.status); -+ ret = -3; -+ goto done; -+ } -+ -+ /* get original (very first) request of the transaction */ -+ orig_msg = t->uas.request; -+ stable.s = table; -+ stable.len = strlen(stable.s); -+ -+ if(uri==NULL || uri->s==NULL || uri->len<=0) { -+ ret = _regapi.lookup_to_dset(orig_msg, &stable, NULL); -+ } else { -+ ret = _regapi.lookup_to_dset(orig_msg, &stable, uri); -+ } -+ -+ if(ret != 1) { -+ LM_ERR("tsilo: transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret); -+ ret = -4; -+ goto done; -+ } -+ -+ /* start the transaction only for the desired contact -+ contact must be of syntax: sip:@: with no parameters list*/ -+ ret = _tmb.t_append_branch_by_contact(contact); -+ -+done: -+ /* unref the transaction which had been referred by t_lookup_ident() call. -+ * Restore the original transaction (if any) */ -+ if(t) _tmb.unref_cell(t); -+ _tmb.t_sett(orig_t, T_BR_UNDEFINED); -+ -+ return ret; -+} -diff --git a/src/modules/tsilo/ts_append.h b/src/modules/tsilo/ts_append.h -index 56f9120..461f888 100644 ---- a/src/modules/tsilo/ts_append.h -+++ b/src/modules/tsilo/ts_append.h -@@ -24,5 +24,7 @@ - - int ts_append(struct sip_msg* msg, str *ruri, char *table); - int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri); -+int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table); -+int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact); - - #endif -diff --git a/src/modules/tsilo/tsilo.c b/src/modules/tsilo/tsilo.c -index 0c531ac..2eefb2f 100644 ---- a/src/modules/tsilo/tsilo.c -+++ b/src/modules/tsilo/tsilo.c -@@ -34,6 +34,8 @@ - #include "../../core/rpc_lookup.h" - #include "../../core/kemi.h" - -+#include "../../core/parser/contact/parse_contact.h" -+ - #include "ts_hash.h" - #include "ts_handlers.h" - #include "ts_append.h" -@@ -61,7 +63,9 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *d, c - static int fixup_ts_append_to(void** param, int param_no); - static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri); - static int fixup_ts_append(void** param, int param_no); -- -+static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri); -+static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact); -+static int fixup_ts_append_by_contact(void** param, int param_no); - static int w_ts_store(struct sip_msg* msg, char *p1, char *p2); - static int w_ts_store1(struct sip_msg* msg, char *_ruri, char *p2); - -@@ -78,6 +82,10 @@ static cmd_export_t cmds[]={ - fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE }, - {"ts_append", (cmd_function)w_ts_append, 2, - fixup_ts_append, 0, REQUEST_ROUTE | FAILURE_ROUTE }, -+ {"ts_append_by_contact", (cmd_function)w_ts_append_by_contact2, 2, /* for two parameters */ -+ fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE }, -+ {"ts_append_by_contact", (cmd_function)w_ts_append_by_contact3, 3, /* for three parameters */ -+ fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE }, - {"ts_store", (cmd_function)w_ts_store, 0, - 0 , 0, REQUEST_ROUTE | FAILURE_ROUTE }, - {"ts_store", (cmd_function)w_ts_store1, 1, -@@ -241,6 +249,23 @@ static int fixup_ts_append(void** param, int param_no) - return 0; - } - -+static int fixup_ts_append_by_contact(void** param, int param_no) -+{ -+ if (param_no==1) { -+ if(strlen((char*)*param)<=1 && (*(char*)(*param)==0 || *(char*)(*param)=='0')) { -+ *param = (void*)0; -+ LM_ERR("empty table name\n"); -+ return -1; -+ } -+ } -+ -+ if (param_no==2 || param_no==3) { -+ return fixup_spve_null(param, 1); -+ } -+ -+ return 0; -+} -+ - /** - * - */ -@@ -357,6 +382,238 @@ static int ki_ts_append_to_uri(sip_msg_t* _msg, int tindex, int tlabel, - _table->s, _uri); - } - -+/** -+ * -+ */ -+static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri) { -+ str ruri = STR_NULL; -+ str ruri_fixed = STR_NULL; -+ -+ str contact = STR_NULL; -+ str tmp_contact = STR_NULL; -+ struct sip_uri curi; -+ -+ int rc; -+ -+ /* parse R-URI */ -+ if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) { -+ LM_ERR("failed to convert r-uri parameter\n"); -+ return -1; -+ } -+ -+ if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) { -+ LM_ERR("tsilo: invalid ruri parameter (empty or zero length).\n"); -+ return -1; -+ } -+ -+ if (pkg_str_dup(&ruri, &ruri_fixed) < 0) { -+ LM_ERR("failed to copy r-uri parameter\n"); -+ return -1; -+ } -+ -+ if (ts_check_uri(&ruri) < 0) { -+ LM_ERR("tsilo: failed to parse R-URI.\n"); -+ return -1; -+ } -+ -+ /* parse Contact header */ -+ if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) -+ || !_msg->contact) { -+ LM_WARN("tsilo: missing contact header or the value is empty/malformed.\n"); -+ return -1; -+ } -+ if (_msg->contact) { -+ if (parse_contact(_msg->contact) < 0) { -+ LM_WARN("tsilo: failed to parse Contact header.\n"); -+ return -1; -+ } -+ if (parse_uri( -+ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, -+ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len, -+ &curi) != 0 ) { -+ if (ts_check_uri(&_msg->contact->body) < 0) { /* one more attempt */ -+ LM_WARN("tsilo: failed to parse Contact header.\n"); -+ return -1; -+ } -+ } -+ -+ tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len; -+ tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1); -+ if (tmp_contact.s == NULL) { -+ PKG_MEM_ERROR; -+ return -1; -+ } -+ memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len); -+ tmp_contact.s[tmp_contact.len] = '\0'; -+ -+ if (pkg_str_dup(&contact, &tmp_contact) < 0) { -+ if (pkg_str_dup(&contact, &_msg->contact->body) < 0) { /* one more attempt */ -+ LM_ERR("tsilo: problems when calling ts_append_contact(), cannot copy Contact parameter.\n"); -+ return -1; -+ } -+ } -+ } -+ -+ /* contact must be of syntax: sip:@: with no parameters list */ -+ rc = ts_append_by_contact(_msg, &ruri, &contact, _table); -+ -+ /* free previously used memory */ -+ pkg_free(ruri.s); -+ pkg_free(contact.s); -+ pkg_free(tmp_contact.s); -+ -+ return rc; -+} -+ -+/** -+ * -+ */ -+static int ki_ts_append_by_contact(sip_msg_t* _msg, str *_table, str *_ruri) { -+ str ruri = STR_NULL; -+ str contact = STR_NULL; -+ str tmp_contact = STR_NULL; -+ struct sip_uri curi; -+ int rc; -+ -+ /* parse R-URI */ -+ if (ts_check_uri(_ruri) < 0) -+ return -1; -+ if (pkg_str_dup(&ruri, _ruri) < 0) -+ return -1; -+ -+ /* parse Contact header */ -+ if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) || !_msg->contact) -+ return -1; -+ -+ if (_msg->contact) { -+ if (parse_contact(_msg->contact) < 0) -+ return -1; -+ if (parse_uri( -+ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, -+ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len, -+ &curi) != 0 ) { -+ if (ts_check_uri(&_msg->contact->body) < 0) /* one more attempt */ -+ return -1; -+ } -+ -+ tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len; -+ tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1); -+ if (tmp_contact.s == NULL) { -+ PKG_MEM_ERROR; -+ return -1; -+ } -+ memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len); -+ tmp_contact.s[tmp_contact.len] = '\0'; -+ -+ if (pkg_str_dup(&contact, &tmp_contact) < 0) { -+ if (pkg_str_dup(&contact, &_msg->contact->body) < 0) /* one more attempt */ -+ return -1; -+ } -+ } -+ -+ /* contact must be of syntax: sip:@: with no parameters list */ -+ rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); -+ -+ pkg_free(ruri.s); -+ pkg_free(contact.s); -+ pkg_free(tmp_contact.s); -+ -+ return rc; -+} -+ -+/** -+ * -+ */ -+static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact) { -+ str ruri = STR_NULL; -+ str ruri_fixed = STR_NULL; -+ -+ str contact = STR_NULL; -+ str contact_fixed = STR_NULL; -+ -+ int rc; -+ -+ /* parse R-URI */ -+ if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) { -+ LM_ERR("failed to convert r-uri parameter\n"); -+ return -1; -+ } -+ -+ if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) { -+ LM_ERR("tsilo: invalid ruri parameter.\n"); -+ return -1; -+ } -+ -+ if (pkg_str_dup(&ruri, &ruri_fixed) < 0) { -+ LM_ERR("failed to copy r-uri parameter\n"); -+ return -1; -+ } -+ -+ if (ts_check_uri(&ruri) < 0) { -+ LM_ERR("tsilo: failed to parse R-URI.\n"); -+ return -1; -+ } -+ -+ /* parse Contact header */ -+ if (fixup_get_svalue(_msg, (gparam_t*)_contact, &contact_fixed)!=0) { -+ LM_ERR("failed to convert contact parameter\n"); -+ return -1; -+ } -+ -+ if (_contact==NULL || strlen(_contact) <= 0 || contact_fixed.len <= 0) { -+ LM_ERR("tsilo: invalid contact parameter.\n"); -+ return -1; -+ } -+ -+ if (pkg_str_dup(&contact, &contact_fixed) < 0) { -+ LM_ERR("failed to copy r-uri parameter\n"); -+ return -1; -+ } -+ -+ if (ts_check_uri(&contact) < 0) { -+ LM_ERR("tsilo: failed to parse Contact parameter.\n"); -+ return -1; -+ } -+ -+ /* contact must be of syntax: sip:@: with no parameters list */ -+ rc = ts_append_by_contact(_msg, &ruri, &contact, _table); -+ -+ pkg_free(ruri.s); -+ pkg_free(contact.s); -+ -+ return rc; -+} -+ -+/** -+ * -+ */ -+static int ki_ts_append_by_contact_uri(sip_msg_t* _msg, str *_table, str *_ruri, str *_contact) { -+ str ruri = STR_NULL; -+ str contact = STR_NULL; -+ -+ int rc; -+ -+ /* parse R-URI */ -+ if(ts_check_uri(_ruri) < 0) -+ return -1; -+ if (pkg_str_dup(&ruri, _ruri) < 0) -+ return -1; -+ -+ /* parse Contact header */ -+ if (ts_check_uri(_contact) < 0) -+ return -1; -+ if (pkg_str_dup(&contact, _contact) < 0) -+ return -1; -+ -+ /* contact must be of syntax: sip:@: with no parameters list */ -+ rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); -+ -+ pkg_free(ruri.s); -+ pkg_free(contact.s); -+ -+ return rc; -+} -+ - /** - * - */ -@@ -417,6 +674,16 @@ static sr_kemi_t sr_kemi_tsilo_exports[] = { - { SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_STR, - SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE } - }, -+ { str_init("tsilo"), str_init("ts_append_by_contact"), -+ SR_KEMIP_INT, ki_ts_append_by_contact, -+ { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, -+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } -+ }, -+ { str_init("tsilo"), str_init("ts_append_by_contact_uri"), -+ SR_KEMIP_INT, ki_ts_append_by_contact_uri, -+ { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR, -+ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } -+ }, - - { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } } - }; diff --git a/debian/patches/upstream/tm_api_improvement_t_append_branches_with_contact.patch b/debian/patches/upstream/tm_api_improvement_t_append_branches_with_contact.patch new file mode 100644 index 000000000..503526edf --- /dev/null +++ b/debian/patches/upstream/tm_api_improvement_t_append_branches_with_contact.patch @@ -0,0 +1,617 @@ +From f564c0d33974eeaa1833abeb7972f5d207c5663f Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Fri, 12 Nov 2021 17:16:37 +0200 +Subject: [PATCH 1/2] 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 c754a90823..2daca1a593 100644 +--- a/src/modules/tm/t_append_branches.c ++++ b/src/modules/tm/t_append_branches.c +@@ -237,3 +237,209 @@ done: + } + 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 2e1cbfb38a..a502909fbf 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 911be5d917..c6fd305655 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 a0f3afde00..7ecfd1b5f3 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; +-- +2.25.1 + + +From cb1b78e7bc8d61261e429664c6deb8bb1b4b53d0 Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Sun, 14 Nov 2021 22:59:58 +0200 +Subject: [PATCH 2/2] tm: merge t_append_branches() and + t_append_branch_by_contact() + +Because the implementation of the functions +'t_append_branches()' and 't_append_branch_by_contact()' is pretty +much the same, it's proposed to merge them into one: +'t_append_branches()' + +The way how the function acts now depends on if the contact +parameter of str type is given or not (empty or not). +If the contact parameter is given, then only a desired location +is meant for appending. If not found in the location table, +an append will not happen for this AOR. + +Otherwise create branches for all existing location records +of this particular AOR. Search for locations is done in the location table. +--- + src/modules/tm/t_append_branches.c | 228 ++++------------------------- + src/modules/tm/t_append_branches.h | 8 +- + src/modules/tm/tm_load.c | 1 - + src/modules/tm/tm_load.h | 1 - + 4 files changed, 28 insertions(+), 210 deletions(-) + +diff --git a/src/modules/tm/t_append_branches.c b/src/modules/tm/t_append_branches.c +index 2daca1a593..203f67a36a 100644 +--- a/src/modules/tm/t_append_branches.c ++++ b/src/modules/tm/t_append_branches.c +@@ -46,7 +46,18 @@ + #include "t_reply.h" + #include "t_append_branches.h" + +-int t_append_branches(void) { ++/* this function can act in two ways: ++ * - first way, create branches for all existing location records ++ * of this particular AOR. Search for locations is done in ++ * the location table. ++ * - second way, if the contact parameter is given, ++ * then only a desired location is meant for appending, ++ * if not found in the location table, an append will not happen ++ * for this AOR. ++ * ++ * If the contact parameter is given, it must be of syntax: ++ * sip:@: (without parameters) */ ++int t_append_branches(str * contact) { + struct cell *t = NULL; + struct sip_msg *orig_msg = NULL; + struct sip_msg *faked_req; +@@ -59,7 +70,7 @@ int t_append_branches(void) { + str current_uri; + str dst_uri, path, instance, ruid, location_ua; + struct socket_info* si; +- int q, i, found; ++ int q, i, found, append; + flag_t backup_bflags = 0; + flag_t bflags = 0; + int new_branch, branch_ret, lowest_ret; +@@ -125,212 +136,25 @@ int t_append_branches(void) { + &bflags, &si, &ruid, &instance, &location_ua))) { + LM_DBG("Current uri %.*s\n",current_uri.len, current_uri.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; +- } ++ /* if the contact parameter is given, then append by ++ an exact location that has been requested for this function call */ ++ if (contact->s != NULL && contact->len != 0) { + +- 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 */ ++ LM_DBG("Comparing requested contact <%.*s> against location <%.*s>\n", ++ contact->len, contact->s, current_uri.len, current_uri.s); + +- 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<s) == NULL) { ++ append = 0; /* this while cycle will be stopped */ + } +- } +- } +- if (success_branch<=0) { +- /* return always E_SEND for now +- * (the real reason could be: denied by onsend routes, blocklisted, +- * send failed or any of the errors listed before + dns failed +- * when attempting dns failover) */ +- ser_error=E_SEND; +- /* else return the last error (?) */ +- ret = -1; +- goto done; +- } +- +- ser_error=0; /* clear branch send errors, we have overall success */ +- set_kr(REQ_FWDED); +- ret = success_branch; +- goto done; +- +-canceled: +- LM_DBG("cannot append branches to a canceled transaction\n"); +- /* reset processed branches */ +- clear_branches(); +- /* restore backup flags from initial env */ +- setbflagsval(0, backup_bflags); +- /* update message flags, if changed in branch route */ +- t->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; +-} +- +-/* 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); ++ /* do not append the branch if a contact does not match */ ++ if (!append) ++ continue; + +- append = 1; +- if (strstr(current_uri.s, contact->s) == NULL) { +- append = 0; ++ LM_DBG("Branch will be appended for contact <%.*s>\n", contact->len, contact->s); + } + +- /* 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 +@@ -442,4 +266,4 @@ done: + 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 a502909fbf..1baec4acd0 100644 +--- a/src/modules/tm/t_append_branches.h ++++ b/src/modules/tm/t_append_branches.h +@@ -31,11 +31,7 @@ + #include "../../core/proxy.h" + #include "h_table.h" + +-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); ++int t_append_branches(str * contact); ++typedef int (*t_append_branches_f)(str * contact); + + #endif +diff --git a/src/modules/tm/tm_load.c b/src/modules/tm/tm_load.c +index c6fd305655..911be5d917 100644 +--- a/src/modules/tm/tm_load.c ++++ b/src/modules/tm/tm_load.c +@@ -134,7 +134,6 @@ 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 7ecfd1b5f3..a0f3afde00 100644 +--- a/src/modules/tm/tm_load.h ++++ b/src/modules/tm/tm_load.h +@@ -117,7 +117,6 @@ 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; +-- +2.25.1 + diff --git a/debian/patches/upstream/tsilo_append_by_contact.patch b/debian/patches/upstream/tsilo_append_by_contact.patch new file mode 100644 index 000000000..eb962b1a3 --- /dev/null +++ b/debian/patches/upstream/tsilo_append_by_contact.patch @@ -0,0 +1,1051 @@ +From 7265f1cf7c57d258538119bc0d41146a04183eec Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Fri, 12 Nov 2021 15:30:44 +0200 +Subject: [PATCH] tsilo: Add support of a lookup and branch creating by contact + +Improvement of the TSILO module, which allows to run a lookup using the provided RURI, +but only to create a new branch for the Contact, which is set in the currently processed REGISTER. +Or optionally a Contact URI value given as a parameter to the function. +If the Contact URI for a lookup, is given as a parameter, +it is possible to provide it as a pseudo-variable. + +Hence it is now possible to append new branch(es) for only UAC(s) +getting REGISTERED at the moment of calling 'ts_append_by_contact()'. + +Previously it was only possible to call 'ts_append()' and create new branches +for all previously present location records (for this specific URI), which was in some circumstsances undersired. + +New script functions introduced: +- ts_append_by_contact(table, ruri [, contact]) + +New module functions introduced: +- w_ts_append_by_contact2() / ki_ts_append_by_contact() +- w_ts_append_by_contact3 / ki_ts_append_by_contact_uri() +- ts_append_by_contact() / ts_append_by_contact_to() + +Backwards compatibility is saved, the new functionality is not overlapping with +the previously existing implementation, hence it only acts when the new script function +ts_append_by_contact() is used. + +The documentation has been updated accordingly. +--- + src/modules/tsilo/doc/tsilo.xml | 5 + + src/modules/tsilo/doc/tsilo_admin.xml | 54 ++++++ + src/modules/tsilo/ts_append.c | 116 +++++++++++ + src/modules/tsilo/ts_append.h | 2 + + src/modules/tsilo/tsilo.c | 269 +++++++++++++++++++++++++- + 5 files changed, 445 insertions(+), 1 deletion(-) + +diff --git a/src/modules/tsilo/doc/tsilo.xml b/src/modules/tsilo/doc/tsilo.xml +index 6a2be7b0e7..1ad967ae64 100644 +--- a/src/modules/tsilo/doc/tsilo.xml ++++ b/src/modules/tsilo/doc/tsilo.xml +@@ -23,6 +23,11 @@ + Cabiddu + federico.cabiddu@gmail.com + ++ ++ Donat ++ Zenichev ++ dzenichev@sipwise.com ++ + + + 2015 +diff --git a/src/modules/tsilo/doc/tsilo_admin.xml b/src/modules/tsilo/doc/tsilo_admin.xml +index c294e7c282..965c339156 100644 +--- a/src/modules/tsilo/doc/tsilo_admin.xml ++++ b/src/modules/tsilo/doc/tsilo_admin.xml +@@ -181,6 +181,60 @@ if (is_method("REGISTER")) { + ts_append("location", "$tu"); + } + ... ++ ++ ++ ++
++ <function moreinfo="none">ts_append_by_contact(domain, ruri [, contact])</function> ++ ++ Has almost the same intention as the ts_append(), ++ but gives a possibility to append branches ++ only for a specific location record (Contact URI). ++ The contact's URI value can be either taken from the currently processed REGISTER ++ or (optionally) given as a third parameter. ++ If the Contact URI for a lookup is given as the parameter, ++ it is possible to provide it as a pseudo-variable. ++ ++ The contact lookup is performed on the table specified by the domain parameter. ++ The method should be called when a REGISTER request is received. ++ ++ Meaning of the parameters is as follows: ++ ++ ++ ++ domain - Name of table that should be used for looking ++ up new contacts for r-uri. ++ ++ ++ ++ ++ ruri - The r-uri for which we want to check existing ++ transactions and add them new branches. Can be a static string value or a ++ dynamic string with pseudo-variables. ++ ++ ++ ++ ++ contact - Optional, a value of the location record ++ (contact URI) based on which to perform the branch appending. ++ If not given, the value will be taken from the currently processed REGISTER. ++ If a location lookup based on this Contact URI fails (no location record found), ++ then the branch append will not happen. ++ ++ ++ ++ ++ This function can be used from REQUEST_ROUTE, FAILURE_ROUTE. ++ ++ ++ <function>ts_append_by_contact</function> usage ++ ++... ++if (is_method("REGISTER")) { ++ $var(formated_ct) = $(x_hdr(Contact){nameaddr.uri}); ++ ts_append_by_contact("location", "$tu", "$var(formated_ct)"); ++} ++... + + +
+diff --git a/src/modules/tsilo/ts_append.c b/src/modules/tsilo/ts_append.c +index 7d951865f0..1847ac1c1b 100644 +--- a/src/modules/tsilo/ts_append.c ++++ b/src/modules/tsilo/ts_append.c +@@ -139,3 +139,119 @@ done: + + return ret; + } ++ ++int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table) { ++ ts_urecord_t* _r; ++ ts_transaction_t* ptr; ++ ++ struct sip_uri p_uri; ++ struct sip_uri c_uri; ++ str *t_uri; ++ ++ int res; ++ int appended; ++ ++ /* parse R-URI */ ++ if (use_domain) { ++ t_uri = ruri; ++ } else { ++ if (parse_uri(ruri->s, ruri->len, &p_uri) < 0) { ++ LM_ERR("tsilo: failed to parse uri %.*s\n", ruri->len, ruri->s); ++ return -1; ++ } ++ t_uri = &p_uri.user; ++ } ++ ++ /* parse contact */ ++ if (parse_uri(contact->s, contact->len, &c_uri) < 0) { ++ LM_ERR("tsilo: failed to parse contact %.*s\n", ruri->len, ruri->s); ++ return -1; ++ } ++ ++ /* find urecord in TSILO cache */ ++ lock_entry_by_ruri(t_uri); ++ res = get_ts_urecord(t_uri, &_r); ++ ++ if (res != 0) { ++ LM_ERR("tsilo: failed to retrieve record for %.*s\n", t_uri->len, t_uri->s); ++ unlock_entry_by_ruri(t_uri); ++ return -1; ++ } ++ ++ /* cycle through existing transactions */ ++ ptr = _r->transactions; ++ while(ptr) { ++ LM_DBG("tsilo: transaction %u:%u found for %.*s, going to append branches\n", ++ ptr->tindex, ptr->tlabel, t_uri->len, t_uri->s); ++ /* append only if the desired contact has been found in locations */ ++ appended = ts_append_by_contact_to(msg, ptr->tindex, ptr->tlabel, table, ruri, contact); ++ if (appended > 0) ++ update_stat(added_branches, appended); ++ ptr = ptr->next; ++ } ++ ++ unlock_entry_by_ruri(t_uri); ++ ++ return 1; ++} ++ ++int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact) { ++ struct cell *t=0; ++ struct cell *orig_t; /* a pointer to an existing transaction or 0 if lookup fails*/ ++ struct sip_msg *orig_msg; ++ int ret; ++ str stable; ++ ++ LM_DBG("tsilo: trying to append based on contact <%.*s>\n", contact->len, contact->s); ++ ++ /* lookup a transaction based on its identifier (hash_index:label) */ ++ orig_t = _tmb.t_gett(); ++ if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0) ++ { ++ LM_ERR("tsilo: transaction [%u:%u] not found\n", tindex, tlabel); ++ ret = -1; ++ goto done; ++ } ++ ++ /* check if the dialog is still in the early stage */ ++ if (t->flags & T_CANCELED) { ++ LM_DBG("tsilo: trasaction [%u:%u] was cancelled\n", tindex, tlabel); ++ ret = -2; ++ goto done; ++ } ++ if (t->uas.status >= 200) { ++ LM_DBG("tsilo: trasaction [%u:%u] sent out a final response already - %d\n", ++ tindex, tlabel, t->uas.status); ++ ret = -3; ++ goto done; ++ } ++ ++ /* get original (very first) request of the transaction */ ++ orig_msg = t->uas.request; ++ stable.s = table; ++ stable.len = strlen(stable.s); ++ ++ if(uri==NULL || uri->s==NULL || uri->len<=0) { ++ ret = _regapi.lookup_to_dset(orig_msg, &stable, NULL); ++ } else { ++ ret = _regapi.lookup_to_dset(orig_msg, &stable, uri); ++ } ++ ++ if(ret != 1) { ++ LM_ERR("tsilo: transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret); ++ ret = -4; ++ goto done; ++ } ++ ++ /* start the transaction only for the desired contact ++ contact must be of syntax: sip:@: with no parameters list*/ ++ ret = _tmb.t_append_branch_by_contact(contact); ++ ++done: ++ /* unref the transaction which had been referred by t_lookup_ident() call. ++ * Restore the original transaction (if any) */ ++ if(t) _tmb.unref_cell(t); ++ _tmb.t_sett(orig_t, T_BR_UNDEFINED); ++ ++ return ret; ++} +diff --git a/src/modules/tsilo/ts_append.h b/src/modules/tsilo/ts_append.h +index 56f91204df..461f8881f3 100644 +--- a/src/modules/tsilo/ts_append.h ++++ b/src/modules/tsilo/ts_append.h +@@ -24,5 +24,7 @@ + + int ts_append(struct sip_msg* msg, str *ruri, char *table); + int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri); ++int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table); ++int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact); + + #endif +diff --git a/src/modules/tsilo/tsilo.c b/src/modules/tsilo/tsilo.c +index 0c531acc74..2eefb2fe2d 100644 +--- a/src/modules/tsilo/tsilo.c ++++ b/src/modules/tsilo/tsilo.c +@@ -34,6 +34,8 @@ + #include "../../core/rpc_lookup.h" + #include "../../core/kemi.h" + ++#include "../../core/parser/contact/parse_contact.h" ++ + #include "ts_hash.h" + #include "ts_handlers.h" + #include "ts_append.h" +@@ -61,7 +63,9 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *d, c + static int fixup_ts_append_to(void** param, int param_no); + static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri); + static int fixup_ts_append(void** param, int param_no); +- ++static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri); ++static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact); ++static int fixup_ts_append_by_contact(void** param, int param_no); + static int w_ts_store(struct sip_msg* msg, char *p1, char *p2); + static int w_ts_store1(struct sip_msg* msg, char *_ruri, char *p2); + +@@ -78,6 +82,10 @@ static cmd_export_t cmds[]={ + fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE }, + {"ts_append", (cmd_function)w_ts_append, 2, + fixup_ts_append, 0, REQUEST_ROUTE | FAILURE_ROUTE }, ++ {"ts_append_by_contact", (cmd_function)w_ts_append_by_contact2, 2, /* for two parameters */ ++ fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE }, ++ {"ts_append_by_contact", (cmd_function)w_ts_append_by_contact3, 3, /* for three parameters */ ++ fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE }, + {"ts_store", (cmd_function)w_ts_store, 0, + 0 , 0, REQUEST_ROUTE | FAILURE_ROUTE }, + {"ts_store", (cmd_function)w_ts_store1, 1, +@@ -241,6 +249,23 @@ static int fixup_ts_append(void** param, int param_no) + return 0; + } + ++static int fixup_ts_append_by_contact(void** param, int param_no) ++{ ++ if (param_no==1) { ++ if(strlen((char*)*param)<=1 && (*(char*)(*param)==0 || *(char*)(*param)=='0')) { ++ *param = (void*)0; ++ LM_ERR("empty table name\n"); ++ return -1; ++ } ++ } ++ ++ if (param_no==2 || param_no==3) { ++ return fixup_spve_null(param, 1); ++ } ++ ++ return 0; ++} ++ + /** + * + */ +@@ -357,6 +382,238 @@ static int ki_ts_append_to_uri(sip_msg_t* _msg, int tindex, int tlabel, + _table->s, _uri); + } + ++/** ++ * ++ */ ++static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri) { ++ str ruri = STR_NULL; ++ str ruri_fixed = STR_NULL; ++ ++ str contact = STR_NULL; ++ str tmp_contact = STR_NULL; ++ struct sip_uri curi; ++ ++ int rc; ++ ++ /* parse R-URI */ ++ if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) { ++ LM_ERR("failed to convert r-uri parameter\n"); ++ return -1; ++ } ++ ++ if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) { ++ LM_ERR("tsilo: invalid ruri parameter (empty or zero length).\n"); ++ return -1; ++ } ++ ++ if (pkg_str_dup(&ruri, &ruri_fixed) < 0) { ++ LM_ERR("failed to copy r-uri parameter\n"); ++ return -1; ++ } ++ ++ if (ts_check_uri(&ruri) < 0) { ++ LM_ERR("tsilo: failed to parse R-URI.\n"); ++ return -1; ++ } ++ ++ /* parse Contact header */ ++ if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) ++ || !_msg->contact) { ++ LM_WARN("tsilo: missing contact header or the value is empty/malformed.\n"); ++ return -1; ++ } ++ if (_msg->contact) { ++ if (parse_contact(_msg->contact) < 0) { ++ LM_WARN("tsilo: failed to parse Contact header.\n"); ++ return -1; ++ } ++ if (parse_uri( ++ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, ++ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len, ++ &curi) != 0 ) { ++ if (ts_check_uri(&_msg->contact->body) < 0) { /* one more attempt */ ++ LM_WARN("tsilo: failed to parse Contact header.\n"); ++ return -1; ++ } ++ } ++ ++ tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len; ++ tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1); ++ if (tmp_contact.s == NULL) { ++ PKG_MEM_ERROR; ++ return -1; ++ } ++ memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len); ++ tmp_contact.s[tmp_contact.len] = '\0'; ++ ++ if (pkg_str_dup(&contact, &tmp_contact) < 0) { ++ if (pkg_str_dup(&contact, &_msg->contact->body) < 0) { /* one more attempt */ ++ LM_ERR("tsilo: problems when calling ts_append_contact(), cannot copy Contact parameter.\n"); ++ return -1; ++ } ++ } ++ } ++ ++ /* contact must be of syntax: sip:@: with no parameters list */ ++ rc = ts_append_by_contact(_msg, &ruri, &contact, _table); ++ ++ /* free previously used memory */ ++ pkg_free(ruri.s); ++ pkg_free(contact.s); ++ pkg_free(tmp_contact.s); ++ ++ return rc; ++} ++ ++/** ++ * ++ */ ++static int ki_ts_append_by_contact(sip_msg_t* _msg, str *_table, str *_ruri) { ++ str ruri = STR_NULL; ++ str contact = STR_NULL; ++ str tmp_contact = STR_NULL; ++ struct sip_uri curi; ++ int rc; ++ ++ /* parse R-URI */ ++ if (ts_check_uri(_ruri) < 0) ++ return -1; ++ if (pkg_str_dup(&ruri, _ruri) < 0) ++ return -1; ++ ++ /* parse Contact header */ ++ if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) || !_msg->contact) ++ return -1; ++ ++ if (_msg->contact) { ++ if (parse_contact(_msg->contact) < 0) ++ return -1; ++ if (parse_uri( ++ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, ++ ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len, ++ &curi) != 0 ) { ++ if (ts_check_uri(&_msg->contact->body) < 0) /* one more attempt */ ++ return -1; ++ } ++ ++ tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len; ++ tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1); ++ if (tmp_contact.s == NULL) { ++ PKG_MEM_ERROR; ++ return -1; ++ } ++ memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len); ++ tmp_contact.s[tmp_contact.len] = '\0'; ++ ++ if (pkg_str_dup(&contact, &tmp_contact) < 0) { ++ if (pkg_str_dup(&contact, &_msg->contact->body) < 0) /* one more attempt */ ++ return -1; ++ } ++ } ++ ++ /* contact must be of syntax: sip:@: with no parameters list */ ++ rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); ++ ++ pkg_free(ruri.s); ++ pkg_free(contact.s); ++ pkg_free(tmp_contact.s); ++ ++ return rc; ++} ++ ++/** ++ * ++ */ ++static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact) { ++ str ruri = STR_NULL; ++ str ruri_fixed = STR_NULL; ++ ++ str contact = STR_NULL; ++ str contact_fixed = STR_NULL; ++ ++ int rc; ++ ++ /* parse R-URI */ ++ if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) { ++ LM_ERR("failed to convert r-uri parameter\n"); ++ return -1; ++ } ++ ++ if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) { ++ LM_ERR("tsilo: invalid ruri parameter.\n"); ++ return -1; ++ } ++ ++ if (pkg_str_dup(&ruri, &ruri_fixed) < 0) { ++ LM_ERR("failed to copy r-uri parameter\n"); ++ return -1; ++ } ++ ++ if (ts_check_uri(&ruri) < 0) { ++ LM_ERR("tsilo: failed to parse R-URI.\n"); ++ return -1; ++ } ++ ++ /* parse Contact header */ ++ if (fixup_get_svalue(_msg, (gparam_t*)_contact, &contact_fixed)!=0) { ++ LM_ERR("failed to convert contact parameter\n"); ++ return -1; ++ } ++ ++ if (_contact==NULL || strlen(_contact) <= 0 || contact_fixed.len <= 0) { ++ LM_ERR("tsilo: invalid contact parameter.\n"); ++ return -1; ++ } ++ ++ if (pkg_str_dup(&contact, &contact_fixed) < 0) { ++ LM_ERR("failed to copy r-uri parameter\n"); ++ return -1; ++ } ++ ++ if (ts_check_uri(&contact) < 0) { ++ LM_ERR("tsilo: failed to parse Contact parameter.\n"); ++ return -1; ++ } ++ ++ /* contact must be of syntax: sip:@: with no parameters list */ ++ rc = ts_append_by_contact(_msg, &ruri, &contact, _table); ++ ++ pkg_free(ruri.s); ++ pkg_free(contact.s); ++ ++ return rc; ++} ++ ++/** ++ * ++ */ ++static int ki_ts_append_by_contact_uri(sip_msg_t* _msg, str *_table, str *_ruri, str *_contact) { ++ str ruri = STR_NULL; ++ str contact = STR_NULL; ++ ++ int rc; ++ ++ /* parse R-URI */ ++ if(ts_check_uri(_ruri) < 0) ++ return -1; ++ if (pkg_str_dup(&ruri, _ruri) < 0) ++ return -1; ++ ++ /* parse Contact header */ ++ if (ts_check_uri(_contact) < 0) ++ return -1; ++ if (pkg_str_dup(&contact, _contact) < 0) ++ return -1; ++ ++ /* contact must be of syntax: sip:@: with no parameters list */ ++ rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); ++ ++ pkg_free(ruri.s); ++ pkg_free(contact.s); ++ ++ return rc; ++} ++ + /** + * + */ +@@ -417,6 +674,16 @@ static sr_kemi_t sr_kemi_tsilo_exports[] = { + { SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_STR, + SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE } + }, ++ { str_init("tsilo"), str_init("ts_append_by_contact"), ++ SR_KEMIP_INT, ki_ts_append_by_contact, ++ { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE, ++ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } ++ }, ++ { str_init("tsilo"), str_init("ts_append_by_contact_uri"), ++ SR_KEMIP_INT, ki_ts_append_by_contact_uri, ++ { SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR, ++ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } ++ }, + + { {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } } + }; +-- +2.25.1 + +From 474649171d3c269e2fcfb00c7b1dbd318a952f51 Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Sun, 14 Nov 2021 23:13:15 +0200 +Subject: [PATCH] tsilo: Be compliant with changes in TM, now only + t_append_branches() + +Since of changes in TM's module, where 't_append_branches()' and +'t_append_branch_by_contact()' have been merged into one function, +we need to edit all the occurences where TM's API is called +in TSILO. + +No logic changes. +--- + src/modules/tsilo/ts_append.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/modules/tsilo/ts_append.c b/src/modules/tsilo/ts_append.c +index 1847ac1c1b..e4967f8167 100644 +--- a/src/modules/tsilo/ts_append.c ++++ b/src/modules/tsilo/ts_append.c +@@ -89,6 +89,10 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str * + int ret; + str stable; + ++ str contact; /* needed for usage of TM's API, t_append_branches() */ ++ contact.s = NULL; /* must be emptied */ ++ contact.len = 0; ++ + orig_t = _tmb.t_gett(); + + if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0) +@@ -129,7 +133,7 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str * + goto done; + } + +- ret = _tmb.t_append_branches(); ++ ret = _tmb.t_append_branches(&contact); + + done: + /* unref the transaction which had been referred by t_lookup_ident() call. +@@ -245,7 +249,7 @@ int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *t + + /* start the transaction only for the desired contact + contact must be of syntax: sip:@: with no parameters list*/ +- ret = _tmb.t_append_branch_by_contact(contact); ++ ret = _tmb.t_append_branches(contact); + + done: + /* unref the transaction which had been referred by t_lookup_ident() call. +-- +2.25.1 + +From c1fd9ebaa0fe0eb7457ea74e8a22444b855af9cd Mon Sep 17 00:00:00 2001 +From: Donat Zenichev +Date: Wed, 17 Nov 2021 16:27:37 +0200 +Subject: [PATCH] tsilo: Merge similar functions in ts_append.c + +We need to merge similar functions in ts_append.c implementation +to give less work for maintaining similar code. +Furthermore the purpose of them is quite the same, +but differes just in some details (usage of TM's API). + +Merged functions are: +- ts_append() and ts_append_by_contact() +- ts_append_to() and ts_append_by_contact_to() + +Now all appending in TSILO happens only through ts_append() / ts_append_to() +An implementation in tsilo.c has been updated accordingly. + +Usage. +In case we do not want to append based on specific Contact (location), +the contact parameter being passed to either ts_append() or ts_append_to() +must be set to zero. +In case we do want to append by a specific Contact, then we must +set the Contact parameter of str type beforehand calling ts_append() / ts_append_to(). +--- + src/modules/tsilo/ts_append.c | 154 ++++++---------------------------- + src/modules/tsilo/ts_append.h | 6 +- + src/modules/tsilo/tsilo.c | 42 +++++++--- + 3 files changed, 61 insertions(+), 141 deletions(-) + +diff --git a/src/modules/tsilo/ts_append.c b/src/modules/tsilo/ts_append.c +index e4967f8167..2781deffc4 100644 +--- a/src/modules/tsilo/ts_append.c ++++ b/src/modules/tsilo/ts_append.c +@@ -36,26 +36,37 @@ + #include "ts_hash.h" + #include "ts_append.h" + +-int ts_append(struct sip_msg* msg, str *ruri, char *table) { ++int ts_append(struct sip_msg* msg, str *ruri, str *contact, char *table) { + ts_urecord_t* _r; + ts_transaction_t* ptr; + + struct sip_uri p_uri; ++ struct sip_uri c_uri; + str *t_uri; + + int res; + int appended; +- ++ ++ /* parse R-URI */ + if (use_domain) { + t_uri = ruri; + } else { +- if(parse_uri(ruri->s, ruri->len, &p_uri)<0) { ++ if(parse_uri(ruri->s, ruri->len, &p_uri) < 0) { + LM_ERR("failed to parse uri %.*s\n", ruri->len, ruri->s); + return -1; + } + t_uri = &p_uri.user; + } + ++ /* parse contact if given */ ++ if(contact->s != NULL && contact->len != 0) { ++ if (parse_uri(contact->s, contact->len, &c_uri) < 0) { ++ LM_ERR("failed to parse contact %.*s\n", ruri->len, ruri->s); ++ return -1; ++ } ++ } ++ ++ /* find urecord in TSILO cache */ + lock_entry_by_ruri(t_uri); + + res = get_ts_urecord(t_uri, &_r); +@@ -66,12 +77,13 @@ int ts_append(struct sip_msg* msg, str *ruri, char *table) { + return -1; + } + ++ /* cycle through existing transactions */ + ptr = _r->transactions; + + while(ptr) { + LM_DBG("transaction %u:%u found for %.*s, going to append branches\n",ptr->tindex, ptr->tlabel, t_uri->len, t_uri->s); + +- appended = ts_append_to(msg, ptr->tindex, ptr->tlabel, table, ruri); ++ appended = ts_append_to(msg, ptr->tindex, ptr->tlabel, table, ruri, contact); + if (appended > 0) + update_stat(added_branches, appended); + ptr = ptr->next; +@@ -82,27 +94,28 @@ int ts_append(struct sip_msg* msg, str *ruri, char *table) { + return 1; + } + +-int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri) { ++int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact) { + struct cell *t=0; +- struct cell *orig_t; ++ struct cell *orig_t; /* a pointer to an existing transaction or 0 if lookup fails */ + struct sip_msg *orig_msg; + int ret; + str stable; + +- str contact; /* needed for usage of TM's API, t_append_branches() */ +- contact.s = NULL; /* must be emptied */ +- contact.len = 0; ++ if(contact->s!=NULL && contact->len > 0) { ++ LM_DBG("trying to append based on specific contact <%.*s>\n", contact->len, contact->s); ++ } + ++ /* lookup a transaction based on its identifier (hash_index:label) */ + orig_t = _tmb.t_gett(); + + if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0) + { +- LM_ERR("transaction [%u:%u] not found\n", +- tindex, tlabel); ++ LM_ERR("transaction [%u:%u] not found\n", tindex, tlabel); + ret = -1; + goto done; + } + ++ /* check if the dialog is still in the early stage */ + if (t->flags & T_CANCELED) { + LM_DBG("trasaction [%u:%u] was cancelled\n", + tindex, tlabel); +@@ -117,119 +130,6 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str * + goto done; + } + +- orig_msg = t->uas.request; +- +- stable.s = table; +- stable.len = strlen(stable.s); +- if(uri==NULL || uri->s==NULL || uri->len<=0) { +- ret = _regapi.lookup_to_dset(orig_msg, &stable, NULL); +- } else { +- ret = _regapi.lookup_to_dset(orig_msg, &stable, uri); +- } +- +- if(ret != 1) { +- LM_DBG("transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret); +- ret = -4; +- goto done; +- } +- +- ret = _tmb.t_append_branches(&contact); +- +-done: +- /* unref the transaction which had been referred by t_lookup_ident() call. +- * Restore the original transaction (if any) */ +- if(t) _tmb.unref_cell(t); +- _tmb.t_sett(orig_t, T_BR_UNDEFINED); +- +- return ret; +-} +- +-int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table) { +- ts_urecord_t* _r; +- ts_transaction_t* ptr; +- +- struct sip_uri p_uri; +- struct sip_uri c_uri; +- str *t_uri; +- +- int res; +- int appended; +- +- /* parse R-URI */ +- if (use_domain) { +- t_uri = ruri; +- } else { +- if (parse_uri(ruri->s, ruri->len, &p_uri) < 0) { +- LM_ERR("tsilo: failed to parse uri %.*s\n", ruri->len, ruri->s); +- return -1; +- } +- t_uri = &p_uri.user; +- } +- +- /* parse contact */ +- if (parse_uri(contact->s, contact->len, &c_uri) < 0) { +- LM_ERR("tsilo: failed to parse contact %.*s\n", ruri->len, ruri->s); +- return -1; +- } +- +- /* find urecord in TSILO cache */ +- lock_entry_by_ruri(t_uri); +- res = get_ts_urecord(t_uri, &_r); +- +- if (res != 0) { +- LM_ERR("tsilo: failed to retrieve record for %.*s\n", t_uri->len, t_uri->s); +- unlock_entry_by_ruri(t_uri); +- return -1; +- } +- +- /* cycle through existing transactions */ +- ptr = _r->transactions; +- while(ptr) { +- LM_DBG("tsilo: transaction %u:%u found for %.*s, going to append branches\n", +- ptr->tindex, ptr->tlabel, t_uri->len, t_uri->s); +- /* append only if the desired contact has been found in locations */ +- appended = ts_append_by_contact_to(msg, ptr->tindex, ptr->tlabel, table, ruri, contact); +- if (appended > 0) +- update_stat(added_branches, appended); +- ptr = ptr->next; +- } +- +- unlock_entry_by_ruri(t_uri); +- +- return 1; +-} +- +-int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact) { +- struct cell *t=0; +- struct cell *orig_t; /* a pointer to an existing transaction or 0 if lookup fails*/ +- struct sip_msg *orig_msg; +- int ret; +- str stable; +- +- LM_DBG("tsilo: trying to append based on contact <%.*s>\n", contact->len, contact->s); +- +- /* lookup a transaction based on its identifier (hash_index:label) */ +- orig_t = _tmb.t_gett(); +- if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0) +- { +- LM_ERR("tsilo: transaction [%u:%u] not found\n", tindex, tlabel); +- ret = -1; +- goto done; +- } +- +- /* check if the dialog is still in the early stage */ +- if (t->flags & T_CANCELED) { +- LM_DBG("tsilo: trasaction [%u:%u] was cancelled\n", tindex, tlabel); +- ret = -2; +- goto done; +- } +- if (t->uas.status >= 200) { +- LM_DBG("tsilo: trasaction [%u:%u] sent out a final response already - %d\n", +- tindex, tlabel, t->uas.status); +- ret = -3; +- goto done; +- } +- + /* get original (very first) request of the transaction */ + orig_msg = t->uas.request; + stable.s = table; +@@ -242,13 +142,13 @@ int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *t + } + + if(ret != 1) { +- LM_ERR("tsilo: transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret); ++ LM_ERR("transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret); + ret = -4; + goto done; + } + +- /* start the transaction only for the desired contact +- contact must be of syntax: sip:@: with no parameters list*/ ++ /* if the contact has been given previously ++ then do a new append only for the desired location */ + ret = _tmb.t_append_branches(contact); + + done: +diff --git a/src/modules/tsilo/ts_append.h b/src/modules/tsilo/ts_append.h +index 461f8881f3..02f3244b27 100644 +--- a/src/modules/tsilo/ts_append.h ++++ b/src/modules/tsilo/ts_append.h +@@ -22,9 +22,7 @@ + #ifndef _TS_APPEND_H + #define _TS_APPEND_H + +-int ts_append(struct sip_msg* msg, str *ruri, char *table); +-int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri); +-int ts_append_by_contact(struct sip_msg* msg, str *ruri, str *contact, char *table); +-int ts_append_by_contact_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact); ++int ts_append(struct sip_msg* msg, str *ruri, str *contact, char *table); ++int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact); + + #endif +diff --git a/src/modules/tsilo/tsilo.c b/src/modules/tsilo/tsilo.c +index 2eefb2fe2d..9769a3c7d8 100644 +--- a/src/modules/tsilo/tsilo.c ++++ b/src/modules/tsilo/tsilo.c +@@ -275,6 +275,9 @@ static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri) + str ruri = STR_NULL; + int rc; + ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ + if(_ruri==NULL || (fixup_get_svalue(_msg, (gparam_p)_ruri, &tmp)!=0 || tmp.len<=0)) { + LM_ERR("invalid ruri parameter\n"); + return -1; +@@ -285,7 +288,7 @@ static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri) + if (pkg_str_dup(&ruri, &tmp) < 0) + return -1; + +- rc = ts_append(_msg, &ruri, _table); ++ rc = ts_append(_msg, &ruri, &contact, _table); + + pkg_free(ruri.s); + +@@ -300,13 +303,16 @@ static int ki_ts_append(sip_msg_t* _msg, str *_table, str *_ruri) + str ruri = STR_NULL; + int rc; + ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ + if(ts_check_uri(_ruri)<0) + return -1; + + if (pkg_str_dup(&ruri, _ruri) < 0) + return -1; + +- rc = ts_append(_msg, &ruri, _table->s); ++ rc = ts_append(_msg, &ruri, &contact, _table->s); + + pkg_free(ruri.s); + +@@ -321,6 +327,9 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table + unsigned int tindex; + unsigned int tlabel; + ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ + if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) { + LM_ERR("cannot get transaction index\n"); + return -1; +@@ -331,7 +340,8 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table + return -1; + } + +- return ts_append_to(msg, tindex, tlabel, table, 0); ++ /* we do not want to do append by particular location here */ ++ return ts_append_to(msg, tindex, tlabel, table, 0, &contact); + } + + /** +@@ -339,8 +349,12 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table + */ + static int ki_ts_append_to(sip_msg_t* _msg, int tindex, int tlabel, str *_table) + { ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ ++ /* we do not want to do append by particular location here */ + return ts_append_to(_msg, (unsigned int)tindex, (unsigned int)tlabel, +- _table->s, 0); ++ _table->s, 0, &contact); + } + + /** +@@ -352,6 +366,9 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl + unsigned int tlabel; + str suri; + ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ + if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) { + LM_ERR("cannot get transaction index\n"); + return -1; +@@ -369,7 +386,8 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl + if(ts_check_uri(&suri)<0) + return -1; + +- return ts_append_to(msg, tindex, tlabel, table, &suri); ++ /* we do not want to do append by particular location here */ ++ return ts_append_to(msg, tindex, tlabel, table, &suri, &contact); + } + + /** +@@ -378,8 +396,12 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl + static int ki_ts_append_to_uri(sip_msg_t* _msg, int tindex, int tlabel, + str *_table, str *_uri) + { ++ /* we do not want to do append by particular location */ ++ str contact = STR_NULL; ++ ++ /* we do not want to do append by particular location here */ + return ts_append_to(_msg, (unsigned int)tindex, (unsigned int)tlabel, +- _table->s, _uri); ++ _table->s, _uri, &contact); + } + + /** +@@ -455,7 +477,7 @@ static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ru + } + + /* contact must be of syntax: sip:@: with no parameters list */ +- rc = ts_append_by_contact(_msg, &ruri, &contact, _table); ++ rc = ts_append(_msg, &ruri, &contact, _table); + + /* free previously used memory */ + pkg_free(ruri.s); +@@ -512,7 +534,7 @@ static int ki_ts_append_by_contact(sip_msg_t* _msg, str *_table, str *_ruri) { + } + + /* contact must be of syntax: sip:@: with no parameters list */ +- rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); ++ rc = ts_append(_msg, &ruri, &contact, _table->s); + + pkg_free(ruri.s); + pkg_free(contact.s); +@@ -576,7 +598,7 @@ static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ru + } + + /* contact must be of syntax: sip:@: with no parameters list */ +- rc = ts_append_by_contact(_msg, &ruri, &contact, _table); ++ rc = ts_append(_msg, &ruri, &contact, _table); + + pkg_free(ruri.s); + pkg_free(contact.s); +@@ -606,7 +628,7 @@ static int ki_ts_append_by_contact_uri(sip_msg_t* _msg, str *_table, str *_ruri, + return -1; + + /* contact must be of syntax: sip:@: with no parameters list */ +- rc = ts_append_by_contact(_msg, &ruri, &contact, _table->s); ++ rc = ts_append(_msg, &ruri, &contact, _table->s); + + pkg_free(ruri.s); + pkg_free(contact.s); +-- +2.25.1 +