Browse Source

Merge pull request #1 from kamailio/master

update my fork from kamailio github
mojtabaesfandiari 5 years ago
parent
commit
0e8eb96982

+ 79 - 1
src/modules/htable/ht_api.c

@@ -237,6 +237,10 @@ ht_t* ht_get_table(str *name)
 	unsigned int htid;
 	unsigned int htid;
 	ht_t *ht;
 	ht_t *ht;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	htid = ht_compute_hash(name);
 	htid = ht_compute_hash(name);
 
 
 	/* does it exist */
 	/* does it exist */
@@ -263,6 +267,10 @@ int ht_add_table(str *name, int autoexp, str *dbtable, str *dbcols, int size,
 	int c;
 	int c;
 	int i;
 	int i;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
 	htid = ht_compute_hash(name);
 	htid = ht_compute_hash(name);
 
 
 	/* does it exist */
 	/* does it exist */
@@ -463,8 +471,14 @@ int ht_set_cell_ex(ht_t *ht, str *name, int type, int_str *val, int mode,
 	ht_cell_t *it, *prev, *cell;
 	ht_cell_t *it, *prev, *cell;
 	time_t now;
 	time_t now;
 
 
-	if(ht==NULL || ht->entries==NULL)
+	if(ht==NULL || ht->entries==NULL) {
+		LM_WARN("invalid ht parameter\n");
+		return -1;
+	}
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
 		return -1;
 		return -1;
+	}
 
 
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
@@ -639,6 +653,10 @@ int ht_del_cell(ht_t *ht, str *name)
 	if(ht==NULL || ht->entries==NULL)
 	if(ht==NULL || ht->entries==NULL)
 		return -1;
 		return -1;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);
@@ -685,6 +703,10 @@ ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, ht_cell_t *old)
 	if(ht==NULL || ht->entries==NULL)
 	if(ht==NULL || ht->entries==NULL)
 		return NULL;
 		return NULL;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);
@@ -807,6 +829,10 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 	if(ht==NULL || ht->entries==NULL)
 	if(ht==NULL || ht->entries==NULL)
 		return NULL;
 		return NULL;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);
@@ -851,6 +877,50 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
 	return NULL;
 	return NULL;
 }
 }
 
 
+int ht_cell_exists(ht_t *ht, str *name)
+{
+	unsigned int idx;
+	unsigned int hid;
+	ht_cell_t *it;
+
+	if(ht==NULL || ht->entries==NULL)
+		return 0;
+
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
+	hid = ht_compute_hash(name);
+
+	idx = ht_get_entry(hid, ht->htsize);
+
+	/* head test and return */
+	if(ht->entries[idx].first==NULL)
+		return 0;
+
+	ht_slot_lock(ht, idx);
+	it = ht->entries[idx].first;
+	while(it!=NULL && it->cellid < hid)
+		it = it->next;
+	while(it!=NULL && it->cellid == hid) {
+		if(name->len==it->name.len
+				&& strncmp(name->s, it->name.s, name->len)==0) {
+			/* found */
+			if(ht->htexpire>0 && it->expire!=0 && it->expire<time(NULL)) {
+				/* entry has expired */
+				ht_slot_unlock(ht, idx);
+				return 0;
+			}
+			ht_slot_unlock(ht, idx);
+			return 1;
+		}
+		it = it->next;
+	}
+	ht_slot_unlock(ht, idx);
+	return 0;
+}
+
+
 int ht_dbg(void)
 int ht_dbg(void)
 {
 {
 	int i;
 	int i;
@@ -1157,6 +1227,10 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 	if(ht->htexpire==0)
 	if(ht->htexpire==0)
 		return 0;
 		return 0;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);
@@ -1202,6 +1276,10 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
 	if(ht->htexpire==0)
 	if(ht->htexpire==0)
 		return 0;
 		return 0;
 
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
 	hid = ht_compute_hash(name);
 	hid = ht_compute_hash(name);
 
 
 	idx = ht_get_entry(hid, ht->htsize);
 	idx = ht_get_entry(hid, ht->htsize);

+ 1 - 0
src/modules/htable/ht_api.h

@@ -92,6 +92,7 @@ int ht_destroy(void);
 int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode);
 int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode);
 int ht_del_cell(ht_t *ht, str *name);
 int ht_del_cell(ht_t *ht, str *name);
 ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, ht_cell_t *old);
 ht_cell_t* ht_cell_value_add(ht_t *ht, str *name, int val, ht_cell_t *old);
