[SR-Dev] git:andrei/switch: script engine: string switch execution

Andrei Pelinescu-Onciul andrei at iptel.org
Thu Feb 19 23:50:55 CET 2009


Module: sip-router
Branch: andrei/switch
Commit: cfeefb4a0564d4b08cdbe33477a8a3e8c498f357
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=cfeefb4a0564d4b08cdbe33477a8a3e8c498f357

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Thu Feb 19 23:38:37 2009 +0100

script engine: string switch execution

- support for matching strings and regular expressions in a string
  switch (MATCH_T).

---

 action.c       |   67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 route_struct.h |    4 +-
 switch.h       |   32 +++++++++++++++++++++++++-
 3 files changed, 99 insertions(+), 4 deletions(-)

diff --git a/action.c b/action.c
index 079bbfe..cf7ac9c 100644
--- a/action.c
+++ b/action.c
@@ -116,6 +116,11 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 	struct switch_cond_table* sct;
 	struct switch_jmp_table*  sjt;
 	struct rval_expr* rve;
+	struct match_cond_table* mct;
+	struct rvalue* rv;
+	struct rvalue* rv1;
+	struct rval_cache c1;
+	str s;
 
 
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
@@ -907,6 +912,68 @@ sw_jt_def:
 											   returns passthrough */
 			}
 			break;
+		case MATCH_COND_T:
+			mct=(struct match_cond_table*)a->val[1].u.data;
+			rval_cache_init(&c1);
+			rv=0;
+			rv1=0;
+			ret=rval_expr_eval_rvint(h, msg, &rv, &v, 
+									(struct rval_expr*)a->val[0].u.data, &c1);
+									
+			if (unlikely( ret<0)){
+				/* handle error in expression => use default */
+				ret=-1;
+				goto match_cond_def;
+			}
+			if (h->run_flags & EXIT_R_F){
+				ret=0;
+				break;
+			}
+			h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break
+													    in expr */
+			if (likely(rv)){
+				rv1=rval_convert(h, msg, RV_STR, rv, &c1);
+				if (unlikely(rv1==0)){
+					ret=-1;
+					goto match_cond_def;
+				}
+				s=rv1->v.s;
+			}else{
+				/* int result in v */
+				rval_cache_clean(&c1);
+				s.s=sint2str(v, &s.len);
+			}
+			ret=1; /* default is continue */
+			for(i=0; i<mct->n; i++)
+				if (( mct->match[i].type==MATCH_STR &&
+						mct->match[i].l.s.len==s.len &&
+						memcmp(mct->match[i].l.s.s, s.s, s.len) == 0 ) ||
+					 ( mct->match[i].type==MATCH_RE &&
+					  regexec(mct->match[i].l.regex, s.s, 0, 0, 0) == 0)
+					){
+					if (likely(mct->jump[i])){
+						ret=run_actions(h, mct->jump[i], msg);
+						h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
+													   returns passthrough */
+					}
+					goto match_cleanup;
+				}
+match_cond_def:
+			if (mct->def){
+				ret=run_actions(h, mct->def, msg);
+				h->run_flags &= ~BREAK_R_F; /* catch breaks, but let
+											   returns passthrough */
+			}
+match_cleanup:
+			if (rv1){
+				rval_destroy(rv1);
+				rval_destroy(rv);
+				rval_cache_clean(&c1);
+			}else if (rv){
+				rval_destroy(rv);
+				rval_cache_clean(&c1);
+			}
+			break;
 		case WHILE_T:
 			i=0;
 			flags=0;
diff --git a/route_struct.h b/route_struct.h
index 85242af..888fadf 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -71,7 +71,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
 		SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T,
 		IF_T, SWITCH_T /* only until fixup*/,
-		BLOCK_T, EVAL_T, SWITCH_JT_T, SWITCH_COND_T, WHILE_T,
+		BLOCK_T, EVAL_T, SWITCH_JT_T, SWITCH_COND_T, MATCH_COND_T, WHILE_T,
 		MODULE_T, MODULE3_T, MODULE4_T, MODULE5_T, MODULE6_T, MODULEX_T,
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
 		AVPFLAG_OPER_T,
@@ -99,7 +99,7 @@ enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
 		SELECT_ST, PVAR_ST,
 		LVAL_ST,  RVE_ST,
 		RETCODE_ST, CASE_ST,
-		BLOCK_ST, JUMPTABLE_ST, CONDTABLE_ST
+		BLOCK_ST, JUMPTABLE_ST, CONDTABLE_ST, MATCH_CONDTABLE_ST
 };
 
 /* run flags */
diff --git a/switch.h b/switch.h
index e92cbad..a598a07 100644
--- a/switch.h
+++ b/switch.h
@@ -27,15 +27,24 @@
 #ifndef __switch_h
 #define __switch_h
 
+#include <regex.h>
+
 #include "route_struct.h"
 
+
 struct case_stms{
 	struct rval_expr* ct_rve;
 	struct action* actions;
 	struct case_stms* next;
 	struct case_stms** append;
-	int int_label;
+	int type;     /**< type: MATCH_UNKOWN, MATCH_INT, MATCH_STR, MATCH_RE */
+	int re_flags; /**< used only for REs */
 	int is_default;
+	union {
+		int match_int;
+		str match_str;
+		regex_t* match_re;
+	} label;  /**< fixed case argument */
 };
 
 
@@ -43,7 +52,7 @@ struct switch_cond_table{
 	int n;                  /**< size */
 	int* cond;              /**< int labels array */
 	struct action** jump;   /**< jump points array */
-	struct action* def; /**< default jump  */
+	struct action* def;     /**< default jump  */
 };
 
 
@@ -54,6 +63,25 @@ struct switch_jmp_table{
 	struct switch_cond_table rest; /**< normal cond. table for the rest */
 };
 
+
+enum match_str_type { MATCH_UNKNOWN, MATCH_INT, MATCH_STR, MATCH_RE };
+
+struct match_str{
+	enum match_str_type type;/**< string or RE */
+	int flags;               /**< flags for re */
+	union{
+		str s;              /* string */
+		regex_t* regex;     /**< compiled regex */
+	}l;
+};
+
+struct match_cond_table{
+	int n;                   /**< size */
+	struct match_str* match; /**< match array */
+	struct action** jump;    /**< jump points array */
+	struct action* def;      /**< default jmp */
+};
+
 int fix_switch(struct action* t);
 
 #endif /*__switch_h*/




More information about the sr-dev mailing list