update to 3.3.0 from upstream

remotes/origin/3.3+ngcp2.6
Andrew Pogrebennyk 14 years ago
parent b1bcb2e798
commit 7c059e4647

17798
ChangeLog

File diff suppressed because it is too large Load Diff

@ -64,6 +64,9 @@ very few, Kamailio enabling next compile time flags:
Switching between flavours is a matter of 'make' command parameters.
Several installation tutorials for Kamailio are available on the web wiki:
- http://www.kamailio.org/wiki/
2. Supported Architectures and Requirements
-------------------------------------------

@ -135,7 +135,7 @@ module_group_standard=acc_syslog auth avp ctl dispatcher diversion enum\
eval exec fifo db_flatstore gflags maxfwd mediaproxy \
nathelper options pdt permissions pike print ratelimit \
registrar rr rtpproxy sanity sl textops timer tm uac \
unixsock uri usrloc xlog cfg_rpc tmrec
unixsock uri usrloc xlog cfg_rpc sipcapture msrp tmrec
# Modules in this group are considered a standard part of SER (due to
# widespread usage) but they have dependencies that must be satisfied for
@ -168,18 +168,16 @@ module_group_mysql=$(module_group_mysql_driver) $(module_group_db)
module_group_postgres_driver=db_postgres
module_group_postgres=$(module_group_postgres_driver) $(module_group_db)
# For redis
module_group_redis=ndb_redis
# For radius
module_group_radius=acc_radius auth_radius misc_radius avp_radius uri_radius \
peering
# For presence
# kamailio modules
module_group_presence=presence presence_dialoginfo presence_mwi presence_xml \
module_group_presence=presence presence_dialoginfo presence_mwi presence_xml presence_profile\
pua pua_bla pua_dialoginfo pua_mi pua_usrloc pua_xmpp \
rls xcap_client xcap_server presence_conference
rls xcap_client xcap_server presence_conference \
presence_reginfo pua_reginfo
#ser modules
module_group_presence+=dialog presence_b2b xcap
# obsolete/unmaintained ser modules
@ -196,9 +194,14 @@ module_group_stable=cpl-c dbtext jabber osp sms pdb
# Modules in this group are either not complete, untested, or without enough
# reports of usage to allow the module into the stable group. They may or may
# not have dependencies
module_group_experimental=tls oracle iptrtpproxy
module_group_experimental=tls oracle iptrtpproxy ndb_redis async
# For cassandra
module_group_cassandra_driver=db_cassandra
module_group_cassandra=$(module_group_cassandra_driver) $(module_group_db)
# Kamailio specific groups
### Kamailio specific groups ###
# Standard modules in K Debian distro
module_group_kstandard=acc alias_db auth auth_db benchmark call_control \
cfgutils db_text dialog dispatcher diversion domain drouting \
@ -210,7 +213,8 @@ module_group_kstandard=acc alias_db auth auth_db benchmark call_control \
avpops cfg_db cfg_rpc ctl db_flatstore dialplan enum \
iptrtpproxy lcr mediaproxy mi_rpc pdb sanity tm topoh \
blst prefix_route counters debugger matrix mqueue mtree \
pipelimit rtpproxy textopsx xhttp tmrec
pipelimit rtpproxy textopsx xhttp xhttp_rpc ipops p_usrloc \
sdpops async sipcapture dmq msrp tmrec db_cluster
# K mysql module
module_group_kmysql=db_mysql
@ -261,9 +265,10 @@ module_group_kmemcached=memcached
module_group_ktls=tls
# K presence modules
module_group_kpresence=presence presence_dialoginfo presence_mwi presence_xml \
module_group_kpresence=presence presence_dialoginfo presence_mwi presence_xml presence_profile\
pua pua_bla pua_dialoginfo pua_mi pua_usrloc pua_xmpp \
rls xcap_client xcap_server presence_conference
rls xcap_client xcap_server presence_conference \
presence_reginfo pua_reginfo
# K lua module
module_group_klua=app_lua
@ -274,9 +279,17 @@ module_group_kpython=app_python
# K geoip module
module_group_kgeoip=geoip
# k redis module
# K sqlite module
module_group_ksqlite=db_sqlite
# K json modules
module_group_kjson=json jsonrpc-c
# K redis module
module_group_kredis=ndb_redis
# K mono module
module_group_kmono=app_mono
# if not set on the cmd. line, env or in the modules.lst (cfg_group_include)
# exclude the below modules.
@ -290,17 +303,18 @@ else
exclude_modules?= cpl mangler postgres jabber mysql cpl-c \
auth_radius misc_radius avp_radius uri_radius \
acc_radius pa rls presence_b2b xcap xmlrpc\
osp tls oracle \
osp tls oracle cassandra \
unixsock dbg print_lib auth_identity ldap \
db_berkeley db_mysql db_postgres db_oracle \
db_unixodbc memcached mi_xmlrpc \
db_sqlite db_unixodbc db_cassandra memcached mi_xmlrpc \
perl perlvdb purple \
snmpstats xmpp \
carrierroute peering \
dialplan lcr utils presence presence_mwi \
presence_dialoginfo presence_xml pua pua_bla \
pua_dialoginfo pua_usrloc pua_xmpp \
regex xcap_client xcap_server presence_conference
regex xcap_client xcap_server presence_conference \
presence_reginfo pua_reginfo
#excluded because they depend on external *.h files
exclude_modules+= h350
# excluded because they do not compile (remove them only after they are
@ -314,6 +328,12 @@ else
exclude_modules+= app_python
# depends on libxml2
exclude_modules+= xmlops
# depends on jsoc-c
exclude_modules+= json jsonrpc-c
# depends on libhiredis
exclude_modules+= ndb_redis
# depends on mono-devel
exclude_modules+= app_mono
# depends on tm being compiled with -DWITH_AS_SUPPORT support
ifeq (,$(findstring -DWITH_AS_SUPPORT, $(C_DEFS)))
exclude_modules+= seas
@ -838,12 +858,9 @@ bin:
deb:
-@if [ -d debian ]; then \
dpkg-buildpackage -rfakeroot -tc; \
elif [ -d pkg/$(MAIN_NAME)/deb/debian ]; then \
ln -s pkg/$(MAIN_NAME)/deb/debian debian; \
dpkg-buildpackage -rfakeroot -tc; \
rm debian; \
else \
ln -s pkg/debian debian; \
ln -s pkg/$(MAIN_NAME)/deb/debian debian; \
dpkg-buildpackage -rfakeroot -tc; \
rm debian; \
fi
@ -854,7 +871,7 @@ sunpkg:
mkdir -p tmp/$(MAIN_NAME)_sun_pkg
$(MAKE) install basedir=$(CURDIR)/tmp/$(MAIN_NAME) \
prefix=/usr/local $(mk_params)
(cd pkg/solaris; \
(cd pkg/$(MAIN_NAME)/solaris; \
pkgmk -r ../../tmp/$(MAIN_NAME)/usr/local -o -d ../../tmp/$(MAIN_NAME)_sun_pkg/ -v "$(RELEASE)" ;\
cd ../..)
cat /dev/null > ../$(NAME)-$(RELEASE)-$(OS)-$(ARCH)-local
@ -1180,3 +1197,7 @@ dbschema:
-@echo "Build database schemas"
$(MAKE) -C lib/srdb1/schema
-@echo "Done"
.PHONY: printcdefs
printcdefs:
@echo -n $(C_DEFS)

@ -5,7 +5,7 @@
# Environment variables:
# PREFIX, LOCALBASE, BASEDIR
# INSTALL, TAR , CC, LEX, YACC,
# CPU, CC_EXTRA_OPTS,
# CPU, CC_EXTRA_OPTS, LD_EXTRA_OPTS
# exclude_modules, skip_modules, include_modules
# extra_defs
#
@ -160,14 +160,14 @@ INSTALL_FLAVOUR=$(FLAVOUR)
#version number
VERSION = 3
PATCHLEVEL = 1
SUBLEVEL = 5
PATCHLEVEL = 3
SUBLEVEL = 0
EXTRAVERSION =
# memory debugger switcher
# 0 - off (release mode)
# 1 - on (devel mode)
MEMDBG ?= 1
MEMDBG ?= 0
SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
$(SUBLEVEL) )
@ -225,6 +225,8 @@ endif
# extra CC command line options (e.g -march=athlon-mp)
CC_EXTRA_OPTS ?=
# extra LD command line options
LD_EXTRA_OPTS ?=
ifeq ($(OS), solaris)
#use GNU versions
@ -291,11 +293,11 @@ ifneq (,$(findstring gcc, $(CC_LONGVER)))
-e 's/3\.[4-9]/3.4/' \
-e 's/4\.[0-1]\..*/4.x/' \
-e 's/4\.[0-1]/4.x/' \
-e 's/4\.[2-46-9]\..*/4.2+/' \
-e 's/4\.[2-46-9]$$/4.2+/' \
-e 's/4\.5\..*/4.5/' \
-e 's/4\.5$$/4.5/')
ifeq (,$(strip $(filter-out 3.0 3.4 4.x 4.2+ 4.5,$(CC_SHORTVER))))
-e 's/4\.[2-4]\..*/4.2+/' \
-e 's/4\.[2-4]$$/4.2+/' \
-e 's/4\.[5-9]\..*/4.5+/' \
-e 's/4\.[5-9]$$/4.5+/')
ifeq (,$(strip $(filter-out 3.0 3.4 4.x 4.2+ 4.5+,$(CC_SHORTVER))))
# dependencies can be generated on-the-fly while compiling *.c
CC_MKDEP_OPTS=-MMD -MP
endif # 3.0 <= $(CC_SHORTVER) <= 4.x
@ -558,6 +560,8 @@ data_target = $(prefix)/$(data_dir)
# now.
# -DDBG_MALLOC
# issues additional debugging information if lock/unlock is called
# -DMEM_JOIN_FREE
# enable the join of free memory chunks (see also mem_join cfg param)
# -DFAST_LOCK
# uses fast arhitecture specific locking (see the arh. specific section)
# -DUSE_SYSV_SEM
@ -674,6 +678,7 @@ C_DEFS= $(extra_defs) \
-DUSE_DNS_FAILOVER \
-DUSE_DST_BLACKLIST \
-DUSE_NAPTR \
-DWITH_XAVP \
#-DUSE_DNS_CACHE_STATS \
#-DUSE_DST_BLACKLIST_STATS \
#-DDNS_WATCHDOG_SUPPORT \
@ -701,8 +706,10 @@ C_DEFS= $(extra_defs) \
ifeq ($(MEMDBG), 1)
C_DEFS+= -DDBG_QM_MALLOC
C_DEFS+= -DMEM_JOIN_FREE
else
C_DEFS+= -DF_MALLOC
C_DEFS+= -DMEM_JOIN_FREE
endif
ifneq ($(PKG_MEM_SIZE),)
C_DEFS+= -DPKG_MEM_SIZE=$(PKG_MEM_SIZE)
@ -863,8 +870,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS=-g -O9 -funroll-loops -Wcast-align $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
$(call set_if_empty,CPU,athlon64)
CFLAGS+=-m32 -minline-all-stringops \
-falign-loops \
@ -913,7 +920,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
ifeq ($(CC_NAME), icc)
@ -938,9 +945,9 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS=-g -O9 -funroll-loops -Wcast-align $(PROFILE)
#if gcc 4.5
#if gcc 4.5+
# don't add '-mtune=$(CPU)' - gcc failure
ifeq ($(CC_SHORTVER), 4.5)
ifeq ($(CC_SHORTVER), 4.5+)
$(call set_if_empty,CPU,opteron)
CFLAGS+=-m64 -minline-all-stringops \
-falign-loops \
@ -999,7 +1006,7 @@ endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.2+
endif # CC_SHORTVER, 4.5
endif # CC_SHORTVER, 4.5+
else # CC_NAME, gcc
ifeq ($(CC_NAME), icc)
@ -1026,8 +1033,8 @@ ifeq ($(CC_NAME), gcc)
CFLAGS=-g -O9 -funroll-loops $(PROFILE) \
#-Wcast-align \
#-Wmissing-prototypes
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
$(call set_if_empty,CPU,ultrasparc)
#use 32bit for now
CFLAGS+=-m64 -mcpu=ultrasparc \
@ -1093,7 +1100,7 @@ endif #CC_SHORTVER, 2.9x
endif #CC_SHORTVER, 3.0
endif #CC_SHORTVER, 3.4
endif #CC_SHORTVER, 4.x
endif #CC_SHORTVER, 4.5 or 4.2+
endif #CC_SHORTVER, 4.5+ or 4.2+
else #CC_NAME, gcc
ifeq ($(CC_NAME), suncc)
@ -1117,8 +1124,8 @@ ifeq ($(CC_NAME), gcc)
CFLAGS=-g -O9 -funroll-loops $(PROFILE) \
#-Wcast-align \
#-Wmissing-prototypes
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
$(call set_if_empty,CPU,v8)
#use 32bit for now
CFLAGS+= -mtune=$(CPU) \
@ -1159,7 +1166,7 @@ endif #CC_SHORTVER, 2.9x
endif #CC_SHORTVER, 3.0
endif #CC_SHORTVER, 3.4
endif #CC_SHORTVER, 4.x
endif #CC_SHORTVER, 4.5 or 4.2+
endif #CC_SHORTVER, 4.5+ or 4.2+
else #CC_NAME, gcc
ifeq ($(CC_NAME), suncc)
@ -1180,8 +1187,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS=-O9 -funroll-loops -fsigned-char $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+= -ftree-vectorize -fno-strict-overflow
# not supported on arm: -minline-all-stringops
else
@ -1213,7 +1220,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1229,8 +1236,8 @@ ifeq ($(CC_NAME), gcc)
#common stuff
CFLAGS=-march=armv6 -O9 -funroll-loops -fsigned-char \
$(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+= -ftree-vectorize -fno-strict-overflow
else
#if gcc 4.x+
@ -1260,7 +1267,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1275,8 +1282,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS=-O9 -funroll-loops $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+=-march=r3000 -minline-all-stringops \
-ftree-vectorize -fno-strict-overflow
else
@ -1307,7 +1314,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1322,8 +1329,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS= -mips2 -O9 -funroll-loops $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+=-minline-all-stringops -ftree-vectorize \
-fno-strict-overflow
else
@ -1352,7 +1359,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1367,8 +1374,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS= -mips64 -O9 -funroll-loops $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+=-minline-all-stringops -ftree-vectorize \
-fno-strict-overflow
else
@ -1397,7 +1404,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1413,7 +1420,7 @@ ifeq ($(CC_NAME), gcc)
#common stuff
CFLAGS= -O9 -funroll-loops $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
CFLAGS+= -fno-strict-overflow
# not supported: -minline-all-stringops
else
@ -1443,7 +1450,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1458,8 +1465,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS= -O9 -funroll-loops -fsigned-char $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
$(call set_if_empty,CPU,powerpc)
CFLAGS+=-ftree-vectorize \
-fno-strict-overflow \
@ -1492,7 +1499,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1507,8 +1514,8 @@ ifeq ($(CC_NAME), gcc)
C_DEFS+=-DCC_GCC_LIKE_ASM
#common stuff
CFLAGS= -O9 -funroll-loops -fsigned-char $(PROFILE)
#if gcc 4.5 or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5,$(CC_SHORTVER))))
#if gcc 4.5+ or 4.2+
ifeq (,$(strip $(filter-out 4.2+ 4.5+,$(CC_SHORTVER))))
$(call set_if_empty,CPU,powerpc64)
CFLAGS+=-ftree-vectorize \
-fno-strict-overflow \
@ -1541,7 +1548,7 @@ endif # CC_SHORTVER, 2.9x
endif # CC_SHORTVER, 3.0
endif # CC_SHORTVER, 3.4
endif # CC_SHORTVER, 4.x
endif # CC_SHORTVER, 4.5 or 4.2+
endif # CC_SHORTVER, 4.5+ or 4.2+
else # CC_NAME, gcc
#other compilers
@ -1589,6 +1596,11 @@ endif
# we need -fPIC -DPIC only for shared objects, we don't need them for
# the executable file, because it's always loaded at a fixed address
# -andrei
LDFLAGS+= $(LD_EXTRA_OPTS)
MOD_LDFLAGS+= $(LD_EXTRA_OPTS)
LIB_LDFLAGS+= $(LD_EXTRA_OPTS)
else #mode,release
ifeq ($(CC_NAME), gcc)
CFLAGS=-g -Wcast-align $(PROFILE)

@ -75,6 +75,14 @@ override static_modules_path=
# temporary def (visible only in the module, not exported)
DEFS += -DMOD_NAME='"$(MOD_NAME)"'
ifeq (,$(findstring -DSER_MOD_INTERFACE, $(DEFS)))
MODIFACE=-DOPENSER_MOD_INTERFACE
else
MODIFACE=-DSER_MOD_INTERFACE
endif
ifneq ($(makefile_defs_included),1)
$(error "the local makefile does not include Makefile.defs!")
endif
@ -273,7 +281,7 @@ $(share_prefix)/$(share_dir):
ifneq (,$(wildcard doc/Makefile))
#doc/Makefile present => we can generate README
README: doc/*.xml
README: doc/*.xml ../../docbook/entities.xml
$(MAKE) -C doc $(MOD_NAME).txt
mv doc/$(MOD_NAME).txt $@
@ -297,6 +305,10 @@ man:
endif
printmiface:
@echo -n $(MODIFACE)
endif # ifeq($(makefile_defs),1)
include $(COREPATH)/Makefile.cfg

@ -93,6 +93,7 @@
#endif
#include "switch.h"
#include "events.h"
#include "cfg/cfg_struct.h"
#include <sys/types.h>
#include <sys/socket.h>
@ -301,6 +302,8 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
unsigned short port;
str* dst_host;
int i, flags;
avp_t* avp;
struct search_state st;
struct switch_cond_table* sct;
struct switch_jmp_table* sjt;
struct rval_expr* rve;
@ -482,15 +485,45 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
break;
case SEND_T:
case SEND_TCP_T:
if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
a->val[0].type, a->val[1].type);
ret=E_BUG;
goto error;
if (a->val[0].type==URIHOST_ST){
/*get next hop uri uri*/
if (msg->dst_uri.len) {
ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len,
&next_hop);
u = &next_hop;
} else {
ret = parse_sip_msg_uri(msg);
u = &msg->parsed_uri;
}
if (ret<0) {
LM_ERR("send() - bad_uri dropping packet\n");
ret=E_BUG;
goto error;
}
/* init dst */
init_dest_info(&dst);
ret = sip_hostport2su(&dst.to, &u->host, u->port_no,
&dst.proto);
if(ret!=0) {
LM_ERR("failed to resolve [%.*s]\n", u->host.len,
ZSW(u->host.s));
ret=E_BUG;
goto error;
}
} else {
if ((a->val[0].type!= PROXY_ST)|(a->val[1].type!=NUMBER_ST)){
LOG(L_CRIT, "BUG: do_action: bad send() types %d, %d\n",
a->val[0].type, a->val[1].type);
ret=E_BUG;
goto error;
}
/* init dst */
init_dest_info(&dst);
ret=proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
if(ret==0)
proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
}
/* init dst */
init_dest_info(&dst);
ret=proxy2su(&dst.to, (struct proxy_l*)a->val[0].u.data);
if (ret==0){
if (p_onsend){
tmp=p_onsend->buf;
@ -521,7 +554,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
ret=E_BUG;
goto error;
}
proxy_mark((struct proxy_l*)a->val[0].u.data, ret);
if (ret>=0) ret=1;
break;
@ -556,6 +588,21 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
ruri_mark_consumed();
break;
/* remove last branch */
case REMOVE_BRANCH_T:
if (a->val[0].type!=NUMBER_ST) {
ret=drop_sip_branch(0) ? -1 : 1;
} else {
ret=drop_sip_branch(a->val[0].u.number) ? -1 : 1;
}
break;
/* remove all branches */
case CLEAR_BRANCHES_T:
clear_branches();
ret=1;
break;
/* jku begin: is_length_greater_than */
case LEN_GT_T:
if (a->val[0].type!=NUMBER_ST) {
@ -617,15 +664,16 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
break;
/* jku - end : flag processing */
case AVPFLAG_OPER_T: {
struct search_state st;
avp_t* avp;
int flag;
case AVPFLAG_OPER_T:
ret = 0;
flag = a->val[1].u.number;
if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL || (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
for (avp=search_first_avp(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, &st); avp; avp = search_next_avp(&st, NULL)) {
switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL ||
(a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
for (avp=search_first_avp(a->val[0].u.attr->type,
a->val[0].u.attr->name, NULL, &st);
avp;
avp = search_next_avp(&st, NULL)) {
switch (a->val[2].u.number) {
/* oper: 0..reset, 1..set, -1..no change */
case 0:
avp->flags &= ~(avp_flags_t)a->val[1].u.number;
break;
@ -634,13 +682,16 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
break;
default:;
}
ret = ret || ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
ret = ret ||
((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
}
}
else {
avp = search_avp_by_index(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
} else {
avp = search_avp_by_index(a->val[0].u.attr->type,
a->val[0].u.attr->name, NULL,
a->val[0].u.attr->index);
if (avp) {
switch (a->val[2].u.number) { /* oper: 0..reset, 1..set, -1..no change */
switch (a->val[2].u.number) {
/* oper: 0..reset, 1..set, -1..no change */
case 0:
avp->flags &= ~(avp_flags_t)a->val[1].u.number;
break;
@ -655,7 +706,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
if (ret==0)
ret = -1;
break;
}
case ERROR_T:
if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
@ -1380,7 +1430,9 @@ match_cleanup:
ret=1;
while(!(flags & (BREAK_R_F|RETURN_R_F|EXIT_R_F)) &&
(rval_expr_eval_int(h, msg, &v, rve) == 0) && v){
i++;
if (cfg_get(core, core_cfg, max_while_loops) > 0)
i++;
if (unlikely(i > cfg_get(core, core_cfg, max_while_loops))){
LOG(L_ERR, "ERROR: runaway while (%d, %d): more then"
" %d loops\n",
@ -1494,6 +1546,40 @@ match_cleanup:
msg->rpl_send_flags.f|= SND_F_CON_CLOSE;
ret=1; /* continue processing */
break;
case CFG_SELECT_T:
if (a->val[0].type != CFG_GROUP_ST) {
BUG("unsupported parameter in CFG_SELECT_T: %d\n",
a->val[0].type);
ret=-1;
goto error;
}
switch(a->val[1].type) {
case NUMBER_ST:
v=(int)a->val[1].u.number;
break;
case RVE_ST:
if (rval_expr_eval_int(h, msg, &v, (struct rval_expr*)a->val[1].u.data) < 0) {
ret=-1;
goto error;
}
break;
default:
BUG("unsupported group id type in CFG_SELECT_T: %d\n",
a->val[1].type);
ret=-1;
goto error;
}
ret=(cfg_select((cfg_group_t*)a->val[0].u.data, v) == 0) ? 1 : -1;
break;
case CFG_RESET_T:
if (a->val[0].type != CFG_GROUP_ST) {
BUG("unsupported parameter in CFG_RESET_T: %d\n",
a->val[0].type);
ret=-1;
goto error;
}
ret=(cfg_reset((cfg_group_t*)a->val[0].u.data) == 0) ? 1 : -1;
break;
/*
default:
LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
@ -1523,6 +1609,7 @@ int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
struct action* t;
int ret;
struct sr_module *mod;
unsigned int ms = 0;
ret=E_UNSPEC;
h->rec_lev++;
@ -1552,7 +1639,21 @@ int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
}
for (t=a; t!=0; t=t->next){
if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0))
ms = TICKS_TO_MS(get_ticks_raw());
ret=do_action(h, t, msg);
if(unlikely(cfg_get(core, core_cfg, latency_limit_action)>0)) {
ms = TICKS_TO_MS(get_ticks_raw()) - ms;
if(ms >= cfg_get(core, core_cfg, latency_limit_action)) {
LOG(cfg_get(core, core_cfg, latency_log),
"alert - action [%s (%d)]"
" cfg [%s:%d] took too long [%u ms]\n",
is_mod_func(t) ?
((cmd_export_common_t*)(t->val[0].u.data))->name
: "corefunc",
t->type, (t->cfile)?t->cfile:"", t->cline, ms);
}
}
/* break, return or drop/exit stop execution of the current
block */
if (unlikely(h->run_flags & (BREAK_R_F|RETURN_R_F|EXIT_R_F))){

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,14 +14,18 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file
* @brief atomic operations and memory barriers (alpha specific)
*
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
/**
* @file
* @brief Atomic operations and memory barriers (alpha specific)
*
* Config defines: - NOSMP
* - __CPU_alpha
* Atomic operations and memory barriers (alpha specific)
* \warning atomic ops do not include memory barriers, see atomic_ops.h
* for more details.
*
* Config defines:
* - NOSMP
* - __CPU_alpha
* @ingroup atomic
*/
/*
* History:

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,15 +14,20 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic ops and memory barriers for arm (>= v3)
* see atomic_ops.h for more details
*
* Config defines: - NOSMP
* - __CPU_arm
* - __CPU_arm6 - armv6 support (supports atomic ops
* via ldrex/strex)
*/
/**
* @file
* @brief Atomic ops and memory barriers for ARM (>= v3)
*
* Atomic ops and memory barriers for ARM architecture (starting from version 3)
* see atomic_ops.h for more info.
*
* Config defines:
* - NOSMP
* - __CPU_arm
* - __CPU_arm6 - armv6 support (supports atomic ops via ldrex/strex)
* @ingroup atomic
*/
/*
* History:
* --------

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,9 +14,22 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* common part for all the atomic operations (atomic_t and common operations)
* See @ref atomic_ops.h for more info.
/**
* @defgroup atomic SIP-router atomic operations
* @brief SIP-router atomic operations and memory barriers support
*
* SIP-router atomic operations and memory barriers support for different CPU
* architectures implemented in assembler. It also provides some generic
* fallback code for architectures not currently supported.
*/
/**
* @file
* @brief Common part for all the atomic operations
*
* Common part for all the atomic operations (atomic_t and common operations)
* see atomic_ops.h for more info.
* @ingroup atomic
*/
/*
@ -27,18 +38,27 @@
* 2006-03-08 created by andrei
* 2007-05-13 split from atomic_ops.h (andrei)
*/
#ifndef __atomic_common
#define __atomic_common
/** @brief atomic_t defined as a struct to easily catch non atomic ops. on it,
* e.g. atomic_t foo; foo++ will generate a compile error */
/**
* @brief atomic_t defined as a struct to easily catch non atomic operations on it.
*
* atomic_t defined as a struct to easily catch non atomic operations on it,
* e.g. atomic_t foo; foo++ will generate a compile error.
*/
typedef struct{ volatile int val; } atomic_t;
/** @name AtomicOps store and load operations are atomic on all cpus, note however that they
/**
* @name Atomic load and store operations
* Atomic store and load operations are atomic on all cpus, note however that they
* don't include memory barriers so if you want to use atomic_{get,set}
* to implement mutexes you must use the mb_* versions or explicitely use
* the barriers */
* the barriers
*/
/*@{ */

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,20 +14,23 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic operations and memory barriers (mips isa 2 and mips64 specific)
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
* WARNING: not tested on mips64 (not even a compile test)
/**
* @file
* @brief Atomic operations and memory barriers (MIPS isa 2 and MIPS64 specific)
*
* Atomic operations and memory barriers (MIPS isa 2 and MIPS64 specific)
* \warning atomic ops do not include memory barriers, see atomic_ops.h for
* more details.
* \warning not tested on MIPS64 (not even a compile test)
*
* Config defines: - NOSMP (in NOSMP mode it will also work on mips isa 1
* cpus that support LL and SC, see MIPS_HAS_LLSC
* in atomic_ops.h)
* - __CPU_MIPS64 (mips64 arch., in 64 bit mode: long and
* void* are 64 bits)
* - __CPU_MIPS2 or __CPU_MIPS && MIPS_HAS_LLSC && NOSMP
* (if __CPU_MIPS64 is not defined)
* Config defines:
* - NOSMP (in NOSMP mode it will also work on mips isa 1 CPUs that support
* LL and SC, see MIPS_HAS_LLSC in atomic_ops.h)
* - __CPU_MIPS64 (mips64 arch., in 64 bit mode: long and void* are 64 bits)
* - __CPU_MIPS2 or __CPU_MIPS && MIPS_HAS_LLSC && NOSMP (if __CPU_MIPS64 is not defined)
* @ingroup atomic
*/
/*
* History:
* --------

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,32 +14,35 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* include file for native (asm) atomic operations and memory barriers
* WARNING: atomic ops do not include memory barriers
* See atomic_ops.h for more info.
* Expects atomic_t to be defined (#include "atomic_common.h")
/**
* @file
* @brief Native (asm) atomic operations and memory barriers
*
* Native (assembler) atomic operations and memory barriers.
* \warning atomic ops do not include memory barriers, see atomic_ops.h for
* more info. Expects atomic_t to be defined (#include "atomic_common.h")
*
* Config defines: CC_GCC_LIKE_ASM - the compiler support gcc style
* inline asm
* NOSMP - the code will be a little faster, but not SMP
* safe
* __CPU_i386, __CPU_x86_64, X86_OOSTORE - see
* atomic_x86.h
* __CPU_mips, __CPU_mips2, __CPU_mips64, MIPS_HAS_LLSC - see
* atomic_mip2.h
* __CPU_ppc, __CPU_ppc64 - see atomic_ppc.h
* __CPU_sparc - see atomic_sparc.h
* __CPU_sparc64, SPARC64_MODE - see atomic_sparc64.h
* __CPU_arm, __CPU_arm6 - see atomic_arm.h
* __CPU_alpha - see atomic_alpha.h
* Config defines:
* - CC_GCC_LIKE_ASM - the compiler support gcc style inline asm
* - NOSMP - the code will be a little faster, but not SMP safe
* - __CPU_i386, __CPU_x86_64, X86_OOSTORE - see atomic_x86.h
* - __CPU_mips, __CPU_mips2, __CPU_mips64, MIPS_HAS_LLSC - see atomic_mip2.h
* - __CPU_ppc, __CPU_ppc64 - see atomic_ppc.h
* - __CPU_sparc - see atomic_sparc.h
* - __CPU_sparc64, SPARC64_MODE - see atomic_sparc64.h
* - __CPU_arm, __CPU_arm6 - see atomic_arm.h
* - __CPU_alpha - see atomic_alpha.h
* @ingroup atomic
*/
/*
* History:
* --------
* 2006-03-08 created by andrei
* 2007-05-13 split from atomic_ops.h (andrei)
*/
#ifndef __atomic_native
#define __atomic_native

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,16 +14,22 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic operations and memory barriers (powerpc and powerpc64 versions)
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
* WARNING: not tested on ppc64
/**
* @file
* @brief Atomic operations and memory barriers (PowerPC and PowerPC64 versions)
*
* Atomic operations and memory barriers (PowerPC and PowerPC64 versions)
* \warning atomic ops do not include memory barriers see atomic_ops.h for
* more details.
* \warning not tested on ppc64
*
* Config defines: - NOSMP
* - __CPU_ppc64 (powerpc64 w/ 64 bits long and void*)
* - __CPU_ppc (powerpc or powerpc64 32bit mode)
* Config defines:
* - NOSMP
* - __CPU_ppc64 (powerpc64 w/ 64 bits long and void*)
* - __CPU_ppc (powerpc or powerpc64 32bit mode)
* @ingroup atomic
*/
/*
* History:
* --------
@ -39,6 +43,7 @@
* membar_*_atomic_setget (andrei)
*/
#ifndef _atomic_ppc_h
#define _atomic_ppc_h

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,11 +14,16 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* memory barriers for sparc32 ( version < v 9))
* see atomic_ops.h for more details
/**
* @file
* @brief Memory barriers for SPARC32 ( version < v 9))
*
* Memory barriers for SPARC32 ( version < v 9)), see atomic_ops.h for more
* details.
*
* Config defines: NOSMP
* Config defines:
* - NOSMP
* @ingroup atomic
*/
/*

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,15 +14,19 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic operations and memory barriers (sparc64 version, 32 and 64 bit modes)
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
/**
* @file
* @brief Atomic operations and memory barriers (SPARC64 version, 32 and 64 bit modes)
*
* Atomic operations and memory barriers (SPARC64 version, 32 and 64 bit modes)
* \warning atomic ops do not include memory barriers see atomic_ops.h for
* more details.
*
* Config defs: - SPARC64_MODE (if defined long is assumed to be 64 bits
* else long & void* are assumed to be 32 for
* sparc32plus code)
* - NOSMP
* Config defines:
* - SPARC64_MODE (if defined long is assumed to be 64 bits else long & void*
* are assumed to be 32 for SPARC32plus code)
* - NOSMP
* @ingroup atomic
*/
/*

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,20 +14,24 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic operations and memory barriers implemented using locks
* (for architectures not yet supported via inline asm)
/**
* @file
* @brief Atomic operations and memory barriers implemented using locks
*
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
* Atomic operations and memory barriers implemented using locks
* (for architectures not yet supported via inline assembler).
*
* Config defs: - NOSMP (membars are null in this case)
* - HAVE_ASM_INLINE_MEMBAR (membars arleady defined =>
* use them)
* - HAVE_ASM_INLINE_ATOMIC_OPS (atomic ops already defined
* => don't redefine them)
* \warning atomic ops do not include memory barriers, see atomic_ops.h
* for more details
*
* Config defines:
* - NOSMP (membars are null in this case)
* - HAVE_ASM_INLINE_MEMBAR (membars already defined => use them)
* - HAVE_ASM_INLINE_ATOMIC_OPS (atomic ops already defined => don't
* redefine them)
* @ingroup atomic
*/
/*
* History:
* --------
@ -40,6 +42,7 @@
* membar_*_atomic_setget (andrei)
*/
#ifndef _atomic_unknown_h
#define _atomic_unknown_h

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -16,19 +14,22 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** @file @brief
* atomic operations and memory barriers (x86 and x86_64/amd64 specific)
* WARNING: atomic ops do not include memory barriers
* see atomic_ops.h for more details
/**
* @file
* @brief Atomic operations and memory barriers (x86 and x86_64/amd64 specific)
*
* Atomic operations and memory barriers (x86 and x86_64/amd64 specific)
* \warning atomic ops do not include memory barriers, see atomic_ops.h for more
* details.
*
* Config defines: - NOSMP
* - X86_OOSTORE (out of order store, defined by default)
* - X86_64_OOSTORE, like X86_OOSTORE, but for x86_64 cpus,
* default off
* - __CPU_x86_64 (64 bit mode, long and void* is 64 bit and
* the cpu has all of the mfence, lfence
* and sfence instructions)
* - __CPU_i386 (486+, 32 bit)
* Config defines:
* - NOSMP
* - X86_OOSTORE (out of order store, defined by default)
* - X86_64_OOSTORE, like X86_OOSTORE, but for x86_64 CPUs, default off
* - __CPU_x86_64 (64 bit mode, long and void* is 64 bit and the CPU has all
* of the mfence, lfence and sfence instructions)
* - __CPU_i386 (486+, 32 bit)
* @ingroup atomic
*/
/*
* History:

@ -21,7 +21,7 @@
* \brief SIP-router core :: Atomic operations and memory barriers
* \ingroup core
* Module: \ref core
* See \ref atomicops
* See \ref atomic
*/
/*

@ -40,8 +40,8 @@
#define __atomic_ops_init_h
/*! \brief init atomic ops */
int init_atomic_ops();
int init_atomic_ops(void);
/*! \brief destroy atomic ops (e.g. frees the locks, if locks are used) */
void destroy_atomic_ops();
void destroy_atomic_ops(void);
#endif

@ -0,0 +1,7 @@
/* this file is autogenerated by make autover.h
* DO NOT EDIT IT
*/
#define REPO_VER "e75049"
#define REPO_HASH "e75049"
#define REPO_STATE ""

@ -860,7 +860,7 @@ inline static int q_base64_dec(unsigned char* src, int slen,
}
/*! \brief inits internal lookup tables */
int init_basex();
int init_basex(void);
#endif /* _basex_h */

@ -18,6 +18,7 @@
* History
* -------
* 2010-04-26 Initial version (Miklos)
* 2011-01-05 bit_test_and_reset added (Miklos)
*/
/* Bit test functions:
@ -30,6 +31,11 @@
* in a bitstring pointed by addr, and sets
* the bit at the given offset.
*
* - int bit_test_and_reset(int offset, unsigned int *addr)
* Returns the bit found at offset position
* in a bitstring pointed by addr, and resets
* the bit at the given offset.
*
* Note that 0 <= offset <= 128, Make sure that addr points to
* a large enough memory area.
*/
@ -86,6 +92,24 @@ static inline int bit_test_and_set(int offset, unsigned int *addr)
return (int)v;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and resets it to 0.
* Note that the CPU can access 4 bytes starting from addr,
* hence 0 <= offset < 128 holds. Make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_reset(int offset, unsigned int *addr)
{
unsigned char v;
asm volatile(
" btr %2, %1 \n\t"
" setc %0 \n\t"
: "=qm" (v) : "m" (*addr), "r" (offset)
);
return (int)v;
}
#else /* BIT_TEST_ASM */
/* Returns the bit found at offset position in the bitstring
@ -116,6 +140,24 @@ static inline int bit_test_and_set(int offset, unsigned int *addr)
return res;
}
/* Returns the bit found at offset position in the bitstring
* pointed by addr and resets it to 0.
* Note that offset can be grater than 32, make sure that addr points
* to a memory area that is large enough.
*/
static inline int bit_test_and_reset(int offset, unsigned int *addr)
{
unsigned int *i;
int mask, res;
i = addr + offset/32;
mask = 1U << (offset % 32);
res = ((*i) & mask) ? 1 : 0;
(*i) &= ~mask;
return res;
}
#endif /* BIT_TEST_ASM */
#endif /* #ifndef _BIT_TEST_H */

@ -158,7 +158,7 @@
} include_stack[MAX_INCLUDE_DEPTH];
static int include_stack_ptr = 0;
static int sr_push_yy_state(char *fin);
static int sr_push_yy_state(char *fin, int mode);
static int sr_pop_yy_state();
static struct sr_yy_fname {
@ -177,7 +177,7 @@
/* start conditions */
%x STRING1 STRING2 STR_BETWEEN COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P
%x PVARID INCLF
%x PVARID INCLF IMPTF
%x LINECOMMENT DEFINE_ID DEFINE_EOL DEFINE_DATA IFDEF_ID IFDEF_EOL IFDEF_SKIP
/* config script types : #!SER or #!KAMAILIO or #!MAX_COMPAT */
@ -200,7 +200,9 @@ SEND_TCP send_tcp
LOG log
ERROR error
ROUTE route
ROUTE_REQUEST request_route
ROUTE_FAILURE failure_route
ROUTE_REPLY reply_route
ROUTE_ONREPLY onreply_route
ROUTE_BRANCH branch_route
ROUTE_SEND onsend_route
@ -235,6 +237,8 @@ STRIP "strip"
STRIP_TAIL "strip_tail"
SET_USERPHONE "userphone"
APPEND_BRANCH "append_branch"
REMOVE_BRANCH "remove_branch"
CLEAR_BRANCHES "clear_branches"
IF "if"
ELSE "else"
SET_ADV_ADDRESS "set_advertised_address"
@ -249,7 +253,8 @@ CASE "case"
DEFAULT "default"
WHILE "while"
INCLUDEFILE "include_file"
CFG_SELECT "cfg_select"
CFG_RESET "cfg_reset"
/*ACTION LVALUES*/
URIHOST "uri:host"
@ -334,10 +339,12 @@ AVP_PREF (([ft][rud]?)|g)\.
/* config vars. */
DEBUG debug
FORK fork
FORK_DELAY fork_delay
LOGSTDERROR log_stderror
LOGFACILITY log_facility
LOGNAME log_name
LISTEN listen
ADVERTISE advertise|ADVERTISE
ALIAS alias
SR_AUTO_ALIASES auto_aliases
DNS dns
@ -365,6 +372,8 @@ DNS_CACHE_MAX_TTL dns_cache_max_ttl
DNS_CACHE_MEM dns_cache_mem
DNS_CACHE_GC_INT dns_cache_gc_interval
DNS_CACHE_DEL_NONEXP dns_cache_del_nonexp|dns_cache_delete_nonexpired
/* ipv6 auto bind */
AUTO_BIND_IPV6 auto_bind_ipv6
/* blacklist */
DST_BLST_INIT dst_blacklist_init
USE_DST_BLST use_dst_blacklist
@ -380,13 +389,18 @@ DST_BLST_SCTP_IMASK dst_blacklist_sctp_imask
PORT port
STAT statistics
MAXBUFFER maxbuffer
SQL_BUFFER_SIZE sql_buffer_size
CHILDREN children
SOCKET_WORKERS socket_workers
CHECK_VIA check_via
PHONE2TEL phone2tel
SYN_BRANCH syn_branch
MEMLOG "memlog"|"mem_log"
MEMDBG "memdbg"|"mem_dbg"
MEMSUM "mem_summary"
MEMSAFETY "mem_safety"
MEMJOIN "mem_join"
CORELOG "corelog"|"core_log"
SIP_WARNING sip_warning
SERVER_SIGNATURE server_signature
SERVER_HEADER server_header
@ -405,6 +419,7 @@ TCP_CONNECT_TIMEOUT "tcp_connect_timeout"
TCP_CON_LIFETIME "tcp_connection_lifetime"
TCP_POLL_METHOD "tcp_poll_method"
TCP_MAX_CONNECTIONS "tcp_max_connections"
TLS_MAX_CONNECTIONS "tls_max_connections"
TCP_NO_CONNECT "tcp_no_connect"
TCP_SOURCE_IPV4 "tcp_source_ipv4"
TCP_SOURCE_IPV6 "tcp_source_ipv6"
@ -424,6 +439,7 @@ TCP_OPT_KEEPINTVL "tcp_keepintvl"
TCP_OPT_KEEPCNT "tcp_keepcnt"
TCP_OPT_CRLF_PING "tcp_crlf_ping"
TCP_OPT_ACCEPT_NO_CL "tcp_accept_no_cl"
TCP_CLONE_RCVBUF "tcp_clone_rcvbuf"
DISABLE_TLS "disable_tls"|"tls_disable"
ENABLE_TLS "enable_tls"|"tls_enable"
TLSLOG "tlslog"|"tls_log"
@ -479,6 +495,9 @@ TOS "tos"
PMTU_DISCOVERY "pmtu_discovery"
KILL_TIMEOUT "exit_timeout"|"ser_kill_timeout"
MAX_WLOOPS "max_while_loops"
PVBUFSIZE "pv_buffer_size"
PVBUFSLOTS "pv_buffer_slots"
HTTP_REPLY_HACK "http_reply_hack"
/* stun config variables */
STUN_REFRESH_INTERVAL "stun_refresh_interval"
@ -487,6 +506,12 @@ STUN_ALLOW_FP "stun_allow_fp"
SERVER_ID "server_id"
LATENCY_LOG latency_log
LATENCY_LIMIT_DB latency_limit_db
LATENCY_LIMIT_ACTION latency_limit_action
MSG_TIME msg_time
CFG_DESCRIPTION "description"|"descr"|"desc"
LOADMODULE loadmodule
@ -542,16 +567,28 @@ COM_LINE #
COM_START "/\*"
COM_END "\*/"
/* start of pre-processing directives */
PREP_START "#!"|"!!"
DEFINE "define"|"def"
IFDEF ifdef
IFNDEF ifndef
ENDIF endif
TRYDEF "trydefine"|"trydef"
REDEF "redefine"|"redef"
/* else is already defined */
EAT_ABLE [\ \t\b\r]
/* pre-processing blocks */
SUBST subst
SUBSTDEF substdef
SUBSTDEFS substdefs
/* include files */
INCLUDEFILE "include_file"
IMPORTFILE "import_file"
%%
@ -581,8 +618,10 @@ SUBST subst
<INITIAL>{AVPFLAGS_DECL} { count(); yylval.strval=yytext; return AVPFLAGS_DECL; }
<INITIAL>{MSGLEN} { count(); yylval.strval=yytext; return MSGLEN; }
<INITIAL>{ROUTE} { count(); yylval.strval=yytext; return ROUTE; }
<INITIAL>{ROUTE_REQUEST} { count(); yylval.strval=yytext; return ROUTE_REQUEST; }
<INITIAL>{ROUTE_ONREPLY} { count(); yylval.strval=yytext;
return ROUTE_ONREPLY; }
<INITIAL>{ROUTE_REPLY} { count(); yylval.strval=yytext; return ROUTE_REPLY; }
<INITIAL>{ROUTE_FAILURE} { count(); yylval.strval=yytext;
return ROUTE_FAILURE; }
<INITIAL>{ROUTE_BRANCH} { count(); yylval.strval=yytext; return ROUTE_BRANCH; }
@ -602,6 +641,10 @@ SUBST subst
<INITIAL>{STRIP_TAIL} { count(); yylval.strval=yytext; return STRIP_TAIL; }
<INITIAL>{APPEND_BRANCH} { count(); yylval.strval=yytext;
return APPEND_BRANCH; }
<INITIAL>{REMOVE_BRANCH} { count(); yylval.strval=yytext;
return REMOVE_BRANCH; }
<INITIAL>{CLEAR_BRANCHES} { count(); yylval.strval=yytext;
return CLEAR_BRANCHES; }
<INITIAL>{SET_USERPHONE} { count(); yylval.strval=yytext;
return SET_USERPHONE; }
<INITIAL>{FORCE_RPORT} { count(); yylval.strval=yytext; return FORCE_RPORT; }
@ -638,6 +681,13 @@ SUBST subst
<INITIAL>{WHILE} { count(); yylval.strval=yytext; return WHILE; }
<INITIAL>{INCLUDEFILE} { count(); BEGIN(INCLF); }
<INITIAL>{PREP_START}{INCLUDEFILE} { count(); BEGIN(INCLF); }
<INITIAL>{IMPORTFILE} { count(); BEGIN(IMPTF); }
<INITIAL>{PREP_START}{IMPORTFILE} { count(); BEGIN(IMPTF); }
<INITIAL>{CFG_SELECT} { count(); yylval.strval=yytext; return CFG_SELECT; }
<INITIAL>{CFG_RESET} { count(); yylval.strval=yytext; return CFG_RESET; }
<INITIAL>{URIHOST} { count(); yylval.strval=yytext; return URIHOST; }
<INITIAL>{URIPORT} { count(); yylval.strval=yytext; return URIPORT; }
@ -664,10 +714,12 @@ SUBST subst
<INITIAL>{DEBUG} { count(); yylval.strval=yytext; return DEBUG_V; }
<INITIAL>{FORK} { count(); yylval.strval=yytext; return FORK; }
<INITIAL>{FORK_DELAY} { count(); yylval.strval=yytext; return FORK_DELAY; }
<INITIAL>{LOGSTDERROR} { yylval.strval=yytext; return LOGSTDERROR; }
<INITIAL>{LOGFACILITY} { yylval.strval=yytext; return LOGFACILITY; }
<INITIAL>{LOGNAME} { yylval.strval=yytext; return LOGNAME; }
<INITIAL>{LISTEN} { count(); yylval.strval=yytext; return LISTEN; }
<INITIAL>{ADVERTISE} { count(); yylval.strval=yytext; return ADVERTISE; }
<INITIAL>{ALIAS} { count(); yylval.strval=yytext; return ALIAS; }
<INITIAL>{SR_AUTO_ALIASES} { count(); yylval.strval=yytext;
return SR_AUTO_ALIASES; }
@ -717,6 +769,8 @@ SUBST subst
return DNS_CACHE_GC_INT; }
<INITIAL>{DNS_CACHE_DEL_NONEXP} { count(); yylval.strval=yytext;
return DNS_CACHE_DEL_NONEXP; }
<INITIAL>{AUTO_BIND_IPV6} { count(); yylval.strval=yytext;
return AUTO_BIND_IPV6; }
<INITIAL>{DST_BLST_INIT} { count(); yylval.strval=yytext;
return DST_BLST_INIT; }
<INITIAL>{USE_DST_BLST} { count(); yylval.strval=yytext;
@ -738,13 +792,18 @@ SUBST subst
<INITIAL>{PORT} { count(); yylval.strval=yytext; return PORT; }
<INITIAL>{STAT} { count(); yylval.strval=yytext; return STAT; }
<INITIAL>{MAXBUFFER} { count(); yylval.strval=yytext; return MAXBUFFER; }
<INITIAL>{SQL_BUFFER_SIZE} { count(); yylval.strval=yytext; return SQL_BUFFER_SIZE; }
<INITIAL>{CHILDREN} { count(); yylval.strval=yytext; return CHILDREN; }
<INITIAL>{SOCKET_WORKERS} { count(); yylval.strval=yytext; return SOCKET_WORKERS; }
<INITIAL>{CHECK_VIA} { count(); yylval.strval=yytext; return CHECK_VIA; }
<INITIAL>{PHONE2TEL} { count(); yylval.strval=yytext; return PHONE2TEL; }
<INITIAL>{SYN_BRANCH} { count(); yylval.strval=yytext; return SYN_BRANCH; }
<INITIAL>{MEMLOG} { count(); yylval.strval=yytext; return MEMLOG; }
<INITIAL>{MEMDBG} { count(); yylval.strval=yytext; return MEMDBG; }
<INITIAL>{MEMSUM} { count(); yylval.strval=yytext; return MEMSUM; }
<INITIAL>{MEMSAFETY} { count(); yylval.strval=yytext; return MEMSAFETY; }
<INITIAL>{MEMJOIN} { count(); yylval.strval=yytext; return MEMJOIN; }
<INITIAL>{CORELOG} { count(); yylval.strval=yytext; return CORELOG; }
<INITIAL>{SIP_WARNING} { count(); yylval.strval=yytext; return SIP_WARNING; }
<INITIAL>{USER} { count(); yylval.strval=yytext; return USER; }
<INITIAL>{GROUP} { count(); yylval.strval=yytext; return GROUP; }
@ -765,6 +824,8 @@ SUBST subst
return TCP_POLL_METHOD; }
<INITIAL>{TCP_MAX_CONNECTIONS} { count(); yylval.strval=yytext;
return TCP_MAX_CONNECTIONS; }
<INITIAL>{TLS_MAX_CONNECTIONS} { count(); yylval.strval=yytext;
return TLS_MAX_CONNECTIONS; }
<INITIAL>{TCP_NO_CONNECT} { count(); yylval.strval=yytext;
return TCP_NO_CONNECT; }
<INITIAL>{TCP_SOURCE_IPV4} { count(); yylval.strval=yytext;
@ -803,6 +864,8 @@ SUBST subst
return TCP_OPT_CRLF_PING; }
<INITIAL>{TCP_OPT_ACCEPT_NO_CL} { count(); yylval.strval=yytext;
return TCP_OPT_ACCEPT_NO_CL; }
<INITIAL>{TCP_CLONE_RCVBUF} { count(); yylval.strval=yytext;
return TCP_CLONE_RCVBUF; }
<INITIAL>{DISABLE_TLS} { count(); yylval.strval=yytext; return DISABLE_TLS; }
<INITIAL>{ENABLE_TLS} { count(); yylval.strval=yytext; return ENABLE_TLS; }
<INITIAL>{TLSLOG} { count(); yylval.strval=yytext; return TLS_PORT_NO; }
@ -907,7 +970,17 @@ SUBST subst
return KILL_TIMEOUT; }
<INITIAL>{MAX_WLOOPS} { count(); yylval.strval=yytext;
return MAX_WLOOPS; }
<INITIAL>{PVBUFSIZE} { count(); yylval.strval=yytext;
return PVBUFSIZE; }
<INITIAL>{PVBUFSLOTS} { count(); yylval.strval=yytext;
return PVBUFSLOTS; }
<INITIAL>{HTTP_REPLY_HACK} { count(); yylval.strval=yytext;
return HTTP_REPLY_HACK; }
<INITIAL>{SERVER_ID} { count(); yylval.strval=yytext; return SERVER_ID;}
<INITIAL>{LATENCY_LOG} { count(); yylval.strval=yytext; return LATENCY_LOG;}
<INITIAL>{MSG_TIME} { count(); yylval.strval=yytext; return MSG_TIME;}
<INITIAL>{LATENCY_LIMIT_DB} { count(); yylval.strval=yytext; return LATENCY_LIMIT_DB;}
<INITIAL>{LATENCY_LIMIT_ACTION} { count(); yylval.strval=yytext; return LATENCY_LIMIT_ACTION;}
<INITIAL>{CFG_DESCRIPTION} { count(); yylval.strval=yytext; return CFG_DESCRIPTION; }
<INITIAL>{LOADMODULE} { count(); yylval.strval=yytext; return LOADMODULE; }
<INITIAL>{LOADPATH} { count(); yylval.strval=yytext; return LOADPATH; }
@ -1195,7 +1268,11 @@ SUBST subst
<INITIAL>{COM_LINE}!{MAXCOMPAT_CFG}{CR} { count();
sr_cfg_compat=SR_COMPAT_MAX;}
<INITIAL>{COM_LINE}!{DEFINE}{EAT_ABLE}+ { count();
<INITIAL>{PREP_START}{DEFINE}{EAT_ABLE}+ { count(); pp_define_set_type(0);
state = DEFINE_S; BEGIN(DEFINE_ID); }
<INITIAL>{PREP_START}{TRYDEF}{EAT_ABLE}+ { count(); pp_define_set_type(1);
state = DEFINE_S; BEGIN(DEFINE_ID); }
<INITIAL>{PREP_START}{REDEF}{EAT_ABLE}+ { count(); pp_define_set_type(2);
state = DEFINE_S; BEGIN(DEFINE_ID); }
<DEFINE_ID>{ID} { count();
if (pp_define(yyleng, yytext)) return 1;
@ -1214,12 +1291,14 @@ SUBST subst
<DEFINE_DATA>. { count();
addstr(&s_buf, yytext, yyleng); }
<INITIAL>{COM_LINE}!{SUBST} { count(); return SUBST;}
<INITIAL>{PREP_START}{SUBST} { count(); return SUBST;}
<INITIAL>{PREP_START}{SUBSTDEF} { count(); return SUBSTDEF;}
<INITIAL>{PREP_START}{SUBSTDEFS} { count(); return SUBSTDEFS;}
<INITIAL,IFDEF_SKIP>{COM_LINE}!{IFDEF}{EAT_ABLE}+ { count();
<INITIAL,IFDEF_SKIP>{PREP_START}{IFDEF}{EAT_ABLE}+ { count();
if (pp_ifdef_type(1)) return 1;
state = IFDEF_S; BEGIN(IFDEF_ID); }
<INITIAL,IFDEF_SKIP>{COM_LINE}!{IFNDEF}{EAT_ABLE}+ { count();
<INITIAL,IFDEF_SKIP>{PREP_START}{IFNDEF}{EAT_ABLE}+ { count();
if (pp_ifdef_type(0)) return 1;
state = IFDEF_S; BEGIN(IFDEF_ID); }
<IFDEF_ID>{ID} { count();
@ -1227,9 +1306,9 @@ SUBST subst
state = IFDEF_EOL_S; BEGIN(IFDEF_EOL); }
<IFDEF_EOL>{EAT_ABLE}*{CR} { count(); pp_ifdef(); }
<INITIAL,IFDEF_SKIP>{COM_LINE}!{ELSE}{EAT_ABLE}*{CR} { count(); pp_else(); }
<INITIAL,IFDEF_SKIP>{PREP_START}{ELSE}{EAT_ABLE}*{CR} { count(); pp_else(); }
<INITIAL,IFDEF_SKIP>{COM_LINE}!{ENDIF}{EAT_ABLE}*{CR} { count();
<INITIAL,IFDEF_SKIP>{PREP_START}{ENDIF}{EAT_ABLE}*{CR} { count();
pp_endif(); }
/* we're in an ifdef that evaluated to false -- throw it away */
@ -1260,11 +1339,29 @@ SUBST subst
<INCLF>[ \t]* /* eat the whitespace */
<INCLF>[^ \t\n]+ { /* get the include file name */
if(sr_push_yy_state(yytext)<0)
memset(&s_buf, 0, sizeof(s_buf));
addstr(&s_buf, yytext, yyleng);
r = pp_subst_run(&s_buf.s);
if(sr_push_yy_state(s_buf.s, 0)<0)
{
LOG(L_CRIT, "error at %s line %d\n", (finame)?finame:"cfg", line);
exit(-1);
}
memset(&s_buf, 0, sizeof(s_buf));
BEGIN(INITIAL);
}
<IMPTF>[ \t]* /* eat the whitespace */
<IMPTF>[^ \t\n]+ { /* get the import file name */
memset(&s_buf, 0, sizeof(s_buf));
addstr(&s_buf, yytext, yyleng);
r = pp_subst_run(&s_buf.s);
if(sr_push_yy_state(s_buf.s, 1)<0)
{
LOG(L_CRIT, "error at %s line %d\n", (finame)?finame:"cfg", line);
exit(-1);
}
memset(&s_buf, 0, sizeof(s_buf));
BEGIN(INITIAL);
}
@ -1356,7 +1453,9 @@ static char* addstr(struct str_buf* dst_b, char* src, int len)
return dst_b->s;
error:
LOG(L_CRIT, "ERROR:lex:addstr: memory allocation error\n");
return 0;
LOG(L_CRIT, "ERROR:lex:addstr: try to increase pkg size with"
" -M parameter\n");
exit(-1);
}
@ -1427,14 +1526,16 @@ int yywrap()
return 1;
}
static int sr_push_yy_state(char *fin)
static int sr_push_yy_state(char *fin, int mode)
{
struct sr_yy_fname *fn = NULL;
FILE *fp = NULL;
char *x = NULL;
char *newf = NULL;
#define MAX_INCLUDE_FNAME 128
char fbuf[MAX_INCLUDE_FNAME];
int i, j, l;
char *tmpfiname = 0;
if ( include_stack_ptr >= MAX_INCLUDE_DEPTH )
{
@ -1444,12 +1545,12 @@ static int sr_push_yy_state(char *fin)
l = strlen(fin);
if(l>=MAX_INCLUDE_FNAME)
{
LOG(L_CRIT, "included file name too long\n");
LOG(L_CRIT, "included file name too long: %s\n", fin);
return -1;
}
if(fin[0]!='"' || fin[l-1]!='"')
{
LOG(L_CRIT, "included file name must be between quotes\n");
LOG(L_CRIT, "included file name must be between quotes: %s\n", fin);
return -1;
}
j = 0;
@ -1459,7 +1560,7 @@ static int sr_push_yy_state(char *fin)
case '\\':
if(i+1==l-1)
{
LOG(L_CRIT, "invalid escape in included file name\n");
LOG(L_CRIT, "invalid escape at %d in included file name: %s\n", i, fin);
return -1;
}
i++;
@ -1483,59 +1584,85 @@ static int sr_push_yy_state(char *fin)
}
if(j==0)
{
LOG(L_CRIT, "invalid included file name\n");
LOG(L_CRIT, "invalid included file name: %s\n", fin);
return -1;
}
fbuf[j] = '\0';
include_stack[include_stack_ptr].state = YY_CURRENT_BUFFER;
include_stack[include_stack_ptr].line = line;
include_stack[include_stack_ptr].column = column;
include_stack[include_stack_ptr].startline = startline;
include_stack[include_stack_ptr].startcolumn = startcolumn;
include_stack[include_stack_ptr].finame = finame;
include_stack_ptr++;
line=1;
column=1;
startline=1;
startcolumn=1;
fp = fopen(fbuf, "r" );
yyin = fopen(fbuf, "r" );
if ( ! yyin )
if ( ! fp )
{
finame = (finame==0)?cfg_file:finame;
if(finame==0 || fbuf[0]=='/')
tmpfiname = (finame==0)?cfg_file:finame;
if(tmpfiname==0 || fbuf[0]=='/')
{
LOG(L_CRIT, "cannot open included file: %s\n", fin);
return -1;
if(mode==0)
{
LOG(L_CRIT, "cannot open included file: %s\n", fin);
return -1;
} else {
LOG(L_DBG, "importing file ignored: %s\n", fin);
return 0;
}
}
x = strrchr(finame, '/');
if(x)
x = strrchr(tmpfiname, '/');
if(x==NULL)
{
newf = (char*)pkg_malloc(x-finame+strlen(fbuf)+2);
if(newf==0)
/* nothing else to try */
if(mode==0)
{
LOG(L_CRIT, "no more pkg\n");
LOG(L_CRIT, "cannot open included file: %s\n", fin);
return -1;
} else {
LOG(L_DBG, "importing file ignored: %s\n", fin);
return 0;
}
newf[0] = '\0';
strncat(newf, finame, x-finame);
strcat(newf, "/");
strcat(newf, fbuf);
}
yyin = fopen(newf, "r" );
if ( ! yyin )
newf = (char*)pkg_malloc(x-tmpfiname+strlen(fbuf)+2);
if(newf==0)
{
LOG(L_CRIT, "cannot open included file: %s (%s)\n", fbuf, newf);
LOG(L_CRIT, "no more pkg\n");
return -1;
}
newf[0] = '\0';
strncat(newf, tmpfiname, x-tmpfiname);
strcat(newf, "/");
strcat(newf, fbuf);
fp = fopen(newf, "r" );
if ( fp==NULL )
{
pkg_free(newf);
if(mode==0)
{
LOG(L_CRIT, "cannot open included file: %s (%s)\n", fbuf, newf);
return -1;
} else {
LOG(L_DBG, "importing file ignored: %s (%s)\n", fbuf, newf);
return 0;
}
}
LOG(L_DBG, "including file: %s (%s)\n", fbuf, newf);
} else {
newf = fbuf;
}
include_stack[include_stack_ptr].state = YY_CURRENT_BUFFER;
include_stack[include_stack_ptr].line = line;
include_stack[include_stack_ptr].column = column;
include_stack[include_stack_ptr].startline = startline;
include_stack[include_stack_ptr].startcolumn = startcolumn;
include_stack[include_stack_ptr].finame = finame;
include_stack_ptr++;
line=1;
column=1;
startline=1;
startcolumn=1;
yyin = fp;
/* make a copy in PKG if does not exist */
fn = sr_yy_fname_list;
while(fn!=0)
@ -1605,6 +1732,8 @@ static int sr_pop_yy_state()
#define MAX_DEFINES 256
static str pp_defines[MAX_DEFINES][2];
static int pp_num_defines = 0;
static int pp_define_type = 0;
static int pp_define_index = -1;
/* pp_ifdef_stack[i] is 1 if the ifdef test at depth i is either
* ifdef(defined), ifndef(undefined), or the opposite of these
@ -1626,66 +1755,111 @@ static int pp_lookup(int len, const char * text)
return -1;
}
int pp_define_set_type(int type)
{
pp_define_type = type;
return 0;
}
int pp_define(int len, const char * text)
{
int ppos;
LM_DBG("defining id: %.*s\n", len, text);
if (pp_num_defines == MAX_DEFINES) {
LOG(L_CRIT, "ERROR: too many defines -- adjust MAX_DEFINES\n");
return -1;
}
if (pp_lookup(len, text) >= 0) {
LOG(L_CRIT, "ERROR: already defined: %.*s\n", len, text);
return -1;
pp_define_index = -1;
ppos = pp_lookup(len, text);
if(ppos >= 0) {
if(pp_define_type==1) {
LOG(L_DBG, "ignoring - already defined: %.*s\n", len, text);
pp_define_index = -2;
return 0;
} else if(pp_define_type==2) {
LOG(L_DBG, "redefining: %.*s\n", len, text);
pp_define_index = ppos;
if(pp_defines[ppos][1].s != NULL) {
pkg_free(pp_defines[ppos][1].s);
pp_defines[ppos][1].len = 0;
pp_defines[ppos][1].s = NULL;
}
return 0;
} else {
LOG(L_CRIT, "ERROR: already defined: %.*s\n", len, text);
return -1;
}
}
pp_defines[pp_num_defines][0].len = len;
pp_defines[pp_num_defines][0].s = (char*)pkg_malloc(len+1);
if(pp_defines[pp_num_defines][0].s==NULL) {
LOG(L_CRIT, "no more memory to define: %.*s\n", len, text);
return -1;
}
memcpy(pp_defines[pp_num_defines][0].s, text, len);
pp_defines[pp_num_defines][1].len = 0;
pp_defines[pp_num_defines][1].s = NULL;
pp_define_index = pp_num_defines;
pp_num_defines++;
return 0;
}
int pp_define_set(int len, char *text)
int pp_define_set(int len, char *text)
{
int ppos;
if(pp_define_index == -2) {
/* #!trydef that should be ignored */
return 0;
}
if(pp_define_index < 0) {
/* invalid position in define table */
LOG(L_BUG, "BUG: the index in define table not set yet\n");
return -1;
}
if(len<=0) {
LOG(L_DBG, "no define value - ignoring\n");
return 0;
}
if (pp_num_defines == MAX_DEFINES) {
LOG(L_BUG, "BUG: setting define value, but no define id yet\n");
LOG(L_CRIT, "ERROR: too many defines -- adjust MAX_DEFINES\n");
return -1;
}
if (pp_num_defines == 0) {
LOG(L_CRIT, "ERROR: too many defines -- adjust MAX_DEFINES\n");
LOG(L_BUG, "BUG: setting define value, but no define id yet\n");
return -1;
}
if (pp_defines[pp_num_defines-1][0].s == NULL) {
ppos = pp_define_index;
if (pp_defines[ppos][0].s == NULL) {
LOG(L_BUG, "BUG: last define ID is null\n");
return -1;
}
if (pp_defines[pp_num_defines-1][1].s != NULL) {
LOG(L_BUG, "BUG: ID %.*s redefined\n",
pp_defines[pp_num_defines-1][0].len,
pp_defines[pp_num_defines-1][0].s);
if (pp_defines[ppos][1].s != NULL) {
LOG(L_BUG, "BUG: ID %.*s [%d] overwritten\n",
pp_defines[ppos][0].len,
pp_defines[ppos][0].s, ppos);
return -1;
}
pp_defines[pp_num_defines-1][1].len = len;
pp_defines[pp_num_defines-1][1].s = text;
pp_defines[ppos][1].len = len;
pp_defines[ppos][1].s = text;
LM_DBG("### setting define ID [%.*s] value [%.*s]\n",
pp_defines[pp_num_defines-1][0].len,
pp_defines[pp_num_defines-1][0].s,
pp_defines[pp_num_defines-1][1].len,
pp_defines[pp_num_defines-1][1].s);
pp_defines[ppos][0].len,
pp_defines[ppos][0].s,
pp_defines[ppos][1].len,
pp_defines[ppos][1].s);
return 0;
}
static str *pp_define_get(int len, const char * text)
static str *pp_define_get(int len, const char * text)
{
str var = {(char *)text, len};
int i;

183
cfg.y

@ -101,7 +101,7 @@
* 2010-02-17 added blacklist imask (DST_BLST_*_IMASK) support (andrei)
*/
%expect 5
%expect 6
%{
@ -111,6 +111,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
@ -142,6 +143,7 @@
#include "msg_translator.h"
#include "ppcfg.h"
#include "pvapi.h"
#include "config.h"
#include "cfg_core.h"
#include "cfg/cfg.h"
@ -163,6 +165,11 @@
if (rt!=ONSEND_ROUTE) yyerror( s " allowed only in onsend_routes");\
}while(0)
#ifdef USE_IPV6
#define IF_AUTO_BIND_IPV6(x) x
#else
#define IF_AUTO_BIND_IPV6(x) warn("IPV6 support not compiled");
#endif
#ifdef USE_DNS_CACHE
#define IF_DNS_CACHE(x) x
@ -307,8 +314,10 @@ extern char *finame;
%token LOG_TOK
%token ERROR
%token ROUTE
%token ROUTE_REQUEST
%token ROUTE_FAILURE
%token ROUTE_ONREPLY
%token ROUTE_REPLY
%token ROUTE_BRANCH
%token ROUTE_SEND
%token ROUTE_EVENT
@ -321,6 +330,8 @@ extern char *finame;
%token STRIP_TAIL
%token SET_USERPHONE
%token APPEND_BRANCH
%token REMOVE_BRANCH
%token CLEAR_BRANCHES
%token SET_USER
%token SET_USERPASS
%token SET_PORT
@ -347,6 +358,8 @@ extern char *finame;
%token CASE
%token DEFAULT
%token WHILE
%token CFG_SELECT
%token CFG_RESET
%token URIHOST
%token URIPORT
%token MAX_LEN
@ -382,10 +395,12 @@ extern char *finame;
/* config vars. */
%token DEBUG_V
%token FORK
%token FORK_DELAY
%token LOGSTDERROR
%token LOGFACILITY
%token LOGNAME
%token LISTEN
%token ADVERTISE
%token ALIAS
%token SR_AUTO_ALIASES
%token DNS
@ -412,6 +427,10 @@ extern char *finame;
%token DNS_CACHE_MEM
%token DNS_CACHE_GC_INT
%token DNS_CACHE_DEL_NONEXP
/* ipv6 auto bind */
%token AUTO_BIND_IPV6
/*blacklist*/
%token DST_BLST_INIT
%token USE_DST_BLST
@ -426,12 +445,16 @@ extern char *finame;
%token PORT
%token STAT
%token CHILDREN
%token SOCKET_WORKERS
%token CHECK_VIA
%token PHONE2TEL
%token SYN_BRANCH
%token MEMLOG
%token MEMDBG
%token MEMSUM
%token MEMSAFETY
%token MEMJOIN
%token CORELOG
%token SIP_WARNING
%token SERVER_SIGNATURE
%token SERVER_HEADER
@ -441,6 +464,7 @@ extern char *finame;
%token LOADPATH
%token MODPARAM
%token MAXBUFFER
%token SQL_BUFFER_SIZE
%token USER
%token GROUP
%token CHROOT
@ -454,6 +478,7 @@ extern char *finame;
%token TCP_CON_LIFETIME
%token TCP_POLL_METHOD
%token TCP_MAX_CONNECTIONS
%token TLS_MAX_CONNECTIONS
%token TCP_NO_CONNECT
%token TCP_SOURCE_IPV4
%token TCP_SOURCE_IPV6
@ -473,6 +498,7 @@ extern char *finame;
%token TCP_OPT_KEEPCNT
%token TCP_OPT_CRLF_PING
%token TCP_OPT_ACCEPT_NO_CL
%token TCP_CLONE_RCVBUF
%token DISABLE_TLS
%token ENABLE_TLS
%token TLSLOG
@ -531,8 +557,15 @@ extern char *finame;
%token PMTU_DISCOVERY
%token KILL_TIMEOUT
%token MAX_WLOOPS
%token PVBUFSIZE
%token PVBUFSLOTS
%token HTTP_REPLY_HACK
%token CFG_DESCRIPTION
%token SERVER_ID
%token LATENCY_LOG
%token LATENCY_LIMIT_DB
%token LATENCY_LIMIT_ACTION
%token MSG_TIME
%token FLAGS_DECL
%token AVPFLAGS_DECL
@ -557,6 +590,8 @@ extern char *finame;
/*pre-processor*/
%token SUBST
%token SUBSTDEF
%token SUBSTDEFS
/* operators, C like precedence */
%right EQUAL
@ -804,6 +839,8 @@ assign_stm:
| DEBUG_V EQUAL error { yyerror("number expected"); }
| FORK EQUAL NUMBER { dont_fork= ! $3; }
| FORK EQUAL error { yyerror("boolean value expected"); }
| FORK_DELAY EQUAL NUMBER { set_fork_delay($3); }
| FORK_DELAY EQUAL error { yyerror("number expected"); }
| LOGSTDERROR EQUAL NUMBER { if (!config_check) log_stderr=$3; }
| LOGSTDERROR EQUAL error { yyerror("boolean value expected"); }
| LOGFACILITY EQUAL ID {
@ -864,6 +901,8 @@ assign_stm:
| DNS_CACHE_GC_INT error { yyerror("boolean value expected"); }
| DNS_CACHE_DEL_NONEXP EQUAL NUMBER { IF_DNS_CACHE(default_core_cfg.dns_cache_del_nonexp=$3); }
| DNS_CACHE_DEL_NONEXP error { yyerror("boolean value expected"); }
| AUTO_BIND_IPV6 EQUAL NUMBER {IF_AUTO_BIND_IPV6(auto_bind_ipv6 = $3);}
| AUTO_BIND_IPV6 error { yyerror("boolean value expected"); }
| DST_BLST_INIT EQUAL NUMBER { IF_DST_BLACKLIST(dst_blacklist_init=$3); }
| DST_BLST_INIT error { yyerror("boolean value expected"); }
| USE_DST_BLST EQUAL NUMBER {
@ -904,9 +943,13 @@ assign_stm:
}
| MAXBUFFER EQUAL NUMBER { maxbuffer=$3; }
| MAXBUFFER EQUAL error { yyerror("number expected"); }
| SQL_BUFFER_SIZE EQUAL NUMBER { sql_buffer_size=$3; }
| SQL_BUFFER_SIZE EQUAL error { yyerror("number expected"); }
| PORT EQUAL error { yyerror("number expected"); }
| CHILDREN EQUAL NUMBER { children_no=$3; }
| CHILDREN EQUAL error { yyerror("number expected"); }
| SOCKET_WORKERS EQUAL NUMBER { socket_workers=$3; }
| SOCKET_WORKERS EQUAL error { yyerror("number expected"); }
| CHECK_VIA EQUAL NUMBER { check_via=$3; }
| CHECK_VIA EQUAL error { yyerror("boolean value expected"); }
| PHONE2TEL EQUAL NUMBER { phone2tel=$3; }
@ -919,6 +962,12 @@ assign_stm:
| MEMDBG EQUAL error { yyerror("int value expected"); }
| MEMSUM EQUAL intno { default_core_cfg.mem_summary=$3; }
| MEMSUM EQUAL error { yyerror("int value expected"); }
| MEMSAFETY EQUAL intno { default_core_cfg.mem_safety=$3; }
| MEMSAFETY EQUAL error { yyerror("int value expected"); }
| MEMJOIN EQUAL intno { default_core_cfg.mem_join=$3; }
| MEMJOIN EQUAL error { yyerror("int value expected"); }
| CORELOG EQUAL intno { default_core_cfg.corelog=$3; }
| CORELOG EQUAL error { yyerror("int value expected"); }
| SIP_WARNING EQUAL NUMBER { sip_warning=$3; }
| SIP_WARNING EQUAL error { yyerror("boolean value expected"); }
| USER EQUAL STRING {
@ -965,7 +1014,7 @@ assign_stm:
| TCP_ACCEPT_ALIASES EQUAL error { yyerror("boolean value expected"); }
| TCP_CHILDREN EQUAL NUMBER {
#ifdef USE_TCP
tcp_children_no=$3;
tcp_cfg_children_no=$3;
#else
warn("tcp support not compiled in");
#endif
@ -1035,6 +1084,14 @@ assign_stm:
#endif
}
| TCP_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
| TLS_MAX_CONNECTIONS EQUAL NUMBER {
#ifdef USE_TLS
tls_max_connections=$3;
#else
warn("tls support not compiled in");
#endif
}
| TLS_MAX_CONNECTIONS EQUAL error { yyerror("number expected"); }
| TCP_NO_CONNECT EQUAL NUMBER {
#ifdef USE_TCP
tcp_default_cfg.no_connect=$3;
@ -1195,6 +1252,14 @@ assign_stm:
#endif
}
| TCP_OPT_ACCEPT_NO_CL EQUAL error { yyerror("boolean value expected"); }
| TCP_CLONE_RCVBUF EQUAL NUMBER {
#ifdef USE_TCP
tcp_set_clone_rcvbuf($3);
#else
warn("tcp support not compiled in");
#endif
}
| TCP_CLONE_RCVBUF EQUAL error { yyerror("number expected"); }
| DISABLE_TLS EQUAL NUMBER {
#ifdef USE_TLS
tls_disable=$3;
@ -1483,6 +1548,20 @@ assign_stm:
}
free_socket_id_lst($3);
}
| LISTEN EQUAL id_lst ADVERTISE listen_id COLON NUMBER {
for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) {
if (add_listen_advertise_iface( lst_tmp->addr_lst->name,
lst_tmp->addr_lst->next,
lst_tmp->port, lst_tmp->proto,
$5, $7,
lst_tmp->flags)!=0) {
LOG(L_CRIT, "ERROR: cfg. parser: failed to add listen"
" address\n");
break;
}
}
free_socket_id_lst($3);
}
| LISTEN EQUAL error { yyerror("ip address, interface name or"
" hostname expected"); }
| ALIAS EQUAL id_lst {
@ -1570,6 +1649,33 @@ assign_stm:
}
| MCAST_TTL EQUAL error { yyerror("number expected"); }
| TOS EQUAL NUMBER { tos=$3; }
| TOS EQUAL ID { if (strcasecmp($3,"IPTOS_LOWDELAY")) {
tos=IPTOS_LOWDELAY;
} else if (strcasecmp($3,"IPTOS_THROUGHPUT")) {
tos=IPTOS_THROUGHPUT;
} else if (strcasecmp($3,"IPTOS_RELIABILITY")) {
tos=IPTOS_RELIABILITY;
#if defined(IPTOS_MINCOST)
} else if (strcasecmp($3,"IPTOS_MINCOST")) {
tos=IPTOS_MINCOST;
#endif
#if defined(IPTOS_LOWCOST)
} else if (strcasecmp($3,"IPTOS_LOWCOST")) {
tos=IPTOS_LOWCOST;
#endif
} else {
yyerror("invalid tos value - allowed: "
"IPTOS_LOWDELAY,IPTOS_THROUGHPUT,"
"IPTOS_RELIABILITY"
#if defined(IPTOS_LOWCOST)
",IPTOS_LOWCOST"
#endif
#if !defined(IPTOS_MINCOST)
",IPTOS_MINCOST"
#endif
"\n");
}
}
| TOS EQUAL error { yyerror("number expected"); }
| PMTU_DISCOVERY EQUAL NUMBER { pmtu_discovery=$3; }
| PMTU_DISCOVERY error { yyerror("number expected"); }
@ -1577,6 +1683,12 @@ assign_stm:
| KILL_TIMEOUT EQUAL error { yyerror("number expected"); }
| MAX_WLOOPS EQUAL NUMBER { default_core_cfg.max_while_loops=$3; }
| MAX_WLOOPS EQUAL error { yyerror("number expected"); }
| PVBUFSIZE EQUAL NUMBER { pv_set_buffer_size($3); }
| PVBUFSIZE EQUAL error { yyerror("number expected"); }
| PVBUFSLOTS EQUAL NUMBER { pv_set_buffer_slots($3); }
| PVBUFSLOTS EQUAL error { yyerror("number expected"); }
| HTTP_REPLY_HACK EQUAL NUMBER { http_reply_hack=$3; }
| HTTP_REPLY_HACK EQUAL error { yyerror("boolean value expected"); }
| STUN_REFRESH_INTERVAL EQUAL NUMBER { IF_STUN(stun_refresh_interval=$3); }
| STUN_REFRESH_INTERVAL EQUAL error{ yyerror("number expected"); }
| STUN_ALLOW_STUN EQUAL NUMBER { IF_STUN(stun_allow_stun=$3); }
@ -1584,6 +1696,14 @@ assign_stm:
| STUN_ALLOW_FP EQUAL NUMBER { IF_STUN(stun_allow_fp=$3) ; }
| STUN_ALLOW_FP EQUAL error{ yyerror("number expected"); }
| SERVER_ID EQUAL NUMBER { server_id=$3; }
| LATENCY_LOG EQUAL NUMBER { default_core_cfg.latency_log=$3; }
| LATENCY_LOG EQUAL error { yyerror("number expected"); }
| LATENCY_LIMIT_DB EQUAL NUMBER { default_core_cfg.latency_limit_db=$3; }
| LATENCY_LIMIT_DB EQUAL error { yyerror("number expected"); }
| LATENCY_LIMIT_ACTION EQUAL NUMBER { default_core_cfg.latency_limit_action=$3; }
| LATENCY_LIMIT_ACTION EQUAL error { yyerror("number expected"); }
| MSG_TIME EQUAL NUMBER { sr_msg_time=$3; }
| MSG_TIME EQUAL error { yyerror("number expected"); }
| UDP_MTU EQUAL NUMBER { default_core_cfg.udp_mtu=$3; }
| UDP_MTU EQUAL error { yyerror("number expected"); }
| FORCE_RPORT EQUAL NUMBER
@ -1635,6 +1755,16 @@ cfg_var:
| cfg_var_id DOT cfg_var_id EQUAL error {
yyerror("number or string expected");
}
| cfg_var_id LBRACK NUMBER RBRACK DOT cfg_var_id EQUAL NUMBER {
if (cfg_ginst_var_int($1, $3, $6, $8)) {
yyerror("variable cannot be added to the group instance");
}
}
| cfg_var_id LBRACK NUMBER RBRACK DOT cfg_var_id EQUAL STRING {
if (cfg_ginst_var_string($1, $3, $6, $8)) {
yyerror("variable cannot be added to the group instance");
}
}
;
module_stm:
@ -1754,8 +1884,13 @@ route_name: NUMBER {
| STRING { $$=$1; }
;
route_main: ROUTE { ; }
| ROUTE_REQUEST { ; }
;
route_stm:
ROUTE LBRACE actions RBRACE {
route_main LBRACE actions RBRACE {
#ifdef SHM_MEM
if (!shm_initialized() && init_shm()<0) {
yyerror("Can't initialize shared memory");
@ -1783,6 +1918,7 @@ route_stm:
push($6, &main_rt.rlist[i_tmp]);
}
| ROUTE error { yyerror("invalid route statement"); }
| ROUTE_REQUEST error { yyerror("invalid request_route statement"); }
;
failure_route_stm:
ROUTE_FAILURE LBRACE actions RBRACE {
@ -1815,8 +1951,14 @@ failure_route_stm:
| ROUTE_FAILURE error { yyerror("invalid failure_route statement"); }
;
route_reply_main: ROUTE_ONREPLY { ; }
| ROUTE_REPLY { ; }
;
onreply_route_stm:
ROUTE_ONREPLY LBRACE {rt=CORE_ONREPLY_ROUTE;} actions RBRACE {
route_reply_main LBRACE {rt=CORE_ONREPLY_ROUTE;} actions RBRACE {
#ifdef SHM_MEM
if (!shm_initialized() && init_shm()<0) {
yyerror("Can't initialize shared memory");
@ -1826,6 +1968,7 @@ onreply_route_stm:
push($4, &onreply_rt.rlist[DEFAULT_RT]);
}
| ROUTE_ONREPLY error { yyerror("invalid onreply_route statement"); }
| ROUTE_REPLY error { yyerror("invalid onreply_route statement"); }
| ROUTE_ONREPLY LBRACK route_name RBRACK
{rt=(*$3=='0' && $3[1]==0)?CORE_ONREPLY_ROUTE:TM_ONREPLY_ROUTE;}
LBRACE actions RBRACE {
@ -1938,6 +2081,10 @@ event_route_stm: ROUTE_EVENT LBRACK EVENT_RT_NAME RBRACK LBRACE actions RBRACE {
preprocess_stm:
SUBST STRING { if(pp_subst_add($2)<0) YYERROR; }
| SUBST error { yyerror("invalid subst preprocess statement"); }
| SUBSTDEF STRING { if(pp_substdef_add($2, 0)<0) YYERROR; }
| SUBSTDEF error { yyerror("invalid substdef preprocess statement"); }
| SUBSTDEFS STRING { if(pp_substdef_add($2, 1)<0) YYERROR; }
| SUBSTDEFS error { yyerror("invalid substdefs preprocess statement"); }
;
/*exp: rval_expr
@ -3010,6 +3157,7 @@ cmd:
| FORWARD_SCTP error { $$=0; yyerror("missing '(' or ')' ?"); }
| FORWARD_SCTP LPAREN error RPAREN { $$=0;
yyerror("bad forward_tls argument"); }
| SEND LPAREN RPAREN { $$=mk_action(SEND_T, 2, URIHOST_ST, 0, URIPORT_ST, 0); set_cfg_pos($$); }
| SEND LPAREN host RPAREN { $$=mk_action(SEND_T, 2, STRING_ST, $3, NUMBER_ST, 0); set_cfg_pos($$); }
| SEND LPAREN STRING RPAREN { $$=mk_action(SEND_T, 2, STRING_ST, $3, NUMBER_ST, 0); set_cfg_pos($$); }
| SEND LPAREN ip RPAREN { $$=mk_action(SEND_T, 2, IP_ST, (void*)$3, NUMBER_ST, 0); set_cfg_pos($$); }
@ -3018,6 +3166,7 @@ cmd:
| SEND LPAREN ip COMMA NUMBER RPAREN { $$=mk_action(SEND_T, 2, IP_ST, (void*)$3, NUMBER_ST, (void*)$5); set_cfg_pos($$); }
| SEND error { $$=0; yyerror("missing '(' or ')' ?"); }
| SEND LPAREN error RPAREN { $$=0; yyerror("bad send argument"); }
| SEND_TCP LPAREN RPAREN { $$=mk_action(SEND_TCP_T, 2, URIHOST_ST, 0, URIPORT_ST, 0); set_cfg_pos($$); }
| SEND_TCP LPAREN host RPAREN { $$=mk_action(SEND_TCP_T, 2, STRING_ST, $3, NUMBER_ST, 0); set_cfg_pos($$); }
| SEND_TCP LPAREN STRING RPAREN { $$=mk_action(SEND_TCP_T, 2, STRING_ST, $3, NUMBER_ST, 0); set_cfg_pos($$); }
| SEND_TCP LPAREN ip RPAREN { $$=mk_action(SEND_TCP_T, 2, IP_ST, (void*)$3, NUMBER_ST, 0); set_cfg_pos($$); }
@ -3152,6 +3301,17 @@ cmd:
NUMBER_ST, (void *)Q_UNSPECIFIED);
set_cfg_pos($$);
}
| REMOVE_BRANCH LPAREN intno RPAREN {
$$=mk_action(REMOVE_BRANCH_T, 1, NUMBER_ST, (void*)$3);
set_cfg_pos($$);
}
| REMOVE_BRANCH LPAREN RPAREN {
$$=mk_action(REMOVE_BRANCH_T, 0);
set_cfg_pos($$);
}
| REMOVE_BRANCH error { $$=0; yyerror("missing '(' or ')' ?"); }
| REMOVE_BRANCH LPAREN error RPAREN { $$=0; yyerror("bad argument, number expected"); }
| CLEAR_BRANCHES LPAREN RPAREN { $$=mk_action(CLEAR_BRANCHES_T, 0); set_cfg_pos($$); }
| SET_HOSTPORT LPAREN STRING RPAREN { $$=mk_action(SET_HOSTPORT_T, 1, STRING_ST, $3); set_cfg_pos($$); }
| SET_HOSTPORT error { $$=0; yyerror("missing '(' or ')' ?"); }
| SET_HOSTPORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
@ -3268,6 +3428,19 @@ cmd:
| SET_RPL_CLOSE {
$$=mk_action(SET_RPL_CLOSE_T, 0); set_cfg_pos($$);
}
| CFG_SELECT LPAREN STRING COMMA NUMBER RPAREN {
$$=mk_action(CFG_SELECT_T, 2, STRING_ST, $3, NUMBER_ST, (void*)$5); set_cfg_pos($$);
}
| CFG_SELECT LPAREN STRING COMMA rval_expr RPAREN {
$$=mk_action(CFG_SELECT_T, 2, STRING_ST, $3, RVE_ST, $5); set_cfg_pos($$);
}
| CFG_SELECT error { $$=0; yyerror("missing '(' or ')' ?"); }
| CFG_SELECT LPAREN error RPAREN { $$=0; yyerror("bad arguments, string and number expected"); }
| CFG_RESET LPAREN STRING RPAREN {
$$=mk_action(CFG_RESET_T, 1, STRING_ST, $3); set_cfg_pos($$);
}
| CFG_RESET error { $$=0; yyerror("missing '(' or ')' ?"); }
| CFG_RESET LPAREN error RPAREN { $$=0; yyerror("bad arguments, string expected"); }
| ID {mod_func_action = mk_action(MODULE0_T, 2, MODEXP_ST, NULL, NUMBER_ST,
0); } LPAREN func_params RPAREN {
mod_func_action->val[0].u.data =
@ -3276,8 +3449,10 @@ cmd:
if (mod_func_action->val[0].u.data == 0) {
if (find_export_record($1, mod_func_action->val[1].u.number, 0,
&u_tmp) ) {
LOG(L_ERR, "misused command %s\n", $1);
yyerror("Command cannot be used in the block\n");
} else {
LOG(L_ERR, "cfg. parser: failed to find command %s\n", $1);
yyerror("unknown command, missing loadmodule?\n");
}
free_mod_func_action(mod_func_action);

@ -43,6 +43,7 @@ int cfg_declare(char *group_name, cfg_def_t *def, void *values, int def_size,
{
int i, num, size, group_name_len;
cfg_mapping_t *mapping = NULL;
cfg_group_t *group;
int types;
/* check the number of the variables */
@ -61,6 +62,7 @@ int cfg_declare(char *group_name, cfg_def_t *def, void *values, int def_size,
for (i=0, size=0; i<num; i++) {
mapping[i].def = &(def[i]);
mapping[i].name_len = strlen(def[i].name);
mapping[i].pos = i;
/* record all the types for sanity checks */
types|=1 << CFG_VAR_MASK(def[i].type);
@ -139,27 +141,35 @@ int cfg_declare(char *group_name, cfg_def_t *def, void *values, int def_size,
goto error;
}
group_name_len = strlen(group_name);
/* check for duplicates */
if (cfg_lookup_group(group_name, group_name_len)) {
LOG(L_ERR, "ERROR: register_cfg_def(): "
"configuration group has been already declared: %s\n",
group_name);
goto error;
}
/* create a new group
I will allocate memory in shm mem for the variables later in a single block,
when we know the size of all the registered groups. */
if (!cfg_new_group(group_name, group_name_len, num, mapping, values, size, handle))
goto error;
/* The cfg variables are ready to use, let us set the handle
before passing the new definitions to the drivers.
We make the interface usable for the fixup functions
at this step */
at this step
cfg_set_group() and cfg_new_group() need the handle to be set because
they save its original value. */
*handle = values;
group_name_len = strlen(group_name);
/* check for duplicates */
if ((group = cfg_lookup_group(group_name, group_name_len))) {
if (group->dynamic != CFG_GROUP_UNKNOWN) {
/* conflict with another module/core group, or with a dynamic group */
LOG(L_ERR, "ERROR: register_cfg_def(): "
"configuration group has been already declared: %s\n",
group_name);
goto error;
}
/* An empty group is found which does not have any variable yet */
cfg_set_group(group, num, mapping, values, size, handle);
} else {
/* create a new group
I will allocate memory in shm mem for the variables later in a single block,
when we know the size of all the registered groups. */
if (!(group = cfg_new_group(group_name, group_name_len, num, mapping, values, size, handle)))
goto error;
}
group->dynamic = CFG_GROUP_STATIC;
/* notify the drivers about the new config definition */
cfg_notify_drivers(group_name, group_name_len, def);
@ -219,13 +229,63 @@ int cfg_declare_str(char *group_name, char *var_name, char *val, char *descr)
return 0;
}
/* Add a varibale to a group instance with integer type.
* The group instance is created if it does not exist.
* wrapper function for new_add_var()
*/
int cfg_ginst_var_int(char *group_name, unsigned int group_id, char *var_name,
int val)
{
str gname, vname;
gname.s = group_name;
gname.len = strlen(group_name);
vname.s = var_name;
vname.len = strlen(var_name);
return new_add_var(&gname, group_id, &vname,
(void *)(long)val, CFG_VAR_INT);
}
/* Add a varibale to a group instance with string type.
* The group instance is created if it does not exist.
* wrapper function for new_add_var()
*/
int cfg_ginst_var_string(char *group_name, unsigned int group_id, char *var_name,
char *val)
{
str gname, vname;
gname.s = group_name;
gname.len = strlen(group_name);
vname.s = var_name;
vname.len = strlen(var_name);
return new_add_var(&gname, group_id, &vname,
(void *)val, CFG_VAR_STRING);
}
/* Create a new group instance.
* wrapper function for new_add_var()
*/
int cfg_new_ginst(char *group_name, unsigned int group_id)
{
str gname;
gname.s = group_name;
gname.len = strlen(group_name);
return new_add_var(&gname, group_id, NULL /* var */,
NULL /* val */, 0 /* type */);
}
/* returns the handle of a cfg group */
void **cfg_get_handle(char *gname)
{
cfg_group_t *group;
group = cfg_lookup_group(gname, strlen(gname));
if (!group || group->dynamic) return NULL;
if (!group || (group->dynamic != CFG_GROUP_STATIC)) return NULL;
return group->handle;
}

@ -30,6 +30,7 @@
#include "../str.h"
/* variable type */
#define CFG_VAR_UNSET 0U
#define CFG_VAR_INT 1U
#define CFG_VAR_STRING 2U
#define CFG_VAR_STR 3U
@ -87,6 +88,25 @@ int cfg_declare_int(char *group_name, char *var_name,
/* declares a single variable with str type */
int cfg_declare_str(char *group_name, char *var_name, char *val, char *descr);
/* Add a varibale to a group instance with integer type.
* The group instance is created if it does not exist.
* wrapper function for new_add_var()
*/
int cfg_ginst_var_int(char *group_name, unsigned int group_id, char *var_name,
int val);
/* Add a varibale to a group instance with string type.
* The group instance is created if it does not exist.
* wrapper function for new_add_var()
*/
int cfg_ginst_var_string(char *group_name, unsigned int group_id, char *var_name,
char *val);
/* Create a new group instance.
* wrapper function for new_add_var()
*/
int cfg_new_ginst(char *group_name, unsigned int group_id);
/* returns the handle of a cfg group */
void **cfg_get_handle(char *gname);

File diff suppressed because it is too large Load Diff

@ -49,6 +49,10 @@ typedef struct _cfg_changed_var {
cfg_mapping_t *var;
struct _cfg_changed_var *next;
unsigned int group_id; /* valid only if group_id_set==1 */
unsigned char group_id_set;
unsigned char del_value; /* delete the value instead of setting it */
/* blob that contains the new value */
union cfg_var_value new_val; /* variable size */
} cfg_changed_var_t;
@ -61,7 +65,6 @@ typedef struct _cfg_ctx {
/* variables that are already changed
but have not been committed yet */
cfg_changed_var_t *changed_first;
cfg_changed_var_t *changed_last;
/* lock protecting the linked-list of
changed variables */
gen_lock_t lock;
@ -84,18 +87,32 @@ int cfg_register_ctx(cfg_ctx_t **handle, cfg_on_declare on_declare_cb);
void cfg_ctx_destroy(void);
/*! \brief set the value of a variable without the need of explicit commit */
int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
void *val, unsigned int val_type);
int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
int cfg_set_now_int(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
int val);
int cfg_set_now_string(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
char *val);
int cfg_set_now_str(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
str *val);
/*! \brief Delete a variable from the group instance.
* wrapper function for cfg_set_now */
int cfg_del_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name);
/* sets the value of a variable but does not commit the change */
int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, str *var_name,
int cfg_set_delayed(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
void *val, unsigned int val_type);
int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, str *var_name, int val);
int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, str *var_name, char *val);
int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, str *var_name, str *val);
int cfg_set_delayed_int(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
int val);
int cfg_set_delayed_string(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
char *val);
int cfg_set_delayed_str(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
str *val);
/*! \brief Delete a variable from the group instance.
* wrapper function for cfg_set_delayed */
int cfg_del_delayed(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name);
/*! \brief commits the previously prepared changes within the context */
int cfg_commit(cfg_ctx_t *ctx);
@ -104,7 +121,7 @@ int cfg_commit(cfg_ctx_t *ctx);
int cfg_rollback(cfg_ctx_t *ctx);
/*! \brief returns the value of a variable */
int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, str *var_name,
int cfg_get_by_name(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *var_name,
void **val, unsigned int *val_type);
/*! \brief returns the description of a variable */
@ -114,10 +131,14 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name,
/*! \brief notify the drivers about the new config definition */
void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
/*! \brief convert the value to the requested type */
/*! \brief convert the value to the requested type.
* Do not forget the call convert_val_cleaup afterwards. */
int convert_val(unsigned int val_type, void *val,
unsigned int var_type, void **new_val);
/*! \brief cleanup function for convert_val() */
void convert_val_cleanup(void);
/*! \brief initialize the handle for cfg_get_group_next() */
#define cfg_get_group_init(handle) \
(*(handle)) = (void *)cfg_group
@ -149,26 +170,55 @@ int cfg_diff_init(cfg_ctx_t *ctx,
/*! \brief return the pending changes that have not been
* committed yet
* return value:
* 1: valid value is found
* 0: no more changed value found
* -1: error occured
*
*
* can be used as follows:
*
* void *handle;
* if (cfg_diff_init(ctx, &handle)) return -1
* while (cfg_diff_next(&handle
* &group_name, &var_name,
* while ((err = cfg_diff_next(&handle
* &group_name, &group_id, &var_name,
* &old_val, &new_val
* &val_type)
* &val_type)) > 0
* ) {
* ...
* }
* cfg_diff_release(ctx);
* if (err) {
* error occured, the changes cannot be retrieved
* ...
* }
*/
int cfg_diff_next(void **h,
str *gname, str *vname,
str *gname, unsigned int **gid, str *vname,
void **old_val, void **new_val,
unsigned int *val_type);
/*! \brief destroy the handle of cfg_diff_next() */
void cfg_diff_release(cfg_ctx_t *ctx);
/* Add a new instance to an existing group */
int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
/* Delete an instance of a group */
int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
/* Check the existance of a group instance.
* return value:
* 1: exists
* 0: does not exist
*/
int cfg_group_inst_exists(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
/* Apply the changes to a group instance as long as the additional variable
* belongs to the specified group_id. *add_var_p is moved to the next additional
* variable, and all the consumed variables are freed.
*/
int cfg_apply_list(cfg_group_inst_t *ginst, cfg_group_t *group,
unsigned int group_id, cfg_add_var_t **add_var_p);
#endif /* _CFG_CTX_H */

@ -31,6 +31,7 @@
#include "../ut.h"
#include "cfg_struct.h"
#include "cfg.h"
#include "cfg_ctx.h"
#include "cfg_script.h"
/* allocates memory for a new config script variable
@ -56,14 +57,14 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type
/* the group may have been already declared */
group = cfg_lookup_group(gname, gname_len);
if (group) {
if (group->dynamic == 0) {
if (group->dynamic == CFG_GROUP_STATIC) {
/* the group has been already declared by a module or by the core */
LOG(L_ERR, "ERROR: new_cfg_script_var(): "
"configuration group has been already declared: %s\n",
gname);
return NULL;
}
/* the dynamic group is found */
/* the dynamic or empty group is found */
/* verify that the variable does not exist */
for ( var = (cfg_script_var_t *)group->vars;
var;
@ -76,6 +77,8 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type
return NULL;
}
}
if (group->dynamic == CFG_GROUP_UNKNOWN)
group->dynamic = CFG_GROUP_DYNAMIC;
} else {
/* create a new group with NULL values, we will fix it later,
@ -85,7 +88,7 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type
NULL /* vars */, 0 /* size */, NULL /* handle */);
if (!group) goto error;
group->dynamic = 1;
group->dynamic = CFG_GROUP_DYNAMIC;
}
switch (type) {
@ -103,7 +106,15 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type
LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n");
return NULL;
}
group->num++;
if (group->num > CFG_MAX_VAR_NUM) {
LOG(L_ERR, "ERROR: new_cfg_script_var(): too many variables (%d) within a single group,"
" the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple"
" definitions.\n",
group->num, CFG_MAX_VAR_NUM);
return NULL;
}
var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t));
if (!var) goto error;
@ -135,6 +146,84 @@ error:
return NULL;
}
/* Rewrite the value of an already declared script variable before forking.
* Return value:
* 0: success
* -1: error
* 1: variable not found
*/
int cfg_set_script_var(cfg_group_t *group, str *var_name,
void *val, unsigned int val_type)
{
cfg_script_var_t *var;
void *v;
str s;
if (cfg_shmized || (group->dynamic != CFG_GROUP_DYNAMIC)) {
LOG(L_ERR, "BUG: cfg_set_script_var(): Not a dynamic group before forking\n");
return -1;
}
for ( var = (cfg_script_var_t *)(void *)group->vars;
var;
var = var->next
) {
if ((var->name_len == var_name->len)
&& (memcmp(var->name, var_name->s, var_name->len) == 0)
) {
switch (var->type) {
case CFG_VAR_INT:
if (convert_val(val_type, val, CFG_INPUT_INT, &v))
goto error;
if ((var->min || var->max)
&& ((var->min > (int)(long)v) || (var->max < (int)(long)v))
) {
LOG(L_ERR, "ERROR: cfg_set_script_var(): integer value is out of range\n");
goto error;
}
var->val.i = (int)(long)v;
break;
case CFG_VAR_STR:
if (convert_val(val_type, val, CFG_INPUT_STR, &v))
goto error;
if (((str *)v)->s) {
s.len = ((str *)v)->len;
s.s = pkg_malloc(sizeof(char) * (s.len + 1));
if (!s.s) {
LOG(L_ERR, "ERROR: cfg_set_script_var(): not enough memory\n");
goto error;
}
memcpy(s.s, ((str *)v)->s, s.len);
s.s[s.len] = '\0';
} else {
s.s = NULL;
s.len = 0;
}
if (var->val.s.s)
pkg_free(var->val.s.s);
var->val.s = s;
break;
default:
LOG(L_ERR, "ERROR: cfg_set_script_var(): unsupported variable type\n");
goto error;
}
convert_val_cleanup();
return 0;
}
}
return 1;
error:
LOG(L_ERR, "ERROR: cfg_set_script_var(): failed to set the script variable: %.*s.%.*s\n",
group->name_len, group->name,
var_name->len, var_name->s);
return -1;
}
/* fix-up the dynamically declared group:
* - allocate memory for the arrays
* - set the values within the memory block
@ -173,6 +262,7 @@ int cfg_script_fixup(cfg_group_t *group, unsigned char *block)
mapping[i].def = &(def[i]);
mapping[i].name_len = script_var->name_len;
mapping[i].pos = i;
switch (script_var->type) {
case CFG_VAR_INT:

@ -29,6 +29,7 @@
#define _CFG_SCRIPT_H
#include "../str.h"
#include "cfg_struct.h"
/* structure used for temporary storing the variables
* which are declared in the script */
@ -52,6 +53,15 @@ typedef struct _cfg_script_var {
cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type,
char *descr);
/* Rewrite the value of an already declared script variable before forking.
* Return value:
* 0: success
* -1: error
* 1: variable not found
*/
int cfg_set_script_var(cfg_group_t *group, str *var_name,
void *val, unsigned int val_type);
/* fix-up the dynamically declared group */
int cfg_script_fixup(cfg_group_t *group, unsigned char *block);

@ -60,14 +60,17 @@ static int cfg_new_select(str *gname, str *vname, void **group_p, void **var_p)
if (!sel->gname.s) goto error;
memcpy(sel->gname.s, gname->s, gname->len);
sel->gname.len = gname->len;
sel->group_p = group_p;
sel->vname.s = (char *)pkg_malloc(sizeof(char)*vname->len);
if (!sel->vname.s) goto error;
memcpy(sel->vname.s, vname->s, vname->len);
sel->vname.len = vname->len;
if (vname) {
sel->vname.s = (char *)pkg_malloc(sizeof(char)*vname->len);
if (!sel->vname.s) goto error;
memcpy(sel->vname.s, vname->s, vname->len);
sel->vname.len = vname->len;
sel->var_p = var_p;
}
sel->group_p = group_p;
sel->var_p = var_p;
sel->next = cfg_non_fixed_selects;
cfg_non_fixed_selects = sel;
@ -111,14 +114,23 @@ int cfg_fixup_selects()
for (sel=cfg_non_fixed_selects; sel; sel=sel->next) {
if (cfg_lookup_var(&sel->gname, &sel->vname, &group, &var)) {
LOG(L_ERR, "ERROR: cfg_parse_selects(): unknown variable: %.*s.%.*s\n",
sel->gname.len, sel->gname.s,
sel->vname.len, sel->vname.s);
return -1;
if (sel->var_p) {
if (cfg_lookup_var(&sel->gname, &sel->vname, &group, &var)) {
LOG(L_ERR, "ERROR: cfg_parse_selects(): unknown variable: %.*s.%.*s\n",
sel->gname.len, sel->gname.s,
sel->vname.len, sel->vname.s);
return -1;
}
*(sel->group_p) = (void *)group;
*(sel->var_p) = (void *)var;
} else {
if (!(group = cfg_lookup_group(sel->gname.s, sel->gname.len))) {
LOG(L_ERR, "ERROR: cfg_parse_selects(): unknown configuration group: %.*s\n",
sel->gname.len, sel->gname.s);
return -1;
}
*(sel->group_p) = (void *)group;
}
*(sel->group_p) = (void *)group;
*(sel->var_p) = (void *)var;
}
/* the select list is not needed anymore */
cfg_free_selects();
@ -137,8 +149,8 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
/* fixup call */
/* two parameters are mandatory, group name and variable name */
if (s->n != 3) {
LOG(L_ERR, "ERROR: select_cfg_var(): two parameters are expected\n");
if (s->n < 3) {
LOG(L_ERR, "ERROR: select_cfg_var(): At least two parameters are expected\n");
return -1;
}
@ -228,6 +240,9 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg)
return 0;
}
/* fake function to eat the first parameter of @cfg_get */
ABSTRACT_F(select_cfg_var1)
/* fix-up function for read_cfg_var()
*
* return value:
@ -331,7 +346,7 @@ unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val)
int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val)
{
unsigned int type;
void *v1, *v2;
void *v1=NULL, *v2=NULL;
if ((type = read_cfg_var(read_handle, &v1)) == 0)
return -1;
@ -349,7 +364,7 @@ int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val)
int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val)
{
unsigned int type;
void *v1, *v2;
void *v1=NULL, *v2=NULL;
if ((type = read_cfg_var(read_handle, &v1)) == 0)
return -1;
@ -360,3 +375,67 @@ int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val)
*val = *(str *)(v2);
return 0;
}
/* return the selected group instance */
int cfg_selected_inst(str *res, select_t *s, struct sip_msg *msg)
{
cfg_group_t *group;
cfg_group_inst_t *inst;
if (msg == NULL) {
/* fixup call */
/* one parameter is mandatory: group name */
if (s->n != 2) {
LOG(L_ERR, "ERROR: selected_inst(): One parameter is expected\n");
return -1;
}
if (s->params[1].type != SEL_PARAM_STR) {
LOG(L_ERR, "ERROR: selected_inst(): string parameter is expected\n");
return -1;
}
/* look-up the group and the variable */
if (!(group = cfg_lookup_group(s->params[1].v.s.s, s->params[1].v.s.len))) {
if (cfg_shmized) {
LOG(L_ERR, "ERROR: selected_inst(): unknown configuration group: %.*s\n",
s->params[1].v.s.len, s->params[1].v.s.s);
return -1;
}
/* The group was not found, add it to the non-fixed select list.
* So we act as if the fixup was successful, and we retry it later */
if (cfg_new_select(&s->params[1].v.s, NULL,
&s->params[1].v.p, NULL))
return -1;
LOG(L_DBG, "DEBUG: selected_inst(): select fixup is postponed: %.*s\n",
s->params[1].v.s.len, s->params[1].v.s.s);
s->params[1].type = SEL_PARAM_PTR;
s->params[1].v.p = NULL;
return 0;
}
s->params[1].type = SEL_PARAM_PTR;
s->params[1].v.p = (void *)group;
return 1;
}
group = (cfg_group_t *)s->params[1].v.p;
if (!group) return -1;
/* Get the current group instance from the group handle. */
inst = CFG_HANDLE_TO_GINST(*(group->handle));
if (inst) {
res->s = int2str(inst->id, &res->len);
} else {
res->s = "";
res->len = 0;
}
return 0;
}

@ -35,10 +35,10 @@ struct cfg_read_handle {
};
/* free the list of not yet fixed selects */
void cfg_free_selects();
void cfg_free_selects(void);
/* fix-up the select calls */
int cfg_fixup_selects();
int cfg_fixup_selects(void);
int select_cfg_var(str *res, select_t *s, struct sip_msg *msg);
@ -61,4 +61,7 @@ unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val);
int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val);
int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val);
/* return the selected group instance */
int cfg_selected_inst(str *res, select_t *s, struct sip_msg *msg);
#endif /* _CFG_SELECT_H */

@ -32,6 +32,7 @@
#include "../mem/shm_mem.h"
#include "../ut.h"
#include "../locking.h"
#include "../bit_scan.h"
#include "cfg_ctx.h"
#include "cfg_script.h"
#include "cfg_select.h"
@ -42,7 +43,7 @@ cfg_block_t **cfg_global = NULL; /* pointer to the active cfg block */
cfg_block_t *cfg_local = NULL; /* per-process pointer to the active cfg block.
Updated only when the child process
finishes working on the SIP message */
static int cfg_block_size = 0; /* size of the cfg block (constant) */
int cfg_block_size = 0; /* size of the cfg block including the meta-data (constant) */
gen_lock_t *cfg_global_lock = 0; /* protects *cfg_global */
gen_lock_t *cfg_writer_lock = 0; /* This lock makes sure that two processes do not
try to clone *cfg_global at the same time.
@ -55,6 +56,12 @@ cfg_child_cb_t **cfg_child_cb_first = NULL; /* first item of the per-child proce
callback list */
cfg_child_cb_t **cfg_child_cb_last = NULL; /* last item of the above list */
cfg_child_cb_t *cfg_child_cb = NULL; /* pointer to the previously executed cb */
int cfg_ginst_count = 0; /* number of group instances set within the child process */
/* forward declarations */
static void del_add_var_list(cfg_group_t *group);
static int apply_add_var_list(cfg_block_t *block, cfg_group_t *group);
/* creates a new cfg group, and adds it to the linked list */
cfg_group_t *cfg_new_group(char *name, int name_len,
@ -68,6 +75,14 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
return NULL;
}
if (num > CFG_MAX_VAR_NUM) {
LOG(L_ERR, "ERROR: cfg_new_group(): too many variables (%d) within a single group,"
" the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple"
" definitions.\n",
num, CFG_MAX_VAR_NUM);
return NULL;
}
group = (cfg_group_t *)pkg_malloc(sizeof(cfg_group_t)+name_len-1);
if (!group) {
LOG(L_ERR, "ERROR: cfg_new_group(): not enough memory\n");
@ -80,6 +95,8 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
group->vars = vars;
group->size = size;
group->handle = handle;
if (handle)
group->orig_handle = *handle;
group->name_len = name_len;
memcpy(&group->name, name, name_len);
@ -90,6 +107,20 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
return group;
}
/* Set the values of an existing cfg group. */
void cfg_set_group(cfg_group_t *group,
int num, cfg_mapping_t *mapping,
char *vars, int size, void **handle)
{
group->num = num;
group->mapping = mapping;
group->vars = vars;
group->size = size;
group->handle = handle;
if (handle)
group->orig_handle = *handle;
}
/* clones a string to shared memory
* (src and dst can be the same)
*/
@ -162,19 +193,37 @@ int cfg_shmize(void)
if (!cfg_group) return 0;
/* Let us allocate one memory block that
will contain all the variables */
* will contain all the variables + meta-data
* in the following form:
* |-----------|
* | meta-data | <- group A: meta_offset
* | variables | <- group A: var_offset
* |-----------|
* | meta-data | <- group B: meta_offset
* | variables | <- group B: var_offset
* |-----------|
* | ... |
* |-----------|
*
* The additional array for the multiple values
* of the same variable is linked to the meta-data.
*/
for ( size=0, group = cfg_group;
group;
group=group->next
) {
size = ROUND_POINTER(size);
group->offset = size;
group->meta_offset = size;
size += sizeof(cfg_group_meta_t);
size = ROUND_POINTER(size);
group->var_offset = size;
size += group->size;
}
block = (cfg_block_t*)shm_malloc(sizeof(cfg_block_t)+size-1);
if (!block) {
LOG(L_ERR, "ERROR: cfg_clone_str(): not enough shm memory\n");
LOG(L_ERR, "ERROR: cfg_shmize(): not enough shm memory\n");
goto error;
}
memset(block, 0, sizeof(cfg_block_t)+size-1);
@ -185,29 +234,40 @@ int cfg_shmize(void)
group;
group=group->next
) {
if (group->dynamic == 0) {
if (group->dynamic == CFG_GROUP_STATIC) {
/* clone the strings to shm mem */
if (cfg_shmize_strings(group)) goto error;
/* copy the values to the new block */
memcpy(block->vars+group->offset, group->vars, group->size);
} else {
memcpy(CFG_GROUP_DATA(block, group), group->vars, group->size);
} else if (group->dynamic == CFG_GROUP_DYNAMIC) {
/* The group was declared with NULL values,
* we have to fix it up.
* The fixup function takes care about the values,
* it fills up the block */
if (cfg_script_fixup(group, block->vars+group->offset)) goto error;
if (cfg_script_fixup(group, CFG_GROUP_DATA(block, group))) goto error;
/* Notify the drivers about the new config definition.
* Temporary set the group handle so that the drivers have a chance to
* overwrite the default values. The handle must be reset after this
* because the main process does not have a local configuration. */
*(group->handle) = block->vars+group->offset;
*(group->handle) = CFG_GROUP_DATA(block, group);
cfg_notify_drivers(group->name, group->name_len,
group->mapping->def);
*(group->handle) = NULL;
} else {
LOG(L_ERR, "ERROR: cfg_shmize(): Configuration group is declared "
"without any variable: %.*s\n",
group->name_len, group->name);
goto error;
}
/* Create the additional group instances with applying
the temporary list. */
if (apply_add_var_list(block, group))
goto error;
}
/* try to fixup the selects that failed to be fixed-up previously */
if (cfg_fixup_selects()) goto error;
@ -243,11 +303,11 @@ static void cfg_destory_groups(unsigned char *block)
(CFG_VAR_TYPE(&mapping[i]) == CFG_VAR_STR)) &&
mapping[i].flag & cfg_var_shmized) {
old_string = *(char **)(block + group->offset + mapping[i].offset);
old_string = *(char **)(block + group->var_offset + mapping[i].offset);
if (old_string) shm_free(old_string);
}
if (group->dynamic) {
if (group->dynamic == CFG_GROUP_DYNAMIC) {
/* the group was dynamically allocated */
cfg_script_destroy(group);
} else {
@ -255,6 +315,8 @@ static void cfg_destory_groups(unsigned char *block)
pointers are just set to static variables */
if (mapping) pkg_free(mapping);
}
/* Delete the additional variable list */
del_add_var_list(group);
group2 = group->next;
pkg_free(group);
@ -339,7 +401,7 @@ void cfg_destroy(void)
cfg_free_selects();
if (cfg_child_cb_first) {
if (*cfg_child_cb_first) cfg_child_cb_free(*cfg_child_cb_first);
if (*cfg_child_cb_first) cfg_child_cb_free_list(*cfg_child_cb_first);
shm_free(cfg_child_cb_first);
cfg_child_cb_first = NULL;
}
@ -471,7 +533,7 @@ void cfg_child_destroy(void)
if (*cfg_child_cb_first == prev_cb) {
/* yes, this process was blocking the deletion */
*cfg_child_cb_first = cfg_child_cb;
shm_free(prev_cb);
cfg_child_cb_free_item(prev_cb);
}
} else {
/* no need to continue, because there is at least
@ -538,6 +600,29 @@ int cfg_lookup_var(str *gname, str *vname,
return -1;
}
/* searches a variable definition within a group by its name */
cfg_mapping_t *cfg_lookup_var2(cfg_group_t *group, char *name, int len)
{
int i;
if (!group->mapping) return NULL; /* dynamic group is not ready */
for ( i = 0;
i < group->num;
i++
) {
if ((group->mapping[i].name_len == len)
&& (memcmp(group->mapping[i].def->name, name, len)==0)) {
return &(group->mapping[i]);
}
}
LOG(L_DBG, "DEBUG: cfg_lookup_var2(): variable not found: %.*s.%.*s\n",
group->name_len, group->name,
len, name);
return NULL;
}
/* clones the global config block
* WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held!
*/
@ -558,6 +643,130 @@ cfg_block_t *cfg_clone_global(void)
return block;
}
/* Clone an array of configuration group instances. */
cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group)
{
cfg_group_inst_t *new_array;
int size;
if (!meta->array || !meta->num)
return NULL;
size = (sizeof(cfg_group_inst_t) + group->size - 1) * meta->num;
new_array = (cfg_group_inst_t *)shm_malloc(size);
if (!new_array) {
LOG(L_ERR, "ERROR: cfg_clone_array(): not enough shm memory\n");
return NULL;
}
memcpy(new_array, meta->array, size);
return new_array;
}
/* Extend the array of configuration group instances with one more instance.
* Only the ID of the new group is set, nothing else. */
cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
unsigned int group_id,
cfg_group_inst_t **new_group)
{
int i;
cfg_group_inst_t *new_array, *old_array;
int inst_size;
inst_size = sizeof(cfg_group_inst_t) + group->size - 1;
new_array = (cfg_group_inst_t *)shm_malloc(inst_size * (meta->num + 1));
if (!new_array) {
LOG(L_ERR, "ERROR: cfg_extend_array(): not enough shm memory\n");
return NULL;
}
/* Find the position of the new group in the array. The array is ordered
by the group IDs. */
old_array = meta->array;
for ( i = 0;
(i < meta->num)
&& (((cfg_group_inst_t *)((char *)old_array + inst_size * i))->id < group_id);
i++
);
if (i > 0)
memcpy( new_array,
old_array,
inst_size * i);
memset((char*)new_array + inst_size * i, 0, inst_size);
*new_group = (cfg_group_inst_t *)((char*)new_array + inst_size * i);
(*new_group)->id = group_id;
if (i < meta->num)
memcpy( (char*)new_array + inst_size * (i + 1),
(char*)old_array + inst_size * i,
inst_size * (meta->num - i));
return new_array;
}
/* Remove an instance from a group array.
* inst must point to an instance within meta->array.
* *_new_array is set to the newly allocated array. */
int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
cfg_group_inst_t *inst,
cfg_group_inst_t **_new_array)
{
cfg_group_inst_t *new_array, *old_array;
int inst_size, offset;
if (!meta->num)
return -1;
if (meta->num == 1) {
*_new_array = NULL;
return 0;
}
inst_size = sizeof(cfg_group_inst_t) + group->size - 1;
new_array = (cfg_group_inst_t *)shm_malloc(inst_size * (meta->num - 1));
if (!new_array) {
LOG(L_ERR, "ERROR: cfg_collapse_array(): not enough shm memory\n");
return -1;
}
old_array = meta->array;
offset = (char *)inst - (char *)old_array;
if (offset)
memcpy( new_array,
old_array,
offset);
if (meta->num * inst_size > offset + inst_size)
memcpy( (char *)new_array + offset,
(char *)old_array + offset + inst_size,
(meta->num - 1) * inst_size - offset);
*_new_array = new_array;
return 0;
}
/* Find the group instance within the meta-data based on the group_id */
cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id)
{
int i;
cfg_group_inst_t *ginst;
if (!meta)
return NULL;
/* For now, search lineray.
TODO: improve */
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)meta->array
+ (sizeof(cfg_group_inst_t) + group_size - 1) * i);
if (ginst->id == group_id)
return ginst;
else if (ginst->id > group_id)
break; /* needless to continue, the array is ordered */
}
return NULL;
}
/* append new callbacks to the end of the child callback list
*
* WARNING: the function is unsafe, either hold CFG_LOCK(),
@ -577,13 +786,33 @@ void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last)
* cb_first and cb_last define a linked list of per-child process
* callbacks. This list is added to the global linked list.
*/
void cfg_install_global(cfg_block_t *block, char **replaced,
void cfg_install_global(cfg_block_t *block, void **replaced,
cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last)
{
cfg_block_t* old_cfg;
CFG_REF(block);
if (replaced) {
/* The replaced array is specified, it has to be linked to the child cb structure.
* The last child process processing this structure will free the old strings and the array. */
if (cb_first) {
cb_first->replaced = replaced;
} else {
/* At least one child cb structure is needed. */
cb_first = cfg_child_cb_new(NULL, NULL, NULL, 0 /* gname, name, cb, type */);
if (cb_first) {
cb_last = cb_first;
cb_first->replaced = replaced;
} else {
LOG(L_ERR, "ERROR: cfg_install_global(): not enough shm memory\n");
/* Nothing more can be done here, the replaced strings are still needed,
* they cannot be freed at this moment.
*/
}
}
}
CFG_LOCK();
old_cfg = *cfg_global;
@ -594,11 +823,8 @@ void cfg_install_global(cfg_block_t *block, char **replaced,
CFG_UNLOCK();
if (old_cfg) {
if (replaced) (old_cfg)->replaced = replaced;
if (old_cfg)
CFG_UNREF(old_cfg);
}
}
/* creates a structure for a per-child process callback */
@ -645,7 +871,7 @@ cfg_child_cb_t *cfg_child_cb_new(str *gname, str *name,
}
/* free the memory allocated for a child cb list */
void cfg_child_cb_free(cfg_child_cb_t *child_cb_first)
void cfg_child_cb_free_list(cfg_child_cb_t *child_cb_first)
{
cfg_child_cb_t *cb, *cb_next;
@ -654,6 +880,440 @@ void cfg_child_cb_free(cfg_child_cb_t *child_cb_first)
cb = cb_next
) {
cb_next = cb->next;
shm_free(cb);
cfg_child_cb_free_item(cb);
}
}
/* Allocate memory for a new additional variable
* and link it to a configuration group.
* type==0 results in creating a new group instance with the default values.
* The group is created with CFG_GROUP_UNKNOWN type if it does not exist.
* Note: this function is usable only before the configuration is shmized.
*/
int new_add_var(str *group_name, unsigned int group_id, str *var_name,
void *val, unsigned int type)
{
cfg_group_t *group;
cfg_add_var_t *add_var = NULL, **add_var_p;
int len;
if (type && !var_name) {
LOG(L_ERR, "ERROR: new_add_var(): Missing variable specification\n");
goto error;
}
if (type)
LOG(L_DBG, "DEBUG: new_add_var(): declaring a new variable instance %.*s[%u].%.*s\n",
group_name->len, group_name->s,
group_id,
var_name->len, var_name->s);
else
LOG(L_DBG, "DEBUG: new_add_var(): declaring a new group instance %.*s[%u]\n",
group_name->len, group_name->s,
group_id);
if (cfg_shmized) {
LOG(L_ERR, "ERROR: new_add_var(): too late, the configuration has already been shmized\n");
goto error;
}
group = cfg_lookup_group(group_name->s, group_name->len);
if (!group) {
/* create a new group with NULL values, it will be filled in later */
group = cfg_new_group(group_name->s, group_name->len,
0 /* num */, NULL /* mapping */,
NULL /* vars */, 0 /* size */, NULL /* handle */);
if (!group)
goto error;
/* It is not yet known whether the group will be static or dynamic */
group->dynamic = CFG_GROUP_UNKNOWN;
}
add_var = (cfg_add_var_t *)pkg_malloc(sizeof(cfg_add_var_t) +
(type ? (var_name->len - 1) : 0));
if (!add_var) {
LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n");
goto error;
}
memset(add_var, 0, sizeof(cfg_add_var_t) +
(type ? (var_name->len - 1) : 0));
add_var->group_id = group_id;
if (type) {
add_var->name_len = var_name->len;
memcpy(add_var->name, var_name->s, var_name->len);
switch (type) {
case CFG_VAR_INT:
add_var->val.i = (int)(long)val;
break;
case CFG_VAR_STR:
len = ((str *)val)->len;
if (len) {
add_var->val.s.s = (char *)pkg_malloc(sizeof(char) * len);
if (!add_var->val.s.s) {
LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n");
goto error;
}
memcpy(add_var->val.s.s, ((str *)val)->s, len);
} else {
add_var->val.s.s = NULL;
}
add_var->val.s.len = len;
break;
case CFG_VAR_STRING:
if (val) {
len = strlen((char *)val);
add_var->val.ch = (char *)pkg_malloc(sizeof(char) * (len + 1));
if (!add_var->val.ch) {
LOG(L_ERR, "ERROR: new_add_var(): Not enough memory\n");
goto error;
}
memcpy(add_var->val.ch, (char *)val, len);
add_var->val.ch[len] = '\0';
} else {
add_var->val.ch = NULL;
}
break;
default:
LOG(L_ERR, "ERROR: new_add_var(): unsupported value type: %u\n",
type);
goto error;
}
add_var->type = type;
}
/* order the list by group_id, it will be easier to count the group instances */
for( add_var_p = &group->add_var;
*add_var_p && ((*add_var_p)->group_id <= group_id);
add_var_p = &((*add_var_p)->next));
add_var->next = *add_var_p;
*add_var_p = add_var;
return 0;
error:
if (!type)
LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional group instance: %.*s[%u]\n",
group_name->len, group_name->s, group_id);
else
LOG(L_ERR, "ERROR: new_add_var(): failed to add the additional variable instance: %.*s[%u].%.*s\n",
group_name->len, group_name->s, group_id,
var_name->len, var_name->s);
if (add_var)
pkg_free(add_var);
return -1;
}
/* delete the additional variable list */
static void del_add_var_list(cfg_group_t *group)
{
cfg_add_var_t *add_var, *add_var2;
add_var = group->add_var;
while (add_var) {
add_var2 = add_var->next;
if ((add_var->type == CFG_VAR_STR) && add_var->val.s.s)
pkg_free(add_var->val.s.s);
else if ((add_var->type == CFG_VAR_STRING) && add_var->val.ch)
pkg_free(add_var->val.ch);
pkg_free(add_var);
add_var = add_var2;
}
group->add_var = NULL;
}
/* create the array of additional group instances from the linked list */
static int apply_add_var_list(cfg_block_t *block, cfg_group_t *group)
{
int i, num, size;
unsigned int group_id;
cfg_add_var_t *add_var;
cfg_group_inst_t *new_array, *ginst;
/* count the number of group instances */
for ( add_var = group->add_var, num = 0, group_id = 0;
add_var;
add_var = add_var->next
) {
if (!num || (group_id != add_var->group_id)) {
num++;
group_id = add_var->group_id;
}
}
if (!num) /* nothing to do */
return 0;
LOG(L_DBG, "DEBUG: apply_add_var_list(): creating the group instance array "
"for '%.*s' with %d slots\n",
group->name_len, group->name, num);
size = (sizeof(cfg_group_inst_t) + group->size - 1) * num;
new_array = (cfg_group_inst_t *)shm_malloc(size);
if (!new_array) {
LOG(L_ERR, "ERROR: apply_add_var_list(): not enough shm memory\n");
return -1;
}
memset(new_array, 0, size);
for (i = 0; i < num; i++) {
/* Go though each group instance, set the default values,
and apply the changes */
if (!group->add_var) {
LOG(L_ERR, "BUG: apply_add_var_list(): no more additional variable left\n");
goto error;
}
ginst = (cfg_group_inst_t *)((char*)new_array + (sizeof(cfg_group_inst_t) + group->size - 1) * i);
ginst->id = group->add_var->group_id;
/* fill in the new group instance with the default data */
memcpy( ginst->vars,
CFG_GROUP_DATA(block, group),
group->size);
/* cfg_apply_list() moves the group->add_var pointer to
the beginning of the new group instance. */
if (cfg_apply_list(ginst, group, ginst->id, &group->add_var))
goto error;
}
#ifdef EXTRA_DEBUG
if (group->add_var) {
LOG(L_ERR, "BUG: apply_add_var_list(): not all the additional variables have been consumed\n");
goto error;
}
#endif
CFG_GROUP_META(block, group)->num = num;
CFG_GROUP_META(block, group)->array = new_array;
return 0;
error:
LOG(L_ERR, "ERROR: apply_add_var_list(): Failed to apply the additional variable list\n");
shm_free(new_array);
return -1;
}
/* Move the group handle to the specified group instance pointed by dst_ginst.
* src_ginst shall point to the active group instance.
* Both parameters can be NULL meaning that the src/dst config is the default,
* not an additional group instance.
* The function executes all the per-child process callbacks which are different
* in the two instaces.
*/
void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, cfg_group_inst_t *dst_ginst)
{
cfg_mapping_t *var;
unsigned int bitmap;
int i, pos;
str gname, vname;
if (src_ginst == dst_ginst)
return; /* nothing to do */
/* move the handle to the variables of the dst group instance,
or to the local config if no dst group instance is specified */
*(group->handle) = dst_ginst ?
dst_ginst->vars
: CFG_GROUP_DATA(cfg_local, group);
if (cfg_child_cb != CFG_NO_CHILD_CBS) {
/* call the per child process callback of those variables
that have different value in the two group instances */
/* TODO: performance optimization: this entire loop can be
skipped if the group does not have any variable with
per-child process callback. Use some flag in the group
structure for this purpose. */
gname.s = group->name;
gname.len = group->name_len;
for (i = 0; i < CFG_MAX_VAR_NUM/(sizeof(int)*8); i++) {
bitmap = ((src_ginst) ? src_ginst->set[i] : 0U)
| ((dst_ginst) ? dst_ginst->set[i] : 0U);
while (bitmap) {
pos = bit_scan_forward32(bitmap);
var = &group->mapping[pos + i*sizeof(int)*8];
if (var->def->on_set_child_cb) {
vname.s = var->def->name;
vname.len = var->name_len;
var->def->on_set_child_cb(&gname, &vname);
}
bitmap -= (1U << pos);
}
}
}
/* keep track of how many group instences are set in the child process */
if (!src_ginst && dst_ginst)
cfg_ginst_count++;
else if (!dst_ginst)
cfg_ginst_count--;
#ifdef EXTRA_DEBUG
if (cfg_ginst_count < 0)
LOG(L_ERR, "ERROR: cfg_select(): BUG, cfg_ginst_count is negative: %d. group=%.*s\n",
cfg_ginst_count, group->name_len, group->name);
#endif
return;
}
/* Move the group handle to the specified group instance. */
int cfg_select(cfg_group_t *group, unsigned int id)
{
cfg_group_inst_t *ginst;
if (!cfg_local) {
LOG(L_ERR, "ERROR: The child process has no local configuration\n");
return -1;
}
if (!(ginst = cfg_find_group(CFG_GROUP_META(cfg_local, group),
group->size,
id))
) {
LOG(L_ERR, "ERROR: cfg_select(): group instance '%.*s[%u]' does not exist\n",
group->name_len, group->name, id);
return -1;
}
cfg_move_handle(group,
CFG_HANDLE_TO_GINST(*(group->handle)), /* the active group instance */
ginst);
LOG(L_DBG, "DEBUG: cfg_select(): group instance '%.*s[%u]' has been selected\n",
group->name_len, group->name, id);
return 0;
}
/* Reset the group handle to the default, local configuration */
int cfg_reset(cfg_group_t *group)
{
if (!cfg_local) {
LOG(L_ERR, "ERROR: The child process has no local configuration\n");
return -1;
}
cfg_move_handle(group,
CFG_HANDLE_TO_GINST(*(group->handle)), /* the active group instance */
NULL);
LOG(L_DBG, "DEBUG: cfg_reset(): default group '%.*s' has been selected\n",
group->name_len, group->name);
return 0;
}
/* Move the group handle to the first group instance.
* This function together with cfg_select_next() can be used
* to iterate though the list of instances.
*
* Return value:
* -1: no group instance found
* 0: first group instance is successfully selected.
*/
int cfg_select_first(cfg_group_t *group)
{
cfg_group_meta_t *meta;
cfg_group_inst_t *ginst;
if (!cfg_local) {
LOG(L_ERR, "ERROR: The child process has no local configuration\n");
return -1;
}
meta = CFG_GROUP_META(cfg_local, group);
if (!meta || (meta->num == 0))
return -1;
ginst = (cfg_group_inst_t *)meta->array;
cfg_move_handle(group,
CFG_HANDLE_TO_GINST(*(group->handle)), /* the active group instance */
ginst);
LOG(L_DBG, "DEBUG: cfg_select_first(): group instance '%.*s[%u]' has been selected\n",
group->name_len, group->name, ginst->id);
return 0;
}
/* Move the group handle to the next group instance.
* This function together with cfg_select_first() can be used
* to iterate though the list of instances.
*
* Return value:
* -1: no more group instance found. Note, that the active group
* instance is not changed in this case.
* 0: the next group instance is successfully selected.
*/
int cfg_select_next(cfg_group_t *group)
{
cfg_group_meta_t *meta;
cfg_group_inst_t *old_ginst, *new_ginst;
int size;
if (!cfg_local) {
LOG(L_ERR, "ERROR: The child process has no local configuration\n");
return -1;
}
if (!(meta = CFG_GROUP_META(cfg_local, group)))
return -1;
if (!(old_ginst = CFG_HANDLE_TO_GINST(*(group->handle)) /* the active group instance */)) {
LOG(L_ERR, "ERROR: cfg_select_next(): No group instance is set currently. Forgot to call cfg_select_first()?\n");
return -1;
}
size = sizeof(cfg_group_inst_t) + group->size - 1;
if (((char *)old_ginst - (char *)meta->array)/size + 1 >= meta->num)
return -1; /* this is the last group instance */
new_ginst = (cfg_group_inst_t *)((char *)old_ginst + size);
cfg_move_handle(group,
old_ginst, /* the active group instance */
new_ginst);
LOG(L_DBG, "DEBUG: cfg_select_next(): group instance '%.*s[%u]' has been selected\n",
group->name_len, group->name, new_ginst->id);
return 0;
}
/* Temporary set the local configuration in the main process before forking.
* This makes the group instances usable in the main process after
* the configuration is shmized, but before the children are forked.
*/
void cfg_main_set_local(void)
{
/* Disable the execution of child-process callbacks,
* they can cause trouble because the children inherit all the
* values later */
cfg_child_cb = CFG_NO_CHILD_CBS;
cfg_update_no_cbs();
}
/* Reset the local configuration of the main process back to its original state
* to make sure that the forked processes are not affected.
*/
void cfg_main_reset_local(void)
{
cfg_group_t *group;
/* Unref the local config, and set it back to NULL.
* Each child will set its own local configuration. */
if (cfg_local) {
CFG_UNREF(cfg_local);
cfg_local = NULL;
/* restore the original value of the module handles */
for ( group = cfg_group;
group;
group = group->next
)
*(group->handle) = group->orig_handle;
/* The handle might have pointed to a group instance,
* reset the instance counter. */
cfg_ginst_count = 0;
}
cfg_child_cb = NULL;
}

@ -34,21 +34,50 @@
#include "../mem/shm_mem.h"
#include "../locking.h"
#include "../compiler_opt.h"
#include "../bit_test.h"
#include "cfg.h"
/*! \brief Maximum number of variables within a configuration group. */
#define CFG_MAX_VAR_NUM 256
/*! \brief indicates that the variable has been already shmized */
#define cfg_var_shmized 1U
/*! \brief Structure for storing additional values of a variable.
* When the config is shmzied, these variables are combined in
* an array.
*/
typedef struct _cfg_add_var {
struct _cfg_add_var *next;
unsigned int type; /*!< type == 0 is also valid, it indicates that the group
must be created with the default values */
union {
char *ch;
str s;
int i;
} val;
unsigned int group_id; /*!< Id of the group instance */
int name_len; /*!< Name of the variable. The variable may not be known,
for example the additional group value is set in the script
before the cfg group is declared. Hence, the pointer cannot
be stored here. */
char name[1];
} cfg_add_var_t;
/*! \brief structure used for variable - pointer mapping */
typedef struct _cfg_mapping {
cfg_def_t *def; /*!< one item of the cfg structure definition */
int name_len; /*!< length of def->name */
/* additional information about the cfg variable */
int pos; /*!< position of the variable within the group starting from 0 */
int offset; /*!< offest within the memory block */
unsigned int flag; /*!< flag indicating the state of the variable */
} cfg_mapping_t;
/*! \brief type of the group */
enum { CFG_GROUP_UNKNOWN = 0, CFG_GROUP_DYNAMIC, CFG_GROUP_STATIC };
/*! \brief linked list of registered groups */
typedef struct _cfg_group {
int num; /*!< number of variables within the group */
@ -57,30 +86,56 @@ typedef struct _cfg_group {
char *vars; /*!< pointer to the memory block where the values
are stored -- used only before the config is
shmized. */
cfg_add_var_t *add_var; /*!< Additional instances of the variables.
This linked list is used only before the config is
shmized. */
int size; /*!< size of the memory block that has to be
allocated to store the values */
int offset; /*!< offset of the group within the
shmized memory block */
int meta_offset; /*!< offset of the group within the
shmized memory block for the meta_data */
int var_offset; /*!< offset of the group within the
shmized memory block for the variables */
void **handle; /*!< per-process handle that can be used
by the modules to access the variables.
It is registered when the group is created,
and updated every time the block is replaced */
void *orig_handle; /*!< Original value that the handle points to
when the config group is registered. This is needed
to temporary set the handle in the main process and
restore it later to its original value. */
unsigned char dynamic; /*!< indicates whether the variables within the group
are dynamically allocated or not */
struct _cfg_group *next;
int name_len;
int name_len;
char name[1];
} cfg_group_t;
/*! \brief One instance of the cfg group variables which stores
* the additional values. These values can overwrite the default values. */
typedef struct _cfg_group_inst {
unsigned int id; /*!< identifier of the group instance */
unsigned int set[CFG_MAX_VAR_NUM/(sizeof(int)*8)];
/*!< Bitmap indicating whether or not a value is explicitely set
within this instance. If the value is not set,
then the default value is used, and copied into this instance. */
unsigned char vars[1]; /*!< block for the values */
} cfg_group_inst_t;
/*! \brief Meta-data which is stored before each variable group
* within the blob. This structure is used to handle the multivalue
* instances of the variables, i.e. manages the array for the
* additional values. */
typedef struct _cfg_group_meta {
int num; /*!< Number of items in the array */
cfg_group_inst_t *array; /*!< Array of cfg groups with num number of items */
} cfg_group_meta_t;
/*! \brief single memoy block that contains all the cfg values */
typedef struct _cfg_block {
atomic_t refcnt; /*!< reference counter,
the block is automatically deleted
when it reaches 0 */
char **replaced; /*!< set of the strings that must be freed
together with the block. The content depends
on the block that replaces this one */
unsigned char vars[1]; /*!< blob that contains the values */
} cfg_block_t;
@ -100,7 +155,12 @@ typedef struct _cfg_child_cb {
* <=0 the cb no longer needs to be executed
*/
str gname, name; /*!< name of the variable that has changed */
cfg_on_set_child cb; /*!< callback function that has to be called */
cfg_on_set_child cb; /*!< callback function that has to be called */
void **replaced; /*!< set of strings and other memory segments
that must be freed together with this structure.
The content depends on the new config block.
This makes sure that the replaced strings are freed
after all the child processes release the old configuration. */
struct _cfg_child_cb *next;
} cfg_child_cb_t;
@ -108,12 +168,14 @@ typedef struct _cfg_child_cb {
extern cfg_group_t *cfg_group;
extern cfg_block_t **cfg_global;
extern cfg_block_t *cfg_local;
extern int cfg_block_size;
extern gen_lock_t *cfg_global_lock;
extern gen_lock_t *cfg_writer_lock;
extern int cfg_shmized;
extern cfg_child_cb_t **cfg_child_cb_first;
extern cfg_child_cb_t **cfg_child_cb_last;
extern cfg_child_cb_t *cfg_child_cb;
extern int cfg_ginst_count;
/* magic value for cfg_child_cb for processes that do not want to
execute per-child callbacks */
@ -123,6 +185,38 @@ extern cfg_child_cb_t *cfg_child_cb;
#define CFG_VAR_TYPE(var) CFG_VAR_MASK((var)->def->type)
#define CFG_INPUT_TYPE(var) CFG_INPUT_MASK((var)->def->type)
/* get the meta-data of a group from the block */
#define CFG_GROUP_META(block, group) \
((cfg_group_meta_t *)((block)->vars + (group)->meta_offset))
/* get the data block of a group from the block */
#define CFG_GROUP_DATA(block, group) \
((unsigned char *)((block)->vars + (group)->var_offset))
/* Test whether a variable is explicitely set in the group instance,
* or it uses the default value */
#define CFG_VAR_TEST(group_inst, var) \
bit_test((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
/* Test whether a variable is explicitely set in the group instance,
* or it uses the default value, and set the flag. */
#define CFG_VAR_TEST_AND_SET(group_inst, var) \
bit_test_and_set((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
/* Test whether a variable is explicitely set in the group instance,
* or it uses the default value, and reset the flag. */
#define CFG_VAR_TEST_AND_RESET(group_inst, var) \
bit_test_and_reset((var)->pos % (sizeof(int)*8), (group_inst)->set + (var)->pos/(sizeof(int)*8))
/* Return the group instance pointer from a handle,
* or NULL if the handle points to the default configuration block */
#define CFG_HANDLE_TO_GINST(h) \
( (((unsigned char*)(h) < cfg_local->vars) \
|| ((unsigned char*)(h) > cfg_local->vars + cfg_block_size) \
) ? \
(cfg_group_inst_t*)((char*)(h) - (unsigned long)&((cfg_group_inst_t *)0)->vars) \
: NULL )
/* initiate the cfg framework */
int sr_cfg_init(void);
@ -173,23 +267,41 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
int num, cfg_mapping_t *mapping,
char *vars, int size, void **handle);
/* Set the values of an existing cfg group. */
void cfg_set_group(cfg_group_t *group,
int num, cfg_mapping_t *mapping,
char *vars, int size, void **handle);
/* copy the variables to shm mem */
int cfg_shmize(void);
/* free the memory of a config block */
static inline void cfg_block_free(cfg_block_t *block)
/* free the memory of a child cb structure */
static inline void cfg_child_cb_free_item(cfg_child_cb_t *cb)
{
int i;
/* free the changed variables */
if (block->replaced) {
for (i=0; block->replaced[i]; i++)
shm_free(block->replaced[i]);
shm_free(block->replaced);
if (cb->replaced) {
for (i=0; cb->replaced[i]; i++)
shm_free(cb->replaced[i]);
shm_free(cb->replaced);
}
shm_free(block);
shm_free(cb);
}
#define cfg_block_free(block) \
shm_free(block)
/* Move the group handle to the specified group instance pointed by dst_ginst.
* src_ginst shall point to the active group instance.
* Both parameters can be NULL meaning that the src/dst config is the default,
* not an additional group instance.
* The function executes all the per-child process callbacks which are different
* in the two instaces.
*/
void cfg_move_handle(cfg_group_t *group, cfg_group_inst_t *src_ginst, cfg_group_inst_t *dst_ginst);
/* lock and unlock the global cfg block -- used only at the
* very last step when the block is replaced */
#define CFG_LOCK() lock_get(cfg_global_lock);
@ -242,7 +354,7 @@ static inline void cfg_update_local(int no_cbs)
group;
group = group->next
)
*(group->handle) = cfg_local->vars + group->offset;
*(group->handle) = CFG_GROUP_DATA(cfg_local, group);
if (unlikely(cfg_child_cb==CFG_NO_CHILD_CBS || no_cbs))
return;
@ -261,19 +373,44 @@ static inline void cfg_update_local(int no_cbs)
/* yes, this process was blocking the deletion */
*cfg_child_cb_first = cfg_child_cb;
CFG_UNLOCK();
shm_free(prev_cb);
cfg_child_cb_free_item(prev_cb);
} else {
CFG_UNLOCK();
}
}
if (atomic_add(&cfg_child_cb->cb_count, -1) >= 0) /* the new value is returned
by atomic_add() */
if (cfg_child_cb->cb
&& (atomic_add(&cfg_child_cb->cb_count, -1) >= 0) /* the new value is returned
by atomic_add() */
)
/* execute the callback */
cfg_child_cb->cb(&cfg_child_cb->gname, &cfg_child_cb->name);
/* else the callback no longer needs to be executed */
}
}
/* Reset all the group handles to the default, local configuration */
static inline void cfg_reset_handles(void)
{
cfg_group_t *group;
if (!cfg_local)
return;
for ( group = cfg_group;
group && cfg_ginst_count; /* cfg_ginst_count is decreased every time
a group handle is reset. When it reaches 0,
needless to continue the loop */
group = group->next
) {
if (((unsigned char*)*(group->handle) < cfg_local->vars)
|| ((unsigned char*)*(group->handle) > cfg_local->vars + cfg_block_size)
)
cfg_move_handle(group,
CFG_HANDLE_TO_GINST(*(group->handle)),
NULL);
}
}
/* sets the local cfg block to the active block
*
* If your module forks a new process that implements
@ -283,6 +420,8 @@ static inline void cfg_update_local(int no_cbs)
*/
#define cfg_update() \
do { \
if (unlikely(cfg_ginst_count)) \
cfg_reset_handles(); \
if (unlikely(cfg_local != *cfg_global)) \
cfg_update_local(0); \
} while(0)
@ -297,6 +436,16 @@ static inline void cfg_update_local(int no_cbs)
cfg_update_local(1); \
} while(0)
/* Reset all the group handles in the child process,
* i.e. move them back to the default local configuration.
*/
#define cfg_reset_all() \
do { \
if (unlikely(cfg_ginst_count)) \
cfg_reset_handles(); \
} while(0)
/* searches a group by name */
cfg_group_t *cfg_lookup_group(char *name, int len);
@ -304,12 +453,36 @@ cfg_group_t *cfg_lookup_group(char *name, int len);
int cfg_lookup_var(str *gname, str *vname,
cfg_group_t **group, cfg_mapping_t **var);
/* clones the global config block */
/* searches a variable definition within a group by its name */
cfg_mapping_t *cfg_lookup_var2(cfg_group_t *group, char *name, int len);
/* clones the global config block
* WARNING: unsafe, cfg_writer_lock or cfg_global_lock must be held!
*/
cfg_block_t *cfg_clone_global(void);
/* Clone an array of configuration group instances. */
cfg_group_inst_t *cfg_clone_array(cfg_group_meta_t *meta, cfg_group_t *group);
/* Extend the array of configuration group instances with one more instance.
* Only the ID of the new group is set, nothing else. */
cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
unsigned int group_id,
cfg_group_inst_t **new_group);
/* Remove an instance from a group array.
* inst must point to an instance within meta->array.
* *_new_array is set to the newly allocated array. */
int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
cfg_group_inst_t *inst,
cfg_group_inst_t **_new_array);
/* clones a string to shared memory */
int cfg_clone_str(str *src, str *dst);
/* Find the group instance within the meta-data based on the group_id */
cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id);
/* append new callbacks to the end of the child callback list
*
* WARNING: the function is unsafe, either hold CFG_LOCK(),
@ -324,7 +497,7 @@ void cfg_install_child_cb(cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
* cb_first and cb_last define a linked list of per-child process
* callbacks. This list is added to the global linked list.
*/
void cfg_install_global(cfg_block_t *block, char **replaced,
void cfg_install_global(cfg_block_t *block, void **replaced,
cfg_child_cb_t *cb_first, cfg_child_cb_t *cb_last);
/* creates a structure for a per-child process callback */
@ -333,6 +506,53 @@ cfg_child_cb_t *cfg_child_cb_new(str *gname, str *name,
unsigned int type);
/* free the memory allocated for a child cb list */
void cfg_child_cb_free(cfg_child_cb_t *child_cb_first);
void cfg_child_cb_free_list(cfg_child_cb_t *child_cb_first);
/* Allocate memory for a new additional variable
* and link it to a configuration group.
* type==0 results in creating a new group instance with the default values.
* The group is created with CFG_GROUP_UNKNOWN type if it does not exist.
* Note: this function is usable only before the configuration is shmized.
*/
int new_add_var(str *group_name, unsigned int group_id, str *var_name,
void *val, unsigned int type);
/* Move the group handle to the specified group instance. */
int cfg_select(cfg_group_t *group, unsigned int id);
/* Reset the group handle to the default, local configuration */
int cfg_reset(cfg_group_t *group);
/* Move the group handle to the first group instance.
* This function together with cfg_select_next() can be used
* to iterate though the list of instances.
*
* Return value:
* -1: no group instance found
* 0: first group instance is successfully selected.
*/
int cfg_select_first(cfg_group_t *group);
/* Move the group handle to the next group instance.
* This function together with cfg_select_first() can be used
* to iterate though the list of instances.
*
* Return value:
* -1: no more group instance found. Note, that the active group
* instance is not changed in this case.
* 0: the next group instance is successfully selected.
*/
int cfg_select_next(cfg_group_t *group);
/* Temporary set the local configuration in the main process before forking.
* This makes the group instances usable in the main process after
* the configuration is shmized, but before the children are forked.
*/
void cfg_main_set_local(void);
/* Reset the local configuration of the main process back to its original state
* to make sure that the forked processes are not affected.
*/
void cfg_main_reset_local(void);
#endif /* _CFG_STRUCT_H */

@ -119,8 +119,14 @@ struct cfg_group_core default_core_cfg = {
-1, /**< udp4_raw_ttl (auto detect by default) */
0, /*!< force_rport */
L_DBG, /*!< memlog */
3 /*!< mem_summary -flags: 0 off, 1 pkg_status, 2 shm_status,
4 pkg_sums, 8 shm_sums */
3, /*!< mem_summary -flags: 0 off, 1 pkg_status, 2 shm_status,
4 pkg_sums, 8 shm_sums, 16 short_status */
0, /*!< mem_safety - 0 disabled */
0, /*!< mem_join - 0 disabled */
L_ERR, /*!< corelog */
L_ERR, /*!< latency log */
0, /*!< latency limit db */
0 /*!< latency limit action */
};
void *core_cfg = &default_core_cfg;
@ -300,12 +306,25 @@ cfg_def_t core_cfg_def[] = {
"force rport for all the received messages" },
{"memlog", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"log level for memory status/summary information"},
{"mem_summary", CFG_VAR_INT|CFG_ATOMIC, 0, 15, 0, 0,
{"mem_summary", CFG_VAR_INT|CFG_ATOMIC, 0, 31, 0, 0,
"memory debugging information displayed on exit (flags): "
" 0 - off,"
" 1 - dump all the pkg used blocks (status),"
" 2 - dump all the shm used blocks (status),"
" 4 - summary of pkg used blocks,"
" 8 - summary of shm used blocks" },
" 8 - summary of shm used blocks,"
" 16 - short status instead of dump" },
{"mem_safety", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"safety level for memory operations"},
{"mem_join", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"join free memory fragments"},
{"corelog", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"log level for non-critical core error messages"},
{"latency_log", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"log level for latency limits alert messages"},
{"latency_limit_db", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"limit is ms for alerting on time consuming db commands"},
{"latency_limit_action", CFG_VAR_INT|CFG_ATOMIC, 0, 0, 0, 0,
"limit is ms for alerting on time consuming config actions"},
{0, 0, 0, 0, 0, 0}
};

@ -108,6 +108,12 @@ struct cfg_group_core {
int force_rport; /*!< if set rport will always be forced*/
int memlog; /*!< log level for memory status/summary info */
int mem_summary; /*!< display memory status/summary info on exit */
int mem_safety; /*!< memory safety control option */
int mem_join; /*!< memory free fragments join option */
int corelog; /*!< log level for non-critcal core error messages */
int latency_log; /*!< log level for latency limits messages */
int latency_limit_db; /*!< alert limit of running db commands */
int latency_limit_action; /*!< alert limit of running cfg actions */
};
extern struct cfg_group_core default_core_cfg;

@ -163,7 +163,7 @@ void cfg_parser_close(struct cfg_parser* st);
struct cfg_option* cfg_lookup_token(struct cfg_option* options, str* token);
/*! ! \briefInterface to the lexical scanner */
/*! ! \brief Interface to the lexical scanner */
int cfg_get_token(struct cfg_token* token, struct cfg_parser* st, unsigned int flags);
/* Commonly needed parser functions */

@ -141,7 +141,7 @@
#define SRV_MAX_PREFIX_LEN SRV_TLS_PREFIX_LEN
#ifndef PKG_MEM_SIZE
#define PKG_MEM_SIZE 16
#define PKG_MEM_SIZE 4
#endif
#define PKG_MEM_POOL_SIZE PKG_MEM_SIZE*1024*1024 /*!< used only if PKG_MALLOC is defined*/
@ -166,7 +166,7 @@
#define MAX_RECEIVED_SIZE 57 /*!< forwarding -- Via buffer dimensioning - Received header */
#define MAX_RPORT_SIZE 13 /*!< forwarding -- Via buffer dimensioning - Rport */
#define MAX_BRANCHES 24 /*!< maximum number of branches per transaction */
#define MAX_BRANCHES 12 /*!< maximum number of branches per transaction */
#define MAX_PRINT_TEXT 256 /*!< max length of the text of fifo 'print' command */

@ -37,9 +37,13 @@
#include "dprint.h"
#include "core_cmd.h"
#include "globals.h"
#include "forward.h"
#include "socket_info.h"
#include "name_alias.h"
#include "pt.h"
#include "ut.h"
#include "tcp_info.h"
#include "tcp_conn.h"
#include "tcp_options.h"
#include "core_cmd.h"
#include "cfg_core.h"
@ -412,6 +416,27 @@ static void core_ps(rpc_t* rpc, void* c)
}
}
static const char* core_psx_doc[] = {
"Returns the detailed description of running SER processes.",
/* Documentation string */
0 /* Method signature(s) */
};
static void core_psx(rpc_t* rpc, void* c)
{
int p;
void *handle;
for (p=0; p<*process_count;p++) {
rpc->add(c, "{", &handle);
rpc->struct_add(handle, "dds",
"IDX", p,
"PID", pt[p].pid,
"DSC", pt[p].desc);
}
}
static const char* core_pwd_doc[] = {
"Returns the working directory of SER server.", /* Documentation string */
@ -655,10 +680,12 @@ static void core_tcpinfo(rpc_t* rpc, void* c)
if (!tcp_disable){
tcp_get_info(&ti);
rpc->add(c, "{", &handle);
rpc->struct_add(handle, "dddd",
rpc->struct_add(handle, "dddddd",
"readers", ti.tcp_readers,
"max_connections", ti.tcp_max_connections,
"max_tls_connections", ti.tls_max_connections,
"opened_connections", ti.tcp_connections_no,
"opened_tls_connections", ti.tls_connections_no,
"write_queued_bytes", ti.tcp_write_queued
);
}else{
@ -685,11 +712,12 @@ static void core_tcp_options(rpc_t* rpc, void* c)
if (!tcp_disable){
tcp_options_get(&t);
rpc->add(c, "{", &handle);
rpc->struct_add(handle, "dddddddddddddddddddddd",
rpc->struct_add(handle, "ddddddddddddddddddddddd",
"connect_timeout", t.connect_timeout_s,
"send_timeout", TICKS_TO_S(t.send_timeout),
"connection_lifetime", TICKS_TO_S(t.con_lifetime),
"max_connections(soft)", t.max_connections,
"max_tls_connections(soft)", t.max_tls_connections,
"no_connect", t.no_connect,
"fd_cache", t.fd_cache,
"async", t.async,
@ -718,6 +746,89 @@ static void core_tcp_options(rpc_t* rpc, void* c)
}
static const char* core_tcp_list_doc[] = {
"Returns tcp connections details.", /* Documentation string */
0 /* Method signature(s) */
};
extern gen_lock_t* tcpconn_lock;
extern struct tcp_connection** tcpconn_id_hash;
static void core_tcp_list(rpc_t* rpc, void* c)
{
#ifdef USE_TCP
char src_ip[IP_ADDR_MAX_STR_SIZE];
char dst_ip[IP_ADDR_MAX_STR_SIZE];
void* handle;
char* state;
char* type;
struct tcp_connection* con;
int i, len, timeout;
TCPCONN_LOCK;
for(i = 0; i < TCP_ID_HASH_SIZE; i++) {
for (con = tcpconn_id_hash[i]; con; con = con->id_next) {
rpc->add(c, "{", &handle);
/* tcp data */
if (con->rcv.proto == PROTO_TCP)
type = "TCP";
else if (con->rcv.proto == PROTO_TCP)
type = "TLS";
else
type = "UNKNOWN";
if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip)))
== 0)
BUG("failed to convert source ip");
src_ip[len] = 0;
if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip)))
== 0)
BUG("failed to convert destination ip");
dst_ip[len] = 0;
timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
switch(con->state) {
case S_CONN_ERROR:
state = "CONN_ERROR";
break;
case S_CONN_BAD:
state = "CONN_BAD";
break;
case S_CONN_OK:
state = "CONN_OK";
break;
case S_CONN_INIT:
state = "CONN_INIT";
break;
case S_CONN_EOF:
state = "CONN_EOF";
break;
case S_CONN_ACCEPT:
state = "CONN_ACCEPT";
break;
case S_CONN_CONNECT:
state = "CONN_CONNECT";
break;
default:
state = "UNKNOWN";
}
rpc->struct_add(handle, "dssdsdsd",
"id", con->id,
"type", type,
"state", state,
"timeout", timeout,
"src_ip", src_ip,
"src_port", con->rcv.src_port,
"dst_ip", dst_ip,
"dst_port", con->rcv.dst_port);
}
}
TCPCONN_UNLOCK;
#else
rpc->fault(c, 500, "tcp support not compiled");
#endif
}
static const char* core_sctp_options_doc[] = {
"Returns active sctp options. With one parameter"
@ -866,6 +977,96 @@ static void core_udp4rawinfo(rpc_t* rpc, void* c)
#endif /* USE_RAW_SOCKS */
}
/**
*
*/
static const char* core_aliases_list_doc[] = {
"List local SIP server host aliases", /* Documentation string */
0 /* Method signature(s) */
};
/**
* list the name aliases for SIP server
*/
static void core_aliases_list(rpc_t* rpc, void* c)
{
void *hr;
void *ha;
struct host_alias* a;
rpc->add(c, "{", &hr);
rpc->struct_add(hr, "s",
"myself_callbacks", is_check_self_func_list_set()?"yes":"no");
for(a=aliases; a; a=a->next) {
rpc->struct_add(hr, "{", "alias", &ha);
rpc->struct_add(ha, "sS",
"proto", proto2a(a->proto),
"address", &a->alias
);
if (a->port)
rpc->struct_add(ha, "d",
"port", a->port);
else
rpc->struct_add(ha, "s",
"port", "*");
}
}
/**
*
*/
static const char* core_sockets_list_doc[] = {
"List local SIP server listen sockets", /* Documentation string */
0 /* Method signature(s) */
};
/**
* list listen sockets for SIP server
*/
static void core_sockets_list(rpc_t* rpc, void* c)
{
void *hr;
void *ha;
struct socket_info *si;
struct socket_info** list;
struct addr_info* ai;
unsigned short proto;
proto=PROTO_UDP;
rpc->add(c, "{", &hr);
do{
list=get_sock_info_list(proto);
for(si=list?*list:0; si; si=si->next){
rpc->struct_add(hr, "{", "socket", &ha);
if (si->addr_info_lst){
rpc->struct_add(ha, "ss",
"proto", get_proto_name(proto),
"address", si->address_str.s);
for (ai=si->addr_info_lst; ai; ai=ai->next)
rpc->struct_add(ha, "ss",
"address", ai->address_str.s);
rpc->struct_add(ha, "sss",
"proto", si->port_no_str.s,
"mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
"mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
} else {
printf(" %s: %s",
get_proto_name(proto),
si->name.s);
rpc->struct_add(ha, "ss",
"proto", get_proto_name(proto),
"address", si->name.s);
if (!si->flags & SI_IS_IP)
rpc->struct_add(ha, "ss",
"ipaddress", si->address_str.s);
rpc->struct_add(ha, "sss",
"proto", si->port_no_str.s,
"mcast", si->flags & SI_IS_MCAST ? "yes" : "no",
"mhomed", si->flags & SI_IS_MHOMED ? "yes" : "no");
}
}
} while((proto=next_proto(proto)));
}
/*
@ -889,6 +1090,7 @@ static rpc_export_t core_rpc_methods[] = {
0 },
{"core.uptime", core_uptime, core_uptime_doc, 0 },
{"core.ps", core_ps, core_ps_doc, RET_ARRAY},
{"core.psx", core_psx, core_psx_doc, 0},
{"core.pwd", core_pwd, core_pwd_doc, RET_ARRAY},
{"core.arg", core_arg, core_arg_doc, RET_ARRAY},
{"core.kill", core_kill, core_kill_doc, 0 },
@ -898,11 +1100,14 @@ static rpc_export_t core_rpc_methods[] = {
#endif
{"core.tcp_info", core_tcpinfo, core_tcpinfo_doc, 0},
{"core.tcp_options", core_tcp_options, core_tcp_options_doc,0},
{"core.tcp_list", core_tcp_list, core_tcp_list_doc,0},
{"core.sctp_options", core_sctp_options, core_sctp_options_doc,
0},
{"core.sctp_info", core_sctpinfo, core_sctpinfo_doc, 0},
{"core.udp4_raw_info", core_udp4rawinfo, core_udp4rawinfo_doc,
0},
{"core.aliases_list", core_aliases_list, core_aliases_list_doc, 0},
{"core.sockets_list", core_sockets_list, core_sockets_list_doc, 0},
#ifdef USE_DNS_CACHE
{"dns.mem_info", dns_cache_mem_info, dns_cache_mem_info_doc,
0 },

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2010 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -15,11 +13,16 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** macros used for various core statistics.
* (if USE_CORE_STATS is not defined they won't do anything)
* @file core_stats.h
/**
* @brief Macros used for various core statistics
*
* Macros used for various core statistics, (if USE_CORE_STATS is not defined
* they won't do anything).
* @file
* @ingroup core
*/
/*
* History:
* --------

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2010 iptelorg GmbH
*
* Permission to use, copy, modify, and distribute this software for any
@ -15,10 +13,13 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/** counters/stats.
* @file counters.c
/**
* @brief counters/stats
* @file
* @ingroup: core
*/
/*
* History:
* --------
@ -202,10 +203,10 @@ int counters_prefork_init(int max_process_no)
/* replace the temporary pre-fork pkg array (with only 1 row) with
the final shm version (with max_process_no rows) */
old = _cnts_vals;
_cnts_vals = shm_malloc(max_process_no * row_size);
_cnts_vals = shm_malloc(size);
if (_cnts_vals == 0)
return -1;
memset(_cnts_vals, 0, max_process_no * row_size);
memset(_cnts_vals, 0, size);
cnts_max_rows = max_process_no;
/* copy prefork values into the newly shm array */
if (old) {

@ -87,8 +87,8 @@ extern int _cnts_row_len; /* number of elements per row */
int init_counters();
void destroy_counters();
int init_counters(void);
void destroy_counters(void);
int counters_prefork_init(int max_process_no);

28
crc.c

@ -294,6 +294,34 @@ int crc32file (char *name)
fclose(fin); return OK;
}
/*!
* \brief CRC32 value from source string
* \param source_string source string
* \param hash_ret calulated CRC32
*/
void crc32_uint (str *source_string, unsigned int *hash_ret)
{
unsigned int hash;
unsigned int len;
const char *data;
hash = 0xffffffff;
data = source_string->s;
for (len = source_string->len / 4; len--; data += 4) {
hash = crc_32_tab[((unsigned char)hash) ^ data[0]] ^ (hash >> 8);
hash = crc_32_tab[((unsigned char)hash) ^ data[1]] ^ (hash >> 8);
hash = crc_32_tab[((unsigned char)hash) ^ data[2]] ^ (hash >> 8);
hash = crc_32_tab[((unsigned char)hash) ^ data[3]] ^ (hash >> 8);
}
for (len = source_string->len % 4; len--; data++) {
hash = crc_32_tab[((unsigned char)hash) ^ *data] ^ (hash >> 8);
}
*hash_ret = ~hash;
}
/*
int main(int argc, char **argv)

@ -16,5 +16,7 @@ unsigned short crcitt_string_ex( char *s, int len, register unsigned short ccitt
unsigned short crcitt_string( char *s, int len );
void crcitt_string_array( char *dst, str src[], int size );
void crc32_uint (str *source_string, unsigned int *hash_ret);
#endif /* _CRC_H_ */

@ -110,7 +110,7 @@ void daemon_status_init()
*
* @return 0 on success, -1 on error (and sets errno).
*/
int daemon_status_pre_daemonize()
int daemon_status_pre_daemonize(void)
{
int ret;

@ -28,17 +28,17 @@
#define _daemonize_h
int daemonize(char* name, int daemon_status_fd_input);
int do_suid();
int do_suid(void);
int increase_open_fds(int target);
int set_core_dump(int enable, long unsigned int size);
int mem_lock_pages();
int mem_lock_pages(void);
int set_rt_prio(int prio, int policy);
void daemon_status_init();
void daemon_status_on_fork_cleanup();
void daemon_status_init(void);
void daemon_status_on_fork_cleanup(void);
int daemon_status_send(char status);
void daemon_status_no_wait();
void daemon_status_on_fork_cleanup();
void daemon_status_no_wait(void);
void daemon_status_on_fork_cleanup(void);
#endif /*_daemonize_h */

@ -650,7 +650,7 @@ void del_nonshm_lump( struct lump** lump_list )
crt = *lump_list;
while (crt) {
if (crt->flags!=LUMPFLAG_SHMEM) {
if (!(crt->flags&LUMPFLAG_SHMEM)) {
/* unlink it */
foo = crt;
crt = crt->next;
@ -665,7 +665,7 @@ void del_nonshm_lump( struct lump** lump_list )
prev_r = crt;
while(r){
foo=r; r=r->after;
if (foo->flags!=LUMPFLAG_SHMEM) {
if (!(foo->flags&LUMPFLAG_SHMEM)) {
prev_r->after = r;
free_lump(foo);
pkg_free(foo);
@ -678,7 +678,7 @@ void del_nonshm_lump( struct lump** lump_list )
prev_r = crt;
while(r){
foo=r; r=r->before;
if (foo->flags!=LUMPFLAG_SHMEM) {
if (!(foo->flags&LUMPFLAG_SHMEM)) {
prev_r->before = r;
free_lump(foo);
pkg_free(foo);

@ -2204,14 +2204,12 @@ inline static struct dns_rr* dns_entry_get_rr( struct dns_hash_entry* e,
{
struct dns_rr* rr;
int n;
int flags;
#ifdef DNS_WATCHDOG_SUPPORT
int servers_up;
servers_up = atomic_get(dns_servers_up);
#endif
flags=0;
for(rr=e->rr_lst, n=0;rr && (n<*no);rr=rr->next, n++);/* skip *no records*/
for(;rr;rr=rr->next){
if (

@ -195,12 +195,12 @@ void fix_dns_flags(str *gname, str *name);
int use_dns_failover_fixup(void *handle, str *gname, str *name, void **val);
int use_dns_cache_fixup(void *handle, str *gname, str *name, void **val);
int dns_cache_max_mem_fixup(void *handle, str *gname, str *name, void **val);
int init_dns_cache();
int init_dns_cache(void);
#ifdef USE_DNS_CACHE_STATS
int init_dns_cache_stats(int iproc_num);
#define DNS_CACHE_ALL_STATS "dc_all_stats"
#endif
void destroy_dns_cache();
void destroy_dns_cache(void);
void dns_hash_put(struct dns_hash_entry* e);

@ -26,6 +26,15 @@ without the need of commit. That means a kind of transaction support,
the framework can keep track of the changes (per driver) until they
are committed or rolled-back.
The framework also supports multiple versions of the core or module
configurations. Every SIP message processing or timer function starts with
the default version which can be changed runtime in the script. Hence, even if
the core/module implements a variable with a single value, it may have multiple
instances with different values in memory, and the configuration instances can be
swapped runtime. New instances of a configuration group can be added and deleted
runtime by the drivers, and all the variables in the group instances take
the default value unless their value has been explicitely set.
2. Using the framework in a module
===============================================================================
@ -130,6 +139,8 @@ Each row consists of the following items:
of the cfg framework. By default this callback is
called by all the child processes separately,
this can be changed with this flag.
Multiple values are not supported together with
the CFG_CB_ONLY_ONCE flag.
- minimum value for integers (optional)
- maximum value for integers (optional)
@ -323,10 +334,11 @@ void *h;
str gname, vname;
void *old_val, *new_val;
unsigned int val_type;
unsigned int *group_id;
if (cfg_diff_init(ctx, &h)) return -1;
while(cfg_diff_next(&h,
&gname, &vname,
&gname, &group_id, &vname,
&old_val, &new_val,
&val_type)
) {
@ -334,6 +346,11 @@ while(cfg_diff_next(&h,
}
cfg_diff_release(ctx);
-------------------------------------------------------------------------------
9. Add/delete an instance of an existing group:
cfg_add_group_inst()
cfg_del_group_inst()
5. Refreshing the configuration
===============================================================================
@ -424,3 +441,45 @@ New configuration values can be declared in the script, the syntax is:
The values can be accessed via select calls:
@cfg_get.<group_name>.<var_name>
Use the following syntax to set an additional instance of a configuration value:
<group_name>[id].<var_name> = <value>
id is an unsigned integer starting from 0, it does not have to be continuous.
Note, that not the variables but the entire configuration group can have multiple
instances, and it is possible to swap the configuration of the entire group at once
with cfg_select("group_name", id), see the example below:
custom.var1 = 1;
custom.var2 = "default string";
custom[1].var1 = 15;
custom[1].var2 = "More specific string";
custom[2].var1 = 3;
# custom[2].var2 is not set, hence, it will inherit the value of custom.var2.
# When custom.var2 changes, custom[2].var1 will be also updated.
route {
# Actual values: var1:1, var2:"default string"
cfg_select("custom", 1);
# Actual values: var1:15, var2:"More specific string"
cfg_select("custom", 2");
# Actual values: var1:3, var2:"default string"
cfg_reset("custom")
# Actual values: var1:1, var2:"default string"
}
cfg_reset("group_name") can be used to reset the configuration back to the original values.
The values are automatically reseted before each SIP message is started to be processed, or after
each timer function execution.
The above example with custom variables is supported also with module and core configuration
groups. The only restriction is that variables with CFG_CB_ONLY_ONCE flag cannot have
multiple values.

@ -511,10 +511,12 @@
memory debugging information displayed on exit (flags): 0 -
off, 1 - dump all the pkg used blocks (status), 2 - dump all
the shm used blocks (status), 4 - summary of pkg used blocks, 8
- summary of shm used blocks.
- summary of shm used blocks, 16 - show only summary of used
blocks instead of full dump (to use in conjuntion with flags 1
and 2).
</para>
<para>Default value: 3.</para>
<para>Range: 0 - 15.</para>
<para>Range: 0 - 31.</para>
<para>Type: integer.</para>
<para>
</para>

@ -1,4 +1,4 @@
1. SER Management Interface
1. RPC Control Interface
__________________________________________________________________
1.1. Overview of Operation
@ -10,6 +10,7 @@
1.2.3.1. scan
1.2.3.2. struct_scan
1.2.3.3. Retrieving Parameters Example
1.2.4. Building Reply
@ -27,14 +28,14 @@
1.1. Overview of Operation
The RPC (Remote Procedure Call) interface of SER is an interface for
The RPC (Remote Procedure Call) interface is an interface for
communicating with external applications. Using it an external
application can call a function or procedure that will be executed
inside SER. Function parameters are supported as well as returning
multiple values as results.
inside SIP Server (SER or Kamailio). Function parameters are supported
as well as returning multiple values as results.
By itself SER RPC consists of two APIs, one for defining RPC functions
in a transport independent way (called the rpc module api) and one for
By itself RPC consists of two APIs, one for defining RPC functions in a
transport independent way (called the rpc module api) and one for
implementing RPC transports.
The RPC transports are implemented by writting a RPC transport module.
@ -45,8 +46,8 @@
information about the existing transport modules, please refer to their
documentation.
When writing a SER RPC procedure or function, one needs only use the
RPC API and it will work automatically with all the transports and
When writing a RPC procedure or function, one needs only use the RPC
API and it will work automatically with all the transports and
encodings. One needs only to load the desired RPC transport module
(e.g. xmlrpc).
@ -56,11 +57,12 @@
1.2. Module API
Each SER module can export RPC functions just like it can export
parameters and functions to be called from the script. Whenever SER
Each module can export RPC functions just like it can export parameters
and functions to be called from the script. Whenever SIP server
receives an RPC request, it will search through the list of exported
RPC functions and the function with matching name will be executed. A
couple of essential RPC functions are also embedded into the SER core.
couple of essential RPC functions are also embedded into the SIP server
core.
This section gives a detailed overview of the whole RPC API.
Section 1.2.1, "RPC Functions" describes the prototype and conventions
@ -82,14 +84,14 @@
1.2.1. RPC Functions
RPC functions are standard C functions with the following prototype:
typedef void (*rpc_function_t)(rpc_t* rpc);
RPC functions take one parameter, this parameter is a pointer to rpc_t
structure and is called RPC context. The context contains references to
all API functions available to the RPC function as well as all data
necessary to create the response. RPC functions do not return any
value, instead the return value is created using functions from the
context. The motivation for this decision is the fact that RPC
typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
RPC functions take two parameters, first parameter is a pointer to
rpc_t structure and the context. The rpc_t structure contains
references to all API functions available to the RPC function as well
as all data necessary to create the response. RPC functions do not
return any value, instead the return value is created using functions
from the context. The motivation for this decision is the fact that RPC
functions should always return a response and even the API functions
called from RPC functions should have the possibility to indicate an
error (and should not rely on RPC functions doing so).
@ -108,7 +110,7 @@ typedef void (*rpc_function_t)(rpc_t* rpc);
function with "_doc" suffix.
Each module containing RPC functions has to export all the RPC
functions to SER core in order to make them visible to the RPC
functions to SIP server core in order to make them visible to the RPC
transport modules. The export process involves a rpc_export_t structure
(either by itself or in an array):
typedef struct rpc_export {
@ -122,13 +124,14 @@ ription */
The flags attribute of the rpc_export structure is reserved for future
use and is currently unused.
There are several ways of exporting the RPC functions to the SER core:
There are several ways of exporting the RPC functions to the SIP server
core:
* register a null terminated array of rpc_export_t structures using
the rpc_register_array() function (defined in rpc_lookup.h), from
the module init function (mod_init()). This is the recommended
method for all the new modules.
Example 1.
The rpc_export_t array for the usrloc module looks like:
Example 1. usrloc RPC Exports Declaration
The rpc_export_t array for the modules_s/usrloc module looks like:
rpc_export_t ul_rpc[] = {
{"usrloc.statistics", rpc_stats, rpc_stats_doc, 0},
{"usrloc.delete_aor", rpc_delete_aor, rpc_delete_aor_doc, 0},
@ -149,9 +152,9 @@ rpc_export_t ul_rpc[] = {
* register RPCs one by one using the rpc_register_function() (defined
in rpc_lookup.h), from the module init function.
* register a null terminated array of rpc_export_t structures using
the SER module interface. For this purpose, the module_exports
structure of SER module API contains a new attribute called
rpc_methods:
the SIP server module interface SER_MOD_INTERFACE (specific for SER
flavour). For this purpose, the module_exports structure of SIP
server module API contains a new attribute called rpc_methods:
struct module_exports {
char* name; /* null terminated module name */
cmd_export_t* cmds; /* null terminated array of the exported command
@ -163,7 +166,7 @@ parameters */
init_function init_f; /* Initialization function */
response_function response_f; /* function used for responses */
destroy_function destroy_f; /* function called upon SER shutdown */
destroy_function destroy_f; /* function called upon shutdown */
onbreak_function onbreak_f;
child_init_function init_child_f; /* function called by all processes after
the fork */
@ -171,10 +174,10 @@ parameters */
rpc_methods is a pointer to an array of rpc_export_t structures.
The last element of the array is a bumper containing zeroes in all
the attributes of the structure. The following program listing
shows the exported RPC functions of the usrloc module, using the
rpc_export_t array ul_rpc defined above, in the
shows the exported RPC functions of the modules_s/usrloc module,
using the rpc_export_t array ul_rpc defined above, in the
rpc_register_array() example:
Example 2.
Example 2. usrloc Module Exports Declaration
struct module_exports exports = {
"usrloc",
cmds, /* Exported functions */
@ -187,15 +190,15 @@ struct module_exports exports = {
child_init /* Child initialization function */ };
Note
This mode works only with modules using the SER module interface.
It does not work for kamailio modules and it will probably not work
for future sip-router modules. It is safer and recommended to use
instead the rpc_register_array() function.
This mode works only with modules using the SER flavour module
interface. It does not work for kamailio modules and it will
probably not work for future sip-router modules. It is safer and
recommended to use instead the rpc_register_array() function.
By convention the name of every exported function consists of two parts
delimited by a dot. The first part is the name of the module or SER
subsystem this function belongs to. The second part is the name of the
function.
delimited by a dot. The first part is the name of the module or SIP
server subsystem this function belongs to. The second part is the name
of the function.
1.2.2. Data Types
@ -311,17 +314,17 @@ Warning
used and the error is lack of more parameters).
The prototype of the function is:
int scan(char* fmt, ...)
int scan((void* ctx, char* fmt, ...)
It is possible to either call the function once to scan all the
parameters:
rpc->scan("sdf", &string_val, &int_val, &double_val);
rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
Or you can call the same function several times and it will continue
where it left off previously:
rpc->scan("s", &string_val);
rpc->scan("d", &int_val);
rpc->scan("f", &double_val);
rpc->scan(ctx, "s", &string_val);
rpc->scan(ctx, "d", &int_val);
rpc->scan(ctx, "f", &double_val);
1.2.3.2. struct_scan
@ -334,7 +337,7 @@ Note
(e.g.: ctl / binrpc). Consider using the normal scan instead.
When retrieving a structure parameter from the parameter set:
rpc->scan("{", &handle);
rpc->scan(ctx, "{", &handle);
The corresponding variable (named handle in the example above) will
contain the index of the structure parameter within the parameter set,
@ -352,8 +355,10 @@ rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
the scan function). The function also indicates an error if a requested
attribute is missing in the structure.
1.2.3.3. Retrieving Parameters Example
Example 3. Retrieving Parameters
static void rpc_delete_contact(rpc_t* rpc)
static void rpc_delete_contact(rpc_t* rpc, void* ctx)
{
str aor, contact;
char* table;
@ -361,7 +366,7 @@ static void rpc_delete_contact(rpc_t* rpc)
int expires;
double q;
if (rpc->scan("sS{", &table, &aor, &handle) < 0) {
if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
/* Reply is set automatically by scan upon failure,
* no need to do anything here
*/
@ -417,7 +422,7 @@ static void core_echo(rpc_t* rpc, void* c)
the reply-related functions described in this section.
Example 4. Sending default reply
static void rpc_dummy(rpc_t* rpc)
static void rpc_dummy(rpc_t* rpc, void *ctx)
{
/* 200 OK with no data will be returned */
}
@ -428,41 +433,41 @@ static void rpc_dummy(rpc_t* rpc)
the server to the caller. The function accepts two parameters. The
first parameter is the status code and the second parameter is the
reason phrase.
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
}
If your function first creates some result using add, or printf
functions then all the data will be lost once you call fault function.
Failure replies must not contain any data:
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->add("s", "result1");
rpc->add("d", variable);
rpc->add(ctx, "s", "result1");
rpc->add(ctx, "d", variable);
/* Reply created by previous functions will be
* deleted and a failure reply 600 Not Yet Implemented
* will be created instead
*/
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
/* You can also add data here, but that will have no
* effect
*/
rpc->add("s", "result2");
rpc->add(ctx, "s", "result2");
}
Similarly you can also call add or printf functions after calling
fault, in this case they will have no effect:
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
/* You can also add data here, but that will have no
* effect and only 600 Not Yet Implemented will be returned
*/
rpc->add("s", "result2");
rpc->add(ctx, "s", "result2");
}
1.2.4.2. send
@ -475,12 +480,12 @@ static void rpc_my_function(rpc_t* rpc)
the reply has been sent.
Example 5. Kill the server
static void core_kill(rpc_t* rpc)
static void core_kill(rpc_t* rpc, void *ctx)
{
int sig_no;
if (rpc->scan("d", &sig_no) < 0) return;
rpc->send(); /* First send a reply */
if (rpc->scan(ctx, "d", &sig_no) < 0) return;
rpc->send(ctx, ); /* First send a reply */
kill(0, sig_no); /* Then kill the server */
}
@ -490,15 +495,15 @@ static void core_kill(rpc_t* rpc)
parameters and use are analogical to scan function described in
Section 1.2.3.1, "scan". The first parameter of the function is the
formatting string that determines the types of additional parameters:
static void rpc_func(rpc_t* rpc)
static void rpc_func(rpc_t* rpc, void *ctx)
{
str str_result;
int int_result;
void *handle;
double float_result;
if (rpc->add("Sdf{", &str_result, int_result, float_result, &handle) < 0) re
turn;
if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) <
0) return;
}
Naturally you can call this function several times, adding only one
@ -523,8 +528,8 @@ turn;
printf is a convenience function. The function adds data of type string
to the result set. The first parameter of the function is again a
formatting string, but this time it is printf-like formatting string:
if (rpc->printf("Unable to delete %d entries from table %s", num_entries, table_
name) < 0) return;
if (rpc->printf(ctx, "Unable to delete %d entries from table %s", num_entries, t
able_name) < 0) return;
The return value of the function is the same as of add function.
@ -539,12 +544,12 @@ name) < 0) return;
second parameter is the value of the attribute. If a parameter with
such a name already exist in the structure then it will be overwritten
with the new value.
static void rpc_func(rpc_t* rpc)
static void rpc_func(rpc_t* rpc, void *ctx)
{
void *handle;
/* Create empty structure and obtain its handle */
if (rpc->add("{", &handle) < 0) return;
if (rpc->add(ctx, "{", &handle) < 0) return;
/* Fill-in the structure */
if (rpc->struct_add(handle, "sd", "attr1", str_val,
"attr2", int_val ) < 0)
@ -560,7 +565,7 @@ static void rpc_func(rpc_t* rpc)
the API together:
Example 6. Real World Example RPC Function
static void rpc_register(rpc_t* rpc)
static void rpc_register(rpc_t* rpc, void *ctx)
{
char* domain;
str aor;
@ -568,7 +573,7 @@ static void rpc_register(rpc_t* rpc)
void *handle;
/* Extract the domain, address of record from the request */
if (rpc->scan("sS{", &domain, &aor, &handle) < 0) return;
if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
/* Extract the structure describing the contact to be processed */
if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
"Expires", &contact.expires,
@ -579,12 +584,12 @@ static void rpc_register(rpc_t* rpc)
cessing */
if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
/* Processing failed, indicate the failure to the caller */
rpc->fault(500, "Error While Processing Contact");
rpc->fault(ctx, 500, "Error While Processing Contact");
return;
}
/* Return the domain and the address of record */
rpc->add("sS{", &domain, &aor, &handle) < 0) return;
rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
/* And also add the new values for contact, q, and expires parameters */
rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
"Expires", &new_contact.expires,

@ -5,7 +5,7 @@
"xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">]
>
<section id="ser_rpc" xmlns:xi="http://www.w3.org/2001/XInclude">
<section id="rpc.main" xmlns:xi="http://www.w3.org/2001/XInclude">
<!--
<sectioninfo>
<releaseinfo role="cvs">$Revision$</releaseinfo>
@ -14,20 +14,20 @@
-->
<title>
SER Management Interface
RPC Control Interface
</title>
<section id="rpc.overview">
<title>Overview of Operation</title>
<para>
The RPC (Remote Procedure Call) interface of SER is an interface for
The RPC (Remote Procedure Call) interface is an interface for
communicating with external applications. Using it an external
application can call a function or procedure that will be executed
inside SER. Function parameters are supported as well as returning
multiple values as results.
inside SIP Server (SER or Kamailio). Function parameters are
supported as well as returning multiple values as results.
</para>
<para>
By itself SER RPC consists of two APIs, one for defining RPC functions
By itself RPC consists of two APIs, one for defining RPC functions
in a transport independent way (called the rpc module api) and one
for implementing RPC transports.
</para>
@ -49,7 +49,7 @@
refer to their documentation.
</para>
<para>
When writing a SER RPC procedure or function, one needs only use the
When writing a RPC procedure or function, one needs only use the
RPC API and it will work automatically with all the transports and
encodings. One needs only to load the desired RPC transport module
(e.g. xmlrpc).
@ -64,12 +64,12 @@
<section id="rpc.module_api">
<title>Module API</title>
<para>
Each SER module can export RPC functions just like it can export
parameters and functions to be called from the script. Whenever SER
Each module can export RPC functions just like it can export
parameters and functions to be called from the script. Whenever SIP server
receives an RPC request, it will search through the list of
exported RPC functions and the function with matching name will be
executed. A couple of essential RPC functions are also embedded into
the SER core.
the SIP server core.
</para>
<para>
This section gives a detailed overview of the whole RPC API. <xref
@ -97,10 +97,10 @@
RPC functions are standard C functions with the following
prototype:
<programlisting>
typedef void (*rpc_function_t)(rpc_t* rpc);
typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
</programlisting>
RPC functions take one parameter, this parameter is a pointer
to rpc_t structure and is called RPC context. The context
RPC functions take two parameters, first parameter is a pointer
to rpc_t structure and the context. The rpc_t structure
contains references to all API functions available to the RPC
function as well as all data necessary to create the
response. RPC functions do not return any value, instead the
@ -129,7 +129,7 @@ typedef void (*rpc_function_t)(rpc_t* rpc);
</para>
<para>
Each module containing RPC functions has to export all the
RPC functions to SER core in order to make them visible to the RPC
RPC functions to SIP server core in order to make them visible to the RPC
transport modules.
The export process involves a <emphasis>rpc_export_t</emphasis>
structure (either by itself or in an array):
@ -150,7 +150,7 @@ typedef struct rpc_export {
use and is currently unused.
</para>
<para>
There are several ways of exporting the RPC functions to the SER core:
There are several ways of exporting the RPC functions to the SIP server core:
<itemizedlist>
<listitem><para>
register a null terminated array of rpc_export_t structures
@ -160,7 +160,7 @@ typedef struct rpc_export {
method for all the new modules.
<example><title>usrloc RPC Exports Declaration</title>
<para>
The <varname>rpc_export_t</varname> array for the usrloc
The <varname>rpc_export_t</varname> array for the modules_s/usrloc
module looks like:
</para>
<programlisting>
@ -196,9 +196,10 @@ rpc_export_t ul_rpc[] = {
</para></listitem>
<listitem><para>
register a null terminated array of rpc_export_t structures
using the SER module interface.
using the SIP server module interface SER_MOD_INTERFACE (specific
for SER flavour).
For this purpose, the
<varname>module_exports</varname> structure of SER module API
<varname>module_exports</varname> structure of SIP server module API
contains a new attribute called <varname>rpc_methods</varname>:
<programlisting>
struct module_exports {
@ -209,7 +210,7 @@ struct module_exports {
init_function init_f; /* Initialization function */
response_function response_f; /* function used for responses */
destroy_function destroy_f; /* function called upon SER shutdown */
destroy_function destroy_f; /* function called upon shutdown */
onbreak_function onbreak_f;
child_init_function init_child_f; /* function called by all processes after the fork */
};
@ -218,7 +219,7 @@ struct module_exports {
rpc_export_t structures. The last element of the array is a
bumper containing zeroes in all the attributes of the
structure. The following program listing shows the exported RPC
functions of the usrloc module, using the rpc_export_t array
functions of the modules_s/usrloc module, using the rpc_export_t array
<emphasis>ul_rpc</emphasis> defined above, in the
rpc_register_array() example:
<example><title>usrloc Module Exports Declaration</title>
@ -237,7 +238,7 @@ struct module_exports exports = {
</programlisting>
</example>
<note><para>
This mode works only with modules using the SER module
This mode works only with modules using the SER flavour module
interface. It does not work for kamailio modules and it
will probably not work for future sip-router modules. It is
safer and recommended to use instead the
@ -249,7 +250,7 @@ struct module_exports exports = {
<para>
By convention the name of every exported function consists of
two parts delimited by a dot. The first part is the name of the
module or SER subsystem this function belongs to. The second
module or SIP server subsystem this function belongs to. The second
part is the name of the function.
</para>
</section>
@ -453,19 +454,19 @@ add("sd", string_param, int_param);
<para>
The prototype of the function is:
<programlisting>
int scan(char* fmt, ...)
int scan((void* ctx, char* fmt, ...)
</programlisting>
It is possible to either call the function once to scan all
the parameters:
<programlisting>
rpc->scan("sdf", &amp;string_val, &amp;int_val, &amp;double_val);
rpc->scan(ctx, "sdf", &amp;string_val, &amp;int_val, &amp;double_val);
</programlisting>
Or you can call the same function several times and it will
continue where it left off previously:
<programlisting>
rpc->scan("s", &amp;string_val);
rpc->scan("d", &amp;int_val);
rpc->scan("f", &amp;double_val);
rpc->scan(ctx, "s", &amp;string_val);
rpc->scan(ctx, "d", &amp;int_val);
rpc->scan(ctx, "f", &amp;double_val);
</programlisting>
</para>
<para>
@ -485,7 +486,7 @@ rpc->scan("f", &amp;double_val);
When retrieving a structure parameter from the
parameter set:
<programlisting>
rpc->scan("{", &amp;handle);
rpc->scan(ctx, "{", &amp;handle);
</programlisting>
The corresponding variable (named
<varname>handle</varname> in the example above) will contain
@ -515,7 +516,7 @@ rpc->struct_scan(handle, "sd", "str_attr", &amp;str_val, "int_attr", &amp;int_va
<title>Retrieving Parameters</title>
<programlisting>
<![CDATA[
static void rpc_delete_contact(rpc_t* rpc)
static void rpc_delete_contact(rpc_t* rpc, void* ctx)
{
str aor, contact;
char* table;
@ -523,7 +524,7 @@ static void rpc_delete_contact(rpc_t* rpc)
int expires;
double q;
if (rpc->scan("sS{", &table, &aor, &handle) < 0) {
if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
/* Reply is set automatically by scan upon failure,
* no need to do anything here
*/
@ -592,7 +593,7 @@ static void core_echo(rpc_t* rpc, void* c)
<title>Sending default reply</title>
<programlisting>
<![CDATA[
static void rpc_dummy(rpc_t* rpc)
static void rpc_dummy(rpc_t* rpc, void *ctx)
{
/* 200 OK with no data will be returned */
}
@ -609,9 +610,9 @@ static void rpc_dummy(rpc_t* rpc)
status code and the second parameter is the reason phrase.
<programlisting>
<![CDATA[
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
}
]]>
</programlisting>
@ -622,21 +623,21 @@ static void rpc_my_function(rpc_t* rpc)
not contain any data:
<programlisting>
<![CDATA[
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->add("s", "result1");
rpc->add("d", variable);
rpc->add(ctx, "s", "result1");
rpc->add(ctx, "d", variable);
/* Reply created by previous functions will be
* deleted and a failure reply 600 Not Yet Implemented
* will be created instead
*/
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
/* You can also add data here, but that will have no
* effect
*/
rpc->add("s", "result2");
rpc->add(ctx, "s", "result2");
}
]]>
</programlisting>
@ -646,14 +647,14 @@ static void rpc_my_function(rpc_t* rpc)
effect:
<programlisting>
<![CDATA[
static void rpc_my_function(rpc_t* rpc)
static void rpc_my_function(rpc_t* rpc, void *ctx)
{
rpc->fault(600, "Not Yet Implemented");
rpc->fault(ctx, 600, "Not Yet Implemented");
/* You can also add data here, but that will have no
* effect and only 600 Not Yet Implemented will be returned
*/
rpc->add("s", "result2");
rpc->add(ctx, "s", "result2");
}
]]>
</programlisting>
@ -675,12 +676,12 @@ static void rpc_my_function(rpc_t* rpc)
<title>Kill the server</title>
<programlisting>
<![CDATA[
static void core_kill(rpc_t* rpc)
static void core_kill(rpc_t* rpc, void *ctx)
{
int sig_no;
if (rpc->scan("d", &sig_no) < 0) return;
rpc->send(); /* First send a reply */
if (rpc->scan(ctx, "d", &sig_no) < 0) return;
rpc->send(ctx, ); /* First send a reply */
kill(0, sig_no); /* Then kill the server */
}
]]>
@ -699,14 +700,14 @@ static void core_kill(rpc_t* rpc)
determines the types of additional parameters:
<programlisting>
<![CDATA[
static void rpc_func(rpc_t* rpc)
static void rpc_func(rpc_t* rpc, void *ctx)
{
str str_result;
int int_result;
void *handle;
double float_result;
if (rpc->add("Sdf{", &str_result, int_result, float_result, &handle) < 0) return;
if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) < 0) return;
}
]]>
</programlisting>
@ -745,7 +746,7 @@ static void rpc_func(rpc_t* rpc)
string, but this time it is <function>printf</function>-like formatting string:
<programlisting>
<![CDATA[
if (rpc->printf("Unable to delete %d entries from table %s", num_entries, table_name) < 0) return;
if (rpc->printf(ctx, "Unable to delete %d entries from table %s", num_entries, table_name) < 0) return;
]]>
</programlisting>
The return value of the function is the same as of
@ -769,12 +770,12 @@ if (rpc->printf("Unable to delete %d entries from table %s", num_entries, table_
new value.
<programlisting>
<![CDATA[
static void rpc_func(rpc_t* rpc)
static void rpc_func(rpc_t* rpc, void *ctx)
{
void *handle;
/* Create empty structure and obtain its handle */
if (rpc->add("{", &handle) < 0) return;
if (rpc->add(ctx, "{", &handle) < 0) return;
/* Fill-in the structure */
if (rpc->struct_add(handle, "sd", "attr1", str_val,
"attr2", int_val ) < 0)
@ -798,7 +799,7 @@ static void rpc_func(rpc_t* rpc)
<title>Real World Example RPC Function</title>
<programlisting>
<![CDATA[
static void rpc_register(rpc_t* rpc)
static void rpc_register(rpc_t* rpc, void *ctx)
{
char* domain;
str aor;
@ -806,7 +807,7 @@ static void rpc_register(rpc_t* rpc)
void *handle;
/* Extract the domain, address of record from the request */
if (rpc->scan("sS{", &domain, &aor, &handle) < 0) return;
if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
/* Extract the structure describing the contact to be processed */
if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
"Expires", &contact.expires,
@ -816,12 +817,12 @@ static void rpc_register(rpc_t* rpc)
/* Process the contact, new_contact will contain updated value after processing */
if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
/* Processing failed, indicate the failure to the caller */
rpc->fault(500, "Error While Processing Contact");
rpc->fault(ctx, 500, "Error While Processing Contact");
return;
}
/* Return the domain and the address of record */
rpc->add("sS{", &domain, &aor, &handle) < 0) return;
rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
/* And also add the new values for contact, q, and expires parameters */
rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
"Expires", &new_contact.expires,

@ -17,35 +17,40 @@ docbook_output_dir=docbook
# make diff-list (which obeys grp_exclude and file_exclude)
# or completely regenerated by replacing files_list with the output of:
# make gen-files-list
# NOTE: suffix duplicated modules located in modules_s with '_s' to
# avoid file naming conflicts
#
files_list= \
$(COREPATH)/core_cmd.c:core \
$(COREPATH)/modules/cfg_rpc/cfg_rpc.c:cfg_rpc \
$(COREPATH)/modules/counters/counters.c:counters \
$(COREPATH)/modules/ctl/ctl.c:ctl \
$(COREPATH)/modules/db_flatstore/flat_rpc.c:db_flatstore \
$(COREPATH)/modules/debugger/debugger_api.c:debugger \
$(COREPATH)/modules/lcr/lcr_rpc.c:lcr \
$(COREPATH)/modules/malloc_test/malloc_test.c:malloc_test \
$(COREPATH)/modules/mi_rpc/mi_rpc_mod.c:mi_rpc \
$(COREPATH)/modules/sl/sl_stats.c:sl \
$(COREPATH)/modules/tls/tls_rpc.c:tls \
$(COREPATH)/modules/tm/tm.c:tm \
$(COREPATH)/modules_k/dialog/dialog.c:dialog \
$(COREPATH)/modules_k/htable/htable.c:htable \
$(COREPATH)/modules/ratelimit/ratelimit.c:ratelimit \
$(COREPATH)/modules_k/uac/uac_reg.c:uac \
$(COREPATH)/modules_k/usrloc/ul_rpc.c:usrloc_k \
$(COREPATH)/modules_s/cpl-c/cpl_rpc.c:cpl-c \
$(COREPATH)/modules_s/dispatcher/ds_rpc.c:dispatcher \
$(COREPATH)/modules_s/domain/domain_rpc.c:domain \
$(COREPATH)/modules_s/gflags/gflags.c:gflags \
$(COREPATH)/modules_s/pdt/pdt.c:pdt \
$(COREPATH)/modules_s/pike/rpc.c:pike \
$(COREPATH)/modules/prefix_route/pr_rpc.c:prefix_route \
$(COREPATH)/modules_s/presence_b2b/rpc.c:presence_b2b \
$(COREPATH)/modules_s/usrloc/ul_rpc.c:usrloc_s
$(COREPATH)/core_cmd.c:core \
$(COREPATH)/modules/cfg_rpc/cfg_rpc.c:cfg_rpc \
$(COREPATH)/modules/counters/counters.c:counters \
$(COREPATH)/modules/ctl/ctl.c:ctl \
$(COREPATH)/modules/db_flatstore/flat_rpc.c:db_flatstore \
$(COREPATH)/modules/debugger/debugger_api.c:debugger \
$(COREPATH)/modules/dialplan/dialplan.c:dialplan \
$(COREPATH)/modules/lcr/lcr_rpc.c:lcr \
$(COREPATH)/modules/malloc_test/malloc_test.c:malloc_test \
$(COREPATH)/modules/mi_rpc/mi_rpc_mod.c:mi_rpc \
$(COREPATH)/modules/prefix_route/pr_rpc.c:prefix_route \
$(COREPATH)/modules/ratelimit/ratelimit.c:ratelimit \
$(COREPATH)/modules/sl/sl_stats.c:sl \
$(COREPATH)/modules/tls/tls_rpc.c:tls \
$(COREPATH)/modules/tm/tm.c:tm \
$(COREPATH)/modules_k/dialog/dialog.c:dialog \
$(COREPATH)/modules_k/dispatcher/dispatcher.c:dispatcher \
$(COREPATH)/modules_k/domain/domain_mod.c:domain \
$(COREPATH)/modules_k/htable/htable.c:htable \
$(COREPATH)/modules_k/kex/pkg_stats.c:kex \
$(COREPATH)/modules_k/uac/uac_reg.c:uac \
$(COREPATH)/modules_k/usrloc/ul_rpc.c:usrloc \
$(COREPATH)/modules_s/cpl-c/cpl_rpc.c:cpl-c \
$(COREPATH)/modules_s/dispatcher/ds_rpc.c:dispatcher_s \
$(COREPATH)/modules_s/domain/domain_rpc.c:domain_s \
$(COREPATH)/modules_s/gflags/gflags.c:gflags \
$(COREPATH)/modules_s/pdt/pdt.c:pdt \
$(COREPATH)/modules_s/pike/rpc.c:pike \
$(COREPATH)/modules_s/presence_b2b/rpc.c:presence_b2b \
$(COREPATH)/modules_s/usrloc/ul_rpc.c:usrloc_s
# list of excluded groups
grp_exclude=pa
@ -76,15 +81,18 @@ gcc=gcc
#-I$(COREPATH)/lib -I$(COREPATH) -I/usr/include/libxml2
# defines used by gcc
c_defs=-D__CPU_i386 -D__OS_linux -DSER_VER=2099099 -DPKG_MALLOC -DSHM_MEM \
# -D__CPU_i386 -DARCH="i386"
c_defsX= -D__CPU_x86_64 -D__OS_linux -DSER_VER=3003000 -DPKG_MALLOC -DSHM_MEM \
-DVERSION='\"3.3.0-dev2\"' -DARCH='\"x86_64\"' -DOS=linux_ -DOS_QUOTED='\"linux\"' \
-DSHM_MMAP -DDNS_IP_HACK -DUSE_IPV6 -DUSE_MCAST -DUSE_TCP \
-DUSE_DNS_CACHE -DUSE_DNS_FAILOVER -DUSE_DST_BLACKLIST -DUSE_NAPTR \
-DUSE_TLS -DTLS_HOOKS -DFAST_LOCK -DCC_GCC_LIKE_ASM \
-DHAVE_GETHOSTBYNAME2 -DHAVE_UNION_SEMUN -DHAVE_SCHED_YIELD \
-DHAVE_MSG_NOSIGNAL -DHAVE_MSGHDR_MSG_CONTROL -DHAVE_ALLOCA_H \
-DHAVE_SCHED_SETSCHEDULER -DHAVE_EPOLL -DUSE_SCTP -DNAME='\"ser\"' \
-DVERSION='\"2.99.99-pre3\"' -DARCH='\"i386\"' -DOS_QUOTED='\"linux\"'
-DCFG_DIR='\"/tmp/\"'
c_defs=$(subst ^^,='\",$(subst ",\"',$(subst =",^^,$(shell make -s -C ../.. printcdefs))))
# common makefile vars used in defs
LOCALBASE=/usr/local
@ -98,7 +106,7 @@ flist=$(call filter_files,$(files_list))
# throws an error if input is not in the format filename:grp
check_fname_grp=$(if $(filter-out 2,$(words $(subst :, ,$(1)))),\
$(error bad format "$(1)", it should be filename:grp))
$(error bad format "$(1)", it should be filename:grp))
# get prereq from file:grp (get_prereq(file:grp) => file)
get_prereq=$(firstword $(subst :, ,$(1)))
@ -106,6 +114,11 @@ get_prereq=$(firstword $(subst :, ,$(1)))
# get grp from file:grp (get_grp(file:grp) => grp)
get_listed_grp=$(word 2, $(subst :, ,$(1)))
# get module interface define
get_modiface=$(word 3, $(subst :, ,$(1)))
find_modiface=$(if $(findstring modules,$(1)),$(shell make -s -C $(dir $(1)) printmiface),-DNONE)
# get base file name from file:grp: get_bname(file:grp)
# => basename(file) without extension (e.g. get_bname(foo/bar.c:x) => bar)
#
@ -188,7 +201,7 @@ $(txt_output_dir)/$$(call get_target,$(1)).txt: \
$$(call get_prereq,$(1)) Makefile $(CFG2TXT)
$(CFG2TXT) --file $$< --$(force_grp)grp=$$(call get_grp,$(1)) \
--gcc="$(gcc)" --txt \
--defs="$(c_defs) $$(e_idefs_$$(call get_grp,$(1)))" \
--defs="$(c_defs) $$(call get_modiface,$(1)) $$(e_idefs_$$(call get_grp,$(1)))" \
> "$$@" || (rm -f "$$@"; exit 1)
$(docbook_output_dir)/$$(call get_target,$(1)).xml: \
@ -333,6 +346,10 @@ gen-file-list gen-files-list gen_files_list:
@$(foreach f,$(call subst_corepath,$(call sort_files,$(f_found_lst))),\
echo "$f \\";)
print-modifaces:
@$(foreach f,$(call sort_files,$(f_found_lst)),\
echo "$(call subst_corepath,$(f)):$(call find_modiface, $(f)) \\";)
.PHONY: check-list
.PHONY: update-list
.PHONY: diff-list

@ -8,6 +8,15 @@ RPC Exports for cfg_rpc
</title>
<section id="cfg.set"><title>cfg.set</title>
<para>
Set the value of a configuration variable and commit the change
immediately
</para>
<para>
</para>
</section>
<section id="cfg.set_now_int"><title>cfg.set_now_int</title>
<para>
Set the value of a configuration variable and commit the change
@ -17,6 +26,15 @@ RPC Exports for cfg_rpc
</para>
</section>
<section id="cfg.seti"><title>cfg.seti</title>
<para>
Set the value of a configuration variable and commit the change
immediately
</para>
<para>
</para>
</section>
<section id="cfg.set_now_string"><title>cfg.set_now_string</title>
<para>
Set the value of a configuration variable and commit the change
@ -26,6 +44,33 @@ RPC Exports for cfg_rpc
</para>
</section>
<section id="cfg.sets"><title>cfg.sets</title>
<para>
Set the value of a configuration variable and commit the change
immediately
</para>
<para>
</para>
</section>
<section id="cfg.del"><title>cfg.del</title>
<para>
Delete the value of a configuration variable from a group
instance and commit the change immediately
</para>
<para>
</para>
</section>
<section id="cfg.set_delayed"><title>cfg.set_delayed</title>
<para>
Prepare the change of a configuration variable, but does not
commit the new value yet
</para>
<para>
</para>
</section>
<section id="cfg.set_delayed_int"><title>cfg.set_delayed_int</title>
<para>
Prepare the change of a configuration variable, but does not
@ -44,6 +89,15 @@ RPC Exports for cfg_rpc
</para>
</section>
<section id="cfg.del_delayed"><title>cfg.del_delayed</title>
<para>
Prepare the deletion of the value of a configuration variable
from a group instance, but does not commit the change yet
</para>
<para>
</para>
</section>
<section id="cfg.commit"><title>cfg.commit</title>
<para>
Commit the previously prepared configuration changes
@ -93,4 +147,20 @@ RPC Exports for cfg_rpc
</para>
</section>
<section id="cfg.add_group_inst"><title>cfg.add_group_inst</title>
<para>
Add a new instance to an existing configuration group
</para>
<para>
</para>
</section>
<section id="cfg.del_group_inst"><title>cfg.del_group_inst</title>
<para>
Delte an instance of a configuration group
</para>
<para>
</para>
</section>
</chapter>

@ -102,6 +102,14 @@ RPC Exports for core
</para>
</section>
<section id="core.psx"><title>core.psx</title>
<para>
Returns the detailed description of running SER processes.
</para>
<para>
</para>
</section>
<section id="core.pwd"><title>core.pwd</title>
<para>
Returns the working directory of SER server.

@ -10,7 +10,7 @@ RPC Exports for db_flatstore
<section id="flatstore.rotate"><title>flatstore.rotate</title>
<para>
Close and reopen flatrotate files during log rotation.
Documentation missing (flat_rotate_doc).
</para>
<para>
</para>

@ -10,7 +10,7 @@ RPC Exports for debugger
<section id="dbg.bp"><title>dbg.bp</title>
<para>
Breakpoint command
Documentation missing (dbg_rpc_bp_doc).
</para>
<para>
</para>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- this file is autogenerated, do not edit! -->
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id="rpc_exports.dialplan">
<title>
RPC Exports for dialplan
</title>
<section id="dialplan.reload"><title>dialplan.reload</title>
<para>
Reload dialplan table from database
</para>
<para>
</para>
</section>
<section id="dialplan.dump"><title>dialplan.dump</title>
<para>
Perform dialplan translation
</para>
<para>
</para>
</section>
</chapter>

@ -8,17 +8,25 @@ RPC Exports for dispatcher
</title>
<section id="dispatcher.dump"><title>dispatcher.dump</title>
<section id="dispatcher.reload"><title>dispatcher.reload</title>
<para>
Dump dispatcher set configuration
Reload dispatcher destination sets
</para>
<para>
</para>
</section>
<section id="dispatcher.reload"><title>dispatcher.reload</title>
<section id="dispatcher.list"><title>dispatcher.list</title>
<para>
Return the content of dispatcher sets
</para>
<para>
</para>
</section>
<section id="dispatcher.set_state"><title>dispatcher.set_state</title>
<para>
Reload dispatcher list from file
Set the state of a destination address
</para>
<para>
</para>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- this file is autogenerated, do not edit! -->
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id="rpc_exports.dispatcher_s">
<title>
RPC Exports for dispatcher_s
</title>
<section id="dispatcher.dump"><title>dispatcher.dump</title>
<para>
Dump dispatcher set configuration
</para>
<para>
</para>
</section>
<section id="dispatcher.reload"><title>dispatcher.reload</title>
<para>
Reload dispatcher list from file
</para>
<para>
</para>
</section>
</chapter>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- this file is autogenerated, do not edit! -->
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id="rpc_exports.domain_s">
<title>
RPC Exports for domain_s
</title>
<section id="domain.reload"><title>domain.reload</title>
<para>
Reload domain table from database
</para>
<para>
</para>
</section>
<section id="domain.dump"><title>domain.dump</title>
<para>
Return the contents of domain table
</para>
<para>
</para>
</section>
</chapter>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- this file is autogenerated, do not edit! -->
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id="rpc_exports.kex">
<title>
RPC Exports for kex
</title>
<section id="pkg.stats"><title>pkg.stats</title>
<para>
Private memory (pkg) statistics per process
</para>
<para>
</para>
</section>
</chapter>

@ -8,8 +8,8 @@
<book id="rpc_list" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>RPC Exports List</title>
<bookinfo><revhistory><revision>
<revnumber>sip-router git-7e5450</revnumber>
<date>Mon, 04 Oct 2010 22:52:57 +0200</date>
<revnumber>sip-router git-0ea931</revnumber>
<date>Fri, 25 Nov 2011 23:59:50 +0100</date>
<revremark>
Automatically generated by:
make -C doc/rpc_list all
@ -21,24 +21,28 @@
<xi:include href="rpc_ctl.xml"/>
<xi:include href="rpc_db_flatstore.xml"/>
<xi:include href="rpc_debugger.xml"/>
<xi:include href="rpc_dialplan.xml"/>
<xi:include href="rpc_lcr.xml"/>
<xi:include href="rpc_malloc_test.xml"/>
<xi:include href="rpc_mi_rpc.xml"/>
<xi:include href="rpc_prefix_route.xml"/>
<xi:include href="rpc_ratelimit.xml"/>
<xi:include href="rpc_sl.xml"/>
<xi:include href="rpc_tls.xml"/>
<xi:include href="rpc_tm.xml"/>
<xi:include href="rpc_dialog.xml"/>
<xi:include href="rpc_dispatcher.xml"/>
<xi:include href="rpc_domain.xml"/>
<xi:include href="rpc_htable.xml"/>
<xi:include href="rpc_ratelimit.xml"/>
<xi:include href="rpc_kex.xml"/>
<xi:include href="rpc_uac.xml"/>
<xi:include href="rpc_usrloc_k.xml"/>
<xi:include href="rpc_usrloc.xml"/>
<xi:include href="rpc_cpl-c.xml"/>
<xi:include href="rpc_dispatcher.xml"/>
<xi:include href="rpc_domain.xml"/>
<xi:include href="rpc_dispatcher_s.xml"/>
<xi:include href="rpc_domain_s.xml"/>
<xi:include href="rpc_gflags.xml"/>
<xi:include href="rpc_pdt.xml"/>
<xi:include href="rpc_pike.xml"/>
<xi:include href="rpc_prefix_route.xml"/>
<xi:include href="rpc_presence_b2b.xml"/>
<xi:include href="rpc_usrloc_s.xml"/>
</book>

@ -10,7 +10,7 @@ RPC Exports for prefix_route
<section id="prefix_route.reload"><title>prefix_route.reload</title>
<para>
Reload prefix routes from DB
Documentation missing (rpc_reload_doc).
</para>
<para>
</para>
@ -18,7 +18,7 @@ RPC Exports for prefix_route
<section id="prefix_route.dump"><title>prefix_route.dump</title>
<para>
Dump the prefix route tree
Documentation missing (rpc_dump_doc).
</para>
<para>
</para>

@ -10,7 +10,7 @@ RPC Exports for sl
<section id="sl.stats"><title>sl.stats</title>
<para>
Print reply statistics.
Documentation missing (rpc_stats_doc).
</para>
<para>
</para>

@ -10,7 +10,7 @@ RPC Exports for tls
<section id="tls.reload"><title>tls.reload</title>
<para>
Reload TLS configuration file
Documentation missing (tls_reload_doc).
</para>
<para>
</para>
@ -18,7 +18,7 @@ RPC Exports for tls
<section id="tls.list"><title>tls.list</title>
<para>
List currently open TLS connections
Documentation missing (tls_list_doc).
</para>
<para>
Returns an array.
@ -27,7 +27,7 @@ RPC Exports for tls
<section id="tls.info"><title>tls.info</title>
<para>
Returns internal tls related info.
Documentation missing (tls_info_doc).
</para>
<para>
</para>
@ -35,7 +35,7 @@ RPC Exports for tls
<section id="tls.options"><title>tls.options</title>
<para>
Dumps all the tls config options.
Documentation missing (tls_options_doc).
</para>
<para>
</para>

@ -10,7 +10,7 @@ RPC Exports for tm
<section id="tm.cancel"><title>tm.cancel</title>
<para>
Cancel a pending transaction
Documentation missing (rpc_cancel_doc).
</para>
<para>
</para>
@ -18,7 +18,7 @@ RPC Exports for tm
<section id="tm.reply"><title>tm.reply</title>
<para>
Reply transaction
Documentation missing (rpc_reply_doc).
</para>
<para>
</para>
@ -26,7 +26,7 @@ RPC Exports for tm
<section id="tm.stats"><title>tm.stats</title>
<para>
Print transaction statistics.
Documentation missing (tm_rpc_stats_doc).
</para>
<para>
</para>
@ -34,8 +34,7 @@ RPC Exports for tm
<section id="tm.hash_stats"><title>tm.hash_stats</title>
<para>
Prints hash table statistics (can be used only if tm is
compiled with -DTM_HASH_STATS).
Documentation missing (tm_rpc_hash_stats_doc).
</para>
<para>
</para>
@ -43,9 +42,7 @@ RPC Exports for tm
<section id="tm.t_uac_start"><title>tm.t_uac_start</title>
<para>
starts a tm uac using a list of string parameters: method,
ruri, dst_uri, send_sock, headers (CRLF separated) and body
(optional)
Documentation missing (rpc_t_uac_start_doc).
</para>
<para>
</para>
@ -53,9 +50,7 @@ RPC Exports for tm
<section id="tm.t_uac_wait"><title>tm.t_uac_wait</title>
<para>
starts a tm uac and waits for the final reply, using a list of
string parameters: method, ruri, dst_uri send_sock, headers
(CRLF separated) and body (optional)
Documentation missing (rpc_t_uac_wait_doc).
</para>
<para>
Returns an array.

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- this file is autogenerated, do not edit! -->
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<chapter id="rpc_exports.usrloc">
<title>
RPC Exports for usrloc
</title>
<section id="ul.dump"><title>ul.dump</title>
<para>
Dump user location tables
</para>
<para>
</para>
</section>
</chapter>

@ -10,7 +10,7 @@ RPC Exports for usrloc_s
<section id="usrloc.stats"><title>usrloc.stats</title>
<para>
Print usrloc statistics
Documentation missing (rpc_stats_doc).
</para>
<para>
Returns an array.
@ -19,7 +19,7 @@ RPC Exports for usrloc_s
<section id="usrloc.delete_uid"><title>usrloc.delete_uid</title>
<para>
Delete all registered contacts for address of record.
Documentation missing (rpc_delete_uid_doc).
</para>
<para>
</para>
@ -27,7 +27,7 @@ RPC Exports for usrloc_s
<section id="usrloc.delete_contact"><title>usrloc.delete_contact</title>
<para>
Delete a contact if it exists.
Documentation missing (rpc_delete_contact_doc).
</para>
<para>
</para>
@ -35,7 +35,7 @@ RPC Exports for usrloc_s
<section id="usrloc.dump"><title>usrloc.dump</title>
<para>
Print all registered contacts.
Documentation missing (rpc_dump_doc).
</para>
<para>
</para>
@ -43,7 +43,7 @@ RPC Exports for usrloc_s
<section id="usrloc.dump_file"><title>usrloc.dump_file</title>
<para>
Print all registered contacts into a file.
Documentation missing (rpc_dump_file_doc).
</para>
<para>
</para>
@ -51,7 +51,7 @@ RPC Exports for usrloc_s
<section id="usrloc.flush"><title>usrloc.flush</title>
<para>
Flush cache into database.
Documentation missing (rpc_flush_doc).
</para>
<para>
</para>
@ -59,7 +59,7 @@ RPC Exports for usrloc_s
<section id="usrloc.add_contact"><title>usrloc.add_contact</title>
<para>
Create a new contact.
Documentation missing (rpc_add_contact_doc).
</para>
<para>
</para>
@ -67,7 +67,7 @@ RPC Exports for usrloc_s
<section id="usrloc.show_contacts"><title>usrloc.show_contacts</title>
<para>
List all registered contacts for address of record
Documentation missing (rpc_show_contacts_doc).
</para>
<para>
Returns an array.

@ -4,38 +4,68 @@ RPC Exports for cfg_rpc
[ this file is autogenerated, do not edit ]
1. cfg.set_now_int
1. cfg.set
Set the value of a configuration variable and commit the change
immediately
2. cfg.set_now_string
2. cfg.set_now_int
Set the value of a configuration variable and commit the change
immediately
3. cfg.set_delayed_int
3. cfg.seti
Set the value of a configuration variable and commit the change
immediately
4. cfg.set_now_string
Set the value of a configuration variable and commit the change
immediately
5. cfg.sets
Set the value of a configuration variable and commit the change
immediately
6. cfg.del
Delete the value of a configuration variable from a group
instance and commit the change immediately
7. cfg.set_delayed
Prepare the change of a configuration variable, but does not
commit the new value yet
8. cfg.set_delayed_int
Prepare the change of a configuration variable, but does not
commit the new value yet
4. cfg.set_delayed_string
9. cfg.set_delayed_string
Prepare the change of a configuration variable, but does not
commit the new value yet
5. cfg.commit
10. cfg.del_delayed
Prepare the deletion of the value of a configuration variable
from a group instance, but does not commit the change yet
11. cfg.commit
Commit the previously prepared configuration changes
6. cfg.rollback
12. cfg.rollback
Drop the prepared configuration changes
7. cfg.get
13. cfg.get
Get the value of a configuration variable
8. cfg.help
14. cfg.help
Print the description of a configuration variable
9. cfg.list
15. cfg.list
List the configuration variables
10. cfg.diff
16. cfg.diff
List the pending configuration changes that have not been
committed yet
17. cfg.add_group_inst
Add a new instance to an existing configuration group
18. cfg.del_group_inst
Delte an instance of a configuration group

@ -43,30 +43,33 @@ RPC Exports for core
Returns the description of running SER processes.
Returns an array.
12. core.pwd
12. core.psx
Returns the detailed description of running SER processes.
13. core.pwd
Returns the working directory of SER server.
Returns an array.
13. core.arg
14. core.arg
Returns the list of command line arguments used on SER startup.
Returns an array.
14. core.kill
15. core.kill
Sends the given signal to SER.
15. core.shmmem
16. core.shmmem
Returns shared memory info. It has an optional parameter that
specifies the measuring unit: b - bytes (default), k or kb, m
or mb, g or gb. Note: when using something different from
bytes, the value is truncated.
16. core.tcp_info
17. core.tcp_info
Returns tcp related info.
17. core.tcp_options
18. core.tcp_options
Returns active tcp options.
18. core.sctp_options
19. core.sctp_options
Returns active sctp options. With one parameter it returns the
sctp options set in the kernel for a specific
socket(debugging), with 0 filled in for non-kernel related
@ -74,80 +77,80 @@ RPC Exports for core
address[:port] . With no parameters it returns ser's idea of
the current sctp options (intended non-debugging use).
19. core.sctp_info
20. core.sctp_info
Returns sctp related info.
20. core.udp4_raw_info
21. core.udp4_raw_info
Returns udp4_raw related info.
21. dns.mem_info
22. dns.mem_info
dns cache memory info.
22. dns.debug
23. dns.debug
dns debug info.
23. dns.debug_all
24. dns.debug_all
complete dns debug dump
24. dns.view
25. dns.view
dns cache dump in a human-readable format
25. dns.lookup
26. dns.lookup
perform a dns lookup
26. dns.delete_all
27. dns.delete_all
deletes all the non-permanent entries from the DNS cache
27. dns.delete_all_force
28. dns.delete_all_force
deletes all the entries from the DNS cache including the
permanent ones
28. dns.add_a
29. dns.add_a
adds an A record to the DNS cache
29. dns.add_aaaa
30. dns.add_aaaa
adds an AAAA record to the DNS cache
30. dns.add_srv
31. dns.add_srv
adds an SRV record to the DNS cache
31. dns.delete_a
32. dns.delete_a
deletes an A record from the DNS cache
32. dns.delete_aaaa
33. dns.delete_aaaa
deletes an AAAA record from the DNS cache
33. dns.delete_srv
34. dns.delete_srv
deletes an SRV record from the DNS cache
34. dns.delete_naptr
35. dns.delete_naptr
deletes a NAPTR record from the DNS cache
35. dns.delete_cname
36. dns.delete_cname
deletes a CNAME record from the DNS cache
36. dns.delete_txt
37. dns.delete_txt
deletes a TXT record from the DNS cache
37. dns.delete_ebl
38. dns.delete_ebl
deletes an EBL record from the DNS cache
38. dns.delete_ptr
39. dns.delete_ptr
deletes an PTR record from the DNS cache
39. dst_blacklist.mem_info
40. dst_blacklist.mem_info
dst blacklist memory usage info.
40. dst_blacklist.debug
41. dst_blacklist.debug
dst blacklist debug info.
41. dst_blacklist.view
42. dst_blacklist.view
dst blacklist dump in human-readable format.
42. dst_blacklist.delete_all
43. dst_blacklist.delete_all
Deletes all the entries from the dst blacklist except the
permanent ones.
43. dst_blacklist.add
44. dst_blacklist.add
Adds a new entry to the dst blacklist.

@ -5,5 +5,5 @@ RPC Exports for db_flatstore
1. flatstore.rotate
Close and reopen flatrotate files during log rotation.
Documentation missing (flat_rotate_doc).

@ -5,7 +5,7 @@ RPC Exports for debugger
1. dbg.bp
Breakpoint command
Documentation missing (dbg_rpc_bp_doc).
2. dbg.ls
List debugging process array

@ -0,0 +1,12 @@
RPC Exports for dialplan
========================
[ this file is autogenerated, do not edit ]
1. dialplan.reload
Reload dialplan table from database
2. dialplan.dump
Perform dialplan translation

@ -4,9 +4,12 @@ RPC Exports for dispatcher
[ this file is autogenerated, do not edit ]
1. dispatcher.dump
Dump dispatcher set configuration
1. dispatcher.reload
Reload dispatcher destination sets
2. dispatcher.reload
Reload dispatcher list from file
2. dispatcher.list
Return the content of dispatcher sets
3. dispatcher.set_state
Set the state of a destination address

@ -0,0 +1,12 @@
RPC Exports for dispatcher_s
============================
[ this file is autogenerated, do not edit ]
1. dispatcher.dump
Dump dispatcher set configuration
2. dispatcher.reload
Reload dispatcher list from file

@ -0,0 +1,12 @@
RPC Exports for domain_s
========================
[ this file is autogenerated, do not edit ]
1. domain.reload
Reload domain table from database
2. domain.dump
Return the contents of domain table

@ -0,0 +1,9 @@
RPC Exports for kex
===================
[ this file is autogenerated, do not edit ]
1. pkg.stats
Private memory (pkg) statistics per process

@ -5,8 +5,8 @@ RPC Exports for prefix_route
1. prefix_route.reload
Reload prefix routes from DB
Documentation missing (rpc_reload_doc).
2. prefix_route.dump
Dump the prefix route tree
Documentation missing (rpc_dump_doc).

@ -5,5 +5,5 @@ RPC Exports for sl
1. sl.stats
Print reply statistics.
Documentation missing (rpc_stats_doc).

@ -5,15 +5,15 @@ RPC Exports for tls
1. tls.reload
Reload TLS configuration file
Documentation missing (tls_reload_doc).
2. tls.list
List currently open TLS connections
Documentation missing (tls_list_doc).
Returns an array.
3. tls.info
Returns internal tls related info.
Documentation missing (tls_info_doc).
4. tls.options
Dumps all the tls config options.
Documentation missing (tls_options_doc).

@ -5,26 +5,21 @@ RPC Exports for tm
1. tm.cancel
Cancel a pending transaction
Documentation missing (rpc_cancel_doc).
2. tm.reply
Reply transaction
Documentation missing (rpc_reply_doc).
3. tm.stats
Print transaction statistics.
Documentation missing (tm_rpc_stats_doc).
4. tm.hash_stats
Prints hash table statistics (can be used only if tm is
compiled with -DTM_HASH_STATS).
Documentation missing (tm_rpc_hash_stats_doc).
5. tm.t_uac_start
starts a tm uac using a list of string parameters: method,
ruri, dst_uri, send_sock, headers (CRLF separated) and body
(optional)
Documentation missing (rpc_t_uac_start_doc).
6. tm.t_uac_wait
starts a tm uac and waits for the final reply, using a list of
string parameters: method, ruri, dst_uri send_sock, headers
(CRLF separated) and body (optional)
Documentation missing (rpc_t_uac_wait_doc).
Returns an array.

@ -0,0 +1,9 @@
RPC Exports for usrloc
======================
[ this file is autogenerated, do not edit ]
1. ul.dump
Dump user location tables

@ -5,28 +5,28 @@ RPC Exports for usrloc_s
1. usrloc.stats
Print usrloc statistics
Documentation missing (rpc_stats_doc).
Returns an array.
2. usrloc.delete_uid
Delete all registered contacts for address of record.
Documentation missing (rpc_delete_uid_doc).
3. usrloc.delete_contact
Delete a contact if it exists.
Documentation missing (rpc_delete_contact_doc).
4. usrloc.dump
Print all registered contacts.
Documentation missing (rpc_dump_doc).
5. usrloc.dump_file
Print all registered contacts into a file.
Documentation missing (rpc_dump_file_doc).
6. usrloc.flush
Flush cache into database.
Documentation missing (rpc_flush_doc).
7. usrloc.add_contact
Create a new contact.
Documentation missing (rpc_add_contact_doc).
8. usrloc.show_contacts
List all registered contacts for address of record
Documentation missing (rpc_show_contacts_doc).
Returns an array.

@ -166,7 +166,9 @@
</xsl:when>
<xsl:when test="$type='string' or
$type='text' or
$type='binary'">
$type='binary' or
$type='largetext' or
$type='largebinary'">
<xsl:text>str</xsl:text>
</xsl:when>
<xsl:otherwise>

@ -0,0 +1,135 @@
<?xml version='1.0'?>
<!--
* XSL converter script for sqlite databases
*
* Copyright (C) 2001-2007 FhG Fokus
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio 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
*
* Kamailio 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
*
*/
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version='1.0'
xmlns:xi="http://www.w3.org/2001/XInclude"
>
<xsl:import href="sql.xsl"/>
<!-- specify the table type -->
<xsl:template name="table.close">
<xsl:text>)</xsl:text>
<xsl:if test="type[@db=$db]">
<xsl:text> Type=</xsl:text>
<xsl:value-of select="normalize-space(type[@db=$db])"/>
</xsl:if>
<xsl:text>;&#x0A;&#x0A;</xsl:text>
</xsl:template>
<xsl:template name="column.type">
<xsl:variable name="type">
<xsl:call-template name="get-type"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="type[@db=$db]">
<xsl:value-of select="normalize-space(type[@db=$db])"/>
</xsl:when>
<xsl:when test="$type='char'">
<xsl:text>SMALLINT</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='short'">
<xsl:text>SMALLINT</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='int'">
<xsl:if test="not(autoincrement)">
<xsl:text>INTEGER</xsl:text>
</xsl:if>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='long'">
<xsl:text>BIGINT</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='datetime'">
<xsl:text>TIMESTAMP</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='double'">
<xsl:text>DOUBLE PRECISION</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='float'">
<xsl:text>REAL</xsl:text>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='string'">
<xsl:text>VARCHAR</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='binary' or
$type='largebinary'">
<xsl:text>BLOB</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='text'or
$type='largetext'">
<xsl:text>TEXT</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="type-error"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="column.trailing">
<xsl:variable name="column.type">
<xsl:call-template name="get-type"/>
</xsl:variable>
<xsl:if test="$column.type='datetime'">
<xsl:text> WITHOUT TIME ZONE</xsl:text>
</xsl:if>
<xsl:if test="autoincrement">
<xsl:text>INTEGER</xsl:text>
</xsl:if>
<!-- PRIMARY KEY column definition -->
<xsl:if test="primary">
<xsl:text> PRIMARY KEY</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template name="get-index-name">
<xsl:variable name="index.name">
<xsl:call-template name="get-name"/>
</xsl:variable>
<xsl:variable name="table.name">
<xsl:call-template name="get-name">
<xsl:with-param name="select" select="parent::table"/>
</xsl:call-template>
</xsl:variable>
<!-- because postgres don't like identical index names, even on table level -->
<xsl:value-of select="concat($table.name, '_', $index.name)"/>
</xsl:template>
</xsl:stylesheet>

@ -90,7 +90,9 @@
</xsl:when>
<xsl:when test="$type='string' or
$type='text' or
$type='binary'">
$type='binary' or
$type='largetext' or
$type='largebinary'">
<xsl:text>string</xsl:text>
</xsl:when>
<xsl:otherwise>

@ -103,11 +103,23 @@
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='largebinary'">
<!-- In MySQL MEDIUMBLOB <= 16MB -->
<xsl:text>MEDIUMBLOB</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='text'">
<xsl:text>TEXT</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='largetext'">
<!-- In MySQL MEDIUMTEXT <= 16MB -->
<xsl:text>MEDIUMTEXT</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="type-error"/>
</xsl:otherwise>

@ -114,12 +114,14 @@
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='binary'">
<xsl:when test="$type='binary' or
$type='largebinary'">
<xsl:text>BLOB</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='text'">
<xsl:when test="$type='text' or
$type='largetext'">
<xsl:text>CLOB</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>

@ -87,12 +87,14 @@
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='binary'">
<xsl:when test="$type='binary' or
$type='largebinary'">
<xsl:text>BYTEA</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>
</xsl:when>
<xsl:when test="$type='text'">
<xsl:when test="$type='text' or
$type='largetext'">
<xsl:text>TEXT</xsl:text>
<xsl:call-template name="column.size"/>
<xsl:call-template name="column.trailing"/>

@ -97,7 +97,7 @@ html_css ?= /css/sr-doc.css
# the site-wide catalog file present in Debian and possibly other systems
# too. This file is updated by the package manager whenever docbook schema
# file or docbook xsl stylesheets are being installed.
catalog=$(docbook_dir)/catalog.xml
catalog ?= $(docbook_dir)/catalog.xml
lynx ?= lynx
dia ?= dia
@ -113,7 +113,14 @@ ifeq ($(validate), 0)
override xsltproc_flags := $(xsltproc_flags) --novalid
endif
all_deps = Makefile $(docbook_dir)/Makefile $(dep_xsl) $(catalog) $(extra_deps)
ifeq ($(nocatalog),yes)
XMLCATALOGX=
else
XMLCATALOGX=XML_CATALOG_FILES=$(catalog)
endif
all_deps = Makefile $(docbook_dir)/Makefile $(docbook_dir)/entities.xml \
$(dep_xsl) $(catalog) $(extra_deps)
all: txt
@ -132,12 +139,12 @@ txt text plaintext: $(txt_files)
readme README: ../README
../README: $(readme_docs) $(readme_deps) $(readme_xsl) $(all_deps)
XML_CATALOG_FILES=$(catalog) $(xsltproc) $(xsltproc_flags) \
$(XMLCATALOGX) $(xsltproc) $(xsltproc_flags) \
--xinclude \
$(readme_xsl) $< | $(lynx) $(lynx_flags) -stdin -dump > $@
$(output_dir)/%.html: %.xml %.d $(single_html_xsl) $(all_deps)
XML_CATALOG_FILES=$(catalog) $(xsltproc) $(xsltproc_flags) \
$(XMLCATALOGX) $(xsltproc) $(xsltproc_flags) \
--xinclude \
--stringparam base.dir "$(output_dir)/" \
--stringparam root.filename "$(basename $<)" \
@ -147,7 +154,7 @@ $(output_dir)/%.html: %.xml %.d $(single_html_xsl) $(all_deps)
$(output_dir)/%.txt: %.xml %.d $(txt_xsl) $(all_deps)
XML_CATALOG_FILES=$(catalog) $(xsltproc) $(xsltproc_flags) \
$(XMLCATALOGX) $(xsltproc) $(xsltproc_flags) \
--xinclude \
$(txt_xsl) $< | $(lynx) $(lynx_flags) -stdin -dump > $@
@ -163,7 +170,7 @@ $(output_dir)/%.txt: %.xml %.d $(txt_xsl) $(all_deps)
.PHONY: check
check: $(docs) $(html_docs) $(txt_docs) $(readme_docs)
XML_CATALOG_FILES=$(catalog) $(xmllint) $(xmllint_flags) $<
$(XMLCATALOGX) $(xmllint) $(xmllint_flags) $<
.PHONY: clean
clean:

@ -3,23 +3,21 @@
<!ENTITY fhg "FhG FOKUS">
<!ENTITY iptel "<ulink url='http://iptel.org'>iptel.org</ulink>">
<!-- Kamailio specific attributes -->
<!ENTITY kamailio "Kamailio">
<!ENTITY kamailiobinary "kamailio">
<!ENTITY kamailioname "Kamailio SIP Server Platform">
<!ENTITY kamailioconfig "kamailio.cfg">
<!ENTITY siprouter "SIP Router">
<!ENTITY siproutername "SIP Router Project">
<!ENTITY siprouterconfig "sip-router.cfg">
<!ENTITY kamwiki "http://www.kamailio.org/dokuwiki/">
<!ENTITY kamwikilink "<ulink url='&kamwiki;'>&kamwiki;</ulink>">
<!ENTITY kamailiohome "http://www.kamailio.org/">
<!ENTITY kamailiobugs "http://sourceforge.net/tracker/?group_id=139143">
<!ENTITY kamailiohelp "http://lists.kamailio.org/cgi-bin/mailman/listinfo/team">
<!ENTITY kamailiousers "http://lists.kamailio.org/cgi-bin/mailman/listinfo/users">
<!ENTITY kamailiodev "http://lists.kamailio.org/cgi-bin/mailman/listinfo/devel">
<!ENTITY kamailiobugs "http://sip-router.org/tracker">
<!ENTITY kamailiohelp "http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users">
<!ENTITY kamailiousers "http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users">
<!ENTITY kamailiodev "http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev">
<!ENTITY kamailiodbdocs "http://www.kamailio.org/docs/db-tables/kamailio-db-devel.html">
<!ENTITY kamailiohomelink "<ulink url='&kamailiohome;'>&kamailiohome;</ulink>">
@ -29,9 +27,9 @@
<!ENTITY kamailiodevlink "<ulink url='&kamailiodev;'>&kamailiodev;</ulink>">
<!ENTITY kamailiodbdocslink "<ulink url='&kamailiodbdocs;'>&kamailiodbdocs;</ulink>">
<!ENTITY kamailiohelpmail "<email>team@lists.kamailio.org</email>">
<!ENTITY kamailiousersmail "<email>users@lists.kamailio.org</email>">
<!ENTITY kamailiodevmail "<email>devel@lists.kamailio.org</email>">
<!ENTITY kamailiohelpmail "<email>sr-users@lists.sip-router.org</email>">
<!ENTITY kamailiousersmail "<email>sr-users@lists.sip-router.org</email>">
<!ENTITY kamailiodevmail "<email>sr-dev@lists.sip-router.org</email>">
<!ENTITY ctltool "kamctl">
<!ENTITY ctltoolrc "kamctlrc">
@ -40,15 +38,21 @@
<!ENTITY develguide "Developer Guide">
<!ENTITY faqguide "Frequently Asked Questions">
<!-- SER Specific Attributes -->
<!ENTITY siprouter "SIP Router">
<!ENTITY siproutername "SIP Router Project">
<!ENTITY siprouterconfig "sip-router.cfg">
<!ENTITY ser "SER">
<!ENTITY sername "SIP Express Router">
<!ENTITY sercmd "sercmd">
<!ENTITY ctlsocket "ser_ctl">
<!ENTITY serhome "http://iptel.org/ser">
<!ENTITY serbugs "http://iptel.org/ser/bugs">
<!ENTITY serusers "http://mail.iptel.org/mailman/listinfo/serusers">
<!ENTITY serdev "http://mail.iptel.org/mailman/listinfo/serdev">
<!ENTITY serbugs "http://sip-router.org/tracker">
<!ENTITY serusers "http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users">
<!ENTITY serdev "http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev">
<!ENTITY serhomelink "<ulink url='&serhome;'>&serhome;</ulink>">
<!ENTITY serbugslink "<ulink url='&serbugs;'>&serbugs;</ulink>">
@ -56,8 +60,8 @@
<!ENTITY seruserslink "<ulink url='&serusers;'>&serusers;</ulink>">
<!ENTITY serdevlink "<ulink url='&serdev;'>&serdev;</ulink>">
<!ENTITY serusersmail "<email>serusers@iptel.org</email>">
<!ENTITY serdevmail "<email>serdev@iptel.org</email>">
<!ENTITY serusersmail "<email>sr-users@lists.sip-router.org</email>">
<!ENTITY serdevmail "<email>sr-dev@lists.sip-router.org</email>">
<!ENTITY defaultdb "mysql://openser:openserrw@localhost/openser">
<!ENTITY defaultrodb "mysql://openserro:openserro@localhost/openser">
@ -93,6 +97,3 @@
<!ENTITY rfc3261 "<ulink url='http://www.ietf.org/rfc/rfc3261.txt'>RFC3261</ulink>">
<!ENTITY rfc822 "<ulink url='http://www.ietf.org/rfc/rfc822.txt'>RFC822</ulink>">
<!ENTITY rfc2543 "<ulink url='http://www.ietf.org/rfc/rfc2543.txt'>RFC2543</ulink>">
<!ENTITY vsname "Voice Sistem SRL">
<!ENTITY voicesystem "<ulink url='http://www.voice-system.ro'>voice-system.ro</ulink>">

@ -104,3 +104,39 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val)
*val = (void *)(long)i;
return 0;
}
/**
* per process debug log level (local)
*/
/* value for unset local log level */
#define UNSET_LOCAL_DEBUG_LEVEL -255
/* the local debug log level */
static int _local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
/**
* @brief return the log level - the local one if it set,
* otherwise the global value
*/
int get_debug_level(void) {
return (_local_debug_level != UNSET_LOCAL_DEBUG_LEVEL) ?
_local_debug_level : cfg_get(core, core_cfg, debug);
}
/**
* @brief set the local debug log level
*/
void set_local_debug_level(int level)
{
_local_debug_level = level;
}
/**
* @brief reset the local debug log level
*/
void reset_local_debug_level(void)
{
_local_debug_level = UNSET_LOCAL_DEBUG_LEVEL;
}

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2001-2003 FhG Fokus
*
* This file is part of ser, a free SIP server.
@ -103,10 +101,10 @@
(log_level_info[(level) - (L_ALERT)].syslog_level)
/** @brief my_pid(), process_no are from pt.h but we cannot #include it here
/** @brief my_pid(), process_no are from pt.h but we cannot \#include it here
because of circular dependencies */
extern int process_no;
extern int my_pid();
extern int my_pid(void);
/** @brief non-zero if logging to stderr instead to the syslog */
extern int log_stderr;
@ -118,7 +116,12 @@ struct log_level_info {
int syslog_level;
};
#define is_printable(level) (cfg_get(core, core_cfg, debug)>=(level))
/** @brief per process debug level handling */
int get_debug_level(void);
void set_local_debug_level(int level);
void reset_local_debug_level(void);
#define is_printable(level) (get_debug_level()>=(level))
extern struct log_level_info log_level_info[];
extern char *log_name;
@ -167,7 +170,7 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
# ifdef __SUNPRO_C
# define LOG_(facility, level, prefix, fmt, ...) \
do { \
if (unlikely(cfg_get(core, core_cfg, debug) >= (level) && \
if (unlikely(get_debuglevel() >= (level) && \
DPRINT_NON_CRIT)) { \
DPRINT_CRIT_ENTER; \
if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \
@ -229,7 +232,7 @@ int log_facility_fixup(void *handle, str *gname, str *name, void **val);
# else /* ! __SUNPRO_C */
# define LOG_(facility, level, prefix, fmt, args...) \
do { \
if (cfg_get(core, core_cfg, debug) >= (level) && \
if (get_debug_level() >= (level) && \
DPRINT_NON_CRIT) { \
DPRINT_CRIT_ENTER; \
if (likely(((level) >= L_ALERT) && ((level) <= L_DBG))){ \

@ -191,11 +191,21 @@ void init_branch_iterator(void)
branch_iterator = 0;
}
/**
* return the value of current branch iterator
*/
int get_branch_iterator(void)
{
return branch_iterator;
}
/**
* set the value of current branch interator
*/
void set_branch_iterator(int n)
{
branch_iterator = n;
}
/** \brief Get a branch from the destination set
@ -289,11 +299,6 @@ int append_branch(struct sip_msg* msg, str* uri, str* dst_uri, str* path,
{
str luri;
#ifdef USE_LOCAL_ROUTE
if (unlikely(dset_state==0))
return -1;
#endif
/* if we have already set up the maximum number
* of branches, don't try new ones
*/
@ -371,6 +376,7 @@ char* print_dset(struct sip_msg* msg, int* len)
qvalue_t q;
str uri;
char* p, *qbuf;
int crt_branch;
static char dset[MAX_REDIRECTION_LEN];
if (msg->new_uri.s) {
@ -384,6 +390,9 @@ char* print_dset(struct sip_msg* msg, int* len)
*len = 0;
}
/* backup current branch index to restore it later */
crt_branch = get_branch_iterator();
init_branch_iterator();
while ((uri.s = next_branch(&uri.len, &q, 0, 0, 0, 0))) {
cnt++;
@ -399,7 +408,7 @@ char* print_dset(struct sip_msg* msg, int* len)
if (*len + 1 > MAX_REDIRECTION_LEN) {
LOG(L_ERR, "ERROR: redirection buffer length exceed\n");
return 0;
goto error;
}
memcpy(dset, CONTACT, CONTACT_LEN);
@ -450,7 +459,12 @@ char* print_dset(struct sip_msg* msg, int* len)
}
memcpy(p, CRLF " ", CRLF_LEN + 1);
set_branch_iterator(crt_branch);
return dset;
error:
set_branch_iterator(crt_branch);
return 0;
}

@ -107,15 +107,19 @@ static inline int ser_append_branch(struct sip_msg* msg,
/*! \brief
* Iterate through the list of transaction branches
* Init the index to iterate through the list of transaction branches
*/
void init_branch_iterator(void);
/*! \brief
* Return branch iterator position
* Return branch iterator position
*/
int get_branch_iterator(void);
/*! \brief
* Set branch iterator position
*/
void set_branch_iterator(int n);
/*! \brief Get the next branch in the current transaction.
* @return pointer to the uri of the next branch (which the length written in

@ -309,7 +309,7 @@ inline static int blacklist_run_hooks(struct blst_callbacks_lst *cb_lst,
/** init per protocol blacklist event ignore masks.
* @return 0 on success, < 0 on error.
*/
int blst_init_ign_masks()
int blst_init_ign_masks(void)
{
if ((PROTO_UDP > PROTO_LAST) || (PROTO_TCP > PROTO_LAST) ||
(PROTO_TLS > PROTO_LAST) || (PROTO_SCTP > PROTO_LAST)){
@ -937,24 +937,6 @@ void dst_blst_mem_info(rpc_t* rpc, void* ctx)
static char* get_proto_name(unsigned char proto)
{
switch(proto){
case PROTO_NONE:
return "*";
case PROTO_UDP:
return "udp";
case PROTO_TCP:
return "tcp";
case PROTO_TLS:
return "tls";
case PROTO_SCTP:
return "sctp";
default:
return "unknown";
}
}
#ifdef USE_DST_BLACKLIST_STATS

@ -1,6 +1,4 @@
/*
* $Id$
*
* Copyright (C) 2006 iptelorg GmbH
*
* This file is part of ser, a free SIP server.
@ -85,16 +83,16 @@ struct blacklist_hook{
int register_blacklist_hook(struct blacklist_hook *h, int type);
#endif /* DST_BLACKLIST_HOOKS */
int init_dst_blacklist();
int init_dst_blacklist(void);
#ifdef USE_DST_BLACKLIST_STATS
int init_dst_blacklist_stats(int iproc_num);
#define DST_BLACKLIST_ALL_STATS "bkl_all_stats"
#endif
void destroy_dst_blacklist();
void destroy_dst_blacklist(void);
/** force add to the blacklist.
* like @function dst_blacklist_add_to, but no ignore mask or
* like function dst_blacklist_add_to, but no ignore mask or
* blacklist enabled checks are made.
* @see dst_blacklist_add_to for the parameters and return value.
*/
@ -102,7 +100,7 @@ int dst_blacklist_force_add_to(unsigned char err_flags, struct dest_info* si,
struct sip_msg* msg, ticks_t timeout);
/** force add to the blacklist, long version.
* like @function dst_blacklist_su_to, but no ignore mask or
* like function dst_blacklist_su_to, but no ignore mask or
* blacklist enabled checks are made.
* @see dst_blacklist_su_to for the parameters and return value.
*/
@ -127,13 +125,12 @@ int dst_blacklist_force_su_to( unsigned char err_flags,
/** checks if blacklist should be used, long version.
* @param err_flags - blacklist reason
* @param err_flags - blacklist reason
* @param snd_flags - snd_flags pointer, can be 0.
* @param proto - protocol, can be 0 (PROTO_NONE).
* @param si - sockaddr_union pointer, can be 0.
* @param su - sockaddr_union pointer, can be 0.
* @return 1 if blacklist is enabled (core_cfg) and the event/error
* is not in the ignore list.
* 0 otherwise
* is not in the ignore list. 0 otherwise
*/
#define should_blacklist_su(err_flags, snd_flags, proto, su) \
(cfg_get(core, core_cfg, use_dst_blacklist) && \

@ -72,7 +72,7 @@ extern int _endian_test_int;
#define is_little_endian() endian_test()
extern int endianness_sanity_check();
extern int endianness_sanity_check(void);
/* detect compile time endianess */
#if defined __BYTE_ORDER && defined __LITTLE_ENDIAN && defined __BIG_ENDIAN

@ -1,6 +1,6 @@
#!KAMAILIO
#
# Kamailio (OpenSER) SIP Server v3.1 - default configuration script
# Kamailio (OpenSER) SIP Server v3.3 - default configuration script
# - web: http://www.kamailio.org
# - git: http://sip-router.org
#
@ -51,6 +51,10 @@
# - enable mysql
# - define WITH_ALIASDB
#
# *** To enable speed dial lookup execute:
# - enable mysql
# - define WITH_SPEEDDIAL
#
# *** To enable multi-domain support execute:
# - enable mysql
# - define WITH_MULTIDOMAIN
@ -68,6 +72,14 @@
# block if more than 16 requests in 2 seconds and ban for 300 seconds)
# - define WITH_ANTIFLOOD
#
# *** To block 3XX redirect replies execute:
# - define WITH_BLOCK3XX
#
# *** To enable VoiceMail routing execute:
# - define WITH_VOICEMAIL
# - set the value of voicemail.srv_ip
# - adjust the value of voicemail.srv_port
#
# *** To enhance accounting execute:
# - enable mysql
# - define WITH_ACCDB
@ -75,11 +87,13 @@
#!ifdef ACCDB_COMMENT
ALTER TABLE acc ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN src_ip varchar(64) NOT NULL default '';
ALTER TABLE acc ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE acc ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_domain VARCHAR(128) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN src_ip varchar(64) NOT NULL default '';
ALTER TABLE missed_calls ADD COLUMN dst_ouser VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN dst_user VARCHAR(64) NOT NULL DEFAULT '';
ALTER TABLE missed_calls ADD COLUMN dst_domain VARCHAR(128) NOT NULL DEFAULT '';
@ -151,6 +165,10 @@ port=5060
enable_tls=yes
#!endif
# life time of TCP connection when there is no traffic
# - a bit higher than registration expires to cope with UA behind NAT
tcp_connection_lifetime=3605
####### Custom Parameters #########
# These parameters can be modified runtime via RPC interface
@ -170,11 +188,18 @@ enable_tls=yes
pstn.gw_ip = "" desc "PSTN GW Address"
#!endif
#!ifdef WITH_VOICEMAIL
# VoiceMail Routing on offline, busy or no answer
#
# - by default Voicemail server IP is empty to avoid misrouting
voicemail.srv_ip = "" desc "VoiceMail IP Address"
voicemail.srv_port = "5060" desc "VoiceMail Port"
#!endif
####### Modules Section ########
# set paths to location of modules
#!ifdef LOCAL_TEST_RUN
# set paths to location of modules (to sources or installation folders)
#!ifdef WITH_SRCPATH
mpath="modules_k:modules"
#!else
mpath="/usr/local/lib/kamailio/modules_k/:/usr/local/lib/kamailio/modules/"
@ -199,6 +224,7 @@ loadmodule "siputils.so"
loadmodule "xlog.so"
loadmodule "sanity.so"
loadmodule "ctl.so"
loadmodule "cfg_rpc.so"
loadmodule "mi_rpc.so"
loadmodule "acc.so"
@ -214,6 +240,10 @@ loadmodule "permissions.so"
loadmodule "alias_db.so"
#!endif
#!ifdef WITH_SPEEDDIAL
loadmodule "speeddial.so"
#!endif
#!ifdef WITH_MULTIDOMAIN
loadmodule "domain.so"
#!endif
@ -241,6 +271,10 @@ loadmodule "pike.so"
loadmodule "xmlrpc.so"
#!endif
#!ifdef WITH_DEBUG
loadmodule "debugger.so"
#!endif
# ----------------- setting module-specific parameters ---------------
@ -270,6 +304,10 @@ modparam("registrar", "method_filtering", 1)
# modparam("registrar", "append_branches", 0)
/* uncomment the next line not to allow more than 10 contacts per AOR */
#modparam("registrar", "max_contacts", 10)
# max value for expires of registrations
modparam("registrar", "max_expires", 3600)
# set it to 1 to enable GRUU
modparam("registrar", "gruu_enabled", 0)
# ----- acc params -----
@ -285,7 +323,8 @@ modparam("acc", "detect_direction", 0)
modparam("acc", "log_flag", FLT_ACC)
modparam("acc", "log_missed_flag", FLT_ACCMISSED)
modparam("acc", "log_extra",
"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
"src_user=$fU;src_domain=$fd;src_ip=$si;"
"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
modparam("acc", "failed_transaction_flag", FLT_ACCFAILED)
/* enhanced DB accounting */
#!ifdef WITH_ACCDB
@ -293,7 +332,8 @@ modparam("acc", "db_flag", FLT_ACC)
modparam("acc", "db_missed_flag", FLT_ACCMISSED)
modparam("acc", "db_url", DBURL)
modparam("acc", "db_extra",
"src_user=$fU;src_domain=$fd;dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
"src_user=$fU;src_domain=$fd;src_ip=$si;"
"dst_ouser=$tU;dst_user=$rU;dst_domain=$rd")
#!endif
@ -330,6 +370,13 @@ modparam("alias_db", "use_domain", MULTIDOMAIN)
#!endif
# ----- speedial params -----
#!ifdef WITH_SPEEDDIAL
modparam("speeddial", "db_url", DBURL)
modparam("speeddial", "use_domain", MULTIDOMAIN)
#!endif
# ----- domain params -----
#!ifdef WITH_MULTIDOMAIN
modparam("domain", "db_url", DBURL)
@ -388,18 +435,24 @@ modparam("xmlrpc", "route", "XMLRPC");
modparam("xmlrpc", "url_match", "^/RPC")
#!endif
#!ifdef WITH_DEBUG
# ----- debugger params -----
modparam("debugger", "cfgtrace", 1)
#!endif
####### Routing Logic ########
# Main SIP request routing logic
# - processing of any incoming SIP request starts with this route
route {
# - note: this is the same as route { ... }
request_route {
# per request initial checks
route(REQINIT);
# NAT detection
route(NAT);
route(NATDETECT);
# handle requests within SIP dialogs
route(WITHINDLG);
@ -460,20 +513,15 @@ route {
route[RELAY] {
#!ifdef WITH_NAT
if (check_route_param("nat=yes")) {
setbflag(FLB_NATB);
}
if (isflagset(FLT_NATS) || isbflagset(FLB_NATB)) {
route(RTPPROXY);
}
#!endif
/* example how to enable some additional event routes */
# enable additional event routes for forwarded requests
# - serial forking, RTP relaying handling, a.s.o.
if (is_method("INVITE|SUBSCRIBE")) {
t_on_branch("MANAGE_BRANCH");
t_on_reply("MANAGE_REPLY");
}
if (is_method("INVITE")) {
#t_on_branch("BRANCH_ONE");
t_on_reply("REPLY_ONE");
t_on_failure("FAIL_ONE");
t_on_failure("MANAGE_FAILURE");
}
if (!t_relay()) {
@ -527,6 +575,10 @@ route[WITHINDLG] {
setflag(FLT_ACC); # do accounting ...
setflag(FLT_ACCFAILED); # ... even if the transaction fails
}
if ( is_method("ACK") ) {
# ACK is forwarded statelessy
route(NATMANAGE);
}
route(RELAY);
} else {
if (is_method("SUBSCRIBE") && uri == myself) {
@ -572,20 +624,31 @@ route[REGISTRAR] {
# USER location service
route[LOCATION] {
#!ifdef WITH_SPEEDIAL
# search for short dialing - 2-digit extension
if($rU=~"^[0-9][0-9]$")
if(sd_lookup("speed_dial"))
route(SIPOUT);
#!endif
#!ifdef WITH_ALIASDB
# search in DB-based aliases
alias_db_lookup("dbaliases");
if(alias_db_lookup("dbaliases"))
route(SIPOUT);
#!endif
$avp(oexten) = $rU;
if (!lookup("location")) {
switch ($rc) {
$var(rc) = $rc;
route(TOVOICEMAIL);
t_newtran();
switch ($var(rc)) {
case -1:
case -3:
t_newtran();
t_reply("404", "Not Found");
send_reply("404", "Not Found");
exit;
case -2:
sl_send_reply("405", "Method Not Allowed");
send_reply("405", "Method Not Allowed");
exit;
}
}
@ -635,72 +698,44 @@ route[PRESENCE] {
# Authentication route
route[AUTH] {
#!ifdef WITH_AUTH
if (is_method("REGISTER"))
{
# authenticate the REGISTER requests (uncomment to enable auth)
if (!www_authorize("$td", "subscriber"))
{
www_challenge("$td", "0");
exit;
}
if ($au!=$tU)
{
sl_send_reply("403","Forbidden auth ID");
exit;
}
} else {
#!ifdef WITH_IPAUTH
if(allow_source_address())
{
# source IP allowed
return;
}
if((!is_method("REGISTER")) && allow_source_address())
{
# source IP allowed
return;
}
#!endif
# authenticate if from local subscriber
if (from_uri==myself)
{
if (!proxy_authorize("$fd", "subscriber")) {
proxy_challenge("$fd", "0");
exit;
}
if (is_method("PUBLISH"))
{
if ($au!=$tU) {
sl_send_reply("403","Forbidden auth ID");
exit;
}
} else {
if ($au!=$fU) {
sl_send_reply("403","Forbidden auth ID");
exit;
}
}
consume_credentials();
# caller authenticated
} else {
# caller is not local subscriber, then check if it calls
# a local destination, otherwise deny, not an open relay here
if (!uri==myself)
{
sl_send_reply("403","Not relaying");
exit;
}
if (is_method("REGISTER") || from_uri==myself)
{
# authenticate requests
if (!auth_check("$fd", "subscriber", "1")) {
auth_challenge("$fd", "0");
exit;
}
# user authenticated - remove auth header
if(!is_method("REGISTER|PUBLISH"))
consume_credentials();
}
# if caller is not local subscriber, then check if it calls
# a local destination, otherwise deny, not an open relay here
if (from_uri!=myself && uri!=myself)
{
sl_send_reply("403","Not relaying");
exit;
}
#!endif
return;
}
# Caller NAT detection route
route[NAT] {
route[NATDETECT] {
#!ifdef WITH_NAT
force_rport();
if (nat_uac_test("19")) {
if (method=="REGISTER") {
if (is_method("REGISTER")) {
fix_nated_register();
} else {
fix_nated_contact();
@ -712,14 +747,30 @@ route[NAT] {
}
# RTPProxy control
route[RTPPROXY] {
route[NATMANAGE] {
#!ifdef WITH_NAT
if (is_method("BYE")) {
unforce_rtp_proxy();
} else if (is_method("INVITE")){
force_rtp_proxy();
if (is_request()) {
if(has_totag()) {
if(check_route_param("nat=yes")) {
setbflag(FLB_NATB);
}
}
}
if (!(isflagset(FLT_NATS) || isbflagset(FLB_NATB)))
return;
rtpproxy_manage();
if (is_request()) {
if (!has_totag()) {
add_rr_param(";nat=yes");
}
}
if (is_reply()) {
if(isbflagset(FLB_NATB)) {
fix_nated_contact();
}
}
if (!has_totag()) add_rr_param(";nat=yes");
#!endif
return;
}
@ -765,8 +816,7 @@ route[PSTN] {
# XMLRPC routing
#!ifdef WITH_XMLRPC
route[XMLRPC]
{
route[XMLRPC] {
# allow XMLRPC from localhost
if ((method=="POST" || method=="GET")
&& (src_ip==127.0.0.1)) {
@ -783,51 +833,64 @@ route[XMLRPC]
}
#!endif
# Sample branch router
branch_route[BRANCH_ONE] {
xdbg("new branch at $ru\n");
}
# route to voicemail server
route[TOVOICEMAIL] {
#!ifdef WITH_VOICEMAIL
if(!is_method("INVITE"))
return;
# Sample onreply route
onreply_route[REPLY_ONE] {
xdbg("incoming reply\n");
#!ifdef WITH_NAT
if ((isflagset(FLT_NATS) || isbflagset(FLB_NATB))
&& status=~"(183)|(2[0-9][0-9])") {
force_rtp_proxy();
}
if (isbflagset(FLB_NATB)) {
fix_nated_contact();
# check if VoiceMail server IP is defined
if (strempty($sel(cfg_get.voicemail.srv_ip))) {
xlog("SCRIPT: VoiceMail rotuing enabled but IP not defined\n");
return;
}
if($avp(oexten)==$null)
return;
$ru = "sip:" + $avp(oexten) + "@" + $sel(cfg_get.voicemail.srv_ip)
+ ":" + $sel(cfg_get.voicemail.srv_port);
route(RELAY);
exit;
#!endif
return;
}
# Sample failure route
failure_route[FAIL_ONE] {
#!ifdef WITH_NAT
if (is_method("INVITE")
&& (isbflagset(FLB_NATB) || isflagset(FLT_NATS))) {
unforce_rtp_proxy();
}
#!endif
# manage outgoing branches
branch_route[MANAGE_BRANCH] {
xdbg("new branch [$T_branch_idx] to $ru\n");
route(NATMANAGE);
}
# manage incoming replies
onreply_route[MANAGE_REPLY] {
xdbg("incoming reply\n");
if(status=~"[12][0-9][0-9]")
route(NATMANAGE);
}
# manage failure routing cases
failure_route[MANAGE_FAILURE] {
route(NATMANAGE);
if (t_is_canceled()) {
exit;
}
# uncomment the following lines if you want to block client
# redirect based on 3xx replies.
##if (t_check_status("3[0-9][0-9]")) {
##t_reply("404","Not found");
## exit;
##}
# uncomment the following lines if you want to redirect the failed
# calls to a different new destination
##if (t_check_status("486|408")) {
## sethostport("192.168.2.100:5060");
## append_branch();
## # do not set the missed call flag again
## t_relay();
##}
#!ifdef WITH_BLOCK3XX
# block call redirect based on 3xx replies.
if (t_check_status("3[0-9][0-9]")) {
t_reply("404","Not found");
exit;
}
#!endif
#!ifdef WITH_VOICEMAIL
# serial forking
# - route to voicemail on busy or no answer (timeout)
if (t_check_status("486|408")) {
route(TOVOICEMAIL);
exit;
}
#!endif
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save