File: rvalue.h

package info (click to toggle)
kamailio 4.2.0-2+deb8u3
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 56,276 kB
  • sloc: ansic: 552,836; xml: 166,484; sh: 8,659; makefile: 7,676; sql: 6,235; perl: 3,487; yacc: 3,428; python: 1,457; cpp: 1,219; php: 1,047; java: 449; pascal: 194; cs: 40; awk: 27
file content (332 lines) | stat: -rw-r--r-- 11,846 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/* 
 * Copyright (C) 2008 iptelorg GmbH
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
/**
 * @file 
 * @brief SIP-router core :: rvalue expressions
 * @ingroup core
 * Module: \ref core
 */
 
/* 
 * History:
 * --------
 *  2008-11-30  initial version (andrei)
 *  2009-04-28  added string and interger versions for the EQ and DIFF
 *              operators (andrei)
 *  2009-05-05  casts operator for int & string (andrei)
 *  2010-03-16  space for an int2str result inside rval_cache (andrei)
 */

#ifndef _rvalue_h_
#define _rvalue_h_

#include "str.h"
#include "ut.h"
#include "usr_avp.h"
#include "select.h"
#include "pvar.h"
#include "route.h"
#include "parser/msg_parser.h"
#include "action.h"

enum rval_type{
	RV_NONE, RV_INT, RV_STR, /* basic types */
	RV_BEXPR, RV_ACTION_ST,  /* special values */
	RV_SEL, RV_AVP, RV_PVAR
};

enum rval_expr_op{
	RVE_NONE_OP,  /**< uninit / empty */
	RVE_RVAL_OP,  /**< special op, means that the expr. is in fact a rval */
	RVE_UMINUS_OP, /**< one member expression, returns -(val) */
	RVE_BOOL_OP,  /**< one member evaluate as bool. : (val!=0)*/
	RVE_LNOT_OP,  /**< one member evaluate as bool. : (!val)*/
	RVE_BNOT_OP,  /**< one member evaluate as binary : (~ val)*/
	RVE_MUL_OP,   /**< 2 members, returns left * right */
	RVE_DIV_OP,   /**< 2 members, returns left / right */
	RVE_MOD_OP,   /**< 2 members, returns left % right */
	RVE_MINUS_OP, /**< 2 members, returns left - right */
	RVE_BAND_OP,  /**< 2 members, returns left | right */
	RVE_BOR_OP,   /**< 2 members, returns left & right */
	RVE_BXOR_OP,   /**< 2 members, returns left XOR right */
	RVE_BLSHIFT_OP, /**< 2 members, returns left << right */
	RVE_BRSHIFT_OP, /**< 2 members, returns left >> right */
	RVE_LAND_OP,  /**< 2 members, returns left && right */
	RVE_LOR_OP,   /**< 2 members, returns left || right */
	RVE_GT_OP,    /**<  2 members, returns left > right */
	RVE_GTE_OP,   /**<  2 members, returns left >= right */
	RVE_LT_OP,    /**<  2 members, returns left  < right */
	RVE_LTE_OP,   /**<  2 members, returns left <= right */
	RVE_IEQ_OP,   /**<  2 members, int == version, returns left == right */
	RVE_IDIFF_OP, /**< 2 members, int != version, returns left != right */
	RVE_IPLUS_OP, /**< 2 members, integer +, returns int(a)+int(b) */
	/* common int & str */
	RVE_PLUS_OP,  /**< generic plus (int or str) returns left + right */
	RVE_EQ_OP,    /**<  2 members, returns left == right  (int)*/
	RVE_DIFF_OP,  /**<  2 members, returns left != right  (int)*/
	/* str only */
	RVE_CONCAT_OP, /**< 2 members, string concat, returns left . right (str)*/
	RVE_STRLEN_OP, /**< one member, string length:, returns strlen(val) (int)*/
	RVE_STREMPTY_OP, /**< one member, returns val=="" (bool) */
	RVE_STREQ_OP,  /**< 2 members, string == , returns left == right (bool)*/
	RVE_STRDIFF_OP,/**< 2 members, string != , returns left != right (bool)*/
	RVE_MATCH_OP,  /**< 2 members, string ~),  returns left matches re(right) */
	/* avp, pvars a.s.o */
	RVE_DEFINED_OP, /**< one member, returns is_defined(val) (bool) */
	RVE_NOTDEFINED_OP, /**< one member, returns is_not_defined(val) (bool) */
	RVE_INT_OP,   /**< one member, returns (int)val  (int) */
	RVE_STR_OP    /**< one member, returns (str)val  (str) */
};


