- support for matching strings and regular expressions in a string
switch (MATCH_T).
... | ... |
@@ -116,6 +116,11 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) |
116 | 116 |
struct switch_cond_table* sct; |
117 | 117 |
struct switch_jmp_table* sjt; |
118 | 118 |
struct rval_expr* rve; |
119 |
+ struct match_cond_table* mct; |
|
120 |
+ struct rvalue* rv; |
|
121 |
+ struct rvalue* rv1; |
|
122 |
+ struct rval_cache c1; |
|
123 |
+ str s; |
|
119 | 124 |
|
120 | 125 |
|
121 | 126 |
/* reset the value of error to E_UNSPEC so avoid unknowledgable |
... | ... |
@@ -907,6 +912,68 @@ sw_jt_def: |
907 | 912 |
returns passthrough */ |
908 | 913 |
} |
909 | 914 |
break; |
915 |
+ case MATCH_COND_T: |
|
916 |
+ mct=(struct match_cond_table*)a->val[1].u.data; |
|
917 |
+ rval_cache_init(&c1); |
|
918 |
+ rv=0; |
|
919 |
+ rv1=0; |
|
920 |
+ ret=rval_expr_eval_rvint(h, msg, &rv, &v, |
|
921 |
+ (struct rval_expr*)a->val[0].u.data, &c1); |
|
922 |
+ |
|
923 |
+ if (unlikely( ret<0)){ |
|
924 |
+ /* handle error in expression => use default */ |
|
925 |
+ ret=-1; |
|
926 |
+ goto match_cond_def; |
|
927 |
+ } |
|
928 |
+ if (h->run_flags & EXIT_R_F){ |
|
929 |
+ ret=0; |
|
930 |
+ break; |
|
931 |
+ } |
|
932 |
+ h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return & break |
|
933 |
+ in expr */ |
|
934 |
+ if (likely(rv)){ |
|
935 |
+ rv1=rval_convert(h, msg, RV_STR, rv, &c1); |
|
936 |
+ if (unlikely(rv1==0)){ |
|
937 |
+ ret=-1; |
|
938 |
+ goto match_cond_def; |
|
939 |
+ } |
|
940 |
+ s=rv1->v.s; |
|
941 |
+ }else{ |
|
942 |
+ /* int result in v */ |
|
943 |
+ rval_cache_clean(&c1); |
|
944 |
+ s.s=sint2str(v, &s.len); |
|
945 |
+ } |
|
946 |
+ ret=1; /* default is continue */ |
|
947 |
+ for(i=0; i<mct->n; i++) |
|
948 |
+ if (( mct->match[i].type==MATCH_STR && |
|
949 |
+ mct->match[i].l.s.len==s.len && |
|
950 |
+ memcmp(mct->match[i].l.s.s, s.s, s.len) == 0 ) || |
|
951 |
+ ( mct->match[i].type==MATCH_RE && |
|
952 |
+ regexec(mct->match[i].l.regex, s.s, 0, 0, 0) == 0) |
|
953 |
+ ){ |
|
954 |
+ if (likely(mct->jump[i])){ |
|
955 |
+ ret=run_actions(h, mct->jump[i], msg); |
|
956 |
+ h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
|
957 |
+ returns passthrough */ |
|
958 |
+ } |
|
959 |
+ goto match_cleanup; |
|
960 |
+ } |
|
961 |
+match_cond_def: |
|
962 |
+ if (mct->def){ |
|
963 |
+ ret=run_actions(h, mct->def, msg); |
|
964 |
+ h->run_flags &= ~BREAK_R_F; /* catch breaks, but let |
|
965 |
+ returns passthrough */ |
|
966 |
+ } |
|
967 |
+match_cleanup: |
|
968 |
+ if (rv1){ |
|
969 |
+ rval_destroy(rv1); |
|
970 |
+ rval_destroy(rv); |
|
971 |
+ rval_cache_clean(&c1); |
|
972 |
+ }else if (rv){ |
|
973 |
+ rval_destroy(rv); |
|
974 |
+ rval_cache_clean(&c1); |
|
975 |
+ } |
|
976 |
+ break; |
|
910 | 977 |
case WHILE_T: |
911 | 978 |
i=0; |
912 | 979 |
flags=0; |
... | ... |
@@ -71,7 +71,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, |
71 | 71 |
SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, |
72 | 72 |
SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T, |
73 | 73 |
IF_T, SWITCH_T /* only until fixup*/, |
74 |
- BLOCK_T, EVAL_T, SWITCH_JT_T, SWITCH_COND_T, WHILE_T, |
|
74 |
+ BLOCK_T, EVAL_T, SWITCH_JT_T, SWITCH_COND_T, MATCH_COND_T, WHILE_T, |
|
75 | 75 |
MODULE_T, MODULE3_T, MODULE4_T, MODULE5_T, MODULE6_T, MODULEX_T, |
76 | 76 |
SETFLAG_T, RESETFLAG_T, ISFLAGSET_T , |
77 | 77 |
AVPFLAG_OPER_T, |
... | ... |
@@ -99,7 +99,7 @@ enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST, |
99 | 99 |
SELECT_ST, PVAR_ST, |
100 | 100 |
LVAL_ST, RVE_ST, |
101 | 101 |
RETCODE_ST, CASE_ST, |
102 |
- BLOCK_ST, JUMPTABLE_ST, CONDTABLE_ST |
|
102 |
+ BLOCK_ST, JUMPTABLE_ST, CONDTABLE_ST, MATCH_CONDTABLE_ST |
|
103 | 103 |
}; |
104 | 104 |
|
105 | 105 |
/* run flags */ |
... | ... |
@@ -27,15 +27,24 @@ |
27 | 27 |
#ifndef __switch_h |
28 | 28 |
#define __switch_h |
29 | 29 |
|
30 |
+#include <regex.h> |
|
31 |
+ |
|
30 | 32 |
#include "route_struct.h" |
31 | 33 |
|
34 |
+ |
|
32 | 35 |
struct case_stms{ |
33 | 36 |
struct rval_expr* ct_rve; |
34 | 37 |
struct action* actions; |
35 | 38 |
struct case_stms* next; |
36 | 39 |
struct case_stms** append; |
37 |
- int int_label; |
|
40 |
+ int type; /**< type: MATCH_UNKOWN, MATCH_INT, MATCH_STR, MATCH_RE */ |
|
41 |
+ int re_flags; /**< used only for REs */ |
|
38 | 42 |
int is_default; |
43 |
+ union { |
|
44 |
+ int match_int; |
|
45 |
+ str match_str; |
|
46 |
+ regex_t* match_re; |
|
47 |
+ } label; /**< fixed case argument */ |
|
39 | 48 |
}; |
40 | 49 |
|
41 | 50 |
|
... | ... |
@@ -43,7 +52,7 @@ struct switch_cond_table{ |
43 | 52 |
int n; /**< size */ |
44 | 53 |
int* cond; /**< int labels array */ |
45 | 54 |
struct action** jump; /**< jump points array */ |
46 |
- struct action* def; /**< default jump */ |
|
55 |
+ struct action* def; /**< default jump */ |
|
47 | 56 |
}; |
48 | 57 |
|
49 | 58 |
|
... | ... |
@@ -54,6 +63,25 @@ struct switch_jmp_table{ |
54 | 63 |
struct switch_cond_table rest; /**< normal cond. table for the rest */ |
55 | 64 |
}; |
56 | 65 |
|
66 |
+ |
|
67 |
+enum match_str_type { MATCH_UNKNOWN, MATCH_INT, MATCH_STR, MATCH_RE }; |
|
68 |
+ |
|
69 |
+struct match_str{ |
|
70 |
+ enum match_str_type type;/**< string or RE */ |
|
71 |
+ int flags; /**< flags for re */ |
|
72 |
+ union{ |
|
73 |
+ str s; /* string */ |
|
74 |
+ regex_t* regex; /**< compiled regex */ |
|
75 |
+ }l; |
|
76 |
+}; |
|
77 |
+ |
|
78 |
+struct match_cond_table{ |
|
79 |
+ int n; /**< size */ |
|
80 |
+ struct match_str* match; /**< match array */ |
|
81 |
+ struct action** jump; /**< jump points array */ |
|
82 |
+ struct action* def; /**< default jmp */ |
|
83 |
+}; |
|
84 |
+ |
|
57 | 85 |
int fix_switch(struct action* t); |
58 | 86 |
|
59 | 87 |
#endif /*__switch_h*/ |