+int ht_cell_exists(ht_t *ht, str *name);
 
 
 int ht_dbg(void);
 int ht_dbg(void);
 ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old);
 ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old);

+ 86 - 0
src/modules/htable/htable.c

@@ -998,6 +998,31 @@ static sr_kemi_xval_t* ki_ht_getw(sip_msg_t *msg, str *htname, str *itname)
 }
 }
 
 
 
 
+/**
+ *
+ */
+static int ki_ht_is_null(sip_msg_t *msg, str *htname, str *itname)
+{
+	ht_t *ht = NULL;
+
+	/* find the hash htable */
+	ht = ht_get_table(htname);
+	if (ht == NULL) {
+		return 2;
+	}
+
+	if(ht->flags==PV_VAL_INT) {
+		/* htable defined with default value */
+		return -2;
+	}
+
+	if(ht_cell_exists(ht, itname)>0) {
+		return -1;
+	}
+
+	return 1;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -1179,6 +1204,52 @@ static int ki_ht_setxi(sip_msg_t *msg, str *htname, str *itname, int itval,
 	return 0;
 	return 0;
 }
 }
 
 
+#define KSR_HT_KEMI_NOINTVAL -255
+static ht_cell_t *_htc_ki_local=NULL;
+
+static int ki_ht_add_op(sip_msg_t *msg, str *htname, str *itname, int itval)
+{
+	ht_t *ht;
+	ht_cell_t *htc=NULL;
+
+	ht = ht_get_table(htname);
+	if(ht==NULL) {
+		return KSR_HT_KEMI_NOINTVAL;
+	}
+
+	htc = ht_cell_value_add(ht, itname, itval, _htc_ki_local);
+	if(_htc_ki_local!=htc) {
+		ht_cell_pkg_free(_htc_ki_local);
+		_htc_ki_local=htc;
+	}
+	if(htc==NULL) {
+		return KSR_HT_KEMI_NOINTVAL;
+	}
+
+	if(htc->flags&AVP_VAL_STR) {
+		return KSR_HT_KEMI_NOINTVAL;
+	}
+
+	/* integer */
+	if (ht->dmqreplicate>0) {
+		if (ht_dmq_replicate_action(HT_DMQ_SET_CELL, htname, itname, 0,
+					&htc->value, 1)!=0) {
+			LM_ERR("dmq relication failed\n");
+		}
+	}
+	return htc->value.n;
+}
+
+static int ki_ht_inc(sip_msg_t *msg, str *htname, str *itname)
+{
+	return ki_ht_add_op(msg, htname, itname, 1);
+}
+
+static int ki_ht_dec(sip_msg_t *msg, str *htname, str *itname)
+{
+	return ki_ht_add_op(msg, htname, itname, -1);
+}
+
 #define RPC_DATE_BUF_LEN 21
 #define RPC_DATE_BUF_LEN 21
 
 
 static const char* htable_dump_doc[2] = {
 static const char* htable_dump_doc[2] = {
@@ -1816,6 +1887,21 @@ static sr_kemi_t sr_kemi_htable_exports[] = {
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_STR,
 			SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE }
 			SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
 	},
+	{ str_init("htable"), str_init("sht_is_null"),
+		SR_KEMIP_INT, ki_ht_is_null,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("htable"), str_init("sht_inc"),
+		SR_KEMIP_INT, ki_ht_inc,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("htable"), str_init("sht_dec"),
+		SR_KEMIP_INT, ki_ht_dec,
+		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
 
 
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
 };
 };

+ 56 - 0
src/modules/kemix/kemix_mod.c

@@ -670,6 +670,46 @@ static sr_kemi_xval_t* ki_kx_getw_body(sip_msg_t *msg)
 	return ki_kx_get_body_mode(msg, SR_KEMI_XVAL_NULL_PRINT);
 	return ki_kx_get_body_mode(msg, SR_KEMI_XVAL_NULL_PRINT);
 }
 }
 
 
