flags.c 7.0 KB

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