Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

flags.c

Go to the documentation of this file.
00001 /*
00002  * $Id: flags.c,v 1.10 2006/12/13 22:50:46 andrei Exp $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of ser, a free SIP server.
00007  *
00008  * ser is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * For a license to use the ser software under conditions
00014  * other than those described here, or to purchase support for this
00015  * software, please contact iptel.org by e-mail at the following addresses:
00016  *    info@iptel.org
00017  *
00018  * ser is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License 
00024  * along with this program; if not, write to the Free Software 
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  */
00027 /*
00028  * History:
00029  * --------
00030  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
00031  *  2006-02-02  named flags support (andrei)
00032  */
00033 
00034 
00035 #include <limits.h>
00036 #include "sr_module.h"
00037 #include "dprint.h"
00038 #include "parser/msg_parser.h"
00039 #include "flags.h"
00040 #include "error.h"
00041 #include "stdlib.h"
00042 #include "hashes.h"
00043 #include "clist.h"
00044 #include "mem/mem.h"
00045 
00046 int setflag( struct sip_msg* msg, flag_t flag ) {
00047         msg->flags |= 1 << flag;
00048         return 1;
00049 }
00050 
00051 int resetflag( struct sip_msg* msg, flag_t flag ) {
00052         msg->flags &= ~ (1 << flag);
00053         return 1;
00054 }
00055 
00056 int isflagset( struct sip_msg* msg, flag_t flag ) {
00057         return (msg->flags & (1<<flag)) ? 1 : -1;
00058 }
00059 
00060 int flag_in_range( flag_t flag ) {
00061         if (flag > MAX_FLAG ) {
00062                 LOG(L_ERR, "ERROR: message flag %d too high; MAX=%d\n",
00063                         flag, MAX_FLAG );
00064                 return 0;
00065         }
00066         if (flag<0) {
00067                 LOG(L_ERR, "ERROR: message flag (%d) must be in range %d..%d\n",
00068                         flag, 0, MAX_FLAG );
00069                 return 0;
00070         }
00071         return 1;
00072 }
00073 
00074 
00075 /* use 2^k */
00076 #define FLAGS_NAME_HASH_ENTRIES         32
00077 
00078 struct flag_entry{
00079         struct flag_entry* next;
00080         struct flag_entry* prev;
00081         str name;
00082         int no;
00083 };
00084 
00085 
00086 struct flag_hash_head{
00087         struct flag_entry* next;
00088         struct flag_entry* prev;
00089 };
00090 
00091 static struct flag_hash_head  name2flags[FLAGS_NAME_HASH_ENTRIES];
00092 static unsigned char registered_flags[MAX_FLAG+1];
00093 
00094 
00095 void init_named_flags()
00096 {
00097         int r;
00098         
00099         for (r=0; r<FLAGS_NAME_HASH_ENTRIES; r++)
00100                 clist_init(&name2flags[r], next, prev);
00101 }
00102 
00103 
00104 
00105 /* returns 0 on success, -1 on error */
00106 int check_flag(int n)
00107 {
00108         if (!flag_in_range(n))
00109                 return -1;
00110         if (registered_flags[n]){
00111                 LOG(L_WARN, "WARNING: check_flag: flag %d is already used by "
00112                                         " a named flag\n", n);
00113         }
00114         return 0;
00115 }
00116 
00117 
00118 inline static struct flag_entry* flag_search(struct flag_hash_head* lst,
00119                                                                                                 char* name, int len)
00120 {
00121         struct flag_entry* fe;
00122         
00123         clist_foreach(lst, fe, next){
00124                 if ((fe->name.len==len) && (memcmp(fe->name.s, name, len)==0)){
00125                         /* found */
00126                         return fe;
00127                 }
00128         }
00129         return 0;
00130 }
00131 
00132 
00133 
00134 /* returns flag entry or 0 on not found */
00135 inline static struct flag_entry* get_flag_entry(char* name, int len)
00136 {
00137         int h;
00138         /* get hash */
00139         h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
00140         return flag_search(&name2flags[h], name, len);
00141 }
00142 
00143 
00144 
00145 /* returns flag number, or -1 on error */
00146 int get_flag_no(char* name, int len)
00147 {
00148         struct flag_entry* fe;
00149         
00150         fe=get_flag_entry(name, len);
00151         return (fe)?fe->no:-1;
00152 }
00153 
00154 
00155 
00156 /* resgiter a new flag name and associates it with pos
00157  * pos== -1 => any position will do 
00158  * returns flag pos on success (>=0)
00159  *         -1  flag is an alias for an already existing flag
00160  *         -2  flag already registered
00161  *         -3  mem. alloc. failure
00162  *         -4  invalid pos
00163  *         -5 no free flags */
00164 int register_flag(char* name, int pos)
00165 {
00166         struct flag_entry* e;
00167         int len;
00168         unsigned int r;
00169         static unsigned int crt_flag=0;
00170         unsigned int last_flag;
00171         unsigned int h;
00172         
00173         len=strlen(name);
00174         h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
00175         /* check if the name already exists */
00176         e=flag_search(&name2flags[h], name, len);
00177         if (e){
00178                 LOG(L_ERR, "ERROR: register_flag: flag %.*s already registered\n",
00179                                         len, name);
00180                 return -2;
00181         }
00182         /* check if there is already another flag registered at pos */
00183         if (pos!=-1){
00184                 if ((pos<0) || (pos>MAX_FLAG)){
00185                         LOG(L_ERR, "ERROR: register_flag: invalid flag %.*s "
00186                                         "position(%d)\n", len, name, pos);
00187                         return -4;
00188                 }
00189                 if (registered_flags[pos]!=0){
00190                         LOG(L_WARN, "WARNING: register_flag:  %.*s:  flag %d already in "
00191                                         "use under another name\n", len, name, pos);
00192                         /* continue */
00193                 }
00194         }else{
00195                 /* alloc an empty flag */
00196                 last_flag=crt_flag+(MAX_FLAG+1);
00197                 for (; crt_flag!=last_flag; crt_flag++){
00198                         r=crt_flag%(MAX_FLAG+1);
00199                         if (registered_flags[r]==0){
00200                                 pos=r;
00201                                 break;
00202                         }
00203                 }
00204                 if (pos==-1){
00205                         LOG(L_ERR, "ERROR: register_flag: could not register %.*s"
00206                                         " - too many flags\n", len, name);
00207                         return -5;
00208                 }
00209         }
00210         registered_flags[pos]++;
00211         
00212         e=pkg_malloc(sizeof(struct flag_entry));
00213         if (e==0){
00214                 LOG(L_ERR, "ERROR: register_flag: memory allocation failure\n");
00215                 return -3;
00216         }
00217         e->name.s=name;
00218         e->name.len=len;
00219         e->no=pos;
00220         clist_insert(&name2flags[h], e, next, prev);
00221         return pos;
00222 }
00223 
00224 
00225 
00226 #ifdef _GET_AWAY
00227 
00228 /* wrapping functions for flag processing  */
00229 static int fixup_t_flag(void** param, int param_no)
00230 {
00231     unsigned int *code;
00232         char *c;
00233         int token;
00234 
00235         DBG("DEBUG: fixing flag: %s\n", (char *) (*param));
00236 
00237         if (param_no!=1) {
00238                 LOG(L_ERR, "ERROR: TM module: only parameter #1 for flags can be"
00239                                         " fixed\n");
00240                 return E_BUG;
00241         };
00242 
00243         if ( !(code =pkg_malloc( sizeof( unsigned int) )) ) return E_OUT_OF_MEM;
00244 
00245         *code = 0;
00246         c = *param;
00247         while ( *c && (*c==' ' || *c=='\t')) c++; /* initial whitespaces */
00248 
00249         token=1;
00250         if (strcasecmp(c, "white")==0) *code=FL_WHITE;
00251         else if (strcasecmp(c, "yellow")==0) *code=FL_YELLOW;
00252         else if (strcasecmp(c, "green")==0) *code=FL_GREEN;
00253         else if (strcasecmp(c, "red")==0) *code=FL_RED;
00254         else if (strcasecmp(c, "blue")==0) *code=FL_BLUE;
00255         else if (strcasecmp(c, "magenta")==0) *code=FL_MAGENTA;
00256         else if (strcasecmp(c, "brown")==0) *code=FL_BROWN;
00257         else if (strcasecmp(c, "black")==0) *code=FL_BLACK;
00258         else if (strcasecmp(c, "acc")==0) *code=FL_ACC;
00259         else {
00260                 token=0;
00261                 while ( *c && *c>='0' && *c<='9' ) {
00262                         *code = *code*10+ *c-'0';
00263                         if (*code > (sizeof( flag_t ) * CHAR_BIT - 1 )) {
00264                                 LOG(L_ERR, "ERROR: TM module: too big flag number: %s; MAX=%d\n",
00265                                         (char *) (*param), sizeof( flag_t ) * CHAR_BIT - 1 );
00266                                 goto error;
00267                         }
00268                         c++;
00269                 }
00270         }
00271         while ( *c && (*c==' ' || *c=='\t')) c++; /* terminating whitespaces */
00272 
00273         if ( *code == 0 ) {
00274                 LOG(L_ERR, "ERROR: TM module: bad flag number: %s\n", (char *) (*param));
00275                 goto error;
00276         }
00277 
00278         if (*code < FL_MAX && token==0) {
00279                 LOG(L_ERR, "ERROR: TM module: too high flag number: %s (%d)\n; lower number"
00280                         " bellow %d reserved\n", (char *) (*param), *code, FL_MAX );
00281                 goto error;
00282         }
00283 
00284         /* free string */
00285         pkg_free( *param );
00286         /* fix now */
00287         *param = code;
00288         
00289         return 0;
00290 
00291 error:
00292         pkg_free( code );
00293         return E_CFG;
00294 }
00295 
00296 
00297 #endif

Generated on Thu Sep 9 04:15:42 2010 for SIPExpressRouter by  doxygen 1.3.9.1