flags.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Copyright (C) 2001-2003 FhG Fokus
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * Kamailio is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. * Kamailio is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /*!
  21. * \file
  22. * \brief Kamailio core :: Flags
  23. * \ingroup core
  24. * Module: \ref core
  25. */
  26. #include <limits.h>
  27. #include "sr_module.h"
  28. #include "dprint.h"
  29. #include "parser/msg_parser.h"
  30. #include "flags.h"
  31. #include "error.h"
  32. #include "stdlib.h"
  33. #include "hashes.h"
  34. #include "clist.h"
  35. #include "mem/mem.h"
  36. /* Script flags */
  37. static flag_t sflags = 0;
  38. int setflag( struct sip_msg* msg, flag_t flag ) {
  39. msg->flags |= 1 << flag;
  40. return 1;
  41. }
  42. int resetflag( struct sip_msg* msg, flag_t flag ) {
  43. msg->flags &= ~ (1 << flag);
  44. return 1;
  45. }
  46. int isflagset( struct sip_msg* msg, flag_t flag ) {
  47. return (msg->flags & (1<<flag)) ? 1 : -1;
  48. }
  49. int flag_in_range( flag_t flag ) {
  50. if (flag > MAX_FLAG ) {
  51. LM_ERR("message flag %d too high; MAX=%d\n", flag, MAX_FLAG );
  52. return 0;
  53. }
  54. if ((int)flag<0) {
  55. LM_ERR("message flag (%d) must be in range 0..%d\n", flag, MAX_FLAG );
  56. return 0;
  57. }
  58. return 1;
  59. }
  60. int setsflagsval(flag_t val)
  61. {
  62. sflags = val;
  63. return 1;
  64. }
  65. int setsflag(flag_t flag)
  66. {
  67. sflags |= 1 << flag;
  68. return 1;
  69. }
  70. int resetsflag(flag_t flag)
  71. {
  72. sflags &= ~ (1 << flag);
  73. return 1;
  74. }
  75. int issflagset(flag_t flag)
  76. {
  77. return (sflags & (1<<flag)) ? 1 : -1;
  78. }
  79. flag_t getsflags(void)
  80. {
  81. return sflags;
  82. }
  83. /* use 2^k */
  84. #define FLAGS_NAME_HASH_ENTRIES 32
  85. struct flag_entry{
  86. struct flag_entry* next;
  87. struct flag_entry* prev;
  88. str name;
  89. int no;
  90. };
  91. struct flag_hash_head{
  92. struct flag_entry* next;
  93. struct flag_entry* prev;
  94. };
  95. static struct flag_hash_head name2flags[FLAGS_NAME_HASH_ENTRIES];
  96. static unsigned char registered_flags[MAX_FLAG+1];
  97. void init_named_flags()
  98. {
  99. int r;
  100. for (r=0; r<FLAGS_NAME_HASH_ENTRIES; r++)
  101. clist_init(&name2flags[r], next, prev);
  102. }
  103. /* returns 0 on success, -1 on error */
  104. int check_flag(int n)
  105. {
  106. if (!flag_in_range(n))
  107. return -1;
  108. if (registered_flags[n]){
  109. LM_WARN("flag %d is already used by a named flag\n", n);
  110. }
  111. return 0;
  112. }
  113. inline static struct flag_entry* flag_search(struct flag_hash_head* lst,
  114. char* name, int len)
  115. {
  116. struct flag_entry* fe;
  117. clist_foreach(lst, fe, next){
  118. if ((fe->name.len==len) && (memcmp(fe->name.s, name, len)==0)){
  119. /* found */
  120. return fe;
  121. }
  122. }
  123. return 0;
  124. }
  125. /* returns flag entry or 0 on not found */
  126. inline static struct flag_entry* get_flag_entry(char* name, int len)
  127. {
  128. int h;
  129. /* get hash */
  130. h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
  131. return flag_search(&name2flags[h], name, len);
  132. }
  133. /* returns flag number, or -1 on error */
  134. int get_flag_no(char* name, int len)
  135. {
  136. struct flag_entry* fe;
  137. fe=get_flag_entry(name, len);
  138. return (fe)?fe->no:-1;
  139. }
  140. /* resgiter a new flag name and associates it with pos
  141. * pos== -1 => any position will do
  142. * returns flag pos on success (>=0)
  143. * -1 flag is an alias for an already existing flag
  144. * -2 flag already registered
  145. * -3 mem. alloc. failure
  146. * -4 invalid pos
  147. * -5 no free flags */
  148. int register_flag(char* name, int pos)
  149. {
  150. struct flag_entry* e;
  151. int len;
  152. unsigned int r;
  153. static unsigned int crt_flag=0;
  154. unsigned int last_flag;
  155. unsigned int h;
  156. len=strlen(name);
  157. h=get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES-1);
  158. /* check if the name already exists */
  159. e=flag_search(&name2flags[h], name, len);
  160. if (e){
  161. LM_ERR("flag %.*s already registered\n", len, name);
  162. return -2;
  163. }
  164. /* check if there is already another flag registered at pos */
  165. if (pos!=-1){
  166. if ((pos<0) || (pos>MAX_FLAG)){
  167. LM_ERR("invalid flag %.*s position(%d)\n", len, name, pos);
  168. return -4;
  169. }
  170. if (registered_flags[pos]!=0){
  171. LM_WARN("%.*s: flag %d already in use under another name\n",
  172. len, name, pos);
  173. /* continue */
  174. }
  175. }else{
  176. /* alloc an empty flag */
  177. last_flag=crt_flag+(MAX_FLAG+1);
  178. for (; crt_flag!=last_flag; crt_flag++){
  179. r=crt_flag%(MAX_FLAG+1);
  180. if (registered_flags[r]==0){
  181. pos=r;
  182. break;
  183. }
  184. }
  185. if (pos==-1){
  186. LM_ERR("could not register %.*s - too many flags\n", len, name);
  187. return -5;
  188. }
  189. }
  190. registered_flags[pos]++;
  191. e=pkg_malloc(sizeof(struct flag_entry));
  192. if (e==0){
  193. LM_ERR("memory allocation failure\n");
  194. return -3;
  195. }
  196. e->name.s=name;
  197. e->name.len=len;
  198. e->no=pos;
  199. clist_insert(&name2flags[h], e, next, prev);
  200. return pos;
  201. }
  202. #ifdef _GET_AWAY
  203. /* wrapping functions for flag processing */
  204. static int fixup_t_flag(void** param, int param_no)
  205. {
  206. unsigned int *code;
  207. char *c;
  208. int token;
  209. LM_DBG("fixing flag: %s\n", (char *) (*param));
  210. if (param_no!=1) {
  211. LM_ERR("TM module: only parameter #1 for flags can be fixed\n");
  212. return E_BUG;
  213. };
  214. if ( !(code =pkg_malloc( sizeof( unsigned int) )) ) return E_OUT_OF_MEM;
  215. *code = 0;
  216. c = *param;
  217. while ( *c && (*c==' ' || *c=='\t')) c++; /* initial whitespaces */
  218. token=1;
  219. if (strcasecmp(c, "white")==0) *code=FL_WHITE;
  220. else if (strcasecmp(c, "yellow")==0) *code=FL_YELLOW;
  221. else if (strcasecmp(c, "green")==0) *code=FL_GREEN;
  222. else if (strcasecmp(c, "red")==0) *code=FL_RED;
  223. else if (strcasecmp(c, "blue")==0) *code=FL_BLUE;
  224. else if (strcasecmp(c, "magenta")==0) *code=FL_MAGENTA;
  225. else if (strcasecmp(c, "brown")==0) *code=FL_BROWN;
  226. else if (strcasecmp(c, "black")==0) *code=FL_BLACK;
  227. else if (strcasecmp(c, "acc")==0) *code=FL_ACC;
  228. else {
  229. token=0;
  230. while ( *c && *c>='0' && *c<='9' ) {
  231. *code = *code*10+ *c-'0';
  232. if (*code > (sizeof( flag_t ) * CHAR_BIT - 1 )) {
  233. LM_ERR("TM module: too big flag number: %s; MAX=%d\n",
  234. (char *) (*param), sizeof( flag_t ) * CHAR_BIT - 1 );
  235. goto error;
  236. }
  237. c++;
  238. }
  239. }
  240. while ( *c && (*c==' ' || *c=='\t')) c++; /* terminating whitespaces */
  241. if ( *code == 0 ) {
  242. LM_ERR("TM module: bad flag number: %s\n", (char *) (*param));
  243. goto error;
  244. }
  245. if (*code < FL_MAX && token==0) {
  246. LM_ERR("TM module: too high flag number: %s (%d)\n; lower number"
  247. " bellow %d reserved\n", (char *) (*param), *code, FL_MAX );
  248. goto error;
  249. }
  250. /* free string */
  251. pkg_free( *param );
  252. /* fix now */
  253. *param = code;
  254. return 0;
  255. error:
  256. pkg_free( code );
  257. return E_CFG;
  258. }
  259. #endif