librevox 0.9 → 1.0.0.alpha2

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.
@@ -1,52 +0,0 @@
1
- require 'eventmachine'
2
- require 'em/protocols/header_and_content'
3
-
4
- class String
5
- alias :each :each_line
6
- end
7
-
8
- module Librevox
9
- class Response
10
- attr_accessor :headers, :content
11
-
12
- def initialize headers="", content=""
13
- self.headers = headers
14
- self.content = content
15
- end
16
-
17
- def headers= headers
18
- @headers = headers_2_hash(headers)
19
- @headers.each {|k,v| v.chomp! if v.is_a?(String)}
20
- end
21
-
22
- def content= content
23
- @content = if content.respond_to?(:match) && content.match(/:/)
24
- headers_2_hash(content).merge(:body => content.split("\n\n", 2)[1].to_s)
25
- else
26
- content
27
- end
28
- @content.each {|k,v| v.chomp! if v.is_a?(String)}
29
- end
30
-
31
- def event?
32
- @content.is_a?(Hash) && @content.include?(:event_name)
33
- end
34
-
35
- def event
36
- @content[:event_name] if event?
37
- end
38
-
39
- def api_response?
40
- @headers[:content_type] == "api/response"
41
- end
42
-
43
- def command_reply?
44
- @headers[:content_type] == "command/reply"
45
- end
46
-
47
- private
48
- def headers_2_hash *args
49
- EM::Protocols::HeaderAndContentProtocol.headers_2_hash *args
50
- end
51
- end
52
- end
data/librevox.gemspec DELETED
@@ -1,37 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.name = "librevox"
3
- s.version = "0.9"
4
- s.date = "2014-04-03"
5
- s.summary = "Ruby library for interacting with FreeSWITCH."
6
- s.email = "harry@vangberg.name"
7
- s.homepage = "http://github.com/vangberg/librevox"
8
- s.description = "EventMachine-based Ruby library for interacting with the
9
- open source telephony platform FreeSwitch."
10
- s.authors = ["Harry Vangberg"]
11
- s.files = [
12
- "README.md",
13
- "LICENSE",
14
- "TODO",
15
- "Rakefile",
16
- "librevox.gemspec",
17
- "lib/librevox.rb",
18
- "lib/librevox/applications.rb",
19
- "lib/librevox/command_socket.rb",
20
- "lib/librevox/commands.rb",
21
- "lib/librevox/response.rb",
22
- "lib/librevox/listener/base.rb",
23
- "lib/librevox/listener/inbound.rb",
24
- "lib/librevox/listener/outbound.rb"
25
- ]
26
- s.test_files = [
27
- "spec/helper.rb",
28
- "spec/librevox/listener.rb",
29
- "spec/librevox/spec_applications.rb",
30
- #"spec/librevox/spec_command_socket.rb",
31
- "spec/librevox/spec_commands.rb",
32
- "spec/librevox/spec_response.rb",
33
- "spec/librevox/listener/spec_inbound.rb",
34
- "spec/librevox/listener/spec_outbound.rb"
35
- ]
36
- s.add_dependency "eventmachine", "~> 1.0"
37
- end
data/spec/helper.rb DELETED
@@ -1,86 +0,0 @@
1
- require 'bacon'
2
- require 'librevox'
3
-
4
- module Librevox::Test
5
- module Matchers
6
- def send_command command
7
- proc {|obj|
8
- obj.outgoing_data.shift.should == "#{command}\n\n"
9
- }
10
- end
11
-
12
- def send_nothing
13
- proc {|obj| obj.outgoing_data.shift.should == nil}
14
- end
15
-
16
- def send_application app, args=nil
17
- proc {|obj|
18
- msg = <<-EOM
19
- sendmsg
20
- call-command: execute
21
- execute-app-name: #{app}
22
- EOM
23
- msg << "execute-app-arg: #{args}\n" if args
24
- msg << "\n"
25
-
26
- obj.outgoing_data.shift.should == msg
27
- }
28
- end
29
-
30
- def update_session session_id=nil
31
- if session_id
32
- proc {|obj|
33
- obj.outgoing_data.shift.should == "api uuid_dump #{session_id}\n\n"
34
- }
35
- else
36
- proc {|obj|
37
- obj.outgoing_data.shift.should.match /^api uuid_dump \d+/
38
- }
39
- end
40
- end
41
- end
42
-
43
- module ListenerHelpers
44
- def command_reply args={}
45
- args["Content-Type"] = "command/reply"
46
- response args
47
- end
48
-
49
- def api_response args={}
50
- args["Content-Type"] = "api/response"
51
- response args
52
- end
53
-
54
- def channel_data args={}
55
- api_response :body => {
56
- "Event-Name" => "CHANNEL_DATA",
57
- "Session-Var" => "Second"
58
- }.merge(args)
59
- end
60
-
61
- def response args={}
62
- body = args.delete :body
63
- headers = args
64
-
65
- if body.is_a? Hash
66
- body = body.map {|k,v| "#{k}: #{v}"}.join "\n"
67
- end
68
-
69
- headers["Content-Length"] = body.size if body
70
- msg = headers.map {|k, v| "#{k}: #{v}"}.join "\n"
71
-
72
- msg << "\n\n" + body if body
73
-
74
- @listener.receive_data msg + "\n\n"
75
- end
76
-
77
- def event name
78
- body = "Event-Name: #{name}"
79
- headers = "Content-Length: #{body.size}"
80
-
81
- @listener.receive_data "#{headers}\n\n#{body}\n\n"
82
- end
83
- end
84
- end
85
-
86
- Bacon.summary_on_exit
@@ -1,22 +0,0 @@
1
- require './spec/helper'
2
- require './spec/librevox/listener'
3
-
4
- require 'librevox/listener/inbound'
5
-
6
- class InboundTestListener < Librevox::Listener::Inbound
7
- end
8
-
9
- describe "Inbound listener" do
10
- before do
11
- @listener = InboundTestListener.new(nil)
12
- end
13
-
14
- behaves_like "events"
15
- behaves_like "api commands"
16
-
17
- should "authorize and subscribe to events" do
18
- @listener.connection_completed
19
- @listener.outgoing_data.shift.should == "auth ClueCon\n\n"
20
- @listener.outgoing_data.shift.should == "event plain ALL\n\n"
21
- end
22
- end
@@ -1,300 +0,0 @@
1
- require './spec/helper'
2
- require './spec/librevox/listener'
3
-
4
- require 'librevox/listener/outbound'
5
-
6
- module Librevox::Applications
7
- def sample_app name, *args, &block
8
- application name, args.join(" "), &block
9
- end
10
- end
11
-
12
- class OutboundTestListener < Librevox::Listener::Outbound
13
- def session_initiated
14
- send_data "session was initiated"
15
- end
16
- end
17
-
18
- def event_and_linger_replies
19
- command_reply "Reply-Text" => "+OK Events Enabled"
20
- command_reply "Reply-Text" => "+OK will linger"
21
- end
22
-
23
- describe "Outbound listener" do
24
- extend Librevox::Test::Matchers
25
-
26
- before do
27
- @listener = OutboundTestListener.new(nil)
28
- command_reply(
29
- "Caller-Caller-Id-Number" => "8675309",
30
- "Unique-ID" => "1234",
31
- "variable_some_var" => "some value"
32
- )
33
- event_and_linger_replies
34
- end
35
-
36
- should "connect to freeswitch and subscribe to events" do
37
- @listener.should send_command "connect"
38
- @listener.should send_command "myevents"
39
- @listener.should send_command "linger"
40
- end
41
-
42
- should "establish a session" do
43
- @listener.session.class.should.equal Hash
44
- end
45
-
46
- should "call session callback after establishing new session" do
47
- @listener.outgoing_data.pop.should == "session was initiated"
48
- end
49
-
50
- should "make headers available through session" do
51
- @listener.session[:caller_caller_id_number].should.equal "8675309"
52
- end
53
-
54
- should "make channel variables available through #variable" do
55
- @listener.variable(:some_var).should == "some value"
56
- end
57
-
58
- behaves_like "events"
59
- behaves_like "api commands"
60
- end
61
-
62
- class OutboundListenerWithNestedApps < Librevox::Listener::Outbound
63
- def session_initiated
64
- sample_app "foo" do
65
- sample_app "bar"
66
- end
67
- end
68
- end
69
-
70
- describe "Outbound listener with apps" do
71
- extend Librevox::Test::Matchers
72
-
73
- before do
74
- @listener = OutboundListenerWithNestedApps.new(nil)
75
-
76
- command_reply "Establish-Session" => "OK",
77
- "Unique-ID" => "1234"
78
- event_and_linger_replies
79
- 3.times {@listener.outgoing_data.shift}
80
- end
81
-
82
- should "only send one app at a time" do
83
- @listener.should send_application "foo"
84
- @listener.should send_nothing
85
-
86
- command_reply "Reply-Text" => "+OK"
87
- @listener.should update_session
88
- channel_data
89
-
90
- @listener.should send_application "bar"
91
- @listener.should send_nothing
92
- end
93
-
94
- should "not be driven forward by events" do
95
- @listener.should send_application "foo"
96
-
97
- command_reply :body => {
98
- "Event-Name" => "CHANNEL_EXECUTE",
99
- "Session-Var" => "Some"
100
- }
101
-
102
- @listener.should send_nothing
103
- end
104
-
105
- should "not be driven forward by api responses" do
106
- @listener.should send_application "foo"
107
-
108
- api_response :body => "Foo"
109
-
110
- @listener.should send_nothing
111
- end
112
-
113
- should "not be driven forward by disconnect notifications" do
114
- @listener.should send_application "foo"
115
-
116
- response "Content-Type" => "text/disconnect-notice",
117
- :body => "Lingering"
118
-
119
- @listener.should send_nothing
120
- end
121
- end
122
-
123
- module Librevox::Applications
124
- def reader_app &block
125
- application 'reader_app', "", {:variable => 'app_var'}, &block
126
- end
127
- end
128
-
129
- class OutboundListenerWithReader < Librevox::Listener::Outbound
130
- def session_initiated
131
- reader_app do |data|
132
- application "send", data
133
- end
134
- end
135
- end
136
-
137
- describe "Outbound listener with app reading data" do
138
- extend Librevox::Test::Matchers
139
-
140
- before do
141
- @listener = OutboundListenerWithReader.new(nil)
142
-
143
- command_reply "Session-Var" => "First",
144
- "Unique-ID" => "1234"
145
- event_and_linger_replies
146
- 3.times {@listener.outgoing_data.shift}
147
-
148
- @listener.should send_application "reader_app"
149
- end
150
-
151
- should "not send anything while missing response" do
152
- @listener.should send_nothing
153
- end
154
-
155
- should "send uuid_dump to get channel var, after getting response" do
156
- command_reply "Reply-Text" => "+OK"
157
- @listener.should update_session 1234
158
- end
159
-
160
- should "update session with new data" do
161
- command_reply :body => "+OK"
162
-
163
- @listener.should update_session 1234
164
- api_response :body => {
165
- "Event-Name" => "CHANNEL_DATA",
166
- "Session-Var" => "Second"
167
- }
168
-
169
- @listener.session[:session_var].should == "Second"
170
- end
171
-
172
- should "return value of channel variable" do
173
- command_reply :body => "+OK"
174
-
175
- @listener.should update_session 1234
176
- api_response :body => {
177
- "Event-Name" => "CHANNEL_DATA",
178
- "variable_app_var" => "Second"
179
- }
180
-
181
- @listener.should send_application "send", "Second"
182
- end
183
- end
184
-
185
- class OutboundListenerWithNonNestedApps < Librevox::Listener::Outbound
186
- attr_reader :queue
187
- def session_initiated
188
- sample_app "foo" do
189
- reader_app do |data|
190
- application "send", "the end: #{data}"
191
- end
192
- end
193
- end
194
- end
195
-
196
- describe "Outbound listener with non-nested apps" do
197
- extend Librevox::Test::Matchers
198
-
199
- before do
200
- @listener = OutboundListenerWithNonNestedApps.new(nil)
201
-
202
- command_reply "Session-Var" => "First",
203
- "Unique-ID" => "1234"
204
- event_and_linger_replies
205
- 3.times {@listener.outgoing_data.shift}
206
- end
207
-
208
- should "wait for response before calling next app" do
209
- @listener.should send_application "foo"
210
- command_reply :body => "+OK"
211
- @listener.should update_session
212
- channel_data "Unique-ID" => "1234"
213
-
214
- @listener.should send_application "reader_app"
215
- command_reply :body => "+OK"
216
-
217
- @listener.should update_session
218
- api_response :body => {
219
- "Event-Name" => "CHANNEL_DATA",
220
- "variable_app_var" => "Second"
221
- }
222
-
223
- @listener.should send_application "send", "the end: Second"
224
- end
225
- end
226
-
227
- module Librevox::Commands
228
- def sample_cmd cmd, *args, &block
229
- command cmd, *args, &block
230
- end
231
- end
232
-
233
- class OutboundListenerWithAppsAndApi < Librevox::Listener::Outbound
234
- def session_initiated
235
- sample_app "foo" do
236
- api.sample_cmd "bar" do
237
- sample_app "baz"
238
- end
239
- end
240
- end
241
- end
242
-
243
- describe "Outbound listener with both apps and api calls" do
244
- extend Librevox::Test::Matchers
245
-
246
- before do
247
- @listener = OutboundListenerWithAppsAndApi.new(nil)
248
-
249
- command_reply "Session-Var" => "First",
250
- "Unique-ID" => "1234"
251
- event_and_linger_replies
252
- 3.times {@listener.outgoing_data.shift}
253
- end
254
-
255
- should "wait for response before calling next app/cmd" do
256
- @listener.should send_application "foo"
257
- command_reply :body => "+OK"
258
- @listener.should update_session
259
- channel_data
260
-
261
- @listener.should send_command "api bar"
262
- api_response :body => "+OK"
263
-
264
- @listener.should send_application "baz"
265
- end
266
- end
267
-
268
- class OutboundListenerWithUpdateSessionCallback < Librevox::Listener::Outbound
269
- def session_initiated
270
- update_session do
271
- application "send", "yay, #{session[:session_var]}"
272
- end
273
- end
274
- end
275
-
276
- describe "Outbound listener with update session callback" do
277
- extend Librevox::Test::Matchers
278
-
279
- before do
280
- @listener = OutboundListenerWithUpdateSessionCallback.new(nil)
281
- command_reply "Session-Var" => "First",
282
- "Unique-ID" => "1234"
283
- event_and_linger_replies
284
- 3.times {@listener.outgoing_data.shift}
285
-
286
- @listener.should update_session
287
- api_response :body => {
288
- "Event-Name" => "CHANNEL_DATA",
289
- "Session-Var" => "Second"
290
- }
291
- end
292
-
293
- should "execute callback" do
294
- @listener.outgoing_data.shift.should =~ /yay,/
295
- end
296
-
297
- should "update session before calling callback" do
298
- @listener.should send_application "send", "yay, Second"
299
- end
300
- end
@@ -1,142 +0,0 @@
1
- require './spec/helper'
2
- require 'librevox/listener/base'
3
-
4
- include Librevox::Test::ListenerHelpers
5
-
6
- class Librevox::Listener::Base
7
- attr_accessor :outgoing_data
8
-
9
- def initialize(*args)
10
- @outgoing_data = []
11
- super *args
12
- end
13
-
14
- def send_data(data)
15
- @outgoing_data << data
16
- end
17
-
18
- def read_data
19
- @outgoing_data.pop
20
- end
21
- end
22
-
23
- # These tests are a bit fragile, as they depend on event hooks being
24
- # executed before on_event.
25
- shared "events" do
26
- before do
27
- @class = @listener.class
28
-
29
- @class.event(:some_event) {send_data "something"}
30
- @class.event(:other_event) {send_data "something else"}
31
- @class.event(:hook_with_arg) {|e| send_data "got event arg: #{e.object_id}"}
32
-
33
- def @listener.on_event(e)
34
- send_data "from on_event: #{e.object_id}"
35
- end
36
-
37
- # Establish session
38
- @listener.receive_data("Content-Length: 0\nTest: Testing\n\n")
39
- end
40
-
41
- should "add event hook" do
42
- @class.hooks.size.should == 3
43
- @class.hooks.each do |event, hooks|
44
- hooks.size.should == 1
45
- end
46
- end
47
-
48
- should "execute callback for event" do
49
- event "OTHER_EVENT"
50
- @listener.read_data.should == "something else"
51
-
52
- event "SOME_EVENT"
53
- @listener.read_data.should == "something"
54
- end
55
-
56
- should "pass response duplicate as arg to hook block" do
57
- event "HOOK_WITH_ARG"
58
-
59
- reply = @listener.read_data
60
- reply.should =~ /^got event arg: /
61
- reply.should.not =~ /^got event arg: #{@listener.response.object_id}$/
62
- end
63
-
64
- should "expose response as event" do
65
- event "OTHER_EVENT"
66
-
67
- @listener.event.class.should == Librevox::Response
68
- @listener.event.content[:event_name].should == "OTHER_EVENT"
69
- end
70
-
71
- should "call on_event" do
72
- event "THIRD_EVENT"
73
-
74
- @listener.read_data.should =~ /^from on_event/
75
- end
76
-
77
- should "call on_event with response duplicate as argument" do
78
- event "THIRD_EVENT"
79
-
80
- @listener.read_data.should.not =~ /^from on_event: #{@listener.response.object_id}$/
81
- end
82
-
83
- should "call event hooks and on_event on CHANNEL_DATA" do
84
- @listener.outgoing_data.clear
85
-
86
- def @listener.on_event e
87
- send_data "on_event: CHANNEL_DATA test"
88
- end
89
- @class.event(:channel_data) {send_data "event hook: CHANNEL_DATA test"}
90
-
91
- event "CHANNEL_DATA"
92
-
93
- @listener.outgoing_data.should.include "on_event: CHANNEL_DATA test"
94
- @listener.outgoing_data.should.include "event hook: CHANNEL_DATA test"
95
- end
96
- end
97
-
98
- module Librevox::Commands
99
- def sample_cmd cmd, args="", &block
100
- command cmd, args, &block
101
- end
102
- end
103
-
104
- shared "api commands" do
105
- before do
106
- @class = @listener.class
107
-
108
- # Establish session
109
- command_reply "Test" => "Testing"
110
- end
111
-
112
- describe "multiple api commands" do
113
- extend Librevox::Test::Matchers
114
-
115
- before do
116
- @listener.outgoing_data.clear
117
-
118
- def @listener.on_event(e) end # Don't send anything, kthx.
119
-
120
- @class.event(:api_test) {
121
- api.sample_cmd "foo" do
122
- api.sample_cmd "foo", "bar baz" do |r|
123
- command "response #{r.content}"
124
- end
125
- end
126
- }
127
- end
128
-
129
- should "only send one command at a time, and return response for commands" do
130
- command_reply :body => {"Event-Name" => "API_TEST"}
131
- @listener.should send_command "api foo"
132
- @listener.should send_nothing
133
-
134
- api_response "Reply-Text" => "+OK"
135
- @listener.should send_command "api foo bar baz"
136
- @listener.should send_nothing
137
-
138
- api_response :body => "+YAY"
139
- @listener.should send_command "response +YAY"
140
- end
141
- end
142
- end