ragi 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/CHANGELOG +12 -0
  2. data/RAGI Overview_files/filelist.xml +5 -0
  3. data/RAGI Overview_files/image001.gif +0 -0
  4. data/README +114 -0
  5. data/call_connection.rb +515 -0
  6. data/call_handler.rb +362 -0
  7. data/call_initiate.rb +188 -0
  8. data/call_server.rb +147 -0
  9. data/config.rb +68 -0
  10. data/example-call-audio.mp3 +0 -0
  11. data/ragi.gempsec +23 -0
  12. data/sample-apps/simon/simon_handler.rb +94 -0
  13. data/sample-apps/simon/sounds/README +9 -0
  14. data/sample-apps/simon/sounds/simon-1.gsm +0 -0
  15. data/sample-apps/simon/sounds/simon-2.gsm +0 -0
  16. data/sample-apps/simon/sounds/simon-3.gsm +0 -0
  17. data/sample-apps/simon/sounds/simon-4.gsm +0 -0
  18. data/sample-apps/simon/sounds/simon-5.gsm +0 -0
  19. data/sample-apps/simon/sounds/simon-6.gsm +0 -0
  20. data/sample-apps/simon/sounds/simon-7.gsm +0 -0
  21. data/sample-apps/simon/sounds/simon-8.gsm +0 -0
  22. data/sample-apps/simon/sounds/simon-9.gsm +0 -0
  23. data/sample-apps/simon/sounds/simon-again.gsm +0 -0
  24. data/sample-apps/simon/sounds/simon-beep-again.gsm +0 -0
  25. data/sample-apps/simon/sounds/simon-beep-beep.gsm +0 -0
  26. data/sample-apps/simon/sounds/simon-beep-gameover.gsm +0 -0
  27. data/sample-apps/simon/sounds/simon-beep-high.gsm +0 -0
  28. data/sample-apps/simon/sounds/simon-beep-low.gsm +0 -0
  29. data/sample-apps/simon/sounds/simon-beep-medium.gsm +0 -0
  30. data/sample-apps/simon/sounds/simon-beep-score.gsm +0 -0
  31. data/sample-apps/simon/sounds/simon-beep-welcome.gsm +0 -0
  32. data/sample-apps/simon/sounds/simon-beep.gsm +0 -0
  33. data/sample-apps/simon/sounds/simon-gameover.gsm +0 -0
  34. data/sample-apps/simon/sounds/simon-goodbye.gsm +0 -0
  35. data/sample-apps/simon/sounds/simon-high.gsm +0 -0
  36. data/sample-apps/simon/sounds/simon-low.gsm +0 -0
  37. data/sample-apps/simon/sounds/simon-medium.gsm +0 -0
  38. data/sample-apps/simon/sounds/simon-score.gsm +0 -0
  39. data/sample-apps/simon/sounds/simon-welcome.gsm +0 -0
  40. data/start_ragi.rb +41 -0
  41. data/test.rb +109 -0
  42. metadata +77 -0
