Browse code

Merge eb856f88d451241d15d64a19a52a0a626d797239 into 136071c4a3cd306ef1043b02d1b61ce7d37efa52

Donat Zenichev authored on 19/11/2021 07:44:12 • GitHub committed on 19/11/2021 07:44:12
Showing 7 changed files
... ...
@@ -46,7 +46,18 @@
46 46
 #include "t_reply.h"
47 47
 #include "t_append_branches.h"
48 48
 
49
-int t_append_branches(void) {
49
+/* this function can act in two ways:
50
+ * - first way, create branches for all existing location records
51
+ *   of this particular AOR. Search for locations is done in
52
+ *   the location table.
53
+ * - second way, if the contact parameter is given,
54
+ *   then only a desired location is meant for appending,
55
+ *   if not found in the location table, an append will not happen
56
+ *   for this AOR.
57
+ *
58
+ *   If the contact parameter is given, it must be of syntax:
59
+ *     sip:<user>@<host>:<port>   (without parameters) */
60
+int t_append_branches(str * contact) {
50 61
 	struct cell *t = NULL;
51 62
 	struct sip_msg *orig_msg = NULL;
52 63
 	struct sip_msg *faked_req;
... ...
@@ -59,7 +70,7 @@ int t_append_branches(void) {
59 70
 	str current_uri;
60 71
 	str dst_uri, path, instance, ruid, location_ua;
61 72
 	struct socket_info* si;
62
-	int q, i, found;
73
+	int q, i, found, append;
63 74
 	flag_t backup_bflags = 0;
64 75
 	flag_t bflags = 0;
65 76
 	int new_branch, branch_ret, lowest_ret;
... ...
@@ -125,6 +136,25 @@ int t_append_branches(void) {
125 136
 										&bflags, &si, &ruid, &instance, &location_ua))) {
126 137
 		LM_DBG("Current uri %.*s\n",current_uri.len, current_uri.s);
127 138
 
139
+		/* if the contact parameter is given, then append by
140
+			an exact location that has been requested for this function call */
141
+		if (contact->s != NULL && contact->len != 0) {
142
+
143
+			LM_DBG("Comparing requested contact <%.*s> against location <%.*s>\n",
144
+							contact->len, contact->s, current_uri.len, current_uri.s);
145
+
146
+			append = 1;
147
+			if (strstr(current_uri.s, contact->s) == NULL) {
148
+				append = 0; /* this while cycle will be stopped */
149
+			}
150
+
151
+			/* do not append the branch if a contact does not match */
152
+			if (!append)
153
+				continue;
154
+
155
+			LM_DBG("Branch will be appended for contact <%.*s>\n", contact->len, contact->s);
156
+		}
157
+
128 158
 		found = 0;
129 159
 		for (i=0; i<outgoings; i++) {
130 160
 			if (t->uac[i].ruid.len == ruid.len
... ...
@@ -31,7 +31,7 @@
31 31
 #include "../../core/proxy.h"
32 32
 #include "h_table.h"
33 33
 
34
-int t_append_branches(void);
35
-typedef int (*t_append_branches_f)(void);
34
+int t_append_branches(str * contact);
35
+typedef int (*t_append_branches_f)(str * contact);
36 36
 
37 37
 #endif
... ...
@@ -23,6 +23,11 @@
23 23
 		<surname>Cabiddu</surname>
24 24
 		<email>federico.cabiddu@gmail.com</email>
25 25
 	    </editor>
26
+	    <editor>
27
+		<firstname>Donat</firstname>
28
+		<surname>Zenichev</surname>
29
+		<email>dzenichev@sipwise.com</email>
30
+	    </editor>
26 31
 	</authorgroup>
27 32
 	<copyright>
28 33
 	    <year>2015</year>
... ...
@@ -181,6 +181,60 @@ if (is_method("REGISTER")) {
181 181
 	ts_append("location", "$tu");
182 182
 }
183 183
 ...
184
+</programlisting>
185
+		</example>
186
+	</section>
187
+	<section id="tsilo.f.ts_append_by_contact">
188
+		<title><function moreinfo="none">ts_append_by_contact(domain, ruri [, contact])</function></title>
189
+		<para>
190
+		Has almost the same intention as the ts_append(),
191
+		but gives a possibility to append branches
192
+		only for a specific location record (Contact URI).
193
+		The contact's URI value can be either taken from the currently processed REGISTER
194
+		or (optionally) given as a third parameter.
195
+		If the Contact URI for a lookup is given as the parameter,
196
+		it is possible to provide it as a pseudo-variable.
197
+
198
+		The contact lookup is performed on the table specified by the domain parameter.
199
+		The method should be called when a REGISTER request is received.
200
+		</para>
201
+		<para>Meaning of the parameters is as follows:</para>
202
+		<itemizedlist>
203
+		<listitem>
204
+			<para>
205
+			<emphasis>domain</emphasis> - Name of table that should be used for looking
206
+			up new contacts for r-uri.
207
+			</para>
208
+		</listitem>
209
+		<listitem>
210
+			<para>
211
+			<emphasis>ruri</emphasis> - The r-uri for which we want to check existing
212
+			transactions and add them new branches. Can be a static string value or a
213
+			dynamic string with pseudo-variables.
214
+			</para>
215
+		</listitem>
216
+		<listitem>
217
+			<para>
218
+			<emphasis>contact</emphasis> - Optional, a value of the location record
219
+			(contact URI) based on which to perform the branch appending.
220
+			If not given, the value will be taken from the currently processed REGISTER.
221
+			If a location lookup based on this Contact URI fails (no location record found),
222
+			then the branch append will not happen.
223
+			</para>
224
+		</listitem>
225
+		</itemizedlist>
226
+		<para>
227
+		This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
228
+		</para>
229
+		<example>
230
+		<title><function>ts_append_by_contact</function> usage</title>
231
+		<programlisting format="linespecific">
232
+...
233
+if (is_method("REGISTER")) {
234
+	$var(formated_ct) = $(x_hdr(Contact){nameaddr.uri});
235
+	ts_append_by_contact("location", "$tu", "$var(formated_ct)");
236
+}
237
+...
184 238
 </programlisting>
185 239
 		</example>
186 240
 	</section>
... ...
@@ -36,26 +36,37 @@
36 36
 #include "ts_hash.h"
37 37
 #include "ts_append.h"
38 38
 
39
-int ts_append(struct sip_msg* msg, str *ruri, char *table) {
39
+int ts_append(struct sip_msg* msg, str *ruri, str *contact, char *table) {
40 40
 	ts_urecord_t* _r;
41 41
 	ts_transaction_t* ptr;
42 42
 
43 43
 	struct sip_uri p_uri;
44
+	struct sip_uri c_uri;
44 45
 	str *t_uri;
45 46
 
46 47
 	int res;
47 48
 	int appended;
48
-	
49
+
50
+	/* parse R-URI */
49 51
 	if (use_domain) {
50 52
 		t_uri = ruri;
51 53
 	} else {
52
-		if(parse_uri(ruri->s, ruri->len, &p_uri)<0) {
54
+		if(parse_uri(ruri->s, ruri->len, &p_uri) < 0) {
53 55
 			LM_ERR("failed to parse uri %.*s\n", ruri->len, ruri->s);
54 56
 			return -1;
55 57
 		}
56 58
 		t_uri = &p_uri.user;
57 59
 	}
58 60
 
61
+	/* parse contact if given */
62
+	if(contact->s != NULL && contact->len != 0) {
63
+		if (parse_uri(contact->s, contact->len, &c_uri) < 0) {
64
+			LM_ERR("failed to parse contact %.*s\n", ruri->len, ruri->s);
65
+			return -1;
66
+		}
67
+	}
68
+
69
+	/* find urecord in TSILO cache */
59 70
 	lock_entry_by_ruri(t_uri);
60 71
 
61 72
 	res = get_ts_urecord(t_uri, &_r);
... ...
@@ -66,12 +77,13 @@ int ts_append(struct sip_msg* msg, str *ruri, char *table) {
66 77
 		return -1;
67 78
 	}
68 79
 
80
+	/* cycle through existing transactions */
69 81
 	ptr = _r->transactions;
70 82
 
71 83
 	while(ptr) {
72 84
 		LM_DBG("transaction %u:%u found for %.*s, going to append branches\n",ptr->tindex, ptr->tlabel, t_uri->len, t_uri->s);
73 85
 
74
-		appended = ts_append_to(msg, ptr->tindex, ptr->tlabel, table, ruri);
86
+		appended = ts_append_to(msg, ptr->tindex, ptr->tlabel, table, ruri, contact);
75 87
 		if (appended > 0)
76 88
 			update_stat(added_branches, appended);
77 89
 		ptr = ptr->next;
... ...
@@ -82,23 +94,28 @@ int ts_append(struct sip_msg* msg, str *ruri, char *table) {
82 94
 	return 1;
83 95
 }
84 96
 
85
-int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri) {
97
+int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact) {
86 98
 	struct cell     *t=0;
87
-	struct cell     *orig_t;
99
+	struct cell     *orig_t;	/* a pointer to an existing transaction or 0 if lookup fails */
88 100
 	struct sip_msg *orig_msg;
89 101
 	int ret;
90 102
 	str stable;
91 103
 
104
+	if(contact->s!=NULL && contact->len > 0) {
105
+		LM_DBG("trying to append based on specific contact <%.*s>\n", contact->len, contact->s);
106
+	}
107
+
108
+	/* lookup a transaction based on its identifier (hash_index:label) */
92 109
 	orig_t = _tmb.t_gett();
93 110
 
94 111
 	if(_tmb.t_lookup_ident(&t, tindex, tlabel) < 0)
95 112
 	{
96
-		LM_ERR("transaction [%u:%u] not found\n",
97
-				tindex, tlabel);
113
+		LM_ERR("transaction [%u:%u] not found\n",	tindex, tlabel);
98 114
 		ret = -1;
99 115
 		goto done;
100 116
 	}
101 117
 
118
+	/* check if the dialog is still in the early stage */
102 119
 	if (t->flags & T_CANCELED) {
103 120
 		LM_DBG("trasaction [%u:%u] was cancelled\n",
104 121
 				tindex, tlabel);
... ...
@@ -113,10 +130,11 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *
113 130
 		goto done;
114 131
 	}
115 132
 
133
+	/* get original (very first) request of the transaction */
116 134
 	orig_msg = t->uas.request;
117
-
118 135
 	stable.s = table;
119 136
 	stable.len = strlen(stable.s);
137
+
120 138
 	if(uri==NULL || uri->s==NULL || uri->len<=0) {
121 139
 		ret = _regapi.lookup_to_dset(orig_msg, &stable, NULL);
122 140
 	} else {
... ...
@@ -124,12 +142,14 @@ int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *
124 142
 	}
125 143
 
126 144
 	if(ret != 1) {
127
-		LM_DBG("transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret);
145
+		LM_ERR("transaction %u:%u: error updating dset (%d)\n", tindex, tlabel, ret);
128 146
 		ret = -4;
129 147
 		goto done;
130 148
 	}
131 149
 
132
-	ret = _tmb.t_append_branches();
150
+	/* if the contact has been given previously
151
+		then do a new append only for the desired location */
152
+	ret = _tmb.t_append_branches(contact);
133 153
 
134 154
 done:
135 155
 	/* unref the transaction which had been referred by t_lookup_ident() call.
... ...
@@ -22,7 +22,7 @@
22 22
 #ifndef _TS_APPEND_H
23 23
 #define _TS_APPEND_H
24 24
 
25
-int ts_append(struct sip_msg* msg, str *ruri, char *table);
26
-int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri);
25
+int ts_append(struct sip_msg* msg, str *ruri, str *contact, char *table);
26
+int ts_append_to(struct sip_msg* msg, int tindex, int tlabel, char *table, str *uri, str *contact);
27 27
 
28 28
 #endif
... ...
@@ -34,6 +34,8 @@
34 34
 #include "../../core/rpc_lookup.h"
35 35
 #include "../../core/kemi.h"
36 36
 
37
+#include "../../core/parser/contact/parse_contact.h"
38
+
37 39
 #include "ts_hash.h"
38 40
 #include "ts_handlers.h"
39 41
 #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
61 63
 static int fixup_ts_append_to(void** param, int param_no);
62 64
 static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri);
63 65
 static int fixup_ts_append(void** param, int param_no);
64
-
66
+static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri);
67
+static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact);
68
+static int fixup_ts_append_by_contact(void** param, int param_no);
65 69
 static int w_ts_store(struct sip_msg* msg, char *p1, char *p2);
66 70
 static int w_ts_store1(struct sip_msg* msg, char *_ruri, char *p2);
67 71
 
... ...
@@ -78,6 +82,10 @@ static cmd_export_t cmds[]={
78 82
 		fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE },
79 83
 	{"ts_append", (cmd_function)w_ts_append,  2,
80 84
 		fixup_ts_append, 0, REQUEST_ROUTE | FAILURE_ROUTE },
85
+	{"ts_append_by_contact", (cmd_function)w_ts_append_by_contact2,  2,	/* for two parameters */
86
+		fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE },
87
+	{"ts_append_by_contact", (cmd_function)w_ts_append_by_contact3,  3,	/* for three parameters */
88
+		fixup_ts_append_by_contact, 0, REQUEST_ROUTE | FAILURE_ROUTE },
81 89
 	{"ts_store", (cmd_function)w_ts_store,  0,
82 90
 		0 , 0, REQUEST_ROUTE | FAILURE_ROUTE },
83 91
 	{"ts_store", (cmd_function)w_ts_store1,  1,
... ...
@@ -241,6 +249,23 @@ static int fixup_ts_append(void** param, int param_no)
241 249
 	return 0;
242 250
 }
243 251
 
252
+static int fixup_ts_append_by_contact(void** param, int param_no)
253
+{
254
+	if (param_no==1) {
255
+		if(strlen((char*)*param)<=1 && (*(char*)(*param)==0 || *(char*)(*param)=='0')) {
256
+			*param = (void*)0;
257
+			LM_ERR("empty table name\n");
258
+			return -1;
259
+		}
260
+	}
261
+
262
+	if (param_no==2 || param_no==3) {
263
+		return fixup_spve_null(param, 1);
264
+	}
265
+
266
+	return 0;
267
+}
268
+
244 269
 /**
245 270
  *
246 271
  */
... ...
@@ -250,6 +275,9 @@ static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri)
250 275
 	str ruri = STR_NULL;
251 276
 	int rc;
252 277
 
278
+	/* we do not want to do append by particular location */
279
+	str contact = STR_NULL;
280
+
253 281
 	if(_ruri==NULL || (fixup_get_svalue(_msg, (gparam_p)_ruri, &tmp)!=0 || tmp.len<=0)) {
254 282
 		LM_ERR("invalid ruri parameter\n");
255 283
 		return -1;
... ...
@@ -260,7 +288,7 @@ static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri)
260 288
 	if (pkg_str_dup(&ruri, &tmp) < 0)
261 289
 		return -1;
262 290
 
263
-	rc = ts_append(_msg, &ruri, _table);
291
+	rc = ts_append(_msg, &ruri, &contact, _table);
264 292
 
265 293
 	pkg_free(ruri.s);
266 294
 
... ...
@@ -275,13 +303,16 @@ static int ki_ts_append(sip_msg_t* _msg, str *_table, str *_ruri)
275 303
 	str ruri = STR_NULL;
276 304
 	int rc;
277 305
 
306
+	/* we do not want to do append by particular location */
307
+	str contact = STR_NULL;
308
+
278 309
 	if(ts_check_uri(_ruri)<0)
279 310
 		return -1;
280 311
 
281 312
 	if (pkg_str_dup(&ruri, _ruri) < 0)
282 313
 		return -1;
283 314
 
284
-	rc = ts_append(_msg, &ruri, _table->s);
315
+	rc = ts_append(_msg, &ruri, &contact, _table->s);
285 316
 
286 317
 	pkg_free(ruri.s);
287 318
 
... ...
@@ -296,6 +327,9 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table
296 327
 	unsigned int tindex;
297 328
 	unsigned int tlabel;
298 329
 
330
+	/* we do not want to do append by particular location */
331
+	str contact = STR_NULL;
332
+
299 333
 	if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) {
300 334
 		LM_ERR("cannot get transaction index\n");
301 335
 		return -1;
... ...
@@ -306,7 +340,8 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table
306 340
 		return -1;
307 341
 	}
308 342
 
309
-	return ts_append_to(msg, tindex, tlabel, table, 0);
343
+	/* we do not want to do append by particular location here */
344
+	return ts_append_to(msg, tindex, tlabel, table, 0, &contact);
310 345
 }
311 346
 
312 347
 /**
... ...
@@ -314,8 +349,12 @@ static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table
314 349
  */
315 350
 static int ki_ts_append_to(sip_msg_t* _msg, int tindex, int tlabel, str *_table)
316 351
 {
352
+	/* we do not want to do append by particular location */
353
+	str contact = STR_NULL;
354
+
355
+	/* we do not want to do append by particular location here */
317 356
 	return ts_append_to(_msg, (unsigned int)tindex, (unsigned int)tlabel,
318
-			_table->s, 0);
357
+			_table->s, 0, &contact);
319 358
 }
320 359
 
321 360
 /**
... ...
@@ -327,6 +366,9 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl
327 366
 	unsigned int tlabel;
328 367
 	str suri;
329 368
 
369
+	/* we do not want to do append by particular location */
370
+	str contact = STR_NULL;
371
+
330 372
 	if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) {
331 373
 		LM_ERR("cannot get transaction index\n");
332 374
 		return -1;
... ...
@@ -344,7 +386,8 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl
344 386
 	if(ts_check_uri(&suri)<0)
345 387
 		return -1;
346 388
 
347
-	return ts_append_to(msg, tindex, tlabel, table, &suri);
389
+	/* we do not want to do append by particular location here */
390
+	return ts_append_to(msg, tindex, tlabel, table, &suri, &contact);
348 391
 }
349 392
 
350 393
 /**
... ...
@@ -353,8 +396,244 @@ static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *tabl
353 396
 static int ki_ts_append_to_uri(sip_msg_t* _msg, int tindex, int tlabel,
354 397
 		str *_table, str *_uri)
355 398
 {
399
+	/* we do not want to do append by particular location */
400
+	str contact = STR_NULL;
401
+
402
+	/* we do not want to do append by particular location here */
356 403
 	return ts_append_to(_msg, (unsigned int)tindex, (unsigned int)tlabel,
357
-			_table->s, _uri);
404
+			_table->s, _uri, &contact);
405
+}
406
+
407
+/**
408
+ *
409
+ */
410
+static int w_ts_append_by_contact2(struct sip_msg* _msg, char *_table, char *_ruri) {
411
+	str ruri = STR_NULL;
412
+	str ruri_fixed = STR_NULL;
413
+
414
+	str contact = STR_NULL;
415
+	str tmp_contact = STR_NULL;
416
+	struct sip_uri curi;
417
+
418
+	int rc;
419
+
420
+	/* parse R-URI */
421
+	if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) {
422
+		LM_ERR("failed to convert r-uri parameter\n");
423
+		return -1;
424
+	}
425
+
426
+	if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) {
427
+		LM_ERR("tsilo: invalid ruri parameter (empty or zero length).\n");
428
+		return -1;
429
+	}
430
+
431
+	if (pkg_str_dup(&ruri, &ruri_fixed) < 0) {
432
+		LM_ERR("failed to copy r-uri parameter\n");
433
+		return -1;
434
+	}
435
+
436
+	if (ts_check_uri(&ruri) < 0) {
437
+		LM_ERR("tsilo: failed to parse R-URI.\n");
438
+		return -1;
439
+	}
440
+
441
+	/* parse Contact header */
442
+	if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0)
443
+			|| !_msg->contact) {
444
+		LM_WARN("tsilo: missing contact header or the value is empty/malformed.\n");
445
+		return -1;
446
+	}
447
+	if (_msg->contact) {
448
+		if (parse_contact(_msg->contact) < 0) {
449
+			LM_WARN("tsilo: failed to parse Contact header.\n");
450
+			return -1;
451
+		}
452
+		if (parse_uri(
453
+						((struct contact_body*)_msg->contact->parsed)->contacts->uri.s,
454
+						((struct contact_body*)_msg->contact->parsed)->contacts->uri.len,
455
+						&curi) != 0 ) {
456
+			if (ts_check_uri(&_msg->contact->body) < 0) {	/* one more attempt */
457
+				LM_WARN("tsilo: failed to parse Contact header.\n");
458
+				return -1;
459
+			}
460
+		}
461
+
462
+		tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len;
463
+		tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1);
464
+		if (tmp_contact.s == NULL) {
465
+			PKG_MEM_ERROR;
466
+			return -1;
467
+		}
468
+		memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len);
469
+		tmp_contact.s[tmp_contact.len] = '\0';
470
+
471
+		if (pkg_str_dup(&contact, &tmp_contact) < 0) {
472
+			if (pkg_str_dup(&contact, &_msg->contact->body) < 0) { /* one more attempt */
473
+				LM_ERR("tsilo: problems when calling ts_append_contact(), cannot copy Contact parameter.\n");
474
+				return -1;
475
+			}
476
+		}
477
+	}
478
+
479
+	/* contact must be of syntax: sip:<user>@<host>:<port> with no parameters list */
480
+	rc = ts_append(_msg, &ruri, &contact, _table);
481
+
482
+	/* free previously used memory */
483
+	pkg_free(ruri.s);
484
+	pkg_free(contact.s);
485
+	pkg_free(tmp_contact.s);
486
+
487
+	return rc;
488
+}
489
+
490
+/**
491
+ *
492
+ */
493
+static int ki_ts_append_by_contact(sip_msg_t* _msg, str *_table, str *_ruri) {
494
+	str ruri = STR_NULL;
495
+	str contact = STR_NULL;
496
+	str tmp_contact = STR_NULL;
497
+	struct sip_uri curi;
498
+	int rc;
499
+
500
+	/* parse R-URI */
501
+	if (ts_check_uri(_ruri) < 0)
502
+		return -1;
503
+	if (pkg_str_dup(&ruri, _ruri) < 0)
504
+		return -1;
505
+
506
+	/* parse Contact header */
507
+	if ((!_msg->contact && parse_headers(_msg, HDR_CONTACT_F, 0) != 0) || !_msg->contact)
508
+		return -1;
509
+
510
+	if (_msg->contact) {
511
+		if (parse_contact(_msg->contact) < 0)
512
+			return -1;
513
+		if (parse_uri(
514
+						((struct contact_body*)_msg->contact->parsed)->contacts->uri.s,
515
+						((struct contact_body*)_msg->contact->parsed)->contacts->uri.len,
516
+						&curi) != 0 ) {
517
+			if (ts_check_uri(&_msg->contact->body) < 0) /* one more attempt */
518
+				return -1;
519
+		}
520
+
521
+		tmp_contact.len = ((struct contact_body*)_msg->contact->parsed)->contacts->uri.len;
522
+		tmp_contact.s = (char*)pkg_malloc(tmp_contact.len+1);
523
+		if (tmp_contact.s == NULL) {
524
+			PKG_MEM_ERROR;
525
+			return -1;
526
+		}
527
+		memcpy(tmp_contact.s, ((struct contact_body*)_msg->contact->parsed)->contacts->uri.s, tmp_contact.len);
528
+		tmp_contact.s[tmp_contact.len] = '\0';
529
+
530
+		if (pkg_str_dup(&contact, &tmp_contact) < 0) {
531
+			if (pkg_str_dup(&contact, &_msg->contact->body) < 0) /* one more attempt */
532
+				return -1;
533
+		}
534
+	}
535
+
536
+	/* contact must be of syntax: sip:<user>@<host>:<port> with no parameters list */
537
+	rc = ts_append(_msg, &ruri, &contact, _table->s);
538
+
539
+	pkg_free(ruri.s);
540
+	pkg_free(contact.s);
541
+	pkg_free(tmp_contact.s);
542
+
543
+	return rc;
544
+}
545
+
546
+/**
547
+ *
548
+ */
549
+static int w_ts_append_by_contact3(struct sip_msg* _msg, char *_table, char *_ruri, char *_contact) {
550
+	str ruri = STR_NULL;
551
+	str ruri_fixed = STR_NULL;
552
+
553
+	str contact = STR_NULL;
554
+	str contact_fixed = STR_NULL;
555
+
556
+	int rc;
557
+
558
+	/* parse R-URI */
559
+	if (fixup_get_svalue(_msg, (gparam_t*)_ruri, &ruri_fixed)!=0) {
560
+		LM_ERR("failed to convert r-uri parameter\n");
561
+		return -1;
562
+	}
563
+
564
+	if (_ruri==NULL || strlen(_ruri) <= 0 || ruri_fixed.len <= 0) {
565
+		LM_ERR("tsilo: invalid ruri parameter.\n");
566
+		return -1;
567
+	}
568
+
569
+	if (pkg_str_dup(&ruri, &ruri_fixed) < 0) {
570
+		LM_ERR("failed to copy r-uri parameter\n");
571
+		return -1;
572
+	}
573
+
574
+	if (ts_check_uri(&ruri) < 0) {
575
+		LM_ERR("tsilo: failed to parse R-URI.\n");
576
+		return -1;
577
+	}
578
+
579
+	/* parse Contact header */
580
+	if (fixup_get_svalue(_msg, (gparam_t*)_contact, &contact_fixed)!=0) {
581
+		LM_ERR("failed to convert contact parameter\n");
582
+		return -1;
583
+	}
584
+
585
+	if (_contact==NULL || strlen(_contact) <= 0 || contact_fixed.len <= 0) {
586
+		LM_ERR("tsilo: invalid contact parameter.\n");
587
+		return -1;
588
+	}
589
+
590
+	if (pkg_str_dup(&contact, &contact_fixed) < 0) {
591
+		LM_ERR("failed to copy r-uri parameter\n");
592
+		return -1;
593
+	}
594
+
595
+	if (ts_check_uri(&contact) < 0) {
596
+		LM_ERR("tsilo: failed to parse Contact parameter.\n");
597
+		return -1;
598
+	}
599
+
600
+	/* contact must be of syntax: sip:<user>@<host>:<port> with no parameters list */
601
+	rc = ts_append(_msg, &ruri, &contact, _table);
602
+
603
+	pkg_free(ruri.s);
604
+	pkg_free(contact.s);
605
+
606
+	return rc;
607
+}
608
+
609
+/**
610
+ *
611
+ */
612
+static int ki_ts_append_by_contact_uri(sip_msg_t* _msg, str *_table, str *_ruri, str *_contact) {
613
+	str ruri = STR_NULL;
614
+	str contact = STR_NULL;
615
+
616
+	int rc;
617
+
618
+	/* parse R-URI */
619
+	if(ts_check_uri(_ruri) < 0)
620
+		return -1;
621
+	if (pkg_str_dup(&ruri, _ruri) < 0)
622
+		return -1;
623
+
624
+	/* parse Contact header */
625
+	if (ts_check_uri(_contact) < 0)
626
+		return -1;
627
+	if (pkg_str_dup(&contact, _contact) < 0)
628
+		return -1;
629
+
630
+	/* contact must be of syntax: sip:<user>@<host>:<port> with no parameters list */
631
+	rc = ts_append(_msg, &ruri, &contact, _table->s);
632
+
633
+	pkg_free(ruri.s);
634
+	pkg_free(contact.s);
635
+
636
+	return rc;
358 637
 }
359 638
 
360 639
 /**
... ...
@@ -417,6 +696,16 @@ static sr_kemi_t sr_kemi_tsilo_exports[] = {
417 696
 		{ SR_KEMIP_INT, SR_KEMIP_INT, SR_KEMIP_STR,
418 697
 			SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE }
419 698
 	},
699
+	{ str_init("tsilo"), str_init("ts_append_by_contact"),
700
+		SR_KEMIP_INT, ki_ts_append_by_contact,
701
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
702
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
703
+	},
704
+	{ str_init("tsilo"), str_init("ts_append_by_contact_uri"),
705
+		SR_KEMIP_INT, ki_ts_append_by_contact_uri,
706
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
707
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
708
+	},
420 709
 
421 710
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
422 711
 };