Programing in SIP servers enables the IP telephony provider to add complex control that is difficult to realise with simple dialplan XML and IVR menus. These are best handled by using a program that is compiled with the telecom application server and invoked by SIP requests or responses in the session. This may include
using policy control or dynamic input to control call routing or blacklisting
transcription for voicemail
media file playback with dynamic text to speech ….so on.
Common Freeswitch , opensips , Kamailio and Astersik suppored programing engines may include python, java, c++, javascript. Opensips and kamailio also include XML_RPC, HTTP API and Websockets as additional means of adding call control login in telephony sever.
Kamailo modules
Opensips modulesFreeswitch modules
Lua (https://www.lua.org) is a small, powerful and lightweight scripting language, mostly used for embedded and gaming use cases. Among many programming engines supported by FreeSWITCH and Kamailio, Lua is very handy to add business logic to call control by integrating with the telecom server.
Form the a multiple choice, Lua is the prefered language for scripting in SIP server which is due to
Does not requie recompilation
Saves on the effort to resatrt the freeswitch server while loading updated script
this in turn saves service disruption for the time server woulve taken to shutdown and restart
Can ve sync or asyn
lua : runs in current thread and waits for script completion
luarun : runs in seprate thread and returns immediately
Freeswitch Lua Integration
To load the program
<action aplication="lua" data="mainprog.lua">
1. In the program, we could get status and print to console log
local api = freeswitch.API()
local status = api:execute("status")
freeswitch.consoleLog(status)
2. we could also check is session is active and play a file inot the call
if session:ready() then
session:streamFile("silence_stream://100000")
end
3.Program to answer call , play file and hangup using session class methods
-- Answer call, play a prompt, hang up
session:answer()
-- Create a string with path and filename of a sound file
pathsep = '/'
-- Windows users do this instead pathsep = ''
prompt ="ivr" ..pathsep .."ivr-welcome_to_freeswitch.wav"
-- Play the prompt
freeswitch.consoleLog("WARNING","About to play '" .. prompt .."'n")
session:streamFile(prompt)
-- Hangup
session:hangup()
freeswitch.consoleLog("WARNING","After hangup")
output
[INFO] mod_dialplan_xml.c:637 Processing altanai <altanai>->5000 in context public
EXECUTE sofia/internal/altanai@x.x.x.x lua(/etc/freeswitch/dialplan/lua_session_answer_prompt_hangup.lua)
...
[DEBUG] switch_channel.c:3781 (sofia/internal/altanai@x.x.x.x) Callstate Change EARLY -> ACTIVE
[WARNING] switch_cpp.cpp:1376 About to play 'ivr/ivr-welcome_to_freeswitch.wav
...
[DEBUG] switch_ivr_play_say.c:1942 done playing file /usr/share/freeswitch/sounds/en/us/callie/ivr/ivr-welcome_to_freeswitch.wav
...
[DEBUG] switch_cpp.cpp:731 CoreSession::hangup
[NOTICE] switch_cpp.cpp:733 Hangup sofia/internal/altanai@x.x.x.x [CS_EXECUTE] [NORMAL_CLEARING]
[WARNING] switch_cpp.cpp:1376 After hangup
other methods :
Initiate new session session:originate()
Record Audio session:recordFile()
5. Fire and consume Events
freeswitch.Event() and freeswitch.eventConsume() can be used to fire new events and consume events respectively. For instance to fire callback function on hangup session:setHangupHook()
A PBX acts as the central switching system for phone calls within a business.
Cloud Hosted IP PBX Systems
On-premise IP PBX
An IP PBX is a PBX system with IP connectivity and may provide additional audio, video, or instant messaging communication utilizing the TCP/IP protocol stack.
Essentially an IP PBX is a telecommunication device( on IP Interface) that provides voice connectivity to IP phones within an organization/internal office network.
Enterprise applications, media servers, presence servers, and the VoIP/SIP PBX are interconnected through a company intranet.SIP clients can be SIP hard-phones or soft-phones on PCs, PDAs etc. A PSTN gateway links the enterprise SIP PBX to the public PSTN.
A soft switch (SIP PBX) can be a combination of several SIP entities, such as SIP registrar, proxy server, redirect server, forking server, Back-To-Back User Agent (B2BUA) etc.
FreeSWITCH is free and open source communications software licensed under Mozilla Public License. It if often the core of voice core to provider call routing and media control . Its core library, libfreeswitch, is capable of being embedded into other projects, as well as being used as a stand-alone application. Read more about FreeSwitch SIP and Media Server.
Just a network-switch is hardware that controls network traffic by receiving and forwarding data to the destination device, a soft-switch is a software that controls traffic and call routing in a voIP communication network.
Class 4 switch
Class 5 switch
Class 4 switches route calls between communication providers such as – between telco and enterprise PBX
Class 5 switches connect communication provider with real clients (or end users) caller and callee. – can provide platform + user agent such as diallers
-nf -- no forking
-reincarnate -- restart the switch on an uncontrolled exit
-reincarnate-reexec -- run execv on a restart (helpful for upgrades)
-u [user] -- specify user to switch to
-g [group] -- specify group to switch to
-core -- dump cores
-help -- this message
-version -- print the version and exit
-rp -- enable high(realtime) priority settings
-lp -- enable low priority settings
-np -- enable normal priority settings
-vg -- run under valgrind
-nosql -- disable internal sql scoreboard
-heavy-timer -- Heavy Timer, possibly more accurate but at a cost
-nonat -- disable auto nat detection
-nonatmap -- disable auto nat port mapping
-nocal -- disable clock calibration
-nort -- disable clock clock_realtime
-stop -- stop freeswitch
-nc -- do not output to a console and background
-ncwait -- do not output to a console and background but wait until the system is ready before exiting (implies -nc)
-c -- output to a console and stay in the foreground
Options to control locations of files:
-base [basedir] -- alternate prefix directory
-cfgname [filename] -- alternate filename for FreeSWITCH main configuration file
-conf [confdir] -- alternate directory for FreeSWITCH configuration files
-log [logdir] -- alternate directory for logfiles
-run [rundir] -- alternate directory for runtime files
-db [dbdir] -- alternate directory for the internal database
-mod [moddir] -- alternate directory for modules
-htdocs [htdocsdir] -- alternate directory for htdocs
-scripts [scriptsdir] -- alternate directory for scripts
-temp [directory] -- alternate directory for temporary files
-grammar [directory] -- alternate directory for grammar files
-certs [directory] -- alternate directory for certificates
-recordings [directory] -- alternate directory for recordings
-storage [directory] -- alternate directory for voicemail storage
-cache [directory] -- alternate directory for cache files
-sounds [directory] -- alternate directory for sound files
checks with ACL for permission and set NAT. Isolate SDP for processing.
New Channel sofia/internal/from_number@sometelco.com:5060 [a8a2003f-5755-40fe-ab63-aab2f5264886]
Running State Change CS_NEW (Cur 1 Tot 274)
receiving invite from caller_ip:35365 version: 1.9.0 -742-8f1b7e0 64bit
IP caller_ip Approved by acl "domains[]". Access Granted.
Setting NAT mode based on nat.auto
Channel sofia/internal/from_number@sometelco.com:5060 entering state [received][100]
Remote SDP:
v=0
o=- 1553248503383592 1 IN IP4 192.168.1.23
s=X-Lite release 5.4.0 stamp 94385
c=IN IP4 192.168.1.23
t=0 0
m=audio 49874 RTP/AVP 8 101
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15
mainatin and Updates call-state (switch_core_state_machine ) CS_NEW -> CS_INIT -> CS_ROUTING -> RINGING and send 100 trying to caller
State Change CS_NEW -> CS_INIT
State NEW
Running State Change CS_INIT (Cur 1 Tot 274)
State INIT
SOFIA INIT
Standard INIT
State Change CS_INIT -> CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 1 Tot 274)
Change DOWN -> RINGING
State ROUTING
send 413 bytes to tcp/[caller_ip]:35365 at 09:55:07.937474:
------------------------------------------------------------------------
SIP/2.0 100 Trying
Via: SIP/2.0/TCP 192.168.1.23:55934;branch=z9hG4bK-524287-1---cc11593581af6519;rport=35365;received=caller_ip
From: "from_number"<sip:from_number@sometelco.com:5060>;tag=47a61272
To: <sip:to_number@sometelco.com:5060>
Call-ID: 94385YTY3ODNlNzE1YjE5MmY4NmQ3ZWUyZDAzM2E0YzBkM2I
CSeq: 1 INVITE
User-Agent: FreeSWITCH-mod_sofia/1.9.0-742-8f1b7e0~64bit
Content-Length: 0
------------------------------------------------------------------------
Checks dialplan to route incoming call. In this case action is to bridge the incoming call to internal user
mod_sofia.c:154 sofia/internal/from_number@sometelco.com:5060 SOFIA ROUTING
switch_core_state_machine.c:236 sofia/internal/from_number@sometelco.com:5060 Standard ROUTING
mod_dialplan_xml.c:637 Processing from_number <from_number>->to_number in context public
Dialplan: sofia/internal/from_number@sometelco.com:5060 parsing [public->dialplan_cutsom] continue=false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Regex (PASS) [dialplan_cutsom] destination_number(to_number) =~ /^(\d+)$/ break=on-false
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action log(INFO ***** Forwarding calls to gateway ****** )
Dialplan: sofia/internal/from_number@sometelco.com:5060 Action bridge({sip_auth_username=user,sip_auth_password=pass,sip_route_uri=sip:to_number@ip_addr;transport=tls,sip_invite_req_uri=sip:to_number@sometelco.com;transport=tls}sofia/external/to_number@ip_addr)
update call state CS_ROUTING -> CS_EXECUTE
State Change CS_ROUTING -> CS_EXECUTE
State ROUTING going to sleep
Running State Change CS_EXECUTE (Cur 1 Tot 274)
State EXECUTE
SOFIA EXECUTE
set the crypto and codecs for the new call
switch_ivr_originate.c:2159 Parsing global variables
switch_channel.c:1104 New Channel sofia/external/to_number@ip_addr [cc1ae238-9efd-4f51-93e9-05abd48bea4d]
mod_sofia.c:5026 (sofia/external/to_number@ip_addr) State Change CS_NEW -> CS_INIT
switch_core_state_machine.c:584 (sofia/external/to_number@ip_addr) Running State Change CS_INIT (Cur 2 Tot 275)
switch_core_state_machine.c:627 (sofia/external/to_number@ip_addr) State INIT
mod_sofia.c:93 sofia/external/to_number@ip_addr SOFIA INIT
Set Local audio crypto Key [1 AEAD_AES_256_GCM_8 inline:ZbEHd76sP6FZSO9AYcqryybaA4HY3O5p2Uo+e1gmmfVaZCEic6cvKyArhMU]
Set Local video crypto Key [1 AEAD_AES_256_GCM_8 inline:Ehr3LoDR8Ur+wtNAMqoqIDn3S7V2inE2/n++awxS6/1P2ijcqfk12+LM/Pc]
Set Local text crypto Key [1 AEAD_AES_256_GCM_8 inline:NVSfjOmSS5BaP/5yqg+SOXcqvEFTHHrC8R5AYkkClXLuNOXYoaUYlrIWeW0]
Set Local audio crypto Key [2 AEAD_AES_128_GCM_8 inline:ePH/F2Qw5+zi8c7tkBb6Y2AQE5uevp+jWUkjgQ]
Set Local video crypto Key [2 AEAD_AES_128_GCM_8 inline:YWdfNLSx6MqG9WQ3TmsV/cSBDqjRUAbHE0rRCg]
Set Local text crypto Key [2 AEAD_AES_128_GCM_8 inline:DFXOP2V2Ep6FoHNz5HIMrm0cu6Za8I5wOI/hUw]
Set Local audio crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:SG5rYx3GSR2imutYQ+LzqHufG9UkG3n/SfmFHFOG/r75v2pwf2lG7Qpup+J0mw]
Set Local video crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:LkU3i9MD25k2wtTfSXUvhlxo66GtMWnXkKoxSdgRZyANoeOhufYnXzbXDo+7+w]
Set Local text crypto Key [3 AES_CM_256_HMAC_SHA1_80 inline:AUgUOVmFunzotvwZ6KuMDnBRR2XKk1DsX2qg465MsT6OAxHc2qKBFpeQEpxrqA]
Set Local audio crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:2PVBBJEp4QcTzTf4Th8Ag/7KiVPmrYb/FCowiRb6yAuTO/kxQLc]
Set Local video crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:OiFbZQ6mWuf5sHJT1pFPU6EWxEvQAO/0rcp8uGMf79k7RSR3IQA]
Set Local text crypto Key [4 AES_CM_192_HMAC_SHA1_80 inline:XyednWJmzRfsWQOgdhKaMeOeE/OLmnwo6hVEZWl4OJdKdgK6TVc]
Set Local audio crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:Yd4L5Qi7A/8xay5ZHWR1jKk9j5Kvy9s2Zo3NOES2]
Set Local video crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:ImgbbD6cnhnH19O1knP5SSIUULsZTaNJJIUepxt0]
Set Local text crypto Key [5 AES_CM_128_HMAC_SHA1_80 inline:V7+IbSZmTdQNjh/upUZ5TFDSlgarhDTVfV+AcUA+]
Set Local audio crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:JI+s9uFdZ3JfZmRRfwHr0OrpyZdtUXmMC0WRIZow1EuXRB9xKFRBk6KmSWomqQ]
Set Local video crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:MX6CGCrMEioUCJsIOCxRqlHOx4mUYRw4DslpY25njZQAkH6MgG/9hp7G8xr44A]
Set Local text crypto Key [6 AES_CM_256_HMAC_SHA1_32 inline:ikCz2sYLGoMO+dlrZj+znlQ3djAkGSYzSLLu6Az8u2THWPgnkFJXVgXSxHOaHw]
Set Local audio crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:5JzlrMywFZhHuNLWPG/HBrUi/Zcg414Q7ZfSaJQnUF5N9APy+GQ]
Set Local video crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:K0dZtwH1Q7AuSMBPPUesy047c4nAF+QuFsVvGdf3fYJDOD0Uwxo]
Set Local text crypto Key [7 AES_CM_192_HMAC_SHA1_32 inline:96SwyWAdV1a+BU3UbiX1PHdkRlSS4RtmwPWNPbCR3NDm1MyBh58]
Set Local audio crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:/RLYPhZs07WCCBRY8tWNTJemT/IFq1VPHGHmGvnG]
Set Local video crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:mQlgScFq1iMKEW8vobzwhmN9TWSmVblAv9u7c1/c]
Set Local text crypto Key [8 AES_CM_128_HMAC_SHA1_32 inline:WAQveMfrQkPBcfqH2qLmuzY63VLfT+N30/YLyuqE]
Set Local audio crypto Key [9 AES_CM_128_NULL_AUTH inline:f2fx2ekxPG3GTwTYARtquNJ87qO0Q5ei47KYlo9K]
Set Local video crypto Key [9 AES_CM_128_NULL_AUTH inline:qpAkfc1bWnZ0Y/1ql+dNvhIGgxxWZoVltnRD5kqn]
Set Local text crypto Key [9 AES_CM_128_NULL_AUTH inline:LyhSlzI3X38WKPwZ83035Ddvse4J/2KnKoydo2FD]
set proxy route and create SDP for sending invite to bridged client
manage and update call state for this call leg too CS_INIT -> CS_ROUTING -> CS_CONSUME_MEDIA
Standard INIT
State Change CS_INIT -> CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 2 Tot 275)
Channel sofia/external/to_number@ip_addr entering state [calling][0]
State ROUTING
SOFIA ROUTING
State Change CS_ROUTING -> CS_CONSUME_MEDIA
State ROUTING going to sleep
Running State Change CS_CONSUME_MEDIA (Cur 2 Tot 275)
State CONSUME_MEDIA
State CONSUME_MEDIA going to sleep
recv 365 bytes from tls/[ip_addr]:5061 at 09:55:07.940977:
------------------------------------------------------------------------
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/TLS via_addr:5080;rport=59774;branch=z9hG4bK21Qm9U3eHX0Nc;received=via_addr
From: "from_number" <sip:from_number@via_addr>;tag=8jByBXa2pF1Fj
To: <sip:to_number@ip_addr>
Call-ID: 6a827514-c72b-1237-8aab-02a933b32da0
CSeq: 2070461 INVITE
Server: XYZ
Content-Length: 0
------------------------------------------------------------------------
set audio codecs, update call state CS_CONSUME_MEDIA -> CS_EXCHANGE_MEDIA
entering state [ready][200]
looking for crypto suite [AEAD_AES_256_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AEAD_AES_128_GCM_8] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
looking for crypto suite [AES_CM_256_HMAC_SHA1_80] in [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Found suite AES_CM_256_HMAC_SHA1_80
Set Remote Key [3 AES_CM_256_HMAC_SHA1_80 inline:/itE1k5BLMoTNzo7YEv6hCyM6R6wyHem3Coc5jjYVlKR2L3tEzBG5zx1QHgVSg==]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/external/to_number@ip_addr PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/external/to_number@ip_addr Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/external/to_number@ip_addr Set 2833 dtmf send payload to 101 recv payload to 101
AUDIO RTP [sofia/external/to_number@ip_addr] 10.130.74.15 port 20072 -> <FS_IPADDR> port 33516 codec: 8 ms: 20
Starting timer [soft] 160 bytes per 20ms
Set 2833 dtmf send payload to 101
Set 2833 dtmf receive payload to 101
Set rtp dtmf delay to 40
Activating audio Secure RTP SEND
srtp:sdes:AES_CM_256_HMAC_SHA1_80
Activating audio Secure RTP RECV
srtp:sdes:AES_CM_256_HMAC_SHA1_80
has been answered
Callstate Change DOWN -> ACTIVE
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMU:0:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1]/[PCMA:8:8000:20:64000:1]
Audio Codec Compare [PCMA:8:8000:20:64000:1] ++++ is saved as a match
Set telephone-event payload to 101@8000
Set Codec sofia/internal/from_number@sometelco.com:5060 PCMA/8000 20 ms 160 samples 64000 bits 1 channels
sofia/internal/from_number@sometelco.com:5060 Original read codec set to PCMA:8
Set telephone-event payload to 101@8000
sofia/internal/from_number@sometelco.com:5060 Set 2833 dtmf send payload to 101 recv payload to 101
Goto folder /usr/local/freeswitch/conf/directory/ and vim default.xml
<include>
<!--the domain or ip (the right hand side of the @ in the addr-->
<domain name="$${domain}">
...
<users>
<user id="altanai">
<params>
<param name="password" value="$${default_password}"/>
<param name="vm-password" value="1000"/>
</params>
<variables>
<variable name="toll_allow" value="domestic,international,local"/>
<variable name="accountcode" value="987"/>
<variable name="user_context" value="video-mcu-stereo"/>
<variable name="effective_caller_id_name" value="altanai"/>
<variable name="outbound_caller_id_name" value="altanai_outbound"/>
</variables>
</user>
</users>
..
</domain>
</include>
2. Blind Registeration
Allow users to register with any username and password
Goto /usr/local/freeswitch/conf/sip_profiles/internal.xml and uncomment below snippet
<!-- this lets anything register -->
<!-- comment the next line and uncomment one or both of the other 2 lines for call authentication -->
<param name="accept-blind-reg" value="true"/>
<!-- accept any authentication without actually checking (not a good feature for most people) -->
<param name="accept-blind-auth" value="true"/>
3. Set a profile
Goto folder for freeswitch conf such as /usr/local/freeswitch/conf/directory/default
First we check the external profile via sofia status . We should’ve configured the internal ip to listen to domain address or public ip. The external profile on port 5080 is used for outgoing and incoming connections .
Create a user profile for interacting with outside world
note $1 contains the dialled number which will be passed to bridge to telcoCompany gateway. Therefore to add prefix for USA use +1$1 or for India +91$1 ( E.164 format) or some inline variable such as ${customercode}$1
After adding reloadxml and also run sofia profile external rescan to let freeswitch find the gateways
Monitoring gateways using OPTIONS
<param name="ping" value="20"/>
Codec Negotiation
Late negotiations reduces re-sampling and codec changes
Other dial plan variables can also be set such as absolute_codec_string, inherit_codec , ep_codec_string. To avoid any codec negotiation on SDP use bypass_media=true .
can be used with modules mod_xml_cdr , mod_csv_cdr , mod_cdr_mongodb, mod_odbc_cdr , mod_cdr_pg_csv , mod_cdr_sqlite , mod_json_cdr , mod_radius_cdr
<configuration name="cdr_csv.conf" description="CDR CSV Format">
<settings>
<!-- 'cdr-csv' will always be appended to log-base -->
<!--<param name="log-base" value="/var/log"/>-->
<param name="default-template" value="example"/>
<!-- This is like the info app but after the call is hung up -->
<!--<param name="debug" value="true"/>-->
<param name="rotate-on-hup" value="true"/>
<!-- may be a b or ab -->
<param name="legs" value="a"/>
<!-- Only log in Master.csv -->
<!-- <param name="master-file-only" value="true"/> -->
</settings>
<templates>
<template name="sql">INSERT INTO cdr VALUES ("${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}");</template>
...
</templates>
</configuration>
This section describes some of the popular and useful freeswitch module. Although there are many more modules, I have picked a few of commonly used one and divided them into categories
Event Driven Archietctural (EDA) systems Design forms the basis for horizontly scalable, distributed and modular design. Such system primarily use event consumers, processing, producers and an effificient messaging system.
The core engine of freeswitch too manages and coordinates events with the help of messaging bus and handlers between itself and modules.
log call detail records (CDRs) to a text file using text generation templates as in /conf/autoload_configs/cdr_csv.conf.xml
<configuration name="cdr_csv.conf" description="CDR CSV Format">
<settings>
<param name="default-template" value="example"/>
<param name="rotate-on-hup" value="true"/>
<!-- may be a b or ab -->
<param name="legs" value="a"/>
</settings>
<templates>
<template name="sql">INSERT INTO cdr VALUES ("${caller_id_name}","${caller_id_number}","${destination_number}","${context}","${start_stamp}","${answer_stamp}","${end_stamp}","${duration}","${billsec}","${hangup_cause}","${uuid}","${bleg_uuid}", "${accountcode}");</template>
</templates>
</configuration>
When any of the endpoints are loaded , they start listening for connection using configuration file . Dialstring identifies the recipient of the channel such as sofia/external/098099999 where sofia is the dial string prefix for SIP.
mod_portaudio
mod_alsa
mod_sofia – SIP protocol support
mod_gsmopen – Supports voice & SMS over a GSM network
mod_h323 – H.323 , ITU rich media communication protocol.
mod_freetdm – Provides support for telephony cards from manufacturers such as Digium, Sangoma and Zaptel. Can communicate in most legacy telephony protocols such as ISDN, SS7 & analog
mod_unicall
mod_skinny
mod_khomp
mod_rtmp
RTMP protocol is primarily used by Flash for streaming audio, video, and data over the Internet.
echo– Echo audio and video back to the originator.
delay_echo – Echo audio at a specified delay.
<action application="delay_echo" data="1000"/>
enable_heartbeat
Enable Media Heartbeat.
endless_playback
Continuously play file to caller.
enum – Perform E.164 lookup.
erlang – Handle a call using Erlang.
eval – Evaluates a string.
event – Fire an event.
execute_extension
Execute an extension from within another extension and return.
export
Export a channel variable across a bridge <varname>=<value>
fax_detect – Detect FAX CNG – may be deprecated. fifo – Send caller to a FIFO queue. fifo_track_call – Count a call as a FIFO call in the manual_calls queue.
gentones – Generate TGML tones. group – Insert or delete members in a group.
ring_ready – Indicate Ring_Ready on a channel. sleep – Pause a channel. set_zombie_exec – Sets the zombie execution flag on the current channel. session_loglevel – Override the system’s loglevel for this channel.
set_audio_level – Adjust the read or write audio levels for a channel. verbose_events – Make ALL Events verbose (Make all variables appear in every single event for this channel). transfer – Immediately transfer the calling channel to a new extension.[old wiki] soft_hold – Put a bridged channel on hold.
hold – Send a hold message.
stop_displace_session – Stop displacement audio on a channel. multiset – Set multiple channel variables with a single action. log – Logs a channel variable for the channel calling the application loop_playback – Playback a file to the channel looply for limted times
limit – Set a limit on number of calls to/from a resource limit_execute – Set the limit on a specific application limit_hash – Set a limit on number of calls to/from a resource limit_hash_execute – Set the limit on a specific application
media_reset – Reset all bypass/proxy media flags.
mkdir – Create a directory. mutex – Block on a call flow, allowing only one at a time page – Play an audio file as a page. park – Park a call. park_state – Park State. pickup – Pickup a call.
record – Record a file from the channel’s input. record_fsv – Record a FSV file. FSV – (FS Video File Format) record_session – Record Session.
recovery_refresh – Send a recovery refresh. redirect – Send a redirect message to a session. regex – Perform a regex. remove_bugs – Remove media bugs. rename – Rename file. respond – Send a respond message to a session.
system – Execute an operating system command. three_way – Three way call with a UUID. tone_detect – Detect the presence of a tone and execute a command if found. translate – Number translation. unbind_meta_app – Unbind a key from an application. unset – Unset a variable. unhold – Send a un-hold message.
mod_sndfile mod_native_file mod_png mod_shell_stream For icecast/mp3 streams/files mod_shout For local streams (play all the files in a directory) mod_local_stream mod_tone_stream
FreeSWITCH is free and open source communications software licensed under Mozilla Public License. It if often the core of voice core to provider call routing and media control . Its core library, libfreeswitch, is capable of being embedded into other projects, as well as being used as a stand-alone application.
FreeSWITCH can route and interconnect communication protocols using audio, video, text, or any other form of media. First released in January 2006, FreeSWITCH has grown to become the world’s premier open-source soft-switch platform. This versatile platform is used to power voice, video, and chat communications on devices ranging from single calls on a Raspberry Pi to large server clusters handling millions of calls. FreeSWITCH powers several commercial products from start-ups to Carriers.
It can perform the functions of ( but not limited to )
PBX Server (Transcoding B2BUA)
IVR & Announcement Server
Conference host
Voicemail
Session Border Controller
Text to Speech (TTS)
VOIP endpoint
Class 5 softswitch
Freeswitch has a modular architecture that is both scalable and customisable. The most important modules are- Endpoint, dialplan and Application.
Application is the instruction added for a particular dial plan with an extension object. Data Arguments are also passed to an application. Examples like Set: configure extension parameter, Bridge: bridge a new channel to the existing one, Answer: answer the call for a channel, Hangup: hangup a current channel, Run an IVR menu etc
Protocols set up call legs/ channels, negotiate codecs and stream media. The endpoint module helps to bridge channels between different protocol supported endpoints like WebRTC , H323, SIP , Jingle etc. SIP being the most popular protocol for the VoIP session is implemented by mod_sofia module while RTP is inbuild into FreeSWITCH core. SRTP ( media protocol for webrtc ) is provided by mod_verto.
Freeswitch can form the basis of complicated and sophisticated communications backend framework with thousand CPS(Call per second ). It can connect to VOIP ( voice over IP ) as well as PSTN ( Public Switched Telephone network ) and PRI ( Primary Rate Interfaces – used in enterprises communication).
Core
Data strutters are opaque and operations can be invoke by APIs with routines getting maximum reuse .
Threaded Model
Enables parallel operation as every connection has its own thread. Event handlers push incoming events into threads . Sub system run in background threads .
Protocol module listens for call message and parses the call details inot an internal data structure for session management by the core’s state machine.
State Change CS_NEW -> CS_INIT
State NEW
Running State Change CS_INIT (Cur 1 Tot 274)
State INIT
SOFIA INIT
Standard INIT
The state is then changes to ROUTING. At this state the Dialplan’s is lookedup to see the operations that were defiendfor this call based on regex matching.
State Change CS_INIT -> CS_ROUTING
State INIT going to sleep
Running State Change CS_ROUTING (Cur 1 Tot 274)
Change DOWN -> RINGING
State ROUTING
Once the call flow logic is found and escuted form the dialplan the state is changes to EXECUTE.
State Change CS_ROUTING -> CS_EXECUTE
State ROUTING going to sleep
Running State Change CS_EXECUTE (Cur 1 Tot 274)
State EXECUTE
SOFIA EXECUTE
State change to Active and Exchnage_media
entering state [completed][200]
Channel [sofia/internal/from_number@sometelco.com:5060] has been answered
Callstate Change EARLY -> ACTIVE
Originate Resulted in Success: [sofia/external/to_number@ip_addr]
State Change CS_CONSUME_MEDIA -> CS_EXCHANGE_MEDIA
Running State Change CS_EXCHANGE_MEDIA (Cur 2 Tot 275)
State EXCHANGE_MEDIA
SOFIA EXCHANGE_MEDIA
Channel variables are used to manipulate dialplan execution, to control call progress, and to provide options to applications. They play a pervasive role, as FreeSWITCH™ frequently consults channel variables as a way to customize processing prior to a channel’s creation, during call progress, and after the channel hangs up.
$${variable} is expanded once when FreeSWITCH™ first parses the configuration on startup or after invoking reloadxml. It is suitable for variables that do not change, such as the domain of a single-tenant FreeSWITCH™ server.
<param name=”domain” value=”$${domain}”/>
${variable} is expanded during each pass through the dialplan, so it is used for variables that are expected to change, such as the ${destination_number} or ${sip_to_user} fields.
A Dialplan is designed to lookup list of instructions from the central XML registry within FreeSWITCH. In general dialplans are used to route a dialed call to an endpoint based on the extension and its condition. When a matching extension is found, it executes its actions . The combination of the above can create detailed control and call flow plans. FS uses Perl-compatible regular expressions (PCRE) for pattern matching. Few formats
sofia/profile2/8765@1.2.3.4 , will dial out 8765 at host 1.2.3.4 using profile2
sofia/gateway/gateway11.com/5432 , will dial through a Gateway (SIP Provider) to user 5432
sofia/profile2/8765@1.2.3.4;transport=tcp , dialing with specific transport like TCP, UDP, TLS, or SCTP.
{absolute_codec_string=PCMU}sofia/external/sip:9106@${local_ip_v4}:5080 , to specify the codecs
Speak Time and Date on Call
when dialed number matches regular expression 9172 , then call is answered , put to sleep for 1 seconds and using say application current date and time is said , then application hangs up .
When call arrives for destination 501 , the condition matches and this blocks action are executed such as in example below .
Exetnsion 501 rings , when not answered it sleeps or 1 seconds , then gets forwarded to voice mail .
If the call to 501 was answered ie handed off then further actions would not be executed
inline= true states that channel variables will be used for later reference while break=never and continue=true tell the program to keep looking for more condition matches incase of failed or successful match respectively
Match incoming network IP address with pre configured IP
Store incoming number to $1 variable and bridge the call with custom profile . Read more about sip profiles in sections below .
Routing by listening on the audio stream for a touch-tone * followed by a single digit.
If the called user dials *1, then the execute_extension::dx XML features command is executed.
<extension name="Local_Extension">
<condition field="destination_number" expression="^(10[01][0-9])$">
<action application="export" data="dialed_extension=$1"/>
<!-- bind_meta_app can have these args <key> [a|b|ab] [a|b|o|s] <app> -->
<action application="bind_meta_app" data="1 b s execute_extension::dx XML features"/>
<action application="bind_meta_app" data="2 b s record_session::${recordings_dir}/${caller_id_number}.${strftime(%Y-%m-%d-%H-%M-%S)}.wav"/>
<action application="bind_meta_app" data="3 b s execute_extension::cf XML features"/>
<action application="bind_meta_app" data="4 b s execute_extension::att_xfer XML features"/>
..
</condition>
</extension>
The dx extension in features accepts the digits and proceeds as defined with the call
Connect to the called party. On answer announce the name. since playback_terminators is set to digits , pressing any one of them will terminate the call
block certain NPAs that you do not want to terminate based on caller id area codes and respond with SIP:503 to your origination so that they can route advance if they have other carrier to terminate to.
DID – Direct Inward Dialling via dialplan Public.xml
Assume we have a DID number 676767 which is served by telco provider either over SIP trunk/PRI lines . When someone from external world calls this number , FE needs to route the call to an internal user for example user at extension 3003 ( in default .xml context)
If we are on multi domain setup , we need to setup the domain correctly .$${domain} is the default domain set from vars.xml but you can set it to any domain we have setup in user directory. Added the extra characters in from of DID number to adjust for various ISD code and number formats suffixes such as +1- ,91- , 0- etc .
IVR ( Interactive Voice Respondent ) using Menu
Main Menu – uses tts enginer and 3 attempsts to repond with timeout 10 seconds
On pressing 1 – bridge the call to conference , on press 2 – transfer to 2222 using default
On press of 3 – transfer using enum while on press 4 – play submenu. On press of 9 – goto top menu
<menu name="demo_ivr"
greet-long="say:Press 1 to join the conference, Press 2 to transfer, 3 to transfer, 4 to goto another menu"
greet-short="phrase:demo_ivr_main_menu_short"
invalid-sound="ivr/ivr-that_was_an_invalid_entry.wav"
exit-sound="voicemail/vm-goodbye.wav"
confirm-macro=""
confirm-key=""
tts-engine="flite"
tts-voice="rms"
confirm-attempts="3"
timeout="10000"
inter-digit-timeout="2000"
max-failures="3"
max-timeouts="3"
digit-len="4">
<entry action="menu-exec-app" digits="1" param="bridge sofia/${domain}/888@conference.telcocompany.org"/>
<entry action="menu-exec-app" digits="2" param="transfer 2222 XML default"/>
<entry action="menu-exec-app" digits="3" param="transfer 1234*256 enum"/>
<entry action="menu-sub" digits="4" param="demo_ivr_submenu"/>
<entry action="menu-exec-app" digits="/^(10[01][0-9])$/" param="transfer $1 XML features"/>
<entry action="menu-top" digits="9"/>
</menu>
Submenu – press * to repeat menu , # to exit . the timeout is 15 seconds
If a users has lets say 3 phone – home , office and car then an incomming call should subesquently ring everywhere one by one till the user picks up the phone closet to him . leg_delay_start is the timer after which this endpoint will start riniging and leg_timeout is the duration till when this endpoint will ring.
Therfore as per below sample homephone will ring , after 5 sceonds office phone will ring and after 15 secons his cellphone 987654321 will ring . after 25 seconds call will end.
user busy – number of attempts is 3 and 480Hz 620Hz is the tone of frequency which is standard busy tone.
destination out of order – number of attempts 2 , 1776.7 Hz frequency . Note that as per condition only these frequencies are detected for action , others are ignored .
/usr/src/freeswitch-debs/freeswitch# scripts/perl/add_user 3000perl: warning: Setting locale failed.perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_CTYPE = "UTF-8", LANG = "en_US.UTF-8"are supported and installed on your system.perl: warning: Falling back to a fallback locale ("en_US.UTF-8").Added 3000 in file /usr/local/freeswitch/conf/directory/default/3000.xml Operation complete. 1 user added.Be sure to reloadxml.Regular expression information:Sample regex for all new users: ^3000$Sample regex for all new AND current users: ^(10(0[0-9]|1[0-9]|20)|3000)$In the default configuration you can modify the expression in the condition for 'Local_Extension'.
Adding a range of users , 3000 to 3010
Since 3000 was already added previously , it threw a warning , rest were successfully added
/usr/src/freeswitch-debs/freeswitch# scripts/perl/add_user -users=3000-3010
perl: warning: Setting locale failed.perl: warning: Please check that your locale settings: LANGUAGE = (unset), LC_ALL = (unset), LC_CTYPE = "UTF-8", LANG = "en_US.UTF-8"are supported and installed on your system.perl: warning: Falling back to a fallback locale ("en_US.UTF-8").User id 3000 already exists, skipping...Added 3001 in file /usr/local/freeswitch/conf/directory/default/3001.xml Added 3002 in file /usr/local/freeswitch/conf/directory/default/3002.xml Added 3003 in file /usr/local/freeswitch/conf/directory/default/3003.xml Added 3004 in file /usr/local/freeswitch/conf/directory/default/3004.xml Added 3005 in file /usr/local/freeswitch/conf/directory/default/3005.xml Added 3006 in file /usr/local/freeswitch/conf/directory/default/3006.xml Added 3007 in file /usr/local/freeswitch/conf/directory/default/3007.xml Added 3008 in file /usr/local/freeswitch/conf/directory/default/3008.xml Added 3009 in file /usr/local/freeswitch/conf/directory/default/3009.xml Added 3010 in file /usr/local/freeswitch/conf/directory/default/3010.xml Operation complete. 10 users added.Be sure to reloadxml.Regular expression information:Sample regex for all new users: ^30(0[123456789]|10)$Sample regex for all new AND current users: ^(10(0[0-9]|1[0-9]|20)|30(0[0-9]|10))$In the default configuration you can modify the expression in the condition for 'Local_Extension'.
After adding the user to directory , users can now make outbound calls . But howver cannot be rechable for incoming calls . To enable that e need to add them to dialplan .
Creating dialplan for the newly added users in conf/dialplan/default.xml
update the existing condition
<conditionfield="destination_number"expression="^(10[01][0-9])$"> with <conditionfield="destination_number"expression="^30(0[123456789]|10)$">
After this goto fs_cli cmd prompt and do reloadxml
*experimental not suitable for production as per Freeswitch docs
The master branch depends on video libraries which are not available as packages in Debian distribution, but are available from FreeSWITCH repository , requires the use of the devscripts and cowbuilder packages.apt-get install git devscripts cowbuilder
for errors such as “The repository ‘http://files.freeswitch.org/repo/ubuntu-1604/freeswitch-unstable xenial InRelease’ is not signed.” and “The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 0xxxxxxx” please note than only debian 8 is the officially supported os version by FS now. hence is using AWS ( amazon web service ) stick with ubuntu v 14 ie Ubuntu Server 14.04 LTS (HVM), SSD Volume Type which is also free tier eligible.
Once build is successfull , install libtool-bin , libcurl4-openssl-dev , libpcre3-dev , libspeex-dev , libspeexdsp-dev ,libtiff5 ,libtiff5-dev , yasm for libvpx , liblua5.1-0-dev for scripting
For mod_enum support install libldns-dev or disable it in modules.conf
we can either install libedit-dev (>= 2.11) or configure with –disable-core-libedit-support
./bootstrap.sh
./configure
make
For errors around lua file such as Cannot find lua.h header file , just do apt-get install lua5.2 and lua5.2-dev and copy the headers file manually to freeswitch languages folder such as
cp -R /usr/include/lua5.2/ src/mod/languages/mod_lua/
or you can copy these one by one lauxlib.h lua.h lua.hpp luaconf.h lualib.h
ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so llua
sudo make install
sudo make uhd-sounds-install
sudo make uhd-moh-install
sudo make samples
If you want to make lua from source
mkdir -p ~/Developing/third_party
cd Developing
wget https://www.lua.org/ftp/lua-5.3.2.tar.gz
tar xf lua-5.3.2.tar.gz
cd lua-5.3.2.tar.gz
make linux
sudo make install INSTALL_TOP=/usr/local
cd ~/Developing/third_party/rtags/build
cmake -DLUA_INCLUDE_DIR=/usr/local/include/ -DLUA_LIBRARY=/usr/local/lib/liblua.a ../
For internal calls , originate api can be used to initiate calls such as originate ALEG BLEG
originate {origination_caller_id_number=9999988888}sofia/internal/1004@127.0.0.1:5060 91999998888 XML default CALLER_ID_NAME CALLER_ID_NUMBER
This will make a call out to sip:1004@1127.0.0.1 with the Caller ID number set to 999998888, then it will send the call to the XML dialplan using context=default. Then the dialplan will process call to 91999998888 with the Caller ID name and number specified in the fields CALLER_ID_NAME and CALLER_ID_NUMBER.
fsc_cli> originate sofia/internal/1002@127.0.0.1:5060 &echo()
switch_ivr_originate.c:2159 Parsing global variables
switch_channel.c:1104 New Channel sofia/internal/1002@127.0.0.1:5060 [5188806e-cabd-4acc-b20b-00620c3362ec]
mod_sofia.c:5026 (sofia/internal/1002@127.0.0.1:5060) State Change CS_NEW -> CS_INIT
switch_core_state_machine.c:584 (sofia/internal/1002@127.0.0.1:5060) Running State Change CS_INIT (Cur 5 Tot 122559)
switch_core_state_machine.c:627 (sofia/internal/1002@127.0.0.1:5060) State INIT
mod_sofia.c:93 sofia/internal/1002@127.0.0.1:5060 SOFIA INIT
sofia_glue.c:1299 sofia/internal/1002@127.0.0.1:5060 sending invite version: 1.9.0 -654-ed4920e 64bit
Local SDP:
v=0
o=FreeSWITCH 1538689496 1538689497 IN IP4 172.31.27.106
s=FreeSWITCH
c=IN IP4 172.31.27.106
t=0 0
m=audio 24636 RTP/AVP 9 0 8 101
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=ptime:20
a=sendrecv
m=video 19042 RTP/AVP 102
b=AS:1024
a=rtpmap:102 VP8/90000
a=sendrecv
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 ccm tmmbr
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
switch_core_state_machine.c:40 sofia/internal/1002@127.0.0.1:5060 Standard INIT
switch_core_state_machine.c:48 (sofia/internal/1002@127.0.0.1:5060) State Change CS_INIT -> CS_ROUTING
switch_core_state_machine.c:627 (sofia/internal/1002@127.0.0.1:5060) State INIT going to sleep
switch_core_state_machine.c:584 (sofia/internal/1002@127.0.0.1:5060) Running State Change CS_ROUTING (Cur 4 Tot 122612)
sofia.c:7291 Channel sofia/internal/1002@127.0.0.1:5060 entering state [calling][0]
sofia.c:7291 Channel sofia/internal/1002@127.0.0.1:5060 entering state [terminated][503]