freeswitcher 0.1.4 → 0.3.0
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/AUTHORS +4 -3
- data/CHANGELOG +123 -0
- data/MANIFEST +3 -9
- data/README +57 -60
- data/Rakefile +4 -4
- data/examples/outbound_event_socket.rb +2 -5
- data/freeswitcher.gemspec +62 -65
- data/lib/fsr/app.rb +1 -3
- data/lib/fsr/app/answer.rb +2 -0
- data/lib/fsr/app/play_and_get_digits.rb +11 -1
- data/lib/fsr/app/read.rb +12 -2
- data/lib/fsr/app/uuid_getvar.rb +13 -2
- data/lib/fsr/app/uuid_setvar.rb +11 -1
- data/lib/fsr/cmd.rb +22 -4
- data/lib/fsr/cmd/originate.rb +23 -6
- data/lib/fsr/command_socket.rb +1 -1
- data/lib/fsr/listener/inbound.rb +19 -10
- data/lib/fsr/listener/outbound.rb +75 -18
- data/lib/fsr/version.rb +1 -1
- data/spec/fsr/app/answer.rb +12 -0
- data/spec/fsr/app/fs_break.rb +12 -0
- data/spec/fsr/app/fs_sleep.rb +12 -0
- data/spec/fsr/cmd/originate.rb +32 -0
- metadata +63 -84
- data/lib/fsr/listener/outbound.rb.orig +0 -131
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("fs_break")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::FsBreak" do
|
6
|
+
|
7
|
+
it "should break a connection" do
|
8
|
+
fs_break = FSR::App::FSBreak.new
|
9
|
+
fs_break.sendmsg.should == "call-command: execute\nexecute-app-name: break\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec/helper'
|
2
|
+
require "fsr/app"
|
3
|
+
FSR::App.load_application("fs_sleep")
|
4
|
+
|
5
|
+
describe "Testing FSR::App::FsSleep" do
|
6
|
+
|
7
|
+
it "should put FreeSWITCH leg to sleep for 7000 miliseconds" do
|
8
|
+
fs_sleep = FSR::App::FSSleep.new(7000)
|
9
|
+
fs_sleep.sendmsg.should == "call-command: execute\nexecute-app-name: sleep\nexecute-app-arg: 7000\n\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
data/spec/fsr/cmd/originate.rb
CHANGED
@@ -3,10 +3,42 @@ require "fsr/cmd"
|
|
3
3
|
FSR::Cmd.load_command("originate")
|
4
4
|
|
5
5
|
describe "Testing FSR::Cmd::Originate" do
|
6
|
+
# Invalid originates
|
7
|
+
it "Must be passed an argument hash" do
|
8
|
+
lambda { FSR::Cmd::Originate.new(nil, :endpoint) }.should.raise(ArgumentError).
|
9
|
+
message.should.match(/args \(Passed: <<<.*?>>>\) must be a hash/)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "Should require args[:target_options] to be a hash" do
|
13
|
+
lambda { FSR::Cmd::Originate.new(nil, :endpoint => "4000", :target => "user/bougyman", :target_options => 1) }.should.raise(ArgumentError).
|
14
|
+
message.should.match(/args\[:target_options\] \(Passed: <<<.*?>>>\) must be a hash/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "Can not originate without a target" do
|
18
|
+
lambda { FSR::Cmd::Originate.new(nil, :endpoint => "4000") }.should.raise(ArgumentError).
|
19
|
+
message.should.match(/Cannot originate without a :target set/)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "Can not originate without an endpoint" do
|
23
|
+
lambda { FSR::Cmd::Originate.new(nil, :target => "4000") }.should.raise(ArgumentError).
|
24
|
+
message.should.match(/Cannot originate without an :endpoint set/)
|
25
|
+
end
|
26
|
+
|
6
27
|
# Originate to an extension
|
7
28
|
it "Originates calls to extensions" do
|
8
29
|
originate = FSR::Cmd::Originate.new(nil, :target => "user/bougyman", :endpoint => "4000")
|
9
30
|
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
31
|
end
|
11
32
|
|
33
|
+
# Different options choices
|
34
|
+
it "Honors timeout in :timeout option" do
|
35
|
+
originate = FSR::Cmd::Originate.new(nil, :target => "user/bougyman", :timeout => 10, :endpoint => "4000")
|
36
|
+
originate.raw.should == "originate {ignore_early_media=true,originate_timeout=10,origination_caller_id_name=FSR,origination_caller_id_number=8675309}user/bougyman 4000"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Honors timeout in :target_options[timeout] option" do
|
40
|
+
originate = FSR::Cmd::Originate.new(nil, :target => "user/bougyman", :target_options => {:timeout => 10}, :endpoint => "4000")
|
41
|
+
originate.raw.should == "originate {ignore_early_media=true,originate_timeout=10,origination_caller_id_name=FSR,origination_caller_id_number=8675309}user/bougyman 4000"
|
42
|
+
end
|
43
|
+
|
12
44
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: freeswitcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jayson Vaughn
|
@@ -12,7 +12,7 @@ autorequire:
|
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
14
|
|
15
|
-
date: 2009-05-
|
15
|
+
date: 2009-05-18 00:00:00 -05:00
|
16
16
|
default_executable:
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: "0"
|
27
27
|
version:
|
28
|
-
description: "========================================================= FreeSWITCHeR Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry) Distributed under the terms of the MIT License. ========================================================== ABOUT ----- A ruby library for interacting with the \"FreeSWITCH\" (http://www.freeswitch.org) opensource telephony platform REQUIREMENTS ------------
|
28
|
+
description: "========================================================= FreeSWITCHeR Copyright (c) 2009 The Rubyists (Jayson Vaughn, Tj Vanderpoel, Michael Fellinger, Kevin Berry) Distributed under the terms of the MIT License. ========================================================== ABOUT ----- A ruby library for interacting with the \"FreeSWITCH\" (http://www.freeswitch.org) opensource telephony platform REQUIREMENTS ------------ * ruby (>= 1.8) * eventmachine (If you wish to use Outbound and Inbound listener) USAGE ----- An Outbound Event Listener Example that reads and returns DTMF input: -------------------------------------------------------------------- Simply just create a subclass of FSR::Listner::Outbound and all new calls/sessions will invoke the \"session_initiated\" callback method. <b>NOTE</b>: FSR uses blocks within the 'session_inititated' method to ensure that the next \"freeswich command\" is not executed until the previous \"Freeswitch command\" has finished. This is kicked off by \"answer do\" #!/usr/bin/ruby require 'fsr' require 'fsr/listener/outbound' class OutboundDemo < FSR::Listener::Outbound def session_initiated exten = @session.headers[:caller_caller_id_number] FSR::Log.info \"*** Answering incoming call from #{exten}\" answer do FSR::Log.info \"***Reading DTMF from #{exten}\" read(\"/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav\", 4, 10, \"input\", 7000) do |read_var| FSR::Log.info \"***Success, grabbed #{read_var.strip} from #{exten}\" hangup #Hangup the call end end end end FSR.start_oes! OutboundDemo, :port => 8084, :host => \"127.0.0.1\" An Inbound Event Socket Listener example using FreeSWITCHeR's hook system: -------------------------------------------------------------------------- #!/usr/bin/ruby require 'pp' require 'fsr' require \"fsr/listener/inbound\" # EXAMPLE 1 # This adds a hook on CHANNEL_CREATE events. You can also create a method to handle the event you're after. See the next example FSL::Inbound.add_event_hook(:CHANNEL_CREATE) {|event| FSR::Log.info \"*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!\" } # EXAMPLE 2 # Define a method to handle CHANNEL_HANGUP events. def custom_channel_hangup_handler(event) FSR::Log.info \"*** [#{event.content[:unique_id]}] Channel hangup. The event:\" pp event end # This adds a hook for EXAMPLE 2 FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) {|event| custom_channel_hangup_handler(event) } # Start FSR Inbound Listener FSR.start_ies!(FSL::Inbound, :host => \"localhost\", :port => 8021) An Inbound Event Socket Listener example using the on_event callback method instead of hooks: --------------------------------------------------------------------------------------------- #!/usr/bin/ruby require 'pp' require 'fsr' require \"fsr/listener/inbound\" class IesDemo < FSR::Listener::Inbound def on_event(event) pp event.headers pp event.content[:event_name] end end FSR.start_ies!(IesDemo, :host => \"localhost\", :port => 8021) An example of using FSR::CommandSocket to originate a new call in irb: ---------------------------------------------------------------------- irb(main):001:0> require 'fsr' => true irb(main):002:0> FSR.load_all_commands => [:sofia, :originate] irb(main):003:0> sock = FSR::CommandSocket.new => #<FSR::CommandSocket:0xb7a89104 @server=\"127.0.0.1\", @socket=#<TCPSocket:0xb7a8908c>, @port=\"8021\", @auth=\"ClueCon\"> irb(main):007:0> sock.originate(:target => 'sofia/gateway/carlos/8179395222', :endpoint => FSR::App::Bridge.new(\"user/bougyman\")).run => {\"Job-UUID\"=>\"732075a4-7dd5-4258-b124-6284a82a5ae7\", \"body\"=>\"\", \"Content-Type\"=>\"command/reply\", \"Reply-Text\"=>\"+OK Job-UUID: 732075a4-7dd5-4258-b124-6284a82a5ae7\"} SUPPORT ------- Home page at http://code.rubyists.com/projects/fs #rubyists on FreeNode"
|
29
29
|
email: FreeSWITCHeR@rubyists.com
|
30
30
|
executables: []
|
31
31
|
|
@@ -89,7 +89,6 @@ files:
|
|
89
89
|
- lib/fsr/listener/inbound.rb
|
90
90
|
- lib/fsr/listener/inbound/event.rb
|
91
91
|
- lib/fsr/listener/outbound.rb
|
92
|
-
- lib/fsr/listener/outbound.rb.orig
|
93
92
|
- lib/fsr/model/call.rb
|
94
93
|
- lib/fsr/version.rb
|
95
94
|
- tasks/authors.rake
|
@@ -107,26 +106,6 @@ files:
|
|
107
106
|
- tasks/spec.rake
|
108
107
|
- tasks/yard.rake
|
109
108
|
- spec/helper.rb
|
110
|
-
- spec/fsr/app.rb
|
111
|
-
- spec/fsr/app/bridge.rb
|
112
|
-
- spec/fsr/app/conference.rb
|
113
|
-
- spec/fsr/app/fifo.rb
|
114
|
-
- spec/fsr/app/hangup.rb
|
115
|
-
- spec/fsr/app/limit.rb
|
116
|
-
- spec/fsr/app/log.rb
|
117
|
-
- spec/fsr/app/play_and_get_digits.rb
|
118
|
-
- spec/fsr/app/playback.rb
|
119
|
-
- spec/fsr/app/set.rb
|
120
|
-
- spec/fsr/app/transfer.rb
|
121
|
-
- spec/fsr/cmd.rb
|
122
|
-
- spec/fsr/cmd/calls.rb
|
123
|
-
- spec/fsr/cmd/originate.rb
|
124
|
-
- spec/fsr/cmd/sofia.rb
|
125
|
-
- spec/fsr/cmd/sofia/profile.rb
|
126
|
-
- spec/fsr/listener.rb
|
127
|
-
- spec/fsr/listener/inbound.rb
|
128
|
-
- spec/fsr/listener/outbound.rb
|
129
|
-
- spec/fsr/loading.rb
|
130
109
|
has_rdoc: false
|
131
110
|
homepage: http://code.rubyists.com/projects/fs
|
132
111
|
post_install_message: |
|
@@ -142,8 +121,8 @@ post_install_message: |
|
|
142
121
|
|
143
122
|
REQUIREMENTS
|
144
123
|
------------
|
145
|
-
|
146
|
-
|
124
|
+
* ruby (>= 1.8)
|
125
|
+
* eventmachine (If you wish to use Outbound and Inbound listener)
|
147
126
|
|
148
127
|
USAGE
|
149
128
|
-----
|
@@ -154,97 +133,94 @@ post_install_message: |
|
|
154
133
|
Simply just create a subclass of FSR::Listner::Outbound and all
|
155
134
|
new calls/sessions will invoke the "session_initiated" callback method.
|
156
135
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
require 'fsr/listener/outbound'
|
163
|
-
|
164
|
-
class OutboundDemo < FSR::Listener::Outbound
|
165
|
-
|
166
|
-
def session_initiated
|
167
|
-
exten = @session.headers[:caller_caller_id_number]
|
168
|
-
FSR::Log.info "*** Answering incoming call from #{exten}"
|
169
|
-
|
170
|
-
answer do
|
171
|
-
FSR::Log.info "***Reading DTMF from #{exten}"
|
172
|
-
read("/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav", 4, 10, "input", 7000) do
|
173
|
-
FSR::Log.info "*** Updating session for #{exten}"
|
174
|
-
update_session do
|
175
|
-
FSR::Log.info "***Success, grabbed #{@session.headers[:variable_input].strip} from #{exten}"
|
176
|
-
hangup #Hangup the call
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
136
|
+
<b>NOTE</b>: FSR uses blocks within the 'session_inititated' method to ensure that the next "freeswich command" is not executed until the previous "Freeswitch command" has finished. This is kicked off by "answer do"
|
137
|
+
|
138
|
+
#!/usr/bin/ruby
|
139
|
+
require 'fsr'
|
140
|
+
require 'fsr/listener/outbound'
|
180
141
|
|
142
|
+
class OutboundDemo < FSR::Listener::Outbound
|
143
|
+
|
144
|
+
def session_initiated
|
145
|
+
exten = @session.headers[:caller_caller_id_number]
|
146
|
+
FSR::Log.info "*** Answering incoming call from #{exten}"
|
147
|
+
|
148
|
+
answer do
|
149
|
+
FSR::Log.info "***Reading DTMF from #{exten}"
|
150
|
+
read("/home/freeswitch/freeswitch/sounds/music/8000/sweet.wav", 4, 10, "input", 7000) do |read_var|
|
151
|
+
FSR::Log.info "***Success, grabbed #{read_var.strip} from #{exten}"
|
152
|
+
hangup #Hangup the call
|
153
|
+
end
|
181
154
|
end
|
182
155
|
|
183
156
|
end
|
184
157
|
|
185
|
-
|
158
|
+
end
|
186
159
|
|
160
|
+
FSR.start_oes! OutboundDemo, :port => 8084, :host => "127.0.0.1"
|
187
161
|
|
188
162
|
An Inbound Event Socket Listener example using FreeSWITCHeR's hook system:
|
189
163
|
--------------------------------------------------------------------------
|
190
164
|
|
191
|
-
|
192
|
-
|
193
|
-
|
165
|
+
#!/usr/bin/ruby
|
166
|
+
require 'pp'
|
167
|
+
require 'fsr'
|
168
|
+
require "fsr/listener/inbound"
|
194
169
|
|
195
|
-
|
196
|
-
|
197
|
-
|
170
|
+
# EXAMPLE 1
|
171
|
+
# This adds a hook on CHANNEL_CREATE events. You can also create a method to handle the event you're after. See the next example
|
172
|
+
FSL::Inbound.add_event_hook(:CHANNEL_CREATE) {|event| FSR::Log.info "*** [#{event.content[:unique_id]}] Channel created - greetings from the hook!" }
|
198
173
|
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
174
|
+
# EXAMPLE 2
|
175
|
+
# Define a method to handle CHANNEL_HANGUP events.
|
176
|
+
def custom_channel_hangup_handler(event)
|
177
|
+
FSR::Log.info "*** [#{event.content[:unique_id]}] Channel hangup. The event:"
|
178
|
+
pp event
|
179
|
+
end
|
205
180
|
|
206
|
-
|
207
|
-
|
181
|
+
# This adds a hook for EXAMPLE 2
|
182
|
+
FSL::Inbound.add_event_hook(:CHANNEL_HANGUP) {|event| custom_channel_hangup_handler(event) }
|
208
183
|
|
209
184
|
|
210
|
-
|
211
|
-
|
185
|
+
# Start FSR Inbound Listener
|
186
|
+
FSR.start_ies!(FSL::Inbound, :host => "localhost", :port => 8021)
|
212
187
|
|
213
188
|
|
214
189
|
An Inbound Event Socket Listener example using the on_event callback method instead of hooks:
|
215
190
|
---------------------------------------------------------------------------------------------
|
216
191
|
|
217
|
-
|
218
|
-
|
219
|
-
|
192
|
+
#!/usr/bin/ruby
|
193
|
+
require 'pp'
|
194
|
+
require 'fsr'
|
195
|
+
require "fsr/listener/inbound"
|
220
196
|
|
221
197
|
|
222
|
-
|
223
|
-
|
224
|
-
def on_event(event)
|
225
|
-
pp event.headers
|
226
|
-
pp event.content[:event_name]
|
227
|
-
end
|
198
|
+
class IesDemo < FSR::Listener::Inbound
|
228
199
|
|
200
|
+
def on_event(event)
|
201
|
+
pp event.headers
|
202
|
+
pp event.content[:event_name]
|
229
203
|
end
|
230
204
|
|
231
|
-
|
205
|
+
end
|
206
|
+
|
207
|
+
FSR.start_ies!(IesDemo, :host => "localhost", :port => 8021)
|
232
208
|
|
233
209
|
|
234
210
|
An example of using FSR::CommandSocket to originate a new call in irb:
|
235
211
|
----------------------------------------------------------------------
|
236
212
|
|
237
|
-
|
238
|
-
|
213
|
+
irb(main):001:0> require 'fsr'
|
214
|
+
=> true
|
239
215
|
|
240
|
-
|
241
|
-
|
216
|
+
irb(main):002:0> FSR.load_all_commands
|
217
|
+
=> [:sofia, :originate]
|
242
218
|
|
243
|
-
|
244
|
-
|
219
|
+
irb(main):003:0> sock = FSR::CommandSocket.new
|
220
|
+
=> #<FSR::CommandSocket:0xb7a89104 @server="127.0.0.1", @socket=#<TCPSocket:0xb7a8908c>, @port="8021", @auth="ClueCon">
|
245
221
|
|
246
|
-
|
247
|
-
|
222
|
+
irb(main):007:0> sock.originate(:target => 'sofia/gateway/carlos/8179395222', :endpoint => FSR::App::Bridge.new("user/bougyman")).run
|
223
|
+
=> {"Job-UUID"=>"732075a4-7dd5-4258-b124-6284a82a5ae7", "body"=>"", "Content-Type"=>"command/reply", "Reply-Text"=>"+OK Job-UUID: 732075a4-7dd5-4258-b124-6284a82a5ae7"}
|
248
224
|
|
249
225
|
|
250
226
|
|
@@ -278,9 +254,12 @@ specification_version: 2
|
|
278
254
|
summary: A library for interacting with the "FreeSWITCH":http://freeswitch.org telephony platform
|
279
255
|
test_files:
|
280
256
|
- spec/fsr/app.rb
|
257
|
+
- spec/fsr/app/answer.rb
|
281
258
|
- spec/fsr/app/bridge.rb
|
282
259
|
- spec/fsr/app/conference.rb
|
283
260
|
- spec/fsr/app/fifo.rb
|
261
|
+
- spec/fsr/app/fs_break.rb
|
262
|
+
- spec/fsr/app/fs_sleep.rb
|
284
263
|
- spec/fsr/app/hangup.rb
|
285
264
|
- spec/fsr/app/limit.rb
|
286
265
|
- spec/fsr/app/log.rb
|
@@ -1,131 +0,0 @@
|
|
1
|
-
require "yaml"
|
2
|
-
require "fsr/listener"
|
3
|
-
module FSR
|
4
|
-
load_all_applications
|
5
|
-
module Listener
|
6
|
-
module Outbound
|
7
|
-
include FSR::Listener
|
8
|
-
|
9
|
-
# Include FSR::App to get all the applications defined as methods
|
10
|
-
include FSR::App
|
11
|
-
|
12
|
-
# Redefine the FSR::App methods to wrap sendmsg around them
|
13
|
-
SENDMSG_METHOD_DEFINITION = "def %s(*args, &block); sendmsg super; end"
|
14
|
-
APPLICATIONS.each { |app, obj| module_eval(SENDMSG_METHOD_DEFINITION % app.to_s) }
|
15
|
-
|
16
|
-
def post_init
|
17
|
-
@session = nil # holds the session object
|
18
|
-
send_data("connect\n\n")
|
19
|
-
FSR::Log.debug "Accepting connections."
|
20
|
-
end
|
21
|
-
|
22
|
-
# Received data dispatches the data received by the EM socket,
|
23
|
-
# Either as a Session, a continuation of a Session, or as a Session's last CommandReply
|
24
|
-
def receive_data(data)
|
25
|
-
FSR::Log.debug("received #{data}")
|
26
|
-
if @session.nil? # if @session is nil, create a new Session object
|
27
|
-
@session = Session.new(data)
|
28
|
-
session_initiated(@session) if @session.initiated?
|
29
|
-
else
|
30
|
-
# If it's not nil, we add the data to this session, Session knows whether
|
31
|
-
# or not to create a CommandReply, complete a CommandReply, or simply add to
|
32
|
-
# its own @data array and @headers/@body structures
|
33
|
-
if @session.initiated?
|
34
|
-
@session << data
|
35
|
-
reply_received(@session.replies.last) if @session.replies.last.complete?
|
36
|
-
else
|
37
|
-
@session << data
|
38
|
-
session_initiated(@session) if @session.initiated?
|
39
|
-
end
|
40
|
-
end
|
41
|
-
@session
|
42
|
-
end
|
43
|
-
|
44
|
-
def session_initiated(session)
|
45
|
-
session
|
46
|
-
end
|
47
|
-
|
48
|
-
def reply_received(command_reply)
|
49
|
-
command_reply
|
50
|
-
end
|
51
|
-
|
52
|
-
alias :receive_response :reply_received
|
53
|
-
# sendmsg sends data to the EM app socket via #send_data, or
|
54
|
-
# returns the string it would send if #send_data is not defined.
|
55
|
-
# It expects an object which responds to either #sendmsg or #to_s,
|
56
|
-
# which should return a EM Outbound Event Socket formatted instruction
|
57
|
-
def sendmsg(message)
|
58
|
-
text = message.respond_to?(:sendmsg) ? message.sendmsg : message.to_s
|
59
|
-
FSR::Log.debug "sending #{text}"
|
60
|
-
message = "sendmsg\n%s\n" % text
|
61
|
-
self.respond_to?(:send_data) ? send_data(message) : message
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
class SocketResponse
|
66
|
-
attr_accessor :headers, :body, :data
|
67
|
-
def initialize(data = "")
|
68
|
-
@data = [data]
|
69
|
-
@headers = {}
|
70
|
-
if data.match(/\n$/)
|
71
|
-
headers, @body = data.split("\n\n")
|
72
|
-
headers.each_line do |line|
|
73
|
-
key, value = line.split(":")
|
74
|
-
@headers[key] = value.to_s.strip
|
75
|
-
end
|
76
|
-
end
|
77
|
-
@body ||= ""
|
78
|
-
FSR::Log.debug("New #{self.class.name} created: #{self}")
|
79
|
-
end
|
80
|
-
|
81
|
-
def <<(data)
|
82
|
-
if data.match(/\n$/)
|
83
|
-
@data.last.match(/\n$/) ? @data << data : @data.last << data
|
84
|
-
extra_headers, more_body = @data.last.split("\n\n")
|
85
|
-
extra_headers.each_line do |line|
|
86
|
-
key, value = line.split(":")
|
87
|
-
@headers[key] = value.to_s.strip
|
88
|
-
end
|
89
|
-
@body << more_body unless more_body.nil?
|
90
|
-
else
|
91
|
-
@data.last.match(/\n$/) ? @data << data : @data.last << data
|
92
|
-
end
|
93
|
-
self
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
class Session < SocketResponse
|
98
|
-
attr_accessor :replies
|
99
|
-
def initialize(data = "")
|
100
|
-
super
|
101
|
-
@replies = []
|
102
|
-
end
|
103
|
-
|
104
|
-
def <<(data)
|
105
|
-
if initiated?
|
106
|
-
if @replies.empty? or @replies.last.complete?
|
107
|
-
@replies << CommandReply.new(data)
|
108
|
-
else
|
109
|
-
@replies.last << data
|
110
|
-
end
|
111
|
-
else
|
112
|
-
super
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def initiated?
|
117
|
-
@headers.keys.include?("Control")
|
118
|
-
end
|
119
|
-
|
120
|
-
end
|
121
|
-
|
122
|
-
class CommandReply < SocketResponse
|
123
|
-
# Set this to true for now, fill it in when we know what completed a reply
|
124
|
-
def complete?
|
125
|
-
true
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
end
|