flags.c 7.3 KB

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