struct str_re{
	str s;
	regex_t* regex;
};

union rval_val{
	void* p;
	long  l;
	str s;
	avp_spec_t avps;
	select_t sel;
	pv_spec_t pvs;
	struct action* action;
	struct expr* bexpr;
	struct str_re re;
};


struct rvalue{
	enum rval_type type;
	int refcnt; /**< refcnt, on 0 the structure is destroyed */
	union rval_val v;
	int bsize; /**< extra data size */
	short flags;
	char buf[1]; /**< extra data, like string contents can be stored here */
};


/* rvalue flags */
#define RV_CNT_ALLOCED_F  1  /**< free contents  (pkg mem allocated) */
#define RV_RV_ALLOCED_F   2  /**< free rv itself (pkg_free(rv)) */
#define RV_ALL_ALLOCED_F  (RV_CNT_ALLOCED|RV_RV_ALLOCED)
#define RV_RE_F  4 /**< string is a RE with a valid v->re member */
#define RV_RE_ALLOCED_F 8 /**< v->re.regex must be freed */

struct rval_expr{
	enum rval_expr_op op;
	union{
		struct rval_expr* rve;
		struct rvalue rval;
	}left;
	union{
		struct rval_expr* rve;
		struct rvalue rval;
	}right;
	struct cfg_pos fpos;
};


enum rval_cache_type{
	RV_CACHE_EMPTY,
	RV_CACHE_PVAR,
	RV_CACHE_AVP,
	RV_CACHE_SELECT,
	RV_CACHE_INT2STR
};

/** value cache for a rvalue struct.
  * Used to optimize functions that would need to 
  * get the value repeatedly (e.g. rval_get_btype() and then rval_get_int())
  */
struct rval_cache{
	enum rval_cache_type cache_type;
	enum rval_type val_type;
	union{
		int_str avp_val; /**< avp value */
		pv_value_t pval; /**< pvar value */
	}c;
	char i2s[INT2STR_MAX_LEN]; /**< space for converting an int to string*/
};



/** allocates a new rval (should be freed by rval_destroy()). */
struct rvalue* rval_new_empty(int extra_size);
struct rvalue* rval_new_str(str* s, int extra_size);

/**
 * @brief create a new pk_malloc'ed rvalue from a rval_val union
 * @param t rvalue type
 * @param v rvalue value
 * @param extra_size extra space to allocate
 * (so that future string operation can reuse the space)
 * @return new rv or 0 on error
 */
struct rvalue* rval_new(enum rval_type t, union rval_val* v, int extra_size);

/** inits a rvalue structure- */
void rval_init(struct rvalue* rv, enum rval_type t, union rval_val* v,
					int flags);
/** frees a rval_new(), rval_convert() or rval_expr_eval() returned rval. */
void rval_destroy(struct rvalue* rv);

/** frees a rval contents */
void rval_clean(struct rvalue* rv);

/** init a rval_cache struct */
#define rval_cache_init(rvc) \
	do{ (rvc)->cache_type=RV_CACHE_EMPTY; (rvc)->val_type=RV_NONE; }while(0)

/** destroy a rval_cache struct contents */
void rval_cache_clean(struct rval_cache* rvc);


/**
 * @brief Convert a rvalue to another rvalue, of a specific type
 *
 * Convert a rvalue to another rvalue, of a specific type.
 * The result is read-only in most cases (can be a reference
 * to another rvalue, can be checked by using rv_chg_in_place()) and
 * _must_ be rval_destroy()'ed.
 *
 * @param h run action context
 * @param msg SIP mesasge
 * @param type - type to convert to
 * @param v - rvalue to convert
 * @param c - rval_cache (cached v value if known/filled by another
 *            function), can be 0 (unknown/not needed)
 * @return pointer to a rvalue (reference to an existing one or a new
 * one, @see rv_chg_in_place() and the above comment), or 0 on error.
 */
struct rvalue* rval_convert(struct run_act_ctx* h, struct sip_msg* msg, 
							enum rval_type type, struct rvalue* v,
							struct rval_cache* c);

