Coverage Report

Created: 2023-11-19 07:01

/src/kamailio/src/core/flags.c
Line
Count
Source (jump to first uncovered line)
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
/*!
22
 * \file
23
 * \brief Kamailio core :: Flags
24
 * \ingroup core
25
 * Module: \ref core
26
 */
27
28
29
#include <limits.h>
30
#include <stdint.h>
31
#include "sr_module.h"
32
#include "dprint.h"
33
#include "parser/msg_parser.h"
34
#include "flags.h"
35
#include "error.h"
36
#include "stdlib.h"
37
#include "hashes.h"
38
#include "clist.h"
39
#include "mem/mem.h"
40
41
/* Script flags */
42
static flag_t sflags = 0;
43
44
45
int setflag(struct sip_msg *msg, flag_t flag)
46
0
{
47
0
  msg->flags |= 1u << flag;
48
0
  return 1;
49
0
}
50
51
int resetflag(struct sip_msg *msg, flag_t flag)
52
0
{
53
0
  msg->flags &= ~(1u << flag);
54
0
  return 1;
55
0
}
56
57
int resetflags(struct sip_msg *msg, flag_t flags)
58
0
{
59
0
  msg->flags &= ~flags;
60
0
  return 1;
61
0
}
62
63
int isflagset(struct sip_msg *msg, flag_t flag)
64
0
{
65
0
  return (msg->flags & (1u << flag)) ? 1 : -1;
66
0
}
67
68
int flag_in_range(flag_t flag)
69
0
{
70
0
  if(flag > MAX_FLAG) {
71
0
    LM_ERR("message flag %d too high; MAX=%d\n", flag, MAX_FLAG);
72
0
    return 0;
73
0
  }
74
0
  return 1;
75
0
}
76
77
78
int setsflagsval(flag_t val)
79
0
{
80
0
  sflags = val;
81
0
  return 1;
82
0
}
83
84
85
int setsflag(flag_t flag)
86
0
{
87
0
  sflags |= 1u << flag;
88
0
  return 1;
89
0
}
90
91
92
int resetsflag(flag_t flag)
93
0
{
94
0
  sflags &= ~(1u << flag);
95
0
  return 1;
96
0
}
97
98
99
int issflagset(flag_t flag)
100
0
{
101
0
  return (sflags & (1u << flag)) ? 1 : -1;
102
0
}
103
104
105
flag_t getsflags(void)
106
0
{
107
0
  return sflags;
108
0
}
109
110
111
/* use 2^k */
112
0
#define FLAGS_NAME_HASH_ENTRIES 32
113
114
struct flag_entry
115
{
116
  struct flag_entry *next;
117
  struct flag_entry *prev;
118
  str name;
119
  int no;
120
};
121
122
123
struct flag_hash_head
124
{
125
  struct flag_entry *next;
126
  struct flag_entry *prev;
127
};
128
129
static struct flag_hash_head name2flags[FLAGS_NAME_HASH_ENTRIES];
130
static unsigned char registered_flags[MAX_FLAG + 1];
131
132
133
void init_named_flags()
134
0
{
135
0
  int r;
136
137
0
  for(r = 0; r < FLAGS_NAME_HASH_ENTRIES; r++)
138
0
    clist_init(&name2flags[r], next, prev);
139
0
}
140
141
142
/* returns 0 on success, -1 on error */
143
int check_flag(int n)
144
0
{
145
0
  if(!flag_in_range(n))
146
0
    return -1;
147
0
  if(registered_flags[n]) {
148
0
    LM_WARN("flag %d is already used by a named flag\n", n);
149
0
  }
150
0
  return 0;
151
0
}
152
153
154
inline static struct flag_entry *flag_search(
155
    struct flag_hash_head *lst, char *name, int len)
156
0
{
157
0
  struct flag_entry *fe;
158
159
0
  clist_foreach(lst, fe, next)
160
0
  {
161
0
    if((fe->name.len == len) && (memcmp(fe->name.s, name, len) == 0)) {
162
      /* found */
163
0
      return fe;
164
0
    }
165
0
  }
166
0
  return 0;
167
0
}
168
169
170
/* returns flag entry or 0 on not found */
171
inline static struct flag_entry *get_flag_entry(char *name, int len)
172
0
{
173
0
  int h;
174
  /* get hash */
175
0
  h = get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES - 1);
