modules/ims_qos: added patch for flow-description bug when request originates from...
[sip-router] / lib / shm_regex / shm_regex.c
1 /*
2  * Copyright (C) 2009 iptelorg GmbH
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 #include <malloc.h>     /* hook prototypes */
23
24 #include "../../mem/shm_mem.h"
25 #include "shm_regex.h"
26
27 typedef void *(malloc_hook_t) (size_t, const void *);
28 typedef void *(realloc_hook_t) (void *, size_t, const void *);
29 typedef void (free_hook_t) (void *, const void *);
30
31 /* The memory hooks are overwritten before calling regcomp(), regfree(),
32  * and regexec(), and shared memory function are called
33  * from the hooks instead of libc malloc/realloc/free.
34  */
35
36 static void *shm_malloc_hook(size_t size, const void *caller)
37 {
38         return shm_malloc (size);
39 }
40
41 static void *shm_realloc_hook(void *p, size_t size, const void *caller)
42 {
43         return shm_realloc (p, size);
44 }
45
46 static void shm_free_hook(void *ptr, const void *caller)
47 {
48         if (ptr) shm_free (ptr);
49 }
50
51 #define replace_malloc_hooks() \
52         do { \
53                 orig_malloc_hook = __malloc_hook; \
54                 orig_realloc_hook = __realloc_hook; \
55                 orig_free_hook = __free_hook; \
56                 __malloc_hook = shm_malloc_hook; \
57                 __realloc_hook = shm_realloc_hook; \
58                 __free_hook = shm_free_hook; \
59         } while (0)
60
61 #define restore_malloc_hooks() \
62         do { \
63                 __malloc_hook = orig_malloc_hook; \
64                 __realloc_hook = orig_realloc_hook; \
65                 __free_hook = orig_free_hook; \
66         } while (0)
67
68 int shm_regcomp(shm_regex_t *preg, const char *regex, int cflags)
69 {
70         malloc_hook_t   *orig_malloc_hook;
71         realloc_hook_t  *orig_realloc_hook;
72         free_hook_t     *orig_free_hook;
73         int             ret;
74
75         if(!lock_init(&preg->lock)) {
76                 return REG_EEND;
77         }
78         replace_malloc_hooks();
79         ret = regcomp(&preg->regexp, regex, cflags);
80         restore_malloc_hooks();
81
82         if(ret) lock_destroy(&preg->lock);
83
84         return ret;
85 }
86
87 void shm_regfree(shm_regex_t *preg)
88 {
89         malloc_hook_t   *orig_malloc_hook;
90         realloc_hook_t  *orig_realloc_hook;
91         free_hook_t     *orig_free_hook;
92         lock_destroy(&preg->lock);
93         replace_malloc_hooks();
94         regfree(&preg->regexp);
95         restore_malloc_hooks();
96 }
97
98 int shm_regexec(shm_regex_t *preg, const char *string, size_t nmatch,
99                    regmatch_t pmatch[], int eflags)
100 {
101         malloc_hook_t   *orig_malloc_hook;
102         realloc_hook_t  *orig_realloc_hook;
103         free_hook_t     *orig_free_hook;
104         int             ret;
105
106         /* regexec() allocates some memory for the pattern buffer
107          * when it is successfully called for the first time, therefore
108          * shared memory is required also here.
109          * The drawback is that shared memory allocation is also used
110          * needlessly for allocating the temporary space for
111          * the elements of pmatch. -- Does not happen if pmatch and
112          * nmatch are 0.
113          * It is safe to call regexec() concurrently without locking,
114          * because regexec() has its own locks.
115          * (Miklos)
116          *
117          * Those locks, however, don't work with shm and multi-core hardware
118          * causing a dead-lock. Tested with glibc 2.3.6. (skeller)
119          */
120
121         lock_get(&preg->lock);
122         replace_malloc_hooks();
123         ret = regexec(&preg->regexp, string, nmatch,
124                         pmatch, eflags);
125         restore_malloc_hooks();
126         lock_release(&preg->lock);
127
128         return ret;
129 }
130
131 size_t shm_regerror(int errcode, const shm_regex_t *preg, char *errbuf,
132                       size_t errbuf_size)
133 {
134         return regerror(errcode, &preg->regexp, errbuf, errbuf_size);
135 }
136