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.
Files changed (60) hide show
  1. data/License.txt +20 -0
  2. data/NEWS +3 -0
  3. data/README +85 -0
  4. data/Rakefile +82 -0
  5. data/bin/cmd_demo.rb +19 -0
  6. data/bin/ies_demo.rb +19 -0
  7. data/bin/ies_demo_with_hook.rb +27 -0
  8. data/bin/oes_demo.rb +22 -0
  9. data/lib/fsr.rb +86 -0
  10. data/lib/fsr/app.rb +72 -0
  11. data/lib/fsr/app/answer.rb +21 -0
  12. data/lib/fsr/app/bridge.rb +33 -0
  13. data/lib/fsr/app/conference.rb +29 -0
  14. data/lib/fsr/app/fifo.rb +38 -0
  15. data/lib/fsr/app/fs_break.rb +21 -0
  16. data/lib/fsr/app/fs_sleep.rb +24 -0
  17. data/lib/fsr/app/hangup.rb +22 -0
  18. data/lib/fsr/app/log.rb +24 -0
  19. data/lib/fsr/app/playback.rb +23 -0
  20. data/lib/fsr/app/set.rb +22 -0
  21. data/lib/fsr/app/speak.rb +25 -0
  22. data/lib/fsr/app/transfer.rb +24 -0
  23. data/lib/fsr/cmd.rb +57 -0
  24. data/lib/fsr/cmd/fsctl.rb +41 -0
  25. data/lib/fsr/cmd/originate.rb +46 -0
  26. data/lib/fsr/cmd/sofia.rb +40 -0
  27. data/lib/fsr/cmd/sofia/profile.rb +75 -0
  28. data/lib/fsr/cmd/sofia/status.rb +39 -0
  29. data/lib/fsr/cmd/sofia_contact.rb +31 -0
  30. data/lib/fsr/cmd/status.rb +25 -0
  31. data/lib/fsr/command_socket.rb +29 -0
  32. data/lib/fsr/database.rb +7 -0
  33. data/lib/fsr/database/call_limit.rb +21 -0
  34. data/lib/fsr/database/core.rb +30 -0
  35. data/lib/fsr/database/sofia_reg_external.rb +0 -0
  36. data/lib/fsr/database/sofia_reg_internal.rb +0 -0
  37. data/lib/fsr/database/voicemail_default.rb +0 -0
  38. data/lib/fsr/event_socket.rb +41 -0
  39. data/lib/fsr/fake_socket.rb +68 -0
  40. data/lib/fsr/listener.rb +10 -0
  41. data/lib/fsr/listener/header_and_content_response.rb +21 -0
  42. data/lib/fsr/listener/inbound.rb +61 -0
  43. data/lib/fsr/listener/inbound/event.rb +42 -0
  44. data/lib/fsr/listener/outbound.rb +62 -0
  45. data/spec/fsr/app.rb +8 -0
  46. data/spec/fsr/app/bridge.rb +17 -0
  47. data/spec/fsr/app/conference.rb +12 -0
  48. data/spec/fsr/app/fifo.rb +29 -0
  49. data/spec/fsr/cmd.rb +8 -0
  50. data/spec/fsr/cmd/originate.rb +12 -0
  51. data/spec/fsr/cmd/sofia.rb +69 -0
  52. data/spec/fsr/cmd/sofia/profile.rb +58 -0
  53. data/spec/fsr/listener.rb +12 -0
  54. data/spec/fsr/listener/inbound.rb +19 -0
  55. data/spec/fsr/listener/outbound.rb +19 -0
  56. data/spec/fsr/loading.rb +27 -0
  57. data/spec/helper.rb +14 -0
  58. data/tasks/package.rake +29 -0
  59. data/tasks/spec.rake +59 -0
  60. 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
@@ -0,0 +1,8 @@
1
+ require "spec/helper"
2
+ describe "Basic FSR::App module" do
3
+ it "Aliases itself as FSA" do
4
+ require "fsr/app"
5
+ FSA.should == FSR::App
6
+ end
7
+ end
8
+
@@ -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
@@ -0,0 +1,8 @@
1
+ require "spec/helper"
2
+ describe "Basic FSR::Cmd module" do
3
+ it "Aliases itself as FSC" do
4
+ require "fsr/cmd"
5
+ FSC.should == FSR::Cmd
6
+ end
7
+ end
8
+
@@ -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