A Ruby library for interacting with FreeSWITCH through mod_event_socket, using async I/O.
You should be familiar with mod_event_socket and the differences between inbound and outbound event sockets before getting started.
Requires Ruby 3.0+.
Add to your Gemfile:
gem "librevox"
Subclass Librevox::Listener::Inbound to create an inbound listener. It connects to
FreeSWITCH and subscribes to events.
React to events in two ways:
on_event, called for every event.event hooks for specific event names.class MyInbound < Librevox::Listener::Inbound
def on_event(e)
puts "Got event: #{e.content[:event_name]}"
end
event :channel_hangup do
do_something
end
# The hook block receives a Response when it takes an argument:
event :channel_bridge do |e|
puts e.content[:caller_caller_id_number]
end
def do_something
# ...
end
end
By default, inbound listeners subscribe to all events. Use events to limit which events
are received, and filters to filter by header values:
class MyInbound < Librevox::Listener::Inbound
events ['CHANNEL_EXECUTE', 'CUSTOM foo']
filters 'Caller-Context' => ['default', 'example'],
'Caller-Privacy-Hide-Name' => 'no'
end
Note on CUSTOM events: FreeSWITCH custom events have a subclass name (e.g.
CUSTOM conference::maintenance). You must include both the event name and subclass —
events ['CUSTOM conference::maintenance']. Using just events ['CUSTOM']
will not match any custom events.
Subclass Librevox::Listener::Outbound to create an outbound listener. FreeSWITCH
connects to it when a call hits a socket application in the dialplan.
Outbound listeners have the same event functionality as inbound, but scoped to the session.
When FreeSWITCH connects, session_initiated is called. Build your dialplan here.
Each application call blocks until FreeSWITCH signals completion
(CHANNEL_EXECUTE_COMPLETE), so applications execute sequentially:
class MyOutbound < Librevox::Listener::Outbound
def session_initiated
answer
digit = play_and_get_digits "enter-digit.wav", "bad-digit.wav"
bridge "sofia/gateway/trunk/#{digit}"
end
end
Applications that read input (like play_and_get_digits and read) return the
collected value directly.
def session_initiated
answer
set "foo", "bar"
multiset "baz" => "1", "qux" => "2"
playback "welcome.wav"
hangup
end
For apps not yet wrapped by a named helper, call application directly:
application "park"
Channel variables are available through session (a hash) and variable:
def session_initiated
answer
number = variable(:destination_number)
playback "greeting-#{number}.wav"
end
To avoid name clashes between applications and commands, commands are accessed through
api:
def session_initiated
answer
api.status
api.originate 'sofia/user/coltrane', extension: "1234"
end
Start a single listener:
Librevox.start MyInbound
With connection options:
Librevox.start MyInbound, host: "1.2.3.4", port: 8021, auth: "secret"
Start multiple listeners:
Librevox.start do
run MyInbound
run MyOutbound, port: 8084
end
Default ports are 8021 for inbound and 8084 for outbound.
After a session ends (e.g. the caller hangs up), the outbound socket connection to FreeSWITCH remains open for post-session events. Close it manually when done to avoid lingering sessions:
class MyOutbound < Librevox::Listener::Outbound
event :channel_hangup do
disconnect
end
end
Librevox::CommandSocket connects to the FreeSWITCH management console for one-off
commands:
require "librevox/command_socket"
socket = Librevox::CommandSocket.new(server: "127.0.0.1", port: 8021, auth: "ClueCon")
socket.originate 'sofia/user/coltrane', extension: "1234"
#=> #<Librevox::Protocol::Response ...>
socket.status
#=> #<Librevox::Protocol::Response ...>
socket.close
Librevox.options[:log_file] = "librevox.log" # default: STDOUT
Librevox.options[:log_level] = Logger::DEBUG # default: Logger::INFO