Today I needed to get Sip Express Router to work with a preconfigured set of aliases. I have a project where there is a very small wafer PC running SER out of flash. The configuration is completely static and I have no need or wish to use MySQL to record this stuff.
I have chosen to use 0.9.6 SER as that seems to be the latest stable.
First port of call was the SER site where I checked out the module documentation for dbtext http://www.iptel.org/ser/doc/modules/dbtext . It was kind of minimal. In particular it didn’t tell me what I needed to know – which fields in the dbtext aliases example were needed and what values should be in them.
I also rapidly discovered that the example configuration file had problems such as wrong module paths.
To cut a long story short (and a horror experience getting mysql going to capture the table contents from ser aliases generated by serctl ) I ended up with the following files in /tmp/serdb. Of particular note is the need to \ the : character in the sip contact field as that is also the dbtext field separator.
In the aliases file username is the text of the alias and contact is where it is routed to – with sip: preceding the actual contact. All other fields should be as listed below – the 2000000000 field entries represent times and dates in the hopefully distant future
/tmp/serdb/aliases
username(str) domain(str,null) contact(str,null) expires(int,null) q(double,null) callid(str,null) cseq(int,null) last_modified(str) replicate(int,null) state(int,null) flags(int) user_agent(str) received(str,null)
1002::sip\\:1009@example.org:2000000000:1.0:FourtyTwo:42:2000000000:0:0:128:SIP Express Router FIFO::
1003::sip\\:1009@example.org:2000000000:1.0:FourtyTwo:42:2000000000:0:0:128:SIP Express Router FIFO::
1004::sip\\:1009@example.org:2000000000:1.0:FourtyTwo:42:2000000000:0:0:128:SIP Express Router FIFO::
/tmp/serdb/subscriber
username(str) password(str) ha1(str) domain(str) ha1b(str) rpid(str)
2000:plain_password:xxx:example.org:xxx:ZZZZ
1009:plan_pass2:xxx:example.org:xxx:ZZZ
/tmp/serdb/version
table_name(str) table_version(int)
subscriber:3
location:7
aliases:7
/tmp/serdb/location
username(str) domain(str,null) contact(str,null) expires(int,null) q(double,null) callid(str,null) cseq(int,null) last_modified(str) replicate(int,null) state(int,null) flags(int) user_agent(str) received(str)
To complement these I had a sercfg set up with correct paths as follows
/usr/local/etc/ser/ser,cfg
# simple quick-start config script with dbtext and correct paths for ser-0.9.6
#
# ----------- global configuration parameters ------------------------
#debug=9 # debug level (cmd line: -dddddddddd)
#forki=yes
#log_stderror=no # (cmd line: -E)
check_via=no # (cmd. line: -v)
dns=no # (cmd. line: -r)
rev_dns=no # (cmd. line: -R)
children=4
listen=10.0.0.1
port=5060
fifo="/tmp/ser_fifo"
alias=example.org
# ------------------ module loading ----------------------------------
# use dbtext database
loadmodule "/usr/local/lib/ser/modules/dbtext.so"
loadmodule "/usr/local/lib/ser/modules/sl.so"
loadmodule "/usr/local/lib/ser/modules/tm.so"
loadmodule "/usr/local/lib/ser/modules/rr.so"
loadmodule "/usr/local/lib/ser/modules/maxfwd.so"
loadmodule "/usr/local/lib/ser/modules/usrloc.so"
loadmodule "/usr/local/lib/ser/modules/registrar.so"
loadmodule "/usr/local/lib/ser/modules/textops.so"
# modules for digest authentication
loadmodule "/usr/local/lib/ser/modules/auth.so"
loadmodule "/usr/local/lib/ser/modules/auth_db.so"
# ----------------- setting module-specific parameters ---------------
# -- usrloc params --
# use dbtext database for persistent storage
modparam("usrloc", "db_mode", 1)
modparam("usrloc|auth_db", "db_url", "dbtext:///tmp/serdb")
# -- auth params --
#
modparam("auth_db", "calculate_ha1", 1)
modparam("auth_db", "password_column", "password")
modparam("auth_db", "user_column", "username")
modparam("auth_db", "domain_column", "domain")
# -- rr params --
# add value to ;lr param to make some broken UAs happy
modparam("rr", "enable_full_lr", 1)
# ------------------------- request routing logic -------------------
# main routing logic
route{
# initial sanity checks -- messages with
# max_forwards==0, or excessively long requests
if (!mf_process_maxfwd_header("10")) {
sl_send_reply("483","Too Many Hops");
break;
};
if (msg:len >= max_len ) {
sl_send_reply("513", "Message too big");
break;
};
# we record-route all messages -- to make sure that
# subsequent messages will go through our proxy; that's
# particularly good if upstreami and downstreami entities
# use different transport protocol
if (!method=="REGISTER") record_route();
# subsequent messages withing a dialogi should take the
# path determined by record-routing
if (loose_route()) {
# mark routing logic in request
append_hf("P-hint: rr-enforcedrn");
route(1);
break;
};
if (!uri==myself) {
# mark routing logic in request
append_hf("P-hint: outboundrn");
route(1);
break;
};
# if the request is for other domain use UsrLoc
# (in case, it does not work, use the following command
# with proper names and addresses in it)
if (uri==myself) {
if (method=="REGISTER") {
# digest authentication
if (!www_authorize("", "subscriber")) {
www_challenge("", "0");
break;
};
save("location");
break;
};
lookup("aliases");
if (!uri==myself) {
append_hf("P-hint: outbound aliasrn");
route(1);
break;
};
# native SIP destinations are handled using our USRLOC DB
if (!lookup("location")) {
sl_send_reply("404", "Not Found");
break;
};
};
append_hf("P-hint: usrloc appliedrn");
route(1);
}
route[1]
{
# send it out now; use stateful forwarding as it works reliably
# even for UDP2TCP
if (!t_relay()) {
sl_reply_error();
};
}