bougyman-freeswitcher 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|