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 following categories :
Loggers
XML Interfaces
Event Handlers
Application
Language
ASR/TTS
Loggers
mod_console
mod_graylog2
mod_logfile
mod_syslog
mod_yaml
Multi-Faceted
mod_enum is a dialplan interface, an application interface and an api command interface
mod_enum
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.
Applications
mod_commands
mod_conference
inbound and outbound conference bridge, loaded from file conf/autoload_configs/conference.conf.xml
mod_curl
mod_db
-tbd
mod_dptools
Dialplan tools provide the apps (commands) to process call sessions in XML dialplans.
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.
flush_dtmf – Flush any queued DTMF.
gentones – Generate TGML tones.
group – Insert or delete members in a group.
hash – Add a hash to the db.
hold – Send a hold message.
httapi
Send call control to a Web server with the HTTAPI infrastructure
info – Display Call Info.
intercept – Lets you pickup a call and take it over if you know the uuid.
ivr
Run an IVR menu.
javascript – Run a JavaScript script from the dialplan
jitterbuffer – Send a jitter buffer message to a session
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
log – Logs a channel variable for the channel calling the application
loop_playback – Playback a file to the channel looply for limted times
lua – Run a Lua script from the dialplan
media_reset – Reset all bypass/proxy media flags.
mkdir – Create a directory.
multiset – Set multiple channel variables with a single action.
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.
phrase – Say a Phrase.
pickup – Pickup a call.
play_and_detect_speech – Play while doing speech recognition.
play_and_get_digits – Play and get Digits.
play_fsv – Play an FSV file. FSV – (FS Video File Format) additional description needed
playback – Play a sound file to the originator.
pre_answer – Answer a channel in early media mode.[old wiki]
preprocess – description needed
presence – Send Presence
privacy – Set caller privacy on calls.
queue_dtmf – Send DTMF digits after a successful bridge.
read – Read Digits.
record – Record a file from the channel’s input.
record_fsv – Record a FSV file. FSV – (FS Video File Format) additional description needed
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.
ring_ready – Indicate Ring_Ready on a channel.
rxfax – Receive a fax as a tif file.
say
Say time/date/ip_address/digits/etc. With pre-recorded prompts.
sched_broadcast – Enable Scheduled Broadcast.
sched_cancel – Cancel a scheduled future broadcast/transfer.
sched_hangup – Enable Scheduled Hangup.
sched_heartbeat – Enable Scheduled Heartbeat.
sched_transfer – Enable Scheduled Transfer.
send_display – Sends an info packet with a sipfrag.
send_dtmf – Send inband DTMF, 2833, or SIP Info digits from a session.
send_info – Send info to the endpoint.
session_loglevel – Override the system’s loglevel for this channel.
set – Set a channel variable for the channel calling the application.
set_audio_level – Adjust the read or write audio levels for a channel.
set_global – Set a global variable.
set_name – Name the channel.
set_profile_var – Set a caller profile variable.
set_user – Set a user.
set_zombie_exec – Sets the zombie execution flag on the current channel.
sleep – Pause a channel.
socket – Establish an outbound socket connection.
sound_test – Analyze Audio.
speak – Speaks a string or file of text to the channel using the defined TTS engine.[old wiki]
soft_hold – Put a bridged channel on hold.
start_dtmf – Start inband DTMF detection.
stop_dtmf – Stop inband DTMF detection.
start_dtmf_generate – Start inband DTMF generation.
stop_displace_session – Stop displacement audio on a channel.
stop_dtmf_generate – Stop inband DTMF generation.
stop_record_session – Stop Record Session.
stop_tone_detect – Stop detecting tones.
strftime – Returns formatted date and time.
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.
transfer – Immediately transfer the calling channel to a new extension.[old wiki]
translate – Number translation.
unbind_meta_app – Unbind a key from an application.
unset – Unset a variable.
unhold – Send a un-hold message.
verbose_events – Make ALL Events verbose (Make all variables appear in every single event for this channel).
wait_for_silence – Pause processing while waiting for silence on the channel.
wait_for_answer – Pause processing while waiting for the call to be answered.
API
chat – Send a text message to a IM client.
presence – Send Presence.
strepoch – Returns the date/time as a UNIX epoch (seconds elapsed since midnight UTC, January 1, 1970).
strftime – Returns formatted date and time.
strftime_tz – Returns formatted date and time in the timezone specified.
mod_expr
mod_fifo
mod_hash
mod_mongo
mod_voicemail
mod_directory
mod_distributor
mod_lcr
mod_easyroute
mod_esf
mod_fsv
mod_cluechoo
mod_valet_parking
mod_fsk
mod_spy
mod_sms
mod_smpp
mod_random
mod_httapi
mod_translate
File Format Interfaces
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
Timers
mod_timerfd
mod_posix_timer
Languages
These scripting languages allow programming the call routing logic
mod_v8
FreeSWITCH has support for the Google V8 JavaScript (ECMAScript) engine. It needs to be uncommented in the modules.conf file
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 is designed to route and interconnect popular 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 a number of commercial products
from start-ups to Carriers.
– freeswitch.com
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 which 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 . SIP being the most popular protocol for 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.
Architecture and Design of Freeswitch
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 .
Channel Variables
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.
Expansion
$${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.
Also channel variables can be limited to scope on an extension . An example of passing some channel variable to log application .
<action application="log" data="INFO Inbound call CallUUID ${call_uuid} SIPCallID ${sip_call_id}- from ${caller_id_number} to ${destination_number}"/>
If the conditions are not met, optional anti-actions are executed.
<name="is_secure" continue="true">
<-- Only Truly consider it secure if its TLS and SRTP -->
<condition field="${sip_via_protocol}" expression="tls"/>
<condition field="${rtp_secure_media_confirmed}" expression="^true$">
<action application="sleep" data="2000"/>
<action application="playback" data="misc/call_secured.wav"/>
<anti-action application="eval" data="not_secure"/>
<condition>
<extension>
Inline actions are executed during the hunting phase of dialplan
Dialplan
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.
To detect early media fail the conditions are
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 .
Directory
A simple directory listing containing two groups with 2 users each
/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
root@ip-172-31-27-106:/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
Installation
Quick Installation on MacOS
Download and run the dmg , screenshots attached .
Building from source on Ubuntu 16.04 Xenial
*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 ../
To see if freeswitch is running – ps aux | grep freeswitch
fs_cli
To check listening ports – ngrep -W byline -d any port 5060 or netstat -lnp | grep 5060
HTTP
TCP
80
0.0.0.0/0
HTTP
TCP
80
::/0
Custom TCP Rule
TCP
5080 – 5081
0.0.0.0/0
Custom TCP Rule
TCP
5080 – 5081
::/0
Custom UDP Rule
UDP
16384 – 32768
0.0.0.0/0
Custom UDP Rule
UDP
16384 – 32768
::/0
All traffic
All
All
0.0.0.0/0
All traffic
All
All
::/0
SSH
TCP
22
0.0.0.0/0
Custom TCP Rule
TCP
8021
0.0.0.0/0
Custom TCP Rule
TCP
8021
::/0
Custom UDP Rule
UDP
5060 – 5062
0.0.0.0/0
Custom UDP Rule
UDP
5060 – 5062
::/0
Custom UDP Rule
UDP
5080 – 5081
0.0.0.0/0
Custom UDP Rule
UDP
5080 – 5081
::/0
HTTPS
TCP
443
0.0.0.0/0
HTTPS
TCP
443
::/0
Custom TCP Rule
TCP
8081 – 8082
0.0.0.0/0
Custom TCP Rule
TCP
8081 – 8082
::/0
Custom TCP Rule
TCP
5060 – 5061
0.0.0.0/0
Custom TCP Rule
TCP
5060 – 5061
::/0
Security
-tbd
ACL
Fail2Ban
IPtables
Debugging and Call
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]