Browse code

topos: when contact mode is set to 1, contact uri created is malformed if received contact has no user part topos: SUBSCRIBE dialog topos: documentation for SUBSCRIBE dialog topos: add description for dialog_expire key

frederic authored on 08/02/2021 14:54:02
Showing 5 changed files
... ...
@@ -23,11 +23,20 @@
23 23
 		<surname>Mierla</surname>
24 24
 		<email>miconda@gmail.com</email>
25 25
 	    </editor>
26
+            <editor>
27
+                <firstname>Frederic</firstname>
28
+                <surname>Gaisnon</surname>
29
+                <email>frederic.gaisnon@gmail.com</email>
30
+            </editor>
26 31
 	</authorgroup>
27 32
 	<copyright>
28 33
 	    <year>2016</year>
29 34
 	    <holder>&fhg;</holder>
30 35
 	</copyright>
36
+        <copyright>
37
+            <year>2021</year>
38
+            <holder>MomentTech</holder>
39
+        </copyright>
31 40
     </bookinfo>
32 41
     <toc></toc>
33 42
     
... ...
@@ -30,8 +30,8 @@
30 30
 		a dialog -- record_route() must be used for them as well, the
31 31
 		headers are not going to be in the messages sent to the network, they
32 32
 		are needed to know local addresses used to communicate with each side.
33
-		At this moment it is not designed to work for presence (SUBSCRIBE-based)
34
-		dialogs. The REGISTER and PUBLISH requests are skipped from processing
33
+                This module is designed to work for presence (SUBSCRIBE-based) dialogs too.
34
+		The REGISTER and PUBLISH requests are skipped from processing
35 35
 		by this module, expected to be terminated on a local SIP server.
36 36
 	</para>
37 37
 	</section>
... ...
@@ -199,6 +199,9 @@ modparam("topos", "branch_expire", 300)
199 199
 			after the initial call setup on re-INVITEs or other in-dialog
200 200
 			messages. So set a large enough value (according your longest call
201 201
 			duration) to prevent problems in re-writing messages.
202
+			This key is only relevant for INVITE dialog. 
203
+                        SUBSCRIBE dialog records lifetime are based on value set in expires
204
+                        header. Moreover each re-SUBSCRIBEs update the dialog timestamp.
202 205
 		</para>
203 206
 		<para>
204 207
 		<emphasis>
... ...
@@ -905,6 +905,11 @@ int tps_request_received(sip_msg_t *msg, int dialog)
905 905
 				goto error;
906 906
 			}
907 907
 		}
908
+		if((get_cseq(msg)->method_id)&(METHOD_SUBSCRIBE)) {
909
+			if(tps_storage_update_dialog(msg, &mtsd, &stsd, TPS_DBU_CONTACT|TPS_DBU_TIME)<0) {
910
+				goto error;
911
+			}
912
+		}
908 913
 	}
909 914
 	return 0;
910 915
 
... ...
@@ -41,6 +41,7 @@
41 41
 #include "../../core/parser/contact/parse_contact.h"
42 42
 #include "../../core/parser/parse_from.h"
43 43
 #include "../../core/parser/parse_to.h"
44
+#include "../../core/parser/parse_expires.h"
44 45
 
45 46
 #include "../../lib/srdb1/db.h"
46 47
 #include "../../core/utils/sruid.h"
... ...
@@ -336,8 +337,11 @@ int tps_storage_fill_contact(sip_msg_t *msg, tps_data_t *td, str *uuid, int dir,
336 337
 				td->cp += pv_val.rs.len;
337 338
 			}
338 339
 		}
339
-		*td->cp = '@';
340
-		td->cp++;
340
+
341
+		if (!((ctmode == 1) && (dir==TPS_DIR_DOWNSTREAM) && (curi.user.len <= 0))) {
342
+			*td->cp = '@';
343
+			td->cp++;
344
+		}
341 345
 
