[sr-dev] git:master: tm: new select functions

Miklos Tirpak miklos at iptel.org
Fri Feb 5 16:53:08 CET 2010


Module: sip-router
Branch: master
Commit: 7cbf4e9cbf4b877a661baf67446aeff10cd331cc
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7cbf4e9cbf4b877a661baf67446aeff10cd331cc

Author: Miklos Tirpak <miklos at iptel.org>
Committer: Miklos Tirpak <miklos at iptel.org>
Date:   Wed Nov 11 12:51:16 2009 +0100

tm: new select functions

New select functions have been introduced:
- @tm.uac.response_retransmission
	Returns "1" if the response is a retransmission
	otherwise "-1".
- @tm.uac.last_status
	Returns the last saved status code of the current branch.
- @tm.uas.request.neg_ack_retransmission
	Returns "1" if the negative ACK request is a retransmission
	otherwise "-1".
	Note: This select function can be used only for negative ACK messages
	(ACK for >=300 responses), it should be enhanced in the future
	to work on any type of requests.

---

 modules/tm/select.c |   94 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)

diff --git a/modules/tm/select.c b/modules/tm/select.c
index a477512..0024a61 100644
--- a/modules/tm/select.c
+++ b/modules/tm/select.c
@@ -36,6 +36,7 @@
 #include "../../ut.h"
 #include "../../select.h"
 #include "../../select_buf.h"
+#include "../../parser/msg_parser.h"
 
 #define RETURN0_res(x) {*res=(x);return 0;}
 
@@ -121,6 +122,26 @@ static int select_tm_uas_response(str* res, select_t* s, struct sip_msg* msg) {
 	return 0;	
 }
 
+/* TODO: implement a general select function that works with any
+ * kind of requests not only with negative ACKs
+ */
+static int select_tm_uas_request_neg_ack_retransmission(str* res, select_t* s, struct sip_msg* msg) {
+        int rv;
+
+	SELECT_check(msg);
+        rv = ((msg->REQ_METHOD == METHOD_ACK)
+		&& (t->uas.status >= 300)
+		/* Misuse the timer flag of the 200 retransmission buffer
+		 * to check whether or not this is an ACK retransmission.
+		 * Warning: this check is not 100% fail-safe because two
+		 * ACKs can be processed in parallel and none of them
+		 * may be considered a retransmission - Miklos */
+		&& (t->uas.response.t_active == 0)) ? 1 : -1;
+
+        return int_to_static_buffer(res, rv);
+}
+
+
 static ABSTRACT_F(select_tm_uac);
 
 static int select_tm_uac_count(str* res, select_t* s, struct sip_msg* msg) {
@@ -135,6 +156,76 @@ static int select_tm_uac_relayed(str* res, select_t* s, struct sip_msg* msg) {
 
 static ABSTRACT_F(select_tm_uac_branch);
 
+/**
+ * Get last_status from current branch. Helper function.
+ * @see selects select_tm_uac_last_status
+ * @see select_tm_uac_response_retransmission
+ */
+static int get_last_status(struct sip_msg* msg, int *last_status)
+{
+	unsigned int branch;
+	char *bptr;
+	int blen;
+	struct cell *t;
+
+/*	DBG("select_tm_uac_last_status: branch param name: '%.*s', value: '%.*s'\n",
+			msg->via1->branch->name.len,
+			msg->via1->branch->name.s,
+			msg->via1->branch->value.len,
+			msg->via1->branch->value.s);
+*/
+	
+	/* branch ID consist of MAGIC '.' HASHID '.'  BRANCH_ID */
+	blen = 0;
+	for (bptr = msg->via1->branch->value.s + msg->via1->branch->value.len - 1;
+	     bptr != msg->via1->branch->value.s;
+	     bptr--, blen++)
+	{
+		if (*bptr == '.') break;
+	}
+	bptr++;
+	/* we have a pointer to the branch number */
+/*	DBG("branch number: '%.*s'\n", blen, bptr); */
+	if (reverse_hex2int(bptr, blen, &branch) < 0) {
+		ERR("Wrong branch number in Via1 branch param\n");
+		return -1;
+	}
+	
+	t = get_t();
+	if ( (t == NULL) || (t == T_UNDEFINED) ) {
+		ERR("get_last_status: no transaction\n");
+		return -1;
+	}
+
+/*	DBG("select_tm_uac_last_status: branch = %d\n", branch); */
+	*last_status = t->uac[branch].last_received;
+	return 1;
+}
+/**
+ * Get last status in current branch.
+ */
+static int select_tm_uac_last_status(str* res, select_t* s, struct sip_msg* msg) {
+	int last_status;
+	if (get_last_status(msg, &last_status) < 0) return -1;
+	return int_to_static_buffer(res, last_status);
+}
+/**
+ * Comparison function which compares current status and last status
+ * in current branch.
+ * It is a simplified method how to detect incoming retransmited responses.
+ * @return  1 if @status is less or equal @tm.uac.last_status (retransmited response)
+ *          otherwise returns -1 (not retransmited response).
+ * @see get_last_status
+ */
+static int select_tm_uac_response_retransmission(str* res, select_t* s, struct sip_msg* msg) {
+	int last_status, rv;
+	if (get_last_status(msg, &last_status) < 0) return -1;
+	rv = msg->first_line.u.reply.statuscode <= last_status ? 1 : -1;
+
+/*	DBG("select_tm_uac_response_retransmission: %d\n", rv); */
+	return int_to_static_buffer(res, rv);
+}
+
 static int select_tm_uac_status(str* res, select_t* s, struct sip_msg* msg) {
 	SELECT_check_branch(s, msg);
 	return int_to_static_buffer(res, t->uac[BRANCH_NO(s)].last_received);
@@ -174,10 +265,13 @@ static select_row_t select_declaration[] = {
 	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("local_to_tag"), select_tm_uas_local_to_tag, 0},
 	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("response"), select_tm_uas_response, 0},
 	{ select_tm_uas, SEL_PARAM_STR, STR_STATIC_INIT("resp"), select_tm_uas_response, 0},
+	{ select_tm_uas_request, SEL_PARAM_STR, STR_STATIC_INIT("neg_ack_retransmission"), select_tm_uas_request_neg_ack_retransmission, 0},
 
 	{ select_tm, SEL_PARAM_STR, STR_STATIC_INIT("uac"), select_tm_uac, SEL_PARAM_EXPECTED},
 	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("count"), select_tm_uac_count, 0},
 	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("relayed"), select_tm_uac_relayed, 0},
+	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("last_status"), select_tm_uac_last_status, 0},  /* last status of current branch */
+	{ select_tm_uac, SEL_PARAM_STR, STR_STATIC_INIT("response_retransmission"), select_tm_uac_response_retransmission, 0},  /* last status of current branch */
 	{ select_tm_uac, SEL_PARAM_INT, STR_NULL, select_tm_uac_branch, SEL_PARAM_EXPECTED},
 	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("status"), select_tm_uac_status, 0},
 	{ select_tm_uac_branch, SEL_PARAM_STR, STR_STATIC_INIT("uri"), select_tm_uac_uri, 0},




More information about the sr-dev mailing list