diff --git a/debian/patches/series b/debian/patches/series index ec12fee9f..0542dc129 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -58,6 +58,9 @@ 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 +# ### Don't just put stuff in any order ### use gbp pq import/export tooling to help maintain patches ### diff --git a/debian/patches/sipwise/tm_t_append_branch_by_contact.patch b/debian/patches/sipwise/tm_t_append_branch_by_contact.patch new file mode 100644 index 000000000..e340d9758 --- /dev/null +++ b/debian/patches/sipwise/tm_t_append_branch_by_contact.patch @@ -0,0 +1,244 @@ +--- 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 new file mode 100644 index 000000000..e315c9001 --- /dev/null +++ b/debian/patches/sipwise/tsilo_add_ts_append_by_contact.patch @@ -0,0 +1,445 @@ +--- 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; ++} +--- 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 +--- 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_ms + 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, + 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; ++} ++ + /** + * + */ +@@ -360,6 +385,238 @@ static int ki_ts_append_to_uri(sip_msg_t + /** + * + */ ++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); ++ ++ 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); ++ ++ pkg_free(ruri.s); ++ pkg_free(contact.s); ++ ++ return rc; ++} ++ ++/** ++ * ++ */ + static int w_ts_store(struct sip_msg* msg, char *p1, char *p2) + { + return ts_store(msg, 0); +@@ -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 } } + };