Explorar o código

Merge pull request #1 from kamailio/master

update my fork from kamailio github
mojtabaesfandiari %!s(int64=5) %!d(string=hai) anos
pai
achega
0e8eb96982

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

@@ -237,6 +237,10 @@ ht_t* ht_get_table(str *name)
 	unsigned int htid;
 	ht_t *ht;
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	htid = ht_compute_hash(name);
 
 	/* does it exist */
@@ -263,6 +267,10 @@ int ht_add_table(str *name, int autoexp, str *dbtable, str *dbcols, int size,
 	int c;
 	int i;
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return -1;
+	}
 	htid = ht_compute_hash(name);
 
 	/* 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;
 	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;
+	}
 
 	hid = ht_compute_hash(name);
 
@@ -639,6 +653,10 @@ int ht_del_cell(ht_t *ht, str *name)
 	if(ht==NULL || ht->entries==NULL)
 		return -1;
 
+	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);
@@ -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)
 		return NULL;
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	hid = ht_compute_hash(name);
 
 	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)
 		return NULL;
 
+	if(name==NULL || name->s==NULL) {
+		LM_WARN("invalid name parameter\n");
+		return NULL;
+	}
 	hid = ht_compute_hash(name);
 
 	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;
 }
 
+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 i;
@@ -1157,6 +1227,10 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
 	if(ht->htexpire==0)
 		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);
@@ -1202,6 +1276,10 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
 	if(ht->htexpire==0)
 		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);

+ 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_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);
+int ht_cell_exists(ht_t *ht, str *name);
 
 int ht_dbg(void);
 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;
 }
 
+#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
 
 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_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 } }
 };

+ 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);
 }
 
+/**
+ *
+ */
+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 }
 	},
+	{ 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"),
 		SR_KEMIP_XVAL, ki_kx_get_ua,
 		{ 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
             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
-            “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
             doesn't support symmetric RTP. Disables learning of endpoint
             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;
 				<quote>extra</quote> - don't take the value from a header, but instead use
 				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
 				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

+ 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;
 					else if (str_eq(&val, "next"))
 						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
 						goto error;
 					goto next;
@@ -2363,6 +2367,8 @@ static bencode_item_t *rtpp_function_call(bencode_buffer_t *bencbuf, struct sip_
 	char md5[MD5_LEN];
 	char branch_buf[MAX_BRANCH_PARAM_LEN];
 	bencode_item_t *result;
+	tm_cell_t *t;
+	unsigned int branch_idx;
 
 	/*** 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);
 
 	if (ng_flags.via) {
-		ret = -1;
+		/* pre-process */
 		switch (ng_flags.via) {
 			case 3:
 				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 2:
 				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:
 				if (!char_msg_val(msg, md5))
 					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);
 
 				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;
 				break;
 		}