176
0
  return flag_search(&name2flags[h], name, len);
177
0
}
178
179
180
/* returns flag number, or -1 on error */
181
int get_flag_no(char *name, int len)
182
0
{
183
0
  struct flag_entry *fe;
184
185
0
  fe = get_flag_entry(name, len);
186
0
  return (fe) ? fe->no : -1;
187
0
}
188
189
190
/* resgiter a new flag name and associates it with pos
191
 * pos== -1 => any position will do
192
 * returns flag pos on success (>=0)
193
 *         -1  flag is an alias for an already existing flag
194
 *         -2  flag already registered
195
 *         -3  mem. alloc. failure
196
 *         -4  invalid pos
197
 *         -5 no free flags */
198
int register_flag(char *name, int pos)
199
0
{
200
0
  struct flag_entry *e;
201
0
  int len;
202
0
  unsigned int r;
203
0
  static unsigned int crt_flag = 0;
204
0
  unsigned int last_flag;
205
0
  unsigned int h;
206
207
0
  len = strlen(name);
208
0
  h = get_hash1_raw(name, len) & (FLAGS_NAME_HASH_ENTRIES - 1);
209
  /* check if the name already exists */
210
0
  e = flag_search(&name2flags[h], name, len);
211
0
  if(e) {
212
0
    LM_ERR("flag %.*s already registered\n", len, name);
213
0
    return -2;
214
0
  }
215
  /* check if there is already another flag registered at pos */
216
0
  if(pos != -1) {
217
0
    if((pos < 0) || (pos > MAX_FLAG)) {
218
0
      LM_ERR("invalid flag %.*s position(%d)\n", len, name, pos);
219
0
      return -4;
220
0
    }
221
0
    if(registered_flags[pos] != 0) {
222
0
      LM_WARN("%.*s:  flag %d already in use under another name\n", len,
223
0
          name, pos);
224
      /* continue */
225
0
    }
226
0
  } else {
227
    /* alloc an empty flag */
228
0
    last_flag = crt_flag + (MAX_FLAG + 1);
229
0
    for(; crt_flag != last_flag; crt_flag++) {
230
0
      r = crt_flag % (MAX_FLAG + 1);
231
0
      if(registered_flags[r] == 0) {
232
0
        pos = r;
233
0
        break;
234
0
      }
235
0
    }
236
0
    if(pos == -1) {
237
0
      LM_ERR("could not register %.*s - too many flags\n", len, name);
238
0
      return -5;
239
0
    }
240
0
  }
241
0
  registered_flags[pos]++;
242
243
0
  e = pkg_malloc(sizeof(struct flag_entry));
244
0
  if(e == 0) {
245
0
    PKG_MEM_ERROR;
246
0
    return -3;
247
0
  }
248
0
  e->name.s = name;
249
0
  e->name.len = len;
250
0
  e->no = pos;
251
0
  clist_insert(&name2flags[h], e, next, prev);
252
0
  return pos;
253
0
}
254
255
256
/**
257
 *
258
 */
259
int setxflag(struct sip_msg *msg, flag_t flag)
260
0
{
261
0
  uint32_t fi;
262
0
  uint32_t fb;
263
0
  fi = flag / (sizeof(flag_t) * CHAR_BIT);
264
0
  fb = flag % (sizeof(flag_t) * CHAR_BIT);
265
0
  msg->xflags[fi] |= 1u << fb;
266
0
  return 1;
267
0
}
268
269
/**
270
 *
271
 */
272
int resetxflag(struct sip_msg *msg, flag_t flag)
273
0
{
274
0
  uint32_t fi;
275
0
  uint32_t fb;
276
0
  fi = flag / (sizeof(flag_t) * CHAR_BIT);
277
0
  fb = flag % (sizeof(flag_t) * CHAR_BIT);
278
0
  msg->xflags[fi] &= ~(1u << fb);
279
0
  return 1;
280
0
}
281
282
/**
283
 *
284
 */
285
int isxflagset(struct sip_msg *msg, flag_t flag)
286
0
{
287
0
  uint32_t fi;
288
0
  uint32_t fb;
289
0
  fi = flag / (sizeof(flag_t) * CHAR_BIT);
290
0
  fb = flag % (sizeof(flag_t) * CHAR_BIT);
291
0
  return (msg->xflags[fi] & (1u << fb)) ? 1 : -1;
292
0
}