+/**
+ *
+ */
+static sr_kemi_xval_t* ki_kx_get_duri_mode(sip_msg_t *msg, int xmode)
+{
+	memset(&_sr_kemi_kx_xval, 0, sizeof(sr_kemi_xval_t));
+	if(msg->dst_uri.s==NULL || msg->dst_uri.len<=0) {
+		sr_kemi_xval_null(&_sr_kemi_kx_xval, xmode);
+		return &_sr_kemi_kx_xval;
+	}
+
+	_sr_kemi_kx_xval.vtype = SR_KEMIP_STR;
+	_sr_kemi_kx_xval.v.s = msg->dst_uri;
+	return &_sr_kemi_kx_xval;
+}
+
+/**
+ *
+ */
+static sr_kemi_xval_t* ki_kx_get_duri(sip_msg_t *msg)
+{
+	return ki_kx_get_duri_mode(msg, SR_KEMI_XVAL_NULL_NONE);
+}
+
+/**
+ *
+ */
+static sr_kemi_xval_t* ki_kx_getw_duri(sip_msg_t *msg)
+{
+	return ki_kx_get_duri_mode(msg, SR_KEMI_XVAL_NULL_PRINT);
+}
+
+/**
+ *
+ */
+static sr_kemi_xval_t* ki_kx_gete_duri(sip_msg_t *msg)
+{
+	return ki_kx_get_duri_mode(msg, SR_KEMI_XVAL_NULL_EMPTY);
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -755,6 +795,22 @@ static sr_kemi_t sr_kemi_kx_exports[] = {
 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
 	},
 	},
