core: fix another bunch of 'no real prototype' warnings, add doxygen docs
[sip-router] / script_cb.c
1 /*
2  * $Id$
3  *
4  * Script callbacks -- they add the ability to register callback
5  * functions which are always called when script for request
6  * processing is entered or left
7  *
8  *
9  * Copyright (C) 2001-2003 FhG Fokus
10  *
11  * This file is part of ser, a free SIP server.
12  *
13  * ser is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version
17  *
18  * For a license to use the ser software under conditions
19  * other than those described here, or to purchase support for this
20  * software, please contact iptel.org by e-mail at the following addresses:
21  *    info@iptel.org
22  *
23  * ser is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License 
29  * along with this program; if not, write to the Free Software 
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31  *
32  * History:
33  * --------
34  *  2003-03-29  cleaning pkg allocation introduced (jiri)
35  *  2003-03-19  replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei)
36  *  2005-02-13  script callbacks devided into request and reply types (bogdan)
37  *  2009-06-01  Added pre- and post-script callback support for all types
38  *              of route blocks. (Miklos)
39  */
40
41 /*!
42  * \file
43  * \brief SIP-router core :: 
44  * \ingroup core
45  * Module: \ref core
46  */
47
48
49 #include <stdlib.h>
50 #include "script_cb.h"
51 #include "dprint.h"
52 #include "error.h"
53 #include "mem/mem.h"
54
55 /* Number of cb types = last cb type */
56 #define SCRIPT_CB_NUM   EVENT_CB_TYPE
57
58 static struct script_cb *pre_script_cb[SCRIPT_CB_NUM];
59 static struct script_cb *post_script_cb[SCRIPT_CB_NUM];
60
61 /* Add a script callback to the beginning of the linked list.
62  * Returns -1 on error
63  */
64 static inline int add_callback( struct script_cb **list,
65         cb_function f, void *param)
66 {
67         struct script_cb *new_cb;
68
69         new_cb=pkg_malloc(sizeof(struct script_cb));
70         if (new_cb==0) {
71                 LOG(L_CRIT, "add_script_callback: out of memory\n");
72                 return -1;
73         }
74         new_cb->cbf = f;
75         new_cb->param = param;
76         /* link at the beginning of the list */
77         new_cb->next = *list;
78         *list = new_cb;
79         return 0;
80 }
81
82 /* Register pre- or post-script callbacks.
83  * Returns -1 on error, 0 on success
84  */
85 int register_script_cb( cb_function f, unsigned int flags, void *param )
86 {
87         struct script_cb        **cb_array;
88         int     i;
89
90         /* type checkings */
91         if ( (flags&((1<<SCRIPT_CB_NUM)-1))==0 ) {
92                 LOG(L_BUG, "register_script_cb: callback flag not specified\n");
93                 return -1;
94         }
95         if ( (flags&(~(PRE_SCRIPT_CB|POST_SCRIPT_CB))) >= 1<<SCRIPT_CB_NUM ) {
96                 LOG(L_BUG, "register_script_cb: unsupported callback flags: %u\n",
97                         flags);
98                 return -1;
99         }
100         if ( (flags&(PRE_SCRIPT_CB|POST_SCRIPT_CB))==0 ||
101         (flags&PRE_SCRIPT_CB && flags&POST_SCRIPT_CB) ) {
102                 LOG(L_BUG, "register_script_cb: callback POST or PRE type must "
103                         "be exactly one\n");
104                 return -1;
105         }
106
107         if (flags&PRE_SCRIPT_CB)
108                 cb_array = pre_script_cb;
109         else
110                 cb_array = post_script_cb;
111
112         /* Add the callback to the lists.
113          * (as many times as many flags are set)
114          */
115         for (i=0; i<SCRIPT_CB_NUM; i++) {
116                 if ((flags&(1<<i)) == 0)
117                         continue;
118                 if (add_callback(&cb_array[i], f, param) < 0)
119                         goto add_error;
120         }
121         return 0;
122
123 add_error:
124         LOG(L_ERR,"register_script_cb: failed to add callback\n");
125         return -1;
126 }
127
128 int init_script_cb()
129 {
130         memset(pre_script_cb, 0, SCRIPT_CB_NUM * sizeof(struct script_cb *));
131         memset(post_script_cb, 0, SCRIPT_CB_NUM * sizeof(struct script_cb *));
132         return 0;
133 }
134
135 static inline void destroy_cb_list(struct script_cb **list)
136 {
137         struct script_cb *foo;
138
139         while( *list ) {
140                 foo = *list;
141                 *list = (*list)->next;
142                 pkg_free( foo );
143         }
144 }
145
146 void destroy_script_cb()
147 {
148         int     i;
149
150         for (i=0; i<SCRIPT_CB_NUM; i++) {
151                 destroy_cb_list(&pre_script_cb[i]);
152                 destroy_cb_list(&post_script_cb[i]);
153         }
154 }
155
156 /* Execute pre-script callbacks of a given type.
157  * Returns 0 on error, 1 on success
158  */
159 int exec_pre_script_cb( struct sip_msg *msg, enum script_cb_type type)
160 {
161         struct script_cb        *cb;
162         unsigned int    flags;
163
164 #ifdef EXTRA_DEBUG
165         if (type >= SCRIPT_CB_NUM) {
166                 LOG(L_BUG, "exec_pre_script_cb: Uknown callback type\n");
167                 abort();
168         }
169 #endif
170         flags = PRE_SCRIPT_CB | (1<<(type-1));
171         for (cb=pre_script_cb[type-1]; cb ; cb=cb->next ) {
172                 /* stop on error */
173                 if (cb->cbf(msg, flags, cb->param)==0)
174                         return 0;
175         }
176         return 1;
177 }
178
179 /* Execute post-script callbacks of a given type.
180  * Always returns 1, success.
181  */
182 int exec_post_script_cb( struct sip_msg *msg, enum script_cb_type type)
183 {
184         struct script_cb        *cb;
185         unsigned int    flags;
186
187 #ifdef EXTRA_DEBUG
188         if (type >= SCRIPT_CB_NUM) {
189                 LOG(L_BUG, "exec_pre_script_cb: Uknown callback type\n");
190                 abort();
191         }
192 #endif
193         flags = POST_SCRIPT_CB | (1<<(type-1));
194         for (cb=post_script_cb[type-1]; cb ; cb=cb->next){
195                 cb->cbf(msg, flags, cb->param);
196         }
197         return 1;
198 }