bougyman-freeswitcher 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/License.txt +20 -0
- data/NEWS +3 -0
- data/README +85 -0
- data/Rakefile +82 -0
- data/bin/cmd_demo.rb +19 -0
- data/bin/ies_demo.rb +19 -0
- data/bin/ies_demo_with_hook.rb +27 -0
- data/bin/oes_demo.rb +22 -0
- data/lib/fsr.rb +86 -0
- data/lib/fsr/app.rb +72 -0
- data/lib/fsr/app/answer.rb +21 -0
- data/lib/fsr/app/bridge.rb +33 -0
- data/lib/fsr/app/conference.rb +29 -0
- data/lib/fsr/app/fifo.rb +38 -0
- data/lib/fsr/app/fs_break.rb +21 -0
- data/lib/fsr/app/fs_sleep.rb +24 -0
- data/lib/fsr/app/hangup.rb +22 -0
- data/lib/fsr/app/log.rb +24 -0
- data/lib/fsr/app/playback.rb +23 -0
- data/lib/fsr/app/set.rb +22 -0
- data/lib/fsr/app/speak.rb +25 -0
- data/lib/fsr/app/transfer.rb +24 -0
- data/lib/fsr/cmd.rb +57 -0
- data/lib/fsr/cmd/fsctl.rb +41 -0
- data/lib/fsr/cmd/originate.rb +46 -0
- data/lib/fsr/cmd/sofia.rb +40 -0
- data/lib/fsr/cmd/sofia/profile.rb +75 -0
- data/lib/fsr/cmd/sofia/status.rb +39 -0
- data/lib/fsr/cmd/sofia_contact.rb +31 -0
- data/lib/fsr/cmd/status.rb +25 -0
- data/lib/fsr/command_socket.rb +29 -0
- data/lib/fsr/database.rb +7 -0
- data/lib/fsr/database/call_limit.rb +21 -0
- data/lib/fsr/database/core.rb +30 -0
- data/lib/fsr/database/sofia_reg_external.rb +0 -0
- data/lib/fsr/database/sofia_reg_internal.rb +0 -0
- data/lib/fsr/database/voicemail_default.rb +0 -0
- data/lib/fsr/event_socket.rb +41 -0
- data/lib/fsr/fake_socket.rb +68 -0
- data/lib/fsr/listener.rb +10 -0
- data/lib/fsr/listener/header_and_content_response.rb +21 -0
- data/lib/fsr/listener/inbound.rb +61 -0
- data/lib/fsr/listener/inbound/event.rb +42 -0
- data/lib/fsr/listener/outbound.rb +62 -0
- data/spec/fsr/app.rb +8 -0
- data/spec/fsr/app/bridge.rb +17 -0
- data/spec/fsr/app/conference.rb +12 -0
- data/spec/fsr/app/fifo.rb +29 -0
- data/spec/fsr/cmd.rb +8 -0
- data/spec/fsr/cmd/originate.rb +12 -0
- data/spec/fsr/cmd/sofia.rb +69 -0
- data/spec/fsr/cmd/sofia/profile.rb +58 -0
- data/spec/fsr/listener.rb +12 -0
- data/spec/fsr/listener/inbound.rb +19 -0
- data/spec/fsr/listener/outbound.rb +19 -0
- data/spec/fsr/loading.rb +27 -0
- data/spec/helper.rb +14 -0
- data/tasks/package.rake +29 -0
- data/tasks/spec.rake +59 -0
- metadata +229 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'fsr/listener'
|
4
|
+
require 'fsr/listener/header_and_content_response.rb'
|
5
|
+
|
6
|
+
module FSR
|
7
|
+
module Listener
|
8
|
+
class Inbound < EventMachine::Protocols::HeaderAndContentProtocol
|
9
|
+
HOOKS = {}
|
10
|
+
|
11
|
+
def initialize(args = {})
|
12
|
+
super
|
13
|
+
@auth = args[:auth] || "ClueCon"
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_init
|
17
|
+
say("auth #{@auth}")
|
18
|
+
say('event plain ALL')
|
19
|
+
end
|
20
|
+
|
21
|
+
def receive_request(header, content)
|
22
|
+
hash_header = headers_2_hash(header)
|
23
|
+
hash_content = headers_2_hash(content)
|
24
|
+
event = HeaderAndContentResponse.new({:headers => hash_header, :content => hash_content})
|
25
|
+
event_name = event.content[:event_name].to_s.strip
|
26
|
+
unless event_name.empty?
|
27
|
+
HOOKS[event_name.to_sym].call(event) unless HOOKS[event_name.to_sym].nil?
|
28
|
+
end
|
29
|
+
on_event(event)
|
30
|
+
end
|
31
|
+
|
32
|
+
def say(line)
|
33
|
+
send_data("#{line}\r\n\r\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def on_event(event)
|
37
|
+
event
|
38
|
+
end
|
39
|
+
|
40
|
+
# Add or replace a block to execute when the specified event occurs
|
41
|
+
#
|
42
|
+
# <b>Parameters</b>
|
43
|
+
# - event : What event to trigger the block on. May be
|
44
|
+
# :CHANNEL_CREATE, :CHANNEL_DESTROY etc
|
45
|
+
# - block : Block to execute
|
46
|
+
#
|
47
|
+
# <b>Returns/<b>
|
48
|
+
# - nil
|
49
|
+
def self.add_event_hook(event, &block)
|
50
|
+
HOOKS[event] = block
|
51
|
+
end
|
52
|
+
|
53
|
+
# Delete the block that was to be executed for the specified event.
|
54
|
+
def self.del_event_hook(event)
|
55
|
+
HOOKS.delete(event)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'fsr/listener/inbound'
|
2
|
+
module FSR
|
3
|
+
module Listener
|
4
|
+
module Inbound
|
5
|
+
class Event
|
6
|
+
def self.from(data)
|
7
|
+
instance = new
|
8
|
+
|
9
|
+
capture = header = {}
|
10
|
+
body = {}
|
11
|
+
|
12
|
+
data.each_line do |line|
|
13
|
+
line.strip!
|
14
|
+
|
15
|
+
case line
|
16
|
+
when ''
|
17
|
+
capture = body
|
18
|
+
when /([a-zA-Z0-9-]+):\s*(.*)/
|
19
|
+
#capture[$1] = $2.strip
|
20
|
+
key, val = line.split(":")
|
21
|
+
capture[key] = val.to_s.strip
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
instance.header.merge!(header)
|
26
|
+
instance.body.merge!(body)
|
27
|
+
instance
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :header, :body
|
31
|
+
|
32
|
+
def initialize(header = {}, body = {})
|
33
|
+
@header, @body = header, body
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](key)
|
37
|
+
@header.merge(@body)[key]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'eventmachine'
|
3
|
+
require 'fsr/listener'
|
4
|
+
require 'fsr/listener/header_and_content_response'
|
5
|
+
|
6
|
+
module FSR
|
7
|
+
load_all_applications
|
8
|
+
module Listener
|
9
|
+
class Outbound < EventMachine::Protocols::HeaderAndContentProtocol
|
10
|
+
|
11
|
+
# Include FSR::App to get all the applications defined as methods
|
12
|
+
include FSR::App
|
13
|
+
|
14
|
+
# Redefine the FSR::App methods to wrap sendmsg around them
|
15
|
+
SENDMSG_METHOD_DEFINITION = "def %s(*args, &block); sendmsg super; end"
|
16
|
+
APPLICATIONS.each { |app, obj| module_eval(SENDMSG_METHOD_DEFINITION % app.to_s) }
|
17
|
+
|
18
|
+
def post_init
|
19
|
+
@session = nil # holds the session object
|
20
|
+
send_data("connect\n\n")
|
21
|
+
FSR::Log.debug "Accepting connections."
|
22
|
+
end
|
23
|
+
|
24
|
+
def receive_request(header, content)
|
25
|
+
hash_header = headers_2_hash(header)
|
26
|
+
hash_content = headers_2_hash(content)
|
27
|
+
session = HeaderAndContentResponse.new({:headers => hash_header, :content => hash_content})
|
28
|
+
if @session.nil?
|
29
|
+
@session = self
|
30
|
+
session_initiated(session)
|
31
|
+
else
|
32
|
+
receive_reply(session)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Received data dispatches the data received by the EM socket,
|
37
|
+
# Either as a Session, a continuation of a Session, or as a Session's last CommandReply
|
38
|
+
|
39
|
+
def session_initiated(session)
|
40
|
+
session
|
41
|
+
end
|
42
|
+
|
43
|
+
def receive_reply(session)
|
44
|
+
session
|
45
|
+
end
|
46
|
+
|
47
|
+
# sendmsg sends data to the EM app socket via #send_data, or
|
48
|
+
# returns the string it would send if #send_data is not defined.
|
49
|
+
# It expects an object which responds to either #sendmsg or #to_s,
|
50
|
+
# which should return a EM Outbound Event Socket formatted instruction
|
51
|
+
|
52
|
+
def sendmsg(message)
|
53
|
+
text = message.respond_to?(:sendmsg) ? message.sendmsg : message.to_s
|
54
|
+
FSR::Log.debug "sending #{text}"
|
55
|
+
message = "sendmsg\n%s\n" % text
|
56
|
+
self.respond_to?(:send_data) ? send_data(message) : message
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/spec/fsr/app.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("bridge")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Bridge" do
|
6
|
+
# Utilize the [] shortcut to start a conference
|
7
|
+
it "Bridges a call, for FSR::Listener::Inbound" do
|
8
|
+
bridge = FSR::App::Bridge.new("user/bougyman")
|
9
|
+
bridge.raw.should == "bridge({}user/bougyman)"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Bridges a call, for FSR::Listener::Outbound" do
|
13
|
+
bridge = FSR::App::Bridge.new("user/bougyman")
|
14
|
+
bridge.sendmsg.should == "call-command: execute\nexecute-app-name: bridge\nexecute-app-arg: user/bougyman\n\n"
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("conference")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Conference" do
|
6
|
+
# Utilize the [] shortcut to start a conference
|
7
|
+
it "Executes a conference using Conference[conf_spec]" do
|
8
|
+
conf = FSR::App::Conference["5290-192.168.6.30"]
|
9
|
+
conf.should == "conference(5290-192.168.6.30@ultrawideband)"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("fifo")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::Fifo" do
|
6
|
+
# Utilize the [] shortcut to start a conference
|
7
|
+
it "Puts a call into a queue, with #new" do
|
8
|
+
fifo = FSR::App::Fifo.new("myqueue", "in")
|
9
|
+
fifo.raw.should == "fifo(myqueue in)"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Puts a call into a queue, with <<" do
|
13
|
+
fifo = FSR::App::Fifo << "myqueue"
|
14
|
+
fifo.raw.should == "fifo(myqueue in)"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "Adds a consumer to a queue, with #new" do
|
18
|
+
fifo = FSR::App::Fifo.new("myqueue", "out")
|
19
|
+
fifo.raw.should == "fifo(myqueue out nowait)"
|
20
|
+
fifo = FSR::App::Fifo.new("myqueue", "out", :wait => true)
|
21
|
+
fifo.raw.should == "fifo(myqueue out wait)"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "Adds a consumer to a queue, with >>" do
|
25
|
+
fifo = FSR::App::Fifo >> "myqueue"
|
26
|
+
fifo.raw.should == "fifo(myqueue out wait)"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/fsr/cmd.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/cmd"
|
3
|
+
FSR::Cmd.load_command("originate")
|
4
|
+
|
5
|
+
describe "Testing FSR::Cmd::Originate" do
|
6
|
+
# Originate to an extension
|
7
|
+
it "Originates calls to extensions" do
|
8
|
+
originate = FSR::Cmd::Originate.new(nil, :target => "user/bougyman", :endpoint => "4000")
|
9
|
+
originate.raw.should == "originate {ignore_early_media=true,originate_timeout=30,origination_caller_id_name=FSR,origination_caller_id_number=8675309}user/bougyman 4000"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/cmd"
|
3
|
+
FSR::Cmd.load_command("sofia")
|
4
|
+
|
5
|
+
describe "Testing FSR::Cmd::Sofia" do
|
6
|
+
## Sofia ##
|
7
|
+
# Interface to sofia
|
8
|
+
it "FSR::Cmd::Sofia should interface to sofia" do
|
9
|
+
sofia = FSR::Cmd::Sofia.new
|
10
|
+
sofia.raw.should == "sofia"
|
11
|
+
end
|
12
|
+
|
13
|
+
## Sofia Status ##
|
14
|
+
it "FSR::Cmd::Sofia should allow status" do
|
15
|
+
sofia = FSR::Cmd::Sofia.new
|
16
|
+
status = sofia.status
|
17
|
+
status.raw.should == "sofia status"
|
18
|
+
end
|
19
|
+
# Sofia status profile internal
|
20
|
+
it "FSR::Cmd::Sofia should allow status profile internal" do
|
21
|
+
sofia = FSR::Cmd::Sofia.new
|
22
|
+
status = sofia.status(:status => 'profile', :name => 'internal')
|
23
|
+
status.raw.should == "sofia status profile internal"
|
24
|
+
end
|
25
|
+
# Sofia status gateway server
|
26
|
+
it "FSR::Cmd::Sofia should allow status gateway server" do
|
27
|
+
sofia = FSR::Cmd::Sofia.new
|
28
|
+
status = sofia.status(:status => 'gateway', :name => 'server')
|
29
|
+
status.raw.should == "sofia status gateway server"
|
30
|
+
end
|
31
|
+
|
32
|
+
## Sofia profile ##
|
33
|
+
it "FSR::Cmd::Sofia should allow profile" do
|
34
|
+
sofia = FSR::Cmd::Sofia.new
|
35
|
+
profile = sofia.profile
|
36
|
+
profile.raw.should == "sofia profile"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "FSR::Cmd::Sofia::Profile should allow raw string" do
|
40
|
+
sofia = FSR::Cmd::Sofia.new
|
41
|
+
profile = sofia.profile('internal stop')
|
42
|
+
profile.raw.should == "sofia profile internal stop"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "FSR::Cmd::Sofia::Profile should allow start" do
|
46
|
+
sofia = FSR::Cmd::Sofia.new
|
47
|
+
profile = sofia.profile.start('internal')
|
48
|
+
profile.raw.should == "sofia profile internal start"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "FSR::Cmd::Sofia::Profile should allow stop" do
|
52
|
+
sofia = FSR::Cmd::Sofia.new
|
53
|
+
profile = sofia.profile.stop('internal')
|
54
|
+
profile.raw.should == "sofia profile internal stop"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "FSR::Cmd::Sofia::Profile should allow restart" do
|
58
|
+
sofia = FSR::Cmd::Sofia.new
|
59
|
+
profile = sofia.profile.restart('internal')
|
60
|
+
profile.raw.should == "sofia profile internal restart"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "FSR::Cmd::Sofia::Profile should allow rescan" do
|
64
|
+
sofia = FSR::Cmd::Sofia.new
|
65
|
+
profile = sofia.profile.rescan('internal')
|
66
|
+
profile.raw.should == "sofia profile internal rescan"
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/cmd"
|
3
|
+
FSR::Cmd.load_command("sofia")
|
4
|
+
|
5
|
+
describe "FSR::Cmd::Sofia::Profile" do
|
6
|
+
|
7
|
+
## Sofia profile ##
|
8
|
+
it "should allow FSR::Cmd::Sofia.new.profile (no arguments) through Sofia instance" do
|
9
|
+
sofia = FSR::Cmd::Sofia.new
|
10
|
+
profile = sofia.profile
|
11
|
+
profile.raw.should == "sofia profile"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow raw string as an argument through Sofia instance" do
|
15
|
+
sofia = FSR::Cmd::Sofia.new
|
16
|
+
profile = sofia.profile('internal stop')
|
17
|
+
profile.raw.should == "sofia profile internal stop"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should start a profile by name through Sofia instance" do
|
21
|
+
sofia = FSR::Cmd::Sofia.new
|
22
|
+
profile = sofia.profile.start('internal')
|
23
|
+
profile.raw.should == "sofia profile internal start"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should stop a profile by name through Sofia instance" do
|
27
|
+
sofia = FSR::Cmd::Sofia.new
|
28
|
+
profile = sofia.profile.stop('internal')
|
29
|
+
profile.raw.should == "sofia profile internal stop"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should restart a profile by name through Sofia instance" do
|
33
|
+
sofia = FSR::Cmd::Sofia.new
|
34
|
+
profile = sofia.profile.restart('internal')
|
35
|
+
profile.raw.should == "sofia profile internal restart"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should rescan a profile by name through Sofia instance" do
|
39
|
+
sofia = FSR::Cmd::Sofia.new
|
40
|
+
profile = sofia.profile.rescan('internal')
|
41
|
+
profile.raw.should == "sofia profile internal rescan"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should start, stop, rescan, restart a profile by name with a class method" do
|
45
|
+
# pass nil as the socket until we get the MockSocket completed
|
46
|
+
FSR::Cmd::Sofia::Profile.start("foo", nil).raw.should == "sofia profile foo start"
|
47
|
+
FSR::Cmd::Sofia::Profile.stop("foo", nil).raw.should == "sofia profile foo stop"
|
48
|
+
FSR::Cmd::Sofia::Profile.restart("foo", nil).raw.should == "sofia profile foo restart"
|
49
|
+
FSR::Cmd::Sofia::Profile.rescan("foo", nil).raw.should == "sofia profile foo rescan"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should allow instantiation directly, with hash options" do
|
53
|
+
# pass nil as the socket until we get the MockSocket completed
|
54
|
+
profile = FSR::Cmd::Sofia::Profile.new(nil, {:name => 'internal', :action => :stop})
|
55
|
+
profile.raw.should == "sofia profile internal stop"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "spec/helper"
|
2
|
+
require "fsr/listener"
|
3
|
+
describe "Basic FSR::Listener module" do
|
4
|
+
it "Aliases itself as FSL" do
|
5
|
+
FSL.should == FSR::Listener
|
6
|
+
end
|
7
|
+
|
8
|
+
it "Defines #receive_data" do
|
9
|
+
FSR::Listener.method_defined?(:receive_data).should == true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/listener/inbound"
|
3
|
+
|
4
|
+
# Bare class to use for testing
|
5
|
+
class MyListener < FSR::Listener::Inbound
|
6
|
+
end
|
7
|
+
|
8
|
+
# helper to instantiate a new MyListener
|
9
|
+
def my_listener
|
10
|
+
MyListener.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Testing FSR::Listener::Inbound" do
|
14
|
+
|
15
|
+
it "defines #post_init" do
|
16
|
+
FSR::Listener::Inbound.method_defined?(:post_init).should == true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/listener/outbound"
|
3
|
+
|
4
|
+
# Bare class to use for testing
|
5
|
+
class MyListener < FSR::Listener::Outbound
|
6
|
+
end
|
7
|
+
|
8
|
+
# helper to instantiate a new MyListener
|
9
|
+
def my_listener
|
10
|
+
MyListener.new
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "Testing FSR::Listener::Outbound" do
|
14
|
+
|
15
|
+
it "defines #post_init" do
|
16
|
+
FSR::Listener::Outbound.method_defined?(:post_init).should == true
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|