@@ -0,0 +1,147 @@
1
+ #
2
+ # RAGI - Ruby classes for implementing an AGI server for Asterisk
3
+ # The BSD License for RAGI follows.
4
+ #
5
+ # Copyright (c) 2005, SNAPVINE LLC (www.snapvine.com)
6
+ # All rights reserved.
7
+
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ # * Neither the name of SNAPVINE nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ require 'webrick/config'
32
+ require 'webrick/log'
33
+ require 'webrick/server'
34
+ require 'ragi/call_handler'
35
+ require 'ragi/call_connection'
36
+ require 'ragi/config'
37
+ require 'thread'
38
+
39
+ module RAGI
40
+ VERSION = "0.0.1"
41
+
42
+ @globalConfig = nil
43
+
44
+ def self.LOGGER
45
+ @logger ||= WEBrick::Log::new
46
+ @logger
47
+ end
48
+
49
+ def self.LOGGER=(logger)
50
+ @logger = logger
51
+ end
52
+
53
+ def self.globalConfig
54
+ # This assignment will make a dup
55
+ @globalConfig ||= RAGI::Config::Globals
56
+ @globalConfig
57
+ end
58
+
59
+ def self.globalConfig=(newConfig)
60
+ @globalConfig = newConfig.dup()
61
+ end
62
+
63
+ class CallServer
64
+ @incomingcallsocket = nil
65
+
66
+ # 4573 = asterisk AGI
67
+ # RAGI::CallHandler - default handler
68
+
69
+ def initialize(config = {}, default = RAGI::Config::Standard)
70
+ @config = default.dup.update(config)
71
+ @config[:Logger] ||= WEBrick::Log::new
72
+ @config[:ParentStopCallback] = @config[:StopCallback] if @config[:StopCallback]
73
+ @config[:StopCallback] = method('shutdown_done')
74
+
75
+ RAGI.LOGGER = @config[:Logger]
76
+
77
+ @mutex = Mutex.new
78
+ @signal = ConditionVariable.new
79
+ @running = true
80
+
81
+ if (@incomingcallsocket == nil)
82
+ begin
83
+ # code to executed in a thread
84
+ RAGI.LOGGER.info("#{self.class.name}: default-handler=#{@config[:DefaultHandler].to_s} port=#{@config[:Port]}")
85
+ @incomingcallsocket = WEBrick::GenericServer.new( @config )
86
+
87
+ @incomingcallsocket.start{ |sock|
88
+ cc = CallConnection.new(sock)
89
+
90
+ route = {
91
+ :handler => @config[:DefaultHandler],
92
+ :action => :dialup
93
+ }
94
+
95
+ # the default call handler comes from config environment.rb
96
+
97
+ if (cc.agi_url != nil && cc.agi_url != '/')
98
+ route = CallHandler.route(cc.agi_url)
99
+ end
100
+ RAGI.LOGGER.info("#{self.class.name}: processing call with #{route[:handler].to_s}")
101
+
102
+ CallHandler.process(route, cc)
103
+
104
+ # todo: Catch exceptions and say something to the user
105
+ # before we disconnect them. Something like this maybe:
106
+ #
107
+ # rescue StandardError => err
108
+ # if (cc) then
109
+ # cc.play_sound('tc/std/sorry-error')
110
+ # cc.hang_up()
111
+ # end
112
+ # raise
113
+ # end
114
+ }
115
+ RAGI.LOGGER.info("#{self.class.name}: server shutdown port=#{@config[:Port]}")
116
+
117
+ rescue StandardError => err
118
+ RAGI.LOGGER.error("#{err.message}")
119
+ RAGI.LOGGER.error(err.backtrace.join("\n"))
120
+ end
121
+
122
+ end
123
+ end
124
+
125
+ def shutdown
126
+ @incomingcallsocket.shutdown
127
+ end
128
+
129
+ def shutdown_done
130
+ RAGI.LOGGER.debug("#{self.class.name}: Shutdown complete")
131
+
132
+ @config[:ParentStopCallback].call if @config[:ParentStopCallback]
133
+ @mutex.synchronize do
134
+ @running = false
135
+ @signal.signal
136
+ end
137
+ end
138
+
139
+ def join
140
+ @mutex.synchronize do
141
+ if @running
142
+ @signal.wait(@mutex)
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,68 @@
1
+ #
2
+ # RAGI - Ruby classes for implementing an AGI server for Asterisk
3
+ # The BSD License for RAGI follows.
4
+ #
5
+ # Copyright (c) 2005, SNAPVINE LLC (www.snapvine.com)
6
+ # All rights reserved.
7
+
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ # * Neither the name of SNAPVINE nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # config.rb -- Default configurations.
32
+ #
33
+
34
+ require 'webrick/config'
35
+ require 'ragi/call_handler'
36
+
37
+ module RAGI
38
+
39
+ DEFAULT_PORT = 4573
40
+
41
+ module Config
42
+
43
+ # for HTTPServer, HTTPRequest, HTTPResponse ...
44
+ Standard = WEBrick::Config::General.dup.update(
45
+ :Port => RAGI::DEFAULT_PORT,
46
+ :HandlerMap => {}
47
+ )
48
+
49
+ Globals = {
50
+ # Name of the box running the agi server, so that asterisk can find it
51
+ # by default this will use your Ruby server's name
52
+ "agiServer" => `hostname`.strip(),
53
+
54
+ # Path to use for saving outgoing call files
55
+ "outgoingCallPath" =>
56
+ ENV['RAGI_OUT_CALL_PATH'] ? ENV['RAGI_OUT_CALL_PATH'] : "var/spool/asterisk/outgoing",
57
+
58
+ # Path to use for saving wakeup call files
59
+ "wakeupCallPath" =>
60
+ ENV['RAGI_WAKEUP_CALL_PATH'] ? ENV['RAGI_WAKEUP_CALL_PATH'] : "var/spool/asterisk/wakeups",
61
+
62
+ # Path to the built-in sound files relative to the SIP server.
63
+ "sipSoundPath" =>
64
+ ENV['RAGI_SIP_SOUND_PATH'] ? ENV['RAGI_SIP_SOUND_PATH'] : "var/lib/asterisk/sounds"
65
+ }
66
+
67
+ end
68
+ end
Binary file
@@ -0,0 +1,23 @@
1
+ require "rubygems"
2
+ require "rake"
3
+
4
+ spec = Gem::Specification.new do |gem|
5
+ gem.name = "ragi"
6
+ gem.version = "1.0.0"
7
+ gem.author = "Joe Heitzeberg"
8
+ gem.email = "joe_AT_snapvine.com"
9
+ gem.homepage = "http://rubyforge.org/projects/ragi"
10
+ gem.platform = Gem::Platform::RUBY
11
+ gem.summary = "RAGI allows you to create useful telephony applications using Asterisk and Ruby [on Rails]."
12
+ gem.description = "RAGI allows you to create useful telephony applications using Asterisk and Ruby [on Rails]. Please see the included README file for more information"
13
+ gem.has_rdoc = false
14
+
15
+ gem.files = FileList['example-call-audio.mp3', 'ragi.gempsec', 'CHANGELOG', 'README', '*.rb', 'RAGI Overview_files/*', 'sample-apps/simon/*.rb', 'sample-apps/simon/sounds/README', 'sample-apps/simon/sounds/*.gsm'].to_a
16
+ gem.files.reject! { |fn| fn.include? "SVN" }
17
+ end
18
+
19
+ if $0 == __FILE__
20
+ Gem.manage_gems
21
+ Gem::Builder.new(spec).build
22
+ end
23
+
@@ -0,0 +1,94 @@
1
+ # RAGI -- Ruby Asterisk Gateway Interface
2
+ # See ragi.sourceforge.net for more information.
3
+ # Sponsored by SnapVine, Inc (www.snapvine.com)
4
+ #
5
+ # Class: SimonHandler
6
+ # Description: this call handler implements a simple memory game over the phone.
7
+ #
8
+
9
+ require 'ragi/call_handler'
10
+
11
+ class SimonHandler < RAGI::CallHandler
12
+ APP_NAME = 'simon'
13
+
14
+ # When the RAGI server connects from Asterisk over AGI to our app, it calls this method.
15
+ def dialup
16
+ answer # answer the call
17
+ wait(1) # give it 1 seconds to make sure the connection is established
18
+
19
+
20
+ playAgain = true
21
+ while (playAgain)
22
+ instructions # tell the caller how to play the game
23
+ score = play_game # start the game and play it, returning the score when done
24
+ announce_score(score) # tell them how they did
25
+ playAgain = ask_play_again # ask if they want to play again
26
+ end
27
+ say_goodbye
28
+ hang_up #end the call
29
+ end
30
+
31
+ def instructions
32
+ play_sound("simon-welcome")
33
+ end
34
+
35
+ def play_game
36
+
37
+ intArray = [rand(10)]
38
+ score = 0
39
+
40
+ # test the user's memory on the current int array
41
+ while memory_test(intArray)
42
+ score += 1
43
+
44
+ # grow the array by one digit
45
+ intArray << rand(10) # choose a number between 0 and 9 inclusive
46
+
47
+ wait(1)
48
+ end
49
+
50
+ score
51
+ end
52
+
53
+ def memory_test(intArray)
54
+ # say each number in the array
55
+ intArray.each do |number|
56
+ play_sound("simon-#{number}") # there are sounds like simon-6.gsm
57
+ end
58
+
59
+ # listen for user key presses (number of presses should be == intArray.length)
60
+ # Note: give about 1 second per key press (intArray.length * 1500)
61
+ resultStr = get_data("simon-beep", (intArray.length * 1500), intArray.length)
62
+
63
+ # Check if what they entered matches the int array
64
+ if (resultStr == intArray.join("")) # note: join converts from array to string
65
+ return true
66
+ else
67
+ play_sound("simon-gameover")
68
+ return false
69
+ end
70
+ end
71
+
72
+ def announce_score(score)
73
+ if (score <= 9)
74
+ play_sound("simon-score")
75
+ play_sound("simon-#{score.to_s}")
76
+ end
77
+ if (score < 5)
78
+ play_sound("simon-low")
79
+ elsif (score < 10)
80
+ play_sound("simon-medium")
81
+ else
82
+ play_sound("simon-high")
83
+ end
84
+ end
85
+
86
+ def ask_play_again
87
+ # Give the user three seconds to press a digit
88
+ return (get_data("simon-again", 3000, 1).length > 0)
89
+ end
90
+
91
+ def say_goodbye
92
+ play_sound("simon-goodbye")
93
+ end
94
+ end
@@ -0,0 +1,9 @@
1
+ These are the sounds needed for the simon sample app.
2
+
3
+ You'll need to copy these sounds directly to the default sounds directory on your Asterisk server (e.g. var/lib/asterisk/sounds/) in order to use the simon game app.
4
+
5
+ In the simon call handler, it plays these sounds using the playSound command, e.g.:
6
+ play_sound("simon-welcome")
7
+
8
+ This command tells the asterisk server to play the sound "simon-welcome.gsm" from the asterisk server's default sound location (e.g. var/lib/asterisk/sounds/simon-welcome.gsm)
9
+
@@ -0,0 +1,41 @@
1
+ #
2
+ # RAGI - Ruby classes for implementing an AGI server for Asterisk
3
+ # The BSD License for RAGI follows.
4
+ #
5
+ # Copyright (c) 2005, SNAPVINE LLC (www.snapvine.com)
6
+ # All rights reserved.
7
+
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ # * Neither the name of SNAPVINE nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ #
31
+ # Class: start_ragi.rb
32
+ # This class provides a server to answer incoming AGI requests from Asterisk.
33
+ # It is configured to run the sample app, Simon.
34
+ #
35
+
36
+
37
+ require 'ragi/call_server'
38
+ require 'ragi/sample-apps/simon/simon_handler'
39
+
40
+ RAGI::CallServer.new( :DefaultHandler => SimonHandler )
41
+
data/test.rb ADDED
@@ -0,0 +1,109 @@
1
+ #
2
+ # RAGI - Ruby classes for implementing an AGI server for Asterisk
3
+ # The BSD License for RAGI follows.
4
+ #
5
+ # Copyright (c) 2005, SNAPVINE LLC (www.snapvine.com)
6
+ # All rights reserved.
7
+
8
+ # Redistribution and use in source and binary forms, with or without
9
+ # modification, are permitted provided that the following conditions are met:
10
+ #
11
+ # * Redistributions of source code must retain the above copyright notice,
12
+ # this list of conditions and the following disclaimer.
13
+ # * Redistributions in binary form must reproduce the above copyright notice,
14
+ # this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ # * Neither the name of SNAPVINE nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this software
18
+ # without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ module RAGI
32
+ # This class is useful for writing unit tests
33
+ class TestSocket
34
+
35
+ def initialize(params, messages)
36
+ @params = params
37
+ @messages = messages
38
+ @inParams = true
39
+ @currentIndex = 0
40
+ end
41
+
42
+ def self.Exec(cmd, params)
43
+ [ "EXEC #{cmd} #{params}", "200 result=0"]
44
+ end
45
+
46
+ def self.GetData(soundfile, result)
47
+ ["GET DATA #{soundfile} 2000", "200 result=#{result} (timeout)"]
48
+ end
49
+
50
+ def self.StreamFile(soundfile, escapeDigits, initialOffset, result, endpos)
51
+ ["STREAM FILE #{soundfile} \"#{escapeDigits}\" #{initialOffset}",
52
+ "200 result=#{result} endpos=#{endpos}"]
53
+ end
54
+
55
+ def self.PlaySound(soundfile)
56
+ [ "EXEC playback #{soundfile}", "200 result=0"]
57
+ end
58
+
59
+ def self.SayNumber(number)
60
+ SayNumberFull(number, " \"*#\"")
61
+ end
62
+
63
+ def self.SayNumberFull(number, escapeDigits)
64
+ [ "SAY NUMBER #{number} \"#{escapeDigits}\"", "200 result=0"]
65
+ end
66
+
67
+ def self.HangUp()
68
+ [ "HANGUP", "200 result=0"]
69
+ end
70
+
71
+ def print(msg)
72
+ if @inParams
73
+ raise StandardError, "Should not receive commands until parameters are parse"
74
+ end
75
+
76
+ if (!@messages[@currentIndex])
77
+ raise StandardError, "Too many messages received\nMessage =#{msg}= received"
78
+ end
79
+
80
+ if (msg != @messages[@currentIndex][0])
81
+ raise StandardError, "Unexpected message received\nMessage =#{msg}= received\nExpected =#{@messages[@currentIndex][0]}"
82
+ end
83
+ end
84
+
85
+ def gets
86
+ if (@inParams) then
87
+ if (@currentIndex < @params.length) then
88
+ key = @params.keys[@currentIndex]
89
+ val = "#{key}: #{@params[@params.keys[@currentIndex]]}"
90
+ @currentIndex += 1
91
+ else
92
+ @currentIndex = 0
93
+ @inParams = false
94
+ val = ''
95
+ end
96
+ else
97
+ if (@currentIndex < @messages.length) then
98
+ val = @messages[@currentIndex][1]
99
+ @currentIndex += 1
100
+ else
101
+ raise StandardError, "Unexpected messages past end of test case"
102
+ @currentIndex = 0
103
+ val = '\n'
104
+ end
105
+ end
106
+ val
107
+ end
108
+ end
109
+ end