caf80ae6 |
/*
* $Id$
*
* Script callbacks -- they add the ability to register callback
* functions which are always called when script for request
* processing is entered or left
* |
7dd0b342 |
* |
53c7e0f1 |
* Copyright (C) 2001-2003 FhG Fokus |
7dd0b342 |
*
* This file is part of ser, a free SIP server.
*
* ser is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* For a license to use the ser software under conditions
* other than those described here, or to purchase support for this
* software, please contact iptel.org by e-mail at the following addresses:
* info@iptel.org
*
* ser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
2e89dc92 |
*
* History: |
e3dccdc9 |
* -------- |
3c8bd369 |
* 2003-03-29 cleaning pkg allocation introduced (jiri) |
e3dccdc9 |
* 2003-03-19 replaced all mallocs/frees w/ pkg_malloc/pkg_free (andrei) |
2e89dc92 |
* 2005-02-13 script callbacks devided into request and reply types (bogdan) |
0a99f1b3 |
* 2009-06-01 Added pre- and post-script callback support for all types
* of route blocks. (Miklos) |
e3dccdc9 |
*/ |
caf80ae6 |
|
1d0661db |
/*!
* \file
* \brief SIP-router core ::
* \ingroup core
* Module: \ref core
*/
|
7dd0b342 |
|
caf80ae6 |
#include <stdlib.h>
#include "script_cb.h"
#include "dprint.h"
#include "error.h" |
e3dccdc9 |
#include "mem/mem.h" |
caf80ae6 |
|
0a99f1b3 |
/* Number of cb types = last cb type */ |
0b79baec |
#define SCRIPT_CB_NUM (MAX_CB_TYPE-1) |
caf80ae6 |
|
0a99f1b3 |
static struct script_cb *pre_script_cb[SCRIPT_CB_NUM];
static struct script_cb *post_script_cb[SCRIPT_CB_NUM]; |
2e89dc92 |
|
0a99f1b3 |
/* Add a script callback to the beginning of the linked list.
* Returns -1 on error
*/ |
2e89dc92 |
static inline int add_callback( struct script_cb **list,
cb_function f, void *param) |
caf80ae6 |
{
struct script_cb *new_cb;
|
e3dccdc9 |
new_cb=pkg_malloc(sizeof(struct script_cb)); |
caf80ae6 |
if (new_cb==0) { |
0a99f1b3 |
LOG(L_CRIT, "add_script_callback: out of memory\n"); |
2e89dc92 |
return -1; |
caf80ae6 |
} |
2e89dc92 |
new_cb->cbf = f;
new_cb->param = param;
/* link at the beginning of the list */
new_cb->next = *list;
*list = new_cb;
return 0;
}
|
0a99f1b3 |
/* Register pre- or post-script callbacks.
* Returns -1 on error, 0 on success
*/
int register_script_cb( cb_function f, unsigned int flags, void *param ) |
2e89dc92 |
{ |
0a99f1b3 |
struct script_cb **cb_array;
int i;
|
2e89dc92 |
/* type checkings */ |
0a99f1b3 |
if ( (flags&((1<<SCRIPT_CB_NUM)-1))==0 ) {
LOG(L_BUG, "register_script_cb: callback flag not specified\n");
return -1;
}
if ( (flags&(~(PRE_SCRIPT_CB|POST_SCRIPT_CB))) >= 1<<SCRIPT_CB_NUM ) {
LOG(L_BUG, "register_script_cb: unsupported callback flags: %u\n",
flags);
return -1; |
caf80ae6 |
} |
0a99f1b3 |
if ( (flags&(PRE_SCRIPT_CB|POST_SCRIPT_CB))==0 ||
(flags&PRE_SCRIPT_CB && flags&POST_SCRIPT_CB) ) {
LOG(L_BUG, "register_script_cb: callback POST or PRE type must " |
2e89dc92 |
"be exactly one\n"); |
0a99f1b3 |
return -1; |
2e89dc92 |
}
|
0a99f1b3 |
if (flags&PRE_SCRIPT_CB)
cb_array = pre_script_cb;
else
cb_array = post_script_cb;
/* Add the callback to the lists.
* (as many times as many flags are set)
*/
for (i=0; i<SCRIPT_CB_NUM; i++) {
if ((flags&(1<<i)) == 0)
continue;
if (add_callback(&cb_array[i], f, param) < 0)
goto add_error; |
2e89dc92 |
}
return 0; |
0a99f1b3 |
|
2e89dc92 |
add_error: |
0a99f1b3 |
LOG(L_ERR,"register_script_cb: failed to add callback\n"); |
2e89dc92 |
return -1; |
caf80ae6 |
}
|
0a99f1b3 |
int init_script_cb()
{
memset(pre_script_cb, 0, SCRIPT_CB_NUM * sizeof(struct script_cb *));
memset(post_script_cb, 0, SCRIPT_CB_NUM * sizeof(struct script_cb *));
return 0;
} |
2e89dc92 |
static inline void destroy_cb_list(struct script_cb **list) |
3c8bd369 |
{ |
2e89dc92 |
struct script_cb *foo;
while( *list ) {
foo = *list;
*list = (*list)->next;
pkg_free( foo );
}
} |
3c8bd369 |
|
2e89dc92 |
void destroy_script_cb()
{ |
0a99f1b3 |
int i; |
3c8bd369 |
|
0a99f1b3 |
for (i=0; i<SCRIPT_CB_NUM; i++) {
destroy_cb_list(&pre_script_cb[i]);
destroy_cb_list(&post_script_cb[i]);
}
} |
2e89dc92 |
|
0a99f1b3 |
/* Execute pre-script callbacks of a given type.
* Returns 0 on error, 1 on success
*/
int exec_pre_script_cb( struct sip_msg *msg, enum script_cb_type type) |
caf80ae6 |
{ |
0a99f1b3 |
struct script_cb *cb;
unsigned int flags;
#ifdef EXTRA_DEBUG
if (type >= SCRIPT_CB_NUM) {
LOG(L_BUG, "exec_pre_script_cb: Uknown callback type\n");
abort();
}
#endif |
d14f2315 |
flags = PRE_SCRIPT_CB | (1<<(type-1));
for (cb=pre_script_cb[type-1]; cb ; cb=cb->next ) { |
a50f3f89 |
/* stop on error */ |
0a99f1b3 |
if (cb->cbf(msg, flags, cb->param)==0) |
a50f3f89 |
return 0;
}
return 1; |
caf80ae6 |
}
|
0a99f1b3 |
/* Execute post-script callbacks of a given type.
* Always returns 1, success.
*/
int exec_post_script_cb( struct sip_msg *msg, enum script_cb_type type) |
2e89dc92 |
{ |
0a99f1b3 |
struct script_cb *cb;
unsigned int flags;
#ifdef EXTRA_DEBUG
if (type >= SCRIPT_CB_NUM) {
LOG(L_BUG, "exec_pre_script_cb: Uknown callback type\n");
abort();
}
#endif |
d14f2315 |
flags = POST_SCRIPT_CB | (1<<(type-1));
for (cb=post_script_cb[type-1]; cb ; cb=cb->next){ |
0a99f1b3 |
cb->cbf(msg, flags, cb->param); |
2e89dc92 |
}
return 1;
} |