Browse code

modules/ims_registrar_scscf: include contact param info in NOTIFY Params are now stored in usrloc - if they exist they should be included in notifications to subscribers

Richard Good authored on 13/11/2014 07:54:36
Showing 1 changed files
... ...
@@ -1064,7 +1064,7 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
1064 1064
     subscriber_data.watcher_uri = &watcher_impu;
1065 1065
     subscriber_data.watcher_contact = &watcher_contact;
1066 1066
     subscriber_data.version = 1; /*default version starts at 1*/
1067
-
1067
+    
1068 1068
     if (expires > 0) {
1069 1069
         LM_DBG("expires is more than zero - SUBSCRIBE");
1070 1070
         event_type = IMS_REGISTRAR_SUBSCRIBE;
... ...
@@ -1112,15 +1112,32 @@ int subscribe_to_reg(struct sip_msg *msg, char *_t, char *str2) {
1112 1112
 
1113 1113
         } else {
1114 1114
 
1115
-            LM_DBG("this must be a re subscribe, lets update it\n");
1116
-	    res = ul.update_subscriber(presentity_impurecord, &reg_subscriber, &expires_time, 0, 0);
1117
-            if (res != 1) {
1118
-                LM_ERR("Failed to update subscription - expires is %d\n", expires_time);
1119
-                ul.unlock_udomain(domain, &presentity_uri);
1120
-                ret = CSCF_RETURN_FALSE;
1121
-                goto error;
1122
-            }
1123
-            new_subscription = 0;
1115
+            if(memcmp(reg_subscriber->call_id.s, subscriber_data.callid->s, reg_subscriber->call_id.len) == 0 && 
1116
+		    memcmp(reg_subscriber->from_tag.s, subscriber_data.ftag->s, reg_subscriber->from_tag.len) == 0 && 
1117
+		    memcmp(reg_subscriber->to_tag.s, subscriber_data.ttag->s, reg_subscriber->to_tag.len) == 0) {
1118
+		LM_DBG("This has same callid, fromtag and totag - must be a re subscribe, lets update it\n");
1119
+		res = ul.update_subscriber(presentity_impurecord, &reg_subscriber, &expires_time, 0, 0);
1120
+		if (res != 1) {
1121
+		    LM_ERR("Failed to update subscription - expires is %d\n", expires_time);
1122
+		    ul.unlock_udomain(domain, &presentity_uri);
1123
+		    ret = CSCF_RETURN_FALSE;
1124
+		    goto error;
1125
+		}
1126
+		new_subscription = 0;
1127
+	    } else {
1128
+		LM_ERR("Re-subscribe for same watcher_contact, presentity_uri, event but with different callid, fromtag and totag  - What happened?\n");
1129
+		LM_DBG("Removing old subscriber and adding new one\n");
1130
+		subscriber_data.presentity_uri = &presentity_impurecord->public_identity;
1131
+		ul.external_delete_subscriber(reg_subscriber, (udomain_t*) _t, 0 /*domain is already locked*/);
1132
+		res = ul.add_subscriber(presentity_impurecord, &subscriber_data, &reg_subscriber, 0 /*not a db_load*/);
1133
+		if (res != 0) {
1134
+		    LM_ERR("Failed to add new subscription\n");
1135
+		    ul.unlock_udomain(domain, &presentity_uri);
1136
+		    ret = CSCF_RETURN_FALSE;
1137
+		    goto error;
1138
+		}
1139
+		new_subscription = 1;
1140
+	    }
1124 1141
         }
1125 1142
 
1126 1143
         ul.unlock_udomain(domain, &presentity_uri);
... ...
@@ -1419,6 +1436,35 @@ out_of_memory:
1419 1436
     return;
1420 1437
 }
1421 1438
 
1439
+/*We currently only support certain unknown params to be sent in NOTIFY bodies
1440
+ This prevents having compatability issues with UEs including non-standard params in contact header
1441
+ Supported params:
1442
+ */
1443
+static str param_q = {"q", 1};
1444
+static str param_video = {"video", 5};
1445
+static str param_expires = {"expires", 7};
1446
+static str param_sip_instance = {"+sip.instance", 13};
1447
+static str param_3gpp_smsip = {"+g.3gpp.smsip", 13};
1448
+static str param_3gpp_icsi_ref = {"+g.3gpp.icsi-ref", 16};
1449
+int inline supported_param(str *param_name) {
1450
+    
1451
+    if(strncasecmp(param_name->s, param_q.s, param_name->len) == 0) {
1452
+	return 0;
1453
+    } else if (strncasecmp(param_name->s, param_video.s, param_name->len) == 0) {
1454
+	return 0;
1455
+    } else if (strncasecmp(param_name->s, param_expires.s, param_name->len) == 0) {
1456
+	return 0;
1457
+    } else if (strncasecmp(param_name->s, param_sip_instance.s, param_name->len) == 0) {
1458
+	return 0;
1459
+    } else if (strncasecmp(param_name->s, param_3gpp_smsip.s, param_name->len) == 0) {
1460
+	return 0;
1461
+    } else if (strncasecmp(param_name->s, param_3gpp_icsi_ref.s, param_name->len) == 0) {
1462
+	return 0;
1463
+    } else {
1464
+	return -1;
1465
+    }
1466
+}
1467
+
1422 1468
 /** Maximum reginfo XML size */