+	{ str_init("kx"), str_init("get_duri"),
+		SR_KEMIP_XVAL, ki_kx_get_duri,
+		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("kx"), str_init("gete_duri"),
+		SR_KEMIP_XVAL, ki_kx_gete_duri,
+		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+	{ str_init("kx"), str_init("getw_duri"),
+		SR_KEMIP_XVAL, ki_kx_getw_duri,
+		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
+			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
+	},
+
 	{ str_init("kx"), str_init("get_ua"),
 	{ str_init("kx"), str_init("get_ua"),
 		SR_KEMIP_XVAL, ki_kx_get_ua,
 		SR_KEMIP_XVAL, ki_kx_get_ua,
 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,

+ 16 - 14
src/modules/rtpengine/README

@@ -1882,20 +1882,22 @@ rtpengine_offer();
             “Via” header; “auto” - use the first “Via” header if this is a
             “Via” header; “auto” - use the first “Via” header if this is a
             request, or the second one if this is a reply; “extra” - don't
             request, or the second one if this is a reply; “extra” - don't
             take the value from a header, but instead use the value of the
             take the value from a header, but instead use the value of the
-            “extra_id_pv” variable; “next” - use the value of the
-            “Via/branch” tag that Kamailio will generate for the next
-            branch. This can be used to create one media session per
-            branch on the RTP proxy. When sending a subsequent “delete”
-            command to the RTP proxy, you can then stop just the session
-            for a specific branch when passing the flag '1' or '2' in the
-            “rtpengine_delete”, or stop all sessions for a call when not
-            passing one of those two flags there. This is especially
-            useful if you have serially forked call scenarios where the
-            RTP proxy gets an “offer” command for a new branch, and then a
-            “delete” command for the previous branch, which would
-            otherwise delete the full call, breaking the subsequent
-            “answer” for the new branch. This flag is only supported by
-            the Sipwise rtpengine RTP proxy at the moment!
+            “extra_id_pv” variable; “next” - use the branch ID generated
+            by Kamailio for the next outgoing branch; “auto-next” - use
+            “next” in requests and “1” in replies; “auto-extra” - use
+            “extra” in requests and “1” in replies. This can be used to
+            create one media session per branch on the RTP proxy. When
+            sending a subsequent “delete” command to the RTP proxy, you
+            can then stop just the session for a specific branch when
+            passing the flag '1' or '2' in the “rtpengine_delete”, or stop
+            all sessions for a call when not passing one of those two
+            flags there. This is especially useful if you have serially
+            forked call scenarios where the RTP proxy gets an “offer”
+            command for a new branch, and then a “delete” command for the
+            previous branch, which would otherwise delete the full call,
+            breaking the subsequent “answer” for the new branch. This flag
+            is only supported by the Sipwise rtpengine RTP proxy at the
+            moment!
           + asymmetric - flags that UA from which message is received
           + asymmetric - flags that UA from which message is received
             doesn't support symmetric RTP. Disables learning of endpoint
             doesn't support symmetric RTP. Disables learning of endpoint
             addresses in the Sipwise rtpengine proxy.
             addresses in the Sipwise rtpengine proxy.

+ 6 - 2
src/modules/rtpengine/doc/rtpengine_admin.xml

@@ -2111,8 +2111,12 @@ rtpengine_offer();
 				a request, or the second one if this is a reply;
 				a request, or the second one if this is a reply;
 				<quote>extra</quote> - don't take the value from a header, but instead use
 				<quote>extra</quote> - don't take the value from a header, but instead use
 				the value of the <quote>extra_id_pv</quote> variable;
 				the value of the <quote>extra_id_pv</quote> variable;
-				<quote>next</quote> - use the value of the <quote>Via/branch</quote>
-				tag that Kamailio will generate for the next branch.
+				<quote>next</quote> - use the branch ID generated by &kamailio; for the
+				next outgoing branch;
+				<quote>auto-next</quote> - use <quote>next</quote> in requests and
+				<quote>1</quote> in replies;
+				<quote>auto-extra</quote> - use <quote>extra</quote> in requests and
+				<quote>1</quote> in replies.
 				This can be used to create one media session per branch
 				This can be used to create one media session per branch
 				on the &rtp; proxy. When sending a subsequent <quote>delete</quote> command to
 				on the &rtp; proxy. When sending a subsequent <quote>delete</quote> command to
 				the &rtp; proxy, you can then stop just the session for a specific branch when
 				the &rtp; proxy, you can then stop just the session for a specific branch when

+ 25 - 3
src/modules/rtpengine/rtpengine.c

@@ -2268,6 +2268,10 @@ static int parse_flags(struct ng_flags_parse *ng_flags, struct sip_msg *msg, enu
 						ng_flags->via = -1;
 						ng_flags->via = -1;
 					else if (str_eq(&val, "next"))
 					else if (str_eq(&val, "next"))
 						ng_flags->via = -2;
 						ng_flags->via = -2;
+					else if (str_eq(&val, "auto-next") || str_eq(&val, "next-auto"))
+						ng_flags->via = -3;
+					else if (str_eq(&val, "auto-extra") || str_eq(&val, "extra-auto"))
+						ng_flags->via = -4;
 					else
 					else
 						goto error;
 						goto error;
 					goto next;
 					goto next;
@@ -2363,6 +2367,8 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 	char md5[MD5_LEN];
 	char md5[MD5_LEN];
 	char branch_buf[MAX_BRANCH_PARAM_LEN];
 	char branch_buf[MAX_BRANCH_PARAM_LEN];
 	bencode_item_t *result;
 	bencode_item_t *result;
+	tm_cell_t *t;
+	unsigned int branch_idx;
 
 
 	/*** get & init basic stuff needed ***/
 	/*** get & init basic stuff needed ***/
 
 
@@ -2453,11 +2459,21 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 	bencode_dictionary_add_str(ng_flags.dict, "call-id", &ng_flags.call_id);
 	bencode_dictionary_add_str(ng_flags.dict, "call-id", &ng_flags.call_id);
 
 
 	if (ng_flags.via) {
 	if (ng_flags.via) {
-		ret = -1;
+		/* pre-process */
 		switch (ng_flags.via) {
 		switch (ng_flags.via) {
 			case 3:
 			case 3:
 				ng_flags.via = (msg->first_line.type == SIP_REPLY) ? 2 : 1;
 				ng_flags.via = (msg->first_line.type == SIP_REPLY) ? 2 : 1;
-				/* fall thru */
+				break;
+			case -3:
+				ng_flags.via = (msg->first_line.type == SIP_REPLY) ? 1 : -2;
+				break;
+			case -4:
+				ng_flags.via = (msg->first_line.type == SIP_REPLY) ? 1 : -1;
+				break;
+		}
+
+		ret = -1;
+		switch (ng_flags.via) {
 			case 1:
 			case 1:
 			case 2:
 			case 2:
 				ret = get_via_branch(msg, ng_flags.via, &viabranch);
 				ret = get_via_branch(msg, ng_flags.via, &viabranch);
@@ -2469,10 +2485,16 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 			case -2:
 			case -2:
 				if (!char_msg_val(msg, md5))
 				if (!char_msg_val(msg, md5))
 					break;
 					break;
+				branch_idx = 0;
+				if (tmb.t_gett) {
+					t = tmb.t_gett();
+					if (t && t != T_UNDEFINED)
+						branch_idx = t->nr_of_outgoings;
+				}
 				msg->hash_index = hash(msg->callid->body, get_cseq(msg)->number);
 				msg->hash_index = hash(msg->callid->body, get_cseq(msg)->number);
 
 
 				viabranch.s = branch_buf;
 				viabranch.s = branch_buf;
-				if (branch_builder(msg->hash_index, 0, md5, 0, branch_buf, &viabranch.len))
+				if (branch_builder(msg->hash_index, 0, md5, branch_idx, branch_buf, &viabranch.len))
 					ret = 0;
 					ret = 0;
 				break;
 				break;
 		}
 		}