pkg/kamailio/fedora/16: Updated rel in .spec to dev2
[sip-router] / flags.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 /*
28  * History:
29  * --------
30  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
31  *  2006-02-02  named flags support (andrei)
32  */
33
34 /*!
35  * \file
36  * \brief SIP-router core :: 
37  * \ingroup core
38  * Module: \ref core
39  */
40
41
42 #include <limits.h>
43 #include "sr_module.h"
44 #include "dprint.h"
45 #include "parser/msg_parser.h"
46 #include "flags.h"
47 #include "error.h"
48 #include "stdlib.h"
49 #include "hashes.h"
50 #include "clist.h"
51 #include "mem/mem.h"
52
53 /* Script flags */
54 static flag_t sflags = 0;
55
56
57 int setflag( struct sip_msg* msg, flag_t flag ) {
58         msg->flags |= 1 << flag;
59         return 1;
60 }
61
62 int resetflag( struct sip_msg* msg, flag_t flag ) {
63         msg->flags &= ~ (1 << flag);
64         return 1;
65 }
66
67 int isflagset( struct sip_msg* msg, flag_t flag ) {
68         return (msg->flags & (1<<flag)) ? 1 : -1;
69 }
70
71 int flag_in_range( flag_t flag ) {
72         if (flag > MAX_FLAG ) {
73                 LOG(L_ERR, "ERROR: message flag %d too high; MAX=%d\n",
74                         flag, MAX_FLAG );
75                 return 0;
76         }
77         if (flag<0) {
78                 LOG(L_ERR, "ERROR: message flag (%d) must be in range %d..%d\n",
79                         flag, 0, MAX_FLAG );
80                 return 0;
81         }
82         return 1;
83 }
84
85
86 int setsflagsval(flag_t val)
87 {
88         sflags = val;
89         return 1;
90 }
91
92
93 int setsflag(flag_t flag)
94 {
95         sflags |= 1 << flag;
96         return 1;
97 }
98
99
100 int resetsflag(flag_t flag)
101 {
102         sflags &= ~ (1 << flag);
103         return 1;
104 }
105
106
107 int issflagset(flag_t flag)
108 {
109         return (sflags & (1<<flag)) ? 1 : -1;
110 }
111
112
113 flag_t getsflags(void)
114 {
115         return sflags;
116 }
117
118
119 /* use 2^k */
120 #define FLAGS_NAME_HASH_ENTRIES         32
121
122 struct flag_entry{
123         struct flag_entry* next;
124         struct flag_entry* prev;
125         str name;
126         int no;
127 };
128
129
130 struct flag_hash_head{
131         struct flag_entry* next;
132         struct flag_entry* prev;
133 };
134
135 static struct flag_hash_head  name2flags[FLAGS_NAME_HASH_ENTRIES];
136 static unsigned char registered_flags[MAX_FLAG+1];
137
138
139 void init_named_flags()
140 {
141         int r;
142         
143         for (r=0; r<FLAGS_NAME_HASH_ENTRIES; r++)
144                 clist_init(&name2flags[r], next, prev);
145 }
146
147
148
149 /* returns 0 on success, -1 on error */
150 int check_flag(int n)
151 {
152         if (!flag_in_range(n))
153                 return -1;
154         if (registered_flags[n]){
155                 LOG(L_WARN, "WARNING: check_flag: flag %d is already used by "
156                                         " a named flag\n", n);
157         }
158         return 0;
159 }
160
161
162 inline static struct flag_entry* flag_search(struct flag_hash_head* lst,
163                                                                                                 char* name, int len)
164 {
165         struct flag_entry* fe;
166         
167         clist_foreach(lst, fe, next){
168                 if ((fe->name.len==len) && (memcmp(fe->name.s, name, len)==0)){
169                         /* found */
170                         return fe;
171                 }
172         }
173         return 0;
174 }
175
176
177
178 /* returns flag entry or 0 on not found */
179 inline static struct flag_entry* get_flag_entry(char* name, int len)
180 {
181         int h;
182         /* get hash */
183         h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
184         return flag_search(&name2flags[h], name, len);
185 }
186
187
188
189 /* returns flag number, or -1 on error */
190 int get_flag_no(char* name, int len)
191 {
192         struct flag_entry* fe;
193         
194         fe=get_flag_entry(name, len);
195         return (fe)?fe->no:-1;
196 }
197
198
199
200 /* resgiter a new flag name and associates it with pos
201  * pos== -1 => any position will do 
202  * returns flag pos on success (>=0)
203  *         -1  flag is an alias for an already existing flag
204  *         -2  flag already registered
205  *         -3  mem. alloc. failure
206  *         -4  invalid pos
207  *         -5 no free flags */
208 int register_flag(char* name, int pos)
209 {
210         struct flag_entry* e;
211         int len;
212         unsigned int r;
213         static unsigned int crt_flag=0;
214         unsigned int last_flag;
215         unsigned int h;
216         
217         len=strlen(name);
218         h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
219         /* check if the name already exists */
220         e=flag_search(&name2flags[h], name, len);
221         if (e){
222                 LOG(L_ERR, "ERROR: register_flag: flag %.*s already registered\n",
223                                         len, name);
224                 return -2;
225         }
226         /* check if there is already another flag registered at pos */
227         if (pos!=-1){
228                 if ((pos<0) || (pos>MAX_FLAG)){
229                         LOG(L_ERR, "ERROR: register_flag: invalid flag %.*s "
230                                         "position(%d)\n", len, name, pos);
231                         return -4;
232                 }
233                 if (registered_flags[pos]!=0){
234                         LOG(L_WARN, "WARNING: register_flag:  %.*s:  flag %d already in "
235                                         "use under another name\n", len, name, pos);
236                         /* continue */
237                 }
238         }else{
239                 /* alloc an empty flag */
240                 last_flag=crt_flag+(MAX_FLAG+1);
241                 for (; crt_flag!=last_flag; crt_flag++){
242                         r=crt_flag%(MAX_FLAG+1);
243                         if (registered_flags[r]==0){
244                                 pos=r;
245                                 break;
246                         }
247                 }
248                 if (pos==-1){
249                         LOG(L_ERR, "ERROR: register_flag: could not register %.*s"
250                                         " - too many flags\n", len, name);
251                         return -5;
252                 }
253         }
254         registered_flags[pos]++;
255         
256         e=pkg_malloc(sizeof(struct flag_entry));
257         if (e==0){
258                 LOG(L_ERR, "ERROR: register_flag: memory allocation failure\n");
259                 return -3;
260         }
261         e->name.s=name;
262         e->name.len=len;
263         e->no=pos;
264         clist_insert(&name2flags[h], e, next, prev);
265         return pos;
266 }
267
268
269
270 #ifdef _GET_AWAY
271
272 /* wrapping functions for flag processing  */
273 static int fixup_t_flag(void** param, int param_no)
274 {
275     unsigned int *code;
276         char *c;
277         int token;
278
279         DBG("DEBUG: fixing flag: %s\n", (char *) (*param));
280
281         if (param_no!=1) {
282                 LOG(L_ERR, "ERROR: TM module: only parameter #1 for flags can be"
283                                         " fixed\n");
284                 return E_BUG;
285         };
286
287         if ( !(code =pkg_malloc( sizeof( unsigned int) )) ) return E_OUT_OF_MEM;
288
289         *code = 0;
290         c = *param;
291         while ( *c && (*c==' ' || *c=='\t')) c++; /* initial whitespaces */
292
293         token=1;
294         if (strcasecmp(c, "white")==0) *code=FL_WHITE;
295         else if (strcasecmp(c, "yellow")==0) *code=FL_YELLOW;
296         else if (strcasecmp(c, "green")==0) *code=FL_GREEN;
297         else if (strcasecmp(c, "red")==0) *code=FL_RED;
298         else if (strcasecmp(c, "blue")==0) *code=FL_BLUE;
299         else if (strcasecmp(c, "magenta")==0) *code=FL_MAGENTA;
300         else if (strcasecmp(c, "brown")==0) *code=FL_BROWN;
301         else if (strcasecmp(c, "black")==0) *code=FL_BLACK;
302         else if (strcasecmp(c, "acc")==0) *code=FL_ACC;
303         else {
304                 token=0;
305                 while ( *c && *c>='0' && *c<='9' ) {
306                         *code = *code*10+ *c-'0';
307                         if (*code > (sizeof( flag_t ) * CHAR_BIT - 1 )) {
308                                 LOG(L_ERR, "ERROR: TM module: too big flag number: %s; MAX=%d\n",
309                                         (char *) (*param), sizeof( flag_t ) * CHAR_BIT - 1 );
310                                 goto error;
311                         }
312                         c++;
313                 }
314         }
315         while ( *c && (*c==' ' || *c=='\t')) c++; /* terminating whitespaces */
316
317         if ( *code == 0 ) {
318                 LOG(L_ERR, "ERROR: TM module: bad flag number: %s\n", (char *) (*param));
319                 goto error;
320         }
321
322         if (*code < FL_MAX && token==0) {
323                 LOG(L_ERR, "ERROR: TM module: too high flag number: %s (%d)\n; lower number"
324                         " bellow %d reserved\n", (char *) (*param), *code, FL_MAX );
325                 goto error;
326         }
327
328         /* free string */
329         pkg_free( *param );
330         /* fix now */
331         *param = code;
332         
333         return 0;
334
335 error:
336         pkg_free( code );
337         return E_CFG;
338 }
339
340
341 #endif