1423 1469
 #define MAX_REGINFO_SIZE 16384
1424 1470
 
... ...
@@ -1441,6 +1487,11 @@ static str r_expired = {"expired", 7};
1441 1487
 static str r_unregistered = {"unregistered", 12};
1442 1488
 static str contact_s = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\">\n", 59};
1443 1489
 static str contact_s_q = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\" q=\"%.3f\">\n", 69};
1490
+static str contact_s_params_with_body = {"\t\t<unknown-param name=\"%.*s\">\"%.*s\"</unknown-param>\n", 1};
1491
+/**NOTIFY XML needs < to be replaced by &lt; and > to be replaced by &gt;*/
1492
+/*For params that need to be fixed we pass in str removing first and last character and replace them with &lt; and &gt;**/
1493
+static str contact_s_params_with_body_fix = {"\t\t<unknown-param name=\"%.*s\">\"&lt;%.*s&gt;\"</unknown-param>\n", 1};
1494
+static str contact_s_params_no_body = {"\t\t<unknown-param name=\"%.*s\"></unknown-param>\n", 1};
1444 1495
 static str contact_e = {"\t\t</contact>\n", 13};
1445 1496
 
1446 1497
 static str uri_s = {"\t\t\t<uri>", 8};
... ...
@@ -1461,6 +1512,7 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) {
1461 1512
     impurecord_t *r;
1462 1513
     int i, j, res;
1463 1514
     ucontact_t* ptr;
1515
+    param_t *param;
1464 1516
 
1465 1517
     buf.s = bufc;
1466 1518
     buf.len = 0;
... ...
@@ -1509,19 +1561,41 @@ str generate_reginfo_full(udomain_t* _t, str* impu_list, int num_impus) {
1509 1561
 			q);
1510 1562
 	    } else {
1511 1563
 		LM_DBG("q value equal to -1");
1512
-		sprintf(pad.s, contact_s.s, ptr, r_active.len, r_active.s,
1564
+	    sprintf(pad.s, contact_s.s, ptr, r_active.len, r_active.s,
1513 1565
 			r_registered.len, r_registered.s,
1514 1566
 			ptr->expires - act_time);
1515 1567
 	    }
1516 1568
 	    pad.len = strlen(pad.s);
1517 1569
 	    STR_APPEND(buf, pad);
1518 1570
 	    STR_APPEND(buf, uri_s);
1519
-
1571
+	    
1520 1572
 	    LM_DBG("Appending contact address: <%.*s>", ptr->c.len, ptr->c.s);
1521 1573
 
1522 1574
 	    STR_APPEND(buf, (ptr->c));
1523 1575
 	    STR_APPEND(buf, uri_e);
1524
-
1576
+	    
1577
+	    param = ptr->params;
1578
+	    while (param && supported_param(&param->name) == 0) {
1579
+		
1580
+		if(param->body.len > 0) {
1581
+		    LM_DBG("This contact has params name: [%.*s] body [%.*s]\n", param->name.len, param->name.s, param->body.len, param->body.s);
1582
+		    if (param->body.s[0] == '<' && param->body.s[param->body.len -1] == '>') {
1583
+			LM_DBG("This param body starts with '<' and ends with '>' we will clean these for the NOTIFY XML with &lt; and &gt;\n");
1584
+			sprintf(pad.s, contact_s_params_with_body_fix.s, param->name.len, param->name.s, param->body.len - 2, param->body.s + 1);
1585
+		    } else {
1586
+			sprintf(pad.s, contact_s_params_with_body.s, param->name.len, param->name.s, param->body.len, param->body.s);
1587
+		    }
1588
+		    
1589
+		    pad.len = strlen(pad.s);
1590
+		    STR_APPEND(buf, pad);
1591
+		} else {
1592
+		    LM_DBG("This contact has params name: [%.*s] \n", param->name.len, param->name.s);
1593
+		    sprintf(pad.s, contact_s_params_no_body.s, param->name.len, param->name.s);
1594
+		    pad.len = strlen(pad.s);
1595
+		    STR_APPEND(buf, pad);
1596
+		}
1597
+		param = param->next;
1598
+	    }
1525 1599
 	    STR_APPEND(buf, contact_e);
1526 1600
 	    j++;
1527 1601
 	}