@cfg_get.<group_name>.<var_name> is documented
[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  */
38
39
40 #include <stdlib.h>
41 #include "script_cb.h"
42 #include "dprint.h"
43 #include "error.h"
44 #include "mem/mem.h"
45
46 static struct script_cb *pre_req_cb=0;
47 static struct script_cb *post_req_cb=0;
48
49 static struct script_cb *pre_rpl_cb=0;
50 static struct script_cb *post_rpl_cb=0;
51
52 static unsigned int cb_id=0;
53
54
55 static inline int add_callback( struct script_cb **list,
56         cb_function f, void *param)
57 {
58         struct script_cb *new_cb;
59
60         new_cb=pkg_malloc(sizeof(struct script_cb));
61         if (new_cb==0) {
62                 LOG(L_ERR, "ERROR:add_script_callback: out of memory\n");
63                 return -1;
64         }
65         new_cb->cbf = f;
66         new_cb->id = cb_id++;
67         new_cb->param = param;
68         /* link at the beginning of the list */
69         new_cb->next = *list;
70         *list = new_cb;
71         return 0;
72 }
73
74
75 int register_script_cb( cb_function f, int type, void *param )
76 {
77         /* type checkings */
78         if ( (type&(REQ_TYPE_CB|RPL_TYPE_CB))==0 ) {
79                 LOG(L_CRIT,"BUG:register_script_cb: REQUEST or REPLY "
80                         "type not specified\n");
81                 goto error;
82         }
83         if ( (type&(PRE_SCRIPT_CB|POST_SCRIPT_CB))==0 ||
84         (type&PRE_SCRIPT_CB && type&POST_SCRIPT_CB) ) {
85                 LOG(L_CRIT,"BUG:register_script_cb: callback POST or PRE type must "
86                         "be exactly one\n");
87                 goto error;
88         }
89
90         if (type&REQ_TYPE_CB) {
91                 /* callback for request script */
92                 if (type&PRE_SCRIPT_CB) {
93                         if (add_callback( &pre_req_cb, f, param)<0)
94                                 goto add_error;
95                 } else if (type&POST_SCRIPT_CB) {
96                         if (add_callback( &post_req_cb, f, param)<0)
97                                 goto add_error;
98                 }
99         }
100         if (type&RPL_TYPE_CB) {
101                 /* callback (also) for reply script */
102                 if (type&PRE_SCRIPT_CB) {
103                         if (add_callback( &pre_rpl_cb, f, param)<0)
104                                 goto add_error;
105                 } else if (type&POST_SCRIPT_CB) {
106                         if (add_callback( &post_rpl_cb, f, param)<0)
107                                 goto add_error;
108                 }
109         }
110
111         return 0;
112 add_error:
113         LOG(L_ERR,"ERROR:register_script_cb: failed to add callback\n");
114 error:
115         return -1;
116 }
117
118
119 static inline void destroy_cb_list(struct script_cb **list)
120 {
121         struct script_cb *foo;
122
123         while( *list ) {
124                 foo = *list;
125                 *list = (*list)->next;
126                 pkg_free( foo );
127         }
128 }
129
130
131 void destroy_script_cb()
132 {
133         destroy_cb_list( &pre_req_cb  );
134         destroy_cb_list( &post_req_cb );
135         destroy_cb_list( &pre_rpl_cb  );
136         destroy_cb_list( &post_req_cb );
137 }
138
139
140 static inline int exec_pre_cb( struct sip_msg *msg, struct script_cb *cb)
141 {
142         for ( ; cb ; cb=cb->next ) {
143                 /* stop on error */
144                 if (cb->cbf(msg, cb->param)==0)
145                         return 0;
146         }
147         return 1;
148 }
149
150
151 static inline int exec_post_cb( struct sip_msg *msg, struct script_cb *cb)
152 {
153         for ( ; cb ; cb=cb->next){
154                 cb->cbf( msg, cb->param);
155         }
156         return 1;
157 }
158
159
160 int exec_pre_req_cb( struct sip_msg *msg)
161 {
162         return exec_pre_cb( msg, pre_req_cb);
163 }
164
165 int exec_pre_rpl_cb( struct sip_msg *msg)
166 {
167         return exec_pre_cb( msg, pre_rpl_cb);
168 }
169
170 int exec_post_req_cb( struct sip_msg *msg)
171 {
172         return exec_post_cb( msg, post_req_cb);
173 }
174
175 int exec_post_rpl_cb( struct sip_msg *msg)
176 {
177         return exec_post_cb( msg, post_rpl_cb);
178 }
179