/** get the integer value of an rvalue. */
int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg, int* i, 
				struct rvalue* rv, struct rval_cache* cache);
/** get the string value of an rv. */
int rval_get_str(struct run_act_ctx* h, struct sip_msg* msg,
								str* s, struct rvalue* rv,
								struct rval_cache* cache);
/** get the string value of an rv in a tmp variable */
int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
								str* tmpv, struct rvalue* rv,
								struct rval_cache* cache,
								struct rval_cache* tmp_cache);

/** evals an integer expr  to an int. */
int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
						int* res, struct rval_expr* rve);

/**
 * @brief Evals a rval expression
 * @warning result must be rval_destroy()'ed if non-null (it might be
 * a reference to another rval). The result can be modified only
 * if rv_chg_in_place() returns true.
 * @param h run action context
 * @param msg SIP message
 * @param rve rvalue expression
 * @return rvalue on success, 0 on error
 */
struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
								struct rval_expr* rve);

/**
 * @brief Evals a rval expression into an int or another rv(str)
 * @warning rv result (rv_res) must be rval_destroy()'ed if non-null
 * (it might be a reference to another rval). The result can be
 * modified only if rv_chg_in_place() returns true.
 * @param h run action context
 * @param msg SIP message
 * @param res_rv pointer to rvalue result, if non-null it means the 
 * expression evaluated to a non-int (str), which will be stored here.
 * @param res_i pointer to int result, if res_rv==0 and the function
 * returns success => the result is an int which will be stored here.
 * @param rve expression that will be evaluated.
 * @param cache write-only value cache, it might be filled if non-null and
 * empty (rval_cache_init()). If non-null, it _must_ be rval_cache_clean()'ed
 * when done. 
 * @return 0 on success, -1 on error, sets *res_rv or *res_i.
 */
int rval_expr_eval_rvint( struct run_act_ctx* h, struct sip_msg* msg,
						 struct rvalue** rv_res, int* i_res,
						 struct rval_expr* rve, struct rval_cache* cache);


/** guess the type of an expression.  */
enum rval_type rve_guess_type(struct rval_expr* rve);
/** returns true if expression is constant. */
int rve_is_constant(struct rval_expr* rve);
/** returns true if the expression can have side-effect */
int rve_has_side_effects(struct rval_expr* rve);

/**
 * @brief Returns 1 if expression is valid (type-wise)
 * @param type filled with the type of the expression (RV_INT, RV_STR or
 *                RV_NONE if it's dynamic)
 * @param rve  checked expression
 * @param bad_rve set on failure to the subexpression for which the 
 * type check failed
 * @param bad_t set on failure to the type of the bad subexpression
 * @param exp_t set on failure to the expected type for the bad
 * subexpression
 * @return 0 or 1 and sets *type to the resulting type
 * (RV_INT, RV_STR or RV_NONE if it can be found only at runtime)
 */
int rve_check_type(enum rval_type* type, struct rval_expr* rve,
					struct rval_expr** bad_rve, enum rval_type* bad_type,
					enum rval_type* exp_type);
/** returns a string name for type (debugging).*/
char* rval_type_name(enum rval_type type);

/** create a RVE_RVAL_OP rval_expr, containing a single rval of the given type
  */
struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val,
									struct cfg_pos* pos);

/**
 * @brief Create a unary op. rval_expr
 * ret= op rve1
 * @param op   - rval expr. unary operator
 * @param rve1 - rval expr. on which the operator will act.
 * @param pos configuration position
 * @return new pkg_malloc'ed rval_expr or 0 on error.
 */
struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
									struct cfg_pos* pos);

/**
 * @brief Create a rval_expr. from 2 other rval exprs, using op
 * ret = rve1 op rve2
 * @param op   - rval expr. operator
 * @param rve1 - rval expr. on which the operator will act.
 * @param rve2 - rval expr. on which the operator will act.
 * @param pos configuration position
 * @return new pkg_malloc'ed rval_expr or 0 on error.
 */
struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
													  struct rval_expr* rve2,
													  struct cfg_pos* pos);
/** destroys a pkg_malloc'ed rve. */
void rve_destroy(struct rval_expr* rve);

/** fix a rval_expr. */
int fix_rval_expr(void* p);
#endif /* _rvalue_h */