Coverage Report

Created: 2025-07-18 06:32

/src/opensips/context.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2014 OpenSIPS Solutions
3
 *
4
 * This file is part of opensips, a free SIP server.
5
 *
6
 * opensips 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
 * opensips 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
 * History:
21
 * --------
22
 *  2014-12-10 initial version (liviu)
23
 */
24
25
#include "str.h"
26
#include "mem/mem.h"
27
#include "context.h"
28
#include <string.h>
29
30
/* Pointer to the current processing context */
31
context_p current_processing_ctx = NULL;
32
33
unsigned int context_sizes[CONTEXT_COUNT];
34
35
unsigned int type_sizes[CONTEXT_COUNT][CONTEXT_COUNT_TYPE];
36
unsigned int type_offsets[CONTEXT_COUNT][CONTEXT_COUNT_TYPE];
37
38
/* vector of destroy functions */
39
static context_destroy_f *context_destroy_array[CONTEXT_COUNT];
40
41
static void register_context_destroy(context_destroy_f f,
42
    enum osips_context ctx, enum osips_context_val t)
43
2
{
44
2
  static int count = 0; /* contains all counters */
45
2
  context_destroy_f *tmp;
46
2
  int pos = 0;
47
2
  int i;
48
49
  /*
50
   * group all functions based on their types:
51
   * first the int functions, then the str and pointers the last
52
   */
53
2
  switch (t) {
54
2
  case CONTEXT_PTR_TYPE:
55
2
    pos += type_sizes[ctx][CONTEXT_PTR_TYPE];
56
2
  case CONTEXT_STR_TYPE:
57
2
    pos += type_sizes[ctx][CONTEXT_STR_TYPE];
58
2
  case CONTEXT_INT_TYPE:
59
2
    pos += type_sizes[ctx][CONTEXT_INT_TYPE];
60
2
    break;
61
0
  default:
62
0
    LM_ERR("should not get here with ctx %d\n", t);
63
0
    return;
64
2
  }
65
  /* TODO: check whether this should be in pkg or shm? */
66
2
  tmp = pkg_realloc(context_destroy_array[ctx], (count + 1) * sizeof(context_destroy_f));
67
2
  if (!tmp) {
68
0
    LM_ERR("cannot add any more destroy functions\n");
69
0
    return;
70
0
  }
71
2
  context_destroy_array[ctx] = tmp;
72
73
  /* move everything to the right to make room for pos */
74
2
  for (i = count; i > pos; i--)
75
0
    context_destroy_array[ctx][i] = context_destroy_array[ctx][i - 1];
76
2
  context_destroy_array[ctx][pos] = f;
77
2
  count++;
78
2
}
79
80
/* Note: @ctx will *not* be freed! */
81
void context_destroy(enum osips_context ctxtype, context_p ctx)
82
0
{
83
0
  int f = 0;
84
0
  int n;
85
0
  int i;
86
0
  str *s;
87
0
  void *p;
88
89
90
  /* int ctx */
91
0
  for (n = 0; n < type_sizes[ctxtype][CONTEXT_INT_TYPE]; n++, f++)
92
0
    if (context_destroy_array[ctxtype][f]) {
93
0
      i = context_get_int(ctxtype, ctx, n);
94
0
      if (i)/* XXX: should we call for 0 values? */
95
0
        context_destroy_array[ctxtype][f](&i);
96
0
    }
97
98
  /* str ctx */
99
0
  for (n = 0; n < type_sizes[ctxtype][CONTEXT_STR_TYPE]; n++, f++)
100
0
    if (context_destroy_array[ctxtype][f]) {
101
0
      s = context_get_str(ctxtype, ctx, n);
102
0
      if (s)/* XXX: how do we determine if s is empty? */
103
0
        context_destroy_array[ctxtype][f](s);
104
0
    }
105
106
  /* ptr ctx */
107
0
  for (n = 0; n < type_sizes[ctxtype][CONTEXT_PTR_TYPE]; n++, f++) {
108
0
    if (context_destroy_array[ctxtype][f]) {
109
0
      p = context_get_ptr(ctxtype, ctx, n);
110
0
      if (p)
111
0
        context_destroy_array[ctxtype][f](p);
112
0
    }
113
0
  }
114
0
}
115
116
context_p context_alloc(enum osips_context type)
117
2
{
118
2
  context_p ctx;
119
120
2
  ctx = pkg_malloc(context_size(type));
121
2
  if (!ctx) {
122
0
    LM_ERR("no more pkg mem\n");
123
0
    return NULL;
124
0
  }
125
126
2
  return ctx;
127
2
}
128
129
130
int ensure_global_context(void)
131
2
{
132
2
  if (current_processing_ctx)
133
0
    return 0;
134
135
2
  current_processing_ctx = context_alloc(CONTEXT_GLOBAL);
136
2
  if (!current_processing_ctx) {
137
0
    LM_ERR("oom\n");
138
0
    return -1;
139
0
  }
140
141
2
  memset(current_processing_ctx, 0, context_size(CONTEXT_GLOBAL));
142
2
  return 0;
143
2
}
144
145
146
0
#define CTX_STACK_SIZE  8
147
static context_p ctx_stack[CTX_STACK_SIZE];
148
static unsigned int ctx_stack_idx = 0;
149
150
int push_new_global_context(void)
151
0
{
152
0
  if (ctx_stack_idx==CTX_STACK_SIZE) {
153
0
    LM_ERR("too many stacked contexts (%d)\n",ctx_stack_idx);
154
0
    return 0;
155
0
  }
156
157
0
  ctx_stack[ctx_stack_idx++] = current_processing_ctx;
158
159
0
  current_processing_ctx = context_alloc(CONTEXT_GLOBAL);
160
0
  if (!current_processing_ctx) {
161
0
    LM_ERR("oom\n");
162
0
    current_processing_ctx = ctx_stack[--ctx_stack_idx];
163
0
    return 0;
164
0
  }
165
166
0
  memset(current_processing_ctx, 0, context_size(CONTEXT_GLOBAL));
167
0
  return 1;
168
0
}
169
170
int pop_pushed_global_context(void)
171
0
{
172
0
  if (ctx_stack_idx==0) {
173
0
    LM_ERR("nothing to pop form the stack\n");
174
0
    return -1;
175
0
  }
176
177
0
  context_destroy(CONTEXT_GLOBAL, current_processing_ctx);
178
0
  context_free(current_processing_ctx);
179
180
0
  current_processing_ctx = ctx_stack[--ctx_stack_idx];
181
0
  return 0;
182
0
}
183
184
185
void clear_global_context(void)
186
0
{
187
0
  if (current_processing_ctx) {
188
0
    context_destroy(CONTEXT_GLOBAL, current_processing_ctx);
189
0
    context_free(current_processing_ctx);
190
0
    current_processing_ctx = NULL;
191
0
  }
192
0
}
193
194
195
int context_register_int(enum osips_context type, context_destroy_f f)
196
0
{
197
0
  context_sizes[type] += sizeof(int);
198
0
  type_offsets[type][CONTEXT_STR_TYPE] += sizeof(int);
199
0
  type_offsets[type][CONTEXT_PTR_TYPE] += sizeof(int);
200
0
  register_context_destroy(f, type, CONTEXT_INT_TYPE);
201
202
0
  return type_sizes[type][CONTEXT_INT_TYPE]++;
203
0
}
204
205
int context_register_str(enum osips_context type, context_destroy_f f)
206
0
{
207
0
  context_sizes[type] += sizeof(str);
208
0
  type_offsets[type][CONTEXT_PTR_TYPE] += sizeof(str);
209
0
  register_context_destroy(f, type, CONTEXT_STR_TYPE);
210
211
0
  return type_sizes[type][CONTEXT_STR_TYPE]++;
212
0
}
213
214
int context_register_ptr(enum osips_context type, context_destroy_f f)
215
2
{
216
2
  context_sizes[type] += sizeof(void *);
217
2
  register_context_destroy(f, type, CONTEXT_PTR_TYPE);
218
219
2
  return type_sizes[type][CONTEXT_PTR_TYPE]++;
220
2
}