flags.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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. * [email protected]
  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. #include <limits.h>
  34. #include "sr_module.h"
  35. #include "dprint.h"
  36. #include "parser/msg_parser.h"
  37. #include "flags.h"
  38. #include "error.h"
  39. #include "stdlib.h"
  40. #include "hashes.h"
  41. #include "clist.h"
  42. #include "mem/mem.h"
  43. int setflag( struct sip_msg* msg, flag_t flag ) {
  44. msg->flags |= 1 << flag;
  45. return 1;
  46. }
  47. int resetflag( struct sip_msg* msg, flag_t flag ) {
  48. msg->flags &= ~ (1 << flag);
  49. return 1;
  50. }
  51. int isflagset( struct sip_msg* msg, flag_t flag ) {
  52. return (msg->flags & (1<<flag)) ? 1 : -1;
  53. }
  54. int flag_in_range( flag_t flag ) {
  55. if (flag > MAX_FLAG ) {
  56. LOG(L_ERR, "ERROR: message flag %d too high; MAX=%d\n",
  57. flag, MAX_FLAG );
  58. return 0;
  59. }
  60. if (flag<0) {
  61. LOG(L_ERR, "ERROR: message flag (%d) must be in range %d..%d\n",
  62. flag, 0, MAX_FLAG );
  63. return 0;
  64. }
  65. return 1;
  66. }
  67. /* use 2^k */
  68. #define FLAGS_NAME_HASH_ENTRIES 32
  69. struct flag_entry{
  70. struct flag_entry* next;
  71. struct flag_entry* prev;
  72. str name;
  73. int no;
  74. };
  75. struct flag_hash_head{
  76. struct flag_entry* next;
  77. struct flag_entry* prev;
  78. };
  79. static struct flag_hash_head name2flags[FLAGS_NAME_HASH_ENTRIES];
  80. static unsigned char registered_flags[MAX_FLAG+1];
  81. void init_named_flags()
  82. {
  83. int r;
  84. for (r=0; r<FLAGS_NAME_HASH_ENTRIES; r++)
  85. clist_init(&name2flags[r], next, prev);
  86. }
  87. /* returns 0 on success, -1 on error */
  88. int check_flag(int n)
  89. {
  90. if (!flag_in_range(n))
  91. return -1;
  92. if (registered_flags[n]){
  93. LOG(L_WARN, "WARNING: check_flag: flag %d is already used by "
  94. " a named flag\n", n);
  95. }
  96. return 0;
  97. }
  98. inline static struct flag_entry* flag_search(struct flag_hash_head* lst,
  99. char* name, int len)
  100. {
  101. struct flag_entry* fe;
  102. clist_foreach(lst, fe, next){
  103. if ((fe->name.len==len) && (memcmp(fe->name.s, name, len)==0)){
  104. /* found */
  105. return fe;
  106. }
  107. }
  108. return 0;
  109. }
  110. /* returns flag entry or 0 on not found */
  111. inline static struct flag_entry* get_flag_entry(char* name, int len)
  112. {
  113. int h;
  114. /* get hash */
  115. h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
  116. return flag_search(&name2flags[h], name, len);
  117. }
  118. /* returns flag number, or -1 on error */
  119. int get_flag_no(char* name, int len)
  120. {
  121. struct flag_entry* fe;
  122. fe=get_flag_entry(name, len);
  123. return (fe)?fe->no:-1;
  124. }
  125. /* resgiter a new flag name and associates it with pos
  126. * pos== -1 => any position will do
  127. * returns flag pos on success (>=0)
  128. * -1 flag is an alias for an already existing flag
  129. * -2 flag already registered
  130. * -3 mem. alloc. failure
  131. * -4 invalid pos
  132. * -5 no free flags */
  133. int register_flag(char* name, int pos)
  134. {
  135. struct flag_entry* e;
  136. int len;
  137. unsigned int r;
  138. static unsigned int crt_flag=0;
  139. unsigned int last_flag;
  140. unsigned int h;
  141. len=strlen(name);
  142. h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
  143. /* check if the name already exists */
  144. e=flag_search(&name2flags[h], name, len);
  145. if (e){
  146. LOG(L_ERR, "ERROR: register_flag: flag %.*s already registered\n",
  147. len, name);
  148. return -2;
  149. }
  150. /* check if there is already another flag registered at pos */
  151. if (pos!=-1){
  152. if ((pos<0) || (pos>MAX_FLAG)){
  153. LOG(L_ERR, "ERROR: register_flag: invalid flag %.*s "
  154. "position(%d)\n", len, name, pos);
  155. return -4;
  156. }
  157. if (registered_flags[pos]!=0){
  158. LOG(L_WARN, "WARNING: register_flag: %.*s: flag %d already in "
  159. "use under another name\n", len, name, pos);
  160. /* continue */
  161. }
  162. }else{
  163. /* alloc an empty flag */
  164. last_flag=crt_flag+(MAX_FLAG+1);
  165. for (; crt_flag!=last_flag; crt_flag++){
  166. r=crt_flag%(MAX_FLAG+1);
  167. if (registered_flags[r]==0){
  168. pos=r;
  169. break;
  170. }
  171. }
  172. if (pos==-1){
  173. LOG(L_ERR, "ERROR: register_flag: could not register %.*s"
  174. " - too many flags\n", len, name);
  175. return -5;
  176. }
  177. }
  178. registered_flags[pos]++;
  179. e=pkg_malloc(sizeof(struct flag_entry));
  180. if (e==0){
  181. LOG(L_ERR, "ERROR: register_flag: memory allocation failure\n");
  182. return -3;
  183. }
  184. e->name.s=name;
  185. e->name.len=len;
  186. e->no=pos;
  187. clist_insert(&name2flags[h], e, next, prev);
  188. return pos;
  189. }
  190. #ifdef _GET_AWAY
  191. /* wrapping functions for flag processing */
  192. static int fixup_t_flag(void** param, int param_no)
  193. {
  194. unsigned int *code;
  195. char *c;
  196. int token;
  197. DBG("DEBUG: fixing flag: %s\n", (char *) (*param));
  198. if (param_no!=1) {
  199. LOG(L_ERR, "ERROR: TM module: only parameter #1 for flags can be"
  200. " fixed\n");
  201. return E_BUG;
  202. };
  203. if ( !(code =pkg_malloc( sizeof( unsigned int) )) ) return E_OUT_OF_MEM;
  204. *code = 0;
  205. c = *param;
  206. while ( *c && (*c==' ' || *c=='\t')) c++; /* initial whitespaces */
  207. token=1;
  208. if (strcasecmp(c, "white")==0) *code=FL_WHITE;
  209. else if (strcasecmp(c, "yellow")==0) *code=FL_YELLOW;
  210. else if (strcasecmp(c, "green")==0) *code=FL_GREEN;
  211. else if (strcasecmp(c, "red")==0) *code=FL_RED;
  212. else if (strcasecmp(c, "blue")==0) *code=FL_BLUE;
  213. else if (strcasecmp(c, "magenta")==0) *code=FL_MAGENTA;
  214. else if (strcasecmp(c, "brown")==0) *code=FL_BROWN;
  215. else if (strcasecmp(c, "black")==0) *code=FL_BLACK;
  216. else if (strcasecmp(c, "acc")==0) *code=FL_ACC;
  217. else {
  218. token=0;
  219. while ( *c && *c>='0' && *c<='9' ) {
  220. *code = *code*10+ *c-'0';
  221. if (*code > (sizeof( flag_t ) * CHAR_BIT - 1 )) {
  222. LOG(L_ERR, "ERROR: TM module: too big flag number: %s; MAX=%d\n",
  223. (char *) (*param), sizeof( flag_t ) * CHAR_BIT - 1 );
  224. goto error;
  225. }
  226. c++;
  227. }
  228. }
  229. while ( *c && (*c==' ' || *c=='\t')) c++; /* terminating whitespaces */
  230. if ( *code == 0 ) {
  231. LOG(L_ERR, "ERROR: TM module: bad flag number: %s\n", (char *) (*param));
  232. goto error;
  233. }
  234. if (*code < FL_MAX && token==0) {
  235. LOG(L_ERR, "ERROR: TM module: too high flag number: %s (%d)\n; lower number"
  236. " bellow %d reserved\n", (char *) (*param), *code, FL_MAX );
  237. goto error;
  238. }
  239. /* free string */
  240. pkg_free( *param );
  241. /* fix now */
  242. *param = code;
  243. return 0;
  244. error:
  245. pkg_free( code );
  246. return E_CFG;
  247. }
  248. #endif