- updated to latest avp api
[sip-router] / modules / tm / t_hooks.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of ser, a free SIP server.
7  *
8  * ser is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * For a license to use the ser software under conditions
14  * other than those described here, or to purchase support for this
15  * software, please contact iptel.org by e-mail at the following addresses:
16  *    info@iptel.org
17  *
18  * ser is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License 
24  * along with this program; if not, write to the Free Software 
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 /*
28  * History:
29  * --------
30  *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei)
31  *  2003-12-04  global callbacks moved into transaction callbacks;
32  *              multiple events per callback added; single list per
33  *              transaction for all its callbacks (bogdan)
34  *  2004-08-23  user avp(attribute value pair) added -> making avp list
35  *              available in callbacks (bogdan)
36  */
37
38 #include "defs.h"
39
40
41 #include "stdlib.h"
42 #include "../../dprint.h"
43 #include "../../error.h"
44 #include "../../mem/mem.h"
45 #include "../../usr_avp.h"
46 #include "t_hooks.h"
47 #include "t_lookup.h"
48 #include "t_funcs.h"
49
50
51 struct tmcb_head_list* req_in_tmcb_hl = 0;
52
53
54
55 int init_tmcb_lists()
56 {
57         req_in_tmcb_hl = (struct tmcb_head_list*)shm_malloc
58                 ( sizeof(struct tmcb_head_list) );
59         if (req_in_tmcb_hl==0) {
60                 LOG(L_CRIT,"ERROR:tm:init_tmcb_lists: no more shared mem\n");
61                 return -1;
62         }
63         req_in_tmcb_hl->first = 0;
64         req_in_tmcb_hl->reg_types = 0;
65         return 1;
66 }
67
68
69 void destroy_tmcb_lists()
70 {
71         struct tm_callback *cbp, *cbp_tmp;
72
73         if (!req_in_tmcb_hl)
74                 return;
75
76         for( cbp=req_in_tmcb_hl->first; cbp ; ) {
77                 cbp_tmp = cbp;
78                 cbp = cbp->next;
79                 if (cbp_tmp->param) shm_free( cbp_tmp->param );
80                 shm_free( cbp_tmp );
81         }
82
83         shm_free(req_in_tmcb_hl);
84 }
85
86
87 int insert_tmcb(struct tmcb_head_list *cb_list, int types,
88                                                                         transaction_cb f, void *param )
89 {
90         struct tm_callback *cbp;
91
92         /* build a new callback structure */
93         if (!(cbp=shm_malloc( sizeof( struct tm_callback)))) {
94                 LOG(L_ERR, "ERROR:tm:insert_tmcb: out of shm. mem\n");
95                 return E_OUT_OF_MEM;
96         }
97
98         /* link it into the proper place... */
99         cbp->next = cb_list->first;
100         cb_list->first = cbp;
101         cb_list->reg_types |= types;
102         /* ... and fill it up */
103         cbp->callback = f;
104         cbp->param = param;
105         cbp->types = types;
106         if (cbp->next)
107                 cbp->id = cbp->next->id+1;
108         else
109                 cbp->id = 0;
110
111         return 1;
112 }
113
114
115
116 /* register a callback function 'f' for 'types' mask of events;
117  * will be called back whenever one of the events occurs in transaction module
118  * (global or per transaction, depending of event type)
119 */
120 int register_tmcb( struct sip_msg* p_msg, struct cell *t, int types,
121                                                                                         transaction_cb f, void *param )
122 {
123         //struct cell* t;
124         struct tmcb_head_list *cb_list;
125
126         /* are the callback types valid?... */
127         if ( types<0 || types>TMCB_MAX ) {
128                 LOG(L_CRIT, "BUG:tm:register_tmcb: invalid callback types: mask=%d\n",
129                         types);
130                 return E_BUG;
131         }
132         /* we don't register null functions */
133         if (f==0) {
134                 LOG(L_CRIT, "BUG:tm:register_tmcb: null callback function\n");
135                 return E_BUG;
136         }
137
138         if (types&TMCB_REQUEST_IN) {
139                 if (types!=TMCB_REQUEST_IN) {
140                         LOG(L_CRIT, "BUG:tm:register_tmcb: callback type TMCB_REQUEST_IN "
141                                 "can't be register along with types\n");
142                         return E_BUG;
143                 }
144                 cb_list = req_in_tmcb_hl;
145         } else {
146                 if (!t) {
147                         if (!p_msg) {
148                                 LOG(L_CRIT,"BUG:tm:register_tmcb: no sip_msg, nor transaction"
149                                         " given\n");
150                                 return E_BUG;
151                         }
152                         /* look for the transaction */
153                         if ( t_check(p_msg,0)!=1 ){
154                                 LOG(L_CRIT,"BUG:tm:register_tmcb: no transaction found\n");
155                                 return E_BUG;
156                         }
157                         if ( (t=get_t())==0 ) {
158                                 LOG(L_CRIT,"BUG:tm:register_tmcb: transaction found "
159                                         "is NULL\n");
160                                 return E_BUG;
161                         }
162                 }
163                 cb_list = &(t->tmcb_hl);
164         }
165
166         return insert_tmcb( cb_list, types, f, param );
167 }
168
169
170 void run_trans_callbacks( int type , struct cell *trans,
171                                                 struct sip_msg *req, struct sip_msg *rpl, int code )
172 {
173         static struct tmcb_params params = {0,0,0,0};
174         struct tm_callback    *cbp;
175         avp_list_t* backup;
176
177         params.req = req;
178         params.rpl = rpl;
179         params.code = code;
180
181         if (trans->tmcb_hl.first==0 || ((trans->tmcb_hl.reg_types)&type)==0 )
182                 return;
183
184         backup = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps );
185         for (cbp=trans->tmcb_hl.first; cbp; cbp=cbp->next)  {
186                 if ( (cbp->types)&type ) {
187                         DBG("DBG: trans=%p, callback type %d, id %d entered\n",
188                                 trans, type, cbp->id );
189                         params.param = &(cbp->param);
190                         cbp->callback( trans, type, &params );
191                 }
192         set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup );
193         }
194 }
195
196
197
198 void run_reqin_callbacks( struct cell *trans, struct sip_msg *req, int code )
199 {
200         static struct tmcb_params params = {0,0,0,0};
201         struct tm_callback    *cbp;
202         avp_list_t* backup;
203
204         params.req = req;
205         params.code = code;
206
207         if (req_in_tmcb_hl->first==0)
208                 return;
209
210         backup = set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, &trans->user_avps );
211         for (cbp=req_in_tmcb_hl->first; cbp; cbp=cbp->next)  {
212                 DBG("DBG: trans=%p, callback type %d, id %d entered\n",
213                         trans, cbp->types, cbp->id );
214                 params.param = &(cbp->param);
215                 cbp->callback( trans, cbp->types, &params );
216         }
217         set_avp_list(AVP_CLASS_USER | AVP_TRACK_FROM, backup );
218 }
219