mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1121 lines
32 KiB
1121 lines
32 KiB
***************************
|
|
* Sems + Ser mini-HOWTO *
|
|
***************************
|
|
|
|
|
|
1. Introduction:
|
|
|
|
This document describes the configuration of a typical Sems installation. It
|
|
aims at giving Sems users a basic understanding on how Sems works, and how to
|
|
configure Ser to implement some simple scenarios using Sems. The author will
|
|
try to focus on the configuration itself, as the main README allready explains
|
|
how to install Sems itself. Please refer to the Ser documentation if you have
|
|
any problems installing Ser itself.
|
|
|
|
In this document, it will be asserted that the reader has a basic
|
|
understanding of Linux and SIP (Session Initiation Protocol, RFC 3261). If you
|
|
don't, please try to get more familiar to Linux before continuing reading this
|
|
document. If need more information on SIP, consider downloading iptel.org's
|
|
SIP tutorial (www.iptel.org/sip).
|
|
|
|
|
|
2. Getting Ser and Sems to communicate together:
|
|
|
|
To work properly, Sems needs a working Ser instance, which will be used as
|
|
Sems' SIP stack. They communicate together either through unix socket servers
|
|
or FIFO servers. Each side implements a server, enabling communication in both
|
|
ways.You will need to configure Ser to use Sems's server, and Sems to use Ser's
|
|
server. If you plan to run more than one Ser instance on the same host,
|
|
be sure to know wich Ser instance you want to connect to Sems (!).
|
|
|
|
Some people have only one Ser instance. Other users have a dedicated instance
|
|
for Sems. If you don't know what you need, try first with a dedicated
|
|
instance, as the configuration of that instance will be much easier. A sample
|
|
configuration with a single ser instance is given in 3.2.
|
|
|
|
|
|
2.1 Configure Sems to use Ser's Unix socket server:
|
|
|
|
- edit Ser's configuration file (default location:
|
|
/usr/local/etc/ser/ser.cfg) and look for the 'fifo=' configuration
|
|
parameter. It should look like:
|
|
|
|
fifo="/tmp/ser_fifo"
|
|
|
|
If the 'fifo' parameter does not exist, add it to the global
|
|
section. If you have another value for that parameter, you don't need to
|
|
change it, just remember it.
|
|
|
|
- open Sems's configuration file (default location:
|
|
/usr/local/etc/sems/sems.conf) and look for the 'ser_fifo_name='
|
|
parameter. It must have the same value as 'fifo=' in Ser's
|
|
configuration file, but without quotes. In our example:
|
|
|
|
ser_fifo_name=/tmp/ser_fifo
|
|
|
|
- then configure the 'socket_name=' parameter. Default value:
|
|
|
|
socket_name=/tmp/am_sock
|
|
|
|
- then configure the 'send_method=' parameter. Default value:
|
|
|
|
send_method=fifo
|
|
|
|
|
|
FIFO server vs. unix socket server
|
|
----------------------------------
|
|
Under heavy load, especially when many calls are initiated at once, the fifo
|
|
buffer can be too small. Therefore unix sockets can be used to write a request
|
|
from ser to sems. Unix sockets only work in cvs version of both ser and sems.
|
|
|
|
examples:
|
|
* SER -> SEMS : use unix socket
|
|
in sems.conf:
|
|
#fifo_name=/tmp/am_fifo # fifo not enabled
|
|
socket_name=/tmp/am_sock # unix socket enabled
|
|
in ser.cfg routing:
|
|
t_write_unix("/tmp/am_sock", "voicemail")
|
|
|
|
* SER -> SEMS : use fifo
|
|
in sems.conf:
|
|
fifo_name=/tmp/am_fifo # fifo enabled
|
|
#socket_name=/tmp/am_sock # unix socket not enabled
|
|
in ser.cfg routing:
|
|
t_write_req("/tmp/am_fifo", "voicemail")
|
|
|
|
* SEMS -> SER : use fifo
|
|
in ser.cfg:
|
|
fifo="/tmp/ser_fifo"
|
|
in sems.conf:
|
|
send_method=fifo
|
|
ser_fifo_name=/tmp/ser_fifo
|
|
|
|
* SEMS -> SER : use unix socket
|
|
in ser.cfg:
|
|
socket="/tmp/ser_socket"
|
|
in sems.conf:
|
|
send_method=unix_socket
|
|
ser_socket_name=/tmp/ser_socket
|
|
|
|
2.2 How to redirect a call to sems?
|
|
|
|
2.2.1 How it works:
|
|
|
|
So that a caller gets connected to Sems, Ser has to pass every SIP message
|
|
concerning that call to Sems through unix socket (or fifo). Basically, Sems
|
|
needs to get an INVITE message to begin a call, and a BYE message to terminate
|
|
that call. Sems must also be aware of CANCELs. ACKs should be absorbed by Ser,
|
|
as Sems does not need them. Redirecting the messages is a very simple
|
|
operation. You just have to call the t_write_unix() (or t_write_req())
|
|
function from the 'tm' module, which you have to load.
|
|
|
|
2.2.2 Load Ser's tm module and configure fifo_db:
|
|
|
|
- add following line to your ser.cfg in the 'module loading' section:
|
|
|
|
loadmodule "/usr/local/lib/ser/modules/tm.so"
|
|
|
|
- add following line to your ser.cfg in the 'global configuration
|
|
parameters' section and change the url according to your database
|
|
configuration:
|
|
|
|
fifo_db_url="mysql://ser:heslo@localhost/ser"
|
|
|
|
|
|
2.2.3 Redirecting SIP messages to Sems:
|
|
|
|
- add following lines to your ser.cfg where you need to redirect the call:
|
|
|
|
# select messages to redirect:
|
|
if ( method=="ACK" || method=="INVITE" || method=="BYE" ||
|
|
method=="CANCEL" ){
|
|
|
|
# switch to stateful mode:
|
|
if (!t_newtran()){
|
|
sl_send_reply("500","could not create transaction");
|
|
break;
|
|
};
|
|
|
|
# prevent timeout on the other side:
|
|
t_reply("100","Trying - just wait a minute !");
|
|
|
|
if (method=="INVITE"){
|
|
|
|
# redirect the call to the 'conference' plug-in
|
|
# if the URI begin with 100
|
|
if (uri=~"sip:100.*@") {
|
|
|
|
# assumes that Sems configuration parameter 'socket_name='
|
|
# has been set to /tmp/am_sock
|
|
if(!t_write_unix("/tmp/am_sock","conference")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# redirect the call to the 'announcement' plug-in
|
|
# if the URI begin with 200
|
|
if (uri=~"sip:200.*@") {
|
|
|
|
if(!t_write_unix("/tmp/am_sock","announcement")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# no service number, redirect to voicemail.
|
|
# do not forget to load AVPs so that voicemail gets the
|
|
# callee's email address.
|
|
load_avp("ruri","email",0);
|
|
if(!t_write_unix("/tmp/am_sock","voicemail")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
}
|
|
else if (method=="BYE" || method="CANCEL") {
|
|
|
|
# Sems should already know which plug-in is handling that
|
|
# call. "bye" is no plug-in name. It is a reserved name which
|
|
# tells Sems to terminate the call.
|
|
|
|
if(!t_write_unix("/tmp/am_sock","bye")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
};
|
|
};
|
|
|
|
In more complicated scenario, you could also redirect REFERs to Sems which
|
|
would enable you for example to implement a click-to-dial, or invite other
|
|
users to take part to conference.
|
|
|
|
|
|
2.3 Pass email address from ser to sems (for voicemail)
|
|
|
|
For the voicemail plug-in to work properly, sems has to get the email address
|
|
of the callee. As email adresses are usually stored in a database and ser
|
|
usually already has a db connection, sems uses ser to get the email address.
|
|
|
|
There are two possibilities to do this:
|
|
1. through fifo_db
|
|
or
|
|
2. with tw_append
|
|
|
|
2.3.1. Using fifo_db
|
|
|
|
SEMS can query the database through the fifo. For this, ser must be configured
|
|
to
|
|
- have a db module loaded (e.g. mysql or textdb)
|
|
- have fifo_db_url.
|
|
|
|
example configuration with mysql:
|
|
loadmodule "/usr/local/lib/ser/modules/mysql.so"
|
|
fifo_db_url="mysql://ser:heslo@localhost/ser"
|
|
|
|
example configuration (ser.cfg) with dbtext:
|
|
fifo_db_url="dbtext:///path/to/dbtext/dir"
|
|
loadmodule "/usr/local/lib/ser/modules/dbtext.so"
|
|
note the three slashes if the path is absolute
|
|
(dbtext:///usr/local/etc/sems/tables) . A sample text file usr_preferences to
|
|
put in /path/to/dbtext/dir would have the following form:
|
|
--- usr_preferences file ------------------------------
|
|
username(str,null) domain(str,null) attribute(str,null) value(str,null) type(int,null)
|
|
Alice:mysipdomain.com:email:alice@maildomain.com:2
|
|
Bob:mysipdomain.com:email:bob@anothermailaddress.com:2
|
|
-------------------------------------------------------
|
|
|
|
2.3.2 Using tw_append and avpops
|
|
|
|
Arbitrary AVPs (attribute value pairs) can be appended to a request when it is
|
|
written to sems with t_write_req/t_write_unix using tw_append. The AVPs can
|
|
e.g. be loaded from a database before, modified with avpops etc. This only
|
|
work in cvs version of both ser and sems.
|
|
|
|
This method is recommended, as it is much more flexible, e.g. the language of
|
|
a user can be stored in the database, and the greeting and voicemail template
|
|
will be selected according to the language, but it is a bit more
|
|
complicated to configure:
|
|
|
|
# load db module
|
|
loadmodule "/usr/local/lib/ser/modules/mysql.so"
|
|
|
|
# load avp modules
|
|
loadmodule "modules/avp/avp.so"
|
|
loadmodule "modules/avpops/avpops.so"
|
|
|
|
# configure avpops db connection
|
|
modparam( "avpops", "avp_url", "mysql://ser:heslo@localhost/ser" )
|
|
modparam( "avpops", "avp_table", "subscriber" )
|
|
modparam( "avpops", "uuid_column", "id" )
|
|
|
|
# configure aliases, the number doesn't matter as long as there are no collisions)
|
|
modparam( "avpops", "avp_aliases", "email=i:67 ; language=i:68" )
|
|
|
|
# scheme to access the database
|
|
modparam( "avpops", "db_scheme",
|
|
"email_scheme:table=subscriber;value_col=email_address;value_type=string")
|
|
modparam( "avpops", "db_scheme",
|
|
"language_scheme:table=subscriber;value_col=language;value_type=string")
|
|
|
|
# configure tm to append this when tw_appent voicemail_headers is used
|
|
modparam("tm", "tw_append",
|
|
"voicemail_headers:hdr[User-Agent];P-Email-Address=avp[$email];P-Language=avp[$language]")
|
|
|
|
# ...
|
|
|
|
# in route section:
|
|
# no service number, redirect to voicemail.
|
|
|
|
avp_db_load( "$ruri", "$email/$email_scheme");
|
|
avp_db_load( "$ruri", "$language/$language_scheme");
|
|
|
|
if(!t_write_req("/tmp/am_fifo","voicemail/voicemail_headers")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
|
|
|
|
This assumes that there is a column 'id', a column 'username', a column 'email_address' and a
|
|
column 'language' in the table named 'subscriber'. dbtext sample file:
|
|
----- subscriber --------------------------------
|
|
id(int,auto) username(str,null) domain(str,null) email_address(str,null) language(str,null)
|
|
1:Alice:iptel.org:alice@mymail.org:english
|
|
2:rco:iptel.org:rco@iptel.org:french
|
|
3:Alex:iptel.org:alex@iptel.org:german
|
|
----- subsciber end ------------------------------
|
|
|
|
|
|
3. Configuration files used in this HOWTO:
|
|
|
|
3.1 simple configuration with dedicated ser instance and fifo_db
|
|
|
|
-------------------------- ser.cfg -----------------------------------
|
|
#
|
|
# simple Ser config script to start using Sems.
|
|
#
|
|
|
|
# ----------- global configuration parameters ------------------------
|
|
|
|
#debug=3 # debug level (cmd line: -dddddddddd)
|
|
#fork=yes
|
|
#log_stderror=no # (cmd line: -E)
|
|
|
|
/* Uncomment these lines to enter debugging mode
|
|
debug=7
|
|
fork=no
|
|
log_stderror=yes
|
|
*/
|
|
|
|
check_via=no # (cmd. line: -v)
|
|
dns=no # (cmd. line: -r)
|
|
rev_dns=no # (cmd. line: -R)
|
|
#port=5060
|
|
#children=4
|
|
|
|
# Configure Ser to create a FIFO server
|
|
fifo="/tmp/ser_sock"
|
|
|
|
# Configure FIFO DB
|
|
fifo_db_url="mysql://ser:heslo@localhost/ser"
|
|
|
|
# ------------------ module loading ----------------------------------
|
|
|
|
loadmodule "/usr/local/lib/ser/modules/mysql.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"
|
|
|
|
# ----------------- setting module-specific parameters ---------------
|
|
|
|
# -- usrloc params --
|
|
#modparam("usrloc", "db_mode", 0)
|
|
|
|
# Uncomment this if you want to use SQL database
|
|
# for persistent storage and comment the previous line
|
|
modparam("usrloc", "db_mode", 2)
|
|
|
|
# -- 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 upstream and downstream entities
|
|
# use different transport protocol
|
|
record_route();
|
|
# loose-route processing
|
|
if (loose_route()) {
|
|
t_relay();
|
|
break;
|
|
};
|
|
|
|
if (uri==myself) {
|
|
|
|
if (method=="REGISTER") {
|
|
|
|
# make UAs which want to register happy
|
|
sl_send_reply("200","OK");
|
|
break;
|
|
};
|
|
|
|
# switch to statefull mode:
|
|
if (!t_newtran()){
|
|
sl_send_reply("500","could not create transaction");
|
|
break;
|
|
};
|
|
|
|
if (method=="ACK"){
|
|
# absorb ACKs
|
|
break;
|
|
};
|
|
|
|
# prevent timeout on the other side:
|
|
t_reply("100","Trying - just wait a minute !");
|
|
|
|
if (method=="INVITE"){
|
|
|
|
# redirect the call to the 'conference' plug-in
|
|
# if the URI begin with 100
|
|
if (uri=~"sip:100.*@") {
|
|
|
|
# assumes that Sems configuration parameter 'socket_name='
|
|
# has been set to /tmp/am_sock
|
|
if(!t_write_unix("/tmp/am_sock","conference")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# redirect the call to the 'announcement' plug-in
|
|
# if the URI begin with 200
|
|
if (uri=~"sip:200.*@") {
|
|
|
|
if(!t_write_unix("/tmp/am_sock","announcement")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# no service number, redirect to voicemail.
|
|
# do not forget to load AVPs so that voicemail gets the
|
|
# callee's email address.
|
|
#load_avp("ruri","email",0);
|
|
if(!t_write_unix("/tmp/am_sock","voicemail")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
}
|
|
else if (method=="BYE" || method=="CANCEL") {
|
|
|
|
# Sems should already know which plug-in is handling that
|
|
# call. "bye" is no plug-in name. It is a reserved name which
|
|
# tells Sems to terminate the call.
|
|
|
|
if(!t_write_unix("/tmp/am_sock","bye")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
};
|
|
};
|
|
|
|
# forward to current uri now; use stateful forwarding; that
|
|
# works reliably even if we forward from TCP to UDP
|
|
if (!t_relay()) {
|
|
sl_reply_error();
|
|
};
|
|
}
|
|
|
|
-------------------------- ser.cfg end --------------------------------
|
|
|
|
|
|
-------------------------- sems.conf ----------------------------------
|
|
#
|
|
# sems.conf.sample
|
|
#
|
|
# Sip Express Media Server (sems)
|
|
#
|
|
# sample configuration file
|
|
#
|
|
#
|
|
# whitespaces (spaces and tabs) are ignored
|
|
# comments start with a "#" and may be used inline
|
|
#
|
|
# example: option=value1, value2 # i like this option
|
|
#
|
|
|
|
##################################
|
|
# global parameters #
|
|
##################################
|
|
|
|
# optional parameter: fork={yes|no}
|
|
#
|
|
# - specifies if sems should run in daemon mode (background)
|
|
# (fork=no is the same as -E)
|
|
fork=yes
|
|
|
|
# optional parameter: stderr={yes|no}
|
|
#
|
|
# - debug mode: do not fork and log to stderr
|
|
# (stderr=yes is the same as -E)
|
|
stderr=no
|
|
|
|
# optional parameter: loglevel={0|1|2|3}
|
|
#
|
|
# - sets log level (error=0, warning=1, info=2, debug=3)
|
|
# (same as -D)
|
|
loglevel=1
|
|
|
|
# optional parameter: ser_fifo_name=<filename>
|
|
#
|
|
# - path and file name of Ser's fifo file (same as -o)
|
|
ser_fifo_name=/tmp/ser_fifo
|
|
|
|
# optional parameter: socket_name=<filename>
|
|
#
|
|
# - path and file name of our unix socket
|
|
socket_name=/tmp/am_sock
|
|
|
|
# optional parameter: ser_socket_name=<filename>
|
|
#
|
|
# - path and file name of Ser's unix socket
|
|
ser_socket_name=/tmp/ser_sock
|
|
|
|
# optional parameter: send_method=<filename>
|
|
#
|
|
# - sets which method will be used to contact Ser:
|
|
# FIFO or unix socket server.
|
|
# - values: fifo (default), unix_socket
|
|
#
|
|
# - PLEASE NOTE THAT: if you use 'fifo', make sure that
|
|
# fifo_name and ser_fifo_name have been set. if you use 'unix_socket',
|
|
# make sure that socket_name and ser_socket_name have been set.
|
|
#
|
|
send_method=fifo
|
|
|
|
# optional parameter: plugin_path=<path>
|
|
#
|
|
# - sets the path to the plug-ins
|
|
# - may be absolute or relative to CWD
|
|
plugin_path=/usr/local/lib/sems/plug-in/
|
|
|
|
# optional parameter: smtp_server=<hostname>
|
|
#
|
|
# - sets address of smtp server
|
|
smtp_server=localhost
|
|
|
|
# optional parameter: smtp_port=<port>
|
|
#
|
|
# - sets port of smtp server
|
|
smtp_port=25
|
|
|
|
# optional parameter: rtp_low_port=<port>
|
|
#
|
|
# - sets port of rtp lowest server
|
|
#rtp_low_port=1024
|
|
|
|
# optional parameter: rtp_high_port=<port>
|
|
#
|
|
# - sets port of rtp highest server
|
|
#rtp_high_port=65535
|
|
|
|
##################################
|
|
# module specific parameters #
|
|
##################################
|
|
|
|
# sample voicemail configuration (inline)
|
|
config.voicemail=inline
|
|
|
|
# optional parameter: announce_path=<path>
|
|
#
|
|
# - sets the path where announce files are searched for
|
|
# - the file to be played is determined the following way:
|
|
# <announce_path>/<domainname>/<username>.wav
|
|
# if this file is not available <announce_path>/<default_anounce> is used
|
|
announce_path=/usr/local/lib/sems/audio/
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the name of the default announce WAV file
|
|
default_announce=default_en.wav
|
|
|
|
# parameter: max_record_time=<seconds>
|
|
#
|
|
# - maximum record time
|
|
max_record_time=30
|
|
|
|
# parameter: email_template=<filename>
|
|
#
|
|
# - email template file
|
|
#
|
|
# See the README file in <sems-src>/plug-in/voicemail
|
|
# for more information on the syntax used.
|
|
#
|
|
email_template=/usr/local/lib/sems/plug-in/mail.template
|
|
|
|
# end of configuration section for voicemail module
|
|
config.voicemail=end
|
|
|
|
|
|
# sample announcement configuration (inline)
|
|
config.announcement=inline
|
|
|
|
# optional parameter: announce_path=<path>
|
|
#
|
|
# - sets the path where announce files are searched for
|
|
announce_path=/usr/local/lib/sems/audio/
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the name of the default announce WAV file
|
|
default_announce=default_en.wav
|
|
|
|
# end of configuration section for announcement module
|
|
config.announcement=end
|
|
|
|
|
|
# sample isdngw module configuration (external file)
|
|
# config.isdngw=/etc/isdngw.conf
|
|
|
|
# sample ivr module configuration (inline)
|
|
config.ivr=inline
|
|
|
|
#parameter: python_script_path=<full path>
|
|
python_script_path=/etc/ivr
|
|
|
|
#parameter: python_script_file=<filename>
|
|
python_script_file=example.py
|
|
|
|
# end of configuration section for ivr module
|
|
config.ivr=end
|
|
|
|
|
|
# sample conference configuration (inline)
|
|
config.conference=inline
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the full pathed name of the default announce WAV file.
|
|
# Will be played to lonely users.
|
|
default_announce=/usr/local/lib/sems/audio/first_participant.wav
|
|
|
|
# parameter: join_sound=<filename>
|
|
#
|
|
# - sets the full pathed name of a WAV file
|
|
# which will be played to conference users
|
|
# when a new user joins the conference.
|
|
join_sound=/usr/local/lib/sems/audio/beep.wav
|
|
|
|
# parameter: drop_sound=<filename>
|
|
#
|
|
# - sets the full pathed name of a WAV file
|
|
# which will be played to conference users
|
|
# when a user drops the conference.
|
|
drop_sound=/usr/local/lib/sems/audio/beep.wav
|
|
|
|
# end of configuration section for conference module
|
|
config.conference=end
|
|
|
|
# example configuration for number reader
|
|
config.number_reader=inline
|
|
|
|
number_path=/usr/local/lib/sems/audio/
|
|
|
|
prolog_file=welcome_to_number_reader.wav
|
|
|
|
epilog_file=thanks_calling_number_reader.wav
|
|
|
|
# end of number_reader configuration
|
|
config.number_reader=end
|
|
|
|
# add more module configurations here (inline or external):
|
|
#
|
|
# config.mymodule=<filename>
|
|
# or
|
|
# config.mymodule=inline
|
|
# ...
|
|
# config.mymodule=end
|
|
|
|
-------------------------- sems.conf end ------------------------------
|
|
|
|
3.2 Single instance ser, using tw_append and avpops
|
|
|
|
If an INVITE is sent to sems, sems will return a Contact in the form of
|
|
<plugin_name><user_prefix_separator><local_user>@<localdomain>
|
|
if user_prefix_separator is set in sems.conf .
|
|
e.g. if the following line is present in sems.conf:
|
|
user_prefix_separator=+
|
|
and an INVITE is sent to voicemail plugin for alice@mydomain.com,
|
|
sems will reply with a Contact header
|
|
Contact: voicemail+alice@mydomain.com
|
|
and all further requests can be routed to that plugin to sems directly.
|
|
|
|
This configuration uses fifo ser->sems ans sems->ser and dbtext.
|
|
mkdir /usr/local/etc/sems/tables
|
|
and create a file subscriber there:
|
|
----- subscriber --------------------------------
|
|
id(int,auto) username(str,null) domain(str,null) email_address(str,null) language(str,null)
|
|
1:Alice:iptel.org:alice@mymail.org:english
|
|
2:rco:iptel.org:rco@iptel.org:french
|
|
3:Alex:iptel.org:alex@iptel.org:german
|
|
----- subsciber end ------------------------------
|
|
|
|
|
|
-------------------------- ser.cfg -----------------------------------
|
|
# ----------- global configuration parameters ------------------------
|
|
#debug=3 # debug level (cmd line: -dddddddddd)
|
|
fork=yes
|
|
log_stderror=no # (cmd line: -E)
|
|
|
|
/* Uncomment these lines to enter debugging mode
|
|
debug=7
|
|
fork=no
|
|
log_stderror=yes
|
|
*/
|
|
|
|
check_via=no # (cmd. line: -v)
|
|
dns=no # (cmd. line: -r)
|
|
rev_dns=no # (cmd. line: -R)
|
|
#port=5060
|
|
#children=4
|
|
|
|
# Configure Ser to create a FIFO server
|
|
fifo="/tmp/ser_fifo"
|
|
|
|
# ------------------ module loading ----------------------------------
|
|
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/avp.so"
|
|
loadmodule "/usr/local/lib/ser/modules/avpops.so"
|
|
|
|
# ----------------- setting module-specific parameters ---------------
|
|
|
|
# -- usrloc params --
|
|
#modparam("usrloc", "db_mode", 0)
|
|
|
|
# Uncomment this if you want to use SQL database
|
|
# for persistent storage and comment the previous line
|
|
#modparam("usrloc", "db_mode", 2)
|
|
|
|
# -- rr params --
|
|
# add value to ;lr param to make some broken UAs happy
|
|
modparam("rr", "enable_full_lr", 1)
|
|
|
|
|
|
modparam( "avpops", "avp_url", "dbtext:///usr/local/etc/sems/tables" )
|
|
modparam( "avpops", "avp_table", "subscriber" )
|
|
modparam( "avpops", "uuid_column", "id" )
|
|
|
|
modparam( "avpops", "avp_aliases", "email=i:67 ; language=i:68" )
|
|
|
|
modparam( "avpops", "db_scheme",
|
|
"email_scheme:table=subscriber;value_col=email_address;value_type=string")
|
|
modparam( "avpops", "db_scheme",
|
|
"language_scheme:table=subscriber;value_col=language;value_type=string")
|
|
|
|
modparam("tm", "tw_append",
|
|
"voicemail_headers:hdr[User-Agent];P-Email-Address=avp[$email];P-Language=avp[$language]")
|
|
|
|
# ------------------------- 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 upstream and downstream entities
|
|
# use different transport protocol
|
|
record_route();
|
|
# loose-route processing
|
|
if (loose_route()) {
|
|
t_relay();
|
|
break;
|
|
};
|
|
|
|
if (uri==myself) {
|
|
|
|
if (method=="REGISTER") {
|
|
|
|
# make UAs which want to register happy
|
|
sl_send_reply("200","OK");
|
|
break;
|
|
};
|
|
|
|
# switch to statefull mode:
|
|
if (!t_newtran()){
|
|
sl_send_reply("500","could not create transaction");
|
|
break;
|
|
};
|
|
|
|
if (method=="ACK"){
|
|
# absorb ACKs
|
|
break;
|
|
};
|
|
|
|
# prevent timeout on the other side:
|
|
t_reply("100","Trying - just wait a minute !");
|
|
|
|
# forward to sems plugin directly if r_uri is plugin_name+...@...
|
|
if (uri=~"sip:voicemail+*@*") {
|
|
if(!t_write_req("/tmp/am_fifo","voicemail")){
|
|
log("could not contact voicemail\n");
|
|
t_reply("500","could not contact voicemail");
|
|
};
|
|
break;
|
|
};
|
|
|
|
if (uri=~"sip:conference+*@*") {
|
|
if(!t_write_req("/tmp/am_fifo","conference")){
|
|
log("could not contact conference\n");
|
|
t_reply("500","could not contact conference");
|
|
};
|
|
break;
|
|
};
|
|
|
|
if (uri=~"sip:announcement+*@*") {
|
|
if(!t_write_req("/tmp/am_fifo","announcement")){
|
|
log("could not contact announcement\n");
|
|
t_reply("500","could not contact announcement");
|
|
};
|
|
break;
|
|
};
|
|
|
|
|
|
if (method=="INVITE"){
|
|
# redirect the call to the 'conference' plug-in
|
|
# if the URI begins with 100
|
|
if (uri=~"sip:100*@") {
|
|
|
|
# assumes that Sems configuration parameter 'socket_name='
|
|
# has been set to /tmp/am_fifo
|
|
if(!t_write_req("/tmp/am_fifo","conference")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# redirect the call to the 'announcement' plug-in
|
|
# if the URI begin with 200
|
|
if (uri=~"sip:200*@") {
|
|
|
|
if(!t_write_req("/tmp/am_fifo","announcement")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
# no service number, redirect to voicemail.
|
|
|
|
avp_db_load( "$ruri", "$email/$email_scheme");
|
|
avp_db_load( "$ruri", "$language/$language_scheme");
|
|
|
|
if(!t_write_req("/tmp/am_fifo","voicemail/voicemail_headers")) {
|
|
t_reply("500","error contacting sems");
|
|
};
|
|
break;
|
|
};
|
|
|
|
};
|
|
|
|
# forward to current uri now; use stateful forwarding; that
|
|
# works reliably even if we forward from TCP to UDP
|
|
if (!t_relay()) {
|
|
sl_reply_error();
|
|
};
|
|
}
|
|
-------------------------- ser.cfg end -------------------------------
|
|
|
|
-------------------------- sems.conf ---------------------------------
|
|
# $Id: Configure-Sems-Ser-HOWTO,v 1.6 2005/01/05 18:07:23 sayer Exp $
|
|
#
|
|
# sems.conf.sample
|
|
#
|
|
# Sip Express Media Server (sems)
|
|
#
|
|
# sample configuration file
|
|
#
|
|
#
|
|
# whitespaces (spaces and tabs) are ignored
|
|
# comments start with a "#" and may be used inline
|
|
#
|
|
# example: option=value1, value2 # i like this option
|
|
#
|
|
|
|
##################################
|
|
# global parameters #
|
|
##################################
|
|
|
|
# optional parameter: fork={yes|no}
|
|
#
|
|
# - specifies if sems should run in daemon mode (background)
|
|
# (fork=no is the same as -E)
|
|
fork=yes
|
|
|
|
# optional parameter: stderr={yes|no}
|
|
#
|
|
# - debug mode: do not fork and log to stderr
|
|
# (stderr=yes is the same as -E)
|
|
stderr=no
|
|
|
|
# optional parameter: loglevel={0|1|2|3}
|
|
#
|
|
# - sets log level (error=0, warning=1, info=2, debug=3)
|
|
# (same as -D)
|
|
loglevel=1
|
|
|
|
# optional parameter: fifo_name=<filename>
|
|
#
|
|
# - path and file name of our fifo file (same as -i)
|
|
fifo_name=/tmp/am_fifo
|
|
|
|
# optional parameter: ser_fifo_name=<filename>
|
|
#
|
|
# - path and file name of Ser's fifo file (same as -o)
|
|
ser_fifo_name=/tmp/ser_fifo
|
|
|
|
# optional parameter: socket_name=<filename>
|
|
#
|
|
# - path and file name of our unix socket
|
|
#socket_name=/tmp/am_sock
|
|
|
|
# optional parameter: ser_socket_name=<filename>
|
|
#
|
|
# - path and file name of Ser's unix socket
|
|
#ser_socket_name=/tmp/ser_sock
|
|
|
|
# optional parameter: send_method=<filename>
|
|
#
|
|
# - sets which method will be used to contact Ser:
|
|
# FIFO or unix socket server.
|
|
# - values: fifo (default), unix_socket
|
|
#
|
|
# - PLEASE NOTE THAT: if you use 'fifo', make sure that
|
|
# fifo_name and ser_fifo_name have been set. if you use 'unix_socket',
|
|
# make sure that socket_name and ser_socket_name have been set.
|
|
#
|
|
send_method=fifo
|
|
|
|
# optional parameter: plugin_path=<path>
|
|
#
|
|
# - sets the path to the plug-ins
|
|
# - may be absolute or relative to CWD
|
|
plugin_path=/usr/local/lib/sems/plug-in/
|
|
|
|
# return a Contact header <app_name>+user@domain in outgoing requests.
|
|
user_prefix_separator=+
|
|
|
|
# optional parameter: smtp_server=<hostname>
|
|
#
|
|
# - sets address of smtp server
|
|
smtp_server=localhost
|
|
|
|
# optional parameter: smtp_port=<port>
|
|
#
|
|
# - sets port of smtp server
|
|
smtp_port=25
|
|
|
|
# optional parameter: rtp_low_port=<port>
|
|
#
|
|
# - sets port of rtp lowest server
|
|
#rtp_low_port=1024
|
|
|
|
# optional parameter: rtp_high_port=<port>
|
|
#
|
|
# - sets port of rtp highest server
|
|
#rtp_high_port=65535
|
|
|
|
##################################
|
|
# module specific parameters #
|
|
##################################
|
|
|
|
# sample voicemail configuration (inline)
|
|
config.voicemail=inline
|
|
|
|
# optional parameter: rec_file_extension=<ext>
|
|
#
|
|
# - sets the file extension which will be used
|
|
# to record messages.
|
|
# - example 1: wav
|
|
# - example 2: mp3
|
|
#
|
|
# WARNING: you must compile the mp3 plug-in
|
|
# in order to use 'mp3' as default
|
|
# extension. You will need the lame
|
|
# encoder for that.
|
|
# See plug-in/mp3/ReadmeMP3.txt for
|
|
# more information.
|
|
#
|
|
rec_file_extension=wav
|
|
|
|
# optional parameter: announce_path=<path>
|
|
#
|
|
# - sets the path where announce files are searched for
|
|
# - the file to be played is searched in the following order:
|
|
# <announce_path>/<domainname>/<username>.wav
|
|
# <announce_path>/<domainname>/<language>/<default_announce>
|
|
# <announce_path>/<domainname>/<default_announce>
|
|
# <announce_path>/<language>/<default_announce>
|
|
# <announce_path>/<default_announce>
|
|
# where <language> is taken from the body of P-Language header
|
|
# of the request (if any).
|
|
announce_path=/usr/local/lib/sems/audio/
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the name of the default announce WAV file
|
|
default_announce=default_en.wav
|
|
|
|
# parameter: max_record_time=<seconds>
|
|
#
|
|
# - maximum record time
|
|
max_record_time=30
|
|
|
|
# parameter: accept_delay=<x>
|
|
#
|
|
# - delays accepting of the call for x seconds
|
|
# - default value is 0
|
|
accept_delay=0
|
|
|
|
# parameter: email_template_path=<filename>
|
|
#
|
|
# - email templates path
|
|
#
|
|
# See the README file in <sems-src>/plug-in/voicemail
|
|
# for more information on the syntax used.
|
|
# - template to be used is selected in the following order:
|
|
# <email_template_path><domain>_<language>.template
|
|
# <email_template_path><domain>.template
|
|
# <email_template_path>default_<language>.template
|
|
# <email_template_path>default.template
|
|
# where <language> is taken from the body of P-Language header
|
|
# of the request (if any).
|
|
#
|
|
email_template_path=/usr/local/etc/sems
|
|
|
|
# end of configuration section for voicemail module
|
|
config.voicemail=end
|
|
|
|
|
|
# sample announcement configuration (inline)
|
|
config.announcement=inline
|
|
|
|
# optional parameter: announce_path=<path>
|
|
#
|
|
# - sets the path where announce files are searched for
|
|
announce_path=/usr/local/lib/sems/audio/
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the name of the default announce WAV file
|
|
default_announce=default_en.wav
|
|
|
|
# end of configuration section for announcement module
|
|
config.announcement=end
|
|
|
|
|
|
# sample isdngw module configuration (external file)
|
|
# config.isdngw=/etc/isdngw.conf
|
|
|
|
# sample ivr module configuration (inline)
|
|
config.ivr=inline
|
|
#
|
|
#
|
|
# The IVR checks for a script with the named of the callee
|
|
# (<local part in r-uri>.py for python, <local part in r-uri>.pl for perl)
|
|
# in the directory <ivr_script_path><domain>, then for
|
|
# <ivr_script_path><domain><ivr_script_file>. If this is not found,
|
|
# <ivr_script_path>/<local part in r-uri>.py if searched,
|
|
# and if this is not found, <ivr_script_path>/<ivr_script_file> is used.
|
|
#
|
|
# So with a call to sayer@iptel.org and
|
|
#ivr_script_path=/etc/ivr and
|
|
#ivr_script_file=ivr.py
|
|
# these files are checked:
|
|
#/etc/ivr/iptel.org/sayer.py
|
|
#/etc/ivr/iptel.org/ivr.py
|
|
#/etc/ivr/sayer.py
|
|
#/etc/ivr/ivr.py
|
|
#
|
|
#parameter: ivr_script_path:
|
|
# path to ivr scripts.
|
|
#
|
|
ivr_script_path=/etc/ivr/
|
|
# default script file: this will be executed if <user>.py does not exist.
|
|
#
|
|
ivr_script_file=ivr.py
|
|
|
|
# parameter : tts_caching
|
|
# y or n
|
|
# text will be read from waves already synthesized and
|
|
# cached in cache_path
|
|
tts_caching=y
|
|
|
|
# parameter : tts_cache_path
|
|
# path to cache waves
|
|
# path must exist!
|
|
tts_cache_path=/tmp/wavs
|
|
# end of configuration section for ivr module
|
|
config.ivr=end
|
|
|
|
# sample conference configuration (inline)
|
|
config.conference=inline
|
|
|
|
# parameter: default_announce=<filename>
|
|
#
|
|
# - sets the full pathed name of the default announce WAV file.
|
|
# Will be played to lonely users.
|
|
default_announce=/usr/local/lib/sems/audio/first_participant.wav
|
|
|
|
# end of configuration section for conference module
|
|
config.conference=end
|
|
|
|
# example configuration for number reader
|
|
config.number_reader=inline
|
|
|
|
number_path=/usr/local/lib/sems/audio/
|
|
|
|
prolog_file=welcome_to_number_reader.wav
|
|
|
|
epilog_file=thanks_calling_number_reader.wav
|
|
|
|
# end of number_reader configuration
|
|
config.number_reader=end
|
|
|
|
-------------------------- sems.conf end -----------------------------
|