342 346
 		if (_tps_contact_host.len) { // using configured hostname in the contact header
343 347
 			memcpy(td->cp, _tps_contact_host.s, _tps_contact_host.len);
... ...
@@ -465,8 +469,8 @@ int tps_storage_link_msg(sip_msg_t *msg, tps_data_t *td, int dir)
465 469
 
466 470
 	/* extract the contact address */
467 471
 	if(parse_headers(msg, HDR_CONTACT_F, 0)<0 || msg->contact==NULL) {
468
-		if(td->s_method_id != METHOD_INVITE) {
469
-			/* no mandatory contact unless is INVITE - done */
472
+		if((td->s_method_id != METHOD_INVITE) && (td->s_method_id != METHOD_SUBSCRIBE)){
473
+			/* no mandatory contact unless is INVITE or SUBSCRIBE - done */
470 474
 			return 0;
471 475
 		}
472 476
 		if(msg->first_line.type==SIP_REPLY) {
... ...
@@ -504,6 +508,13 @@ int tps_storage_link_msg(sip_msg_t *msg, tps_data_t *td, int dir)
504 508
 		}
505 509
 	}
506 510
 
511
+	if  (td->s_method_id == METHOD_SUBSCRIBE) {
512
+		if(msg->expires && (msg->expires->body.len > 0) && (msg->expires->parsed || (parse_expires(msg->expires) >= 0))) {
513
+			td->expires = ((exp_body_t *)msg->expires->parsed)->val;
514
+		}
515
+	}
516
+
517
+
507 518
 	LM_DBG("downstream: %s - acontact: [%.*s] - bcontact: [%.*s]\n",
508 519
 			(dir==TPS_DIR_DOWNSTREAM)?"yes":"no",
509 520
 			td->a_contact.len, (td->a_contact.len>0)?td->a_contact.s:"",
... ...
@@ -1036,6 +1047,8 @@ int tps_db_load_branch(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1036 1047
 	db_key_t db_cols[TPS_NR_KEYS];
1037 1048
 	db1_res_t* db_res = NULL;
1038 1049
 	str sinv = str_init("INVITE");
1050
+	str ssub = str_init("SUBSCRIBE");
1051
+	int bInviteDlg = 1;
1039 1052
 	int nr_keys;
1040 1053
 	int nr_cols;
1041 1054
 	int n;
... ...
@@ -1047,6 +1060,10 @@ int tps_db_load_branch(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1047 1060
 	nr_keys = 0;
1048 1061
 	nr_cols = 0;
1049 1062
 
1063
+	if((get_cseq(msg)->method_id == METHOD_SUBSCRIBE) || ((get_cseq(msg)->method_id == METHOD_NOTIFY) && (msg->event->len > 0))) {
1064
+		bInviteDlg = 0;
1065
+	}
1066
+
1050 1067
 	if(mode==0) {
1051 1068
 		/* load same transaction using Via branch */
1052 1069
 		db_keys[nr_keys]=&tt_col_x_vbranch;
... ...
@@ -1075,7 +1092,7 @@ int tps_db_load_branch(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1075 1092
 		db_ops[nr_keys]=OP_EQ;
1076 1093
 		db_vals[nr_keys].type = DB1_STR;
1077 1094
 		db_vals[nr_keys].nul = 0;
1078
-		db_vals[nr_keys].val.str_val = sinv;
1095
+		db_vals[nr_keys].val.str_val = bInviteDlg ? sinv : ssub;
1079 1096
 		nr_keys++;
1080 1097
 	}
1081 1098
 
... ...
@@ -1407,7 +1424,7 @@ int tps_storage_update_branch(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1407 1424
 	if(msg==NULL || md==NULL || sd==NULL)
1408 1425
 		return -1;
1409 1426
 
1410
-	if(md->s_method_id != METHOD_INVITE) {
1427
+	if((md->s_method_id != METHOD_INVITE) && (md->s_method_id != METHOD_SUBSCRIBE)) {
1411 1428
 		return 0;
1412 1429
 	}
1413 1430
 
... ...
@@ -1514,6 +1531,14 @@ int tps_db_update_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1514 1531
 			}
1515 1532
 		}
1516 1533
 	}
1534
+	if ((mode & TPS_DBU_TIME) && ((sd->b_tag.len > 0)
1535
+			&& ((md->direction == TPS_DIR_UPSTREAM) && (msg->first_line.type==SIP_REQUEST))
1536
+			&& (msg->first_line.u.request.method_value == METHOD_SUBSCRIBE))) {
1537
+		db_ucols[nr_ucols] = &td_col_rectime;
1538
+		db_uvals[nr_ucols].type = DB1_DATETIME;
1539
+		db_uvals[nr_ucols].val.time_val = time(NULL);
1540
+		nr_ucols++;
1541
+	}
1517 1542
 
1518 1543
 	if(nr_ucols==0) {
1519 1544
 		return 0;
... ...
@@ -1543,7 +1568,7 @@ int tps_storage_update_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd,
1543 1568
 	if(msg==NULL || md==NULL || sd==NULL)
1544 1569
 		return -1;
1545 1570
 
1546
-	if(md->s_method_id != METHOD_INVITE) {
1571
+	if((md->s_method_id != METHOD_INVITE) && (md->s_method_id != METHOD_SUBSCRIBE)) {
1547 1572
 		return 0;
1548 1573
 	}
1549 1574
 	if(msg->first_line.type==SIP_REPLY) {
... ...
@@ -1575,7 +1600,7 @@ int tps_db_end_dialog(sip_msg_t *msg, tps_data_t *md, tps_data_t *sd)
1575 1600
 	if(msg==NULL || md==NULL || sd==NULL || _tps_db_handle==NULL)
1576 1601
 		return -1;
1577 1602
 
1578
-	if(md->s_method_id != METHOD_BYE) {
1603
+	if((md->s_method_id != METHOD_BYE) && !((md->s_method_id == METHOD_SUBSCRIBE) && (md->expires == 0))) {
1579 1604
 		return 0;
1580 1605
 	}
1581 1606
 
... ...
@@ -41,6 +41,7 @@
41 41
 #define TPS_DBU_RPLATTRS	(1<<1)
42 42
 #define TPS_DBU_ARR		(1<<2)
43 43
 #define TPS_DBU_BRR		(1<<3)
44
+#define TPS_DBU_TIME		(1<<4)
44 45
 #define TPS_DBU_ALL		(0xffffffff)
45 46
 
46 47
 #define TPS_DATA_SIZE	8192
... ...
@@ -79,6 +80,7 @@ typedef struct tps_data {
79 80
 	int32_t iflags;
80 81
 	int32_t direction;
81 82
 	uint32_t s_method_id;
83
+	int32_t expires;
82 84
 } tps_data_t;
83 85
 
84 86
 int tps_storage_dialog_find(sip_msg_t *msg, tps_data_t *td);