Links
- Official website is https://www.freeswitch.com which redirects to https://signalwire.com/freeswitch.
- Source code is at github.com/signalwire/freeswitch.
Configuration
Configuration directories
How do I get the configuration directories from FreeSWITCH again?
Nick vs Networking shows a command for getting all _dir paths:
$ fs_cli -x "global_getvar" | grep _dir
base_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x
recordings_dir=/var/lib/freeswitch/recordings
sounds_dir=/etc/freeswitch/sounds
conf_dir=/etc/freeswitch
log_dir=/var/log/freeswitch
run_dir=/run/freeswitch
db_dir=/var/cache/freeswitch
mod_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/lib/freeswitch/mod
htdocs_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/share/freeswitch/htdocs
script_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/share/freeswitch/scripts
temp_dir=/tmp
grammar_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/share/freeswitch/grammar
fonts_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/share/freeswitch/fonts
images_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/var/lib/freeswitch/images
certs_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/etc/freeswitch/tls
storage_dir=/var/lib/freeswitch/storage
cache_dir=/var/cache/freeswitch
data_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/share/freeswitch
localstate_dir=/nix/store/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-freeswitch-1.xx.x/var/lib/freeswitch
And now I’m trying to remember how I actually set the script_dir to be something else.
Ah, it’s by providing a “-scripts” argument when launching FreeSWITCH.
So I need to modify my systemd service that adds that.
Sounds
You can see the sounds directory with eval $${sounds_dir}.
Say it’s /etc/freeswitch/sounds and you want to play a file called example.wav.
You’d do that with a line like <action application="playback" data="example.wav"/>.
But you can’t just put the file at /etc/freeswitch/sounds/example.wav, you need to put it in a path like /etc/freeswitch/sounds/en/us/callie/example.wav.
Users
For logging into SIP, user configuration is located in directory/default/.
ACLs
Allowed IP addresses are listed in autoload_configs/acl.conf.xml, which is used by <param name="apply-candidate-acl" value="XXXXXX"/> in sip_profiles/internal.xml.
fs_cli configuration
If you modify the password for fs_cli (which you probably should), you’ll probably want to configure the password so you don’t have to type it as a command argument.
You’d put the following in ~/.fs_cli_conf:
[default]
; Put me in ~/.fs_cli_conf
password => some_secret_password
Call bridging
Note to self: Need to get call ringing to a softphone to actually play a ringing tone.
Supposedly, setting <action application="set" data="ringback=${us-ring}"/> should work, but it hasn’t so far.
Maybe I need to check if ${us-ring} exists?
Oh, eval $${us-ring} returns %(2000,4000,440,480).
While testing bridging with Gnome Calls, I noticed that bridging immediately failed while origination succeeded.
Looking at debugging output of gnome calls I see:
20:26:09.9716 CallsSipOrigin[1077203]: WARNING: No common codecs in SDP. Hanging up. Remote SDP: v=0 o=FreeSWITCH 1772148003 1772148004 IN IP4 ░░░░░░░░░░░ s=FreeSWITCH c=IN IP4 ░░░░░░░░░░░ t=0 0 m=audio 18366 RTP/AVP 9 101 13 a=rtpmap:9 G722/8000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=rtpmap:13 CN/8000 a=ptime:20
but when testing with origination I see:
20:28:21.3234 CallsSipOrigin[1077203]: DEBUG: Remote SDP was set to: v=0 o=FreeSWITCH 1772148603 1772148604 IN IP4 ░░░░░░░░░░░ s=FreeSWITCH c=IN IP4 ░░░░░░░░░░░ t=0 0 m=audio 17898 RTP/AVP 102 9 0 8 104 105 101 13 a=rtpmap:102 opus/48000/2 a=fmtp:102 useinbandfec=1; maxaveragebitrate=30000; maxplaybackrate=48000; ptime=20; minptime=10; maxptime=40 a=rtpmap:9 G722/8000 a=rtpmap:0 PCMU/8000 a=rtpmap:8 PCMA/8000 a=rtpmap:104 telephone-event/48000 a=fmtp:104 0-15 a=rtpmap:105 CN/48000 a=rtpmap:101 telephone-event/8000 a=fmtp:101 0-15 a=rtpmap:13 CN/8000 a=ptime:20 m=video 19584 RTP/AVP 103 b=AS:1024 a=rtpmap:103 VP8/90000 a=rtcp-fb:103 ccm fir a=rtcp-fb:103 ccm tmmbr a=rtcp-fb:103 nack a=rtcp-fb:103 nack pli
I was wondering which codecs Gnome Calls maybe uses, so here’s its local SDP (I guess PCMU/PCMA):
v=0
c=IN IP4 ░░░░░░░░░░░░
m=audio 40907 RTP/AVP 0 8
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtcp:37621
Asking an LLM and looking at FreeSWITCH codec negotiation explained docs, I first tried setting the variable codec_string (but that didn’t work) and eventually arrived at:
<action application="export" data="nolocal:absolute_codec_string=PCMA,PCMU"/>
<action application="bridge" data="{bridge_early_media=true,ignore_early_media=true}user/1000"/>
which did work. However, it didn’t get ringing to the softphone.
I should have known softphones don’t really have early media.
What seemed to work was removing bridge_early_media and adding instant_ringback=true.
<action application="set" data="instant_ringback=true"/>
<action application="bridge" data="{ignore_early_media=true}user/1000"/>
Enabling TTS in NixOS
Looks like I need to override the modules part of pkgs.freeswitch to get stuff like mod_flite or mod_tts_commandline working.
Looks like there was a bug with modules in Nixpkgs being incorrectly named “ast_tts” instead of “asr_tts”.
Speech recognition
I was trying to figure out “detect_speech” but it looks like “unimrcp” was removed from FreeSWITCH and mod_pocketsphinx probably won’t work since pocketsphinx has been removed from nixpkgs.
Vosk integration with FreeSWITCH seems interesting.
WebRTC
One idea for connecting to FreeSWITCH via WebRTC is to use the Janus WebRTC gateway. See an example at https://janus.conf.meetecho.com/siptest.html.
Ports
I think internal users use port 5060 (5061 if TLS is enabled) and external users use port 5080.
mod_event_socket uses port 8021 by default (and has a default password that likely should be changed).
Sound issues (firewall)
If your calls are connecting but you’re not hearing audio, you may want to try opening up your firewall more. I had an issue with Linphone and FreeSWITCH, so as a workaround I’ve added some rules in nftables (see /nftables) on both the local and remote end that just allow connections from certain IPs for now. I should verify which specific rules or ports were needed. And I should improve the firewall rules later, perhaps by specifying certain RTP port ranges that are allowed. Or maybe I’ll set up a TURN server.
Console
| Command | Description |
|---|---|
reloadxml
|
Reloads some XML configuration. |
console loglevel 7
|
Sets the log level to DEBUG. |
show modules
|
List loaded modules. |
sofia status profile internal reg
|
See currently registered users (i.e. softphones currently online) |
show channels
|
Get a list of active calls. |
uuid_kill b8a9a043-2706-47c0-ba93-5f8659327b7c
|
Kill a specific call. |
sofia status profile internal reg
|
List currently registered users (i.e. softphones currently online): |
sofia profile internal siptrace onsofia profile internal siptrace off
|
View a siptrace (for debugging connections). |
sofia loglevel all 9sofia global siptrace on
|
Seems to output even more debugging information. |
system echo hisystem pwdsystem echo $PATH |
Example running shell commands. bg_system does it in the background.
Apparently this is pretty dangerous, as someone could control how variables expand.
|
/event all |
See all events for the Event Socket Layer (ESL). |
Here’s how you can reload internal SIP (getting it to rebind ports, if necessary):
sofia profile internal stop
sofia profile internal start
If you can’t get a profile like internal to show up:
reload mod_sofia
Originate a call like: originate {origination_caller_id_number=5000,origination_caller_id_name='IVR example'}user/1000 5000.
To originate to an external number (going to local extension 7425), do something like originate {origination_caller_id_number=6508875788,ignore_early_media=true,originate_timeout=60}sofia/gateway/somegateway/18445674826 7425 XML default.
To play some media: originate {origination_caller_id_number=6508875788,ignore_early_media=true,originate_timeout=60}sofia/gateway/somegateway/18445674826 &playback(rick.oga)
Event Socket Layer (ESL)
$ telnet 127.0.0.1 8021 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Content-Type: auth/request auth WhateverYourPasswordIs Content-Type: command/reply Reply-Text: +OK accepted event plain ALL Content-Type: command/reply Reply-Text: +OK event listener enabled plain
Notes: telnet is part of inetutils. You have to press Enter twice after the command.
Misc
- I should look at mod_httapi more.
- I should see how the Event Socket Layer (ESL) works, so I could maybe better respond to things and process stuff in a language like Clojure. Titon Barua has a freeswitch-clj ESL library, which I haven’t tried.