FreeSWITCHeR 0.0.8

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