Michigan Telephone and I have been discussing using FreeSWITCH as an on-box adjunct to Asterisk to enable cutting-edge features, such as Google Voice integration, without having to use development-level Asterisk code. Here’s how to set up a very minimal FreeSWITCH on the same server as Asterisk for this very purpose.
References, at the top of the post to suggest that you read these first:
The steps:
FreeSWITCH
- Follow the installation guide to retrieve the development version of FreeSWITCH from the git repository. Warning! The Subversion repository is old, and so is the tarball, which claims to be a nightly snapshot. It is not. Only git will get you the current code.
- Build:
./bootstrap.sh
- Edit modules.conf in the source directory and uncomment endpoints/mod_dingaling. Later, once you see the minimal installation we’re producing, you may want to comment out other unused modules to save some build time.
./configure
, make
, and make install
. My Asterisk box already had most of the required libraries; only libtiff-devel was missing (needed for the spandsp module). I was able to retrieve libraries and headers with yum (yum install libtiff-devel
for example). The make process will alert you of anything missing. Just install the requirements and then make
again, and it will pick up where it left off.
- FreeSWITCH will now be installed in /usr/local/freeswitch and is contained within this directory and subdirectories. I noticed that it builds its own copy of iksemel, which I already have installed elsewhere for Asterisk’s use, but the custom libs are in /usr/local/freeswitch/lib so there is no interference.
- Delete the contents of /usr/local/freeswitch/conf. You can get them back later if you want by doing
make samples
from your FreeSWITCH source directory, but for this minimal installation, we can put all of the configuration in a single file and be sure nothing else is loading.
- I spent some time trying to optimize the FreeSWITCH config so that it contains just enough to act as a gateway between Asterisk (using SIP) and Google Voice. My freeswitch.xml config, appended to this post, should work for anyone following these steps. Copy it to the /usr/local/freeswitch/conf directory, editing the lines related to GMail login.
Asterisk
- If you’re set up for NAT, you may not (probably don’t) have the loopback network configured in your sip.conf as a local (non-NAT) network. Add
localnet = 127.0.0.0/255.255.255.0
to [general] in sip.conf or the sip_nat.file if you’re using FreePBX. Otherwise, Asterisk will try to use NAT-traversal methods for the Asterisk-FreeSWITCH on-box trunk.
- Set up a new SIP trunk. In FreePBX, name the peer “freeswitch” and use these trunk details:
host=127.0.0.1
port=5050
qualify=30000
type=friend
(FreePBX now sets up contexts appropriately within from-trunk, so the context line can be omitted here unless you wish to specify one.) The non-FreePBX method would be to create a [freeswitch]
block in sip.conf with the aforementioned details and an appropriate context=
line. That’s it. No registration, no usernames, nothing–we are authenticating by IP address and port only.
- Set up appropriate inbound and outbound routes in FreePBX or in your extensions.conf dialplan. This is outside the scope of this how-to.
Firewall
FreeSWITCH and/or the GTalk/Jingle protocol use more RTP ports than what I had previously configured in my router-firewall for Asterisk. So I updated my firewall to include UDP ports 10000-65000.
Google Voice and GMail
- Log into the GMail account with an associated Google Voice number, bring up the chat window and enable voice calling. Call a number and see that it works through your browser.
- Log into Google Voice and instruct it to route calls to Google Chat. According to the FreeSWITCH wiki, the FreeSWITCH integration only works when call screening is turned on. (Why?) So turn it on. Call your Google Voice number from any phone and see that it rings through to your browser. Then sign out of chat.
Get it started
With these settings in place, Asterisk should be listening to FreeSWITCH on 127.0.0.1 port 5060, and FreeSWITCH should be listening to Asterisk on 127.0.0.1 port 5050. Furthermore, FreeSWITCH should be able to navigate a NAT and talk to the Google Talk server and, using the latest FreeSWITCH code, send and receive calls on the Google Voice number.
Start FreeSWITCH. /usr/local/freeswitch/bin/freeswitch -c
will give you a console and once you have worked out the bugs, you can run it in the background with -nc
instead.
Does it work?
Let me know if you have followed these instructions and achieved success. I was able to send and receive calls with Google Voice, with working DTMF and mostly acceptable audio quality.
Place test calls with dl_debug on
in the FreeSWITCH console to see the XMPP messages. I spent a lot of time examining these and Wireshark captures to find RTP issues (solved in the config and with the firewall adjustments).
I was disappointed that the audio was sometimes jittery, which I never see with the Gizmo5 or PSTN Google Voice transports. I don’t know if it was from the Internet or from the server itself, but I can say that FreeSWITCH in this very minimal mode seems to add very little additional memory or CPU usage.
Appendix: the config
My single-config-file freeswitch.xml. Cut, paste and use. Replace YOURUSERNAME, YOURPASSWORD, and YOURDID with your settings. A veteran FreeSWITCH user could help me optimize this even more.
<?xml version=”1.0″?>
<document type=”freeswitch/xml”>
<include>
<!– this is a good place to pre-define globals if you want –>
<X-PRE-PROCESS cmd=”set” data=”global_codec_prefs=G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM”/>
</include>
<section name=”configuration” description=”Various Configuration”>
<configuration name=”modules.conf” description=”Modules”>
<modules>
<load module=”mod_console”/>
<load module=”mod_logfile”/>
<load module=”mod_sofia”/>
<load module=”mod_dingaling”/>
<load module=”mod_commands”/>
<load module=”mod_dptools”/>
<load module=”mod_dialplan_xml”/>
</modules>
</configuration>
<configuration name=”console.conf” description=”Console Logger”>
<mappings>
<map name=”all” value=”console,debug,info,notice,warning,err,crit,alert”/>
</mappings>
<settings>
<param name=”colorize” value=”true”/>
<param name=”loglevel” value=”info”/>
</settings>
</configuration>
<configuration name=”switch.conf” description=”Core Configuration”>
<cli-keybindings>
<key name=”1″ value=”help”/>
<key name=”2″ value=”status”/>
<key name=”3″ value=”show channels”/>
<key name=”4″ value=”show calls”/>
<key name=”5″ value=”sofia status”/>
<key name=”6″ value=”dingaling status”/>
<key name=”7″ value=”reloadxml”/>
</cli-keybindings>
<settings>
<param name=”colorize-console” value=”true”/>
<param name=”max-sessions” value=”1000″/>
<param name=”sessions-per-second” value=”30″/>
<param name=”loglevel” value=”debug”/>
<param name=”dump-cores” value=”yes”/>
<param name=”rtp-enable-zrtp” value=”false”/>
</settings>
</configuration>
<configuration name=”logfile.conf” description=”File Logging”>
<settings>
<param name=”rotate-on-hup” value=”true”/>
</settings>
<profiles>
<profile name=”default”>
<settings>
<param name=”rollover” value=”10485760″/>
</settings>
<mappings>
<map name=”all” value=”debug,info,notice,warning,err,crit,alert”/>
</mappings>
</profile>
</profiles>
</configuration>
<configuration name=”sofia.conf” description=”sofia Endpoint”>
<global_settings>
<param name=”log-level” value=”0″/>
<param name=”debug-presence” value=”0″/>
</global_settings>
<profiles>
<profile name=”freeswitch-sip”>
<gateways>
<gateway name=”asterisk-local”>
<param name=”username” value=”freeswitch”/>
<param name=”password” value=”0″/>
<param name=”proxy” value=”127.0.0.1:5060″/>
<param name=”register” value=”false”/>
<param name=”retry-seconds” value=”30″/>
<param name=”caller-id-in-from” value=”true”/>
</gateway>
</gateways>
<domains>
<domain name=”all” alias=”true” parse=”false”/>
</domains>
<settings>
<param name=”debug” value=”0″/>
<param name=”sip-trace” value=”no”/>
<param name=”log-auth-failures” value=”false”/>
<param name=”forward-unsolicited-mwi-notify” value=”false”/>
<param name=”context” value=”asterisk”/>
<param name=”rfc2833-pt” value=”101″/>
<param name=”sip-port” value=”5050″/>
<param name=”dialplan” value=”XML”/>
<param name=”dtmf-type” value=”info”/>
<param name=”inbound-codec-prefs” value=”$${global_codec_prefs}”/>
<param name=”outbound-codec-prefs” value=”$${global_codec_prefs}”/>
<param name=”use-rtp-timer” value=”true”/>
<param name=”rtp-timer-name” value=”soft”/>
<param name=”vad” value=”none”/>
<param name=”rtp-ip” value=”127.0.0.1″/>
<param name=”sip-ip” value=”127.0.0.1″/>
<param name=”inbound-codec-negotiation” value=”generous”/>
<param name=”tls” value=”false”/>
<param name=”nonce-ttl” value=”60″/>
<!–<param name=”disable-transcoding” value=”true”/>–>
<param name=”auth-calls” value=”false”/>
<param name=”auth-all-packets” value=”false”/>
<param name=”ext-rtp-ip” value=”127.0.0.1″/>
<param name=”ext-sip-ip” value=”127.0.0.1″/>
<param name=”rtp-timeout-sec” value=”300″/>
<param name=”rtp-hold-timeout-sec” value=”1800″/>
<param name=”challenge-realm” value=”auto_from”/>
</settings>
</profile>
</profiles>
</configuration>
<configuration name=”dingaling.conf” description=”XMPP Jingle Endpoint”>
<settings>
<param name=”debug” value=”0″/>
<param name=”codec-prefs” value=”PCMU”/>
</settings>
<profile type=”client”>
<param name=”name” value=”gtalk”/>
<param name=”login” value=”YOURUSERNAME@gmail.com/freeswitch”/>
<param name=”password” value=”YOURPASSWORD”/>
<param name=”dialplan” value=”XML”/>
<param name=”context” value=”gtalk”/>
<param name=”message” value=”This is FreeSWITCH”/>
<param name=”auto-reply” value=”This is an automated system for audio calls only. Please do not chat.”/>
<param name=”rtp-ip” value=”auto”/>
<param name=”candidate-acl” value=”wan.auto”/>
<param name=”local-network-acl” value=”localnet.auto”/>
<param name=”ext-rtp-ip” value=”stun:stun.freeswitch.org”/>
<param name=”auto-login” value=”true”/>
<param name=”sasl” value=”plain”/>
<param name=”server” value=”talk.google.com”/>
<param name=”tls” value=”true”/>
<!– disable to trade async for more calls –>
<param name=”use-rtp-timer” value=”false”/>
<!– default extension (if one cannot be determined) –>
<param name=”exten” value=”gtalk-in”/>
</profile>
</configuration>
<configuration name=”post_load_modules.conf” description=”Post-load modules” />
</section>
<section name=”dialplan” description=”Regex/XML Dialplan”>
<context name=”asterisk”>
<extension name=”asterisk-outbound”>
<condition field=”destination_number” expression=”^(.*)$”>
<action application=”ring_ready” />
<action application=”set” data=”hangup_after_bridge=true”/>
<action application=”set” data=”bridge_generate_comfort_noise=true”/>
<action application=”bridge” data=”dingaling/gtalk/+$1@voice.google.com”/>
</condition>
</extension>
</context>
<context name=”gtalk”>
<extension name=”gtalk-in”>
<condition field=”destination_number” expression=”^(.*)$”>
<action application=”set” data=”hangup_after_bridge=true”/>
<action application=”set” data=”effective_caller_id_name=${caller_id_number}”/>
<action application=”set” data=”execute_on_answer=send_dtmf 1″/>
<action application=”set” data=”bridge_generate_comfort_noise=true”/>
<!– <action application=”answer” /> Add this to answer the call before bridge to * –>
<!– <action application=”ring_ready” /> Or GV Voicemail will get it if you don’t ans. –>
<!– <action application=”set” data=”ringback=%(2000, 4000, 440.0, 480.0)” /> –>
<action application=”bridge” data=”sofia/gateway/asterisk-local/YOURDID” />
</condition>
</extension>
</context>
</section>